3333
3434**Hardware:**
3535
36- .. todo:: Add links to any specific hardware product page(s), or category page(s). Use unordered list & hyperlink rST
36+ .. todo:: Add links to any specific hardware product page(s), or category page(s). Use
37+ unordered list & hyperlink rST
3738 inline format: "* `Link Text <url>`_"
3839
3940**Software and Dependencies:**
4041
4142* Adafruit CircuitPython firmware for the supported boards:
4243 https://github.com/adafruit/circuitpython/releases
4344
44- .. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based on the library's use of either.
45+ .. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based
46+ on the library's use of either.
4547
4648# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
4749# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
4850"""
4951
5052import displayio
5153
54+ __version__ = "0.0.0-auto.0"
55+ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
56+
5257
5358class Label (displayio .Group ):
59+ """A label displaying a string of text. The origin point set by ``x`` and ``y``
60+ properties will be the left edge of the bounding box, and in the center of a M
61+ glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
62+ it will try to have it be center-left as close as possible.
63+
64+ :param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``.
65+ Must include a capital M for measuring character size.
66+ :param str text: Text to display
67+ :param int max_glyphs: Unnecessary parameter (provided only for direct compability
68+ with label.py)
69+ :param int color: Color of all text in RGB hex
70+ :param int background_color: Color of the background, use `None` for transparent
71+ :param double line_spacing: Line spacing of text to display
72+ :param boolean background_tight: Set `True` only if you want background box to tightly
73+ surround text
74+ :param int padding_top: Additional pixels added to background bounding box at top
75+ :param int padding_bottom: Additional pixels added to background bounding box at bottom
76+ :param int padding_left: Additional pixels added to background bounding box at left
77+ :param int padding_right: Additional pixels added to background bounding box at right
78+ :param (double,double) anchor_point: Point that anchored_position moves relative to.
79+ Tuple with decimal percentage of width and height.
80+ (E.g. (0,0) is top left, (1.0, 0.5): is middle right.)
81+ :param (int,int) anchored_position: Position relative to the anchor_point. Tuple
82+ containing x,y pixel coordinates.
83+ :param int scale: Integer value of the pixel scaling
84+ """
85+
86+ # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments
87+ # Note: max_glyphs parameter is unnecessary, this is used for direct
88+ # compatibility with label.py
5489
5590 # Class variable
5691 # To save memory, set Label._memory_saver=True and avoid storing the text string in the class.
@@ -63,8 +98,8 @@ def __init__(
6398 x = 0 ,
6499 y = 0 ,
65100 text = "" ,
66- max_glyphs = None , # This input parameter is ignored, only present for compatibility with label.py
67- # width, height,
101+ max_glyphs = None , # This input parameter is ignored, only present for compatibility
102+ # with label.py
68103 color = 0xFFFFFF ,
69104 background_color = None ,
70105 line_spacing = 1.25 ,
@@ -102,8 +137,9 @@ def __init__(
102137
103138 # Calculate the text bounding box
104139
105- # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations
106- (tight_box_x , tight_box_y , x_offset , tight_y_offset ) = self .text_bounding_box (
140+ # Calculate tight box to provide bounding box dimensions to match label for
141+ # anchor_position calculations
142+ (tight_box_x , tight_box_y , x_offset , tight_y_offset ) = self ._text_bounding_box (
107143 text , font , self ._line_spacing , background_tight = True ,
108144 )
109145
@@ -113,7 +149,7 @@ def __init__(
113149 y_offset = tight_y_offset
114150
115151 else :
116- (box_x , box_y , x_offset , y_offset ) = self .text_bounding_box (
152+ (box_x , box_y , x_offset , y_offset ) = self ._text_bounding_box (
117153 text , font , self ._line_spacing , background_tight = background_tight ,
118154 )
119155 # Calculate the background size including padding
@@ -133,7 +169,7 @@ def __init__(
133169 self .bitmap = displayio .Bitmap (box_x , box_y , len (self .palette ))
134170
135171 # Place the text into the Bitmap
136- text_size = self .place_text (
172+ self ._place_text (
137173 self .bitmap ,
138174 text ,
139175 font ,
@@ -186,23 +222,15 @@ def __init__(
186222 ) # sets anchored_position with setter after bitmap is created
187223
188224 @staticmethod
189- def line_spacing_ypixels (font , line_spacing ):
225+ def _line_spacing_ypixels (font , line_spacing ):
190226 # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level
191227 return_value = int (line_spacing * font .get_bounding_box ()[1 ])
192228 return return_value
193229
194- def text_bounding_box (
230+ def _text_bounding_box (
195231 self , text , font , line_spacing , background_tight = False
196232 ): # **** change default background_tight=False
197233
198- label_position_yoffset = int ( # for calibration with label.py positioning
199- (
200- font .get_glyph (ord ("M" )).height
201- - font .get_bounding_box ()[1 ] * line_spacing
202- )
203- / 2
204- )
205-
206234 # This empirical approach checks several glyphs for maximum ascender and descender height
207235 # (consistent with label.py)
208236 glyphs = "M j'" # choose glyphs with highest ascender and lowest
@@ -213,13 +241,9 @@ def text_bounding_box(
213241 if this_glyph :
214242 ascender_max = max (ascender_max , this_glyph .height + this_glyph .dy )
215243 descender_max = max (descender_max , - this_glyph .dy )
216- font_height = ascender_max + descender_max
217- font_yoffset = ascender_max
218244
219245 lines = 1
220246
221- font_height = font .get_glyph (ord ("M" )).height
222-
223247 xposition = x_start = 0 # starting x position (left margin)
224248 yposition = y_start = 0
225249
@@ -229,7 +253,7 @@ def text_bounding_box(
229253 y_offset_tight = int (
230254 (
231255 font .get_glyph (ord ("M" )).height
232- - text .count ("\n " ) * self .line_spacing_ypixels (font , line_spacing )
256+ - text .count ("\n " ) * self ._line_spacing_ypixels (font , line_spacing )
233257 )
234258 / 2
235259 )
@@ -247,13 +271,13 @@ def text_bounding_box(
247271
248272 my_glyph = font .get_glyph (ord (char ))
249273
250- if my_glyph == None : # Error checking: no glyph found
274+ if my_glyph is None : # Error checking: no glyph found
251275 print ("Glyph not found: {}" .format (repr (char )))
252276 else :
253277 if newline :
254278 newline = False
255279 xposition = x_start # reset to left column
256- yposition = yposition + self .line_spacing_ypixels (
280+ yposition = yposition + self ._line_spacing_ypixels (
257281 font , line_spacing
258282 ) # Add a newline
259283 lines += 1
@@ -264,14 +288,14 @@ def text_bounding_box(
264288 top = min (top , - my_glyph .height - my_glyph .dy + y_offset_tight )
265289 bottom = max (bottom , yposition - my_glyph .dy + y_offset_tight )
266290
267- loose_height = (lines - 1 ) * self .line_spacing_ypixels (font , line_spacing ) + (
291+ loose_height = (lines - 1 ) * self ._line_spacing_ypixels (font , line_spacing ) + (
268292 ascender_max + descender_max
269293 )
270294
271295 label_calibration_offset = int (
272296 (
273297 font .get_glyph (ord ("M" )).height
274- - text .count ("\n " ) * self .line_spacing_ypixels (font , line_spacing )
298+ - text .count ("\n " ) * self ._line_spacing_ypixels (font , line_spacing )
275299 )
276300 / 2
277301 )
@@ -289,7 +313,8 @@ def text_bounding_box(
289313
290314 return (final_box_width , final_box_height , 0 , final_y_offset )
291315
292- def place_text (
316+ # pylint: disable=too-many-nested-blocks
317+ def _place_text (
293318 self ,
294319 bitmap ,
295320 text ,
@@ -299,20 +324,18 @@ def place_text(
299324 yposition ,
300325 text_palette_index = 1 ,
301326 background_palette_index = 0 ,
302- scale = 1 ,
303327 print_only_pixels = True , # print_only_pixels = True: only update the bitmap where the glyph
304328 # pixel color is > 0. This is especially useful for script fonts where glyph
305329 # bounding boxes overlap
306330 # Set `print_only_pixels=False` to write all pixels
307331 ):
308332 # placeText - Writes text into a bitmap at the specified location.
309333 #
310- # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts
334+ # Verify paletteIndex is working properly with * operator, especially
335+ # if accommodating multicolored fonts
311336 #
312337 # Note: Scale is not implemented at this time, is pushed up to Group level
313338
314- font_height = font .get_glyph (ord ("M" )).height
315-
316339 bitmap_width = bitmap .width
317340 bitmap_height = bitmap .height
318341
@@ -326,15 +349,15 @@ def place_text(
326349
327350 if char == "\n " : # newline
328351 xposition = x_start # reset to left column
329- yposition = yposition + self .line_spacing_ypixels (
352+ yposition = yposition + self ._line_spacing_ypixels (
330353 font , line_spacing
331354 ) # Add a newline
332355
333356 else :
334357
335358 my_glyph = font .get_glyph (ord (char ))
336359
337- if my_glyph == None : # Error checking: no glyph found
360+ if my_glyph is None : # Error checking: no glyph found
338361 print ("Glyph not found: {}" .format (repr (char )))
339362 else :
340363
@@ -343,31 +366,22 @@ def place_text(
343366 top = min (top , - my_glyph .height - my_glyph .dy )
344367 bottom = max (bottom , yposition - my_glyph .dy )
345368
346- width = my_glyph .width
347- height = my_glyph .height
348- dx = my_glyph .dx
349- dy = my_glyph .dy
350- shift_x = my_glyph .shift_x
351- shift_y = my_glyph .shift_x
352369 glyph_offset_x = (
353- my_glyph .tile_index * width
370+ my_glyph .tile_index * my_glyph . width
354371 ) # for type BuiltinFont, this creates the x-offset in the glyph bitmap.
355372 # for BDF loaded fonts, this should equal 0
356373
357- y_offset = font_height - height
358- for y in range (height ):
359- for x in range (width ):
360- x_placement = x + xposition + dx
361- y_placement = y + yposition - height - dy
362-
363- if (
364- (x_placement >= 0 )
365- and (y_placement >= 0 )
366- and (x_placement < bitmap_width )
367- and (y_placement < bitmap_height )
374+ for y in range (my_glyph .height ):
375+ for x in range (my_glyph .width ):
376+ x_placement = x + xposition + my_glyph .dx
377+ y_placement = y + yposition - my_glyph .height - my_glyph .dy
378+
379+ if (bitmap_width > x_placement >= 0 ) and (
380+ bitmap_height > y_placement >= 0
368381 ):
369382
370- # Allows for remapping the bitmap indexes using paletteIndex for background and text.
383+ # Allows for remapping the bitmap indexes using paletteIndex
384+ # for background and text.
371385 palette_indexes = (
372386 background_palette_index ,
373387 text_palette_index ,
@@ -380,14 +394,15 @@ def place_text(
380394 ]
381395
382396 if not print_only_pixels or this_pixel_color > 0 :
383- # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0
397+ # write all characters if printOnlyPixels = False,
398+ # or if thisPixelColor is > 0
384399 bitmap [
385400 y_placement * bitmap_width + x_placement
386401 ] = this_pixel_color
387402 elif y_placement > bitmap_height :
388403 break
389404
390- xposition = xposition + shift_x
405+ xposition = xposition + my_glyph . shift_x
391406
392407 return (left , top , right - left , bottom - top ) # bounding_box
393408
@@ -407,11 +422,12 @@ def anchor_point(self, new_anchor_point):
407422
408423 @property
409424 def anchored_position (self ):
425+ """Position relative to the anchor_point. Tuple containing x,y
426+ pixel coordinates."""
410427 return self ._anchored_position
411428
412429 @anchored_position .setter
413430 def anchored_position (self , new_position ):
414-
415431 self ._anchored_position = new_position
416432
417433 # Set anchored_position
0 commit comments