@@ -125,6 +125,7 @@ def __init__(self, font, **kwargs) -> None:
125125 self ._padding_left = kwargs .get ("padding_left" , 0 )
126126 self ._padding_right = kwargs .get ("padding_right" , 0 )
127127 self .base_alignment = kwargs .get ("base_alignment" , False )
128+ self .label_type = kwargs .get ("label_direction" , "LTR" )
128129
129130 if text is not None :
130131 self ._update_text (str (text ))
@@ -139,7 +140,6 @@ def _create_background_box(self, lines: int, y_offset: int) -> None:
139140 :param y_offset: int y pixel bottom coordinate for the background_box"""
140141
141142 left = self ._bounding_box [0 ]
142-
143143 if self ._background_tight : # draw a tight bounding box
144144 box_width = self ._bounding_box [2 ]
145145 box_height = self ._bounding_box [3 ]
@@ -149,14 +149,33 @@ def _create_background_box(self, lines: int, y_offset: int) -> None:
149149 else : # draw a "loose" bounding box to include any ascenders/descenders.
150150 ascent , descent = self ._get_ascent_descent ()
151151
152- box_width = self ._bounding_box [2 ] + self ._padding_left + self ._padding_right
153- x_box_offset = - self ._padding_left
154- box_height = (
155- (ascent + descent )
156- + int ((lines - 1 ) * self .height * self ._line_spacing )
157- + self ._padding_top
158- + self ._padding_bottom
159- )
152+ if (
153+ self .label_type == "UPR"
154+ or self .label_type == "DWR"
155+ or self .label_type == "TTB"
156+ ):
157+ box_height = (
158+ self ._bounding_box [3 ] + self ._padding_top + self ._padding_bottom
159+ )
160+ x_box_offset = - self ._padding_bottom
161+ box_width = (
162+ (ascent + descent )
163+ + int ((lines - 1 ) * self .width * self ._line_spacing )
164+ + self ._padding_left
165+ + self ._padding_right
166+ )
167+ else :
168+ box_width = (
169+ self ._bounding_box [2 ] + self ._padding_left + self ._padding_right
170+ )
171+ x_box_offset = - self ._padding_left
172+ box_height = (
173+ (ascent + descent )
174+ + int ((lines - 1 ) * self .height * self ._line_spacing )
175+ + self ._padding_top
176+ + self ._padding_bottom
177+ )
178+
160179 if self .base_alignment :
161180 y_box_offset = - ascent - self ._padding_top
162181 else :
@@ -165,17 +184,31 @@ def _create_background_box(self, lines: int, y_offset: int) -> None:
165184 box_width = max (0 , box_width ) # remove any negative values
166185 box_height = max (0 , box_height ) # remove any negative values
167186
187+ if self .label_type == "UPR" :
188+ movx = left + x_box_offset
189+ movy = - box_height - x_box_offset
190+ elif self .label_type == "DWR" :
191+ movx = left + x_box_offset
192+ movy = x_box_offset
193+ elif self .label_type == "TTB" :
194+ movx = left + x_box_offset
195+ movy = x_box_offset
196+ else :
197+ movx = left + x_box_offset
198+ movy = y_box_offset
199+
168200 background_bitmap = displayio .Bitmap (box_width , box_height , 1 )
169201 tile_grid = displayio .TileGrid (
170202 background_bitmap ,
171203 pixel_shader = self ._background_palette ,
172- x = left + x_box_offset ,
173- y = y_box_offset ,
204+ x = movx ,
205+ y = movy ,
174206 )
175207
208+
176209 return tile_grid
177210
178- def _update_background_color (self , new_color ) :
211+ def _update_background_color (self , new_color : int ) -> None :
179212 """Private class function that allows updating the font box background color
180213 :param new_color: int color as an RGB hex number."""
181214
@@ -231,8 +264,8 @@ def _update_background_color(self, new_color):
231264 self ._added_background_tilegrid = False
232265
233266 def _update_text (
234- self , new_text
235- ): # pylint: disable=too-many-locals ,too-many-branches, too-many-statements
267+ self , new_text : str
268+ ) -> None : # pylint: disable=too-many-locals ,too-many-branches, too-many-statements
236269 x = 0
237270 y = 0
238271 if self ._added_background_tilegrid :
@@ -245,8 +278,15 @@ def _update_text(
245278 else :
246279 self ._y_offset = self ._get_ascent () // 2
247280
248- right = top = bottom = 0
249- left = None
281+ if self .label_type == "RTL" :
282+ left = top = bottom = 0
283+ right = None
284+ elif self .label_type == "LTR" :
285+ right = top = bottom = 0
286+ left = None
287+ else :
288+ top = right = left = 0
289+ bottom = 0
250290
251291 for character in new_text :
252292 if character == "\n " :
@@ -256,17 +296,74 @@ def _update_text(
256296 glyph = self ._font .get_glyph (ord (character ))
257297 if not glyph :
258298 continue
259- right = max (right , x + glyph .shift_x , x + glyph .width + glyph .dx )
260- if x == 0 :
261- if left is None :
262- left = glyph .dx
299+
300+ if self .label_type == "LTR" or self .label_type == "RTL" :
301+ bottom = max (bottom , y - glyph .dy + y_offset )
302+ if y == 0 : # first line, find the Ascender height
303+ top = min (top , - glyph .height - glyph .dy + y_offset )
304+ position_y = y - glyph .height - glyph .dy + y_offset
305+
306+ if self .label_type == "LTR" :
307+ right = max (right , x + glyph .shift_x , x + glyph .width + glyph .dx )
308+ if x == 0 :
309+ if left is None :
310+ left = glyph .dx
311+ else :
312+ left = min (left , glyph .dx )
313+ position_x = x + glyph .dx
263314 else :
264- left = min (left , glyph .dx )
265- if y == 0 : # first line, find the Ascender height
266- top = min (top , - glyph .height - glyph .dy + self ._y_offset )
267- bottom = max (bottom , y - glyph .dy + self ._y_offset )
268- position_y = y - glyph .height - glyph .dy + self ._y_offset
269- position_x = x + glyph .dx
315+ left = max (
316+ left , abs (x ) + glyph .shift_x , abs (x ) + glyph .width + glyph .dx
317+ )
318+ if x == 0 :
319+ if right is None :
320+ right = glyph .dx
321+ else :
322+ right = max (right , glyph .dx )
323+ position_x = x - glyph .width
324+
325+ if self .label_type == "TTB" :
326+ if x == 0 :
327+ if left is None :
328+ left = glyph .dx
329+ else :
330+ left = min (left , glyph .dx )
331+ if y == 0 :
332+ top = min (top , - glyph .dy )
333+
334+ bottom = max (bottom , y + glyph .height , y + glyph .height + glyph .dy )
335+ right = max (
336+ right , x + glyph .width + glyph .dx , x + glyph .shift_x + glyph .dx
337+ )
338+ position_y = y + glyph .dy
339+ position_x = x - glyph .width // 2 + y_offset
340+
341+ if self .label_type == "UPR" :
342+ if x == 0 :
343+ if bottom is None :
344+ bottom = - glyph .dx
345+
346+ if y == 0 : # first line, find the Ascender height
347+ bottom = min (bottom , - glyph .dy )
348+ left = min (left , x - glyph .height + y_offset )
349+ top = min (top , y - glyph .width - glyph .dx , y - glyph .shift_x )
350+ right = max (right , x + glyph .height , x + glyph .height - glyph .dy )
351+ position_y = y - glyph .width - glyph .dx
352+ position_x = x - glyph .height - glyph .dy + y_offset
353+
354+ if self .label_type == "DWR" :
355+ if y == 0 :
356+ if top is None :
357+ top = - glyph .dx
358+ top = min (top , - glyph .dx )
359+ if x == 0 :
360+ left = min (left , - glyph .dy )
361+ left = min (left , x , x - glyph .dy - y_offset )
362+ bottom = max (bottom , y + glyph .width + glyph .dx , y + glyph .shift_x )
363+ right = max (right , x + glyph .height )
364+ position_y = y + glyph .dx
365+ position_x = x + glyph .dy - y_offset
366+
270367 if glyph .width > 0 and glyph .height > 0 :
271368 try :
272369 # pylint: disable=unexpected-keyword-arg
@@ -288,27 +385,63 @@ def _update_text(
288385 x = position_x ,
289386 y = position_y ,
290387 )
388+
389+ if self .label_type == "UPR" :
390+ face .transpose_xy = True
391+ face .flip_x = True
392+ if self .label_type == "DWR" :
393+ face .transpose_xy = True
394+ face .flip_y = True
395+
291396 if tilegrid_count < len (self .local_group ):
292397 self .local_group [tilegrid_count ] = face
293398 else :
294399 self .local_group .append (face )
295400 tilegrid_count += 1
296- x += glyph .shift_x
401+
402+ if self .label_type == "RTL" :
403+ x = x - glyph .shift_x
404+ if self .label_type == "TTB" :
405+ if glyph .height < 2 :
406+ y = y + glyph .shift_x
407+ else :
408+ y = y + glyph .height + 1
409+ if self .label_type == "UPR" :
410+ y = y - glyph .shift_x
411+ if self .label_type == "DWR" :
412+ y = y + glyph .shift_x
413+ if self .label_type == "LTR" :
414+ x = x + glyph .shift_x
415+
297416 i += 1
298- # Remove the rest
299417
300- if left is None :
418+ if self . label_type == "LTR" and left is None :
301419 left = 0
420+ if self .label_type == "RTL" and right is None :
421+ right = 0
422+ if self .label_type == "TTB" and top is None :
423+ top = 0
302424
303425 while len (self .local_group ) > tilegrid_count : # i:
304426 self .local_group .pop ()
427+
428+ if self .label_type == "RTL" :
429+ self ._bounding_box = (- left , top , left - right , bottom - top )
430+ if self .label_type == "TTB" :
431+ self ._bounding_box = (left , top , right - left , bottom - top )
432+ if self .label_type == "UPR" :
433+ self ._bounding_box = (left , top , right , bottom - top )
434+ if self .label_type == "DWR" :
435+ self ._bounding_box = (left , top , right , bottom - top )
436+ if self .label_type == "LTR" :
437+ self ._bounding_box = (left , top , right - left , bottom - top )
438+
305439 self ._text = new_text
306- self ._bounding_box = (left , top , right - left , bottom - top )
307440
308441 if self .background_color is not None :
309442 self ._update_background_color (self ._background_color )
310443
311- def _reset_text (self , new_text ) :
444+ def _reset_text (self , new_text : str ) -> None :
312445 new_text = self ._tab_text .join (new_text .split ("\t " ))
313446 try :
314447 current_anchored_position = self .anchored_position
@@ -317,7 +450,7 @@ def _reset_text(self, new_text):
317450 except RuntimeError as run_error :
318451 raise RuntimeError ("Text length exceeds max_glyphs" ) from run_error
319452
320- def _set_font (self , new_font ):
453+ def _set_font (self , new_font ) -> None :
321454 old_text = self ._text
322455 current_anchored_position = self .anchored_position
323456 self ._text = ""
@@ -326,11 +459,11 @@ def _set_font(self, new_font):
326459 self ._update_text (str (old_text ))
327460 self .anchored_position = current_anchored_position
328461
329- def _set_line_spacing (self , new_line_spacing ) :
462+ def _set_line_spacing (self , new_line_spacing : float ) -> None :
330463 self ._line_spacing = new_line_spacing
331464 self .text = self ._text # redraw the box
332465
333- def _set_text (self , new_text , scale ) :
466+ def _set_text (self , new_text : str , scale : int ) -> None :
334467 self ._reset_text (new_text )
335468
336469 def _set_background_color (self , new_color ):
0 commit comments