33
33
34
34
**Hardware:**
35
35
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
37
38
inline format: "* `Link Text <url>`_"
38
39
39
40
**Software and Dependencies:**
40
41
41
42
* Adafruit CircuitPython firmware for the supported boards:
42
43
https://github.com/adafruit/circuitpython/releases
43
44
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.
45
47
46
48
# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
47
49
# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
48
50
"""
49
51
50
52
import displayio
51
53
54
+ __version__ = "0.0.0-auto.0"
55
+ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
56
+
52
57
53
58
class 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
54
89
55
90
# Class variable
56
91
# To save memory, set Label._memory_saver=True and avoid storing the text string in the class.
@@ -63,8 +98,8 @@ def __init__(
63
98
x = 0 ,
64
99
y = 0 ,
65
100
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
68
103
color = 0xFFFFFF ,
69
104
background_color = None ,
70
105
line_spacing = 1.25 ,
@@ -102,8 +137,9 @@ def __init__(
102
137
103
138
# Calculate the text bounding box
104
139
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 (
107
143
text , font , self ._line_spacing , background_tight = True ,
108
144
)
109
145
@@ -113,7 +149,7 @@ def __init__(
113
149
y_offset = tight_y_offset
114
150
115
151
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 (
117
153
text , font , self ._line_spacing , background_tight = background_tight ,
118
154
)
119
155
# Calculate the background size including padding
@@ -133,7 +169,7 @@ def __init__(
133
169
self .bitmap = displayio .Bitmap (box_x , box_y , len (self .palette ))
134
170
135
171
# Place the text into the Bitmap
136
- text_size = self .place_text (
172
+ self ._place_text (
137
173
self .bitmap ,
138
174
text ,
139
175
font ,
@@ -186,23 +222,15 @@ def __init__(
186
222
) # sets anchored_position with setter after bitmap is created
187
223
188
224
@staticmethod
189
- def line_spacing_ypixels (font , line_spacing ):
225
+ def _line_spacing_ypixels (font , line_spacing ):
190
226
# Note: Scale is not implemented at this time, any scaling is pushed up to the Group level
191
227
return_value = int (line_spacing * font .get_bounding_box ()[1 ])
192
228
return return_value
193
229
194
- def text_bounding_box (
230
+ def _text_bounding_box (
195
231
self , text , font , line_spacing , background_tight = False
196
232
): # **** change default background_tight=False
197
233
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
-
206
234
# This empirical approach checks several glyphs for maximum ascender and descender height
207
235
# (consistent with label.py)
208
236
glyphs = "M j'" # choose glyphs with highest ascender and lowest
@@ -213,13 +241,9 @@ def text_bounding_box(
213
241
if this_glyph :
214
242
ascender_max = max (ascender_max , this_glyph .height + this_glyph .dy )
215
243
descender_max = max (descender_max , - this_glyph .dy )
216
- font_height = ascender_max + descender_max
217
- font_yoffset = ascender_max
218
244
219
245
lines = 1
220
246
221
- font_height = font .get_glyph (ord ("M" )).height
222
-
223
247
xposition = x_start = 0 # starting x position (left margin)
224
248
yposition = y_start = 0
225
249
@@ -229,7 +253,7 @@ def text_bounding_box(
229
253
y_offset_tight = int (
230
254
(
231
255
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 )
233
257
)
234
258
/ 2
235
259
)
@@ -247,13 +271,13 @@ def text_bounding_box(
247
271
248
272
my_glyph = font .get_glyph (ord (char ))
249
273
250
- if my_glyph == None : # Error checking: no glyph found
274
+ if my_glyph is None : # Error checking: no glyph found
251
275
print ("Glyph not found: {}" .format (repr (char )))
252
276
else :
253
277
if newline :
254
278
newline = False
255
279
xposition = x_start # reset to left column
256
- yposition = yposition + self .line_spacing_ypixels (
280
+ yposition = yposition + self ._line_spacing_ypixels (
257
281
font , line_spacing
258
282
) # Add a newline
259
283
lines += 1
@@ -264,14 +288,14 @@ def text_bounding_box(
264
288
top = min (top , - my_glyph .height - my_glyph .dy + y_offset_tight )
265
289
bottom = max (bottom , yposition - my_glyph .dy + y_offset_tight )
266
290
267
- loose_height = (lines - 1 ) * self .line_spacing_ypixels (font , line_spacing ) + (
291
+ loose_height = (lines - 1 ) * self ._line_spacing_ypixels (font , line_spacing ) + (
268
292
ascender_max + descender_max
269
293
)
270
294
271
295
label_calibration_offset = int (
272
296
(
273
297
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 )
275
299
)
276
300
/ 2
277
301
)
@@ -289,7 +313,8 @@ def text_bounding_box(
289
313
290
314
return (final_box_width , final_box_height , 0 , final_y_offset )
291
315
292
- def place_text (
316
+ # pylint: disable=too-many-nested-blocks
317
+ def _place_text (
293
318
self ,
294
319
bitmap ,
295
320
text ,
@@ -299,20 +324,18 @@ def place_text(
299
324
yposition ,
300
325
text_palette_index = 1 ,
301
326
background_palette_index = 0 ,
302
- scale = 1 ,
303
327
print_only_pixels = True , # print_only_pixels = True: only update the bitmap where the glyph
304
328
# pixel color is > 0. This is especially useful for script fonts where glyph
305
329
# bounding boxes overlap
306
330
# Set `print_only_pixels=False` to write all pixels
307
331
):
308
332
# placeText - Writes text into a bitmap at the specified location.
309
333
#
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
311
336
#
312
337
# Note: Scale is not implemented at this time, is pushed up to Group level
313
338
314
- font_height = font .get_glyph (ord ("M" )).height
315
-
316
339
bitmap_width = bitmap .width
317
340
bitmap_height = bitmap .height
318
341
@@ -326,15 +349,15 @@ def place_text(
326
349
327
350
if char == "\n " : # newline
328
351
xposition = x_start # reset to left column
329
- yposition = yposition + self .line_spacing_ypixels (
352
+ yposition = yposition + self ._line_spacing_ypixels (
330
353
font , line_spacing
331
354
) # Add a newline
332
355
333
356
else :
334
357
335
358
my_glyph = font .get_glyph (ord (char ))
336
359
337
- if my_glyph == None : # Error checking: no glyph found
360
+ if my_glyph is None : # Error checking: no glyph found
338
361
print ("Glyph not found: {}" .format (repr (char )))
339
362
else :
340
363
@@ -343,31 +366,22 @@ def place_text(
343
366
top = min (top , - my_glyph .height - my_glyph .dy )
344
367
bottom = max (bottom , yposition - my_glyph .dy )
345
368
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
352
369
glyph_offset_x = (
353
- my_glyph .tile_index * width
370
+ my_glyph .tile_index * my_glyph . width
354
371
) # for type BuiltinFont, this creates the x-offset in the glyph bitmap.
355
372
# for BDF loaded fonts, this should equal 0
356
373
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
368
381
):
369
382
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.
371
385
palette_indexes = (
372
386
background_palette_index ,
373
387
text_palette_index ,
@@ -380,14 +394,15 @@ def place_text(
380
394
]
381
395
382
396
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
384
399
bitmap [
385
400
y_placement * bitmap_width + x_placement
386
401
] = this_pixel_color
387
402
elif y_placement > bitmap_height :
388
403
break
389
404
390
- xposition = xposition + shift_x
405
+ xposition = xposition + my_glyph . shift_x
391
406
392
407
return (left , top , right - left , bottom - top ) # bounding_box
393
408
@@ -407,11 +422,12 @@ def anchor_point(self, new_anchor_point):
407
422
408
423
@property
409
424
def anchored_position (self ):
425
+ """Position relative to the anchor_point. Tuple containing x,y
426
+ pixel coordinates."""
410
427
return self ._anchored_position
411
428
412
429
@anchored_position .setter
413
430
def anchored_position (self , new_position ):
414
-
415
431
self ._anchored_position = new_position
416
432
417
433
# Set anchored_position
0 commit comments