Browse Source

split text drawing interface into multiple methods.

Thomas Buck 9 months ago
parent
commit
d8943ab606
5 changed files with 114 additions and 60 deletions
  1. 49
    25
      bdf.py
  2. 40
    22
      pico.py
  3. 2
    1
      qr.py
  4. 3
    2
      scroll.py
  5. 20
    10
      tetris.py

+ 49
- 25
bdf.py View File

@@ -55,14 +55,14 @@ class DrawText:
55 55
 
56 56
             # center vertically, in case of
57 57
             # multiple stacked panels
58
-            # TODO hard-coded offsets assume 32x32 panels
59
-            if self.gui.height > 32:
60
-                offset += 16
58
+            if self.gui.height > self.gui.panelH:
59
+                offset += int(self.gui.panelH / 2)
61 60
 
62 61
             font = Font(os.path.join(fontDir, filename))
63 62
             data = (font, offset, {}, spacing)
64 63
             self.fonts[filename[:-4]] = data
65 64
 
65
+    # internal
66 66
     def getGlyph(self, c, font):
67 67
         if not isinstance(font, str):
68 68
             # fall-back to first available font
@@ -91,34 +91,58 @@ class DrawText:
91 91
 
92 92
         return (cache[c], offset, spacing)
93 93
 
94
+    # internal
94 95
     def drawGlyph(self, g, xOff, yOff, spacing):
95
-        if xOff >= self.gui.width:
96
-            return
97
-
98
-        for x in range(0, g.width):
96
+        for x in range(0, g.width + spacing):
99 97
             for y in range(0, g.height):
100
-                xTarget = xOff + x
101
-                if (xTarget < 0) or (xTarget >= self.gui.width):
102
-                    continue
103
-
104
-                p = g.getpixel((x, y))
105
-                self.gui.set_pixel(xTarget, yOff + y, p)
98
+                pos = (xOff + x, yOff + y)
99
+                if x >= g.width:
100
+                    self.image.putpixel(pos, self.bg)
101
+                else:
102
+                    p = g.getpixel((x, y))
103
+                    self.image.putpixel(pos, p)
104
+
105
+    # text drawing API
106
+    def setText(self, s, f):
107
+        # calculate length of whole text
108
+        w = 0
109
+        h = 0
110
+        for c in s:
111
+            g, y, spacing = self.getGlyph(c, f)
112
+            w += g.width + spacing
113
+            if h < g.height:
114
+                h = g.height
106 115
 
107
-        for x in range(0, spacing):
108
-            for y in range(0, g.height):
109
-                self.gui.set_pixel(xOff + x + g.width, yOff + y, self.bg)
116
+        # create new blank image buffer
117
+        self.image = Image.new('RGBA', (w, h))
110 118
 
111
-    def text(self, s, f, offset = 0, earlyAbort = True, yOff = 0):
119
+        # render glyphs into image
112 120
         w = 0
113 121
         for c in s:
114
-            xOff = -offset + w
115
-            if earlyAbort:
116
-                if xOff >= self.gui.width:
117
-                    break
118
-
119 122
             g, y, spacing = self.getGlyph(c, f)
123
+            self.drawGlyph(g, w, 0, spacing)
120 124
             w += g.width + spacing
125
+            self.yOffset = y
126
+
127
+    # text drawing API
128
+    def getDimensions(self):
129
+        return (self.image.width, self.image.height)
130
+
131
+    # text drawing API
132
+    def draw(self, xOff = 0, yOff = 0):
133
+        for x in range(0, self.image.width):
134
+            xTarget = -xOff + x
135
+            if xTarget < 0:
136
+                continue
137
+            if xTarget >= self.gui.width:
138
+                break
139
+
140
+            for y in range(0, self.image.height):
141
+                yTarget = yOff + y + self.yOffset
142
+                if yTarget < 0:
143
+                    continue
144
+                if yTarget >= self.gui.height:
145
+                    break
121 146
 
