From 32f2bf2422155840664317e62ee8805e0be00119 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Sun, 2 Aug 2020 10:51:23 -0500 Subject: [PATCH 01/26] Added first revision of bitmap_label.py. A lot of cleanup to do on this, but wanted to make a commit in case I happend to lose anything. --- adafruit_display_text/bitmap_label.py | 516 ++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 adafruit_display_text/bitmap_label.py diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py new file mode 100644 index 0000000..33f7d12 --- /dev/null +++ b/adafruit_display_text/bitmap_label.py @@ -0,0 +1,516 @@ +# The MIT License (MIT) +# +# Copyright (c) 2020 Kevin Matocha +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`bitmap_label` +================================================================================ + +Text graphics handling for CircuitPython, including text boxes + + +* Author(s): Kevin Matocha + +Implementation Notes +-------------------- + +**Hardware:** + +.. todo:: Add links to any specific hardware product page(s), or category page(s). Use unordered list & hyperlink rST + inline format: "* `Link Text `_" + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://github.com/adafruit/circuitpython/releases + +.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based on the library's use of either. + +# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice +# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register +""" + +#import terminalio +import displayio + +def lineSpacingY(font, lineSpacing): + # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level + #fontHeight = font.get_glyph(ord('M')).height + fontHeight = font.get_bounding_box()[1] + returnValue = int(lineSpacing * fontHeight) + return returnValue + +def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** change default background_tight=False + # this is the preferred approach since it utilizes the BDF file values + #(font_width, font_height, font_xoffset, font_yoffset)=font.get_bounding_box() # max glyph dimension + + + label_position_yoffset = int( # for calibration with label.py positioning + ( + font.get_glyph(ord("M")).height + - text.count("\n") * font.get_bounding_box()[1] * lineSpacing + ) + / 2 + ) + + # this empirical approach checks several glyphs for maximum ascender and descender height + # Alternate option: utilize `font.get_bounding_box()` to get max glyph dimensions + glyphs = "M j'" # choose glyphs with highest ascender and lowest + # descender, will depend upon font used + ascender_max = descender_max = 0 + for char in glyphs: + this_glyph = font.get_glyph(ord(char)) + if this_glyph: + #print('char: {}, this_glyph.height: {}, this_glyph.dy: {}'.format(char, this_glyph.height, this_glyph.dy)) + ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) + descender_max = max(descender_max, -this_glyph.dy) + #print('ascender_max: {}, descender_max: {}'.format(ascender_max, descender_max)) + #print('FINAL -- ascender_max: {}, descender_max: {}'.format(ascender_max, descender_max)) + font_height=ascender_max+descender_max + font_yoffset=ascender_max + + + base_point=(0,0) # entry point for the next glyph + # calculate dimensions for both "tight" and "loose" bounding boxes + x1_min=y1_min=x2_max=y2_max=None # initialize the bounding box corners (1:lower left, 2: upper right) + + y_offset=None # Provide the baseline y_offset for the bitmap + + firstline=True # handles special cases for first line + + box_height=0 + box_width=0 + box_height_adder=0 + + for char in text: + if char == '\n': # newline + #if y1_min is None: + # y1_min=font_yoffset-base_point[1] + if firstline: # This the first line + firstline = False + if background_tight: + if y1_min is None: + y_offset=label_position_yoffset + box_height_adder = lineSpacingY(font, lineSpacing-1) - y_offset + #y_offset=label_position_yoffset + #box_height_adder=-label_position_yoffset + print('label_position_yoffset: {}, lineSpacingY:{}, font[1]: {}'.format(label_position_yoffset, lineSpacingY(font, lineSpacing), font.get_bounding_box()[1])) + # for a leading newline, this adds to the box_height + else: + y_offset = -y1_min # The bitmap y-offset is the max y-position of the first line + + else: # background is "loose" + #y_offset = font_height + font_yoffset + y_offset = font_yoffset + if y1_min is None: + box_height_adder = lineSpacingY(font, lineSpacing) + + base_point=(0, base_point[1] + lineSpacingY(font, lineSpacing)) # baseline point for the next glyph + + else: + myGlyph = font.get_glyph(ord(char)) + if myGlyph == None: # Error checking: no glyph found + print('Glyph not found: {}'.format(repr(char))) + else: + x1=base_point[0] # x1,y1 = upper left of glyph + x2=x1+myGlyph.shift_x # x2,y2 = lower right of glyph + if background_tight: + y1=base_point[1]-(myGlyph.height+myGlyph.dy) # Upper left corner Note: Positive Y is down + y2=y1+myGlyph.height + else: # background is "loose" + y1=base_point[1]-font_yoffset + y2=y1+font_height + base_point=(base_point[0]+myGlyph.shift_x, base_point[1]+myGlyph.shift_y) # update the next baseline point location + + # find the min bounding box size incorporating this glyph's bounding box + if x1_min is not None: + x1_min = min(x1, x1_min) + else: + x1_min = min(0, x1) # **** + if y1_min is not None: + y1_min = min(y1, y1_min) + else: + y1_min = y1 + if x2_max is not None: + x2_max = max(x2, x2_max) + else: + x2_max = x2 + if y2_max is not None: + y2_max = max(y2, y2_max) + else: + y2_max = y2 + + if x1_min is not None and x2_max is not None: + box_width = max(0, x2_max - x1_min) + if y1_min is not None and y2_max is not None: + box_height = y2_max - y1_min + + + if firstline: # This the first line + if background_tight: + y_offset =-y1_min # The bitmap y-offset is the max y-position of the first line + else: # background is "loose" + #y_offset = font_height + font_yoffset + y_offset=font_yoffset + + box_height=max(0, box_height+box_height_adder) # to add any additional height for leading newlines + + print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) + + return(box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset + + + +def text_bounding_box(text, font, lineSpacing, background_tight=False): + # bounding_box - determines the bounding box size around the new text to be added. + # To be used to calculate if the new text will be printed within the bounding_box + # This function can used to determine character-wrapping or word-wrapping for a + # text terminal box, prior to actually printing the text in the bitmap. + # + # Note: Scale is not implemented at this time + + #print('bounding_box text: {}'.format(text)) + boxHeight = boxWidth = 0 + fontHeight = font.get_glyph(ord("M")).height + thisLineWidth = 0 + + for char in text: + if char == '\n': # newline + boxWidth = max(boxWidth, thisLineWidth) # check to see if the last line is wider than any others. + thisLineWidth = 0 # new line, so restart thislineWidth at 0 + boxHeight = boxHeight + _lineSpacingY(font, lineSpacing) # add a lineSpacing to the boxHeight + + else: + myGlyph = font.get_glyph(ord(char)) + if myGlyph == None: # Error checking: no glyph found + print('Glyph not found: {}'.format(repr(char))) + else: + width = myGlyph.width + height = myGlyph.height + dx = myGlyph.dx + dy = myGlyph.dy + shift_x = myGlyph.shift_x + shift_y = myGlyph.shift_y + + # Not working yet*** + # This offset is used to match the label.py function from Adafruit_Display_Text library + # y_offset = int( + # ( + # self._font.get_glyph(ord("M")).height + # - new_text.count("\n") * self.height * self.line_spacing + # ) + # / 2 ) + + # yOffset = int( (fontHeight-height*lineSpacing)/2 ) + yOffset = fontHeight - height + + thisLineWidth = thisLineWidth + shift_x + boxHeight = max(boxHeight, height - dy + yOffset) + + boxWidth = max(boxWidth, thisLineWidth) + + return (boxWidth, boxHeight) + + +def place_text( + bitmap, text, font, lineSpacing, xPosition, yPosition, + textPaletteIndex=1, + backgroundPaletteIndex=0, + scale=1, + printOnlyPixels=True, # only update the bitmap where the glyph pixel color is > 0 + # this is especially useful for script fonts +): + # placeText - Writes text into a bitmap at the specified location. + # + # (xPosition, yPosition) correspond to upper left corner of the height of the 'M' glyph + # To Do: Add anchor positions, and adjust the default baseline position to match + # the current "label" function + # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts + # + # Note: Scale is not implemented at this time + + + fontHeight = font.get_glyph(ord("M")).height + + bitmapWidth = bitmap.width + bitmapHeight = bitmap.height + + xStart=xPosition # starting x position (left margin) + yStart=yPosition + + # **** check this. + if backgroundPaletteIndex != 0: # the textbackground is different from the bitmap background + # draw a bounding box where the text will go + + (ignore, fontLineHeight)=bounding_box('M g', font, lineSpacing, scale) # check height with ascender and descender. + (boxX, boxY) = bounding_box(text, font, lineSpacing, scale) + boxY=max(fontLineHeight, boxY) + + for y in range(boxY): + for x in range(boxX): + if (xPosition+x < bitmapWidth) and (yPosition+y < bitmapHeight): # check boundaries + #bitmap[xPosition+x, yPosition+y]=backgroundPaletteIndex + bitmap[(yPosition+y)*bitmapWidth + (xPosition + x)]=backgroundPaletteIndex + + left=right=xStart + top=bottom=yStart + print('xStart, yStart: {}, {}'.format(xStart, yStart)) + + for char in text: + + if char == '\n': # newline + xPosition = xStart # reset to left column + yPosition = yPosition + lineSpacingY(font, lineSpacing) # Add a newline + + else: + + myGlyph = font.get_glyph(ord(char)) + + if myGlyph == None: # Error checking: no glyph found + print('Glyph not found: {}'.format(repr(char))) + else: + + right = max(right, xPosition + myGlyph.shift_x) + if yPosition == yStart: # first line, find the Ascender height + top = min(top, -myGlyph.height - myGlyph.dy) + bottom = max(bottom, yPosition - myGlyph.dy) + + width = myGlyph.width + height = myGlyph.height + # print('glyph width: {}, height: {}'.format(width, height)) + dx = myGlyph.dx + dy = myGlyph.dy + shift_x = myGlyph.shift_x + shift_y = myGlyph.shift_x + glyph_offset_x = myGlyph.tile_index * width # for type BuiltinFont, this creates the x-offset in the glyph bitmap. + # for BDF loaded fonts, this should equal 0 + + yOffset = fontHeight - height + for y in range(height): + for x in range(width): + xPlacement = x + xPosition + dx + yPlacement = y + yPosition - height - dy #+ yOffset + + #left=min(xPlacement, left) + #right=max(xPlacement, right) + #top=min(yPlacement, top) + #bottom=max(yPlacement, bottom) + + if ( + (xPlacement >= 0) + and (yPlacement >= 0) + and (xPlacement < bitmapWidth) + and (yPlacement < bitmapHeight) + ): + + paletteIndexes=(backgroundPaletteIndex, textPaletteIndex) + + # Allows for different paletteIndex for background and text. + thisPixelColor=paletteIndexes[myGlyph.bitmap[y*width + x+glyph_offset_x]] + if not printOnlyPixels or thisPixelColor > 0: + # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 + bitmap[yPlacement*bitmapWidth + xPlacement] = thisPixelColor + elif (yPlacement > bitmapHeight): + break + + xPosition = xPosition + shift_x + + print('left: {}, top: {}, right: {}, bottom: {}'.format(left, top, right, bottom)) + + return (left, top, left+right, bottom-top) # bounding_box + + +class Label(displayio.Group): + + # Class variable + # To save memory, set Bitmap.Label._memory_saver=True, to avoid storing the text string in the class. + # If set to False, the class saves the text string for future reference. *** use getter + _memory_saver=True + + def __init__( + self, + font, + x=0, + y=0, + text="", + max_glyphs=None, # This input parameter is ignored, only present for compatibility with label.py + #width, height, + color=0xFFFFFF, + background_color=None, + line_spacing=1.25, + background_tight=False, + padding_top=0, + padding_bottom=0, + padding_left=0, + padding_right=0, + anchor_point=(0,0), + anchored_position=None, + **kwargs + ): + + if text == "": + raise RuntimeError("Please provide text string") + + # Scale will be passed to Group using kwargs. + if "scale" in kwargs.keys(): + self._scale = kwargs["scale"] + else: + self._scale = 1 + + self._line_spacing=line_spacing + + if self._memory_saver == False: + self._text = text # text to be displayed + + # limit padding to >= 0 *** raise an error if negative padding is requested + padding_top = max(0, padding_top) + padding_bottom = max(0, padding_bottom) + padding_left = max(0, padding_left) + padding_right = max(0, padding_right) + + # Calculate the text bounding box + + # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations + (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box2(text, font, + self._line_spacing, + background_tight=True, + ) + + (box_x, box_y, x_offset, y_offset) = text_bounding_box2(text, font, + self._line_spacing, + background_tight=background_tight, + ) + # Calculate the background size including padding + box_x = box_x + padding_left + padding_right + box_y = box_y + padding_top + padding_bottom + + #print('box_x: {}, box_y: {}'.format(box_x, box_y)) + + # Determine the x,y offsets of the text inside the bitmap box, to be used with place_text + # **** Is this x_offset=padding_top and y_offset=padding_left + + + + # Create the two-color palette + self.palette = displayio.Palette(2) + if background_color is not None: + self.palette[0] = background_color + else: + self.palette[0] = 0 + self.palette.make_transparent(0) + self.palette[1] = color + + # Create the bitmap and TileGrid + self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) + + # Place the text into the Bitmap + + text_size=place_text(self.bitmap, text, font, self._line_spacing, padding_left+x_offset, padding_top+y_offset) + + + + label_position_yoffset = int( # for calibration with label.py positioning + ( + font.get_glyph(ord("M")).height + - text.count("\n") * font.get_bounding_box()[1] * self._line_spacing + ) + / 2 + ) + + #print('label_position_yoffset: {}, text: {}'.format(label_position_yoffset, text)) + + self.tilegrid = displayio.TileGrid(self.bitmap, pixel_shader=self.palette, + width=1, height=1, + tile_width=box_x, tile_height=box_y, + default_tile=0, + x=0, + y=label_position_yoffset - y_offset, + ) + #print('box_x,y: ({},{}) y: {}, label_position_yoffset: {}'.format(box_x, box_y, y, label_position_yoffset)) + print('bitmap_label bitmap width: {} height: {}, (x,y): ({},{})'.format(box_x, box_y, x, y+label_position_yoffset)) + + # instance the Group with super... super().__init__( + # this Group will contain just one TileGrid with one contained bitmap + super().__init__(max_size=1, x=x, y=y, **kwargs) # this will include any arguments, including scale + self.append(self.tilegrid) # add the bitmap's tilegrid to the group + + ####### ******* + # Set the tileGrid position in the parent based upon anchor_point and anchor_position + # **** Should scale affect the placement of anchor_position? + + self.bounding_box=(self.tilegrid.x, self.tilegrid.y+(y_offset-tight_y_offset), tight_box_x, tight_box_y) + #self.bounding_box = (self.tilegrid.x, self.tilegrid.y, box_x, box_y) + # Update bounding_box values. Note: To be consistent with label.py, + # this is the bounding box for the text only, not including the background. + # ******** Need repair + # Create the TileGrid to hold the single Bitmap (self.bitmap) + + self._anchored_position=anchored_position + self.anchor_point=anchor_point + self.anchored_position=self._anchored_position # sets anchored_position with setter after bitmap is created + + + @property + def anchor_point(self): + """Point that anchored_position moves relative to. + Tuple with decimal percentage of width and height. + (E.g. (0,0) is top left, (1.0, 0.5): is middle right.)""" + return self._anchor_point + + @anchor_point.setter + def anchor_point(self, new_anchor_point): + self._anchor_point = new_anchor_point + self.anchored_position = self._anchored_position # update the anchored_position using setter + + @property + def anchored_position(self): + return self._anchored_position + + @anchored_position.setter + def anchored_position(self, new_position): + #print('in bitmap_label self.tilegrid.x,y: {},{}'.format(self.tilegrid.x, self.tilegrid.y)) + #print('in bitmap_label self.x,y: {},{}'.format(self.x, self.y)) + + + self._anchored_position=new_position + #print('_anchor_point: {}, _anchored_position: {}, scale: {}'.format(self._anchor_point, self._anchored_position, self.scale)) + + # Set anchored_position + if (self._anchor_point is not None) and (self._anchored_position is not None): + new_x = int( + new_position[0] + - self._anchor_point[0] * (self.bounding_box[2] * self._scale) + ) + new_y = int( + new_position[1] + - (self._anchor_point[1] * self.bounding_box[3] * self.scale) + + round((self.bounding_box[3] * self.scale) / 2.0) + ) + self.x = new_x + self.y = new_y + print('bitmap_label new x,y: {},{}'.format(new_x, new_y)) + #print('out bitmap_label self.tilegrid.x,y: {},{}'.format(self.tilegrid.x, self.tilegrid.y)) + print('out bitmap_label self.x,y: {},{}'.format(self.x, self.y)) + + + + + + From bf8577692c997b9989dd9941bc8826c47e38a41f Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Sun, 2 Aug 2020 16:36:49 -0500 Subject: [PATCH 02/26] Fixed bug for index into glyph.bitmap in place_text --- adafruit_display_text/bitmap_label.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 33f7d12..f741e11 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -111,7 +111,7 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** box_height_adder = lineSpacingY(font, lineSpacing-1) - y_offset #y_offset=label_position_yoffset #box_height_adder=-label_position_yoffset - print('label_position_yoffset: {}, lineSpacingY:{}, font[1]: {}'.format(label_position_yoffset, lineSpacingY(font, lineSpacing), font.get_bounding_box()[1])) + #print('label_position_yoffset: {}, lineSpacingY:{}, font[1]: {}'.format(label_position_yoffset, lineSpacingY(font, lineSpacing), font.get_bounding_box()[1])) # for a leading newline, this adds to the box_height else: y_offset = -y1_min # The bitmap y-offset is the max y-position of the first line @@ -172,7 +172,7 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** box_height=max(0, box_height+box_height_adder) # to add any additional height for leading newlines - print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) + #print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) return(box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset @@ -234,14 +234,12 @@ def place_text( textPaletteIndex=1, backgroundPaletteIndex=0, scale=1, - printOnlyPixels=True, # only update the bitmap where the glyph pixel color is > 0 - # this is especially useful for script fonts + printOnlyPixels=True, # printOnlyPixels = True: only update the bitmap where the glyph pixel + # color is > 0 this is especially useful for script fonts where glyph + # bounding boxes overlap ): # placeText - Writes text into a bitmap at the specified location. # - # (xPosition, yPosition) correspond to upper left corner of the height of the 'M' glyph - # To Do: Add anchor positions, and adjust the default baseline position to match - # the current "label" function # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts # # Note: Scale is not implemented at this time @@ -271,7 +269,7 @@ def place_text( left=right=xStart top=bottom=yStart - print('xStart, yStart: {}, {}'.format(xStart, yStart)) + print('##place_text xStart, yStart: {}, {}'.format(xStart, yStart)) for char in text: @@ -323,16 +321,19 @@ def place_text( paletteIndexes=(backgroundPaletteIndex, textPaletteIndex) # Allows for different paletteIndex for background and text. - thisPixelColor=paletteIndexes[myGlyph.bitmap[y*width + x+glyph_offset_x]] + #thisPixelColor=paletteIndexes[myGlyph.bitmap[x+glyph_offset_x,y]] + thisPixelColor=paletteIndexes[myGlyph.bitmap[y*myGlyph.bitmap.width + x + glyph_offset_x]] + #print('myGlyph.bitmap.width,height: {},{} char: {}, myGlyph.tile_index: {}, (x,y): ({},{}), glyph_offset_x: {}, thisPixelColor: {}'.format(myGlyph.bitmap.width, myGlyph.bitmap.height, char, myGlyph.tile_index, x, y, glyph_offset_x, thisPixelColor)) if not printOnlyPixels or thisPixelColor > 0: # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 bitmap[yPlacement*bitmapWidth + xPlacement] = thisPixelColor + #print('* pixel') elif (yPlacement > bitmapHeight): break xPosition = xPosition + shift_x - print('left: {}, top: {}, right: {}, bottom: {}'.format(left, top, right, bottom)) + print('##place_text left: {}, top: {}, right: {}, bottom: {}'.format(left, top, right, bottom)) return (left, top, left+right, bottom-top) # bounding_box From b628dffa0eca69bea802546d54b77a5eb096e04e Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Sun, 2 Aug 2020 16:43:29 -0500 Subject: [PATCH 03/26] Sample file for debugging bitmap_label - see code.py --- examples/code.py | 408 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100755 examples/code.py diff --git a/examples/code.py b/examples/code.py new file mode 100755 index 0000000..f07914b --- /dev/null +++ b/examples/code.py @@ -0,0 +1,408 @@ +# Sample code using the textMap library and the "textBox" wrapper class +# Creates four textBox instances +# Inserts each textBox into a tileGrid group +# Writes text into the box one character at a time +# Moves the position of the textBox around the display +# Clears each textBox after the full string is written (even if the text is outside of the box) + +#import textmap +#from textmap import textBox + +import board +import displayio +import time +import terminalio +import fontio +import sys +import busio +#from adafruit_st7789 import ST7789 +from adafruit_ili9341 import ILI9341 + +from adafruit_display_text import bitmap_label +#from adafruit_display_text import bitmap_label as Label + +from adafruit_display_text import label + +# Setup the SPI display + +print('Starting the display...') # goes to serial only +displayio.release_displays() + + +spi = board.SPI() +tft_cs = board.D9 # arbitrary, pin not used +tft_dc = board.D10 +tft_backlight = board.D12 +tft_reset=board.D11 + +while not spi.try_lock(): + spi.configure(baudrate=32000000) + pass +spi.unlock() + +display_bus = displayio.FourWire( + spi, + command=tft_dc, + chip_select=tft_cs, + reset=tft_reset, + baudrate=32000000, + polarity=1, + phase=1, +) + +print('spi.frequency: {}'.format(spi.frequency)) + +DISPLAY_WIDTH=320 +DISPLAY_HEIGHT=240 + +#display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0) +display = ILI9341(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, rotation=180, auto_refresh=True) + +display.show(None) + +print ('Display is started') + + +# load all the fonts +print('loading fonts...') + +import terminalio + + +fontList = [] +fontHeight = [] + +##### the BuiltinFont terminalio.FONT has a different return strategy for get_glyphs and +# is currently not handled by these functions. +#fontList.append(terminalio.FONT) +#fontHeight = [10] # somehow the terminalio.FONT needs to be adjusted to 10 + +# Load some proportional fonts +fontFiles = [ + 'fonts/Helvetica-Bold-16.bdf', +# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 +# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText + ] + +from adafruit_bitmap_font import bitmap_font + +for i, fontFile in enumerate(fontFiles): + thisFont = bitmap_font.load_font(fontFile) + + + #thisFont=terminalio.FONT + + fontList.append(thisFont) + fontHeight.append( thisFont.get_glyph(ord("M")).height ) + + + +preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory + # preloading the glyphs will help speed up the rendering of text but will use more RAM + +if preloadTheGlyphs: + + # identify the glyphs to load into memory -> increases rendering speed + glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + + print('loading glyphs...') + for font in fontList: + font.load_glyphs(glyphs) + + print('Glyphs are loaded.') + + +#for char in glyphs: +# my_glyph=font.get_glyph(char) +# print('char: {}, size x,y ({},{}) offset x,y ({},{})'.format(chr(char), my_glyph.width, my_glyph.height, my_glyph.dx, my_glyph.dy)) + +print('Fonts completed loading.') + +# create group +import gc + +#tileGridList=[] # list of tileGrids +#print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) + + +myString12=('Bit Juice ({[]}) Monsters!\"\'ABCDEFGHIJKLMNOPQRSTUVWXYZ\npuppy bug jump ({[]})') +myString34='\nnone' +myString_bitmap_label='bitmap_label' +myString_label='label bitmap_label' +#myString=('Full Screen Size: This is a stationary box, not a stationery box') +#myString=('Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box.') +#myString=('MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM') +#print('myString: {}'.format(myString)) +#print('string length: {}'.format(len(myString))) + +gc.collect() +bitmap_label_start=gc.mem_free() +bmap_label = bitmap_label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=10, + line_spacing=1.25, + #anchored_position=(10,10), + ) + +#print("***bmap_label[0] (x,y): ({},{})".format(bmap_label[0].x, bmap_label[0].y)) +# +bmap_label2 = bitmap_label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + #anchored_position=(10,60), + ) +label3_padding=0 +bmap_label3 = bitmap_label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), + background_color=0xFFFF00, + padding_bottom=label3_padding, + padding_left=label3_padding, + padding_right=label3_padding, + padding_top=label3_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + #anchored_position=(10,100), + ) + +bmap_label4 = bitmap_label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + #anchored_position=(10,150), + ) +#bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString_bitmap_label, color=0x000000, max_glyphs=len(myString_bitmap_label), +bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + #anchored_position=(10,200), + ) + +myString6='bitmap_label -->' +bmap_label6 = bitmap_label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(1,0.5), + anchored_position=(200,200), + ) + + + +gc.collect() +bitmap_label_end=gc.mem_free() + +bmap_group = displayio.Group( max_size=6 ) # Create a group for displaying +bmap_group.append(bmap_label) +bmap_group.append(bmap_label2) +bmap_group.append(bmap_label3) +bmap_group.append(bmap_label4) +bmap_group.append(bmap_label5) +bmap_group.append(bmap_label6) + + + +gc.collect() +label_start=gc.mem_free() + +label1 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=10, + line_spacing=1.25, + #anchored_position=(10,10), + ) + +#print('label1 bounding_box: {}'.format(label1.bounding_box)) +#print('label1[0].width: {}, height: {}, x,y: ({},{})'.format(label1[0].tile_width, label1[0].tile_height, label1[0].x, label1[0].y)) + +#print("***label1[0] (x,y): ({},{})".format(label1[0].x, label1[0].y)) +#print("***label1 (x,y): ({},{})".format(label1.x, label1.y)) + + +label2 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + #anchored_position=(10,60), + ) + +label3 = label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), + background_color=0xFFFF00, + padding_bottom=label3_padding, + padding_left=label3_padding, + padding_right=label3_padding, + padding_top=label3_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + #anchored_position=(10,100), + ) + +label4 = label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + #anchored_position=(10,150), + ) + +label5 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + #anchored_position=(10,200), + ) + + +myString6 = '<-- label' +label6 = label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(0,0.5), + anchored_position=(50,200), + ) + +gc.collect() +label_end=gc.mem_free() + +label_group = displayio.Group( max_size=6 ) # Create a group for displaying +label_group.append(label1) +label_group.append(label2) +label_group.append(label3) +label_group.append(label4) +label_group.append(label5) +label_group.append(label6) + + + +print('bitmap_label mem usage: {}, label mem usage: {}'.format(bitmap_label_start-bitmap_label_end, label_start-label_end)) + + +gc.collect() +memBeforeLoop=gc.mem_free() +print('After display.show(myGroup), just before loop start Memory free: {}'.format(memBeforeLoop) ) + +print('bmap_label bounding_box: {}'.format(bmap_label.bounding_box)) +print('label1 bounding_box: {}'.format(label1.bounding_box)) +print('bmap_label2 bounding_box: {}'.format(bmap_label2.bounding_box)) +print('label2 bounding_box: {}'.format(label2.bounding_box)) + + +print('***') +print('bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) +print('bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) +print('label3 bounding_box: {}'.format(label3.bounding_box)) +print('label3 x,y: {},{}'.format(label3.x, label3.y)) +print('***') + + +print('bmap_label4 bounding_box: {}'.format(bmap_label4.bounding_box)) +print('label4 bounding_box: {}'.format(label4.bounding_box)) +print('bmap_label5 bounding_box: {}'.format(bmap_label5.bounding_box)) +print('label5 bounding_box: {}'.format(label5.bounding_box)) + +print('**************') +print('before ** bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) +print('1 - bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) #### how is this changing it? +print('before ** bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) +bmap_label3.anchor_point=(0,0) +bmap_label3.anchored_position=(200,150) + +label3.anchor_point=(0,0) +label3.anchored_position=(200,150) + + +print('***') +print('bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) +print('bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) +print('bmap_label3 tilegrid.x,y: {},{}'.format(bmap_label3.tilegrid.x, bmap_label3.tilegrid.y)) +print('bmap_label3[0].x,y: {},{}'.format(bmap_label3[0].x, bmap_label3[0].y)) +print('****') +print('label3 bounding_box: {}'.format(label3.bounding_box)) +print('label3 x,y: {},{}'.format(label3.x, label3.y)) +print('label3 tilegrid.x,y: {},{}'.format(label3[1].x, label3[1].y)) + +print('***') + +display.auto_refresh=True + +while True: + print('bitmap_label') + time.sleep(0.1) + display.show(bmap_group) + + time.sleep(2) + + print('label') + time.sleep(0.1) + display.show(label_group) + time.sleep(2) + + + + + + From 4a7e7a017e7783622f7e03b4d30bc2c4a74029d0 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Mon, 3 Aug 2020 09:38:28 -0500 Subject: [PATCH 04/26] Corrected sign error for calibration to label.py --- adafruit_display_text/bitmap_label.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f741e11..1cae546 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -65,11 +65,14 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** label_position_yoffset = int( # for calibration with label.py positioning ( font.get_glyph(ord("M")).height - - text.count("\n") * font.get_bounding_box()[1] * lineSpacing + #- text.count("\n") * font.get_bounding_box()[1] * lineSpacing + - font.get_bounding_box()[1] * lineSpacing ) / 2 ) + print('M height: {}, font.get_bounding_box()[1]: {}, label_position_yoffset: {}'.format(font.get_glyph(ord("M")).height, font.get_bounding_box()[1], label_position_yoffset)) + # this empirical approach checks several glyphs for maximum ascender and descender height # Alternate option: utilize `font.get_bounding_box()` to get max glyph dimensions glyphs = "M j'" # choose glyphs with highest ascender and lowest @@ -107,8 +110,11 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** firstline = False if background_tight: if y1_min is None: - y_offset=label_position_yoffset - box_height_adder = lineSpacingY(font, lineSpacing-1) - y_offset + y_offset = label_position_yoffset + box_height_adder = ( lineSpacingY(font, lineSpacing)-lineSpacingY(font, 1) ) + y_offset + + print('box_height_adder:{}'.format(box_height_adder)) + #y_offset=label_position_yoffset #box_height_adder=-label_position_yoffset #print('label_position_yoffset: {}, lineSpacingY:{}, font[1]: {}'.format(label_position_yoffset, lineSpacingY(font, lineSpacing), font.get_bounding_box()[1])) @@ -129,6 +135,9 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** if myGlyph == None: # Error checking: no glyph found print('Glyph not found: {}'.format(repr(char))) else: + + #print('.width: {} .height: {} .dx: {} .dy: {} .shift_x: {} .shift_y: {}'.format(myGlyph.width, myGlyph.height, myGlyph.dx, myGlyph.dy, myGlyph.shift_x, myGlyph.shift_y)) + x1=base_point[0] # x1,y1 = upper left of glyph x2=x1+myGlyph.shift_x # x2,y2 = lower right of glyph if background_tight: @@ -172,7 +181,8 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** box_height=max(0, box_height+box_height_adder) # to add any additional height for leading newlines - #print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) + print('text: {}'.format(text)) + print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) return(box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset From be6747308df333cd504197471903fb38efab3678 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Mon, 3 Aug 2020 12:40:48 -0500 Subject: [PATCH 05/26] Removed debugging print statements, will do more testing to verify --- adafruit_display_text/bitmap_label.py | 134 +++++--------------------- 1 file changed, 22 insertions(+), 112 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 1cae546..f7e9ee8 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -57,10 +57,7 @@ def lineSpacingY(font, lineSpacing): returnValue = int(lineSpacing * fontHeight) return returnValue -def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** change default background_tight=False - # this is the preferred approach since it utilizes the BDF file values - #(font_width, font_height, font_xoffset, font_yoffset)=font.get_bounding_box() # max glyph dimension - +def text_bounding_box(text, font, lineSpacing, background_tight=False): # **** change default background_tight=False label_position_yoffset = int( # for calibration with label.py positioning ( @@ -71,8 +68,7 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** / 2 ) - print('M height: {}, font.get_bounding_box()[1]: {}, label_position_yoffset: {}'.format(font.get_glyph(ord("M")).height, font.get_bounding_box()[1], label_position_yoffset)) - + # this empirical approach checks several glyphs for maximum ascender and descender height # Alternate option: utilize `font.get_bounding_box()` to get max glyph dimensions glyphs = "M j'" # choose glyphs with highest ascender and lowest @@ -81,16 +77,13 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** for char in glyphs: this_glyph = font.get_glyph(ord(char)) if this_glyph: - #print('char: {}, this_glyph.height: {}, this_glyph.dy: {}'.format(char, this_glyph.height, this_glyph.dy)) ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) descender_max = max(descender_max, -this_glyph.dy) - #print('ascender_max: {}, descender_max: {}'.format(ascender_max, descender_max)) - #print('FINAL -- ascender_max: {}, descender_max: {}'.format(ascender_max, descender_max)) font_height=ascender_max+descender_max font_yoffset=ascender_max - base_point=(0,0) # entry point for the next glyph + # calculate dimensions for both "tight" and "loose" bounding boxes x1_min=y1_min=x2_max=y2_max=None # initialize the bounding box corners (1:lower left, 2: upper right) @@ -104,26 +97,18 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** for char in text: if char == '\n': # newline - #if y1_min is None: - # y1_min=font_yoffset-base_point[1] if firstline: # This the first line firstline = False if background_tight: if y1_min is None: y_offset = label_position_yoffset box_height_adder = ( lineSpacingY(font, lineSpacing)-lineSpacingY(font, 1) ) + y_offset + # for a leading newline, this adds to the box_height - print('box_height_adder:{}'.format(box_height_adder)) - - #y_offset=label_position_yoffset - #box_height_adder=-label_position_yoffset - #print('label_position_yoffset: {}, lineSpacingY:{}, font[1]: {}'.format(label_position_yoffset, lineSpacingY(font, lineSpacing), font.get_bounding_box()[1])) - # for a leading newline, this adds to the box_height else: y_offset = -y1_min # The bitmap y-offset is the max y-position of the first line else: # background is "loose" - #y_offset = font_height + font_yoffset y_offset = font_yoffset if y1_min is None: box_height_adder = lineSpacingY(font, lineSpacing) @@ -136,8 +121,6 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** print('Glyph not found: {}'.format(repr(char))) else: - #print('.width: {} .height: {} .dx: {} .dy: {} .shift_x: {} .shift_y: {}'.format(myGlyph.width, myGlyph.height, myGlyph.dx, myGlyph.dy, myGlyph.shift_x, myGlyph.shift_y)) - x1=base_point[0] # x1,y1 = upper left of glyph x2=x1+myGlyph.shift_x # x2,y2 = lower right of glyph if background_tight: @@ -176,67 +159,14 @@ def text_bounding_box2(text, font, lineSpacing, background_tight=False): # **** if background_tight: y_offset =-y1_min # The bitmap y-offset is the max y-position of the first line else: # background is "loose" - #y_offset = font_height + font_yoffset y_offset=font_yoffset box_height=max(0, box_height+box_height_adder) # to add any additional height for leading newlines - print('text: {}'.format(text)) - print('background_tight: {}, box_width: {}, box_height: {}, x_offset: {}, y_offset: {}'.format(background_tight, box_width, box_height, -x1_min, y_offset)) - return(box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset -def text_bounding_box(text, font, lineSpacing, background_tight=False): - # bounding_box - determines the bounding box size around the new text to be added. - # To be used to calculate if the new text will be printed within the bounding_box - # This function can used to determine character-wrapping or word-wrapping for a - # text terminal box, prior to actually printing the text in the bitmap. - # - # Note: Scale is not implemented at this time - - #print('bounding_box text: {}'.format(text)) - boxHeight = boxWidth = 0 - fontHeight = font.get_glyph(ord("M")).height - thisLineWidth = 0 - - for char in text: - if char == '\n': # newline - boxWidth = max(boxWidth, thisLineWidth) # check to see if the last line is wider than any others. - thisLineWidth = 0 # new line, so restart thislineWidth at 0 - boxHeight = boxHeight + _lineSpacingY(font, lineSpacing) # add a lineSpacing to the boxHeight - - else: - myGlyph = font.get_glyph(ord(char)) - if myGlyph == None: # Error checking: no glyph found - print('Glyph not found: {}'.format(repr(char))) - else: - width = myGlyph.width - height = myGlyph.height - dx = myGlyph.dx - dy = myGlyph.dy - shift_x = myGlyph.shift_x - shift_y = myGlyph.shift_y - - # Not working yet*** - # This offset is used to match the label.py function from Adafruit_Display_Text library - # y_offset = int( - # ( - # self._font.get_glyph(ord("M")).height - # - new_text.count("\n") * self.height * self.line_spacing - # ) - # / 2 ) - - # yOffset = int( (fontHeight-height*lineSpacing)/2 ) - yOffset = fontHeight - height - - thisLineWidth = thisLineWidth + shift_x - boxHeight = max(boxHeight, height - dy + yOffset) - - boxWidth = max(boxWidth, thisLineWidth) - - return (boxWidth, boxHeight) def place_text( @@ -263,7 +193,6 @@ def place_text( xStart=xPosition # starting x position (left margin) yStart=yPosition - # **** check this. if backgroundPaletteIndex != 0: # the textbackground is different from the bitmap background # draw a bounding box where the text will go @@ -279,7 +208,7 @@ def place_text( left=right=xStart top=bottom=yStart - print('##place_text xStart, yStart: {}, {}'.format(xStart, yStart)) + #print('##place_text xStart, yStart: {}, {}'.format(xStart, yStart)) for char in text: @@ -328,23 +257,19 @@ def place_text( and (yPlacement < bitmapHeight) ): + # Allows for remapping the bitmap indexes using paletteIndex for background and text. paletteIndexes=(backgroundPaletteIndex, textPaletteIndex) - - # Allows for different paletteIndex for background and text. - #thisPixelColor=paletteIndexes[myGlyph.bitmap[x+glyph_offset_x,y]] + thisPixelColor=paletteIndexes[myGlyph.bitmap[y*myGlyph.bitmap.width + x + glyph_offset_x]] - #print('myGlyph.bitmap.width,height: {},{} char: {}, myGlyph.tile_index: {}, (x,y): ({},{}), glyph_offset_x: {}, thisPixelColor: {}'.format(myGlyph.bitmap.width, myGlyph.bitmap.height, char, myGlyph.tile_index, x, y, glyph_offset_x, thisPixelColor)) + if not printOnlyPixels or thisPixelColor > 0: # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 bitmap[yPlacement*bitmapWidth + xPlacement] = thisPixelColor - #print('* pixel') elif (yPlacement > bitmapHeight): break xPosition = xPosition + shift_x - print('##place_text left: {}, top: {}, right: {}, bottom: {}'.format(left, top, right, bottom)) - return (left, top, left+right, bottom-top) # bounding_box @@ -399,26 +324,25 @@ def __init__( # Calculate the text bounding box # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations - (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box2(text, font, + (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box(text, font, self._line_spacing, background_tight=True, ) - (box_x, box_y, x_offset, y_offset) = text_bounding_box2(text, font, - self._line_spacing, - background_tight=background_tight, - ) + if background_tight: + box_x=tight_box_x + box_y=tight_box_y + x_offset=dummy_x_offset + y_offset=tight_y_offset + else: + (box_x, box_y, x_offset, y_offset) = text_bounding_box(text, font, + self._line_spacing, + background_tight=background_tight, + ) # Calculate the background size including padding box_x = box_x + padding_left + padding_right box_y = box_y + padding_top + padding_bottom - #print('box_x: {}, box_y: {}'.format(box_x, box_y)) - - # Determine the x,y offsets of the text inside the bitmap box, to be used with place_text - # **** Is this x_offset=padding_top and y_offset=padding_left - - - # Create the two-color palette self.palette = displayio.Palette(2) if background_color is not None: @@ -431,13 +355,10 @@ def __init__( # Create the bitmap and TileGrid self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) - # Place the text into the Bitmap - + # Place the text into the Bitmap text_size=place_text(self.bitmap, text, font, self._line_spacing, padding_left+x_offset, padding_top+y_offset) - - - label_position_yoffset = int( # for calibration with label.py positioning + label_position_yoffset = int( # To calibrate with label.py positioning ( font.get_glyph(ord("M")).height - text.count("\n") * font.get_bounding_box()[1] * self._line_spacing @@ -445,8 +366,6 @@ def __init__( / 2 ) - #print('label_position_yoffset: {}, text: {}'.format(label_position_yoffset, text)) - self.tilegrid = displayio.TileGrid(self.bitmap, pixel_shader=self.palette, width=1, height=1, tile_width=box_x, tile_height=box_y, @@ -454,8 +373,6 @@ def __init__( x=0, y=label_position_yoffset - y_offset, ) - #print('box_x,y: ({},{}) y: {}, label_position_yoffset: {}'.format(box_x, box_y, y, label_position_yoffset)) - print('bitmap_label bitmap width: {} height: {}, (x,y): ({},{})'.format(box_x, box_y, x, y+label_position_yoffset)) # instance the Group with super... super().__init__( # this Group will contain just one TileGrid with one contained bitmap @@ -467,7 +384,6 @@ def __init__( # **** Should scale affect the placement of anchor_position? self.bounding_box=(self.tilegrid.x, self.tilegrid.y+(y_offset-tight_y_offset), tight_box_x, tight_box_y) - #self.bounding_box = (self.tilegrid.x, self.tilegrid.y, box_x, box_y) # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. # ******** Need repair @@ -496,12 +412,8 @@ def anchored_position(self): @anchored_position.setter def anchored_position(self, new_position): - #print('in bitmap_label self.tilegrid.x,y: {},{}'.format(self.tilegrid.x, self.tilegrid.y)) - #print('in bitmap_label self.x,y: {},{}'.format(self.x, self.y)) - self._anchored_position=new_position - #print('_anchor_point: {}, _anchored_position: {}, scale: {}'.format(self._anchor_point, self._anchored_position, self.scale)) # Set anchored_position if (self._anchor_point is not None) and (self._anchored_position is not None): @@ -516,9 +428,7 @@ def anchored_position(self, new_position): ) self.x = new_x self.y = new_y - print('bitmap_label new x,y: {},{}'.format(new_x, new_y)) - #print('out bitmap_label self.tilegrid.x,y: {},{}'.format(self.tilegrid.x, self.tilegrid.y)) - print('out bitmap_label self.x,y: {},{}'.format(self.x, self.y)) + From 25ff802a7cdb866167959aaf76d7de59c628a805 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Mon, 3 Aug 2020 18:07:29 -0500 Subject: [PATCH 06/26] Corrected to snake_case, updated formatting --- adafruit_display_text/bitmap_label.py | 469 ++++++++++++++------------ 1 file changed, 257 insertions(+), 212 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index f7e9ee8..debe0e6 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -47,95 +47,109 @@ # * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register """ -#import terminalio import displayio -def lineSpacingY(font, lineSpacing): + +def line_spacing_ypixels(font, line_spacing): # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level - #fontHeight = font.get_glyph(ord('M')).height - fontHeight = font.get_bounding_box()[1] - returnValue = int(lineSpacing * fontHeight) - return returnValue + return_value = int(line_spacing * font.get_bounding_box()[1]) + return return_value -def text_bounding_box(text, font, lineSpacing, background_tight=False): # **** change default background_tight=False - label_position_yoffset = int( # for calibration with label.py positioning - ( - font.get_glyph(ord("M")).height - #- text.count("\n") * font.get_bounding_box()[1] * lineSpacing - - font.get_bounding_box()[1] * lineSpacing - ) - / 2 - ) +def text_bounding_box( + text, font, line_spacing, background_tight=False +): # **** change default background_tight=False + + label_position_yoffset = int( # for calibration with label.py positioning + (font.get_glyph(ord("M")).height - font.get_bounding_box()[1] * line_spacing) + / 2 + ) - - # this empirical approach checks several glyphs for maximum ascender and descender height - # Alternate option: utilize `font.get_bounding_box()` to get max glyph dimensions - glyphs = "M j'" # choose glyphs with highest ascender and lowest - # descender, will depend upon font used + # This empirical approach checks several glyphs for maximum ascender and descender height + # (consistent with label.py) + glyphs = "M j'" # choose glyphs with highest ascender and lowest + # descender, will depend upon font used ascender_max = descender_max = 0 for char in glyphs: this_glyph = font.get_glyph(ord(char)) if this_glyph: ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) descender_max = max(descender_max, -this_glyph.dy) - font_height=ascender_max+descender_max - font_yoffset=ascender_max + font_height = ascender_max + descender_max + font_yoffset = ascender_max - base_point=(0,0) # entry point for the next glyph + base_point = (0, 0) # entry point for the next glyph - # calculate dimensions for both "tight" and "loose" bounding boxes - x1_min=y1_min=x2_max=y2_max=None # initialize the bounding box corners (1:lower left, 2: upper right) + x1_min = ( + y1_min + ) = ( + x2_max + ) = ( + y2_max + ) = None # initialize the bounding box corners (1:lower left, 2: upper right) - y_offset=None # Provide the baseline y_offset for the bitmap + y_offset = None # Provide the baseline y_offset for the bitmap - firstline=True # handles special cases for first line + box_height = 0 + box_width = 0 + box_height_adder = 0 - box_height=0 - box_width=0 - box_height_adder=0 + firstline = True # handles special cases for first line for char in text: - if char == '\n': # newline - if firstline: # This the first line + if char == "\n": # newline + if firstline: # This the first line firstline = False if background_tight: - if y1_min is None: - y_offset = label_position_yoffset - box_height_adder = ( lineSpacingY(font, lineSpacing)-lineSpacingY(font, 1) ) + y_offset - # for a leading newline, this adds to the box_height + if ( + y1_min is None + ): # A newline was the first character of the first line + y_offset = label_position_yoffset + box_height_adder = ( + line_spacing_ypixels(font, line_spacing - 1) + y_offset + ) + # for a leading newline, this adds to the box_height else: - y_offset = -y1_min # The bitmap y-offset is the max y-position of the first line - - else: # background is "loose" + y_offset = ( + -y1_min + ) # The bitmap y-offset is the max y-position of the first line + + else: # background is "loose" y_offset = font_yoffset if y1_min is None: - box_height_adder = lineSpacingY(font, lineSpacing) + box_height_adder = line_spacing_ypixels(font, line_spacing) - base_point=(0, base_point[1] + lineSpacingY(font, lineSpacing)) # baseline point for the next glyph + base_point = ( + 0, + base_point[1] + line_spacing_ypixels(font, line_spacing), + ) # baseline point for the next glyph else: - myGlyph = font.get_glyph(ord(char)) - if myGlyph == None: # Error checking: no glyph found - print('Glyph not found: {}'.format(repr(char))) + my_glyph = font.get_glyph(ord(char)) + if my_glyph == None: # Error checking: no glyph found + print("Glyph not found: {}".format(repr(char))) else: - - x1=base_point[0] # x1,y1 = upper left of glyph - x2=x1+myGlyph.shift_x # x2,y2 = lower right of glyph + x1 = base_point[0] # x1,y1 = upper left of glyph + x2 = x1 + my_glyph.shift_x # x2,y2 = lower right of glyph if background_tight: - y1=base_point[1]-(myGlyph.height+myGlyph.dy) # Upper left corner Note: Positive Y is down - y2=y1+myGlyph.height - else: # background is "loose" - y1=base_point[1]-font_yoffset - y2=y1+font_height - base_point=(base_point[0]+myGlyph.shift_x, base_point[1]+myGlyph.shift_y) # update the next baseline point location - - # find the min bounding box size incorporating this glyph's bounding box + y1 = base_point[1] - ( + my_glyph.height + my_glyph.dy + ) # Upper left corner Note: Positive Y is down + y2 = y1 + my_glyph.height + else: # background is "loose" + y1 = base_point[1] - font_yoffset + y2 = y1 + font_height + base_point = ( + base_point[0] + my_glyph.shift_x, + base_point[1] + my_glyph.shift_y, + ) # update the next baseline point location + + # find the min bounding box size incorporating this glyph's bounding box if x1_min is not None: x1_min = min(x1, x1_min) else: - x1_min = min(0, x1) # **** + x1_min = min(0, x1) # **** if y1_min is not None: y1_min = min(y1, y1_min) else: @@ -154,152 +168,169 @@ def text_bounding_box(text, font, lineSpacing, background_tight=False): # **** if y1_min is not None and y2_max is not None: box_height = y2_max - y1_min - - if firstline: # This the first line + if firstline: # This the first line if background_tight: - y_offset =-y1_min # The bitmap y-offset is the max y-position of the first line - else: # background is "loose" - y_offset=font_yoffset - - box_height=max(0, box_height+box_height_adder) # to add any additional height for leading newlines - - return(box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset - + y_offset = ( + -y1_min + ) # The bitmap y-offset is the max y-position of the first line + else: # background is "loose" + y_offset = font_yoffset + box_height = max( + 0, box_height + box_height_adder + ) # to add any additional height for leading newlines + return (box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset def place_text( - bitmap, text, font, lineSpacing, xPosition, yPosition, - textPaletteIndex=1, - backgroundPaletteIndex=0, + bitmap, + text, + font, + line_spacing, + xposition, + yposition, + text_palette_index=1, + background_palette_index=0, scale=1, - printOnlyPixels=True, # printOnlyPixels = True: only update the bitmap where the glyph pixel - # color is > 0 this is especially useful for script fonts where glyph - # bounding boxes overlap + print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph + # pixel color is > 0. This is especially useful for script fonts where glyph + # bounding boxes overlap + # Set `print_only_pixels=False` to write all pixels ): # placeText - Writes text into a bitmap at the specified location. # # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts # - # Note: Scale is not implemented at this time + # Note: Scale is not implemented at this time, is pushed up to Group level + font_height = font.get_glyph(ord("M")).height - fontHeight = font.get_glyph(ord("M")).height + bitmap_width = bitmap.width + bitmap_height = bitmap.height - bitmapWidth = bitmap.width - bitmapHeight = bitmap.height + x_start = xposition # starting x position (left margin) + y_start = yposition - xStart=xPosition # starting x position (left margin) - yStart=yPosition - - if backgroundPaletteIndex != 0: # the textbackground is different from the bitmap background + if ( + background_palette_index != 0 + ): # the textbackground is different from the bitmap background # draw a bounding box where the text will go - (ignore, fontLineHeight)=bounding_box('M g', font, lineSpacing, scale) # check height with ascender and descender. - (boxX, boxY) = bounding_box(text, font, lineSpacing, scale) - boxY=max(fontLineHeight, boxY) + (ignore, font_line_height) = bounding_box( + "M g", font, line_spacing, scale + ) # check height with ascender and descender. + (box_x, box_y) = bounding_box(text, font, line_spacing, scale) + box_y = max(font_line_height, box_y) + + for y in range(box_y): + for x in range(box_x): + if (xposition + x < bitmap_width) and ( + yposition + y < bitmap_height + ): # check boundaries + bitmap[ + (yposition + y) * bitmap_width + (xposition + x) + ] = background_palette_index - for y in range(boxY): - for x in range(boxX): - if (xPosition+x < bitmapWidth) and (yPosition+y < bitmapHeight): # check boundaries - #bitmap[xPosition+x, yPosition+y]=backgroundPaletteIndex - bitmap[(yPosition+y)*bitmapWidth + (xPosition + x)]=backgroundPaletteIndex + left = right = x_start + top = bottom = y_start - left=right=xStart - top=bottom=yStart - #print('##place_text xStart, yStart: {}, {}'.format(xStart, yStart)) - for char in text: - if char == '\n': # newline - xPosition = xStart # reset to left column - yPosition = yPosition + lineSpacingY(font, lineSpacing) # Add a newline + if char == "\n": # newline + xposition = x_start # reset to left column + yposition = yposition + line_spacing_ypixels( + font, line_spacing + ) # Add a newline else: - myGlyph = font.get_glyph(ord(char)) + my_glyph = font.get_glyph(ord(char)) - if myGlyph == None: # Error checking: no glyph found - print('Glyph not found: {}'.format(repr(char))) + if my_glyph == None: # Error checking: no glyph found + print("Glyph not found: {}".format(repr(char))) else: - right = max(right, xPosition + myGlyph.shift_x) - if yPosition == yStart: # first line, find the Ascender height - top = min(top, -myGlyph.height - myGlyph.dy) - bottom = max(bottom, yPosition - myGlyph.dy) - - width = myGlyph.width - height = myGlyph.height - # print('glyph width: {}, height: {}'.format(width, height)) - dx = myGlyph.dx - dy = myGlyph.dy - shift_x = myGlyph.shift_x - shift_y = myGlyph.shift_x - glyph_offset_x = myGlyph.tile_index * width # for type BuiltinFont, this creates the x-offset in the glyph bitmap. - # for BDF loaded fonts, this should equal 0 - - yOffset = fontHeight - height + right = max(right, xposition + my_glyph.shift_x) + if yposition == y_start: # first line, find the Ascender height + top = min(top, -my_glyph.height - my_glyph.dy) + bottom = max(bottom, yposition - my_glyph.dy) + + width = my_glyph.width + height = my_glyph.height + dx = my_glyph.dx + dy = my_glyph.dy + shift_x = my_glyph.shift_x + shift_y = my_glyph.shift_x + glyph_offset_x = ( + my_glyph.tile_index * width + ) # for type BuiltinFont, this creates the x-offset in the glyph bitmap. + # for BDF loaded fonts, this should equal 0 + + y_offset = font_height - height for y in range(height): for x in range(width): - xPlacement = x + xPosition + dx - yPlacement = y + yPosition - height - dy #+ yOffset - - #left=min(xPlacement, left) - #right=max(xPlacement, right) - #top=min(yPlacement, top) - #bottom=max(yPlacement, bottom) + x_placement = x + xposition + dx + y_placement = y + yposition - height - dy if ( - (xPlacement >= 0) - and (yPlacement >= 0) - and (xPlacement < bitmapWidth) - and (yPlacement < bitmapHeight) + (x_placement >= 0) + and (y_placement >= 0) + and (x_placement < bitmap_width) + and (y_placement < bitmap_height) ): # Allows for remapping the bitmap indexes using paletteIndex for background and text. - paletteIndexes=(backgroundPaletteIndex, textPaletteIndex) - - thisPixelColor=paletteIndexes[myGlyph.bitmap[y*myGlyph.bitmap.width + x + glyph_offset_x]] - - if not printOnlyPixels or thisPixelColor > 0: + palette_indexes = ( + background_palette_index, + text_palette_index, + ) + + this_pixel_color = palette_indexes[ + my_glyph.bitmap[ + y * my_glyph.bitmap.width + x + glyph_offset_x + ] + ] + + if not print_only_pixels or this_pixel_color > 0: # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 - bitmap[yPlacement*bitmapWidth + xPlacement] = thisPixelColor - elif (yPlacement > bitmapHeight): + bitmap[ + y_placement * bitmap_width + x_placement + ] = this_pixel_color + elif y_placement > bitmap_height: break - - xPosition = xPosition + shift_x - return (left, top, left+right, bottom-top) # bounding_box + xposition = xposition + shift_x + return (left, top, left + right, bottom - top) # bounding_box -class Label(displayio.Group): - # Class variable - # To save memory, set Bitmap.Label._memory_saver=True, to avoid storing the text string in the class. +class Label(displayio.Group): + # Class variable + # To save memory, set Label._memory_saver=True and avoid storing the text string in the class. # If set to False, the class saves the text string for future reference. *** use getter - _memory_saver=True + _memory_saver = True def __init__( - self, - font, - x=0, - y=0, - text="", - max_glyphs=None, # This input parameter is ignored, only present for compatibility with label.py - #width, height, - color=0xFFFFFF, - background_color=None, - line_spacing=1.25, - background_tight=False, - padding_top=0, - padding_bottom=0, - padding_left=0, - padding_right=0, - anchor_point=(0,0), - anchored_position=None, - **kwargs - ): + self, + font, + x=0, + y=0, + text="", + max_glyphs=None, # This input parameter is ignored, only present for compatibility with label.py + # width, height, + color=0xFFFFFF, + background_color=None, + line_spacing=1.25, + background_tight=False, + padding_top=0, + padding_bottom=0, + padding_left=0, + padding_right=0, + anchor_point=(0, 0), + anchored_position=None, + **kwargs + ): if text == "": raise RuntimeError("Please provide text string") @@ -310,11 +341,13 @@ def __init__( else: self._scale = 1 - self._line_spacing=line_spacing + self._line_spacing = line_spacing - if self._memory_saver == False: + if self._memory_saver: # do not save the text in the instance + self._text = None + else: self._text = text # text to be displayed - + # limit padding to >= 0 *** raise an error if negative padding is requested padding_top = max(0, padding_top) padding_bottom = max(0, padding_bottom) @@ -324,41 +357,46 @@ def __init__( # Calculate the text bounding box # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations - (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box(text, font, - self._line_spacing, - background_tight=True, - ) + (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box( + text, font, self._line_spacing, background_tight=True, + ) if background_tight: - box_x=tight_box_x - box_y=tight_box_y - x_offset=dummy_x_offset - y_offset=tight_y_offset + box_x = tight_box_x + box_y = tight_box_y + x_offset = dummy_x_offset + y_offset = tight_y_offset else: - (box_x, box_y, x_offset, y_offset) = text_bounding_box(text, font, - self._line_spacing, - background_tight=background_tight, - ) + (box_x, box_y, x_offset, y_offset) = text_bounding_box( + text, font, self._line_spacing, background_tight=background_tight, + ) # Calculate the background size including padding box_x = box_x + padding_left + padding_right box_y = box_y + padding_top + padding_bottom - # Create the two-color palette + # Create the two-color palette self.palette = displayio.Palette(2) if background_color is not None: - self.palette[0] = background_color + self.palette[0] = background_color else: - self.palette[0] = 0 - self.palette.make_transparent(0) + self.palette[0] = 0 + self.palette.make_transparent(0) self.palette[1] = color # Create the bitmap and TileGrid - self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) + self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) + + # Place the text into the Bitmap + text_size = place_text( + self.bitmap, + text, + font, + self._line_spacing, + padding_left + x_offset, + padding_top + y_offset, + ) - # Place the text into the Bitmap - text_size=place_text(self.bitmap, text, font, self._line_spacing, padding_left+x_offset, padding_top+y_offset) - - label_position_yoffset = int( # To calibrate with label.py positioning + label_position_yoffset = int( # To calibrate with label.py positioning ( font.get_glyph(ord("M")).height - text.count("\n") * font.get_bounding_box()[1] * self._line_spacing @@ -366,33 +404,45 @@ def __init__( / 2 ) - self.tilegrid = displayio.TileGrid(self.bitmap, pixel_shader=self.palette, - width=1, height=1, - tile_width=box_x, tile_height=box_y, - default_tile=0, - x=0, - y=label_position_yoffset - y_offset, - ) + self.tilegrid = displayio.TileGrid( + self.bitmap, + pixel_shader=self.palette, + width=1, + height=1, + tile_width=box_x, + tile_height=box_y, + default_tile=0, + x=0, + y=label_position_yoffset - y_offset, + ) # instance the Group with super... super().__init__( # this Group will contain just one TileGrid with one contained bitmap - super().__init__(max_size=1, x=x, y=y, **kwargs) # this will include any arguments, including scale - self.append(self.tilegrid) # add the bitmap's tilegrid to the group + super().__init__( + max_size=1, x=x, y=y, **kwargs + ) # this will include any arguments, including scale + self.append(self.tilegrid) # add the bitmap's tilegrid to the group ####### ******* # Set the tileGrid position in the parent based upon anchor_point and anchor_position # **** Should scale affect the placement of anchor_position? - self.bounding_box=(self.tilegrid.x, self.tilegrid.y+(y_offset-tight_y_offset), tight_box_x, tight_box_y) - # Update bounding_box values. Note: To be consistent with label.py, - # this is the bounding box for the text only, not including the background. - # ******** Need repair + self.bounding_box = ( + self.tilegrid.x, + self.tilegrid.y + (y_offset - tight_y_offset), + tight_box_x, + tight_box_y, + ) + # Update bounding_box values. Note: To be consistent with label.py, + # this is the bounding box for the text only, not including the background. + # ******** Need repair # Create the TileGrid to hold the single Bitmap (self.bitmap) - self._anchored_position=anchored_position - self.anchor_point=anchor_point - self.anchored_position=self._anchored_position # sets anchored_position with setter after bitmap is created - + self._anchored_position = anchored_position + self.anchor_point = anchor_point + self.anchored_position = ( + self._anchored_position + ) # sets anchored_position with setter after bitmap is created @property def anchor_point(self): @@ -404,7 +454,9 @@ def anchor_point(self): @anchor_point.setter def anchor_point(self, new_anchor_point): self._anchor_point = new_anchor_point - self.anchored_position = self._anchored_position # update the anchored_position using setter + self.anchored_position = ( + self._anchored_position + ) # update the anchored_position using setter @property def anchored_position(self): @@ -413,25 +465,18 @@ def anchored_position(self): @anchored_position.setter def anchored_position(self, new_position): - self._anchored_position=new_position + self._anchored_position = new_position # Set anchored_position if (self._anchor_point is not None) and (self._anchored_position is not None): new_x = int( - new_position[0] - - self._anchor_point[0] * (self.bounding_box[2] * self._scale) - ) + new_position[0] + - self._anchor_point[0] * (self.bounding_box[2] * self._scale) + ) new_y = int( new_position[1] - (self._anchor_point[1] * self.bounding_box[3] * self.scale) + round((self.bounding_box[3] * self.scale) / 2.0) - ) + ) self.x = new_x self.y = new_y - - - - - - - From d0c7d38c56e8c5b8d69c76c093c3c79127bc9091 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Mon, 3 Aug 2020 18:56:04 -0500 Subject: [PATCH 07/26] added font and two code samples, with minor updates to bitmap_label.py --- adafruit_display_text/bitmap_label.py | 9 +- examples/{code.py => code_complex.py} | 11 +- examples/code_simpler.py | 280 ++ fonts/Helvetica-Bold-16.bdf | 4194 +++++++++++++++++++++++++ 4 files changed, 4485 insertions(+), 9 deletions(-) rename examples/{code.py => code_complex.py} (98%) create mode 100755 examples/code_simpler.py create mode 100755 fonts/Helvetica-Bold-16.bdf diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index debe0e6..9f2130a 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -104,7 +104,7 @@ def text_bounding_box( if ( y1_min is None ): # A newline was the first character of the first line - y_offset = label_position_yoffset + y_offset = 0 #label_position_yoffset box_height_adder = ( line_spacing_ypixels(font, line_spacing - 1) + y_offset ) @@ -399,7 +399,7 @@ def __init__( label_position_yoffset = int( # To calibrate with label.py positioning ( font.get_glyph(ord("M")).height - - text.count("\n") * font.get_bounding_box()[1] * self._line_spacing + - font.get_bounding_box()[1] * self._line_spacing ) / 2 ) @@ -412,8 +412,9 @@ def __init__( tile_width=box_x, tile_height=box_y, default_tile=0, - x=0, - y=label_position_yoffset - y_offset, + x=-padding_left, + #y=label_position_yoffset - y_offset - padding_left, + y= - y_offset - padding_left, ) # instance the Group with super... super().__init__( diff --git a/examples/code.py b/examples/code_complex.py similarity index 98% rename from examples/code.py rename to examples/code_complex.py index f07914b..6ac490e 100755 --- a/examples/code.py +++ b/examples/code_complex.py @@ -79,9 +79,9 @@ # Load some proportional fonts fontFiles = [ - 'fonts/Helvetica-Bold-16.bdf', +# 'fonts/Helvetica-Bold-16.bdf', # 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 -# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText + 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText ] from adafruit_bitmap_font import bitmap_font @@ -90,7 +90,7 @@ thisFont = bitmap_font.load_font(fontFile) - #thisFont=terminalio.FONT + thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts fontList.append(thisFont) fontHeight.append( thisFont.get_glyph(ord("M")).height ) @@ -107,7 +107,8 @@ print('loading glyphs...') for font in fontList: - font.load_glyphs(glyphs) + if font is not terminalio.FONT: + font.load_glyphs(glyphs) print('Glyphs are loaded.') @@ -126,7 +127,7 @@ myString12=('Bit Juice ({[]}) Monsters!\"\'ABCDEFGHIJKLMNOPQRSTUVWXYZ\npuppy bug jump ({[]})') -myString34='\nnone' +myString34=' none ' myString_bitmap_label='bitmap_label' myString_label='label bitmap_label' #myString=('Full Screen Size: This is a stationary box, not a stationery box') diff --git a/examples/code_simpler.py b/examples/code_simpler.py new file mode 100755 index 0000000..0323198 --- /dev/null +++ b/examples/code_simpler.py @@ -0,0 +1,280 @@ +# Sample code using the textMap library and the "textBox" wrapper class +# Creates four textBox instances +# Inserts each textBox into a tileGrid group +# Writes text into the box one character at a time +# Moves the position of the textBox around the display +# Clears each textBox after the full string is written (even if the text is outside of the box) + +#import textmap +#from textmap import textBox + +import board +import displayio +import time +import terminalio +import fontio +import sys +import busio +#from adafruit_st7789 import ST7789 +from adafruit_ili9341 import ILI9341 + + +# Use these two options to decide which system and font to use + +########## +use_bitmap_label=True +########## +use_builtin_font=False +########## + +my_scale=1 + +if use_bitmap_label: # use bitmap_label.py library (Bitmap) + from adafruit_display_text import bitmap_label as label + myString6='bitmap_label -->' + label6_anchor_point=(1,0.5) + label6_anchored_position=(200,200) + + version='bitmap_label.py' + +else: # use label.py library (TileGrid) + from adafruit_display_text import label as label + myString6='<-- label' + label6_anchor_point=(0,0.5) + label6_anchored_position=(50,200) + + version='label.py' + + +# Setup the SPI display + +print('Starting the display...') # goes to serial only +displayio.release_displays() + +spi = board.SPI() +tft_cs = board.D9 # arbitrary, pin not used +tft_dc = board.D10 +tft_backlight = board.D12 +tft_reset=board.D11 + +while not spi.try_lock(): + spi.configure(baudrate=32000000) + pass +spi.unlock() + +display_bus = displayio.FourWire( + spi, + command=tft_dc, + chip_select=tft_cs, + reset=tft_reset, + baudrate=32000000, + polarity=1, + phase=1, +) + +print('spi.frequency: {}'.format(spi.frequency)) + +DISPLAY_WIDTH=320 +DISPLAY_HEIGHT=240 + +#display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0) +display = ILI9341(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, rotation=180, auto_refresh=True) + +display.show(None) + +print ('Display is started') + + +# load all the fonts +print('loading fonts...') + +import terminalio + + +fontList = [] +fontHeight = [] + +##### the BuiltinFont terminalio.FONT has a different return strategy for get_glyphs and +# is currently not handled by these functions. +#fontList.append(terminalio.FONT) +#fontHeight = [10] # somehow the terminalio.FONT needs to be adjusted to 10 + +# Load some proportional fonts +fontFiles = [ + 'fonts/Helvetica-Bold-16.bdf', +# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 +# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText +# 'fonts/Fayette-HandwrittenScript-64.bdf', + ] + +from adafruit_bitmap_font import bitmap_font + +for i, fontFile in enumerate(fontFiles): + thisFont = bitmap_font.load_font(fontFile) + + if use_builtin_font: + thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts + + fontList.append(thisFont) + fontHeight.append( thisFont.get_glyph(ord("M")).height ) + + + +preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory + # preloading the glyphs will help speed up the rendering of text but will use more RAM + +if preloadTheGlyphs: + + # identify the glyphs to load into memory -> increases rendering speed + glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + + print('loading glyphs...') + for font in fontList: + if font is not terminalio.FONT: + font.load_glyphs(glyphs) + + print('Glyphs are loaded.') + + +#for char in glyphs: +# my_glyph=font.get_glyph(char) +# print('char: {}, size x,y ({},{}) offset x,y ({},{})'.format(chr(char), my_glyph.width, my_glyph.height, my_glyph.dx, my_glyph.dy)) + +print('Fonts completed loading.') + +# create group +import gc + +#tileGridList=[] # list of tileGrids +#print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) + + +myString12=('Bug Juice ({[]}) \'Monsters!\"\'\npuppy jump ({[]})') +myString34='\n none ' +myString_bitmap_label='bitmap_label' +myString_label='label bitmap_label' + + +gc.collect() +label_start_memory=gc.mem_free() +bmap_label = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=30, + line_spacing=1.25, + scale=my_scale, + ) + + +bmap_label2 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=90, + line_spacing=1.25, + scale=my_scale, + #anchored_position=(10,60), + ) +label3_padding=0 +bmap_label3 = label.Label(font=fontList[0], text=myString34, + color=0x000000, + #color=0xFF00FF, + max_glyphs=len(myString34), + background_color=0xFFFF00, + #background_color=None, + padding_bottom=label3_padding, + padding_left=label3_padding, + padding_right=label3_padding, + padding_top=label3_padding, + background_tight=False, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0,0), + anchored_position=(200,150), + ) + +bmap_label4 = label.Label(font=fontList[0], text=myString34, + color=0x000000, + #color=0xFF00FF, + max_glyphs=len(myString34), + background_color=0xFFFF00, + #background_color=None, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, + #anchored_position=(10,150), + ) + +bmap_label5 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + scale=my_scale, + #anchored_position=(10,200), + ) + + +bmap_label6 = label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + anchor_point=label6_anchor_point, + anchored_position=label6_anchored_position, + scale=my_scale, + ) + + + +gc.collect() +label_end_memory=gc.mem_free() + +bmap_group = displayio.Group( max_size=6 ) # Create a group for displaying +#bmap_group.append(bmap_label) +#bmap_group.append(bmap_label2) +#bmap_group.append(bmap_label3) +bmap_group.append(bmap_label4) +#bmap_group.append(bmap_label5) +#bmap_group.append(bmap_label6) + + +print('***') +print('{} memory used: {}'.format(version, label_start_memory-label_end_memory)) +display.auto_refresh=True + +#time.sleep(0.1) +display.show(bmap_group) + +while True: + pass + + + diff --git a/fonts/Helvetica-Bold-16.bdf b/fonts/Helvetica-Bold-16.bdf new file mode 100755 index 0000000..2a34591 --- /dev/null +++ b/fonts/Helvetica-Bold-16.bdf @@ -0,0 +1,4194 @@ +STARTFONT 2.1 +FONT -FontForge-Helvetica-Bold-R-Normal--17-160-75-75-P-93-ISO10646-1 +SIZE 16 75 75 +FONTBOUNDINGBOX 20 21 -3 -4 +COMMENT "Generated by fontforge, http://fontforge.sourceforge.net" +COMMENT "Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries." +STARTPROPERTIES 40 +FOUNDRY "FontForge" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 17 +POINT_SIZE 160 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 93 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONTNAME_REGISTRY "" +CHARSET_COLLECTIONS "ISO10646-1" +FONT_NAME "Helvetica-Bold" +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries." +FONT_VERSION "001.007" +FONT_ASCENT 14 +FONT_DESCENT 3 +UNDERLINE_POSITION -2 +UNDERLINE_THICKNESS 1 +X_HEIGHT 8 +CAP_HEIGHT 12 +RAW_ASCENT 800 +RAW_DESCENT 200 +NORM_SPACE 5 +RELATIVE_WEIGHT 70 +RELATIVE_SETWIDTH 50 +SUPERSCRIPT_X 0 +SUPERSCRIPT_Y 8 +SUPERSCRIPT_SIZE 11 +SUBSCRIPT_X 0 +SUBSCRIPT_Y 2 +SUBSCRIPT_SIZE 11 +FIGURE_WIDTH 9 +AVG_LOWERCASE_WIDTH 90 +AVG_UPPERCASE_WIDTH 113 +ENDPROPERTIES +CHARS 229 +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 13 2 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 8 0 +BBX 4 5 2 8 +BITMAP +90 +90 +90 +90 +90 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +1B00 +1B00 +1300 +7F80 +7F80 +3200 +3600 +FF80 +FF00 +2600 +2600 +2400 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 15 1 -2 +BITMAP +10 +7C +FE +D6 +D7 +D0 +F0 +7C +1E +17 +D3 +FE +7C +10 +10 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 14 12 1 0 +BITMAP +7040 +F8C0 +8C80 +8D80 +F900 +7200 +0270 +04F8 +058C +098C +18F8 +1070 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +1C00 +3E00 +7300 +7300 +3600 +3E00 +3CC0 +7EC0 +E7C0 +C780 +E380 +7FC0 +3CE0 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 4 0 +BBX 2 5 1 8 +BITMAP +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 17 1 -4 +BITMAP +30 +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 17 1 -4 +BITMAP +80 +C0 +60 +60 +60 +70 +30 +30 +30 +30 +30 +70 +60 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 5 6 1 7 +BITMAP +20 +20 +F8 +70 +D0 +10 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +18 +18 +18 +FF +FF +18 +18 +18 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 5 1 -3 +BITMAP +E0 +E0 +60 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 4 +BITMAP +F8 +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 2 1 0 +BITMAP +E0 +E0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 13 0 0 +BITMAP +18 +18 +18 +30 +30 +30 +60 +60 +60 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +3C +7E +E6 +C7 +C7 +C7 +C7 +C7 +C7 +E6 +7E +3C +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 5 12 1 0 +BITMAP +18 +18 +F8 +F8 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +3E00 +7F00 +6300 +6380 +0380 +0700 +0F00 +1C00 +3800 +7000 +7F80 +FF80 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +3E00 +7F00 +6300 +6300 +0300 +0E00 +0F00 +0380 +E380 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +0700 +0F00 +1F00 +1F00 +3700 +6700 +6700 +FF80 +FF80 +0700 +0700 +0700 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +7E +FE +C0 +C0 +FC +FE +C7 +07 +07 +C6 +FE +7C +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +3C +7E +E6 +C0 +FC +FE +C7 +C7 +C7 +C7 +7E +3C +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +FF80 +FF80 +0300 +0700 +0600 +0C00 +0C00 +1C00 +1800 +3800 +3800 +3800 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +3C +FE +C6 +C6 +E6 +7C +FE +C7 +C7 +C7 +FE +7C +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +7C +FE +C6 +C7 +C7 +C7 +FF +7F +07 +C6 +FE +78 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 8 2 0 +BITMAP +C0 +C0 +00 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 11 2 -3 +BITMAP +C0 +C0 +00 +00 +00 +00 +C0 +C0 +40 +C0 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +01 +07 +1E +F8 +C0 +F0 +3E +07 +01 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 6 1 1 +BITMAP +FF +FF +00 +00 +FF +FF +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +E0 +78 +1E +03 +0F +7C +E0 +80 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +7F +E7 +E3 +03 +07 +0E +1C +18 +00 +00 +1C +1C +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 17 0 +BBX 13 13 2 0 +BITMAP +0F80 +38E0 +6030 +4750 +CFD0 +D8D8 +D890 +D990 +DFE0 +6FC0 +7020 +3CE0 +0F80 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 13 0 0 +BITMAP +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +FF00 +FFC0 +E1C0 +E0C0 +E1C0 +FF80 +FFC0 +E1C0 +E0C0 +E0C0 +E1C0 +FFC0 +FF80 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +1F00 +7F80 +71C0 +E0C0 +E000 +C000 +C000 +C000 +E0E0 +E0C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +FF00 +FF80 +E1C0 +E0C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0C0 +E1C0 +E1C0 +FF80 +FF00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +FF80 +FF80 +E000 +E000 +E000 +FF80 +FF80 +E000 +E000 +E000 +E000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +FF80 +FF80 +E000 +E000 +E000 +FF00 +FF00 +E000 +E000 +E000 +E000 +E000 +E000 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +1F00 +3FC0 +71E0 +E0E0 +E000 +C000 +C3E0 +C3E0 +E060 +E0E0 +71E0 +3FE0 +1F60 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +E0C0 +E0C0 +E0C0 +E0C0 +E0C0 +FFC0 +FFC0 +E0C0 +E0C0 +E0C0 +E0C0 +E0C0 +E0C0 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 13 1 0 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 13 0 0 +BITMAP +03 +03 +03 +03 +03 +03 +03 +03 +E3 +E3 +67 +7F +3E +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +E1E0 +E3C0 +E780 +E700 +EE00 +FC00 +FE00 +FE00 +E700 +E380 +E3C0 +E1C0 +E0E0 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +E000 +E000 +E000 +E000 +E000 +E000 +E000 +E000 +E000 +E000 +E000 +FF80 +FF80 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 14 0 +BBX 12 13 1 0 +BITMAP +F0F0 +F0F0 +F0B0 +F8B0 +F9B0 +F9B0 +F9B0 +E930 +ED30 +EF30 +EF30 +E730 +E630 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +E0C0 +F0C0 +F0C0 +F8C0 +F8C0 +ECC0 +ECC0 +E6C0 +E6C0 +E3C0 +E3C0 +E1C0 +E1C0 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +FF00 +FF80 +E180 +E1C0 +E1C0 +E180 +FF80 +FF00 +E000 +E000 +E000 +E000 +E000 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E160 +E3E0 +71C0 +3FE0 +1F60 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +FF80 +FFC0 +E1C0 +E0C0 +E0C0 +E0C0 +E1C0 +FF80 +FF80 +E1C0 +E1C0 +E1C0 +E0C0 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +3E00 +7F00 +E380 +C180 +E000 +FC00 +7F80 +0F80 +01C0 +C1C0 +E180 +7F80 +3E00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 10 13 0 0 +BITMAP +FFC0 +FFC0 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +0C00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 11 13 0 0 +BITMAP +E0E0 +60E0 +70C0 +71C0 +31C0 +3980 +3980 +1B80 +1B00 +1F00 +0F00 +0E00 +0E00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 16 0 +BBX 16 13 0 0 +BITMAP +E187 +63C6 +73C6 +73CE +73CE +33CC +366C +3E6C +1E7C +1E78 +1E78 +1C38 +0C30 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +E1C0 +E380 +7300 +7700 +3E00 +1E00 +1C00 +3E00 +3E00 +7700 +7380 +E380 +C1C0 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +C1C0 +E180 +6380 +7300 +3700 +3E00 +1E00 +1C00 +1C00 +1C00 +1C00 +1C00 +1C00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 10 13 0 0 +BITMAP +7FC0 +7FC0 +03C0 +0380 +0700 +0E00 +0E00 +1C00 +3800 +7800 +7000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 17 1 -4 +BITMAP +F0 +F0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F0 +F0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 13 0 0 +BITMAP +C0 +C0 +C0 +C0 +60 +60 +60 +30 +30 +30 +18 +18 +18 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 17 0 -4 +BITMAP +F8 +F8 +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +F8 +F8 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 7 6 1 6 +BITMAP +18 +3C +3C +64 +66 +C2 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 1 0 -2 +BITMAP +FF80 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 3 2 0 11 +BITMAP +E0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +C000 +C000 +C000 +C000 +DE00 +FF00 +E380 +C380 +C380 +C380 +E300 +FF00 +DE00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +3C +FE +E7 +C0 +C0 +C0 +E7 +FE +3C +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +03 +03 +03 +03 +7B +FF +E7 +C3 +C3 +C3 +E7 +FF +7B +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +3E00 +7F00 +6380 +FF80 +FF80 +E000 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 13 0 0 +BITMAP +38 +38 +70 +70 +F8 +F8 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 -4 +BITMAP +3B +7F +E7 +C3 +C3 +C3 +E7 +FF +3B +03 +E3 +FF +7C +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +C0 +C0 +C0 +C0 +DE +FF +E3 +E3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 13 1 0 +BITMAP +E0 +E0 +00 +00 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 17 0 -4 +BITMAP +70 +70 +00 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +E0 +E0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 13 1 0 +BITMAP +E0 +E0 +E0 +E0 +E7 +EE +FC +F8 +FC +EC +EE +E7 +E7 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 13 1 0 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 13 9 1 0 +BITMAP +DEF0 +FFF8 +E738 +C718 +C718 +C718 +C718 +C718 +C718 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +DE +FF +E3 +E3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 -4 +BITMAP +DE00 +FF00 +E380 +C380 +C380 +C380 +E300 +FF00 +DE00 +C000 +C000 +C000 +C000 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 -4 +BITMAP +3B +FF +E7 +C3 +C3 +C3 +E7 +FF +7B +03 +03 +03 +03 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +D8 +F8 +E0 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +7C +FE +C7 +FC +7E +07 +C7 +FE +7C +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +70 +70 +F8 +F8 +70 +70 +70 +70 +70 +78 +38 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +7B +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +E180 +6380 +7300 +7300 +3700 +3600 +1E00 +1C00 +1C00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 13 9 0 0 +BITMAP +E718 +6738 +6730 +65B0 +75B0 +3DE0 +3DE0 +38E0 +18E0 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +E7 +E6 +7E +7C +38 +38 +7C +EE +C7 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 -4 +BITMAP +E180 +6380 +7300 +7300 +3700 +3600 +3E00 +1E00 +1C00 +1C00 +1C00 +7800 +7800 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7F +7F +0F +0E +1C +38 +70 +FF +FF +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 5 16 1 -3 +BITMAP +38 +38 +60 +60 +60 +60 +60 +E0 +C0 +60 +60 +60 +60 +60 +70 +38 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 5 0 +BBX 2 13 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 6 16 0 -3 +BITMAP +E0 +70 +30 +30 +30 +30 +30 +1C +1C +38 +30 +30 +30 +30 +30 +F0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 3 1 3 +BITMAP +72 +FF +8E +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 12 2 -3 +BITMAP +C0 +C0 +00 +80 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 11 1 -1 +BITMAP +04 +3C +7E +EF +D0 +D0 +D0 +F7 +FE +7C +20 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 0 +BITMAP +1E00 +7F00 +7380 +6180 +6000 +7000 +FC00 +3000 +3000 +3000 +7C80 +7F80 +4780 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 10 0 1 +BITMAP +0080 +DD80 +7F00 +7300 +6300 +6300 +7300 +7F00 +DD80 +0080 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +E180 +6380 +7300 +3300 +3E00 +FF80 +1C00 +FF80 +0C00 +0C00 +0C00 +0C00 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 5 0 +BBX 2 13 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +00 +00 +00 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 16 1 -3 +BITMAP +3C +7E +C6 +E0 +78 +7C +DE +C7 +E3 +FE +3C +0E +06 +E6 +7E +3C +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 6 2 0 11 +BITMAP +DC +DC +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 13 0 +BBX 13 13 0 0 +BITMAP +0F80 +3DE0 +6070 +CFB0 +D890 +D818 +D818 +D8D8 +CDB0 +6730 +6060 +3DC0 +0F80 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 9 0 4 +BITMAP +78 +4C +7C +CC +CC +7C +00 +00 +7C +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 7 7 1 1 +BITMAP +02 +26 +6C +C8 +CC +66 +22 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 5 1 2 +BITMAP +FF +FF +03 +03 +03 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 13 0 +BBX 13 13 0 0 +BITMAP +0F80 +3FE0 +6060 +EF30 +C990 +C998 +CF98 +CB18 +C910 +E9B0 +6060 +3DE0 +0F80 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 6 1 0 10 +BITMAP +FC +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 7 0 +BBX 5 5 1 7 +BITMAP +70 +88 +88 +98 +70 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +18 +18 +FF +FF +18 +18 +18 +FF +FF +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 6 8 0 4 +BITMAP +78 +D8 +C8 +18 +38 +70 +40 +FC +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 6 8 0 4 +BITMAP +78 +D8 +08 +38 +08 +CC +C8 +78 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 2 2 11 +BITMAP +70 +E0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 -4 +BITMAP +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +FB +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 15 0 -3 +BITMAP +7F80 +FD80 +FD80 +FD80 +FD80 +7D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 3 1 3 +BITMAP +40 +E0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 4 0 -4 +BITMAP +20 +70 +10 +F0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 8 0 4 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 6 0 +BBX 6 9 0 4 +BITMAP +78 +CC +CC +CC +CC +78 +00 +00 +7C +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 7 7 1 1 +BITMAP +80 +C8 +6C +26 +66 +CC +88 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 14 0 +BBX 13 12 0 0 +BITMAP +3060 +F040 +3080 +3180 +3100 +3300 +3230 +3450 +0CD0 +0890 +19F8 +1010 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 14 0 +BBX 13 12 0 0 +BITMAP +3060 +F040 +3080 +3180 +3100 +3370 +32D8 +34C8 +0C18 +0830 +1840 +10F8 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 14 0 +BBX 14 12 0 0 +BITMAP +7820 +4860 +0840 +38C0 +0C80 +CD18 +CB38 +7A58 +06D8 +04FC +0818 +1818 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 12 1 -3 +BITMAP +18 +18 +00 +18 +18 +38 +70 +E0 +C3 +E7 +7F +3C +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 16 0 0 +BITMAP +1C00 +0600 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 16 0 0 +BITMAP +0380 +0600 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 16 0 0 +BITMAP +0F00 +0980 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 16 0 0 +BITMAP +0E80 +1300 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 16 0 0 +BITMAP +1D80 +1D80 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 17 0 0 +BITMAP +0600 +0900 +0600 +0000 +0700 +0F00 +0F00 +0F80 +1D80 +1980 +19C0 +38C0 +3FC0 +3FE0 +70E0 +6060 +E070 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 16 13 0 0 +BITMAP +0FFF +0FFF +0DC0 +1DC0 +19C0 +19FE +39FE +31C0 +3FC0 +7FC0 +61C0 +61FF +E1FF +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 17 1 -4 +BITMAP +1F00 +7F80 +71C0 +E0C0 +E000 +C000 +C000 +C000 +E0E0 +E0C0 +71C0 +7F80 +1F00 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +3800 +1800 +0000 +FF80 +FF80 +E000 +E000 +E000 +FF80 +FF80 +E000 +E000 +E000 +E000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +0600 +0C00 +0000 +FF80 +FF80 +E000 +E000 +E000 +FF80 +FF80 +E000 +E000 +E000 +E000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +1C00 +3600 +0000 +FF80 +FF80 +E000 +E000 +E000 +FF80 +FF80 +E000 +E000 +E000 +E000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +3600 +3600 +0000 +FF80 +FF80 +E000 +E000 +E000 +FF80 +FF80 +E000 +E000 +E000 +E000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 16 0 0 +BITMAP +C0 +60 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 16 1 0 +BITMAP +70 +60 +00 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 16 0 0 +BITMAP +70 +D8 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 16 0 0 +BITMAP +D8 +D8 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 13 0 0 +BITMAP +7F80 +7FC0 +70E0 +7060 +7070 +FE70 +FE70 +7070 +7060 +70E0 +70E0 +7FC0 +7F80 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +1D00 +2600 +0000 +E0C0 +F0C0 +F0C0 +F8C0 +F8C0 +ECC0 +ECC0 +E6C0 +E6C0 +E3C0 +E3C0 +E1C0 +E1C0 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 16 1 0 +BITMAP +1C00 +0C00 +0000 +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 16 1 0 +BITMAP +0300 +0600 +0000 +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 16 1 0 +BITMAP +0E00 +1B00 +0000 +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 16 1 0 +BITMAP +1F80 +1700 +0000 +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 11 16 1 0 +BITMAP +1B00 +1B00 +0000 +1F00 +3FC0 +71C0 +E0E0 +E060 +C060 +C060 +C060 +E060 +E0E0 +71C0 +3FC0 +1F00 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +C3 +E7 +7E +3C +3C +7E +E7 +42 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 13 0 +BBX 12 13 1 0 +BITMAP +1F30 +3FE0 +71C0 +E0E0 +E160 +C260 +C460 +C860 +F060 +F0E0 +71C0 +FFC0 +9F00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +3800 +0C00 +0000 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +0700 +0C00 +0000 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +1E00 +1300 +0000 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +3B00 +3B00 +0000 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +E1C0 +71C0 +7F80 +1F00 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +0600 +0C00 +0000 +C1C0 +E180 +6380 +7300 +3700 +3E00 +1E00 +1C00 +1C00 +1C00 +1C00 +1C00 +1C00 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 13 1 0 +BITMAP +E000 +E000 +FF00 +FF80 +E180 +E1C0 +E1C0 +E180 +FF80 +FF00 +E000 +E000 +E000 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +3E00 +7F00 +E700 +E300 +E700 +EE00 +EF00 +E380 +E380 +E380 +E380 +EF00 +EE00 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +3800 +1800 +0000 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +0600 +0C00 +0000 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +1E00 +3600 +0000 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 0 +BITMAP +3B00 +2E00 +0000 +0000 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 0 +BITMAP +3600 +3600 +0000 +0000 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 0 +BITMAP +0C00 +1200 +1200 +0C00 +3E00 +7F00 +6300 +0300 +3F00 +6300 +E300 +7F00 +7B80 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 15 9 0 0 +BITMAP +3EF8 +7FFC +638C +0FFE +7FFE +6300 +E38C +7FFC +3CF8 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 13 1 -4 +BITMAP +3C +FE +E7 +C0 +C0 +C0 +E7 +FE +3C +10 +38 +08 +78 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +3800 +1800 +0000 +3E00 +7F00 +6380 +FF80 +FF80 +E000 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +0600 +0C00 +0000 +3E00 +7F00 +6380 +FF80 +FF80 +E000 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 12 0 0 +BITMAP +1E00 +3600 +0000 +3E00 +7F00 +6380 +FF80 +FF80 +E000 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 13 0 0 +BITMAP +3600 +3600 +0000 +0000 +3E00 +7F00 +6380 +FF80 +FF80 +E000 +6380 +7F00 +3E00 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 12 0 0 +BITMAP +C0 +60 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 12 1 0 +BITMAP +70 +60 +00 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 12 0 0 +BITMAP +70 +D8 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 13 0 0 +BITMAP +D8 +D8 +00 +00 +70 +70 +70 +70 +70 +70 +70 +70 +70 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +1A00 +3E00 +3E00 +2700 +3B00 +7F00 +E380 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3A +7E +00 +00 +DE +FF +E3 +E3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 12 1 0 +BITMAP +7000 +1800 +0000 +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 12 1 0 +BITMAP +0E00 +0800 +0000 +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 12 1 0 +BITMAP +3C00 +2600 +0000 +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +3A00 +7E00 +0000 +0000 +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 1 0 +BITMAP +7600 +7600 +0000 +0000 +3C00 +7F00 +E300 +C380 +C380 +C380 +E300 +7F00 +3C00 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 10 1 -1 +BITMAP +18 +38 +18 +00 +FF +FF +00 +18 +38 +18 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +3C80 +7F00 +E300 +C780 +CB80 +D380 +E300 +FF00 +BC00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +70 +18 +00 +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +7B +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +0E +08 +00 +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +7B +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +3C +26 +00 +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +7B +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +76 +76 +00 +00 +E3 +E3 +E3 +E3 +E3 +E3 +E7 +FF +7B +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 16 0 -4 +BITMAP +0600 +0C00 +0000 +E180 +6380 +7300 +7300 +3700 +3600 +3E00 +1E00 +1C00 +1C00 +1C00 +7800 +7800 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 17 1 -4 +BITMAP +C000 +C000 +C000 +C000 +DE00 +FF00 +E380 +C380 +C380 +C380 +E300 +FF00 +DE00 +C000 +C000 +C000 +C000 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 17 0 -4 +BITMAP +3600 +3600 +0000 +0000 +E180 +6380 +7300 +7300 +3700 +3600 +3E00 +1E00 +1C00 +1C00 +1C00 +7800 +7800 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 9 1 0 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 10 13 0 0 +BITMAP +7000 +7000 +7000 +7000 +7400 +7C00 +7000 +F000 +7000 +7000 +7000 +7FC0 +7FC0 +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 13 0 0 +BITMAP +70 +70 +70 +70 +78 +78 +70 +F0 +F0 +70 +70 +70 +70 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 15 13 1 0 +BITMAP +3FFE +7FFE +F1C0 +E1C0 +C1C0 +C1FE +C1FE +C1C0 +C1C0 +E1C0 +F3C0 +7FFE +1FFE +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 944 0 +DWIDTH 16 0 +BBX 15 9 1 0 +BITMAP +3CF0 +7FFC +E38C +C3FC +C3FE +C300 +E38C +7FFC +3CF8 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +3600 +1C00 +0000 +3E00 +7F00 +E380 +C180 +E000 +FC00 +7F80 +0F80 +01C0 +C1C0 +E180 +7F80 +3E00 +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +6C +38 +00 +7C +FE +C7 +FC +7E +07 +C7 +FE +7C +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 667 0 +DWIDTH 11 0 +BBX 10 16 1 0 +BITMAP +3600 +3600 +0000 +C1C0 +E180 +6380 +7300 +3700 +3E00 +1E00 +1C00 +1C00 +1C00 +1C00 +1C00 +1C00 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 10 16 0 0 +BITMAP +1B00 +0E00 +0000 +7FC0 +7FC0 +03C0 +0380 +0700 +0E00 +0E00 +1C00 +3800 +7800 +7000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 8 12 0 0 +BITMAP +36 +1C +00 +7F +7F +0F +0E +1C +38 +70 +FF +FF +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 17 0 -4 +BITMAP +0780 +0F80 +0C00 +0C00 +7F00 +7F00 +1C00 +1C00 +1800 +1800 +1800 +1800 +3800 +3800 +3000 +F000 +E000 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 11 +BITMAP +70 +F8 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 11 +BITMAP +C8 +78 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 10 +BITMAP +C8 +78 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 2 2 11 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 3 1 10 +BITMAP +60 +90 +60 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 4 1 -4 +BITMAP +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 6 2 0 11 +BITMAP +64 +B8 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 7 2 1 11 +BITMAP +EE +CC +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 9 2 0 4 +BITMAP +FF80 +FF80 +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 17 2 0 4 +BITMAP +FFFF80 +FFFF80 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 5 1 8 +BITMAP +60 +C0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 5 1 8 +BITMAP +E0 +E0 +40 +40 +80 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 4 1 -2 +BITMAP +E0 +E0 +40 +40 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 6 5 1 8 +BITMAP +44 +88 +CC +CC +CC +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 6 5 1 8 +BITMAP +CC +CC +44 +44 +88 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 6 5 1 -3 +BITMAP +CC +CC +44 +C4 +08 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 15 1 -2 +BITMAP +18 +18 +18 +18 +FF +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 556 0 +DWIDTH 9 0 +BBX 8 16 1 -3 +BITMAP +18 +18 +18 +18 +FF +FF +18 +18 +18 +18 +FF +FF +18 +18 +18 +18 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 350 0 +DWIDTH 6 0 +BBX 6 6 0 3 +BITMAP +78 +F8 +FC +FC +78 +30 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 13 2 2 0 +BITMAP +C718 +C718 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 17 12 0 0 +BITMAP +708000 +F90000 +C90000 +CA0000 +FA0000 +340000 +0D8600 +0BCF80 +1E6980 +166980 +23EF80 +21C700 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 3 6 1 1 +BITMAP +20 +60 +C0 +C0 +60 +20 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 3 6 1 1 +BITMAP +C0 +E0 +20 +20 +E0 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 167 0 +DWIDTH 3 0 +BBX 8 12 -3 0 +BITMAP +01 +03 +02 +06 +04 +08 +18 +10 +30 +20 +40 +C0 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 1000 0 +DWIDTH 17 0 +BBX 15 7 1 6 +BITMAP +FDCE +31CE +31CE +31FE +31FE +31B6 +31B6 +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 584 0 +DWIDTH 10 0 +BBX 8 2 1 3 +BITMAP +FF +FF +ENDCHAR +STARTCHAR fi +ENCODING 64257 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 0 0 +BITMAP +3980 +3980 +7000 +7000 +F980 +F980 +7180 +7180 +7180 +7180 +7180 +7180 +7180 +ENDCHAR +STARTCHAR fl +ENCODING 64258 +SWIDTH 611 0 +DWIDTH 10 0 +BBX 9 13 0 0 +BITMAP +3980 +3980 +7180 +7180 +F980 +F980 +7180 +7180 +7180 +7180 +7180 +7180 +7180 +ENDCHAR +STARTCHAR .notdef +ENCODING -1 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +ENDFONT From ace3e7891f95b5ebfe8c9b188561fdd128b77eb9 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Tue, 4 Aug 2020 14:07:42 -0500 Subject: [PATCH 08/26] Cleaned up the text_bounding_box function to be similar to label.py --- adafruit_display_text/bitmap_label.py | 198 +++++++++++--------------- 1 file changed, 81 insertions(+), 117 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 9f2130a..2c8a1aa 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -78,109 +78,83 @@ def text_bounding_box( font_height = ascender_max + descender_max font_yoffset = ascender_max - base_point = (0, 0) # entry point for the next glyph - x1_min = ( - y1_min - ) = ( - x2_max - ) = ( - y2_max - ) = None # initialize the bounding box corners (1:lower left, 2: upper right) + lines = 1 - y_offset = None # Provide the baseline y_offset for the bitmap + font_height = font.get_glyph(ord("M")).height + + + xposition = x_start = 0 # starting x position (left margin) + yposition = y_start = 0 + + left = right = x_start + top = bottom = y_start - box_height = 0 - box_width = 0 - box_height_adder = 0 - firstline = True # handles special cases for first line + y_offset_tight = int(( font.get_glyph(ord("M")).height - text.count("\n") *line_spacing_ypixels(font, line_spacing) + ) + / 2) + # this needs to be reviewed (also in label.py), since it doesn't respond + # properly to the number of newlines. + + newline=False for char in text: + if char == "\n": # newline - if firstline: # This the first line - firstline = False - if background_tight: - if ( - y1_min is None - ): # A newline was the first character of the first line - y_offset = 0 #label_position_yoffset - box_height_adder = ( - line_spacing_ypixels(font, line_spacing - 1) + y_offset - ) - # for a leading newline, this adds to the box_height - - else: - y_offset = ( - -y1_min - ) # The bitmap y-offset is the max y-position of the first line - - else: # background is "loose" - y_offset = font_yoffset - if y1_min is None: - box_height_adder = line_spacing_ypixels(font, line_spacing) - - base_point = ( - 0, - base_point[1] + line_spacing_ypixels(font, line_spacing), - ) # baseline point for the next glyph + newline=True else: + my_glyph = font.get_glyph(ord(char)) + if my_glyph == None: # Error checking: no glyph found print("Glyph not found: {}".format(repr(char))) else: - x1 = base_point[0] # x1,y1 = upper left of glyph - x2 = x1 + my_glyph.shift_x # x2,y2 = lower right of glyph - if background_tight: - y1 = base_point[1] - ( - my_glyph.height + my_glyph.dy - ) # Upper left corner Note: Positive Y is down - y2 = y1 + my_glyph.height - else: # background is "loose" - y1 = base_point[1] - font_yoffset - y2 = y1 + font_height - base_point = ( - base_point[0] + my_glyph.shift_x, - base_point[1] + my_glyph.shift_y, - ) # update the next baseline point location - - # find the min bounding box size incorporating this glyph's bounding box - if x1_min is not None: - x1_min = min(x1, x1_min) - else: - x1_min = min(0, x1) # **** - if y1_min is not None: - y1_min = min(y1, y1_min) - else: - y1_min = y1 - if x2_max is not None: - x2_max = max(x2, x2_max) - else: - x2_max = x2 - if y2_max is not None: - y2_max = max(y2, y2_max) - else: - y2_max = y2 - - if x1_min is not None and x2_max is not None: - box_width = max(0, x2_max - x1_min) - if y1_min is not None and y2_max is not None: - box_height = y2_max - y1_min - - if firstline: # This the first line - if background_tight: - y_offset = ( - -y1_min - ) # The bitmap y-offset is the max y-position of the first line - else: # background is "loose" - y_offset = font_yoffset - - box_height = max( - 0, box_height + box_height_adder - ) # to add any additional height for leading newlines - - return (box_width, box_height, -x1_min, y_offset) # -x1_min is the x_offset + if newline: + newline=False + xposition = x_start # reset to left column + yposition = yposition + line_spacing_ypixels( + font, line_spacing + ) # Add a newline + lines += 1 + xposition += my_glyph.shift_x + right = max(right, xposition) + + if yposition == y_start: # first line, find the Ascender height + top = min(top, - my_glyph.height - my_glyph.dy + y_offset_tight) + bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight) + + # width = my_glyph.width + # height = my_glyph.height + # dx = my_glyph.dx + # dy = my_glyph.dy + # shift_x = my_glyph.shift_x + # shift_y = my_glyph.shift_x + + + loose_height= (lines - 1) * line_spacing_ypixels(font, line_spacing) + (ascender_max + descender_max) + + + + label_calibration_offset=int(( font.get_glyph(ord("M")).height - text.count("\n") *line_spacing_ypixels(font, line_spacing) + ) + / 2) + + y_offset_tight = -top +label_calibration_offset # + + + + final_box_width=right-left + if background_tight: + final_box_height=bottom-top + final_y_offset=y_offset_tight + + else: + final_box_height=loose_height + final_y_offset=ascender_max + + return (final_box_width, final_box_height, 0, final_y_offset) # -x1_min is the x_offset def place_text( @@ -212,26 +186,6 @@ def place_text( x_start = xposition # starting x position (left margin) y_start = yposition - if ( - background_palette_index != 0 - ): # the textbackground is different from the bitmap background - # draw a bounding box where the text will go - - (ignore, font_line_height) = bounding_box( - "M g", font, line_spacing, scale - ) # check height with ascender and descender. - (box_x, box_y) = bounding_box(text, font, line_spacing, scale) - box_y = max(font_line_height, box_y) - - for y in range(box_y): - for x in range(box_x): - if (xposition + x < bitmap_width) and ( - yposition + y < bitmap_height - ): # check boundaries - bitmap[ - (yposition + y) * bitmap_width + (xposition + x) - ] = background_palette_index - left = right = x_start top = bottom = y_start @@ -302,7 +256,7 @@ def place_text( xposition = xposition + shift_x - return (left, top, left + right, bottom - top) # bounding_box + return (left, top, right-left, bottom - top) # bounding_box class Label(displayio.Group): @@ -357,15 +311,15 @@ def __init__( # Calculate the text bounding box # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations - (tight_box_x, tight_box_y, dummy_x_offset, tight_y_offset) = text_bounding_box( + (tight_box_x, tight_box_y, x_offset, tight_y_offset) = text_bounding_box( text, font, self._line_spacing, background_tight=True, ) if background_tight: box_x = tight_box_x box_y = tight_box_y - x_offset = dummy_x_offset y_offset = tight_y_offset + else: (box_x, box_y, x_offset, y_offset) = text_bounding_box( text, font, self._line_spacing, background_tight=background_tight, @@ -399,7 +353,7 @@ def __init__( label_position_yoffset = int( # To calibrate with label.py positioning ( font.get_glyph(ord("M")).height - - font.get_bounding_box()[1] * self._line_spacing + - text.count("\n") * font.get_bounding_box()[1] * self._line_spacing ) / 2 ) @@ -413,8 +367,7 @@ def __init__( tile_height=box_y, default_tile=0, x=-padding_left, - #y=label_position_yoffset - y_offset - padding_left, - y= - y_offset - padding_left, + y= label_position_yoffset - y_offset - padding_top, ) # instance the Group with super... super().__init__( @@ -430,10 +383,21 @@ def __init__( self.bounding_box = ( self.tilegrid.x, - self.tilegrid.y + (y_offset - tight_y_offset), + #self.tilegrid.y + (y_offset - tight_y_offset), + self.tilegrid.y, #+ (y_offset - tight_y_offset), tight_box_x, tight_box_y, ) + + # self.bounding_box = ( + # self.tilegrid.x, + # self.tilegrid.y + (y_offset), + # tight_box_x, + # tight_box_y, + # ) + + + # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. # ******** Need repair From accdb870562b01c77d8acec27afa33a367ce8884 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Wed, 5 Aug 2020 13:29:58 -0500 Subject: [PATCH 09/26] Added simpletest, with time measurement --- examples/code_complex.py | 409 ------------------ examples/code_simpler.py | 280 ------------ ...y_text_label_vs_bitmap_label_simpletest.py | 182 ++++++++ 3 files changed, 182 insertions(+), 689 deletions(-) delete mode 100755 examples/code_complex.py delete mode 100755 examples/code_simpler.py create mode 100755 examples/display_text_label_vs_bitmap_label_simpletest.py diff --git a/examples/code_complex.py b/examples/code_complex.py deleted file mode 100755 index 6ac490e..0000000 --- a/examples/code_complex.py +++ /dev/null @@ -1,409 +0,0 @@ -# Sample code using the textMap library and the "textBox" wrapper class -# Creates four textBox instances -# Inserts each textBox into a tileGrid group -# Writes text into the box one character at a time -# Moves the position of the textBox around the display -# Clears each textBox after the full string is written (even if the text is outside of the box) - -#import textmap -#from textmap import textBox - -import board -import displayio -import time -import terminalio -import fontio -import sys -import busio -#from adafruit_st7789 import ST7789 -from adafruit_ili9341 import ILI9341 - -from adafruit_display_text import bitmap_label -#from adafruit_display_text import bitmap_label as Label - -from adafruit_display_text import label - -# Setup the SPI display - -print('Starting the display...') # goes to serial only -displayio.release_displays() - - -spi = board.SPI() -tft_cs = board.D9 # arbitrary, pin not used -tft_dc = board.D10 -tft_backlight = board.D12 -tft_reset=board.D11 - -while not spi.try_lock(): - spi.configure(baudrate=32000000) - pass -spi.unlock() - -display_bus = displayio.FourWire( - spi, - command=tft_dc, - chip_select=tft_cs, - reset=tft_reset, - baudrate=32000000, - polarity=1, - phase=1, -) - -print('spi.frequency: {}'.format(spi.frequency)) - -DISPLAY_WIDTH=320 -DISPLAY_HEIGHT=240 - -#display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0) -display = ILI9341(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, rotation=180, auto_refresh=True) - -display.show(None) - -print ('Display is started') - - -# load all the fonts -print('loading fonts...') - -import terminalio - - -fontList = [] -fontHeight = [] - -##### the BuiltinFont terminalio.FONT has a different return strategy for get_glyphs and -# is currently not handled by these functions. -#fontList.append(terminalio.FONT) -#fontHeight = [10] # somehow the terminalio.FONT needs to be adjusted to 10 - -# Load some proportional fonts -fontFiles = [ -# 'fonts/Helvetica-Bold-16.bdf', -# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 - 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText - ] - -from adafruit_bitmap_font import bitmap_font - -for i, fontFile in enumerate(fontFiles): - thisFont = bitmap_font.load_font(fontFile) - - - thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts - - fontList.append(thisFont) - fontHeight.append( thisFont.get_glyph(ord("M")).height ) - - - -preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory - # preloading the glyphs will help speed up the rendering of text but will use more RAM - -if preloadTheGlyphs: - - # identify the glyphs to load into memory -> increases rendering speed - glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' - - print('loading glyphs...') - for font in fontList: - if font is not terminalio.FONT: - font.load_glyphs(glyphs) - - print('Glyphs are loaded.') - - -#for char in glyphs: -# my_glyph=font.get_glyph(char) -# print('char: {}, size x,y ({},{}) offset x,y ({},{})'.format(chr(char), my_glyph.width, my_glyph.height, my_glyph.dx, my_glyph.dy)) - -print('Fonts completed loading.') - -# create group -import gc - -#tileGridList=[] # list of tileGrids -#print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) - - -myString12=('Bit Juice ({[]}) Monsters!\"\'ABCDEFGHIJKLMNOPQRSTUVWXYZ\npuppy bug jump ({[]})') -myString34=' none ' -myString_bitmap_label='bitmap_label' -myString_label='label bitmap_label' -#myString=('Full Screen Size: This is a stationary box, not a stationery box') -#myString=('Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box. Full Screen Size: This is a stationary box, not a stationery box.') -#myString=('MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM') -#print('myString: {}'.format(myString)) -#print('string length: {}'.format(len(myString))) - -gc.collect() -bitmap_label_start=gc.mem_free() -bmap_label = bitmap_label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=10, - line_spacing=1.25, - #anchored_position=(10,10), - ) - -#print("***bmap_label[0] (x,y): ({},{})".format(bmap_label[0].x, bmap_label[0].y)) -# -bmap_label2 = bitmap_label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=60, - line_spacing=1.25, - #anchored_position=(10,60), - ) -label3_padding=0 -bmap_label3 = bitmap_label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), - background_color=0xFFFF00, - padding_bottom=label3_padding, - padding_left=label3_padding, - padding_right=label3_padding, - padding_top=label3_padding, - background_tight=False, - x=10, - y=100, - line_spacing=1.25, - #anchored_position=(10,100), - ) - -bmap_label4 = bitmap_label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - #anchored_position=(10,150), - ) -#bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString_bitmap_label, color=0x000000, max_glyphs=len(myString_bitmap_label), -bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - #anchored_position=(10,200), - ) - -myString6='bitmap_label -->' -bmap_label6 = bitmap_label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - anchor_point=(1,0.5), - anchored_position=(200,200), - ) - - - -gc.collect() -bitmap_label_end=gc.mem_free() - -bmap_group = displayio.Group( max_size=6 ) # Create a group for displaying -bmap_group.append(bmap_label) -bmap_group.append(bmap_label2) -bmap_group.append(bmap_label3) -bmap_group.append(bmap_label4) -bmap_group.append(bmap_label5) -bmap_group.append(bmap_label6) - - - -gc.collect() -label_start=gc.mem_free() - -label1 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=10, - line_spacing=1.25, - #anchored_position=(10,10), - ) - -#print('label1 bounding_box: {}'.format(label1.bounding_box)) -#print('label1[0].width: {}, height: {}, x,y: ({},{})'.format(label1[0].tile_width, label1[0].tile_height, label1[0].x, label1[0].y)) - -#print("***label1[0] (x,y): ({},{})".format(label1[0].x, label1[0].y)) -#print("***label1 (x,y): ({},{})".format(label1.x, label1.y)) - - -label2 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=60, - line_spacing=1.25, - #anchored_position=(10,60), - ) - -label3 = label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), - background_color=0xFFFF00, - padding_bottom=label3_padding, - padding_left=label3_padding, - padding_right=label3_padding, - padding_top=label3_padding, - background_tight=False, - x=10, - y=100, - line_spacing=1.25, - #anchored_position=(10,100), - ) - -label4 = label.Label(font=fontList[0], text=myString34, color=0x000000, max_glyphs=len(myString34), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - #anchored_position=(10,150), - ) - -label5 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - #anchored_position=(10,200), - ) - - -myString6 = '<-- label' -label6 = label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - anchor_point=(0,0.5), - anchored_position=(50,200), - ) - -gc.collect() -label_end=gc.mem_free() - -label_group = displayio.Group( max_size=6 ) # Create a group for displaying -label_group.append(label1) -label_group.append(label2) -label_group.append(label3) -label_group.append(label4) -label_group.append(label5) -label_group.append(label6) - - - -print('bitmap_label mem usage: {}, label mem usage: {}'.format(bitmap_label_start-bitmap_label_end, label_start-label_end)) - - -gc.collect() -memBeforeLoop=gc.mem_free() -print('After display.show(myGroup), just before loop start Memory free: {}'.format(memBeforeLoop) ) - -print('bmap_label bounding_box: {}'.format(bmap_label.bounding_box)) -print('label1 bounding_box: {}'.format(label1.bounding_box)) -print('bmap_label2 bounding_box: {}'.format(bmap_label2.bounding_box)) -print('label2 bounding_box: {}'.format(label2.bounding_box)) - - -print('***') -print('bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) -print('bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) -print('label3 bounding_box: {}'.format(label3.bounding_box)) -print('label3 x,y: {},{}'.format(label3.x, label3.y)) -print('***') - - -print('bmap_label4 bounding_box: {}'.format(bmap_label4.bounding_box)) -print('label4 bounding_box: {}'.format(label4.bounding_box)) -print('bmap_label5 bounding_box: {}'.format(bmap_label5.bounding_box)) -print('label5 bounding_box: {}'.format(label5.bounding_box)) - -print('**************') -print('before ** bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) -print('1 - bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) #### how is this changing it? -print('before ** bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) -bmap_label3.anchor_point=(0,0) -bmap_label3.anchored_position=(200,150) - -label3.anchor_point=(0,0) -label3.anchored_position=(200,150) - - -print('***') -print('bmap_label3 bounding_box: {}'.format(bmap_label3.bounding_box)) -print('bmap_label3 x,y: {},{}'.format(bmap_label3.x, bmap_label3.y)) -print('bmap_label3 tilegrid.x,y: {},{}'.format(bmap_label3.tilegrid.x, bmap_label3.tilegrid.y)) -print('bmap_label3[0].x,y: {},{}'.format(bmap_label3[0].x, bmap_label3[0].y)) -print('****') -print('label3 bounding_box: {}'.format(label3.bounding_box)) -print('label3 x,y: {},{}'.format(label3.x, label3.y)) -print('label3 tilegrid.x,y: {},{}'.format(label3[1].x, label3[1].y)) - -print('***') - -display.auto_refresh=True - -while True: - print('bitmap_label') - time.sleep(0.1) - display.show(bmap_group) - - time.sleep(2) - - print('label') - time.sleep(0.1) - display.show(label_group) - time.sleep(2) - - - - - - diff --git a/examples/code_simpler.py b/examples/code_simpler.py deleted file mode 100755 index 0323198..0000000 --- a/examples/code_simpler.py +++ /dev/null @@ -1,280 +0,0 @@ -# Sample code using the textMap library and the "textBox" wrapper class -# Creates four textBox instances -# Inserts each textBox into a tileGrid group -# Writes text into the box one character at a time -# Moves the position of the textBox around the display -# Clears each textBox after the full string is written (even if the text is outside of the box) - -#import textmap -#from textmap import textBox - -import board -import displayio -import time -import terminalio -import fontio -import sys -import busio -#from adafruit_st7789 import ST7789 -from adafruit_ili9341 import ILI9341 - - -# Use these two options to decide which system and font to use - -########## -use_bitmap_label=True -########## -use_builtin_font=False -########## - -my_scale=1 - -if use_bitmap_label: # use bitmap_label.py library (Bitmap) - from adafruit_display_text import bitmap_label as label - myString6='bitmap_label -->' - label6_anchor_point=(1,0.5) - label6_anchored_position=(200,200) - - version='bitmap_label.py' - -else: # use label.py library (TileGrid) - from adafruit_display_text import label as label - myString6='<-- label' - label6_anchor_point=(0,0.5) - label6_anchored_position=(50,200) - - version='label.py' - - -# Setup the SPI display - -print('Starting the display...') # goes to serial only -displayio.release_displays() - -spi = board.SPI() -tft_cs = board.D9 # arbitrary, pin not used -tft_dc = board.D10 -tft_backlight = board.D12 -tft_reset=board.D11 - -while not spi.try_lock(): - spi.configure(baudrate=32000000) - pass -spi.unlock() - -display_bus = displayio.FourWire( - spi, - command=tft_dc, - chip_select=tft_cs, - reset=tft_reset, - baudrate=32000000, - polarity=1, - phase=1, -) - -print('spi.frequency: {}'.format(spi.frequency)) - -DISPLAY_WIDTH=320 -DISPLAY_HEIGHT=240 - -#display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0) -display = ILI9341(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, rotation=180, auto_refresh=True) - -display.show(None) - -print ('Display is started') - - -# load all the fonts -print('loading fonts...') - -import terminalio - - -fontList = [] -fontHeight = [] - -##### the BuiltinFont terminalio.FONT has a different return strategy for get_glyphs and -# is currently not handled by these functions. -#fontList.append(terminalio.FONT) -#fontHeight = [10] # somehow the terminalio.FONT needs to be adjusted to 10 - -# Load some proportional fonts -fontFiles = [ - 'fonts/Helvetica-Bold-16.bdf', -# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 -# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText -# 'fonts/Fayette-HandwrittenScript-64.bdf', - ] - -from adafruit_bitmap_font import bitmap_font - -for i, fontFile in enumerate(fontFiles): - thisFont = bitmap_font.load_font(fontFile) - - if use_builtin_font: - thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts - - fontList.append(thisFont) - fontHeight.append( thisFont.get_glyph(ord("M")).height ) - - - -preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory - # preloading the glyphs will help speed up the rendering of text but will use more RAM - -if preloadTheGlyphs: - - # identify the glyphs to load into memory -> increases rendering speed - glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' - - print('loading glyphs...') - for font in fontList: - if font is not terminalio.FONT: - font.load_glyphs(glyphs) - - print('Glyphs are loaded.') - - -#for char in glyphs: -# my_glyph=font.get_glyph(char) -# print('char: {}, size x,y ({},{}) offset x,y ({},{})'.format(chr(char), my_glyph.width, my_glyph.height, my_glyph.dx, my_glyph.dy)) - -print('Fonts completed loading.') - -# create group -import gc - -#tileGridList=[] # list of tileGrids -#print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) - - -myString12=('Bug Juice ({[]}) \'Monsters!\"\'\npuppy jump ({[]})') -myString34='\n none ' -myString_bitmap_label='bitmap_label' -myString_label='label bitmap_label' - - -gc.collect() -label_start_memory=gc.mem_free() -bmap_label = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=30, - line_spacing=1.25, - scale=my_scale, - ) - - -bmap_label2 = label.Label(font=fontList[0], text=myString12, color=0xFFFFFF, max_glyphs=len(myString12), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=90, - line_spacing=1.25, - scale=my_scale, - #anchored_position=(10,60), - ) -label3_padding=0 -bmap_label3 = label.Label(font=fontList[0], text=myString34, - color=0x000000, - #color=0xFF00FF, - max_glyphs=len(myString34), - background_color=0xFFFF00, - #background_color=None, - padding_bottom=label3_padding, - padding_left=label3_padding, - padding_right=label3_padding, - padding_top=label3_padding, - background_tight=False, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0,0), - anchored_position=(200,150), - ) - -bmap_label4 = label.Label(font=fontList[0], text=myString34, - color=0x000000, - #color=0xFF00FF, - max_glyphs=len(myString34), - background_color=0xFFFF00, - #background_color=None, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, - #anchored_position=(10,150), - ) - -bmap_label5 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - scale=my_scale, - #anchored_position=(10,200), - ) - - -bmap_label6 = label.Label(font=fontList[0], text=myString6, color=0xFFFFFF, max_glyphs=len(myString6), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - anchor_point=label6_anchor_point, - anchored_position=label6_anchored_position, - scale=my_scale, - ) - - - -gc.collect() -label_end_memory=gc.mem_free() - -bmap_group = displayio.Group( max_size=6 ) # Create a group for displaying -#bmap_group.append(bmap_label) -#bmap_group.append(bmap_label2) -#bmap_group.append(bmap_label3) -bmap_group.append(bmap_label4) -#bmap_group.append(bmap_label5) -#bmap_group.append(bmap_label6) - - -print('***') -print('{} memory used: {}'.format(version, label_start_memory-label_end_memory)) -display.auto_refresh=True - -#time.sleep(0.1) -display.show(bmap_group) - -while True: - pass - - - diff --git a/examples/display_text_label_vs_bitmap_label_simpletest.py b/examples/display_text_label_vs_bitmap_label_simpletest.py new file mode 100755 index 0000000..ecd786e --- /dev/null +++ b/examples/display_text_label_vs_bitmap_label_simpletest.py @@ -0,0 +1,182 @@ +# Sample code using the textMap library and the "textBox" wrapper class +# Creates four textBox instances +# Inserts each textBox into a tileGrid group +# Writes text into the box one character at a time +# Moves the position of the textBox around the display +# Clears each textBox after the full string is written (even if the text is outside of the box) + +#import textmap +#from textmap import textBox + +import board +import displayio +import terminalio +import gc +import time + +########## +# Use these Boolean variables to select the text display library and which font style to use +########## +use_bitmap_label=True # Set True if to use 'bitmap_label.py' + # Set False to use 'label.py' library +########## +use_builtin_font=True # Set True to use the terminalio.FONT BuiltinFont, + # Set False to use a BDF loaded font, see "fontFiles" below +########## + + +my_scale=1 + +if use_bitmap_label: # use bitmap_label.py library (Bitmap) + from adafruit_display_text import bitmap_label as label + + version='bitmap_label.py' + +else: # use label.py library (TileGrid) + from adafruit_display_text import label as label + + version='label.py' + +# Setup the SPI display + +if "DISPLAY" not in dir(board): + # Setup the LCD display with driver + # You may need to change this to match the display driver for the chipset + # used on your display + from adafruit_ili9341 import ILI9341 + + displayio.release_displays() + + # setup the SPI bus + spi = board.SPI() + tft_cs = board.D9 # arbitrary, pin not used + tft_dc = board.D10 + tft_backlight = board.D12 + tft_reset = board.D11 + + while not spi.try_lock(): + spi.configure(baudrate=32000000) + spi.unlock() + + display_bus = displayio.FourWire( + spi, + command=tft_dc, + chip_select=tft_cs, + reset=tft_reset, + baudrate=32000000, + polarity=1, + phase=1, + ) + + # Number of pixels in the display + DISPLAY_WIDTH = 320 + DISPLAY_HEIGHT = 240 + + # create the display + display = ILI9341( + display_bus, + width=DISPLAY_WIDTH, + height=DISPLAY_HEIGHT, + rotation=180, # The rotation can be adjusted to match your configuration. + auto_refresh=True, + native_frames_per_second=90, + ) + + # reset the display to show nothing. + display.show(None) +else: + # built-in display + display = board.DISPLAY + +print ('Display is started') + +# load all the fonts +print('loading fonts...') + + + + +# Setup file locations for BDF font files +font_files = [ + 'fonts/Helvetica-Bold-16.bdf', +# 'fonts/BitstreamVeraSans-Roman-24.bdf', +# 'fonts/BitstreamVeraSans-Roman-16.bdf', +# 'fonts/Fayette-HandwrittenScript-64.bdf', + ] + +font_list = [] + +for i, font_file in enumerate(font_files): + + if use_builtin_font: + this_font=terminalio.FONT # comment this out to switch back to BDF loaded fonts + else: + from adafruit_bitmap_font import bitmap_font + this_font = bitmap_font.load_font(font_file) + + font_list.append(this_font) + + +preload_the_glyphs= True # set this to True if you want to preload the font glyphs into memory + # preloading the glyphs will help speed up the rendering of text but will use more RAM + +if preload_the_glyphs: + + # identify the glyphs to load into memory -> increases rendering speed + glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + + print('loading glyphs...') + for font in font_list: + if font is not terminalio.FONT: + font.load_glyphs(glyphs) + + print('Glyphs are loaded.') + +print('Fonts completed loading.') + +# create group +import gc +gc.collect() +print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) + + + +my_string=('Welcome to using displayio on CircuitPython!') + +gc.collect() +label_start_memory=gc.mem_free() +start_time=time.monotonic() + +bmap_label = label.Label(font=font_list[0], text=my_string, color=0xFFFFFF, max_glyphs=len(my_string), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=30, + line_spacing=1.25, + scale=my_scale, + ) +end_time=time.monotonic() + +gc.collect() +label_end_memory=gc.mem_free() + +bmap_group = displayio.Group( max_size=1 ) # Create a group for displaying +bmap_group.append(bmap_label) + + +print('***') +print('{} memory used: {}'.format(version, label_start_memory-label_end_memory)) +print('{} time to process: {} seconds'.format(version, end_time-start_time)) +display.auto_refresh=True + +display.show(bmap_group) + +while True: + pass + + + From 8a164973b6db14f012cb2a30ce0729bfd386ad82 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 17:18:10 -0500 Subject: [PATCH 10/26] Add more complex example with alternating display of label and bitmap_label --- ..._text_label_vs_bitmap_label_alternating.py | 345 ++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100755 examples/display_text_label_vs_bitmap_label_alternating.py diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py new file mode 100755 index 0000000..d1b19e5 --- /dev/null +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -0,0 +1,345 @@ +# Sample code using the textMap library and the "textBox" wrapper class +# Creates four textBox instances +# Inserts each textBox into a tileGrid group +# Writes text into the box one character at a time +# Moves the position of the textBox around the display +# Clears each textBox after the full string is written (even if the text is outside of the box) + +#import textmap +#from textmap import textBox + +import board +import displayio +import terminalio +import fontio +import sys +import time +import busio + +from adafruit_display_text import bitmap_label +#from adafruit_display_text import bitmap_label as Label + +from adafruit_display_text import label + +# Setup the SPI display +########## +# Use this Boolean variables to select which font style to use +########## +use_builtin_font=True # Set True to use the terminalio.FONT BuiltinFont, + # Set False to use a BDF loaded font, see "fontFiles" below +########## + +# Set scaling factor for display text +my_scale=1 + +# Setup the SPI display + +if "DISPLAY" not in dir(board): + # Setup the LCD display with driver + # You may need to change this to match the display driver for the chipset + # used on your display + from adafruit_ili9341 import ILI9341 + + displayio.release_displays() + + # setup the SPI bus + spi = board.SPI() + tft_cs = board.D9 # arbitrary, pin not used + tft_dc = board.D10 + tft_backlight = board.D12 + tft_reset = board.D11 + + while not spi.try_lock(): + spi.configure(baudrate=32000000) + spi.unlock() + + display_bus = displayio.FourWire( + spi, + command=tft_dc, + chip_select=tft_cs, + reset=tft_reset, + baudrate=32000000, + polarity=1, + phase=1, + ) + + # Number of pixels in the display + DISPLAY_WIDTH = 320 + DISPLAY_HEIGHT = 240 + + # create the display + display = ILI9341( + display_bus, + width=DISPLAY_WIDTH, + height=DISPLAY_HEIGHT, + rotation=180, # The rotation can be adjusted to match your configuration. + auto_refresh=True, + native_frames_per_second=90, + ) + + # reset the display to show nothing. + display.show(None) +else: + # built-in display + display = board.DISPLAY + +print ('Display is started') + + +# load all the fonts +print('loading fonts...') + +fontList = [] + +# Load some proportional fonts +fontFiles = [ + 'fonts/Helvetica-Bold-16.bdf', +# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 +# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText + ] + +from adafruit_bitmap_font import bitmap_font + +for i, fontFile in enumerate(fontFiles): + + if use_builtin_font: + thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts + else: + thisFont = bitmap_font.load_font(fontFile) + + fontList.append(thisFont) + + +preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory + # preloading the glyphs will help speed up the rendering of text but will use more RAM + +if preloadTheGlyphs: + + # identify the glyphs to load into memory -> increases rendering speed + glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + + print('loading glyphs...') + for font in fontList: + if font is not terminalio.FONT: + font.load_glyphs(glyphs) + + print('Glyphs are loaded.') + + +print('Fonts completed loading.') + +# create group +import gc + + +myString1=('This is a label.py and\nbitmap_label.py comparison.') +myString23='none' +myString_bitmap_label='bitmap_label' +myString_label='label bitmap_label' + + +##### +# Create the "bitmap_label.py" versions of the text labels. + +gc.collect() +bitmap_label_start=gc.mem_free() + +bmap_label1 = bitmap_label.Label(font=fontList[0], text=myString1, color=0xFFFFFF, max_glyphs=len(myString1), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0.5,0), + anchored_position=(160, 50), + ) +label2_padding=10 +bmap_label2 = bitmap_label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=label2_padding, + padding_left=0, + padding_right=0, + padding_top=label2_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0,0), + anchored_position=(200,150), + ) + +bmap_label3 = bitmap_label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, + ) + +bmap_label4 = bitmap_label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + scale=my_scale, + ) + +myString5='bitmap_label -->' +bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString5, color=0xFFFFFF, max_glyphs=len(myString5), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(1,0.5), + anchored_position=(200,200), + scale=my_scale, + ) + + + +gc.collect() +bitmap_label_end=gc.mem_free() + +bmap_group = displayio.Group( max_size=5 ) # Create a group for displaying +bmap_group.append(bmap_label1) +bmap_group.append(bmap_label2) +bmap_group.append(bmap_label3) +bmap_group.append(bmap_label4) +bmap_group.append(bmap_label5) + + + +##### +# Create the "label.py" versions of the text labels. + +gc.collect() +label_start=gc.mem_free() + +label1 = label.Label(font=fontList[0], text=myString1, color=0xFFFFFF, max_glyphs=len(myString1), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0.5,0), + anchored_position=(160, 50), + ) + +label2 = label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=label2_padding, + padding_left=0, + padding_right=0, + padding_top=label2_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0,0), + anchored_position=(200,150), + ) + +label3 = label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, + ) + +label4 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + scale=my_scale, + ) + + +myString5 = '<-- label' +label5 = label.Label(font=fontList[0], text=myString5, color=0xFFFFFF, max_glyphs=len(myString5), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(0,0.5), + anchored_position=(50,200), + scale=my_scale, + ) + +gc.collect() +label_end=gc.mem_free() + +label_group = displayio.Group( max_size=5 ) # Create a group for displaying +label_group.append(label1) +label_group.append(label2) +label_group.append(label3) +label_group.append(label4) +label_group.append(label5) + + + + +print('***') + +display.auto_refresh=True + +while True: + print('bitmap_label') + time.sleep(0.1) + display.show(bmap_group) + + time.sleep(2) + + print('label') + time.sleep(0.1) + display.show(label_group) + time.sleep(2) + + + + + + From 9640d00d040964f12070d4642128bafbf4b59aae Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 17:23:19 -0500 Subject: [PATCH 11/26] Removed unnecessary comments and ran black --- adafruit_display_text/bitmap_label.py | 95 +++++++++++---------------- 1 file changed, 37 insertions(+), 58 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 2c8a1aa..b67041b 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -78,31 +78,32 @@ def text_bounding_box( font_height = ascender_max + descender_max font_yoffset = ascender_max - lines = 1 font_height = font.get_glyph(ord("M")).height - xposition = x_start = 0 # starting x position (left margin) yposition = y_start = 0 left = right = x_start top = bottom = y_start - - y_offset_tight = int(( font.get_glyph(ord("M")).height - text.count("\n") *line_spacing_ypixels(font, line_spacing) + y_offset_tight = int( + ( + font.get_glyph(ord("M")).height + - text.count("\n") * line_spacing_ypixels(font, line_spacing) + ) + / 2 ) - / 2) - # this needs to be reviewed (also in label.py), since it doesn't respond + # this needs to be reviewed (also in label.py), since it doesn't respond # properly to the number of newlines. - newline=False + newline = False for char in text: if char == "\n": # newline - newline=True + newline = True else: @@ -112,49 +113,43 @@ def text_bounding_box( print("Glyph not found: {}".format(repr(char))) else: if newline: - newline=False + newline = False xposition = x_start # reset to left column yposition = yposition + line_spacing_ypixels( - font, line_spacing - ) # Add a newline + font, line_spacing + ) # Add a newline lines += 1 xposition += my_glyph.shift_x right = max(right, xposition) if yposition == y_start: # first line, find the Ascender height - top = min(top, - my_glyph.height - my_glyph.dy + y_offset_tight) + top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight) bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight) - # width = my_glyph.width - # height = my_glyph.height - # dx = my_glyph.dx - # dy = my_glyph.dy - # shift_x = my_glyph.shift_x - # shift_y = my_glyph.shift_x - - - loose_height= (lines - 1) * line_spacing_ypixels(font, line_spacing) + (ascender_max + descender_max) - - - - label_calibration_offset=int(( font.get_glyph(ord("M")).height - text.count("\n") *line_spacing_ypixels(font, line_spacing) + loose_height = (lines - 1) * line_spacing_ypixels(font, line_spacing) + ( + ascender_max + descender_max ) - / 2) - - y_offset_tight = -top +label_calibration_offset # + label_calibration_offset = int( + ( + font.get_glyph(ord("M")).height + - text.count("\n") * line_spacing_ypixels(font, line_spacing) + ) + / 2 + ) + y_offset_tight = -top + label_calibration_offset - final_box_width=right-left + final_box_width = right - left if background_tight: - final_box_height=bottom-top - final_y_offset=y_offset_tight - + final_box_height = bottom - top + final_y_offset = y_offset_tight + else: - final_box_height=loose_height - final_y_offset=ascender_max + final_box_height = loose_height + final_y_offset = ascender_max - return (final_box_width, final_box_height, 0, final_y_offset) # -x1_min is the x_offset + return (final_box_width, final_box_height, 0, final_y_offset) def place_text( @@ -256,13 +251,13 @@ def place_text( xposition = xposition + shift_x - return (left, top, right-left, bottom - top) # bounding_box + return (left, top, right - left, bottom - top) # bounding_box class Label(displayio.Group): # Class variable # To save memory, set Label._memory_saver=True and avoid storing the text string in the class. - # If set to False, the class saves the text string for future reference. *** use getter + # If set to False, the class saves the text string for future reference. _memory_saver = True def __init__( @@ -302,7 +297,7 @@ def __init__( else: self._text = text # text to be displayed - # limit padding to >= 0 *** raise an error if negative padding is requested + # limit padding to >= 0 padding_top = max(0, padding_top) padding_bottom = max(0, padding_bottom) padding_left = max(0, padding_left) @@ -367,7 +362,7 @@ def __init__( tile_height=box_y, default_tile=0, x=-padding_left, - y= label_position_yoffset - y_offset - padding_top, + y=label_position_yoffset - y_offset - padding_top, ) # instance the Group with super... super().__init__( @@ -377,32 +372,16 @@ def __init__( ) # this will include any arguments, including scale self.append(self.tilegrid) # add the bitmap's tilegrid to the group - ####### ******* - # Set the tileGrid position in the parent based upon anchor_point and anchor_position - # **** Should scale affect the placement of anchor_position? + # Update bounding_box values. Note: To be consistent with label.py, + # this is the bounding box for the text only, not including the background. self.bounding_box = ( self.tilegrid.x, - #self.tilegrid.y + (y_offset - tight_y_offset), - self.tilegrid.y, #+ (y_offset - tight_y_offset), + self.tilegrid.y, tight_box_x, tight_box_y, ) - # self.bounding_box = ( - # self.tilegrid.x, - # self.tilegrid.y + (y_offset), - # tight_box_x, - # tight_box_y, - # ) - - - - # Update bounding_box values. Note: To be consistent with label.py, - # this is the bounding box for the text only, not including the background. - # ******** Need repair - # Create the TileGrid to hold the single Bitmap (self.bitmap) - self._anchored_position = anchored_position self.anchor_point = anchor_point self.anchored_position = ( From 93756e43e6a65c83169ed4674dc2f526c39449f1 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 19:22:52 -0500 Subject: [PATCH 12/26] Updated class function organization and ran black --- adafruit_display_text/bitmap_label.py | 418 +++++++++++++------------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index b67041b..931b935 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -49,212 +49,8 @@ import displayio - -def line_spacing_ypixels(font, line_spacing): - # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level - return_value = int(line_spacing * font.get_bounding_box()[1]) - return return_value - - -def text_bounding_box( - text, font, line_spacing, background_tight=False -): # **** change default background_tight=False - - label_position_yoffset = int( # for calibration with label.py positioning - (font.get_glyph(ord("M")).height - font.get_bounding_box()[1] * line_spacing) - / 2 - ) - - # This empirical approach checks several glyphs for maximum ascender and descender height - # (consistent with label.py) - glyphs = "M j'" # choose glyphs with highest ascender and lowest - # descender, will depend upon font used - ascender_max = descender_max = 0 - for char in glyphs: - this_glyph = font.get_glyph(ord(char)) - if this_glyph: - ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) - descender_max = max(descender_max, -this_glyph.dy) - font_height = ascender_max + descender_max - font_yoffset = ascender_max - - lines = 1 - - font_height = font.get_glyph(ord("M")).height - - xposition = x_start = 0 # starting x position (left margin) - yposition = y_start = 0 - - left = right = x_start - top = bottom = y_start - - y_offset_tight = int( - ( - font.get_glyph(ord("M")).height - - text.count("\n") * line_spacing_ypixels(font, line_spacing) - ) - / 2 - ) - # this needs to be reviewed (also in label.py), since it doesn't respond - # properly to the number of newlines. - - newline = False - - for char in text: - - if char == "\n": # newline - newline = True - - else: - - my_glyph = font.get_glyph(ord(char)) - - if my_glyph == None: # Error checking: no glyph found - print("Glyph not found: {}".format(repr(char))) - else: - if newline: - newline = False - xposition = x_start # reset to left column - yposition = yposition + line_spacing_ypixels( - font, line_spacing - ) # Add a newline - lines += 1 - xposition += my_glyph.shift_x - right = max(right, xposition) - - if yposition == y_start: # first line, find the Ascender height - top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight) - bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight) - - loose_height = (lines - 1) * line_spacing_ypixels(font, line_spacing) + ( - ascender_max + descender_max - ) - - label_calibration_offset = int( - ( - font.get_glyph(ord("M")).height - - text.count("\n") * line_spacing_ypixels(font, line_spacing) - ) - / 2 - ) - - y_offset_tight = -top + label_calibration_offset - - final_box_width = right - left - if background_tight: - final_box_height = bottom - top - final_y_offset = y_offset_tight - - else: - final_box_height = loose_height - final_y_offset = ascender_max - - return (final_box_width, final_box_height, 0, final_y_offset) - - -def place_text( - bitmap, - text, - font, - line_spacing, - xposition, - yposition, - text_palette_index=1, - background_palette_index=0, - scale=1, - print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph - # pixel color is > 0. This is especially useful for script fonts where glyph - # bounding boxes overlap - # Set `print_only_pixels=False` to write all pixels -): - # placeText - Writes text into a bitmap at the specified location. - # - # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts - # - # Note: Scale is not implemented at this time, is pushed up to Group level - - font_height = font.get_glyph(ord("M")).height - - bitmap_width = bitmap.width - bitmap_height = bitmap.height - - x_start = xposition # starting x position (left margin) - y_start = yposition - - left = right = x_start - top = bottom = y_start - - for char in text: - - if char == "\n": # newline - xposition = x_start # reset to left column - yposition = yposition + line_spacing_ypixels( - font, line_spacing - ) # Add a newline - - else: - - my_glyph = font.get_glyph(ord(char)) - - if my_glyph == None: # Error checking: no glyph found - print("Glyph not found: {}".format(repr(char))) - else: - - right = max(right, xposition + my_glyph.shift_x) - if yposition == y_start: # first line, find the Ascender height - top = min(top, -my_glyph.height - my_glyph.dy) - bottom = max(bottom, yposition - my_glyph.dy) - - width = my_glyph.width - height = my_glyph.height - dx = my_glyph.dx - dy = my_glyph.dy - shift_x = my_glyph.shift_x - shift_y = my_glyph.shift_x - glyph_offset_x = ( - my_glyph.tile_index * width - ) # for type BuiltinFont, this creates the x-offset in the glyph bitmap. - # for BDF loaded fonts, this should equal 0 - - y_offset = font_height - height - for y in range(height): - for x in range(width): - x_placement = x + xposition + dx - y_placement = y + yposition - height - dy - - if ( - (x_placement >= 0) - and (y_placement >= 0) - and (x_placement < bitmap_width) - and (y_placement < bitmap_height) - ): - - # Allows for remapping the bitmap indexes using paletteIndex for background and text. - palette_indexes = ( - background_palette_index, - text_palette_index, - ) - - this_pixel_color = palette_indexes[ - my_glyph.bitmap[ - y * my_glyph.bitmap.width + x + glyph_offset_x - ] - ] - - if not print_only_pixels or this_pixel_color > 0: - # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 - bitmap[ - y_placement * bitmap_width + x_placement - ] = this_pixel_color - elif y_placement > bitmap_height: - break - - xposition = xposition + shift_x - - return (left, top, right - left, bottom - top) # bounding_box - - class Label(displayio.Group): + # Class variable # To save memory, set Label._memory_saver=True and avoid storing the text string in the class. # If set to False, the class saves the text string for future reference. @@ -306,7 +102,7 @@ def __init__( # Calculate the text bounding box # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations - (tight_box_x, tight_box_y, x_offset, tight_y_offset) = text_bounding_box( + (tight_box_x, tight_box_y, x_offset, tight_y_offset) = self.text_bounding_box( text, font, self._line_spacing, background_tight=True, ) @@ -316,7 +112,7 @@ def __init__( y_offset = tight_y_offset else: - (box_x, box_y, x_offset, y_offset) = text_bounding_box( + (box_x, box_y, x_offset, y_offset) = self.text_bounding_box( text, font, self._line_spacing, background_tight=background_tight, ) # Calculate the background size including padding @@ -336,7 +132,7 @@ def __init__( self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) # Place the text into the Bitmap - text_size = place_text( + text_size = self.place_text( self.bitmap, text, font, @@ -365,7 +161,7 @@ def __init__( y=label_position_yoffset - y_offset - padding_top, ) - # instance the Group with super... super().__init__( + # instance the Group # this Group will contain just one TileGrid with one contained bitmap super().__init__( max_size=1, x=x, y=y, **kwargs @@ -388,6 +184,210 @@ def __init__( self._anchored_position ) # sets anchored_position with setter after bitmap is created + @staticmethod + def line_spacing_ypixels(font, line_spacing): + # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level + return_value = int(line_spacing * font.get_bounding_box()[1]) + return return_value + + def text_bounding_box(self, + text, font, line_spacing, background_tight=False + ): # **** change default background_tight=False + + label_position_yoffset = int( # for calibration with label.py positioning + (font.get_glyph(ord("M")).height - font.get_bounding_box()[1] * line_spacing) + / 2 + ) + + # This empirical approach checks several glyphs for maximum ascender and descender height + # (consistent with label.py) + glyphs = "M j'" # choose glyphs with highest ascender and lowest + # descender, will depend upon font used + ascender_max = descender_max = 0 + for char in glyphs: + this_glyph = font.get_glyph(ord(char)) + if this_glyph: + ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) + descender_max = max(descender_max, -this_glyph.dy) + font_height = ascender_max + descender_max + font_yoffset = ascender_max + + lines = 1 + + font_height = font.get_glyph(ord("M")).height + + xposition = x_start = 0 # starting x position (left margin) + yposition = y_start = 0 + + left = right = x_start + top = bottom = y_start + + y_offset_tight = int( + ( + font.get_glyph(ord("M")).height + - text.count("\n") * self.line_spacing_ypixels(font, line_spacing) + ) + / 2 + ) + # this needs to be reviewed (also in label.py), since it doesn't respond + # properly to the number of newlines. + + newline = False + + for char in text: + + if char == "\n": # newline + newline = True + + else: + + my_glyph = font.get_glyph(ord(char)) + + if my_glyph == None: # Error checking: no glyph found + print("Glyph not found: {}".format(repr(char))) + else: + if newline: + newline = False + xposition = x_start # reset to left column + yposition = yposition + self.line_spacing_ypixels( + font, line_spacing + ) # Add a newline + lines += 1 + xposition += my_glyph.shift_x + right = max(right, xposition) + + if yposition == y_start: # first line, find the Ascender height + top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight) + bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight) + + loose_height = (lines - 1) * self.line_spacing_ypixels(font, line_spacing) + ( + ascender_max + descender_max + ) + + label_calibration_offset = int( + ( + font.get_glyph(ord("M")).height + - text.count("\n") * self.line_spacing_ypixels(font, line_spacing) + ) + / 2 + ) + + y_offset_tight = -top + label_calibration_offset + + final_box_width = right - left + if background_tight: + final_box_height = bottom - top + final_y_offset = y_offset_tight + + else: + final_box_height = loose_height + final_y_offset = ascender_max + + return (final_box_width, final_box_height, 0, final_y_offset) + + def place_text(self, + bitmap, + text, + font, + line_spacing, + xposition, + yposition, + text_palette_index=1, + background_palette_index=0, + scale=1, + print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph + # pixel color is > 0. This is especially useful for script fonts where glyph + # bounding boxes overlap + # Set `print_only_pixels=False` to write all pixels + ): + # placeText - Writes text into a bitmap at the specified location. + # + # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts + # + # Note: Scale is not implemented at this time, is pushed up to Group level + + font_height = font.get_glyph(ord("M")).height + + bitmap_width = bitmap.width + bitmap_height = bitmap.height + + x_start = xposition # starting x position (left margin) + y_start = yposition + + left = right = x_start + top = bottom = y_start + + for char in text: + + if char == "\n": # newline + xposition = x_start # reset to left column + yposition = yposition + self.line_spacing_ypixels( + font, line_spacing + ) # Add a newline + + else: + + my_glyph = font.get_glyph(ord(char)) + + if my_glyph == None: # Error checking: no glyph found + print("Glyph not found: {}".format(repr(char))) + else: + + right = max(right, xposition + my_glyph.shift_x) + if yposition == y_start: # first line, find the Ascender height + top = min(top, -my_glyph.height - my_glyph.dy) + bottom = max(bottom, yposition - my_glyph.dy) + + width = my_glyph.width + height = my_glyph.height + dx = my_glyph.dx + dy = my_glyph.dy + shift_x = my_glyph.shift_x + shift_y = my_glyph.shift_x + glyph_offset_x = ( + my_glyph.tile_index * width + ) # for type BuiltinFont, this creates the x-offset in the glyph bitmap. + # for BDF loaded fonts, this should equal 0 + + y_offset = font_height - height + for y in range(height): + for x in range(width): + x_placement = x + xposition + dx + y_placement = y + yposition - height - dy + + if ( + (x_placement >= 0) + and (y_placement >= 0) + and (x_placement < bitmap_width) + and (y_placement < bitmap_height) + ): + + # Allows for remapping the bitmap indexes using paletteIndex for background and text. + palette_indexes = ( + background_palette_index, + text_palette_index, + ) + + this_pixel_color = palette_indexes[ + my_glyph.bitmap[ + y * my_glyph.bitmap.width + x + glyph_offset_x + ] + ] + + if not print_only_pixels or this_pixel_color > 0: + # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 + bitmap[ + y_placement * bitmap_width + x_placement + ] = this_pixel_color + elif y_placement > bitmap_height: + break + + xposition = xposition + shift_x + + return (left, top, right - left, bottom - top) # bounding_box + + + @property def anchor_point(self): """Point that anchored_position moves relative to. From 9ffd22a7b9b1dbe6927f0addafe488595eaa8899 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 19:37:41 -0500 Subject: [PATCH 13/26] Ran black on examples --- ..._text_label_vs_bitmap_label_alternating.py | 421 ++++++++++-------- ...y_text_label_vs_bitmap_label_simpletest.py | 122 ++--- 2 files changed, 291 insertions(+), 252 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py index d1b19e5..aff2c86 100755 --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -5,8 +5,8 @@ # Moves the position of the textBox around the display # Clears each textBox after the full string is written (even if the text is outside of the box) -#import textmap -#from textmap import textBox +# import textmap +# from textmap import textBox import board import displayio @@ -17,7 +17,8 @@ import busio from adafruit_display_text import bitmap_label -#from adafruit_display_text import bitmap_label as Label + +# from adafruit_display_text import bitmap_label as Label from adafruit_display_text import label @@ -25,12 +26,12 @@ ########## # Use this Boolean variables to select which font style to use ########## -use_builtin_font=True # Set True to use the terminalio.FONT BuiltinFont, - # Set False to use a BDF loaded font, see "fontFiles" below +use_builtin_font = True # Set True to use the terminalio.FONT BuiltinFont, +# Set False to use a BDF loaded font, see "fontFiles" below ########## # Set scaling factor for display text -my_scale=1 +my_scale = 1 # Setup the SPI display @@ -83,145 +84,168 @@ # built-in display display = board.DISPLAY -print ('Display is started') +print("Display is started") # load all the fonts -print('loading fonts...') +print("loading fonts...") fontList = [] # Load some proportional fonts -fontFiles = [ - 'fonts/Helvetica-Bold-16.bdf', -# 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 -# 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText - ] +fontFiles = [ + "fonts/Helvetica-Bold-16.bdf", + # 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 + # 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText +] from adafruit_bitmap_font import bitmap_font for i, fontFile in enumerate(fontFiles): - if use_builtin_font: - thisFont=terminalio.FONT # comment this out to switch back to BDF loaded fonts + if use_builtin_font: + thisFont = ( + terminalio.FONT + ) # comment this out to switch back to BDF loaded fonts else: - thisFont = bitmap_font.load_font(fontFile) + thisFont = bitmap_font.load_font(fontFile) fontList.append(thisFont) -preloadTheGlyphs= True # set this to True if you want to preload the font glyphs into memory - # preloading the glyphs will help speed up the rendering of text but will use more RAM +preloadTheGlyphs = ( + True # set this to True if you want to preload the font glyphs into memory +) +# preloading the glyphs will help speed up the rendering of text but will use more RAM if preloadTheGlyphs: # identify the glyphs to load into memory -> increases rendering speed - glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " - print('loading glyphs...') + print("loading glyphs...") for font in fontList: if font is not terminalio.FONT: font.load_glyphs(glyphs) - print('Glyphs are loaded.') + print("Glyphs are loaded.") -print('Fonts completed loading.') +print("Fonts completed loading.") -# create group +# create group import gc -myString1=('This is a label.py and\nbitmap_label.py comparison.') -myString23='none' -myString_bitmap_label='bitmap_label' -myString_label='label bitmap_label' +myString1 = "This is a label.py and\nbitmap_label.py comparison." +myString23 = "none" +myString_bitmap_label = "bitmap_label" +myString_label = "label bitmap_label" ##### # Create the "bitmap_label.py" versions of the text labels. gc.collect() -bitmap_label_start=gc.mem_free() - -bmap_label1 = bitmap_label.Label(font=fontList[0], text=myString1, color=0xFFFFFF, max_glyphs=len(myString1), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=60, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0.5,0), - anchored_position=(160, 50), - ) -label2_padding=10 -bmap_label2 = bitmap_label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), - background_color=0xFFFF00, - padding_bottom=label2_padding, - padding_left=0, - padding_right=0, - padding_top=label2_padding, - background_tight=False, - x=10, - y=100, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0,0), - anchored_position=(200,150), - ) - -bmap_label3 = bitmap_label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, - ) - -bmap_label4 = bitmap_label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - scale=my_scale, - ) - -myString5='bitmap_label -->' -bmap_label5 = bitmap_label.Label(font=fontList[0], text=myString5, color=0xFFFFFF, max_glyphs=len(myString5), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - anchor_point=(1,0.5), - anchored_position=(200,200), - scale=my_scale, - ) - +bitmap_label_start = gc.mem_free() + +bmap_label1 = bitmap_label.Label( + font=fontList[0], + text=myString1, + color=0xFFFFFF, + max_glyphs=len(myString1), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0.5, 0), + anchored_position=(160, 50), +) +label2_padding = 10 +bmap_label2 = bitmap_label.Label( + font=fontList[0], + text=myString23, + color=0x000000, + max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=label2_padding, + padding_left=0, + padding_right=0, + padding_top=label2_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0, 0), + anchored_position=(200, 150), +) + +bmap_label3 = bitmap_label.Label( + font=fontList[0], + text=myString23, + color=0x000000, + max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, +) + +bmap_label4 = bitmap_label.Label( + font=fontList[0], + text=myString_label, + color=0x000000, + max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + scale=my_scale, +) + +myString5 = "bitmap_label -->" +bmap_label5 = bitmap_label.Label( + font=fontList[0], + text=myString5, + color=0xFFFFFF, + max_glyphs=len(myString5), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(1, 0.5), + anchored_position=(200, 200), + scale=my_scale, +) gc.collect() -bitmap_label_end=gc.mem_free() +bitmap_label_end = gc.mem_free() -bmap_group = displayio.Group( max_size=5 ) # Create a group for displaying +bmap_group = displayio.Group(max_size=5) # Create a group for displaying bmap_group.append(bmap_label1) bmap_group.append(bmap_label2) bmap_group.append(bmap_label3) @@ -229,90 +253,109 @@ bmap_group.append(bmap_label5) - ##### # Create the "label.py" versions of the text labels. gc.collect() -label_start=gc.mem_free() - -label1 = label.Label(font=fontList[0], text=myString1, color=0xFFFFFF, max_glyphs=len(myString1), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=60, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0.5,0), - anchored_position=(160, 50), - ) - -label2 = label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), - background_color=0xFFFF00, - padding_bottom=label2_padding, - padding_left=0, - padding_right=0, - padding_top=label2_padding, - background_tight=False, - x=10, - y=100, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0,0), - anchored_position=(200,150), - ) - -label3 = label.Label(font=fontList[0], text=myString23, color=0x000000, max_glyphs=len(myString23), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, - ) - -label4 = label.Label(font=fontList[0], text=myString_label, color=0x000000, max_glyphs=len(myString_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - scale=my_scale, - ) - - -myString5 = '<-- label' -label5 = label.Label(font=fontList[0], text=myString5, color=0xFFFFFF, max_glyphs=len(myString5), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - anchor_point=(0,0.5), - anchored_position=(50,200), - scale=my_scale, - ) +label_start = gc.mem_free() + +label1 = label.Label( + font=fontList[0], + text=myString1, + color=0xFFFFFF, + max_glyphs=len(myString1), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=60, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0.5, 0), + anchored_position=(160, 50), +) + +label2 = label.Label( + font=fontList[0], + text=myString23, + color=0x000000, + max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=label2_padding, + padding_left=0, + padding_right=0, + padding_top=label2_padding, + background_tight=False, + x=10, + y=100, + line_spacing=1.25, + scale=my_scale, + anchor_point=(0, 0), + anchored_position=(200, 150), +) + +label3 = label.Label( + font=fontList[0], + text=myString23, + color=0x000000, + max_glyphs=len(myString23), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=150, + line_spacing=1.25, + scale=my_scale, +) + +label4 = label.Label( + font=fontList[0], + text=myString_label, + color=0x000000, + max_glyphs=len(myString_label), + background_color=0xFFFF00, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=True, + x=10, + y=200, + line_spacing=1.25, + scale=my_scale, +) + + +myString5 = "<-- label" +label5 = label.Label( + font=fontList[0], + text=myString5, + color=0xFFFFFF, + max_glyphs=len(myString5), + background_color=0x000000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=200, + line_spacing=1.25, + anchor_point=(0, 0.5), + anchored_position=(50, 200), + scale=my_scale, +) gc.collect() -label_end=gc.mem_free() +label_end = gc.mem_free() -label_group = displayio.Group( max_size=5 ) # Create a group for displaying +label_group = displayio.Group(max_size=5) # Create a group for displaying label_group.append(label1) label_group.append(label2) label_group.append(label3) @@ -320,26 +363,18 @@ label_group.append(label5) +print("***") - -print('***') - -display.auto_refresh=True +display.auto_refresh = True while True: - print('bitmap_label') + print("bitmap_label") time.sleep(0.1) display.show(bmap_group) - + time.sleep(2) - print('label') + print("label") time.sleep(0.1) display.show(label_group) time.sleep(2) - - - - - - diff --git a/examples/display_text_label_vs_bitmap_label_simpletest.py b/examples/display_text_label_vs_bitmap_label_simpletest.py index ecd786e..c4ef0ca 100755 --- a/examples/display_text_label_vs_bitmap_label_simpletest.py +++ b/examples/display_text_label_vs_bitmap_label_simpletest.py @@ -5,8 +5,8 @@ # Moves the position of the textBox around the display # Clears each textBox after the full string is written (even if the text is outside of the box) -#import textmap -#from textmap import textBox +# import textmap +# from textmap import textBox import board import displayio @@ -17,25 +17,25 @@ ########## # Use these Boolean variables to select the text display library and which font style to use ########## -use_bitmap_label=True # Set True if to use 'bitmap_label.py' - # Set False to use 'label.py' library +use_bitmap_label = True # Set True if to use 'bitmap_label.py' +# Set False to use 'label.py' library ########## -use_builtin_font=True # Set True to use the terminalio.FONT BuiltinFont, - # Set False to use a BDF loaded font, see "fontFiles" below +use_builtin_font = True # Set True to use the terminalio.FONT BuiltinFont, +# Set False to use a BDF loaded font, see "fontFiles" below ########## -my_scale=1 +my_scale = 1 -if use_bitmap_label: # use bitmap_label.py library (Bitmap) +if use_bitmap_label: # use bitmap_label.py library (Bitmap) from adafruit_display_text import bitmap_label as label - version='bitmap_label.py' + version = "bitmap_label.py" -else: # use label.py library (TileGrid) +else: # use label.py library (TileGrid) from adafruit_display_text import label as label - version='label.py' + version = "label.py" # Setup the SPI display @@ -88,95 +88,99 @@ # built-in display display = board.DISPLAY -print ('Display is started') +print("Display is started") # load all the fonts -print('loading fonts...') - - +print("loading fonts...") # Setup file locations for BDF font files -font_files = [ - 'fonts/Helvetica-Bold-16.bdf', -# 'fonts/BitstreamVeraSans-Roman-24.bdf', -# 'fonts/BitstreamVeraSans-Roman-16.bdf', -# 'fonts/Fayette-HandwrittenScript-64.bdf', - ] +font_files = [ + "fonts/Helvetica-Bold-16.bdf", + # 'fonts/BitstreamVeraSans-Roman-24.bdf', + # 'fonts/BitstreamVeraSans-Roman-16.bdf', + # 'fonts/Fayette-HandwrittenScript-64.bdf', +] font_list = [] for i, font_file in enumerate(font_files): - + if use_builtin_font: - this_font=terminalio.FONT # comment this out to switch back to BDF loaded fonts + this_font = ( + terminalio.FONT + ) # comment this out to switch back to BDF loaded fonts else: from adafruit_bitmap_font import bitmap_font - this_font = bitmap_font.load_font(font_file) + + this_font = bitmap_font.load_font(font_file) font_list.append(this_font) -preload_the_glyphs= True # set this to True if you want to preload the font glyphs into memory - # preloading the glyphs will help speed up the rendering of text but will use more RAM +preload_the_glyphs = ( + True # set this to True if you want to preload the font glyphs into memory +) +# preloading the glyphs will help speed up the rendering of text but will use more RAM if preload_the_glyphs: # identify the glyphs to load into memory -> increases rendering speed - glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! ' + glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " - print('loading glyphs...') + print("loading glyphs...") for font in font_list: if font is not terminalio.FONT: font.load_glyphs(glyphs) - print('Glyphs are loaded.') + print("Glyphs are loaded.") -print('Fonts completed loading.') +print("Fonts completed loading.") -# create group +# create group import gc -gc.collect() -print( 'After creating Group, Memory free: {}'.format(gc.mem_free()) ) +gc.collect() +print("After creating Group, Memory free: {}".format(gc.mem_free())) -my_string=('Welcome to using displayio on CircuitPython!') +my_string = "Welcome to using displayio on CircuitPython!" gc.collect() -label_start_memory=gc.mem_free() -start_time=time.monotonic() - -bmap_label = label.Label(font=font_list[0], text=my_string, color=0xFFFFFF, max_glyphs=len(my_string), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=30, - line_spacing=1.25, - scale=my_scale, - ) -end_time=time.monotonic() +label_start_memory = gc.mem_free() +start_time = time.monotonic() + +bmap_label = label.Label( + font=font_list[0], + text=my_string, + color=0xFFFFFF, + max_glyphs=len(my_string), + background_color=0xFF0000, + padding_bottom=0, + padding_left=0, + padding_right=0, + padding_top=0, + background_tight=False, + x=10, + y=30, + line_spacing=1.25, + scale=my_scale, +) +end_time = time.monotonic() gc.collect() -label_end_memory=gc.mem_free() +label_end_memory = gc.mem_free() -bmap_group = displayio.Group( max_size=1 ) # Create a group for displaying +bmap_group = displayio.Group(max_size=1) # Create a group for displaying bmap_group.append(bmap_label) -print('***') -print('{} memory used: {}'.format(version, label_start_memory-label_end_memory)) -print('{} time to process: {} seconds'.format(version, end_time-start_time)) -display.auto_refresh=True +print("***") +print("{} memory used: {}".format(version, label_start_memory - label_end_memory)) +print("{} time to process: {} seconds".format(version, end_time - start_time)) +display.auto_refresh = True display.show(bmap_group) while True: pass - - - From 4bdfb61e8db4f4482f86196f47914b819e4bf146 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 19:42:49 -0500 Subject: [PATCH 14/26] Ran black --- adafruit_display_text/bitmap_label.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 931b935..8b119ef 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -49,6 +49,7 @@ import displayio + class Label(displayio.Group): # Class variable @@ -161,7 +162,7 @@ def __init__( y=label_position_yoffset - y_offset - padding_top, ) - # instance the Group + # instance the Group # this Group will contain just one TileGrid with one contained bitmap super().__init__( max_size=1, x=x, y=y, **kwargs @@ -190,12 +191,15 @@ def line_spacing_ypixels(font, line_spacing): return_value = int(line_spacing * font.get_bounding_box()[1]) return return_value - def text_bounding_box(self, - text, font, line_spacing, background_tight=False + def text_bounding_box( + self, text, font, line_spacing, background_tight=False ): # **** change default background_tight=False label_position_yoffset = int( # for calibration with label.py positioning - (font.get_glyph(ord("M")).height - font.get_bounding_box()[1] * line_spacing) + ( + font.get_glyph(ord("M")).height + - font.get_bounding_box()[1] * line_spacing + ) / 2 ) @@ -285,7 +289,8 @@ def text_bounding_box(self, return (final_box_width, final_box_height, 0, final_y_offset) - def place_text(self, + def place_text( + self, bitmap, text, font, @@ -386,8 +391,6 @@ def place_text(self, return (left, top, right - left, bottom - top) # bounding_box - - @property def anchor_point(self): """Point that anchored_position moves relative to. From dfe6899570b8233f62021ac5b92f0e40fbc095e1 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 20:25:48 -0500 Subject: [PATCH 15/26] cleaned for pylint and black --- adafruit_display_text/bitmap_label.py | 128 +++++++++++++++----------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 8b119ef..e9daef2 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -33,7 +33,8 @@ **Hardware:** -.. todo:: Add links to any specific hardware product page(s), or category page(s). Use unordered list & hyperlink rST +.. todo:: Add links to any specific hardware product page(s), or category page(s). Use +unordered list & hyperlink rST inline format: "* `Link Text `_" **Software and Dependencies:** @@ -41,7 +42,8 @@ * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases -.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based on the library's use of either. +.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based +on the library's use of either. # * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice # * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register @@ -49,8 +51,41 @@ import displayio +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git" + class Label(displayio.Group): + """A label displaying a string of text. The origin point set by ``x`` and ``y`` + properties will be the left edge of the bounding box, and in the center of a M + glyph (if its one line), or the (number of lines * linespacing + M)/2. That is, + it will try to have it be center-left as close as possible. + + :param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``. + Must include a capital M for measuring character size. + :param str text: Text to display + :param int max_glyphs: Unnecessary parameter (provided only for direct compability + with label.py) + :param int color: Color of all text in RGB hex + :param int background_color: Color of the background, use `None` for transparent + :param double line_spacing: Line spacing of text to display + :param boolean background_tight: Set `True` only if you want background box to tightly + surround text + :param int padding_top: Additional pixels added to background bounding box at top + :param int padding_bottom: Additional pixels added to background bounding box at bottom + :param int padding_left: Additional pixels added to background bounding box at left + :param int padding_right: Additional pixels added to background bounding box at right + :param (double,double) anchor_point: Point that anchored_position moves relative to. + Tuple with decimal percentage of width and height. + (E.g. (0,0) is top left, (1.0, 0.5): is middle right.) + :param (int,int) anchored_position: Position relative to the anchor_point. Tuple + containing x,y pixel coordinates. + :param int scale: Integer value of the pixel scaling + """ + + # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments + # Note: max_glyphs parameter is unnecessary, this is used for direct + # compatibility with label.py # Class variable # To save memory, set Label._memory_saver=True and avoid storing the text string in the class. @@ -63,8 +98,8 @@ def __init__( x=0, y=0, text="", - max_glyphs=None, # This input parameter is ignored, only present for compatibility with label.py - # width, height, + max_glyphs=None, # This input parameter is ignored, only present for compatibility + # with label.py color=0xFFFFFF, background_color=None, line_spacing=1.25, @@ -102,8 +137,9 @@ def __init__( # Calculate the text bounding box - # Calculate tight box to provide bounding box dimensions to match label for anchor_position calculations - (tight_box_x, tight_box_y, x_offset, tight_y_offset) = self.text_bounding_box( + # Calculate tight box to provide bounding box dimensions to match label for + # anchor_position calculations + (tight_box_x, tight_box_y, x_offset, tight_y_offset) = self._text_bounding_box( text, font, self._line_spacing, background_tight=True, ) @@ -113,7 +149,7 @@ def __init__( y_offset = tight_y_offset else: - (box_x, box_y, x_offset, y_offset) = self.text_bounding_box( + (box_x, box_y, x_offset, y_offset) = self._text_bounding_box( text, font, self._line_spacing, background_tight=background_tight, ) # Calculate the background size including padding @@ -133,7 +169,7 @@ def __init__( self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) # Place the text into the Bitmap - text_size = self.place_text( + self._place_text( self.bitmap, text, font, @@ -186,23 +222,15 @@ def __init__( ) # sets anchored_position with setter after bitmap is created @staticmethod - def line_spacing_ypixels(font, line_spacing): + def _line_spacing_ypixels(font, line_spacing): # Note: Scale is not implemented at this time, any scaling is pushed up to the Group level return_value = int(line_spacing * font.get_bounding_box()[1]) return return_value - def text_bounding_box( + def _text_bounding_box( self, text, font, line_spacing, background_tight=False ): # **** change default background_tight=False - label_position_yoffset = int( # for calibration with label.py positioning - ( - font.get_glyph(ord("M")).height - - font.get_bounding_box()[1] * line_spacing - ) - / 2 - ) - # This empirical approach checks several glyphs for maximum ascender and descender height # (consistent with label.py) glyphs = "M j'" # choose glyphs with highest ascender and lowest @@ -213,13 +241,9 @@ def text_bounding_box( if this_glyph: ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy) descender_max = max(descender_max, -this_glyph.dy) - font_height = ascender_max + descender_max - font_yoffset = ascender_max lines = 1 - font_height = font.get_glyph(ord("M")).height - xposition = x_start = 0 # starting x position (left margin) yposition = y_start = 0 @@ -229,7 +253,7 @@ def text_bounding_box( y_offset_tight = int( ( font.get_glyph(ord("M")).height - - text.count("\n") * self.line_spacing_ypixels(font, line_spacing) + - text.count("\n") * self._line_spacing_ypixels(font, line_spacing) ) / 2 ) @@ -247,13 +271,13 @@ def text_bounding_box( my_glyph = font.get_glyph(ord(char)) - if my_glyph == None: # Error checking: no glyph found + if my_glyph is None: # Error checking: no glyph found print("Glyph not found: {}".format(repr(char))) else: if newline: newline = False xposition = x_start # reset to left column - yposition = yposition + self.line_spacing_ypixels( + yposition = yposition + self._line_spacing_ypixels( font, line_spacing ) # Add a newline lines += 1 @@ -264,14 +288,14 @@ def text_bounding_box( top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight) bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight) - loose_height = (lines - 1) * self.line_spacing_ypixels(font, line_spacing) + ( + loose_height = (lines - 1) * self._line_spacing_ypixels(font, line_spacing) + ( ascender_max + descender_max ) label_calibration_offset = int( ( font.get_glyph(ord("M")).height - - text.count("\n") * self.line_spacing_ypixels(font, line_spacing) + - text.count("\n") * self._line_spacing_ypixels(font, line_spacing) ) / 2 ) @@ -289,7 +313,8 @@ def text_bounding_box( return (final_box_width, final_box_height, 0, final_y_offset) - def place_text( + # pylint: disable=too-many-nested-blocks + def _place_text( self, bitmap, text, @@ -299,7 +324,6 @@ def place_text( yposition, text_palette_index=1, background_palette_index=0, - scale=1, print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph # pixel color is > 0. This is especially useful for script fonts where glyph # bounding boxes overlap @@ -307,12 +331,11 @@ def place_text( ): # placeText - Writes text into a bitmap at the specified location. # - # Verify paletteIndex is working properly with * operator, especially if accommodating multicolored fonts + # Verify paletteIndex is working properly with * operator, especially + # if accommodating multicolored fonts # # Note: Scale is not implemented at this time, is pushed up to Group level - font_height = font.get_glyph(ord("M")).height - bitmap_width = bitmap.width bitmap_height = bitmap.height @@ -326,7 +349,7 @@ def place_text( if char == "\n": # newline xposition = x_start # reset to left column - yposition = yposition + self.line_spacing_ypixels( + yposition = yposition + self._line_spacing_ypixels( font, line_spacing ) # Add a newline @@ -334,7 +357,7 @@ def place_text( my_glyph = font.get_glyph(ord(char)) - if my_glyph == None: # Error checking: no glyph found + if my_glyph is None: # Error checking: no glyph found print("Glyph not found: {}".format(repr(char))) else: @@ -343,31 +366,22 @@ def place_text( top = min(top, -my_glyph.height - my_glyph.dy) bottom = max(bottom, yposition - my_glyph.dy) - width = my_glyph.width - height = my_glyph.height - dx = my_glyph.dx - dy = my_glyph.dy - shift_x = my_glyph.shift_x - shift_y = my_glyph.shift_x glyph_offset_x = ( - my_glyph.tile_index * width + my_glyph.tile_index * my_glyph.width ) # for type BuiltinFont, this creates the x-offset in the glyph bitmap. # for BDF loaded fonts, this should equal 0 - y_offset = font_height - height - for y in range(height): - for x in range(width): - x_placement = x + xposition + dx - y_placement = y + yposition - height - dy - - if ( - (x_placement >= 0) - and (y_placement >= 0) - and (x_placement < bitmap_width) - and (y_placement < bitmap_height) + for y in range(my_glyph.height): + for x in range(my_glyph.width): + x_placement = x + xposition + my_glyph.dx + y_placement = y + yposition - my_glyph.height - my_glyph.dy + + if (bitmap_width > x_placement >= 0) and ( + bitmap_height > y_placement >= 0 ): - # Allows for remapping the bitmap indexes using paletteIndex for background and text. + # Allows for remapping the bitmap indexes using paletteIndex + # for background and text. palette_indexes = ( background_palette_index, text_palette_index, @@ -380,14 +394,15 @@ def place_text( ] if not print_only_pixels or this_pixel_color > 0: - # write all characters if printOnlyPixels = False, or if thisPixelColor is > 0 + # write all characters if printOnlyPixels = False, + # or if thisPixelColor is > 0 bitmap[ y_placement * bitmap_width + x_placement ] = this_pixel_color elif y_placement > bitmap_height: break - xposition = xposition + shift_x + xposition = xposition + my_glyph.shift_x return (left, top, right - left, bottom - top) # bounding_box @@ -407,11 +422,12 @@ def anchor_point(self, new_anchor_point): @property def anchored_position(self): + """Position relative to the anchor_point. Tuple containing x,y + pixel coordinates.""" return self._anchored_position @anchored_position.setter def anchored_position(self, new_position): - self._anchored_position = new_position # Set anchored_position From 119a7d0aed308afa58555e22f267b0aa4d11f399 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 20:37:37 -0500 Subject: [PATCH 16/26] Limited pylint cleanup of examples --- ..._text_label_vs_bitmap_label_alternating.py | 73 +++++++++---------- ...y_text_label_vs_bitmap_label_simpletest.py | 16 ++-- 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py index aff2c86..deda7e7 100755 --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -8,13 +8,12 @@ # import textmap # from textmap import textBox +import gc +import time import board import displayio import terminalio -import fontio -import sys -import time -import busio +from adafruit_bitmap_font import bitmap_font from adafruit_display_text import bitmap_label @@ -26,7 +25,7 @@ ########## # Use this Boolean variables to select which font style to use ########## -use_builtin_font = True # Set True to use the terminalio.FONT BuiltinFont, +use_builtinfont = True # Set True to use the terminalio.FONT BuiltinFont, # Set False to use a BDF loaded font, see "fontFiles" below ########## @@ -99,11 +98,11 @@ # 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText ] -from adafruit_bitmap_font import bitmap_font + for i, fontFile in enumerate(fontFiles): - if use_builtin_font: + if use_builtinfont: thisFont = ( terminalio.FONT ) # comment this out to switch back to BDF loaded fonts @@ -113,12 +112,10 @@ fontList.append(thisFont) -preloadTheGlyphs = ( - True # set this to True if you want to preload the font glyphs into memory -) +preload_glyphs = True # set this to True if you want to preload the font glyphs into memory # preloading the glyphs will help speed up the rendering of text but will use more RAM -if preloadTheGlyphs: +if preload_glyphs: # identify the glyphs to load into memory -> increases rendering speed glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " @@ -134,13 +131,11 @@ print("Fonts completed loading.") # create group -import gc - -myString1 = "This is a label.py and\nbitmap_label.py comparison." -myString23 = "none" -myString_bitmap_label = "bitmap_label" -myString_label = "label bitmap_label" +my_string1 = "This is a label.py and\nbitmap_label.py comparison." +my_string23 = "none" +my_string_bitmap_label = "bitmap_label" +my_string_label = "label bitmap_label" ##### @@ -151,9 +146,9 @@ bmap_label1 = bitmap_label.Label( font=fontList[0], - text=myString1, + text=my_string1, color=0xFFFFFF, - max_glyphs=len(myString1), + max_glyphs=len(my_string1), background_color=0xFF0000, padding_bottom=0, padding_left=0, @@ -170,9 +165,9 @@ label2_padding = 10 bmap_label2 = bitmap_label.Label( font=fontList[0], - text=myString23, + text=my_string23, color=0x000000, - max_glyphs=len(myString23), + max_glyphs=len(my_string23), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, @@ -189,9 +184,9 @@ bmap_label3 = bitmap_label.Label( font=fontList[0], - text=myString23, + text=my_string23, color=0x000000, - max_glyphs=len(myString23), + max_glyphs=len(my_string23), background_color=0xFFFF00, padding_bottom=0, padding_left=0, @@ -206,9 +201,9 @@ bmap_label4 = bitmap_label.Label( font=fontList[0], - text=myString_label, + text=my_string_label, color=0x000000, - max_glyphs=len(myString_label), + max_glyphs=len(my_string_label), background_color=0xFFFF00, padding_bottom=0, padding_left=0, @@ -221,12 +216,12 @@ scale=my_scale, ) -myString5 = "bitmap_label -->" +my_string5 = "bitmap_label -->" bmap_label5 = bitmap_label.Label( font=fontList[0], - text=myString5, + text=my_string5, color=0xFFFFFF, - max_glyphs=len(myString5), + max_glyphs=len(my_string5), background_color=0x000000, padding_bottom=0, padding_left=0, @@ -261,9 +256,9 @@ label1 = label.Label( font=fontList[0], - text=myString1, + text=my_string1, color=0xFFFFFF, - max_glyphs=len(myString1), + max_glyphs=len(my_string1), background_color=0xFF0000, padding_bottom=0, padding_left=0, @@ -280,9 +275,9 @@ label2 = label.Label( font=fontList[0], - text=myString23, + text=my_string23, color=0x000000, - max_glyphs=len(myString23), + max_glyphs=len(my_string23), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, @@ -299,9 +294,9 @@ label3 = label.Label( font=fontList[0], - text=myString23, + text=my_string23, color=0x000000, - max_glyphs=len(myString23), + max_glyphs=len(my_string23), background_color=0xFFFF00, padding_bottom=0, padding_left=0, @@ -316,9 +311,9 @@ label4 = label.Label( font=fontList[0], - text=myString_label, + text=my_string_label, color=0x000000, - max_glyphs=len(myString_label), + max_glyphs=len(my_string_label), background_color=0xFFFF00, padding_bottom=0, padding_left=0, @@ -332,12 +327,12 @@ ) -myString5 = "<-- label" +my_string5 = "<-- label" label5 = label.Label( font=fontList[0], - text=myString5, + text=my_string5, color=0xFFFFFF, - max_glyphs=len(myString5), + max_glyphs=len(my_string5), background_color=0x000000, padding_bottom=0, padding_left=0, diff --git a/examples/display_text_label_vs_bitmap_label_simpletest.py b/examples/display_text_label_vs_bitmap_label_simpletest.py index c4ef0ca..1fb9b75 100755 --- a/examples/display_text_label_vs_bitmap_label_simpletest.py +++ b/examples/display_text_label_vs_bitmap_label_simpletest.py @@ -8,32 +8,33 @@ # import textmap # from textmap import textBox +import gc +import time import board import displayio import terminalio -import gc -import time + ########## # Use these Boolean variables to select the text display library and which font style to use ########## -use_bitmap_label = True # Set True if to use 'bitmap_label.py' +use_bitmaplabel = True # Set True if to use 'bitmap_label.py' # Set False to use 'label.py' library ########## -use_builtin_font = True # Set True to use the terminalio.FONT BuiltinFont, +use_builtinfont = True # Set True to use the terminalio.FONT BuiltinFont, # Set False to use a BDF loaded font, see "fontFiles" below ########## my_scale = 1 -if use_bitmap_label: # use bitmap_label.py library (Bitmap) +if use_bitmaplabel: # use bitmap_label.py library (Bitmap) from adafruit_display_text import bitmap_label as label version = "bitmap_label.py" else: # use label.py library (TileGrid) - from adafruit_display_text import label as label + from adafruit_display_text import label version = "label.py" @@ -106,7 +107,7 @@ for i, font_file in enumerate(font_files): - if use_builtin_font: + if use_builtinfont: this_font = ( terminalio.FONT ) # comment this out to switch back to BDF loaded fonts @@ -138,7 +139,6 @@ print("Fonts completed loading.") # create group -import gc gc.collect() print("After creating Group, Memory free: {}".format(gc.mem_free())) From 6a30b327dc093ed8e652ef2ac2b979dfd23964fa Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 6 Aug 2020 20:45:48 -0500 Subject: [PATCH 17/26] ran black --- examples/display_text_label_vs_bitmap_label_alternating.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py index deda7e7..9c2eaf4 100755 --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -99,7 +99,6 @@ ] - for i, fontFile in enumerate(fontFiles): if use_builtinfont: @@ -112,7 +111,9 @@ fontList.append(thisFont) -preload_glyphs = True # set this to True if you want to preload the font glyphs into memory +preload_glyphs = ( + True # set this to True if you want to preload the font glyphs into memory +) # preloading the glyphs will help speed up the rendering of text but will use more RAM if preload_glyphs: From 6aac22d59d9274e6a7bd6d80a56c9a328884264a Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Sat, 8 Aug 2020 10:12:40 -0500 Subject: [PATCH 18/26] minor edits of comments and for pylint no-member --- ...splay_text_label_vs_bitmap_label_alternating.py | 14 ++++---------- ...isplay_text_label_vs_bitmap_label_simpletest.py | 12 +++--------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py index 9c2eaf4..41b0d22 100755 --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -1,12 +1,6 @@ -# Sample code using the textMap library and the "textBox" wrapper class -# Creates four textBox instances -# Inserts each textBox into a tileGrid group -# Writes text into the box one character at a time -# Moves the position of the textBox around the display -# Clears each textBox after the full string is written (even if the text is outside of the box) +# Sample for comparing label and bitmap_label positioning with Builtin or loaded BDF fonts -# import textmap -# from textmap import textBox +# pylint: disable=no-member import gc import time @@ -17,10 +11,10 @@ from adafruit_display_text import bitmap_label -# from adafruit_display_text import bitmap_label as Label - from adafruit_display_text import label +# pylint: disable=no-member + # Setup the SPI display ########## # Use this Boolean variables to select which font style to use diff --git a/examples/display_text_label_vs_bitmap_label_simpletest.py b/examples/display_text_label_vs_bitmap_label_simpletest.py index 1fb9b75..5565a26 100755 --- a/examples/display_text_label_vs_bitmap_label_simpletest.py +++ b/examples/display_text_label_vs_bitmap_label_simpletest.py @@ -1,12 +1,4 @@ -# Sample code using the textMap library and the "textBox" wrapper class -# Creates four textBox instances -# Inserts each textBox into a tileGrid group -# Writes text into the box one character at a time -# Moves the position of the textBox around the display -# Clears each textBox after the full string is written (even if the text is outside of the box) - -# import textmap -# from textmap import textBox +# Sample for comparing label and bitmap_label memory usage with Builtin or loaded BDF fonts import gc import time @@ -15,6 +7,8 @@ import terminalio +# pylint: disable=no-member + ########## # Use these Boolean variables to select the text display library and which font style to use ########## From e08643cdf801b8a4f4c7e3c347bbf1b1673a87fd Mon Sep 17 00:00:00 2001 From: FoamyGuy Date: Tue, 11 Aug 2020 18:42:34 -0500 Subject: [PATCH 19/26] changing example script to simpletest --- .../display_text_bitmap_label_simpletest.py | 12 ++ ...y_text_label_vs_bitmap_label_simpletest.py | 180 ------------------ 2 files changed, 12 insertions(+), 180 deletions(-) create mode 100644 examples/display_text_bitmap_label_simpletest.py delete mode 100755 examples/display_text_label_vs_bitmap_label_simpletest.py diff --git a/examples/display_text_bitmap_label_simpletest.py b/examples/display_text_bitmap_label_simpletest.py new file mode 100644 index 0000000..acb2ca0 --- /dev/null +++ b/examples/display_text_bitmap_label_simpletest.py @@ -0,0 +1,12 @@ +import board +import terminalio +from adafruit_display_text import bitmap_label + + +text = "Hello world" +text_area = bitmap_label.Label(terminalio.FONT, text=text) +text_area.x = 10 +text_area.y = 10 +board.DISPLAY.show(text_area) +while True: + pass diff --git a/examples/display_text_label_vs_bitmap_label_simpletest.py b/examples/display_text_label_vs_bitmap_label_simpletest.py deleted file mode 100755 index 5565a26..0000000 --- a/examples/display_text_label_vs_bitmap_label_simpletest.py +++ /dev/null @@ -1,180 +0,0 @@ -# Sample for comparing label and bitmap_label memory usage with Builtin or loaded BDF fonts - -import gc -import time -import board -import displayio -import terminalio - - -# pylint: disable=no-member - -########## -# Use these Boolean variables to select the text display library and which font style to use -########## -use_bitmaplabel = True # Set True if to use 'bitmap_label.py' -# Set False to use 'label.py' library -########## -use_builtinfont = True # Set True to use the terminalio.FONT BuiltinFont, -# Set False to use a BDF loaded font, see "fontFiles" below -########## - - -my_scale = 1 - -if use_bitmaplabel: # use bitmap_label.py library (Bitmap) - from adafruit_display_text import bitmap_label as label - - version = "bitmap_label.py" - -else: # use label.py library (TileGrid) - from adafruit_display_text import label - - version = "label.py" - -# Setup the SPI display - -if "DISPLAY" not in dir(board): - # Setup the LCD display with driver - # You may need to change this to match the display driver for the chipset - # used on your display - from adafruit_ili9341 import ILI9341 - - displayio.release_displays() - - # setup the SPI bus - spi = board.SPI() - tft_cs = board.D9 # arbitrary, pin not used - tft_dc = board.D10 - tft_backlight = board.D12 - tft_reset = board.D11 - - while not spi.try_lock(): - spi.configure(baudrate=32000000) - spi.unlock() - - display_bus = displayio.FourWire( - spi, - command=tft_dc, - chip_select=tft_cs, - reset=tft_reset, - baudrate=32000000, - polarity=1, - phase=1, - ) - - # Number of pixels in the display - DISPLAY_WIDTH = 320 - DISPLAY_HEIGHT = 240 - - # create the display - display = ILI9341( - display_bus, - width=DISPLAY_WIDTH, - height=DISPLAY_HEIGHT, - rotation=180, # The rotation can be adjusted to match your configuration. - auto_refresh=True, - native_frames_per_second=90, - ) - - # reset the display to show nothing. - display.show(None) -else: - # built-in display - display = board.DISPLAY - -print("Display is started") - -# load all the fonts -print("loading fonts...") - - -# Setup file locations for BDF font files -font_files = [ - "fonts/Helvetica-Bold-16.bdf", - # 'fonts/BitstreamVeraSans-Roman-24.bdf', - # 'fonts/BitstreamVeraSans-Roman-16.bdf', - # 'fonts/Fayette-HandwrittenScript-64.bdf', -] - -font_list = [] - -for i, font_file in enumerate(font_files): - - if use_builtinfont: - this_font = ( - terminalio.FONT - ) # comment this out to switch back to BDF loaded fonts - else: - from adafruit_bitmap_font import bitmap_font - - this_font = bitmap_font.load_font(font_file) - - font_list.append(this_font) - - -preload_the_glyphs = ( - True # set this to True if you want to preload the font glyphs into memory -) -# preloading the glyphs will help speed up the rendering of text but will use more RAM - -if preload_the_glyphs: - - # identify the glyphs to load into memory -> increases rendering speed - glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " - - print("loading glyphs...") - for font in font_list: - if font is not terminalio.FONT: - font.load_glyphs(glyphs) - - print("Glyphs are loaded.") - -print("Fonts completed loading.") - -# create group - -gc.collect() -print("After creating Group, Memory free: {}".format(gc.mem_free())) - - -my_string = "Welcome to using displayio on CircuitPython!" - -gc.collect() -label_start_memory = gc.mem_free() -start_time = time.monotonic() - -bmap_label = label.Label( - font=font_list[0], - text=my_string, - color=0xFFFFFF, - max_glyphs=len(my_string), - background_color=0xFF0000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=30, - line_spacing=1.25, - scale=my_scale, -) -end_time = time.monotonic() - -gc.collect() -label_end_memory = gc.mem_free() - -bmap_group = displayio.Group(max_size=1) # Create a group for displaying -bmap_group.append(bmap_label) - - -print("***") -print("{} memory used: {}".format(version, label_start_memory - label_end_memory)) -print("{} time to process: {} seconds".format(version, end_time - start_time)) -display.auto_refresh = True - -display.show(bmap_group) - -while True: - pass From b6662efe48c6e30bed1cd43fd17b59500c7de0b9 Mon Sep 17 00:00:00 2001 From: FoamyGuy Date: Tue, 11 Aug 2020 19:04:15 -0500 Subject: [PATCH 20/26] working on bitmap_label vs. label comparison example --- ..._text_label_vs_bitmap_label_alternating.py | 239 ++++-------------- 1 file changed, 45 insertions(+), 194 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_alternating.py index 41b0d22..54728c8 100755 --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_alternating.py @@ -10,24 +10,33 @@ from adafruit_bitmap_font import bitmap_font from adafruit_display_text import bitmap_label - from adafruit_display_text import label # pylint: disable=no-member -# Setup the SPI display + ########## # Use this Boolean variables to select which font style to use ########## -use_builtinfont = True # Set True to use the terminalio.FONT BuiltinFont, +use_builtinfont = False # Set True to use the terminalio.FONT BuiltinFont, +fontToUse = terminalio.FONT # Set False to use a BDF loaded font, see "fontFiles" below ########## +if not use_builtinfont: + # load the fonts + print("loading font...") + + fontList = [] + + # Load some proportional fonts + fontFile = "fonts/Helvetica-Bold-16.bdf" + fontToUse = bitmap_font.load_font(fontFile) + # Set scaling factor for display text my_scale = 1 # Setup the SPI display - if "DISPLAY" not in dir(board): # Setup the LCD display with driver # You may need to change this to match the display driver for the chipset @@ -80,58 +89,28 @@ print("Display is started") -# load all the fonts -print("loading fonts...") - -fontList = [] - -# Load some proportional fonts -fontFiles = [ - "fonts/Helvetica-Bold-16.bdf", - # 'fonts/BitstreamVeraSans-Roman-24.bdf', # Header2 - # 'fonts/BitstreamVeraSans-Roman-16.bdf', # mainText -] - - -for i, fontFile in enumerate(fontFiles): - - if use_builtinfont: - thisFont = ( - terminalio.FONT - ) # comment this out to switch back to BDF loaded fonts - else: - thisFont = bitmap_font.load_font(fontFile) - - fontList.append(thisFont) - preload_glyphs = ( True # set this to True if you want to preload the font glyphs into memory ) # preloading the glyphs will help speed up the rendering of text but will use more RAM -if preload_glyphs: +if preload_glyphs and not use_builtinfont: # identify the glyphs to load into memory -> increases rendering speed glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " print("loading glyphs...") - for font in fontList: - if font is not terminalio.FONT: - font.load_glyphs(glyphs) + fontToUse.load_glyphs(glyphs) print("Glyphs are loaded.") - print("Fonts completed loading.") # create group -my_string1 = "This is a label.py and\nbitmap_label.py comparison." -my_string23 = "none" -my_string_bitmap_label = "bitmap_label" -my_string_label = "label bitmap_label" - +long_string = "The purple snake\nbrings python fun\nto everyone." +short_string = "Hello World" ##### # Create the "bitmap_label.py" versions of the text labels. @@ -140,107 +119,45 @@ bitmap_label_start = gc.mem_free() bmap_label1 = bitmap_label.Label( - font=fontList[0], - text=my_string1, + font=fontToUse, + text=short_string, color=0xFFFFFF, - max_glyphs=len(my_string1), + max_glyphs=len(short_string), background_color=0xFF0000, padding_bottom=0, padding_left=0, padding_right=0, padding_top=0, background_tight=True, - x=10, - y=60, line_spacing=1.25, scale=my_scale, - anchor_point=(0.5, 0), - anchored_position=(160, 50), + anchor_point=(0.0, 0), + anchored_position=(10, 60), ) label2_padding = 10 bmap_label2 = bitmap_label.Label( - font=fontList[0], - text=my_string23, + font=fontToUse, + text=long_string, color=0x000000, - max_glyphs=len(my_string23), + max_glyphs=len(long_string), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, padding_right=0, padding_top=label2_padding, background_tight=False, - x=10, - y=100, line_spacing=1.25, scale=my_scale, - anchor_point=(0, 0), - anchored_position=(200, 150), + anchor_point=(0.0, 0), + anchored_position=(10, 120), ) -bmap_label3 = bitmap_label.Label( - font=fontList[0], - text=my_string23, - color=0x000000, - max_glyphs=len(my_string23), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, -) - -bmap_label4 = bitmap_label.Label( - font=fontList[0], - text=my_string_label, - color=0x000000, - max_glyphs=len(my_string_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, - line_spacing=1.25, - scale=my_scale, -) - -my_string5 = "bitmap_label -->" -bmap_label5 = bitmap_label.Label( - font=fontList[0], - text=my_string5, - color=0xFFFFFF, - max_glyphs=len(my_string5), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - anchor_point=(1, 0.5), - anchored_position=(200, 200), - scale=my_scale, -) - - gc.collect() bitmap_label_end = gc.mem_free() -bmap_group = displayio.Group(max_size=5) # Create a group for displaying +bmap_group = displayio.Group(max_size=4) # Create a group for displaying bmap_group.append(bmap_label1) bmap_group.append(bmap_label2) -bmap_group.append(bmap_label3) -bmap_group.append(bmap_label4) -bmap_group.append(bmap_label5) ##### @@ -250,121 +167,55 @@ label_start = gc.mem_free() label1 = label.Label( - font=fontList[0], - text=my_string1, + font=fontToUse, + text=short_string, color=0xFFFFFF, - max_glyphs=len(my_string1), + max_glyphs=len(short_string), background_color=0xFF0000, padding_bottom=0, padding_left=0, padding_right=0, padding_top=0, background_tight=True, - x=10, - y=60, line_spacing=1.25, scale=my_scale, - anchor_point=(0.5, 0), - anchored_position=(160, 50), + anchor_point=(1.0, 0), + anchored_position=(display.width-10, 60), ) label2 = label.Label( - font=fontList[0], - text=my_string23, + font=fontToUse, + text=long_string, color=0x000000, - max_glyphs=len(my_string23), + max_glyphs=len(long_string), background_color=0xFFFF00, padding_bottom=label2_padding, padding_left=0, padding_right=0, padding_top=label2_padding, background_tight=False, - x=10, - y=100, - line_spacing=1.25, - scale=my_scale, - anchor_point=(0, 0), - anchored_position=(200, 150), -) - -label3 = label.Label( - font=fontList[0], - text=my_string23, - color=0x000000, - max_glyphs=len(my_string23), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=150, - line_spacing=1.25, - scale=my_scale, -) - -label4 = label.Label( - font=fontList[0], - text=my_string_label, - color=0x000000, - max_glyphs=len(my_string_label), - background_color=0xFFFF00, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=True, - x=10, - y=200, - line_spacing=1.25, - scale=my_scale, -) - - -my_string5 = "<-- label" -label5 = label.Label( - font=fontList[0], - text=my_string5, - color=0xFFFFFF, - max_glyphs=len(my_string5), - background_color=0x000000, - padding_bottom=0, - padding_left=0, - padding_right=0, - padding_top=0, - background_tight=False, - x=10, - y=200, line_spacing=1.25, - anchor_point=(0, 0.5), - anchored_position=(50, 200), scale=my_scale, + anchor_point=(1.0, 0), + anchored_position=(display.width-10, 120), ) gc.collect() label_end = gc.mem_free() -label_group = displayio.Group(max_size=5) # Create a group for displaying +label_group = displayio.Group(max_size=4) # Create a group for displaying label_group.append(label1) label_group.append(label2) -label_group.append(label3) -label_group.append(label4) -label_group.append(label5) print("***") +main_group = displayio.Group() +main_group.append(label_group) +main_group.append(bmap_group) + display.auto_refresh = True +display.show(main_group) while True: - print("bitmap_label") - time.sleep(0.1) - display.show(bmap_group) - - time.sleep(2) - - print("label") - time.sleep(0.1) - display.show(label_group) - time.sleep(2) + pass \ No newline at end of file From e443db28741a5d2c7375d7137361bf1575cc660c Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Tue, 11 Aug 2020 19:26:53 -0500 Subject: [PATCH 21/26] Updated getters/setters to match label.py --- adafruit_display_text/bitmap_label.py | 132 ++++++++++++++++++++------ 1 file changed, 102 insertions(+), 30 deletions(-) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index e9daef2..71b29de 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -33,20 +33,11 @@ **Hardware:** -.. todo:: Add links to any specific hardware product page(s), or category page(s). Use -unordered list & hyperlink rST - inline format: "* `Link Text `_" - **Software and Dependencies:** * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases -.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based -on the library's use of either. - -# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice -# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register """ import displayio @@ -56,7 +47,18 @@ class Label(displayio.Group): - """A label displaying a string of text. The origin point set by ``x`` and ``y`` + """A label displaying a string of text that is stored in a bitmap. + Note: This ``bitmap_label.py`` library utilizes a bitmap to display the text. + This method is memory-conserving relative to ``label.py``. + For the bitmap_label library, the font, text, and line_spacing must be set at + instancing and are immutable. The ``max_glyphs`` parameter is ignored and is present + only for direct compatability with label.py. + For use cases where text changes are required after the initial instancing, please + use the `label.py` library. + For further reduction in memory usage, set save_text to False (text string will not + be stored). + + The origin point set by ``x`` and ``y`` properties will be the left edge of the bounding box, and in the center of a M glyph (if its one line), or the (number of lines * linespacing + M)/2. That is, it will try to have it be center-left as close as possible. @@ -81,17 +83,14 @@ class Label(displayio.Group): :param (int,int) anchored_position: Position relative to the anchor_point. Tuple containing x,y pixel coordinates. :param int scale: Integer value of the pixel scaling + :param bool save_text: Set True to save the text string as a constant in the + label structure. Set False to reduce memory use. """ # pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments # Note: max_glyphs parameter is unnecessary, this is used for direct # compatibility with label.py - # Class variable - # To save memory, set Label._memory_saver=True and avoid storing the text string in the class. - # If set to False, the class saves the text string for future reference. - _memory_saver = True - def __init__( self, font, @@ -108,13 +107,18 @@ def __init__( padding_bottom=0, padding_left=0, padding_right=0, - anchor_point=(0, 0), + anchor_point=None, anchored_position=None, + save_text=True, # can reduce memory use if save_text = False **kwargs ): if text == "": - raise RuntimeError("Please provide text string") + raise RuntimeError( + "Please provide text string, or use label.py for mutable text" + ) + + self._font = font # Scale will be passed to Group using kwargs. if "scale" in kwargs.keys(): @@ -123,11 +127,12 @@ def __init__( self._scale = 1 self._line_spacing = line_spacing + self._save_text = save_text - if self._memory_saver: # do not save the text in the instance - self._text = None + if self._save_text: # text string will be saved + self._text = text else: - self._text = text # text to be displayed + self._text = None # save a None value since text string is not saved # limit padding to >= 0 padding_top = max(0, padding_top) @@ -158,12 +163,9 @@ def __init__( # Create the two-color palette self.palette = displayio.Palette(2) - if background_color is not None: - self.palette[0] = background_color - else: - self.palette[0] = 0 - self.palette.make_transparent(0) - self.palette[1] = color + + self.background_color = background_color + self.color = color # Create the bitmap and TileGrid self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette)) @@ -208,7 +210,7 @@ def __init__( # Update bounding_box values. Note: To be consistent with label.py, # this is the bounding box for the text only, not including the background. - self.bounding_box = ( + self._bounding_box = ( self.tilegrid.x, self.tilegrid.y, tight_box_x, @@ -406,6 +408,76 @@ def _place_text( return (left, top, right - left, bottom - top) # bounding_box + @property + def bounding_box(self): + """An (x, y, w, h) tuple that completely covers all glyphs. The + first two numbers are offset from the x, y origin of this group""" + return self._bounding_box + + @property + def line_spacing(self): + """The amount of space between lines of text, in multiples of the font's + bounding-box height. (E.g. 1.0 is the bounding-box height)""" + return self._line_spacing + + @line_spacing.setter + def line_spacing(self, new_line_spacing): + raise RuntimeError( + "line_spacing is immutable for bitmap_label.py; use label.py for mutable line_spacing" + ) + + @property + def color(self): + """Color of the text as an RGB hex number.""" + return self._color + + @color.setter + def color(self, new_color): + self._color = new_color + if new_color is not None: + self.palette[1] = new_color + self.palette.make_opaque(1) + else: + self.palette[1] = 0 + self.palette.make_transparent(1) + + @property + def background_color(self): + """Color of the background as an RGB hex number.""" + return self._background_color + + @background_color.setter + def background_color(self, new_color): + self._background_color = new_color + if new_color is not None: + self.palette[0] = new_color + self.palette.make_opaque(0) + else: + self.palette[0] = 0 + self.palette.make_transparent(0) + + @property + def text(self): + """Text to displayed.""" + return self._text + + @text.setter + def text(self, new_text): + raise RuntimeError( + "text is immutable for bitmap_label.py; use label.py library for mutable text" + ) + + @property + def font(self): + """Font to use for text display.""" + return self.font + + @font.setter + def font(self, new_font): + raise RuntimeError( + "font is immutable for bitmap_label.py; use label.py library for mutable font" + ) + @property def anchor_point(self): """Point that anchored_position moves relative to. @@ -434,12 +506,12 @@ def anchored_position(self, new_position): if (self._anchor_point is not None) and (self._anchored_position is not None): new_x = int( new_position[0] - - self._anchor_point[0] * (self.bounding_box[2] * self._scale) + - self._anchor_point[0] * (self._bounding_box[2] * self._scale) ) new_y = int( new_position[1] - - (self._anchor_point[1] * self.bounding_box[3] * self.scale) - + round((self.bounding_box[3] * self.scale) / 2.0) + - (self._anchor_point[1] * self._bounding_box[3] * self.scale) + + round((self._bounding_box[3] * self.scale) / 2.0) ) self.x = new_x self.y = new_y From 8c98dacd815e804ec86d129c94857884a5c352c6 Mon Sep 17 00:00:00 2001 From: FoamyGuy Date: Tue, 11 Aug 2020 20:09:22 -0500 Subject: [PATCH 22/26] working on comparison example --- ...> display_text_label_vs_bitmap_label_comparison.py} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename examples/{display_text_label_vs_bitmap_label_alternating.py => display_text_label_vs_bitmap_label_comparison.py} (96%) mode change 100755 => 100644 diff --git a/examples/display_text_label_vs_bitmap_label_alternating.py b/examples/display_text_label_vs_bitmap_label_comparison.py old mode 100755 new mode 100644 similarity index 96% rename from examples/display_text_label_vs_bitmap_label_alternating.py rename to examples/display_text_label_vs_bitmap_label_comparison.py index 54728c8..a9bde6c --- a/examples/display_text_label_vs_bitmap_label_alternating.py +++ b/examples/display_text_label_vs_bitmap_label_comparison.py @@ -110,7 +110,6 @@ # create group long_string = "The purple snake\nbrings python fun\nto everyone." -short_string = "Hello World" ##### # Create the "bitmap_label.py" versions of the text labels. @@ -120,9 +119,8 @@ bmap_label1 = bitmap_label.Label( font=fontToUse, - text=short_string, + text="bitmap_label", color=0xFFFFFF, - max_glyphs=len(short_string), background_color=0xFF0000, padding_bottom=0, padding_left=0, @@ -155,6 +153,8 @@ gc.collect() bitmap_label_end = gc.mem_free() +print("bitmap_label used: {} memory".format(bitmap_label_start - bitmap_label_end)) + bmap_group = displayio.Group(max_size=4) # Create a group for displaying bmap_group.append(bmap_label1) bmap_group.append(bmap_label2) @@ -168,9 +168,8 @@ label1 = label.Label( font=fontToUse, - text=short_string, + text="label", color=0xFFFFFF, - max_glyphs=len(short_string), background_color=0xFF0000, padding_bottom=0, padding_left=0, @@ -203,6 +202,7 @@ gc.collect() label_end = gc.mem_free() +print("label used: {} memory".format(label_start - label_end)) label_group = displayio.Group(max_size=4) # Create a group for displaying label_group.append(label1) label_group.append(label2) From b14b9455fd47a397e923544a939473f1f69ad45c Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Tue, 11 Aug 2020 21:14:07 -0500 Subject: [PATCH 23/26] Added pylint: disable=no-self-use on getters that throw errors --- adafruit_display_text/bitmap_label.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adafruit_display_text/bitmap_label.py b/adafruit_display_text/bitmap_label.py index 71b29de..98f9322 100644 --- a/adafruit_display_text/bitmap_label.py +++ b/adafruit_display_text/bitmap_label.py @@ -420,6 +420,7 @@ def line_spacing(self): bounding-box height. (E.g. 1.0 is the bounding-box height)""" return self._line_spacing + # pylint: disable=no-self-use @line_spacing.setter def line_spacing(self, new_line_spacing): raise RuntimeError( @@ -461,6 +462,7 @@ def text(self): """Text to displayed.""" return self._text + # pylint: disable=no-self-use @text.setter def text(self, new_text): raise RuntimeError( @@ -472,6 +474,7 @@ def font(self): """Font to use for text display.""" return self.font + # pylint: disable=no-self-use @font.setter def font(self, new_font): raise RuntimeError( From 12440fd02a65238d9f9c633319ff07325618840e Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Wed, 12 Aug 2020 08:16:26 -0500 Subject: [PATCH 24/26] Ran black on example --- examples/display_text_label_vs_bitmap_label_comparison.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_comparison.py b/examples/display_text_label_vs_bitmap_label_comparison.py index a9bde6c..53bc76f 100644 --- a/examples/display_text_label_vs_bitmap_label_comparison.py +++ b/examples/display_text_label_vs_bitmap_label_comparison.py @@ -89,7 +89,6 @@ print("Display is started") - preload_glyphs = ( True # set this to True if you want to preload the font glyphs into memory ) @@ -179,7 +178,7 @@ line_spacing=1.25, scale=my_scale, anchor_point=(1.0, 0), - anchored_position=(display.width-10, 60), + anchored_position=(display.width - 10, 60), ) label2 = label.Label( @@ -196,7 +195,7 @@ line_spacing=1.25, scale=my_scale, anchor_point=(1.0, 0), - anchored_position=(display.width-10, 120), + anchored_position=(display.width - 10, 120), ) gc.collect() @@ -218,4 +217,4 @@ display.show(main_group) while True: - pass \ No newline at end of file + pass From b0d1d5914aff1ce0d9b476736391ec04b752f5a9 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Wed, 12 Aug 2020 08:19:01 -0500 Subject: [PATCH 25/26] Deleted unnecessary import --- examples/display_text_label_vs_bitmap_label_comparison.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/display_text_label_vs_bitmap_label_comparison.py b/examples/display_text_label_vs_bitmap_label_comparison.py index 53bc76f..c14ca72 100644 --- a/examples/display_text_label_vs_bitmap_label_comparison.py +++ b/examples/display_text_label_vs_bitmap_label_comparison.py @@ -3,7 +3,6 @@ # pylint: disable=no-member import gc -import time import board import displayio import terminalio From d4517644f6ef92192b5c6523b6f893857f228e11 Mon Sep 17 00:00:00 2001 From: Margaret Matocha Date: Thu, 13 Aug 2020 08:23:50 -0500 Subject: [PATCH 26/26] added glyphs and moved variable outside of memory check --- examples/display_text_label_vs_bitmap_label_comparison.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/display_text_label_vs_bitmap_label_comparison.py b/examples/display_text_label_vs_bitmap_label_comparison.py index c14ca72..24c8d2a 100644 --- a/examples/display_text_label_vs_bitmap_label_comparison.py +++ b/examples/display_text_label_vs_bitmap_label_comparison.py @@ -96,7 +96,9 @@ if preload_glyphs and not use_builtinfont: # identify the glyphs to load into memory -> increases rendering speed - glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.:?! " + glyphs = ( + b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-_,.:?!'\n " + ) print("loading glyphs...") fontToUse.load_glyphs(glyphs) @@ -108,6 +110,7 @@ # create group long_string = "The purple snake\nbrings python fun\nto everyone." +label2_padding = 10 ##### # Create the "bitmap_label.py" versions of the text labels. @@ -130,7 +133,7 @@ anchor_point=(0.0, 0), anchored_position=(10, 60), ) -label2_padding = 10 + bmap_label2 = bitmap_label.Label( font=fontToUse, text=long_string,