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