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 } 360519 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 }