MCPcopy Index your code
hub / github.com/crosspoint-reader/crosspoint-reader / buildMiniKernMatrix

Method buildMiniKernMatrix

lib/EpdFont/SdCardFont.cpp:265–394  ·  view source on GitHub ↗

Build a small per-page kern matrix containing ONLY the (leftClass, rightClass) pairs reachable from codepoints in the current text. Class IDs are renumbered to a dense 1..N range so the resulting matrix is usedLeft × usedRight (typical Latin page: ~25×25 bytes) instead of the font's full ~180×200 (~36KB). Correctness: EpdFont::getKerning only touches `kernLeftClasses` / `kernRightClasses` / `kern

Source from the content-addressed store, hash-verified

263// on this page simply returns class 0 (no kerning), which was the pre-existing
264// behavior for any codepoint outside the kern classes.
265bool SdCardFont::buildMiniKernMatrix(PerStyle& s, const uint32_t* codepoints, uint32_t cpCount) {
266 freeStyleMiniKern(s);
267 if (!s.kernLeftClasses || !s.kernRightClasses || s.header.kernLeftEntryCount == 0 ||
268 s.header.kernRightEntryCount == 0) {
269 return true; // font has no kern classes — nothing to build
270 }
271
272 // Step 1: mark used left/right classes via a 256-wide bitmap (class IDs are uint8_t).
273 bool usedLeft[256] = {};
274 bool usedRight[256] = {};
275 for (uint32_t i = 0; i < cpCount; i++) {
276 uint8_t lc = miniLookupKernClass(s.kernLeftClasses, s.header.kernLeftEntryCount, codepoints[i]);
277 if (lc) usedLeft[lc] = true;
278 uint8_t rc = miniLookupKernClass(s.kernRightClasses, s.header.kernRightEntryCount, codepoints[i]);
279 if (rc) usedRight[rc] = true;
280 }
281
282 // Step 2: build renumber maps (oldClassId -> newClassId, 1-based) and
283 // reverse maps (newClassId -> oldClassId) for the SD read step.
284 uint8_t leftRenumber[256] = {};
285 uint8_t rightRenumber[256] = {};
286 uint8_t newToOldLeft[256] = {};
287 uint8_t newToOldRight[256] = {};
288 uint8_t numLeft = 0, numRight = 0;
289 for (int i = 1; i < 256; i++) {
290 if (usedLeft[i]) {
291 numLeft++;
292 leftRenumber[i] = numLeft;
293 newToOldLeft[numLeft] = static_cast<uint8_t>(i);
294 }
295 if (usedRight[i]) {
296 numRight++;
297 rightRenumber[i] = numRight;
298 newToOldRight[numRight] = static_cast<uint8_t>(i);
299 }
300 }
301 if (numLeft == 0 || numRight == 0) {
302 return true; // no kern pairs applicable on this page
303 }
304
305 // Step 3: count how many codepoint→classId entries the mini class tables need.
306 // Each resident class table has one entry per kerned codepoint in the page.
307 uint16_t miniLeftCount = 0;
308 uint16_t miniRightCount = 0;
309 for (uint32_t i = 0; i < cpCount; i++) {
310 if (miniLookupKernClass(s.kernLeftClasses, s.header.kernLeftEntryCount, codepoints[i]) != 0) miniLeftCount++;
311 if (miniLookupKernClass(s.kernRightClasses, s.header.kernRightEntryCount, codepoints[i]) != 0) miniRightCount++;
312 }
313
314 // Step 4: allocate the three mini buffers. The matrix is <1KB in practice
315 // (<30 × <30 × 1 byte) so fragmentation is a non-issue.
316 const uint32_t matrixBytes = static_cast<uint32_t>(numLeft) * numRight;
317 s.miniKernLeftClasses = new (std::nothrow) EpdKernClassEntry[miniLeftCount];
318 s.miniKernRightClasses = new (std::nothrow) EpdKernClassEntry[miniRightCount];
319 s.miniKernMatrix = new (std::nothrow) int8_t[matrixBytes];
320 if (!s.miniKernLeftClasses || !s.miniKernRightClasses || !s.miniKernMatrix) {
321 LOG_ERR("SDCF", "Failed to allocate mini kern (%u+%u+%u bytes)", miniLeftCount * 3u, miniRightCount * 3u,
322 matrixBytes);

Callers

nothing calls this directly

Calls 5

miniLookupKernClassFunction · 0.85
openFileForReadMethod · 0.80
seekSetMethod · 0.80
getMethod · 0.80
readMethod · 0.45

Tested by

no test coverage detected