• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkScalerContext.h"
11 #include "SkColorPriv.h"
12 #include "SkDescriptor.h"
13 #include "SkDraw.h"
14 #include "SkFontHost.h"
15 #include "SkMaskFilter.h"
16 #include "SkPathEffect.h"
17 #include "SkRasterizer.h"
18 #include "SkRasterClip.h"
19 #include "SkStroke.h"
20 #include "SkThread.h"
21 
22 #define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
23 
toMask(SkMask * mask) const24 void SkGlyph::toMask(SkMask* mask) const {
25     SkASSERT(mask);
26 
27     mask->fImage = (uint8_t*)fImage;
28     mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
29     mask->fRowBytes = this->rowBytes();
30     mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
31 }
32 
computeImageSize() const33 size_t SkGlyph::computeImageSize() const {
34     const size_t size = this->rowBytes() * fHeight;
35 
36     switch (fMaskFormat) {
37         case SkMask::k3D_Format:
38             return 3 * size;
39         default:
40             return size;
41     }
42 }
43 
zeroMetrics()44 void SkGlyph::zeroMetrics() {
45     fAdvanceX = 0;
46     fAdvanceY = 0;
47     fWidth    = 0;
48     fHeight   = 0;
49     fTop      = 0;
50     fLeft     = 0;
51     fRsbDelta = 0;
52     fLsbDelta = 0;
53 }
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 
57 #ifdef SK_DEBUG
58     #define DUMP_RECx
59 #endif
60 
load_flattenable(const SkDescriptor * desc,uint32_t tag)61 static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
62     SkFlattenable*  obj = NULL;
63     uint32_t        len;
64     const void*     data = desc->findEntry(tag, &len);
65 
66     if (data) {
67         SkFlattenableReadBuffer   buffer(data, len);
68         obj = buffer.readFlattenable();
69         SkASSERT(buffer.offset() == buffer.size());
70     }
71     return obj;
72 }
73 
SkScalerContext(const SkDescriptor * desc)74 SkScalerContext::SkScalerContext(const SkDescriptor* desc)
75     : fPathEffect(NULL), fMaskFilter(NULL)
76 {
77     fBaseGlyphCount = 0;
78     fNextContext = NULL;
79 
80     const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
81     SkASSERT(rec);
82 
83     fRec = *rec;
84 
85 #ifdef DUMP_REC
86     desc->assertChecksum();
87     SkDebugf("SkScalarContext checksum %x count %d length %d\n",
88              desc->getChecksum(), desc->getCount(), desc->getLength());
89     SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
90         rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
91         rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
92     SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
93         rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
94         rec->fMaskFormat, rec->fStrokeJoin);
95     SkDebugf("  pathEffect %x maskFilter %x\n",
96              desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
97         desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
98 #endif
99 
100     fPathEffect = (SkPathEffect*)load_flattenable(desc, kPathEffect_SkDescriptorTag);
101     fMaskFilter = (SkMaskFilter*)load_flattenable(desc, kMaskFilter_SkDescriptorTag);
102     fRasterizer = (SkRasterizer*)load_flattenable(desc, kRasterizer_SkDescriptorTag);
103 
104     // initialize based on our settings. subclasses can also force this
105     fGenerateImageFromPath = fRec.fFrameWidth > 0 || fPathEffect != NULL ||
106                              fRasterizer != NULL;
107 }
108 
~SkScalerContext()109 SkScalerContext::~SkScalerContext() {
110     SkDELETE(fNextContext);
111 
112     SkSafeUnref(fPathEffect);
113     SkSafeUnref(fMaskFilter);
114     SkSafeUnref(fRasterizer);
115 }
116 
allocNextContext(const SkScalerContext::Rec & rec)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     uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
122     if (0 == newFontID) {
123         return NULL;
124     }
125 
126     SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
127     SkDescriptor*       desc = ad.getDesc();
128 
129     desc->init();
130     SkScalerContext::Rec* newRec =
131     (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
132                                           sizeof(rec), &rec);
133     newRec->fFontID = newFontID;
134     desc->computeChecksum();
135 
136     return SkFontHost::CreateScalerContext(desc);
137 }
138 
139 /*  Return the next context, creating it if its not already created, but return
140     NULL if the fonthost says there are no more fonts to fallback to.
141  */
getNextContext()142 SkScalerContext* SkScalerContext::getNextContext() {
143     SkScalerContext* next = fNextContext;
144     // if next is null, then either it isn't cached yet, or we're at the
145     // end of our possible chain
146     if (NULL == next) {
147         next = allocNextContext(fRec);
148         if (NULL == next) {
149             return NULL;
150         }
151         // next's base is our base + our local count
152         next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
153         // cache the answer
154         fNextContext = next;
155     }
156     return next;
157 }
158 
getGlyphContext(const SkGlyph & glyph)159 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
160     unsigned glyphID = glyph.getGlyphID();
161     SkScalerContext* ctx = this;
162     for (;;) {
163         unsigned count = ctx->getGlyphCount();
164         if (glyphID < count) {
165             break;
166         }
167         glyphID -= count;
168         ctx = ctx->getNextContext();
169         if (NULL == ctx) {
170             SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
171             // just return the original context (this)
172             return this;
173         }
174     }
175     return ctx;
176 }
177 
178 #ifdef SK_BUILD_FOR_ANDROID
179 /*  This loops through all available fallback contexts (if needed) until it
180     finds some context that can handle the unichar and return it.
181 
182     As this is somewhat expensive operation, it should only be done on the first
183     char of a run.
184  */
getBaseGlyphCount(SkUnichar uni)185 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
186     SkScalerContext* ctx = this;
187     unsigned glyphID;
188     for (;;) {
189         glyphID = ctx->generateCharToGlyph(uni);
190         if (glyphID) {
191             break;  // found it
192         }
193         ctx = ctx->getNextContext();
194         if (NULL == ctx) {
195             SkDebugf("--- no context for char %x\n", uni);
196             // just return the original context (this)
197             return this->fBaseGlyphCount;
198         }
199     }
200     return ctx->fBaseGlyphCount;
201 }
202 #endif
203 
204 /*  This loops through all available fallback contexts (if needed) until it
205     finds some context that can handle the unichar. If all fail, returns 0
206  */
charToGlyphID(SkUnichar uni)207 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
208     SkScalerContext* ctx = this;
209     unsigned glyphID;
210     for (;;) {
211         glyphID = ctx->generateCharToGlyph(uni);
212         if (glyphID) {
213             break;  // found it
214         }
215         ctx = ctx->getNextContext();
216         if (NULL == ctx) {
217             return 0;   // no more contexts, return missing glyph
218         }
219     }
220     // add the ctx's base, making glyphID unique for chain of contexts
221     glyphID += ctx->fBaseGlyphCount;
222     // check for overflow of 16bits, since our glyphID cannot exceed that
223     if (glyphID > 0xFFFF) {
224         glyphID = 0;
225     }
226     return SkToU16(glyphID);
227 }
228 
glyphIDToChar(uint16_t glyphID)229 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
230     SkScalerContext* ctx = this;
231     unsigned rangeEnd = 0;
232     do {
233         unsigned rangeStart = rangeEnd;
234 
235         rangeEnd += ctx->getGlyphCount();
236         if (rangeStart <= glyphID && glyphID < rangeEnd) {
237             return ctx->generateGlyphToChar(glyphID - rangeStart);
238         }
239         ctx = ctx->getNextContext();
240     } while (NULL != ctx);
241     return 0;
242 }
243 
getAdvance(SkGlyph * glyph)244 void SkScalerContext::getAdvance(SkGlyph* glyph) {
245     // mark us as just having a valid advance
246     glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
247     // we mark the format before making the call, in case the impl
248     // internally ends up calling its generateMetrics, which is OK
249     // albeit slower than strictly necessary
250     this->getGlyphContext(*glyph)->generateAdvance(glyph);
251 }
252 
getMetrics(SkGlyph * glyph)253 void SkScalerContext::getMetrics(SkGlyph* glyph) {
254     this->getGlyphContext(*glyph)->generateMetrics(glyph);
255 
256     // for now we have separate cache entries for devkerning on and off
257     // in the future we might share caches, but make our measure/draw
258     // code make the distinction. Thus we zap the values if the caller
259     // has not asked for them.
260     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
261         // no devkern, so zap the fields
262         glyph->fLsbDelta = glyph->fRsbDelta = 0;
263     }
264 
265     // if either dimension is empty, zap the image bounds of the glyph
266     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
267         glyph->fWidth   = 0;
268         glyph->fHeight  = 0;
269         glyph->fTop     = 0;
270         glyph->fLeft    = 0;
271         glyph->fMaskFormat = 0;
272         return;
273     }
274 
275     if (fGenerateImageFromPath) {
276         SkPath      devPath, fillPath;
277         SkMatrix    fillToDevMatrix;
278 
279         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
280 
281         if (fRasterizer) {
282             SkMask  mask;
283 
284             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
285                                        fMaskFilter, &mask,
286                                        SkMask::kJustComputeBounds_CreateMode)) {
287                 glyph->fLeft    = mask.fBounds.fLeft;
288                 glyph->fTop     = mask.fBounds.fTop;
289                 glyph->fWidth   = SkToU16(mask.fBounds.width());
290                 glyph->fHeight  = SkToU16(mask.fBounds.height());
291             } else {
292                 goto SK_ERROR;
293             }
294         } else {
295             // just use devPath
296             SkIRect ir;
297             devPath.getBounds().roundOut(&ir);
298 
299             if (ir.isEmpty() || !ir.is16Bit()) {
300                 goto SK_ERROR;
301             }
302             glyph->fLeft    = ir.fLeft;
303             glyph->fTop     = ir.fTop;
304             glyph->fWidth   = SkToU16(ir.width());
305             glyph->fHeight  = SkToU16(ir.height());
306         }
307     }
308 
309 	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
310 		glyph->fMaskFormat = fRec.fMaskFormat;
311 	}
312 
313     if (fMaskFilter) {
314         SkMask      src, dst;
315         SkMatrix    matrix;
316 
317         glyph->toMask(&src);
318         fRec.getMatrixFrom2x2(&matrix);
319 
320         src.fImage = NULL;  // only want the bounds from the filter
321         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
322             SkASSERT(dst.fImage == NULL);
323             glyph->fLeft    = dst.fBounds.fLeft;
324             glyph->fTop     = dst.fBounds.fTop;
325             glyph->fWidth   = SkToU16(dst.fBounds.width());
326             glyph->fHeight  = SkToU16(dst.fBounds.height());
327             glyph->fMaskFormat = dst.fFormat;
328         }
329     }
330     return;
331 
332 SK_ERROR:
333     // draw nothing 'cause we failed
334     glyph->fLeft    = 0;
335     glyph->fTop     = 0;
336     glyph->fWidth   = 0;
337     glyph->fHeight  = 0;
338     // put a valid value here, in case it was earlier set to
339     // MASK_FORMAT_JUST_ADVANCE
340     glyph->fMaskFormat = fRec.fMaskFormat;
341 }
342 
isLCD(const SkScalerContext::Rec & rec)343 static bool isLCD(const SkScalerContext::Rec& rec) {
344     return SkMask::kLCD16_Format == rec.fMaskFormat ||
345            SkMask::kLCD32_Format == rec.fMaskFormat;
346 }
347 
a8_to_rgb565(unsigned a8)348 static uint16_t a8_to_rgb565(unsigned a8) {
349     return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
350 }
351 
copyToLCD16(const SkBitmap & src,const SkMask & dst)352 static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
353     SkASSERT(SkBitmap::kA8_Config == src.config());
354     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
355 
356     const int width = dst.fBounds.width();
357     const int height = dst.fBounds.height();
358     const uint8_t* srcP = src.getAddr8(0, 0);
359     size_t srcRB = src.rowBytes();
360     uint16_t* dstP = (uint16_t*)dst.fImage;
361     size_t dstRB = dst.fRowBytes;
362     for (int y = 0; y < height; ++y) {
363         for (int x = 0; x < width; ++x) {
364             dstP[x] = a8_to_rgb565(srcP[x]);
365         }
366         srcP += srcRB;
367         dstP = (uint16_t*)((char*)dstP + dstRB);
368     }
369 }
370 
371 #define SK_FREETYPE_LCD_LERP    160
372 
lerp(int start,int end)373 static int lerp(int start, int end) {
374     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
375     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
376 }
377 
packLCD16(unsigned r,unsigned g,unsigned b)378 static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
379     if (SK_FREETYPE_LCD_LERP) {
380         // want (a+b+c)/3, but we approx to avoid the divide
381         unsigned ave = (5 * (r + g + b) + g) >> 4;
382         r = lerp(r, ave);
383         g = lerp(g, ave);
384         b = lerp(b, ave);
385     }
386     return SkPackRGB16(r >> 3, g >> 2, b >> 3);
387 }
388 
pack3xHToLCD16(const SkBitmap & src,const SkMask & dst)389 static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
390     SkASSERT(SkBitmap::kA8_Config == src.config());
391     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
392 
393     const int width = dst.fBounds.width();
394     const int height = dst.fBounds.height();
395     uint16_t* dstP = (uint16_t*)dst.fImage;
396     size_t dstRB = dst.fRowBytes;
397     for (int y = 0; y < height; ++y) {
398         const uint8_t* srcP = src.getAddr8(0, y);
399         for (int x = 0; x < width; ++x) {
400             unsigned r = *srcP++;
401             unsigned g = *srcP++;
402             unsigned b = *srcP++;
403             dstP[x] = packLCD16(r, g, b);
404         }
405         dstP = (uint16_t*)((char*)dstP + dstRB);
406     }
407 }
408 
pack3xHToLCD32(const SkBitmap & src,const SkMask & dst)409 static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
410     SkASSERT(SkBitmap::kA8_Config == src.config());
411     SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
412 
413     const int width = dst.fBounds.width();
414     const int height = dst.fBounds.height();
415     SkPMColor* dstP = (SkPMColor*)dst.fImage;
416     size_t dstRB = dst.fRowBytes;
417     for (int y = 0; y < height; ++y) {
418         const uint8_t* srcP = src.getAddr8(0, y);
419         for (int x = 0; x < width; ++x) {
420             unsigned r = *srcP++;
421             unsigned g = *srcP++;
422             unsigned b = *srcP++;
423             unsigned a = SkMax32(SkMax32(r, g), b);
424             dstP[x] = SkPackARGB32(a, r, g, b);
425         }
426         dstP = (SkPMColor*)((char*)dstP + dstRB);
427     }
428 }
429 
generateMask(const SkMask & mask,const SkPath & path)430 static void generateMask(const SkMask& mask, const SkPath& path) {
431     SkBitmap::Config config;
432     SkPaint     paint;
433 
434     int srcW = mask.fBounds.width();
435     int srcH = mask.fBounds.height();
436     int dstW = srcW;
437     int dstH = srcH;
438     int dstRB = mask.fRowBytes;
439 
440     SkMatrix matrix;
441     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
442                         -SkIntToScalar(mask.fBounds.fTop));
443 
444     if (SkMask::kBW_Format == mask.fFormat) {
445         config = SkBitmap::kA1_Config;
446         paint.setAntiAlias(false);
447     } else {
448         config = SkBitmap::kA8_Config;
449         paint.setAntiAlias(true);
450         switch (mask.fFormat) {
451             case SkMask::kA8_Format:
452                 break;
453             case SkMask::kLCD16_Format:
454             case SkMask::kLCD32_Format:
455                 // TODO: trigger off LCD orientation
456                 dstW *= 3;
457                 matrix.postScale(SkIntToScalar(3), SK_Scalar1);
458                 dstRB = 0;  // signals we need a copy
459                 break;
460             default:
461                 SkDEBUGFAIL("unexpected mask format");
462         }
463     }
464 
465     SkRasterClip clip;
466     clip.setRect(SkIRect::MakeWH(dstW, dstH));
467 
468     SkBitmap bm;
469     bm.setConfig(config, dstW, dstH, dstRB);
470 
471     if (0 == dstRB) {
472         bm.allocPixels();
473         bm.lockPixels();
474     } else {
475         bm.setPixels(mask.fImage);
476     }
477     sk_bzero(bm.getPixels(), bm.getSafeSize());
478 
479     SkDraw  draw;
480     sk_bzero(&draw, sizeof(draw));
481     draw.fRC    = &clip;
482     draw.fClip  = &clip.bwRgn();
483     draw.fMatrix = &matrix;
484     draw.fBitmap = &bm;
485     draw.drawPath(path, paint);
486 
487     if (0 == dstRB) {
488         switch (mask.fFormat) {
489             case SkMask::kLCD16_Format:
490                 pack3xHToLCD16(bm, mask);
491                 break;
492             case SkMask::kLCD32_Format:
493                 pack3xHToLCD32(bm, mask);
494                 break;
495             default:
496                 SkDEBUGFAIL("bad format for copyback");
497         }
498     }
499 }
500 
getImage(const SkGlyph & origGlyph)501 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
502     const SkGlyph*  glyph = &origGlyph;
503     SkGlyph         tmpGlyph;
504 
505     if (fMaskFilter) {   // restore the prefilter bounds
506         tmpGlyph.init(origGlyph.fID);
507 
508         // need the original bounds, sans our maskfilter
509         SkMaskFilter* mf = fMaskFilter;
510         fMaskFilter = NULL;             // temp disable
511         this->getMetrics(&tmpGlyph);
512         fMaskFilter = mf;               // restore
513 
514         tmpGlyph.fImage = origGlyph.fImage;
515 
516         // we need the prefilter bounds to be <= filter bounds
517         SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
518         SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
519         glyph = &tmpGlyph;
520     }
521 
522     if (fGenerateImageFromPath) {
523         SkPath      devPath, fillPath;
524         SkMatrix    fillToDevMatrix;
525         SkMask      mask;
526 
527         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
528         glyph->toMask(&mask);
529 
530         if (fRasterizer) {
531             mask.fFormat = SkMask::kA8_Format;
532             sk_bzero(glyph->fImage, mask.computeImageSize());
533 
534             if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
535                                         fMaskFilter, &mask,
536                                         SkMask::kJustRenderImage_CreateMode)) {
537                 return;
538             }
539         } else {
540             generateMask(mask, devPath);
541         }
542     } else {
543         this->getGlyphContext(*glyph)->generateImage(*glyph);
544     }
545 
546     if (fMaskFilter) {
547         SkMask      srcM, dstM;
548         SkMatrix    matrix;
549 
550         // the src glyph image shouldn't be 3D
551         SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
552         glyph->toMask(&srcM);
553         fRec.getMatrixFrom2x2(&matrix);
554 
555         if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
556             int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
557             int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
558             int dstRB = origGlyph.rowBytes();
559             int srcRB = dstM.fRowBytes;
560 
561             const uint8_t* src = (const uint8_t*)dstM.fImage;
562             uint8_t* dst = (uint8_t*)origGlyph.fImage;
563 
564             if (SkMask::k3D_Format == dstM.fFormat) {
565                 // we have to copy 3 times as much
566                 height *= 3;
567             }
568 
569             // clean out our glyph, since it may be larger than dstM
570             //sk_bzero(dst, height * dstRB);
571 
572             while (--height >= 0) {
573                 memcpy(dst, src, width);
574                 src += srcRB;
575                 dst += dstRB;
576             }
577             SkMask::FreeImage(dstM.fImage);
578         }
579     }
580 }
581 
getPath(const SkGlyph & glyph,SkPath * path)582 void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
583     this->internalGetPath(glyph, NULL, path, NULL);
584 }
585 
getFontMetrics(SkPaint::FontMetrics * mx,SkPaint::FontMetrics * my)586 void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
587                                      SkPaint::FontMetrics* my) {
588     this->generateFontMetrics(mx, my);
589 }
590 
generateGlyphToChar(uint16_t glyph)591 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
592     return 0;
593 }
594 
595 ///////////////////////////////////////////////////////////////////////////////
596 
internalGetPath(const SkGlyph & glyph,SkPath * fillPath,SkPath * devPath,SkMatrix * fillToDevMatrix)597 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
598                                   SkPath* devPath, SkMatrix* fillToDevMatrix) {
599     SkPath  path;
600 
601     this->getGlyphContext(glyph)->generatePath(glyph, &path);
602 
603     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
604         SkFixed dx = glyph.getSubXFixed();
605         SkFixed dy = glyph.getSubYFixed();
606         if (dx | dy) {
607             path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
608         }
609     }
610 
611     if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
612         // need the path in user-space, with only the point-size applied
613         // so that our stroking and effects will operate the same way they
614         // would if the user had extracted the path themself, and then
615         // called drawPath
616         SkPath      localPath;
617         SkMatrix    matrix, inverse;
618 
619         fRec.getMatrixFrom2x2(&matrix);
620         matrix.invert(&inverse);
621         path.transform(inverse, &localPath);
622         // now localPath is only affected by the paint settings, and not the canvas matrix
623 
624         SkScalar width = fRec.fFrameWidth;
625 
626         if (fPathEffect) {
627             SkPath effectPath;
628 
629             if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
630                 localPath.swap(effectPath);
631             }
632         }
633 
634         if (width > 0) {
635             SkStroke    stroker;
636             SkPath      outline;
637 
638             stroker.setWidth(width);
639             stroker.setMiterLimit(fRec.fMiterLimit);
640             stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
641             stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
642             stroker.strokePath(localPath, &outline);
643             localPath.swap(outline);
644         }
645 
646         // now return stuff to the caller
647         if (fillToDevMatrix) {
648             *fillToDevMatrix = matrix;
649         }
650         if (devPath) {
651             localPath.transform(matrix, devPath);
652         }
653         if (fillPath) {
654             fillPath->swap(localPath);
655         }
656     } else {   // nothing tricky to do
657         if (fillToDevMatrix) {
658             fillToDevMatrix->reset();
659         }
660         if (devPath) {
661             if (fillPath == NULL) {
662                 devPath->swap(path);
663             } else {
664                 *devPath = path;
665             }
666         }
667 
668         if (fillPath) {
669             fillPath->swap(path);
670         }
671     }
672 
673     if (devPath) {
674         devPath->updateBoundsCache();
675     }
676     if (fillPath) {
677         fillPath->updateBoundsCache();
678     }
679 }
680 
681 
getMatrixFrom2x2(SkMatrix * dst) const682 void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
683     dst->reset();
684     dst->setScaleX(fPost2x2[0][0]);
685     dst->setSkewX( fPost2x2[0][1]);
686     dst->setSkewY( fPost2x2[1][0]);
687     dst->setScaleY(fPost2x2[1][1]);
688 }
689 
getLocalMatrix(SkMatrix * m) const690 void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
691     m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
692     if (fPreSkewX) {
693         m->postSkew(fPreSkewX, 0);
694     }
695 }
696 
getSingleMatrix(SkMatrix * m) const697 void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
698     this->getLocalMatrix(m);
699 
700     //  now concat the device matrix
701     SkMatrix    deviceMatrix;
702     this->getMatrixFrom2x2(&deviceMatrix);
703     m->postConcat(deviceMatrix);
704 }
705 
SkComputeAxisAlignmentForHText(const SkMatrix & matrix)706 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
707     SkASSERT(!matrix.hasPerspective());
708 
709     if (0 == matrix[SkMatrix::kMSkewY]) {
710         return kX_SkAxisAlignment;
711     }
712     if (0 == matrix[SkMatrix::kMScaleX]) {
713         return kY_SkAxisAlignment;
714     }
715     return kNone_SkAxisAlignment;
716 }
717 
718 ///////////////////////////////////////////////////////////////////////////////
719 
720 #include "SkFontHost.h"
721 
722 class SkScalerContext_Empty : public SkScalerContext {
723 public:
SkScalerContext_Empty(const SkDescriptor * desc)724     SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
725 
726 protected:
generateGlyphCount()727     virtual unsigned generateGlyphCount() {
728         return 0;
729     }
generateCharToGlyph(SkUnichar uni)730     virtual uint16_t generateCharToGlyph(SkUnichar uni) {
731         return 0;
732     }
generateAdvance(SkGlyph * glyph)733     virtual void generateAdvance(SkGlyph* glyph) {
734         glyph->zeroMetrics();
735     }
generateMetrics(SkGlyph * glyph)736     virtual void generateMetrics(SkGlyph* glyph) {
737         glyph->zeroMetrics();
738     }
generateImage(const SkGlyph & glyph)739     virtual void generateImage(const SkGlyph& glyph) {}
generatePath(const SkGlyph & glyph,SkPath * path)740     virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
generateFontMetrics(SkPaint::FontMetrics * mx,SkPaint::FontMetrics * my)741     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
742                                      SkPaint::FontMetrics* my) {
743         if (mx) {
744             sk_bzero(mx, sizeof(*mx));
745         }
746         if (my) {
747             sk_bzero(my, sizeof(*my));
748         }
749     }
750 };
751 
752 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
753 
Create(const SkDescriptor * desc)754 SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
755 	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
756 	if (NULL == c) {
757 		c = SkFontHost::CreateScalerContext(desc);
758 	}
759     if (NULL == c) {
760         c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
761     }
762     return c;
763 }
764 
765