SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) { SkScalerContext* ctx = this; unsigned rangeEnd = 0; do { unsigned rangeStart = rangeEnd; rangeEnd += ctx->getGlyphCount(); if (rangeStart <= glyphID && glyphID < rangeEnd) { return ctx->generateGlyphToChar(glyphID - rangeStart); } ctx = ctx->getNextContext(); } while (NULL != ctx); return 0; }
SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, unsigned& glyphID) { SkScalerContext* ctx = this; for (;;) { glyphID = ctx->generateCharToGlyph(uni); if (glyphID) { break; // found it } ctx = ctx->getNextContext(); if (NULL == ctx) { return NULL; } } return ctx; }
/* This loops through all available fallback contexts (if needed) until it finds some context that can handle the unichar and return it. As this is somewhat expensive operation, it should only be done on the first char of a run. */ unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) { SkScalerContext* ctx = this; unsigned glyphID; for (;;) { glyphID = ctx->generateCharToGlyph(uni); if (glyphID) { break; // found it } ctx = ctx->getNextContext(); if (NULL == ctx) { SkDebugf("--- no context for char %x\n", uni); // just return the original context (this) return this->fBaseGlyphCount; } } return ctx->fBaseGlyphCount; }
SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) { unsigned glyphID = glyph.getGlyphID(); SkScalerContext* ctx = this; for (;;) { unsigned count = ctx->getGlyphCount(); if (glyphID < count) { break; } glyphID -= count; ctx = ctx->getNextContext(); if (NULL == ctx) { SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID()); // just return the original context (this) return this; } } return ctx; }
SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, uint16_t* glyphID) { SkScalerContext* ctx = this; for (;;) { const uint16_t glyph = ctx->generateCharToGlyph(uni); if (glyph) { if (NULL != glyphID) { *glyphID = glyph; } break; // found it } ctx = ctx->getNextContext(); if (NULL == ctx) { return NULL; } } return ctx; }
/* This loops through all available fallback contexts (if needed) until it finds some context that can handle the unichar. If all fail, returns 0 */ uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) { SkScalerContext* ctx = this; unsigned glyphID; for (;;) { glyphID = ctx->generateCharToGlyph(uni); if (glyphID) { break; // found it } ctx = ctx->getNextContext(); if (NULL == ctx) { return 0; // no more contexts, return missing glyph } } // add the ctx's base, making glyphID unique for chain of contexts glyphID += ctx->fBaseGlyphCount; // check for overflow of 16bits, since our glyphID cannot exceed that if (glyphID > 0xFFFF) { glyphID = 0; } return SkToU16(glyphID); }