122
-            if xOff >= -16: # some wiggle room so chars dont disappear
123
-                self.drawGlyph(g, xOff, y + yOff, spacing)
124
-        return w
147
+                p = self.image.getpixel((x, y))
148
+                self.gui.set_pixel(xTarget, yTarget, p)

+ 40
- 22
pico.py View File

@@ -177,11 +177,19 @@ class PicoText:
177 177
         self.bg = bg
178 178
         self.color = c
179 179
 
180
-    def text(self, s, f, offset = 0, earlyAbort = True, yOff = 0, compat = True):
181
-        if not earlyAbort:
182
-            self.gui.matrix.display.set_font(f)
183
-            return self.gui.matrix.display.measure_text(s, scale=1)
184
-
180
+    # text drawing API
181
+    def setText(self, s, f):
182
+        self.text = s
183
+        self.font = f
184
+
185
+    # text drawing API
186
+    def getDimensions(self):
187
+        self.gui.matrix.display.set_font(self.font)
188
+        w = self.gui.matrix.display.measure_text(self.text, scale=1)
189
+        return (w, 42) # TODO wrong height
190
+
191
+    # text drawing API
192
+    def draw(self, xOff = 0, yOff = 0, compat = True):
185 193
         color = self.fg
186 194
         if isinstance(self.gui, MapperReduceBrightness):
187 195
             color = self.gui.adjust(color)
@@ -189,26 +197,26 @@ class PicoText:
189 197
         pen = self.gui.matrix.display.create_pen(color[0], color[1], color[2])
190 198
         self.gui.matrix.display.set_pen(pen)
191 199
 
192
-        self.gui.matrix.display.set_font(f)
200
+        self.gui.matrix.display.set_font(self.font)
193 201
 
194 202
         if not compat:
195 203
             # absolute positioning
196
-            x = offset
204
+            x = xOff
197 205
             y = yOff
198 206
         else:
199 207
             # centered, like BDF DrawText implementation
200 208
             fontOff = 0
201
-            if f == "bitmap6":
209
+            if self.font == "bitmap6":
202 210
                 fontOff = 3
203
-            elif f == "bitmap8":
211
+            elif self.font == "bitmap8":
204 212
                 fontOff = 4
205
-            elif f == "bitmap14_outline":
213
+            elif self.font == "bitmap14_outline":
206 214
                 fontOff = 7
207 215
 
208
-            x = -offset
216
+            x = -xOff
209 217
             y = int(self.gui.height / 2 - fontOff + yOff)
210 218
 
211
-        self.gui.matrix.display.text(s, x, y, scale=1)
219
+        self.gui.matrix.display.text(self.text, x, y, scale=1)
212 220
 
213 221
 class PicoBatt:
214 222
     def __init__(self, g, ti = 5.0, tt = 5.0):
@@ -230,12 +238,16 @@ class PicoBatt:
230 238
         c = batt_to_color(batt)
231 239
 
232 240
         self.text.fg = (255, 255, 255)
233
-        self.text.text(                  "Batt:", "bitmap8", 0, True, 8 * 0, False)
241
+        self.text.setText(                  "Batt:", "bitmap8")
242
+        self.text.draw(0, 8 * 0, False)
234 243
 
235 244
         self.text.fg = c
236
-        self.text.text("{:.2f}%".format(batt[0]), "bitmap8", 0, True, 8 * 1, False)
237
-        self.text.text("{:.2f}V".format(batt[1]), "bitmap8", 0, True, 8 * 2, False)
238
-        self.text.text("{:.2f}V".format(batt[2]), "bitmap8", 0, True, 8 * 3, False)
245
+        self.text.setText("{:.2f}%".format(batt[0]), "bitmap8")
246
+        self.text.draw(0, 8 * 1, False)
247
+        self.text.setText("{:.2f}V".format(batt[1]), "bitmap8")
248
+        self.text.draw(0, 8 * 2, False)
249
+        self.text.setText("{:.2f}V".format(batt[2]), "bitmap8")
250
+        self.text.draw(0, 8 * 3, False)
239 251
 
