From 982d028ce3b975a1a8b0ac895cf722a5ddb0f553 Mon Sep 17 00:00:00 2001 From: Ted Toal Date: Wed, 5 Jul 2023 15:32:02 -0700 Subject: [PATCH 1/4] Added getTextBounds() optional arguments xF and yF, with extensive comments in .cpp file. --- Adafruit_GFX.cpp | 135 ++++++++++++++++++++++++++++++++++++----------- Adafruit_GFX.h | 13 +++-- 2 files changed, 113 insertions(+), 35 deletions(-) diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index af98900..8e098bc 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -1356,9 +1356,9 @@ void Adafruit_GFX::setFont(const GFXfont *f) { Broke this out as it's used by both the PROGMEM- and RAM-resident getTextBounds() functions. @param c The ASCII character in question - @param x Pointer to x location of character. Value is modified by + @param x Pointer to x cursor position of character. Value is modified by this function to advance to next character. - @param y Pointer to y location of character. Value is modified by + @param y Pointer to y cursor position of character. Value is modified by this function to advance to next character. @param minx Pointer to minimum X coordinate, passed in to AND returned by this function -- this is used to incrementally build a @@ -1435,26 +1435,86 @@ void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y, /**************************************************************************/ /*! @brief Helper to determine size of a string with current font/size. - Pass string and a cursor position, returns UL corner and W,H. - @param str The ASCII string to measure - @param x The current cursor X - @param y The current cursor Y - @param x1 The boundary X coordinate, returned by function - @param y1 The boundary Y coordinate, returned by function - @param w The boundary width, returned by function - @param h The boundary height, returned by function + Pass string and a cursor position, returns UL corner, baseline Y, + and W,H. + @param str ASCII string to measure + @param x Starting cursor X (left side, first character) + @param y Starting cursor Y (on baseline, first character) + @param xL Left text boundary X coordinate, returned by function + @param yT Top text boundary Y coordinate, returned by function + @param w Text boundary width, returned by function + @param h Text boundary height, returned by function + @param xF Ending cursor X (right side of baseline, last char), if not NULL + @param yF Ending cursor Y (on baseline, last char), returned if not NULL + @notes The values of (x, y) on call to this function actually don't + matter to it; they are simply incremented past the string + bounds. However, they COULD BE the CURSOR POSITION used in a + call to setCursor(). More often, the reason for calling this + function is to get the text size so that the starting cursor + position can be adjusted (e.g. for center alignment), so the + cursor position is unknown when this function is called, and + (x, y) can really just be arbitrary values. + Since the returned (xL, yT) values are the coords of the upper + left corner of the text boundary box, then the correct CURSOR + position to use with setCursor() when printing the text, if + the upper-left corner of the text is to be at position (X1,Y1) + (which may or may not equal the (x, y) arguments to this + function), is: + (X1+x-xL, Y1+y-yT) + Suppose (x, y) are indeed set to (X1, Y1) when calling this + function. In that case (x-XL) and (y-yT) will evaluate to a + small positive or negative integer, possibly 0 but not always + 0, and adding that small integer to X1 and Y1 will move them + slightly so they can be used in a call to setCursor(). The + cursor position is NOT the upper-left corner of the next + character to be printed. Rather, it is a position on the TEXT + BASELINE (bottom of characters that don't have descenders on + them), used to align the character font data. (y-yT) will + almost always be a positive value that is the distance from + the top of the text (yT) to the text baseline. Note that the + text baseline is NOT Y1+h, because h includes the full string + height including descenders on characters. + If instead of the above setting, the cursor position for + displaying the string is set to (X1, Y1+h), the text will be + shifted left or right slightly when the first character starts + slightly left or right of the cursor position (which some + characters do), and the text will be shifted up if it contains + any characters with descenders that extend below the baseline. + The optional arguments xF and yF provide a way to discover + where to start adding more characters after the string, if + desired. The final cursor position is returned in (xF, yF). + This is NOT the same as (xL+w, yT+h). Instead, XF might be + slightly more or less than that, while yF is probably the same + as the y value given at the start (unless there was text + wrapping). The final CURSOR position to use to print additional + text after the string, if the upper-left corner of the text is + at position (X1, Y1), is: + (X1+xF-xL, Y1+yF-yT) + The position of the lower-right corner of the bounding box, + (X2, Y2), is of course: + (X1+w, Y1+h) + If another character is printed after the string, using the + starting cursor position (X1+xF-xL, Y1+yF-yT), and that new + character has top-left bound box offset (dX, dY) and width + W and height H, then the new lower-right corner of the bounding + box (X2, Y2) is: + (X1+xF-xL+dX+W, Y1+yF-yT+max(0, dY+H)) + and so the new total text string width and height are: + new w = xF-xL+dX+W = new X2 - X1 + new h = yF-yT+max(0, dY+H) = new Y2 - Y1 */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, - int16_t *x1, int16_t *y1, uint16_t *w, - uint16_t *h) { + int16_t *xL, int16_t *yT, + uint16_t *w, uint16_t *h, + int16_t *xF, int16_t *yF) { uint8_t c; // Current character int16_t minx = 0x7FFF, miny = 0x7FFF, maxx = -1, maxy = -1; // Bound rect // Bound rect is intentionally initialized inverted, so 1st char sets it - *x1 = x; // Initial position is value passed in - *y1 = y; + *xL = x; // This initialization SHOULD be overwritten below after charBounds() + *yT = y; // is called. (Unless string is empty). *w = *h = 0; // Initial size is zero while ((c = *str++)) { @@ -1464,13 +1524,20 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, } if (maxx >= minx) { // If legit string bounds were found... - *x1 = minx; // Update x1 to least X coord, + *xL = minx; // Update xL to least X coord, *w = maxx - minx + 1; // And w to bound rect width } - if (maxy >= miny) { // Same for height - *y1 = miny; + + if (maxy >= miny) { // Same for height as for width + *yT = miny; *h = maxy - miny + 1; } + + // If xF and yF arguments provided, return final cursor x and y position. + if (xF != NULL) + *xF = x; + if (yF != NULL) + *yF = y; } /**************************************************************************/ @@ -1480,17 +1547,18 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, @param str The ascii string to measure (as an arduino String() class) @param x The current cursor X @param y The current cursor Y - @param x1 The boundary X coordinate, set by function - @param y1 The boundary Y coordinate, set by function + @param xL The left boundary X coordinate, set by function + @param yT The top boundary Y coordinate, set by function @param w The boundary width, set by function @param h The boundary height, set by function */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, - int16_t *x1, int16_t *y1, uint16_t *w, - uint16_t *h) { + int16_t *xL, int16_t *yT, + uint16_t *w, uint16_t *h, + int16_t *xF, int16_t *yF) { if (str.length() != 0) { - getTextBounds(const_cast(str.c_str()), x, y, x1, y1, w, h); + getTextBounds(const_cast(str.c_str()), x, y, xL, yT, w, h, xF, yF); } } @@ -1501,19 +1569,20 @@ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, @param str The flash-memory ascii string to measure @param x The current cursor X @param y The current cursor Y - @param x1 The boundary X coordinate, set by function - @param y1 The boundary Y coordinate, set by function + @param xL The left boundary X coordinate, set by function + @param yT The top boundary Y coordinate, set by function @param w The boundary width, set by function @param h The boundary height, set by function */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x, - int16_t y, int16_t *x1, int16_t *y1, - uint16_t *w, uint16_t *h) { + int16_t y, int16_t *xL, int16_t *yT, + uint16_t *w, uint16_t *h, + int16_t *xF, int16_t *yF) { uint8_t *s = (uint8_t *)str, c; - *x1 = x; - *y1 = y; + *xL = x; + *yT = y; *w = *h = 0; int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; @@ -1522,13 +1591,19 @@ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x, charBounds(c, &x, &y, &minx, &miny, &maxx, &maxy); if (maxx >= minx) { - *x1 = minx; + *xL = minx; *w = maxx - minx + 1; } if (maxy >= miny) { - *y1 = miny; + *yT = miny; *h = maxy - miny + 1; } + + // If xF and yF arguments provided, return final cursor x and y position. + if (xF != NULL) + *xF = x; + if (yF != NULL) + *yF = y; } /**************************************************************************/ diff --git a/Adafruit_GFX.h b/Adafruit_GFX.h index 63c6ab6..ae33999 100644 --- a/Adafruit_GFX.h +++ b/Adafruit_GFX.h @@ -111,12 +111,15 @@ public: uint16_t bg, uint8_t size); void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y); - void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, - int16_t *y1, uint16_t *w, uint16_t *h); + void getTextBounds(const char *string, int16_t x, int16_t y, + int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, + int16_t *xF=NULL, int16_t *yF=NULL); void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, - int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); - void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, - int16_t *y1, uint16_t *w, uint16_t *h); + int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, + int16_t *xF=NULL, int16_t *yF=NULL); + void getTextBounds(const String &str, int16_t x, int16_t y, + int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, + int16_t *xF=NULL, int16_t *yF=NULL); void setTextSize(uint8_t s); void setTextSize(uint8_t sx, uint8_t sy); void setFont(const GFXfont *f = NULL); From 9cd11b3230abd0bbaca0964086f5427f40c46608 Mon Sep 17 00:00:00 2001 From: Ted Toal Date: Wed, 5 Jul 2023 17:23:13 -0700 Subject: [PATCH 2/4] Run git-clang-format --- Adafruit_GFX.cpp | 31 +++++++++++++++---------------- Adafruit_GFX.h | 14 +++++++------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 8e098bc..2714ca8 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -1356,10 +1356,10 @@ void Adafruit_GFX::setFont(const GFXfont *f) { Broke this out as it's used by both the PROGMEM- and RAM-resident getTextBounds() functions. @param c The ASCII character in question - @param x Pointer to x cursor position of character. Value is modified by - this function to advance to next character. - @param y Pointer to y cursor position of character. Value is modified by - this function to advance to next character. + @param x Pointer to x cursor position of character. Value is modified + by this function to advance to next character. + @param y Pointer to y cursor position of character. Value is modified + by this function to advance to next character. @param minx Pointer to minimum X coordinate, passed in to AND returned by this function -- this is used to incrementally build a bounding rectangle for a string. @@ -1444,7 +1444,8 @@ void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y, @param yT Top text boundary Y coordinate, returned by function @param w Text boundary width, returned by function @param h Text boundary height, returned by function - @param xF Ending cursor X (right side of baseline, last char), if not NULL + @param xF Ending cursor X (right side of baseline, last char), if not + NULL @param yF Ending cursor Y (on baseline, last char), returned if not NULL @notes The values of (x, y) on call to this function actually don't matter to it; they are simply incremented past the string @@ -1505,16 +1506,15 @@ void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y, */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, - int16_t *xL, int16_t *yT, - uint16_t *w, uint16_t *h, - int16_t *xF, int16_t *yF) { + int16_t *xL, int16_t *yT, uint16_t *w, + uint16_t *h, int16_t *xF, int16_t *yF) { uint8_t c; // Current character int16_t minx = 0x7FFF, miny = 0x7FFF, maxx = -1, maxy = -1; // Bound rect // Bound rect is intentionally initialized inverted, so 1st char sets it - *xL = x; // This initialization SHOULD be overwritten below after charBounds() - *yT = y; // is called. (Unless string is empty). + *xL = x; // This initialization SHOULD be overwritten below after charBounds() + *yT = y; // is called. (Unless string is empty). *w = *h = 0; // Initial size is zero while ((c = *str++)) { @@ -1528,7 +1528,7 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, *w = maxx - minx + 1; // And w to bound rect width } - if (maxy >= miny) { // Same for height as for width + if (maxy >= miny) { // Same for height as for width *yT = miny; *h = maxy - miny + 1; } @@ -1554,9 +1554,8 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, - int16_t *xL, int16_t *yT, - uint16_t *w, uint16_t *h, - int16_t *xF, int16_t *yF) { + int16_t *xL, int16_t *yT, uint16_t *w, + uint16_t *h, int16_t *xF, int16_t *yF) { if (str.length() != 0) { getTextBounds(const_cast(str.c_str()), x, y, xL, yT, w, h, xF, yF); } @@ -1577,8 +1576,8 @@ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, /**************************************************************************/ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x, int16_t y, int16_t *xL, int16_t *yT, - uint16_t *w, uint16_t *h, - int16_t *xF, int16_t *yF) { + uint16_t *w, uint16_t *h, int16_t *xF, + int16_t *yF) { uint8_t *s = (uint8_t *)str, c; *xL = x; diff --git a/Adafruit_GFX.h b/Adafruit_GFX.h index ae33999..4265a9b 100644 --- a/Adafruit_GFX.h +++ b/Adafruit_GFX.h @@ -111,15 +111,15 @@ public: uint16_t bg, uint8_t size); void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y); - void getTextBounds(const char *string, int16_t x, int16_t y, - int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, - int16_t *xF=NULL, int16_t *yF=NULL); + void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *xL, + int16_t *yT, uint16_t *w, uint16_t *h, int16_t *xF = NULL, + int16_t *yF = NULL); void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, - int16_t *xF=NULL, int16_t *yF=NULL); - void getTextBounds(const String &str, int16_t x, int16_t y, - int16_t *xL, int16_t *yT, uint16_t *w, uint16_t *h, - int16_t *xF=NULL, int16_t *yF=NULL); + int16_t *xF = NULL, int16_t *yF = NULL); + void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *xL, + int16_t *yT, uint16_t *w, uint16_t *h, int16_t *xF = NULL, + int16_t *yF = NULL); void setTextSize(uint8_t s); void setTextSize(uint8_t sx, uint8_t sy); void setFont(const GFXfont *f = NULL); From 886b2d904f92e777c09f1e7b2cfc169a2622349a Mon Sep 17 00:00:00 2001 From: Ted Toal Date: Fri, 7 Jul 2023 19:32:49 -0700 Subject: [PATCH 3/4] Fix doxygen errors --- .gitignore | 3 ++- Adafruit_GFX.cpp | 26 ++++++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 469bb73..99955ac 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ fontconvert/fontconvert # Our handy .gitignore for automation ease Doxyfile* doxygen_sqlite3.db -html \ No newline at end of file +html +.DS_Store diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 2714ca8..80c7d6d 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -1447,7 +1447,7 @@ void Adafruit_GFX::charBounds(unsigned char c, int16_t *x, int16_t *y, @param xF Ending cursor X (right side of baseline, last char), if not NULL @param yF Ending cursor Y (on baseline, last char), returned if not NULL - @notes The values of (x, y) on call to this function actually don't + @note The values of (x, y) on call to this function actually don't matter to it; they are simply incremented past the string bounds. However, they COULD BE the CURSOR POSITION used in a call to setCursor(). More often, the reason for calling this @@ -1544,13 +1544,16 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, /*! @brief Helper to determine size of a string with current font/size. Pass string and a cursor position, returns UL corner and W,H. - @param str The ascii string to measure (as an arduino String() class) - @param x The current cursor X - @param y The current cursor Y - @param xL The left boundary X coordinate, set by function - @param yT The top boundary Y coordinate, set by function - @param w The boundary width, set by function - @param h The boundary height, set by function + @param str The ascii string to measure (as an arduino String() class) + @param x The current cursor X + @param y The current cursor Y + @param xL The left boundary X coordinate, set by function + @param yT The top boundary Y coordinate, set by function + @param w The boundary width, set by function + @param h The boundary height, set by function + @param xF Ending cursor X (right side of baseline, last char), if not + NULL + @param yF Ending cursor Y (on baseline, last char), returned if not NULL */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, @@ -1570,8 +1573,11 @@ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, @param y The current cursor Y @param xL The left boundary X coordinate, set by function @param yT The top boundary Y coordinate, set by function - @param w The boundary width, set by function - @param h The boundary height, set by function + @param w The boundary width, set by function + @param h The boundary height, set by function + @param xF Ending cursor X (right side of baseline, last char), if not + NULL + @param yF Ending cursor Y (on baseline, last char), returned if not NULL */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x, From dba4c4f66c6be1489ced7b0f193f1c4e328f0b65 Mon Sep 17 00:00:00 2001 From: Ted Toal Date: Fri, 7 Jul 2023 19:38:36 -0700 Subject: [PATCH 4/4] Run clang-format again --- Adafruit_GFX.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 80c7d6d..3c5cccb 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -1551,9 +1551,10 @@ void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y, @param yT The top boundary Y coordinate, set by function @param w The boundary width, set by function @param h The boundary height, set by function - @param xF Ending cursor X (right side of baseline, last char), if not + @param xF Ending cursor X (right side of baseline, last char), if + not NULL + @param yF Ending cursor Y (on baseline, last char), returned if not NULL - @param yF Ending cursor Y (on baseline, last char), returned if not NULL */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, @@ -1575,9 +1576,10 @@ void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y, @param yT The top boundary Y coordinate, set by function @param w The boundary width, set by function @param h The boundary height, set by function - @param xF Ending cursor X (right side of baseline, last char), if not + @param xF Ending cursor X (right side of baseline, last char), if + not NULL + @param yF Ending cursor Y (on baseline, last char), returned if not NULL - @param yF Ending cursor Y (on baseline, last char), returned if not NULL */ /**************************************************************************/ void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, int16_t x,