aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkScalerContext.cpp
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-17 17:59:53 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-17 17:59:53 +0000
commita14ea0e930c82daa2364ece4bd0b06256272302a (patch)
tree425f401e5731ead3050590fcc878ea49d006aaab /src/core/SkScalerContext.cpp
parent452f844f64d97e0f54b9258b800755686193136e (diff)
Simplify font-chaining (fallbacks) to have fonthost just return the next
logical fontID. Extend ImageRef to accept an imagedecoder factory, to replace calling the std one. git-svn-id: http://skia.googlecode.com/svn/trunk@125 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkScalerContext.cpp')
-rw-r--r--src/core/SkScalerContext.cpp131
1 files changed, 75 insertions, 56 deletions
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index bbcc1308c1..8f84cbba9c 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -95,7 +95,7 @@ SkScalerContext::SkScalerContext(const SkDescriptor* desc)
}
fBaseGlyphCount = 0;
- fAuxScalerContext = NULL;
+ fNextContext = NULL;
const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
SkASSERT(rec);
@@ -121,78 +121,97 @@ SkScalerContext::SkScalerContext(const SkDescriptor* desc)
}
SkScalerContext::~SkScalerContext() {
+ SkDELETE(fNextContext);
+
fPathEffect->safeUnref();
fMaskFilter->safeUnref();
fRasterizer->safeUnref();
-
- SkDELETE(fAuxScalerContext);
}
-SkScalerContext* SkScalerContext::loadAuxContext() const {
- if (NULL == fAuxScalerContext) {
- fAuxScalerContext = SkFontHost::CreateFallbackScalerContext(fRec);
- if (NULL != fAuxScalerContext) {
- fAuxScalerContext->setBaseGlyphCount(this->getGlyphCount());
- }
+static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
+ // fonthost will determine the next possible font to search, based
+ // on the current font in fRec. It will return NULL if ctx is our
+ // last font that can be searched (i.e. ultimate fallback font)
+ uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID);
+ if (0 == newFontID) {
+ return NULL;
}
- return fAuxScalerContext;
-}
-#ifdef TRACK_MISSING_CHARS
- static uint8_t gMissingChars[1 << 13];
-#endif
+ SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
+ SkDescriptor* desc = ad.getDesc();
-uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
- unsigned glyphID = this->generateCharToGlyph(uni);
-
- if (0 == glyphID) { // try auxcontext
- SkScalerContext* ctx = this->loadAuxContext();
- if (NULL != ctx) {
- glyphID = ctx->generateCharToGlyph(uni);
- if (0 != glyphID) { // only fiddle with it if its not missing
- glyphID += this->getGlyphCount();
- if (glyphID > 0xFFFF) {
- glyphID = 0;
- }
- }
+ desc->init();
+ SkScalerContext::Rec* newRec =
+ (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
+ sizeof(rec), &rec);
+ newRec->fFontID = newFontID;
+ desc->computeChecksum();
+
+ return SkFontHost::CreateScalerContext(desc);
+}
+
+/* Return the next context, creating it if its not already created, but return
+ NULL if the fonthost says there are no more fonts to fallback to.
+ */
+SkScalerContext* SkScalerContext::getNextContext() {
+ SkScalerContext* next = fNextContext;
+ // if next is null, then either it isn't cached yet, or we're at the
+ // end of our possible chain
+ if (NULL == next) {
+ next = allocNextContext(fRec);
+ if (NULL == next) {
+ return NULL;
}
+ // next's base is our base + our local count
+ next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
+ // cache the answer
+ fNextContext = next;
}
-#ifdef TRACK_MISSING_CHARS
- if (0 == glyphID) {
- bool announce = false;
- if (uni > 0xFFFF) { // we don't record these
- announce = true;
- } else {
- unsigned index = uni >> 3;
- unsigned mask = 1 << (uni & 7);
- SkASSERT(index < SK_ARRAY_COUNT(gMissingChars));
- if ((gMissingChars[index] & mask) == 0) {
- gMissingChars[index] |= mask;
- announce = true;
- }
+ return next;
+}
+
+SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
+ unsigned glyphID = glyph.getGlyphID();
+ SkScalerContext* ctx = this;
+ for (;;) {
+ unsigned count = ctx->getGlyphCount();
+ if (glyphID < count) {
+ break;
}
- if (announce) {
- printf(">>> MISSING CHAR <<< 0x%04X\n", uni);
+ 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;
}
}
-#endif
- return SkToU16(glyphID);
+ return ctx;
}
-/* Internal routine to resolve auxContextID into a real context.
- Only makes sense to call once the glyph has been given a
- valid auxGlyphID.
-*/
-SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) const {
- SkScalerContext* ctx = const_cast<SkScalerContext*>(this);
-
- if (glyph.getGlyphID() >= this->getGlyphCount()) {
- ctx = this->loadAuxContext();
- if (NULL == ctx) { // if no aux, just return us
- ctx = const_cast<SkScalerContext*>(this);
+/* 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
}
}
- return ctx;
+ // 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);
}
void SkScalerContext::getAdvance(SkGlyph* glyph) {