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