11import std/ [os, posix, strutils]
22import nimPNG
33
4- import ../ common/ [fb, process]
5- import stb_truetype
4+ import common/ [fb, process]
5+ import common / ffi / stb_truetype
66
77const
88 ScreenWidth = 320
@@ -26,17 +26,6 @@ proc fromRGB565(pixel: uint16, r, g, b: var uint8) {.inline.} =
2626 g = SixToEight [(pixel shr 5 ) and 0x 3F ]
2727 b = FiveToEight [pixel and 0x 1F ]
2828
29- proc setPixel (fb: ptr UncheckedArray [uint16 ], x, y: int , color: uint16 ) {.inline .} =
30- if x >= 0 and x < ScreenWidth and y >= 0 and y < ScreenHeight :
31- let fbIdx = RowOffsets [RotationXMap [x]] + y
32- fb[fbIdx] = color
33-
34- proc getPixel (fb: ptr UncheckedArray [uint16 ], x, y: int ): uint16 {.inline .} =
35- if x >= 0 and x < SCREEN_WIDTH and y >= 0 and y < SCREEN_HEIGHT :
36- let fbIdx = RowOffsets [RotationXMap [x]] + y
37- return fb[fbIdx]
38- return 0
39-
4029proc loadFont (path: string ): seq [byte ] =
4130 let f = open (path, fmRead)
4231 defer : f.close ()
@@ -88,38 +77,50 @@ proc renderTextLine(fb: ptr UncheckedArray[uint16], font: ptr stbtt_fontinfo,
8877 var cr, cg, cb: uint8
8978 fromRGB565 (color, cr, cg, cb)
9079
80+ var bitmapBuf = newSeqUninit [byte ](64 * 64 )
81+
9182 for i, ch in text:
9283 var ix0, iy0, ix1, iy1: cint
9384 stbtt_GetCodepointBitmapBox (font, cint (ch), scale, scale,
9485 addr ix0, addr iy0, addr ix1, addr iy1)
95-
9686 let w = ix1 - ix0
9787 let h = iy1 - iy0
9888
9989 if w > 0 and h > 0 :
100- var bitmap = newSeqUninit [byte ](w * h)
101- stbtt_MakeCodepointBitmap (font, cast [ptr UncheckedArray [byte ]](addr bitmap[0 ]),
102- w, h, w, scale, scale, cint (ch))
103-
104- {.push checks :off .}
105- for by in 0 ..< h:
106- for bx in 0 ..< w:
107- let alpha = bitmap[by * w + bx]
108- if alpha > 0 :
109- let px = x + int (ix0) + bx
110- let py = baseline + int (iy0) + by
111-
112- if px >= 0 and px < ScreenWidth and py >= 0 and py < ScreenHeight :
113- let bgPixel = getPixel (fb, px, py)
114-
115- var bgR, bgG, bgB: uint8
116- fromRGB565 (bgPixel, bgR, bgG, bgB)
117-
118- let newR = uint8 ((uint16 (cr) * alpha + uint16 (bgR) * (255 - alpha)) div 255 )
119- let newG = uint8 ((uint16 (cg) * alpha + uint16 (bgG) * (255 - alpha)) div 255 )
120- let newB = uint8 ((uint16 (cb) * alpha + uint16 (bgB) * (255 - alpha)) div 255 )
121-
122- setPixel (fb, px, py, toRGB565 (newR, newG, newB))
90+ let needed = w * h
91+ if needed > bitmapBuf.len:
92+ bitmapBuf.setLen (needed)
93+
94+ stbtt_MakeCodepointBitmap (font,
95+ cast [ptr UncheckedArray [byte ]](addr bitmapBuf[0 ]),
96+ w, h, w, scale, scale, cint (ch))
97+
98+ let charX = x + int (ix0)
99+ let charY = baseline + int (iy0)
100+
101+ {.push checks : off .}
102+ for bx in 0 ..< w:
103+ let px = charX + bx
104+ if px < 0 or px >= ScreenWidth : continue
105+ let fbBase = FbXBase [px]
106+
107+ for by in 0 ..< h:
108+ let alpha = bitmapBuf[by * w + bx]
109+ if alpha == 0 : continue
110+ let py = charY + by
111+ if py < 0 or py >= ScreenHeight : continue
112+
113+ if alpha == 255 :
114+ fb[fbBase + py] = color
115+ else :
116+ let bgPixel = fb[fbBase + py]
117+ var bgR, bgG, bgB: uint8
118+ fromRGB565 (bgPixel, bgR, bgG, bgB)
119+ let inv = 255 'u32 - uint32 (alpha)
120+ let newR = uint8 ((uint32 (cr) * uint32 (alpha) + uint32 (bgR) * inv) div 255 )
121+ let newG = uint8 ((uint32 (cg) * uint32 (alpha) + uint32 (bgG) * inv) div 255 )
122+ let newB = uint8 ((uint32 (cb) * uint32 (alpha) + uint32 (bgB) * inv) div 255 )
123+ fb[fbBase + py] = toRGB565 (newR, newG, newB)
123124 {.pop .}
124125
125126 var advanceWidth, leftSideBearing: cint
@@ -168,7 +169,7 @@ proc display*(text: string,
168169 let g = png.data[srcIdx + 1 ]
169170 let b = png.data[srcIdx + 2 ]
170171 srcIdx += 4
171- fb[RowOffsets [ RotationXMap [lx] ] + ly] = toRGB565 (r.uint8 , g.uint8 , b.uint8 )
172+ fb[FbXBase [lx ] + ly] = toRGB565 (r.uint8 , g.uint8 , b.uint8 )
172173
173174 if not fileExists (fontPath):
174175 raise newException (IOError , " display: font file not found: " & fontPath)
0 commit comments