Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 */
10 #include "SkScalerContext.h"
11 #include "SkColorPriv.h"
12 #include "SkDescriptor.h"
13 #include "SkDraw.h"
14 #include "SkFontHost.h"
15 #include "SkGlyph.h"
16 #include "SkMaskFilter.h"
17 #include "SkMaskGamma.h"
18 #include "SkReadBuffer.h"
19 #include "SkWriteBuffer.h"
20 #include "SkPathEffect.h"
21 #include "SkRasterizer.h"
22 #include "SkRasterClip.h"
23 #include "SkStroke.h"
24 #include "SkThread.h"
26 #ifdef SK_BUILD_FOR_ANDROID
27 #include "SkTypeface_android.h"
28 #endif
30 #define ComputeBWRowBytes(width) (((unsigned)(width) + 7) >> 3)
32 void SkGlyph::toMask(SkMask* mask) const {
33 SkASSERT(mask);
35 mask->fImage = (uint8_t*)fImage;
36 mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
37 mask->fRowBytes = this->rowBytes();
38 mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
39 }
41 size_t SkGlyph::computeImageSize() const {
42 const size_t size = this->rowBytes() * fHeight;
44 switch (fMaskFormat) {
45 case SkMask::k3D_Format:
46 return 3 * size;
47 default:
48 return size;
49 }
50 }
52 void SkGlyph::zeroMetrics() {
53 fAdvanceX = 0;
54 fAdvanceY = 0;
55 fWidth = 0;
56 fHeight = 0;
57 fTop = 0;
58 fLeft = 0;
59 fRsbDelta = 0;
60 fLsbDelta = 0;
61 }
63 ///////////////////////////////////////////////////////////////////////////////
65 #ifdef SK_DEBUG
66 #define DUMP_RECx
67 #endif
69 static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag,
70 SkFlattenable::Type ft) {
71 SkFlattenable* obj = NULL;
72 uint32_t len;
73 const void* data = desc->findEntry(tag, &len);
75 if (data) {
76 SkReadBuffer buffer(data, len);
77 obj = buffer.readFlattenable(ft);
78 SkASSERT(buffer.offset() == buffer.size());
79 }
80 return obj;
81 }
83 SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
84 : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL)))
86 , fBaseGlyphCount(0)
87 , fTypeface(SkRef(typeface))
88 , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_SkDescriptorTag,
89 SkFlattenable::kSkPathEffect_Type)))
90 , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_SkDescriptorTag,
91 SkFlattenable::kSkMaskFilter_Type)))
92 , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_SkDescriptorTag,
93 SkFlattenable::kSkRasterizer_Type)))
94 // Initialize based on our settings. Subclasses can also force this.
95 , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL)
97 , fNextContext(NULL)
99 , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMaskPreBlend(fRec))
100 , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec)
101 : SkMaskGamma::PreBlend())
102 {
103 #ifdef DUMP_REC
104 desc->assertChecksum();
105 SkDebugf("SkScalerContext checksum %x count %d length %d\n",
106 desc->getChecksum(), desc->getCount(), desc->getLength());
107 SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
108 rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
109 rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
110 SkDebugf(" frame %g miter %g hints %d framefill %d format %d join %d\n",
111 rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
112 rec->fMaskFormat, rec->fStrokeJoin);
113 SkDebugf(" pathEffect %x maskFilter %x\n",
114 desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
115 desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
116 #endif
117 #ifdef SK_BUILD_FOR_ANDROID
118 uint32_t len;
119 const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len);
120 if (data) {
121 SkReadBuffer buffer(data, len);
122 fPaintOptionsAndroid.unflatten(buffer);
123 SkASSERT(buffer.offset() == buffer.size());
124 }
125 #endif
126 }
128 SkScalerContext::~SkScalerContext() {
129 SkDELETE(fNextContext);
131 SkSafeUnref(fPathEffect);
132 SkSafeUnref(fMaskFilter);
133 SkSafeUnref(fRasterizer);
134 }
136 // Return the context associated with the next logical typeface, or NULL if
137 // there are no more entries in the fallback chain.
138 SkScalerContext* SkScalerContext::allocNextContext() const {
139 #ifdef SK_BUILD_FOR_ANDROID
140 SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID,
141 fRec.fOrigFontID,
142 fPaintOptionsAndroid);
143 if (0 == newFace) {
144 return NULL;
145 }
147 SkAutoTUnref<SkTypeface> aur(newFace);
148 uint32_t newFontID = newFace->uniqueID();
150 SkWriteBuffer androidBuffer;
151 fPaintOptionsAndroid.flatten(androidBuffer);
153 SkAutoDescriptor ad(sizeof(fRec) + androidBuffer.bytesWritten()
154 + SkDescriptor::ComputeOverhead(2));
155 SkDescriptor* desc = ad.getDesc();
157 desc->init();
158 SkScalerContext::Rec* newRec =
159 (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
160 sizeof(fRec), &fRec);
161 androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag,
162 androidBuffer.bytesWritten(), NULL));
164 newRec->fFontID = newFontID;
165 desc->computeChecksum();
167 return newFace->createScalerContext(desc);
168 #else
169 return NULL;
170 #endif
171 }
173 /* Return the next context, creating it if its not already created, but return
174 NULL if the fonthost says there are no more fonts to fallback to.
175 */
176 SkScalerContext* SkScalerContext::getNextContext() {
177 SkScalerContext* next = fNextContext;
178 // if next is null, then either it isn't cached yet, or we're at the
179 // end of our possible chain
180 if (NULL == next) {
181 next = this->allocNextContext();
182 if (NULL == next) {
183 return NULL;
184 }
185 // next's base is our base + our local count
186 next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
187 // cache the answer
188 fNextContext = next;
189 }
190 return next;
191 }
193 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
194 unsigned glyphID = glyph.getGlyphID();
195 SkScalerContext* ctx = this;
196 for (;;) {
197 unsigned count = ctx->getGlyphCount();
198 if (glyphID < count) {
199 break;
200 }
201 glyphID -= count;
202 ctx = ctx->getNextContext();
203 if (NULL == ctx) {
204 // SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
205 // just return the original context (this)
206 return this;
207 }
208 }
209 return ctx;
210 }
212 SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni,
213 uint16_t* glyphID) {
214 SkScalerContext* ctx = this;
215 for (;;) {
216 const uint16_t glyph = ctx->generateCharToGlyph(uni);
217 if (glyph) {
218 if (NULL != glyphID) {
219 *glyphID = glyph;
220 }
221 break; // found it
222 }
223 ctx = ctx->getNextContext();
224 if (NULL == ctx) {
225 return NULL;
226 }
227 }
228 return ctx;
229 }
231 #ifdef SK_BUILD_FOR_ANDROID
232 SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) {
233 SkScalerContext* ctx = this->getContextFromChar(uni, NULL);
234 if (NULL != ctx) {
235 return ctx->fRec.fFontID;
236 } else {
237 return 0;
238 }
239 }
241 /* This loops through all available fallback contexts (if needed) until it
242 finds some context that can handle the unichar and return it.
244 As this is somewhat expensive operation, it should only be done on the first
245 char of a run.
246 */
247 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
248 SkScalerContext* ctx = this->getContextFromChar(uni, NULL);
249 if (NULL != ctx) {
250 return ctx->fBaseGlyphCount;
251 } else {
252 SkDEBUGF(("--- no context for char %x\n", uni));
253 return this->fBaseGlyphCount;
254 }
255 }
256 #endif
258 /* This loops through all available fallback contexts (if needed) until it
259 finds some context that can handle the unichar. If all fail, returns 0
260 */
261 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
263 uint16_t tempID;
264 SkScalerContext* ctx = this->getContextFromChar(uni, &tempID);
265 if (NULL == ctx) {
266 return 0; // no more contexts, return missing glyph
267 }
268 // add the ctx's base, making glyphID unique for chain of contexts
269 unsigned glyphID = tempID + ctx->fBaseGlyphCount;
270 // check for overflow of 16bits, since our glyphID cannot exceed that
271 if (glyphID > 0xFFFF) {
272 glyphID = 0;
273 }
274 return SkToU16(glyphID);
275 }
277 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
278 SkScalerContext* ctx = this;
279 unsigned rangeEnd = 0;
280 do {
281 unsigned rangeStart = rangeEnd;
283 rangeEnd += ctx->getGlyphCount();
284 if (rangeStart <= glyphID && glyphID < rangeEnd) {
285 return ctx->generateGlyphToChar(glyphID - rangeStart);
286 }
287 ctx = ctx->getNextContext();
288 } while (NULL != ctx);
289 return 0;
290 }
292 void SkScalerContext::getAdvance(SkGlyph* glyph) {
293 // mark us as just having a valid advance
294 glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
295 // we mark the format before making the call, in case the impl
296 // internally ends up calling its generateMetrics, which is OK
297 // albeit slower than strictly necessary
298 this->getGlyphContext(*glyph)->generateAdvance(glyph);
299 }
301 void SkScalerContext::getMetrics(SkGlyph* glyph) {
302 this->getGlyphContext(*glyph)->generateMetrics(glyph);
304 // for now we have separate cache entries for devkerning on and off
305 // in the future we might share caches, but make our measure/draw
306 // code make the distinction. Thus we zap the values if the caller
307 // has not asked for them.
308 if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
309 // no devkern, so zap the fields
310 glyph->fLsbDelta = glyph->fRsbDelta = 0;
311 }
313 // if either dimension is empty, zap the image bounds of the glyph
314 if (0 == glyph->fWidth || 0 == glyph->fHeight) {
315 glyph->fWidth = 0;
316 glyph->fHeight = 0;
317 glyph->fTop = 0;
318 glyph->fLeft = 0;
319 glyph->fMaskFormat = 0;
320 return;
321 }
323 if (fGenerateImageFromPath) {
324 SkPath devPath, fillPath;
325 SkMatrix fillToDevMatrix;
327 this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
329 if (fRasterizer) {
330 SkMask mask;
332 if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
333 fMaskFilter, &mask,
334 SkMask::kJustComputeBounds_CreateMode)) {
335 glyph->fLeft = mask.fBounds.fLeft;
336 glyph->fTop = mask.fBounds.fTop;
337 glyph->fWidth = SkToU16(mask.fBounds.width());
338 glyph->fHeight = SkToU16(mask.fBounds.height());
339 } else {
340 goto SK_ERROR;
341 }
342 } else {
343 // just use devPath
344 SkIRect ir;
345 devPath.getBounds().roundOut(&ir);
347 if (ir.isEmpty() || !ir.is16Bit()) {
348 goto SK_ERROR;
349 }
350 glyph->fLeft = ir.fLeft;
351 glyph->fTop = ir.fTop;
352 glyph->fWidth = SkToU16(ir.width());
353 glyph->fHeight = SkToU16(ir.height());
355 if (glyph->fWidth > 0) {
356 switch (fRec.fMaskFormat) {
357 case SkMask::kLCD16_Format:
358 case SkMask::kLCD32_Format:
359 glyph->fWidth += 2;
360 glyph->fLeft -= 1;
361 break;
362 default:
363 break;
364 }
365 }
366 }
367 }
369 if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
370 glyph->fMaskFormat = fRec.fMaskFormat;
371 }
373 // If we are going to create the mask, then we cannot keep the color
374 if ((fGenerateImageFromPath || fMaskFilter) &&
375 SkMask::kARGB32_Format == glyph->fMaskFormat) {
376 glyph->fMaskFormat = SkMask::kA8_Format;
377 }
379 if (fMaskFilter) {
380 SkMask src, dst;
381 SkMatrix matrix;
383 glyph->toMask(&src);
384 fRec.getMatrixFrom2x2(&matrix);
386 src.fImage = NULL; // only want the bounds from the filter
387 if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
388 if (dst.fBounds.isEmpty() || !dst.fBounds.is16Bit()) {
389 goto SK_ERROR;
390 }
391 SkASSERT(dst.fImage == NULL);
392 glyph->fLeft = dst.fBounds.fLeft;
393 glyph->fTop = dst.fBounds.fTop;
394 glyph->fWidth = SkToU16(dst.fBounds.width());
395 glyph->fHeight = SkToU16(dst.fBounds.height());
396 glyph->fMaskFormat = dst.fFormat;
397 }
398 }
399 return;
401 SK_ERROR:
402 // draw nothing 'cause we failed
403 glyph->fLeft = 0;
404 glyph->fTop = 0;
405 glyph->fWidth = 0;
406 glyph->fHeight = 0;
407 // put a valid value here, in case it was earlier set to
408 // MASK_FORMAT_JUST_ADVANCE
409 glyph->fMaskFormat = fRec.fMaskFormat;
410 }
412 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
414 static void applyLUTToA8Mask(const SkMask& mask, const uint8_t* lut) {
415 uint8_t* SK_RESTRICT dst = (uint8_t*)mask.fImage;
416 unsigned rowBytes = mask.fRowBytes;
418 for (int y = mask.fBounds.height() - 1; y >= 0; --y) {
419 for (int x = mask.fBounds.width() - 1; x >= 0; --x) {
420 dst[x] = lut[dst[x]];
421 }
422 dst += rowBytes;
423 }
424 }
426 template<bool APPLY_PREBLEND>
427 static void pack4xHToLCD16(const SkBitmap& src, const SkMask& dst,
428 const SkMaskGamma::PreBlend& maskPreBlend) {
429 #define SAMPLES_PER_PIXEL 4
430 #define LCD_PER_PIXEL 3
431 SkASSERT(kAlpha_8_SkColorType == src.colorType());
432 SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
434 const int sample_width = src.width();
435 const int height = src.height();
437 uint16_t* dstP = (uint16_t*)dst.fImage;
438 size_t dstRB = dst.fRowBytes;
439 // An N tap FIR is defined by
440 // out[n] = coeff[0]*x[n] + coeff[1]*x[n-1] + ... + coeff[N]*x[n-N]
441 // or
442 // out[n] = sum(i, 0, N, coeff[i]*x[n-i])
444 // The strategy is to use one FIR (different coefficients) for each of r, g, and b.
445 // This means using every 4th FIR output value of each FIR and discarding the rest.
446 // The FIRs are aligned, and the coefficients reach 5 samples to each side of their 'center'.
447 // (For r and b this is technically incorrect, but the coeffs outside round to zero anyway.)
449 // These are in some fixed point repesentation.
450 // Adding up to more than one simulates ink spread.
451 // For implementation reasons, these should never add up to more than two.
453 // Coefficients determined by a gausian where 5 samples = 3 std deviations (0x110 'contrast').
454 // Calculated using tools/generate_fir_coeff.py
455 // With this one almost no fringing is ever seen, but it is imperceptibly blurry.
456 // The lcd smoothed text is almost imperceptibly different from gray,
457 // but is still sharper on small stems and small rounded corners than gray.
458 // This also seems to be about as wide as one can get and only have a three pixel kernel.
459 // TODO: caculate these at runtime so parameters can be adjusted (esp contrast).
460 static const unsigned int coefficients[LCD_PER_PIXEL][SAMPLES_PER_PIXEL*3] = {
461 //The red subpixel is centered inside the first sample (at 1/6 pixel), and is shifted.
462 { 0x03, 0x0b, 0x1c, 0x33, 0x40, 0x39, 0x24, 0x10, 0x05, 0x01, 0x00, 0x00, },
463 //The green subpixel is centered between two samples (at 1/2 pixel), so is symetric
464 { 0x00, 0x02, 0x08, 0x16, 0x2b, 0x3d, 0x3d, 0x2b, 0x16, 0x08, 0x02, 0x00, },
465 //The blue subpixel is centered inside the last sample (at 5/6 pixel), and is shifted.
466 { 0x00, 0x00, 0x01, 0x05, 0x10, 0x24, 0x39, 0x40, 0x33, 0x1c, 0x0b, 0x03, },
467 };
469 for (int y = 0; y < height; ++y) {
470 const uint8_t* srcP = src.getAddr8(0, y);
472 // TODO: this fir filter implementation is straight forward, but slow.
473 // It should be possible to make it much faster.
474 for (int sample_x = -4, pixel_x = 0; sample_x < sample_width + 4; sample_x += 4, ++pixel_x) {
475 int fir[LCD_PER_PIXEL] = { 0 };
476 for (int sample_index = SkMax32(0, sample_x - 4), coeff_index = sample_index - (sample_x - 4)
477 ; sample_index < SkMin32(sample_x + 8, sample_width)
478 ; ++sample_index, ++coeff_index)
479 {
480 int sample_value = srcP[sample_index];
481 for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
482 fir[subpxl_index] += coefficients[subpxl_index][coeff_index] * sample_value;
483 }
484 }
485 for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
486 fir[subpxl_index] /= 0x100;
487 fir[subpxl_index] = SkMin32(fir[subpxl_index], 255);
488 }
490 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(fir[0], maskPreBlend.fR);
491 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(fir[1], maskPreBlend.fG);
492 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(fir[2], maskPreBlend.fB);
493 #if SK_SHOW_TEXT_BLIT_COVERAGE
494 r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
495 #endif
496 dstP[pixel_x] = SkPack888ToRGB16(r, g, b);
497 }
498 dstP = (uint16_t*)((char*)dstP + dstRB);
499 }
500 }
502 template<bool APPLY_PREBLEND>
503 static void pack4xHToLCD32(const SkBitmap& src, const SkMask& dst,
504 const SkMaskGamma::PreBlend& maskPreBlend) {
505 SkASSERT(kAlpha_8_SkColorType == src.colorType());
506 SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
508 const int width = dst.fBounds.width();
509 const int height = dst.fBounds.height();
510 SkPMColor* dstP = (SkPMColor*)dst.fImage;
511 size_t dstRB = dst.fRowBytes;
513 for (int y = 0; y < height; ++y) {
514 const uint8_t* srcP = src.getAddr8(0, y);
516 // TODO: need to use fir filter here as well.
517 for (int x = 0; x < width; ++x) {
518 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR);
519 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG);
520 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB);
521 dstP[x] = SkPackARGB32(0xFF, r, g, b);
522 }
523 dstP = (SkPMColor*)((char*)dstP + dstRB);
524 }
525 }
527 static inline int convert_8_to_1(unsigned byte) {
528 SkASSERT(byte <= 0xFF);
529 return byte >> 7;
530 }
532 static uint8_t pack_8_to_1(const uint8_t alpha[8]) {
533 unsigned bits = 0;
534 for (int i = 0; i < 8; ++i) {
535 bits <<= 1;
536 bits |= convert_8_to_1(alpha[i]);
537 }
538 return SkToU8(bits);
539 }
541 static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
542 const int height = mask.fBounds.height();
543 const int width = mask.fBounds.width();
544 const int octs = width >> 3;
545 const int leftOverBits = width & 7;
547 uint8_t* dst = mask.fImage;
548 const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
549 SkASSERT(dstPad >= 0);
551 const int srcPad = srcRB - width;
552 SkASSERT(srcPad >= 0);
554 for (int y = 0; y < height; ++y) {
555 for (int i = 0; i < octs; ++i) {
556 *dst++ = pack_8_to_1(src);
557 src += 8;
558 }
559 if (leftOverBits > 0) {
560 unsigned bits = 0;
561 int shift = 7;
562 for (int i = 0; i < leftOverBits; ++i, --shift) {
563 bits |= convert_8_to_1(*src++) << shift;
564 }
565 *dst++ = bits;
566 }
567 src += srcPad;
568 dst += dstPad;
569 }
570 }
572 static void generateMask(const SkMask& mask, const SkPath& path,
573 const SkMaskGamma::PreBlend& maskPreBlend) {
574 SkPaint paint;
576 int srcW = mask.fBounds.width();
577 int srcH = mask.fBounds.height();
578 int dstW = srcW;
579 int dstH = srcH;
580 int dstRB = mask.fRowBytes;
582 SkMatrix matrix;
583 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
584 -SkIntToScalar(mask.fBounds.fTop));
586 SkBitmap::Config config = SkBitmap::kA8_Config;
587 paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat);
588 switch (mask.fFormat) {
589 case SkMask::kBW_Format:
590 dstRB = 0; // signals we need a copy
591 break;
592 case SkMask::kA8_Format:
593 break;
594 case SkMask::kLCD16_Format:
595 case SkMask::kLCD32_Format:
596 // TODO: trigger off LCD orientation
597 dstW = 4*dstW - 8;
598 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1),
599 -SkIntToScalar(mask.fBounds.fTop));
600 matrix.postScale(SkIntToScalar(4), SK_Scalar1);
601 dstRB = 0; // signals we need a copy
602 break;
603 default:
604 SkDEBUGFAIL("unexpected mask format");
605 }
607 SkRasterClip clip;
608 clip.setRect(SkIRect::MakeWH(dstW, dstH));
610 SkBitmap bm;
611 bm.setConfig(config, dstW, dstH, dstRB);
613 if (0 == dstRB) {
614 if (!bm.allocPixels()) {
615 // can't allocate offscreen, so empty the mask and return
616 sk_bzero(mask.fImage, mask.computeImageSize());
617 return;
618 }
619 bm.lockPixels();
620 } else {
621 bm.setPixels(mask.fImage);
622 }
623 sk_bzero(bm.getPixels(), bm.getSafeSize());
625 SkDraw draw;
626 draw.fRC = &clip;
627 draw.fClip = &clip.bwRgn();
628 draw.fMatrix = &matrix;
629 draw.fBitmap = &bm;
630 draw.drawPath(path, paint);
632 switch (mask.fFormat) {
633 case SkMask::kBW_Format:
634 packA8ToA1(mask, bm.getAddr8(0, 0), bm.rowBytes());
635 break;
636 case SkMask::kA8_Format:
637 if (maskPreBlend.isApplicable()) {
638 applyLUTToA8Mask(mask, maskPreBlend.fG);
639 }
640 break;
641 case SkMask::kLCD16_Format:
642 if (maskPreBlend.isApplicable()) {
643 pack4xHToLCD16<true>(bm, mask, maskPreBlend);
644 } else {
645 pack4xHToLCD16<false>(bm, mask, maskPreBlend);
646 }
647 break;
648 case SkMask::kLCD32_Format:
649 if (maskPreBlend.isApplicable()) {
650 pack4xHToLCD32<true>(bm, mask, maskPreBlend);
651 } else {
652 pack4xHToLCD32<false>(bm, mask, maskPreBlend);
653 }
654 break;
655 default:
656 break;
657 }
658 }
660 static void extract_alpha(const SkMask& dst,
661 const SkPMColor* srcRow, size_t srcRB) {
662 int width = dst.fBounds.width();
663 int height = dst.fBounds.height();
664 int dstRB = dst.fRowBytes;
665 uint8_t* dstRow = dst.fImage;
667 for (int y = 0; y < height; ++y) {
668 for (int x = 0; x < width; ++x) {
669 dstRow[x] = SkGetPackedA32(srcRow[x]);
670 }
671 // zero any padding on each row
672 for (int x = width; x < dstRB; ++x) {
673 dstRow[x] = 0;
674 }
675 dstRow += dstRB;
676 srcRow = (const SkPMColor*)((const char*)srcRow + srcRB);
677 }
678 }
680 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
681 const SkGlyph* glyph = &origGlyph;
682 SkGlyph tmpGlyph;
684 // in case we need to call generateImage on a mask-format that is different
685 // (i.e. larger) than what our caller allocated by looking at origGlyph.
686 SkAutoMalloc tmpGlyphImageStorage;
688 // If we are going to draw-from-path, then we cannot generate color, since
689 // the path only makes a mask. This case should have been caught up in
690 // generateMetrics().
691 SkASSERT(!fGenerateImageFromPath ||
692 SkMask::kARGB32_Format != origGlyph.fMaskFormat);
694 if (fMaskFilter) { // restore the prefilter bounds
695 tmpGlyph.init(origGlyph.fID);
697 // need the original bounds, sans our maskfilter
698 SkMaskFilter* mf = fMaskFilter;
699 fMaskFilter = NULL; // temp disable
700 this->getMetrics(&tmpGlyph);
701 fMaskFilter = mf; // restore
703 // we need the prefilter bounds to be <= filter bounds
704 SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
705 SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
707 if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) {
708 tmpGlyph.fImage = origGlyph.fImage;
709 } else {
710 tmpGlyphImageStorage.reset(tmpGlyph.computeImageSize());
711 tmpGlyph.fImage = tmpGlyphImageStorage.get();
712 }
713 glyph = &tmpGlyph;
714 }
716 if (fGenerateImageFromPath) {
717 SkPath devPath, fillPath;
718 SkMatrix fillToDevMatrix;
719 SkMask mask;
721 this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
722 glyph->toMask(&mask);
724 if (fRasterizer) {
725 mask.fFormat = SkMask::kA8_Format;
726 sk_bzero(glyph->fImage, mask.computeImageSize());
728 if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
729 fMaskFilter, &mask,
730 SkMask::kJustRenderImage_CreateMode)) {
731 return;
732 }
733 if (fPreBlend.isApplicable()) {
734 applyLUTToA8Mask(mask, fPreBlend.fG);
735 }
736 } else {
737 SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
738 generateMask(mask, devPath, fPreBlend);
739 }
740 } else {
741 this->getGlyphContext(*glyph)->generateImage(*glyph);
742 }
744 if (fMaskFilter) {
745 SkMask srcM, dstM;
746 SkMatrix matrix;
748 // the src glyph image shouldn't be 3D
749 SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
751 SkAutoSMalloc<32*32> a8storage;
752 glyph->toMask(&srcM);
753 if (SkMask::kARGB32_Format == srcM.fFormat) {
754 // now we need to extract the alpha-channel from the glyph's image
755 // and copy it into a temp buffer, and then point srcM at that temp.
756 srcM.fFormat = SkMask::kA8_Format;
757 srcM.fRowBytes = SkAlign4(srcM.fBounds.width());
758 size_t size = srcM.computeImageSize();
759 a8storage.reset(size);
760 srcM.fImage = (uint8_t*)a8storage.get();
761 extract_alpha(srcM,
762 (const SkPMColor*)glyph->fImage, glyph->rowBytes());
763 }
765 fRec.getMatrixFrom2x2(&matrix);
767 if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
768 int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
769 int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
770 int dstRB = origGlyph.rowBytes();
771 int srcRB = dstM.fRowBytes;
773 const uint8_t* src = (const uint8_t*)dstM.fImage;
774 uint8_t* dst = (uint8_t*)origGlyph.fImage;
776 if (SkMask::k3D_Format == dstM.fFormat) {
777 // we have to copy 3 times as much
778 height *= 3;
779 }
781 // clean out our glyph, since it may be larger than dstM
782 //sk_bzero(dst, height * dstRB);
784 while (--height >= 0) {
785 memcpy(dst, src, width);
786 src += srcRB;
787 dst += dstRB;
788 }
789 SkMask::FreeImage(dstM.fImage);
791 if (fPreBlendForFilter.isApplicable()) {
792 applyLUTToA8Mask(srcM, fPreBlendForFilter.fG);
793 }
794 }
795 }
796 }
798 void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
799 this->internalGetPath(glyph, NULL, path, NULL);
800 }
802 void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* fm) {
803 // All of this complexity should go away when we change generateFontMetrics
804 // to just take one parameter (since it knows if it is vertical or not)
805 SkPaint::FontMetrics* mx = NULL;
806 SkPaint::FontMetrics* my = NULL;
807 if (fRec.fFlags & kVertical_Flag) {
808 mx = fm;
809 } else {
810 my = fm;
811 }
812 this->generateFontMetrics(mx, my);
813 }
815 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
816 return 0;
817 }
819 ///////////////////////////////////////////////////////////////////////////////
821 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
822 SkPath* devPath, SkMatrix* fillToDevMatrix) {
823 SkPath path;
825 this->getGlyphContext(glyph)->generatePath(glyph, &path);
827 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
828 SkFixed dx = glyph.getSubXFixed();
829 SkFixed dy = glyph.getSubYFixed();
830 if (dx | dy) {
831 path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
832 }
833 }
835 if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
836 // need the path in user-space, with only the point-size applied
837 // so that our stroking and effects will operate the same way they
838 // would if the user had extracted the path themself, and then
839 // called drawPath
840 SkPath localPath;
841 SkMatrix matrix, inverse;
843 fRec.getMatrixFrom2x2(&matrix);
844 if (!matrix.invert(&inverse)) {
845 // assume fillPath and devPath are already empty.
846 return;
847 }
848 path.transform(inverse, &localPath);
849 // now localPath is only affected by the paint settings, and not the canvas matrix
851 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
853 if (fRec.fFrameWidth > 0) {
854 rec.setStrokeStyle(fRec.fFrameWidth,
855 SkToBool(fRec.fFlags & kFrameAndFill_Flag));
856 // glyphs are always closed contours, so cap type is ignored,
857 // so we just pass something.
858 rec.setStrokeParams(SkPaint::kButt_Cap,
859 (SkPaint::Join)fRec.fStrokeJoin,
860 fRec.fMiterLimit);
861 }
863 if (fPathEffect) {
864 SkPath effectPath;
865 if (fPathEffect->filterPath(&effectPath, localPath, &rec, NULL)) {
866 localPath.swap(effectPath);
867 }
868 }
870 if (rec.needToApply()) {
871 SkPath strokePath;
872 if (rec.applyToPath(&strokePath, localPath)) {
873 localPath.swap(strokePath);
874 }
875 }
877 // now return stuff to the caller
878 if (fillToDevMatrix) {
879 *fillToDevMatrix = matrix;
880 }
881 if (devPath) {
882 localPath.transform(matrix, devPath);
883 }
884 if (fillPath) {
885 fillPath->swap(localPath);
886 }
887 } else { // nothing tricky to do
888 if (fillToDevMatrix) {
889 fillToDevMatrix->reset();
890 }
891 if (devPath) {
892 if (fillPath == NULL) {
893 devPath->swap(path);
894 } else {
895 *devPath = path;
896 }
897 }
899 if (fillPath) {
900 fillPath->swap(path);
901 }
902 }
904 if (devPath) {
905 devPath->updateBoundsCache();
906 }
907 if (fillPath) {
908 fillPath->updateBoundsCache();
909 }
910 }
913 void SkScalerContextRec::getMatrixFrom2x2(SkMatrix* dst) const {
914 dst->setAll(fPost2x2[0][0], fPost2x2[0][1], 0,
915 fPost2x2[1][0], fPost2x2[1][1], 0,
916 0, 0, SkScalarToPersp(SK_Scalar1));
917 }
919 void SkScalerContextRec::getLocalMatrix(SkMatrix* m) const {
920 SkPaint::SetTextMatrix(m, fTextSize, fPreScaleX, fPreSkewX);
921 }
923 void SkScalerContextRec::getSingleMatrix(SkMatrix* m) const {
924 this->getLocalMatrix(m);
926 // now concat the device matrix
927 SkMatrix deviceMatrix;
928 this->getMatrixFrom2x2(&deviceMatrix);
929 m->postConcat(deviceMatrix);
930 }
932 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
933 SkASSERT(!matrix.hasPerspective());
935 if (0 == matrix[SkMatrix::kMSkewY]) {
936 return kX_SkAxisAlignment;
937 }
938 if (0 == matrix[SkMatrix::kMScaleX]) {
939 return kY_SkAxisAlignment;
940 }
941 return kNone_SkAxisAlignment;
942 }
944 ///////////////////////////////////////////////////////////////////////////////
946 #include "SkFontHost.h"
948 class SkScalerContext_Empty : public SkScalerContext {
949 public:
950 SkScalerContext_Empty(SkTypeface* face, const SkDescriptor* desc)
951 : SkScalerContext(face, desc) {}
953 protected:
954 virtual unsigned generateGlyphCount() SK_OVERRIDE {
955 return 0;
956 }
957 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE {
958 return 0;
959 }
960 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE {
961 glyph->zeroMetrics();
962 }
963 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE {
964 glyph->zeroMetrics();
965 }
966 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE {}
967 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE {}
968 virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
969 SkPaint::FontMetrics* my) SK_OVERRIDE {
970 if (mx) {
971 sk_bzero(mx, sizeof(*mx));
972 }
973 if (my) {
974 sk_bzero(my, sizeof(*my));
975 }
976 }
977 };
979 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
981 SkScalerContext* SkTypeface::createScalerContext(const SkDescriptor* desc,
982 bool allowFailure) const {
983 SkScalerContext* c = this->onCreateScalerContext(desc);
985 if (!c && !allowFailure) {
986 c = SkNEW_ARGS(SkScalerContext_Empty,
987 (const_cast<SkTypeface*>(this), desc));
988 }
989 return c;
990 }