240 252
     def drawImage(self, refresh = False):
241 253
         x_off = const(1)
@@ -251,9 +263,10 @@ class PicoBatt:
251 263
         fill_w = int(batt[0] / 100.0 * (w - nub_w))
252 264
 
253 265
         s = "{:.0f}%".format(batt[0])
254
-        s_w = self.text.text(s, "bitmap14_outline", 0, False)
266
+        self.text.setText(s, "bitmap14_outline")
267
+        s_w = self.text.getDimensions()[0]
255 268
         self.text.fg = (255, 255, 255)
256
-        self.text.text(s, "bitmap14_outline", int((self.gui.width - s_w) / 2), True, 1, False)
269
+        self.text.draw(int((self.gui.width - s_w) / 2), 1, False)
257 270
 
258 271
         for x in range(0, w - nub_w):
259 272
             for y in range(0, h):
@@ -273,6 +286,7 @@ class PicoBatt:
273 286
 
274 287
 if __name__ == "__main__":
275 288
     import time
289
+    import util
276 290
 
277 291
     t = PicoMatrix(32, 32)
278 292
     s = PicoText(t)
@@ -294,10 +308,14 @@ if __name__ == "__main__":
294 308
             b.draw(True)
295 309
             time.sleep(1.0)
296 310
         elif i == 4:
297
-            s.text("Abgj6", "bitmap6", 0, True, 0, False)
298
-            s.text("Abdgj8", "bitmap8", 0, True, 6 + 2, False)
299
-            s.text("Ag14", "bitmap14_outline", 0, True, 6 + 2 + 8 + 1, False)
311
+            s.setText("Abgj6", "bitmap6")
312
+            s.draw(0, 0, False)
313
+            s.setText("Abdgj8", "bitmap8")
314
+            s.draw(0, 6 + 2, False)
315
+            s.setText("Ag14", "bitmap14_outline")
316
+            s.draw(0, 6 + 2 + 8 + 1, False)
300 317
         else:
301
-            s.text("Drinks:", "bitmap8", 0)
318
+            s.setText("Drinks:", "bitmap8")
319
+            s.draw()
302 320
 
303 321
     util.loop(t, helper)

+ 2
- 1
qr.py View File

@@ -63,6 +63,7 @@ class QRScreen:
63 63
         if self.heading != None:
64 64
             DrawText = util.getTextDrawer()
65 65
             self.text = DrawText(self.gui, self.c1, self.c2)
66
+            self.text.setText(self.heading, self.font)
66 67
             self.yOff = self.gui.height - self.image.height
67 68
         else:
68 69
             self.yOff = int((self.gui.height - self.image.height) / 2)
@@ -98,7 +99,7 @@ class QRScreen:
98 99
             elif self.font == "tom-thumb":
99 100
                 off = -11
100 101
 
101
-            self.text.text(self.heading, self.font, 0, True, off)
102
+            self.text.draw(0, off)
102 103
 
103 104
         for x in range(0, self.image.width):
104 105
             for y in range(0, self.image.height):

+ 3
- 2
scroll.py View File

@@ -32,7 +32,8 @@ class ScrollText:
32 32
     def setText(self, t, f):
33 33
         self.text = t
34 34
         self.font = f
35
-        self.width = self.drawer.text(self.text, self.font, 0, False)
35
+        self.drawer.setText(t, f)
36
+        self.width, height = self.drawer.getDimensions()
36 37
 
37 38
     def restart(self):
38 39
         self.offset = -self.gui.width
@@ -52,7 +53,7 @@ class ScrollText:
52 53
                 self.offset = -self.gui.width
53 54
                 self.count += 1
54 55
 
