MCPcopy Create free account
hub / github.com/crosspoint-reader/crosspoint-reader / renderCharScaled

Function renderCharScaled

lib/GfxRenderer/GfxRenderer.cpp:148–213  ·  view source on GitHub ↗

Shared glyph rendering logic for normal and rotated text. Coordinate mapping and cursor advance direction are selected at compile time via the template parameter. Render a glyph at 50% scale. Used for SUP/SUB style bits. Each destination pixel represents a 2x2 source block. Drawing when that block contains ink preserves thin strokes that nearest-neighbor sampling can skip. The advance width is a

Source from the content-addressed store, hash-verified

146// The advance width is also halved in drawText() so layout reserves exactly the right
147// horizontal space for the scaled glyph.
148static void renderCharScaled(const GfxRenderer& renderer, GfxRenderer::RenderMode renderMode,
149 const EpdFontFamily& fontFamily, const uint32_t cp, int cursorX, int cursorY,
150 const bool pixelState, const EpdFontFamily::Style style) {
151 const EpdGlyph* glyph = fontFamily.getGlyph(cp, style);
152 if (!glyph) return;
153
154 const EpdFontData* fontData = fontFamily.getData(style);
155 const uint8_t* bitmap = renderer.getGlyphBitmap(fontData, glyph);
156 if (!bitmap) return;
157
158 const int srcW = glyph->width;
159 const int srcH = glyph->height;
160 const int dstW = (srcW + 1) / 2; // ceil so odd-width glyphs aren't clipped
161 const int dstH = (srcH + 1) / 2;
162 // Scale the glyph bearing by the same factor so the scaled glyph sits at the correct
163 // pixel offset from the (already-shifted) cursor position.
164 const int baseX = cursorX + glyph->left / 2;
165 const int baseY = cursorY - glyph->top / 2;
166
167 if (fontData->is2Bit) {
168 // 2-bit packed format: 4 pixels per byte, MSB first, 2 bits per pixel.
169 // raw value: 0=white, 1=light-gray, 2=dark-gray, 3=black.
170 for (int dstY = 0; dstY < dstH; dstY++) {
171 const int srcY = dstY * 2;
172 for (int dstX = 0; dstX < dstW; dstX++) {
173 const int srcX = dstX * 2;
174 uint8_t coverage = 0;
175 uint8_t maxRaw = 0;
176 for (int sampleY = 0; sampleY < 2 && srcY + sampleY < srcH; sampleY++) {
177 for (int sampleX = 0; sampleX < 2 && srcX + sampleX < srcW; sampleX++) {
178 const int pos = (srcY + sampleY) * srcW + srcX + sampleX;
179 const uint8_t byte = bitmap[pos >> 2];
180 const uint8_t raw = (byte >> ((3 - (pos & 3)) * 2)) & 0x3;
181 coverage += raw;
182 if (raw > maxRaw) maxRaw = raw;
183 }
184 }
185 if (maxRaw >= 2 || coverage >= 2) {
186 renderer.drawPixel(baseX + dstX, baseY + dstY, pixelState);
187 }
188 }
189 }
190 } else {
191 // 1-bit packed format: 8 pixels per byte, MSB first.
192 for (int dstY = 0; dstY < dstH; dstY++) {
193 const int srcY = dstY * 2;
194 for (int dstX = 0; dstX < dstW; dstX++) {
195 const int srcX = dstX * 2;
196 bool hasInk = false;
197 for (int sampleY = 0; sampleY < 2 && srcY + sampleY < srcH; sampleY++) {
198 for (int sampleX = 0; sampleX < 2 && srcX + sampleX < srcW; sampleX++) {
199 const int pos = (srcY + sampleY) * srcW + srcX + sampleX;
200 const uint8_t byte = bitmap[pos >> 3];
201 const uint8_t bit = 7 - (pos & 7);
202 if ((byte >> bit) & 1) {
203 hasInk = true;
204 }
205 }

Callers 1

drawTextMethod · 0.85

Calls 4

getDataMethod · 0.80
getGlyphBitmapMethod · 0.80
drawPixelMethod · 0.80
getGlyphMethod · 0.45

Tested by

no test coverage detected