のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

NextLogicalFont

 117 static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
    118     // fonthost will determine the next possible font to search, based
    119     // on the current font in fRec. It will return NULL if ctx is our
    120     // last font that can be searched (i.e. ultimate fallback font)
    121 #ifdef SK_BUILD_FOR_ANDROID
    122         // On Android, pass entire rec structure so that clients can change fallback behavior
    123         uint32_t newFontID = SkFontHost::NextLogicalFont(rec);
    124 #else
    125         uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
    126 #endif
    127 
    128     if (0 == newFontID) {
    129         return NULL;
    130     }
    131 
    132     SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
    133     SkDescriptor*       desc = ad.getDesc();
    134 
    135     desc->init();
    136     SkScalerContext::Rec* newRec =
    137     (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
    138                                           sizeof(rec), &rec);
    139     newRec->fFontID = newFontID;
    140     desc->computeChecksum();
    141 
    142     return SkFontHost::CreateScalerContext(desc);
    143 }
    148 SkScalerContext* SkScalerContext::getNextContext() {
    149     SkScalerContext* next = fNextContext;
    150     // if next is null, then either it isn't cached yet, or we're at the
    151     // end of our possible chain
    152     if (NULL == next) {
    153         next = allocNextContext(fRec); <===================================
    154         if (NULL == next) {
    155             return NULL;
    156         }
    157         // next's base is our base + our local count
    158         next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
    159         // cache the answer
    160         fNextContext = next;
    161     }
    162     return next;
    163 }
  165 SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, unsigned& glyphID) {
    166     SkScalerContext* ctx = this;
    167     for (;;) {
    168         glyphID = ctx->generateCharToGlyph(uni);
    169         if (glyphID) {
    170             break;  // found it
    171         }
    172         ctx = ctx->getNextContext(); <===============================
    173         if (NULL == ctx) {
    174             return NULL;
    175         }
    176     }
    177     return ctx;
    178 }
   180 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
    181     unsigned glyphID = glyph.getGlyphID();
    182     SkScalerContext* ctx = this;
    183     for (;;) {
    184         unsigned count = ctx->getGlyphCount();
    185         if (glyphID < count) {
    186             break;
    187         }
    188         glyphID -= count;
    189         ctx = ctx->getNextContext(); <===============================
    190         if (NULL == ctx) {
    191             SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
    192             // just return the original context (this)
    193             return this;
    194         }
    195     }
    196     return ctx;
    197 }
    247 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
    248     SkScalerContext* ctx = this;
    249     unsigned rangeEnd = 0;
    250     do {
    251         unsigned rangeStart = rangeEnd;
    252 
    253         rangeEnd += ctx->getGlyphCount();
    254         if (rangeStart <= glyphID && glyphID < rangeEnd) {
    255             return ctx->generateGlyphToChar(glyphID - rangeStart);
    256         }
    257         ctx = ctx->getNextContext(); <===============================
    258     } while (NULL != ctx);
    259     return 0;
    260 }