55
-        self.drawer.text(self.text, self.font, self.offset, True)
56
+        self.drawer.draw(self.offset)
56 57
 
57 58
 if __name__ == "__main__":
58 59
     import util

+ 20
- 10
tetris.py View File

@@ -41,10 +41,18 @@ class Tetris:
41 41
 
42 42
         DrawText = util.getTextDrawer()
43 43
         self.text = []
44
-        self.text.append(DrawText(self.gui, self.colors[1]))
45
-        self.text.append(DrawText(self.gui, self.colors[0]))
46
-        self.text.append(DrawText(self.gui, self.colors[4]))
47
-        self.text.append(DrawText(self.gui, self.colors[5]))
44
+        self.text.append(DrawText(self.gui, self.colors[1])) # Green, "Score"
45
+        self.text.append(DrawText(self.gui, self.colors[0])) # Pink, Score Number
46
+        self.text.append(DrawText(self.gui, self.colors[4])) # Yellow, "Paused"
47
+        self.text.append(DrawText(self.gui, self.colors[5])) # Blue, "next"
48
+        self.text.append(DrawText(self.gui, self.colors[0])) # Pink, "Tetris"
49
+        self.text.append(DrawText(self.gui, self.colors[5])) # Blue, "up"
50
+        self.text[0].setText("Score:", "tom-thumb")
51
+        self.text[1].setText("0", "tom-thumb")
52
+        self.text[2].setText("Paused", "tom-thumb")
53
+        self.text[3].setText("next", "tom-thumb")
54
+        self.text[4].setText("Tetris", "tom-thumb")
55
+        self.text[5].setText("up", "tom-thumb")
48 56
 
49 57
         # all [y][x] sub-lists must be the same length
50 58
         self.pieces = [
@@ -119,6 +127,7 @@ class Tetris:
119 127
         self.last = time.time()
120 128
         self.button = None
121 129
         self.score = 0
130
+        self.text[1].setText(str(self.score), "tom-thumb")
122 131
         self.done = False
123 132
         self.data = [[self.bg for y in range(self.height)] for x in range(self.width)]
124 133
         self.piece = None
@@ -206,6 +215,7 @@ class Tetris:
206 215
 
207 216
             if had_data and line_full:
208 217
                 self.score += 1
218
+                self.text[1].setText(str(self.score), "tom-thumb")
209 219
 
210 220
                 # move stuff above into this line
211 221
                 for y2 in reversed(range(1, y + 1)):
@@ -336,11 +346,11 @@ class Tetris:
336 346
     def draw_stats(self, off):
337 347
         x_off, y_off = off
338 348
 
339
-        self.text[0].text("Score:", "tom-thumb", -x_off - 2, True, y_off - 11)
340
-        self.text[1].text(str(self.score), "tom-thumb", -x_off - 2, True, y_off - 5)
349
+        self.text[0].draw(-x_off - 2, y_off - 11)
350
+        self.text[1].draw(-x_off - 2, y_off - 5)
341 351
 
342 352
         if self.pause:
343
-            self.text[2].text("Paused", "tom-thumb", -x_off - 2, True, -y_off + 11)
353
+            self.text[2].draw(-x_off - 2, -y_off + 11)
344 354
 
345 355
     def draw(self):
346 356
         if self.input != None:
@@ -370,9 +380,9 @@ class Tetris:
370 380
                 self.endText.restart()
371 381
 
372 382
         # static text
373
-        self.text[1].text("Tetris", "tom-thumb", -2, True, -11)
374
-        self.text[3].text("next", "tom-thumb", -14, True, 5)
375
-        self.text[3].text("up", "tom-thumb", -14, True, 12)
383
+        self.text[4].draw(-2, -11)
384
+        self.text[3].draw(-14, 5)
385
+        self.text[5].draw(-14, 12)
376 386
 
377 387
         # draw play area and border
378 388
         for x in range(-1, self.width + 1):

Loading…
Cancel
Save