• 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 #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 }
144 
145 /*  Return the next context, creating it if its not already created, but return
146     NULL if the fonthost says there are no more fonts to fallback to.
147  */
getNextContext()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 }
164 
getContextFromChar(SkUnichar uni,unsigned & glyphID)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 }
179 
getGlyphContext(const SkGlyph & glyph)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 }
198 
199 #ifdef SK_BUILD_FOR_ANDROID
findTypefaceIdForChar(SkUnichar uni)200 SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) {
201     unsigned glyphID;
202     SkScalerContext* ctx = getContextFromChar(uni, glyphID);
203     if (ctx) {
204         return ctx->fRec.fFontID;
205     } else {
206         return 0;
207     }
208 }
209 
210 /*  This loops through all available fallback contexts (if needed) until it
211     finds some context that can handle the unichar and return it.
212 
213     As this is somewhat expensive operation, it should only be done on the first
214     char of a run.
215  */
getBaseGlyphCount(SkUnichar uni)216 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
217     unsigned glyphID;
218     SkScalerContext* ctx = getContextFromChar(uni, glyphID);
219     if (ctx) {
220         return ctx->fBaseGlyphCount;
221     } else {
222         SkDEBUGF(("--- no context for char %x\n", uni));
223         return this->fBaseGlyphCount;
224     }
225 }
226 #endif
227 
228 /*  This loops through all available fallback contexts (if needed) until it
229     finds some context that can handle the unichar. If all fail, returns 0
230  */
charToGlyphID(SkUnichar uni)231 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
232 
233     unsigned glyphID;
234     SkScalerContext* ctx = getContextFromChar(uni, glyphID);
235     if (!ctx) {
236         return 0; // no more contexts, return missing glyph
237     }
238     // add the ctx's base, making glyphID unique for chain of contexts
239     glyphID += ctx->fBaseGlyphCount;
240     // check for overflow of 16bits, since our glyphID cannot exceed that
241     if (glyphID > 0xFFFF) {
242         glyphID = 0;
243     }
244     return SkToU16(glyphID);
245 }
246 
glyphIDToChar(uint16_t glyphID)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 }
261 
getAdvance(SkGlyph * glyph)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 }
270 
getMetrics(SkGlyph * glyph)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 
isLCD(const SkScalerContext::Rec & rec)361 static bool isLCD(const SkScalerContext::Rec& rec) {
362     return SkMask::kLCD16_Format == rec.fMaskFormat ||
363            SkMask::kLCD32_Format == rec.fMaskFormat;
364 }
365 
a8_to_rgb565(unsigned a8)366 static uint16_t a8_to_rgb565(unsigned a8) {
367     return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
368 }
369 
copyToLCD16(const SkBitmap & src,const SkMask & dst)370 static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
371     SkASSERT(SkBitmap::kA8_Config == src.config());
372     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
373 
374     const int width = dst.fBounds.width();
375     const int height = dst.fBounds.height();
376     const uint8_t* srcP = src.getAddr8(0, 0);
377     size_t srcRB = src.rowBytes();
378     uint16_t* dstP = (uint16_t*)dst.fImage;
379     size_t dstRB = dst.fRowBytes;
380     for (int y = 0; y < height; ++y) {
381         for (int x = 0; x < width; ++x) {
382             dstP[x] = a8_to_rgb565(srcP[x]);
383         }
384         srcP += srcRB;
385         dstP = (uint16_t*)((char*)dstP + dstRB);
386     }
387 }
388 
389 #define SK_FREETYPE_LCD_LERP    160
390 
lerp(int start,int end)391 static int lerp(int start, int end) {
392     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
393     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
394 }
395 
packLCD16(unsigned r,unsigned g,unsigned b)396 static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
397     if (SK_FREETYPE_LCD_LERP) {
398         // want (a+b+c)/3, but we approx to avoid the divide
399         unsigned ave = (5 * (r + g + b) + g) >> 4;
400         r = lerp(r, ave);
401         g = lerp(g, ave);
402         b = lerp(b, ave);
403     }
404     return SkPackRGB16(r >> 3, g >> 2, b >> 3);
405 }
406 
pack3xHToLCD16(const SkBitmap & src,const SkMask & dst)407 static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
408     SkASSERT(SkBitmap::kA8_Config == src.config());
409     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
410 
411     const int width = dst.fBounds.width();
412     const int height = dst.fBounds.height();
413     uint16_t* dstP = (uint16_t*)dst.fImage;
414     size_t dstRB = dst.fRowBytes;
415     for (int y = 0; y < height; ++y) {
416         const uint8_t* srcP = src.getAddr8(0, y);
417         for (int x = 0; x < width; ++x) {
418             unsigned r = *srcP++;
419             unsigned g = *srcP++;
420             unsigned b = *srcP++;
421             dstP[x] = packLCD16(r, g, b);
422         }
423         dstP = (uint16_t*)((char*)dstP + dstRB);
424     }
425 }
426 
pack3xHToLCD32(const SkBitmap & src,const SkMask & dst)427 static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
428     SkASSERT(SkBitmap::kA8_Config == src.config());
429     SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
430 
431     const int width = dst.fBounds.width();
432     const int height = dst.fBounds.height();
433     SkPMColor* dstP = (SkPMColor*)dst.fImage;
434     size_t dstRB = dst.fRowBytes;
435     for (int y = 0; y < height; ++y) {
436         const uint8_t* srcP = src.getAddr8(0, y);
437         for (int x = 0; x < width; ++x) {
438             unsigned r = *srcP++;
439             unsigned g = *srcP++;
440             unsigned b = *srcP++;
441             unsigned a = SkMax32(SkMax32(r, g), b);
442             dstP[x] = SkPackARGB32(a, r, g, b);
443         }
444         dstP = (SkPMColor*)((char*)dstP + dstRB);
445     }
446 }
447 
generateMask(const SkMask & mask,const SkPath & path)448 static void generateMask(const SkMask& mask, const SkPath& path) {
449     SkBitmap::Config config;
450     SkPaint     paint;
451 
452     int srcW = mask.fBounds.width();
453     int srcH = mask.fBounds.height();
454     int dstW = srcW;
455     int dstH = srcH;
456     int dstRB = mask.fRowBytes;
457 
458     SkMatrix matrix;
459     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
460                         -SkIntToScalar(mask.fBounds.fTop));
461 
462     if (SkMask::kBW_Format == mask.fFormat) {
463         config = SkBitmap::kA1_Config;
464         paint.setAntiAlias(false);
465     } else {
466         config = SkBitmap::kA8_Config;
467         paint.setAntiAlias(true);
468         switch (mask.fFormat) {
469             case SkMask::kA8_Format:
470                 break;
471             case SkMask::kLCD16_Format:
472             case SkMask::kLCD32_Format:
473                 // TODO: trigger off LCD orientation
474                 dstW *= 3;
475                 matrix.postScale(SkIntToScalar(3), SK_Scalar1);
476                 dstRB = 0;  // signals we need a copy
477                 break;
478             default:
479                 SkDEBUGFAIL("unexpected mask format");
480         }
481     }
482 
483     SkRasterClip clip;
484     clip.setRect(SkIRect::MakeWH(dstW, dstH));
485 
486     SkBitmap bm;
487     bm.setConfig(config, dstW, dstH, dstRB);
488 
489     if (0 == dstRB) {
490         bm.allocPixels();
491         bm.lockPixels();
492     } else {
493         bm.setPixels(mask.fImage);
494     }
495     sk_bzero(bm.getPixels(), bm.getSafeSize());
496 
497     SkDraw  draw;
498     sk_bzero(&draw, sizeof(draw));
499     draw.fRC    = &clip;
500     draw.fClip  = &clip.bwRgn();
501     draw.fMatrix = &matrix;
502     draw.fBitmap = &bm;
503     draw.drawPath(path, paint);
504 
505     if (0 == dstRB) {
506         switch (mask.fFormat) {
507             case SkMask::kLCD16_Format:
508                 pack3xHToLCD16(bm, mask);
509                 break;
510             case SkMask::kLCD32_Format:
511                 pack3xHToLCD32(bm, mask);
512                 break;
513             default:
514                 SkDEBUGFAIL("bad format for copyback");
515         }
516     }
517 }
518 
getImage(const SkGlyph & origGlyph)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 }
599 
getPath(const SkGlyph & glyph,SkPath * path)600 void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
601     this->internalGetPath(glyph, NULL, path, NULL);
602 }
603 
getFontMetrics(SkPaint::FontMetrics * mx,SkPaint::FontMetrics * my)604 void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
605                                      SkPaint::FontMetrics* my) {
606     this->generateFontMetrics(mx, my);
607 }
608 
generateGlyphToChar(uint16_t glyph)609 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
610     return 0;
611 }
612 
613 ///////////////////////////////////////////////////////////////////////////////
614 
internalGetPath(const SkGlyph & glyph,SkPath * fillPath,SkPath * devPath,SkMatrix * fillToDevMatrix)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 }
698 
699 
getMatrixFrom2x2(SkMatrix * dst) const700 void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
701     dst->reset();
702     dst->setScaleX(fPost2x2[0][0]);
703     dst->setSkewX( fPost2x2[0][1]);
704     dst->setSkewY( fPost2x2[1][0]);
705     dst->setScaleY(fPost2x2[1][1]);
706 }
707 
getLocalMatrix(SkMatrix * m) const708 void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
709     m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
710     if (fPreSkewX) {
711         m->postSkew(fPreSkewX, 0);
712     }
713 }
714 
getSingleMatrix(SkMatrix * m) const715 void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
716     this->getLocalMatrix(m);
717 
718     //  now concat the device matrix
719     SkMatrix    deviceMatrix;
720     this->getMatrixFrom2x2(&deviceMatrix);
721     m->postConcat(deviceMatrix);
722 }
723 
SkComputeAxisAlignmentForHText(const SkMatrix & matrix)724 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
725     SkASSERT(!matrix.hasPerspective());
726 
727     if (0 == matrix[SkMatrix::kMSkewY]) {
728         return kX_SkAxisAlignment;
729     }
730     if (0 == matrix[SkMatrix::kMScaleX]) {
731         return kY_SkAxisAlignment;
732     }
733     return kNone_SkAxisAlignment;
734 }
735 
736 ///////////////////////////////////////////////////////////////////////////////
737 
738 #include "SkFontHost.h"
739 
740 class SkScalerContext_Empty : public SkScalerContext {
741 public:
SkScalerContext_Empty(const SkDescriptor * desc)742     SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
743 
744 protected:
generateGlyphCount()745     virtual unsigned generateGlyphCount() {
746         return 0;
747     }
generateCharToGlyph(SkUnichar uni)748     virtual uint16_t generateCharToGlyph(SkUnichar uni) {
749         return 0;
750     }
generateAdvance(SkGlyph * glyph)751     virtual void generateAdvance(SkGlyph* glyph) {
752         glyph->zeroMetrics();
753     }
generateMetrics(SkGlyph * glyph)754     virtual void generateMetrics(SkGlyph* glyph) {
755         glyph->zeroMetrics();
756     }
generateImage(const SkGlyph & glyph)757     virtual void generateImage(const SkGlyph& glyph) {}
generatePath(const SkGlyph & glyph,SkPath * path)758     virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
generateFontMetrics(SkPaint::FontMetrics * mx,SkPaint::FontMetrics * my)759     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
760                                      SkPaint::FontMetrics* my) {
761         if (mx) {
762             sk_bzero(mx, sizeof(*mx));
763         }
764         if (my) {
765             sk_bzero(my, sizeof(*my));
766         }
767     }
768 };
769 
770 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
771 
Create(const SkDescriptor * desc)772 SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
773 	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
774 	if (NULL == c) {
775 		c = SkFontHost::CreateScalerContext(desc);
776 	}
777     if (NULL == c) {
778         c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
779     }
780     return c;
781 }
782 
783