getGlyphContext()

    262 void SkScalerContext::getAdvance(SkGlyph* glyph) {
    263     // mark us as just having a valid advance
    264     glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
    265     // we mark the format before making the call, in case the impl
    266     // internally ends up calling its generateMetrics, which is OK
    267     // albeit slower than strictly necessary
    268     this->getGlyphContext(*glyph)->generateAdvance(glyph); <============
    269 }
    271 void SkScalerContext::getMetrics(SkGlyph* glyph) {
    272     this->getGlyphContext(*glyph)->generateMetrics(glyph); <============
    273 
    274     // for now we have separate cache entries for devkerning on and off
    275     // in the future we might share caches, but make our measure/draw
    276     // code make the distinction. Thus we zap the values if the caller
    277     // has not asked for them.
    278     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
    279         // no devkern, so zap the fields
    280         glyph->fLsbDelta = glyph->fRsbDelta = 0;
    281     }
    282 
    283     // if either dimension is empty, zap the image bounds of the glyph
    284     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
    285         glyph->fWidth   = 0;
    286         glyph->fHeight  = 0;
    287         glyph->fTop     = 0;
    288         glyph->fLeft    = 0;
    289         glyph->fMaskFormat = 0;
    290         return;
    291     }
    292 
    293     if (fGenerateImageFromPath) {
    294         SkPath      devPath, fillPath;
    295         SkMatrix    fillToDevMatrix;
    296 
    297         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    298 
    299         if (fRasterizer) {
    300             SkMask  mask;
    301 
    302             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    303                                        fMaskFilter, &mask,
    304                                        SkMask::kJustComputeBounds_CreateMode)) {
    305                 glyph->fLeft    = mask.fBounds.fLeft;
    306                 glyph->fTop     = mask.fBounds.fTop;
    307                 glyph->fWidth   = SkToU16(mask.fBounds.width());
    308                 glyph->fHeight  = SkToU16(mask.fBounds.height());
    309             } else {
    310                 goto SK_ERROR;
    311             }
    312         } else {
    313             // just use devPath
    314             SkIRect ir;
    315             devPath.getBounds().roundOut(&ir);
    316 
    317             if (ir.isEmpty() || !ir.is16Bit()) {
    318                 goto SK_ERROR;
    319             }
    320             glyph->fLeft    = ir.fLeft;
    321             glyph->fTop     = ir.fTop;
    322             glyph->fWidth   = SkToU16(ir.width());
    323             glyph->fHeight  = SkToU16(ir.height());
    324         }
    325     }
    326 
    327 	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
    328 		glyph->fMaskFormat = fRec.fMaskFormat;
    329 	}
    330 
    331     if (fMaskFilter) {
    332         SkMask      src, dst;
    333         SkMatrix    matrix;
    334 
    335         glyph->toMask(&src);
    336         fRec.getMatrixFrom2x2(&matrix);
    337 
    338         src.fImage = NULL;  // only want the bounds from the filter
    339         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
    340             SkASSERT(dst.fImage == NULL);
    341             glyph->fLeft    = dst.fBounds.fLeft;
    342             glyph->fTop     = dst.fBounds.fTop;
    343             glyph->fWidth   = SkToU16(dst.fBounds.width());
    344             glyph->fHeight  = SkToU16(dst.fBounds.height());
    345             glyph->fMaskFormat = dst.fFormat;
    346         }
    347     }
    348     return;
    349 
    350 SK_ERROR:
    351     // draw nothing 'cause we failed
    352     glyph->fLeft    = 0;
    353     glyph->fTop     = 0;
    354     glyph->fWidth   = 0;
    355     glyph->fHeight  = 0;
    356     // put a valid value here, in case it was earlier set to
    357     // MASK_FORMAT_JUST_ADVANCE
    358     glyph->fMaskFormat = fRec.fMaskFormat;
    359 }
    360 
    519 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
    520     const SkGlyph*  glyph = &origGlyph;
    521     SkGlyph         tmpGlyph;
    522 
    523     if (fMaskFilter) {   // restore the prefilter bounds
    524         tmpGlyph.init(origGlyph.fID);
    525 
    526         // need the original bounds, sans our maskfilter
    527         SkMaskFilter* mf = fMaskFilter;
    528         fMaskFilter = NULL;             // temp disable
    529         this->getMetrics(&tmpGlyph);
    530         fMaskFilter = mf;               // restore
    531 
    532         tmpGlyph.fImage = origGlyph.fImage;
    533 
    534         // we need the prefilter bounds to be <= filter bounds
    535         SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
    536         SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
    537         glyph = &tmpGlyph;
    538     }
    539 
    540     if (fGenerateImageFromPath) {
    541         SkPath      devPath, fillPath;
    542         SkMatrix    fillToDevMatrix;
    543         SkMask      mask;
    544 
    545         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    546         glyph->toMask(&mask);
    547 
    548         if (fRasterizer) {
    549             mask.fFormat = SkMask::kA8_Format;
    550             sk_bzero(glyph->fImage, mask.computeImageSize());
    551 
    552             if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    553                                         fMaskFilter, &mask,
    554                                         SkMask::kJustRenderImage_CreateMode)) {
    555                 return;
    556             }
    557         } else {
    558             generateMask(mask, devPath);
    559         }
    560     } else {
    561         this->getGlyphContext(*glyph)->generateImage(*glyph); <======================
    562     }
    563 
    564     if (fMaskFilter) {
    565         SkMask      srcM, dstM;
    566         SkMatrix    matrix;
    567 
    568         // the src glyph image shouldn't be 3D
    569         SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
    570         glyph->toMask(&srcM);
    571         fRec.getMatrixFrom2x2(&matrix);
    572 
    573         if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
    574             int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
    575             int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
    576             int dstRB = origGlyph.rowBytes();
    577             int srcRB = dstM.fRowBytes;
    578 
    579             const uint8_t* src = (const uint8_t*)dstM.fImage;
    580             uint8_t* dst = (uint8_t*)origGlyph.fImage;
    581 
    582             if (SkMask::k3D_Format == dstM.fFormat) {
    583                 // we have to copy 3 times as much
    584                 height *= 3;
    585             }
    586 
    587             // clean out our glyph, since it may be larger than dstM
    588             //sk_bzero(dst, height * dstRB);
    589 
    590             while (--height >= 0) {
    591                 memcpy(dst, src, width);
    592                 src += srcRB;
    593                 dst += dstRB;
    594             }
    595             SkMask::FreeImage(dstM.fImage);
    596         }
    597     }
    598 }
    614 
    615 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    616                                   SkPath* devPath, SkMatrix* fillToDevMatrix) {
    617     SkPath  path;
    618 
    619     this->getGlyphContext(glyph)->generatePath(glyph, &path); <====================
    620 
    621     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
    622         SkFixed dx = glyph.getSubXFixed();
    623         SkFixed dy = glyph.getSubYFixed();
    624         if (dx | dy) {
    625             path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
    626         }
    627     }
    628 
    629     if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
    630         // need the path in user-space, with only the point-size applied
    631         // so that our stroking and effects will operate the same way they
    632         // would if the user had extracted the path themself, and then
    633         // called drawPath
    634         SkPath      localPath;
    635         SkMatrix    matrix, inverse;
    636 
    637         fRec.getMatrixFrom2x2(&matrix);
    638         matrix.invert(&inverse);
    639         path.transform(inverse, &localPath);
    640         // now localPath is only affected by the paint settings, and not the canvas matrix
    641 
    642         SkScalar width = fRec.fFrameWidth;
    643 
    644         if (fPathEffect) {
    645             SkPath effectPath;
    646 
    647             if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
    648                 localPath.swap(effectPath);
    649             }
    650         }
    651 
    652         if (width > 0) {
    653             SkStroke    stroker;
    654             SkPath      outline;
    655 
    656             stroker.setWidth(width);
    657             stroker.setMiterLimit(fRec.fMiterLimit);
    658             stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
    659             stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
    660             stroker.strokePath(localPath, &outline);
    661             localPath.swap(outline);
    662         }
    663 
    664         // now return stuff to the caller
    665         if (fillToDevMatrix) {
    666             *fillToDevMatrix = matrix;
    667         }
    668         if (devPath) {
    669             localPath.transform(matrix, devPath);
    670         }
    671         if (fillPath) {
    672             fillPath->swap(localPath);
    673         }
    674     } else {   // nothing tricky to do
    675         if (fillToDevMatrix) {
    676             fillToDevMatrix->reset();
    677         }
    678         if (devPath) {
    679             if (fillPath == NULL) {
    680                 devPath->swap(path);
    681             } else {
    682                 *devPath = path;
    683             }
    684         }
    685 
    686         if (fillPath) {
    687             fillPath->swap(path);
    688         }
    689     }
    690 
    691     if (devPath) {
    692         devPath->updateBoundsCache();
    693     }
    694     if (fillPath) {
    695         fillPath->updateBoundsCache();
    696     }
    697 }