Line data Source code
1 : /*
2 : * Copyright 2006-2012 The Android Open Source Project
3 : * Copyright 2012 Mozilla Foundation
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 : #include "SkBitmap.h"
10 : #include "SkCanvas.h"
11 : #include "SkColor.h"
12 : #include "SkColorPriv.h"
13 : #include "SkFDot6.h"
14 : #include "SkFontHost_FreeType_common.h"
15 : #include "SkPath.h"
16 :
17 : #include <ft2build.h>
18 : #include FT_FREETYPE_H
19 : #include FT_BITMAP_H
20 : #include FT_IMAGE_H
21 : #include FT_OUTLINE_H
22 : // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
23 : #include FT_SYNTHESIS_H
24 :
25 : // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
26 : // were introduced in FreeType 2.5.0.
27 : // The following may be removed once FreeType 2.5.0 is required to build.
28 : #ifndef FT_LOAD_COLOR
29 : # define FT_LOAD_COLOR ( 1L << 20 )
30 : # define FT_PIXEL_MODE_BGRA 7
31 : #endif
32 :
33 : //#define SK_SHOW_TEXT_BLIT_COVERAGE
34 :
35 : namespace {
36 :
37 0 : FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
38 0 : switch (format) {
39 : case SkMask::kBW_Format:
40 0 : return FT_PIXEL_MODE_MONO;
41 : case SkMask::kA8_Format:
42 : default:
43 0 : return FT_PIXEL_MODE_GRAY;
44 : }
45 : }
46 :
47 : ///////////////////////////////////////////////////////////////////////////////
48 :
49 17191 : uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
50 : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
51 : r = SkTMax(r, (U8CPU)0x40);
52 : g = SkTMax(g, (U8CPU)0x40);
53 : b = SkTMax(b, (U8CPU)0x40);
54 : #endif
55 17191 : return SkPack888ToRGB16(r, g, b);
56 : }
57 :
58 0 : uint16_t grayToRGB16(U8CPU gray) {
59 : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
60 : gray = SkTMax(gray, (U8CPU)0x40);
61 : #endif
62 0 : return SkPack888ToRGB16(gray, gray, gray);
63 : }
64 :
65 0 : int bittst(const uint8_t data[], int bitOffset) {
66 0 : SkASSERT(bitOffset >= 0);
67 0 : int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7);
68 0 : return lowBit & 1;
69 : }
70 :
71 : /**
72 : * Copies a FT_Bitmap into an SkMask with the same dimensions.
73 : *
74 : * FT_PIXEL_MODE_MONO
75 : * FT_PIXEL_MODE_GRAY
76 : * FT_PIXEL_MODE_LCD
77 : * FT_PIXEL_MODE_LCD_V
78 : */
79 : template<bool APPLY_PREBLEND>
80 58 : void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR,
81 : const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB)
82 : {
83 58 : SkASSERT(SkMask::kLCD16_Format == mask.fFormat);
84 58 : if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) {
85 0 : SkASSERT(mask.fBounds.width() == static_cast<int>(bitmap.width));
86 : }
87 58 : if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) {
88 58 : SkASSERT(mask.fBounds.height() == static_cast<int>(bitmap.rows));
89 : }
90 :
91 58 : const uint8_t* src = bitmap.buffer;
92 58 : uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage);
93 58 : const size_t dstRB = mask.fRowBytes;
94 :
95 58 : const int width = mask.fBounds.width();
96 58 : const int height = mask.fBounds.height();
97 :
98 58 : switch (bitmap.pixel_mode) {
99 : case FT_PIXEL_MODE_MONO:
100 0 : for (int y = height; y --> 0;) {
101 0 : for (int x = 0; x < width; ++x) {
102 0 : dst[x] = -bittst(src, x);
103 : }
104 0 : dst = (uint16_t*)((char*)dst + dstRB);
105 0 : src += bitmap.pitch;
106 : }
107 0 : break;
108 : case FT_PIXEL_MODE_GRAY:
109 0 : for (int y = height; y --> 0;) {
110 0 : for (int x = 0; x < width; ++x) {
111 0 : dst[x] = grayToRGB16(src[x]);
112 : }
113 0 : dst = (uint16_t*)((char*)dst + dstRB);
114 0 : src += bitmap.pitch;
115 : }
116 0 : break;
117 : case FT_PIXEL_MODE_LCD:
118 58 : SkASSERT(3 * mask.fBounds.width() == static_cast<int>(bitmap.width));
119 1104 : for (int y = height; y --> 0;) {
120 1046 : const uint8_t* triple = src;
121 1046 : if (lcdIsBGR) {
122 0 : for (int x = 0; x < width; x++) {
123 0 : dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR),
124 0 : sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
125 0 : sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB));
126 0 : triple += 3;
127 : }
128 : } else {
129 18237 : for (int x = 0; x < width; x++) {
130 51573 : dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR),
131 17191 : sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
132 17191 : sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB));
133 17191 : triple += 3;
134 : }
135 : }
136 1046 : src += bitmap.pitch;
137 1046 : dst = (uint16_t*)((char*)dst + dstRB);
138 : }
139 58 : break;
140 : case FT_PIXEL_MODE_LCD_V:
141 0 : SkASSERT(3 * mask.fBounds.height() == static_cast<int>(bitmap.rows));
142 0 : for (int y = height; y --> 0;) {
143 0 : const uint8_t* srcR = src;
144 0 : const uint8_t* srcG = srcR + bitmap.pitch;
145 0 : const uint8_t* srcB = srcG + bitmap.pitch;
146 0 : if (lcdIsBGR) {
147 0 : SkTSwap(srcR, srcB);
148 : }
149 0 : for (int x = 0; x < width; x++) {
150 0 : dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR),
151 : sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG),
152 : sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB));
153 : }
154 0 : src += 3 * bitmap.pitch;
155 0 : dst = (uint16_t*)((char*)dst + dstRB);
156 : }
157 0 : break;
158 : default:
159 0 : SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode));
160 0 : SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16");
161 0 : break;
162 : }
163 58 : }
164 :
165 : /**
166 : * Copies a FT_Bitmap into an SkMask with the same dimensions.
167 : *
168 : * Yes, No, Never Requested, Never Produced
169 : *
170 : * kBW kA8 k3D kARGB32 kLCD16
171 : * FT_PIXEL_MODE_MONO Y Y NR N Y
172 : * FT_PIXEL_MODE_GRAY N Y NR N Y
173 : * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP
174 : * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP
175 : * FT_PIXEL_MODE_LCD NP NP NR NP NP
176 : * FT_PIXEL_MODE_LCD_V NP NP NR NP NP
177 : * FT_PIXEL_MODE_BGRA N N NR Y N
178 : *
179 : * TODO: All of these N need to be Y or otherwise ruled out.
180 : */
181 0 : void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
182 0 : SkASSERTF(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width),
183 : "dstMask.fBounds.width() = %d\n"
184 : "static_cast<int>(srcFTBitmap.width) = %d",
185 : dstMask.fBounds.width(),
186 : static_cast<int>(srcFTBitmap.width)
187 : );
188 0 : SkASSERTF(dstMask.fBounds.height() == static_cast<int>(srcFTBitmap.rows),
189 : "dstMask.fBounds.height() = %d\n"
190 : "static_cast<int>(srcFTBitmap.rows) = %d",
191 : dstMask.fBounds.height(),
192 : static_cast<int>(srcFTBitmap.rows)
193 : );
194 :
195 0 : const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer);
196 0 : const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel_mode);
197 : // FT_Bitmap::pitch is an int and allowed to be negative.
198 0 : const int srcPitch = srcFTBitmap.pitch;
199 0 : const size_t srcRowBytes = SkTAbs(srcPitch);
200 :
201 0 : uint8_t* dst = dstMask.fImage;
202 0 : const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat);
203 0 : const size_t dstRowBytes = dstMask.fRowBytes;
204 :
205 0 : const size_t width = srcFTBitmap.width;
206 0 : const size_t height = srcFTBitmap.rows;
207 :
208 0 : if (SkMask::kLCD16_Format == dstFormat) {
209 0 : copyFT2LCD16<false>(srcFTBitmap, dstMask, false, nullptr, nullptr, nullptr);
210 0 : return;
211 : }
212 :
213 0 : if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) ||
214 0 : (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat))
215 : {
216 0 : size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes);
217 0 : for (size_t y = height; y --> 0;) {
218 0 : memcpy(dst, src, commonRowBytes);
219 0 : src += srcPitch;
220 0 : dst += dstRowBytes;
221 0 : }
222 0 : } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) {
223 0 : for (size_t y = height; y --> 0;) {
224 0 : uint8_t byte = 0;
225 0 : int bits = 0;
226 0 : const uint8_t* src_row = src;
227 0 : uint8_t* dst_row = dst;
228 0 : for (size_t x = width; x --> 0;) {
229 0 : if (0 == bits) {
230 0 : byte = *src_row++;
231 0 : bits = 8;
232 : }
233 0 : *dst_row++ = byte & 0x80 ? 0xff : 0x00;
234 0 : bits--;
235 0 : byte <<= 1;
236 : }
237 0 : src += srcPitch;
238 0 : dst += dstRowBytes;
239 0 : }
240 0 : } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) {
241 : // FT_PIXEL_MODE_BGRA is pre-multiplied.
242 0 : for (size_t y = height; y --> 0;) {
243 0 : const uint8_t* src_row = src;
244 0 : SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst);
245 0 : for (size_t x = 0; x < width; ++x) {
246 0 : uint8_t b = *src_row++;
247 0 : uint8_t g = *src_row++;
248 0 : uint8_t r = *src_row++;
249 0 : uint8_t a = *src_row++;
250 0 : *dst_row++ = SkPackARGB32(a, r, g, b);
251 : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
252 : *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE, 0x40);
253 : #endif
254 : }
255 0 : src += srcPitch;
256 0 : dst += dstRowBytes;
257 0 : }
258 : } else {
259 0 : SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat));
260 0 : SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format");
261 : }
262 : }
263 :
264 0 : inline int convert_8_to_1(unsigned byte) {
265 0 : SkASSERT(byte <= 0xFF);
266 : // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better.
267 0 : return (byte >> 6) != 0;
268 : }
269 :
270 0 : uint8_t pack_8_to_1(const uint8_t alpha[8]) {
271 0 : unsigned bits = 0;
272 0 : for (int i = 0; i < 8; ++i) {
273 0 : bits <<= 1;
274 0 : bits |= convert_8_to_1(alpha[i]);
275 : }
276 0 : return SkToU8(bits);
277 : }
278 :
279 0 : void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
280 0 : const int height = mask.fBounds.height();
281 0 : const int width = mask.fBounds.width();
282 0 : const int octs = width >> 3;
283 0 : const int leftOverBits = width & 7;
284 :
285 0 : uint8_t* dst = mask.fImage;
286 0 : const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
287 0 : SkASSERT(dstPad >= 0);
288 :
289 0 : const int srcPad = srcRB - width;
290 0 : SkASSERT(srcPad >= 0);
291 :
292 0 : for (int y = 0; y < height; ++y) {
293 0 : for (int i = 0; i < octs; ++i) {
294 0 : *dst++ = pack_8_to_1(src);
295 0 : src += 8;
296 : }
297 0 : if (leftOverBits > 0) {
298 0 : unsigned bits = 0;
299 0 : int shift = 7;
300 0 : for (int i = 0; i < leftOverBits; ++i, --shift) {
301 0 : bits |= convert_8_to_1(*src++) << shift;
302 : }
303 0 : *dst++ = bits;
304 : }
305 0 : src += srcPad;
306 0 : dst += dstPad;
307 : }
308 0 : }
309 :
310 0 : inline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) {
311 0 : switch (colorType) {
312 : case kAlpha_8_SkColorType:
313 0 : return SkMask::kA8_Format;
314 : case kN32_SkColorType:
315 0 : return SkMask::kARGB32_Format;
316 : default:
317 0 : SkDEBUGFAIL("unsupported SkBitmap::Config");
318 0 : return SkMask::kA8_Format;
319 : }
320 : }
321 :
322 0 : inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
323 0 : switch (pixel_mode) {
324 : case FT_PIXEL_MODE_MONO:
325 : case FT_PIXEL_MODE_GRAY:
326 0 : return kAlpha_8_SkColorType;
327 : case FT_PIXEL_MODE_BGRA:
328 0 : return kN32_SkColorType;
329 : default:
330 0 : SkDEBUGFAIL("unsupported FT_PIXEL_MODE");
331 0 : return kAlpha_8_SkColorType;
332 : }
333 : }
334 :
335 0 : inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) {
336 0 : switch (format) {
337 : case SkMask::kBW_Format:
338 : case SkMask::kA8_Format:
339 : case SkMask::kLCD16_Format:
340 0 : return kAlpha_8_SkColorType;
341 : case SkMask::kARGB32_Format:
342 0 : return kN32_SkColorType;
343 : default:
344 0 : SkDEBUGFAIL("unsupported destination SkBitmap::Config");
345 0 : return kAlpha_8_SkColorType;
346 : }
347 : }
348 :
349 : #ifdef SK_DEBUG
350 :
351 : # define SK_STRING(X) SK_STRING_IMPL(X)
352 : # define SK_STRING_IMPL(X) #X
353 :
354 : # undef __FTERRORS_H__
355 : # define FT_ERROR_START_LIST
356 : # define FT_ERRORDEF(e, v, s) { SK_STRING(e), s },
357 : # define FT_ERROR_END_LIST
358 :
359 : const struct {
360 : const char* err_code;
361 : const char* err_msg;
362 : } sk_ft_errors[] = {
363 : # include FT_ERRORS_H
364 : };
365 :
366 0 : void SkTraceFTR(const char* file, unsigned long line, FT_Error err, const char* msg) {
367 0 : SkString s;
368 0 : s.printf("%s:%lu:1: error: 0x%x ", file, line, err);
369 0 : if (0 <= err && (unsigned)err < SK_ARRAY_COUNT(sk_ft_errors)) {
370 0 : s.appendf("%s '%s' ", sk_ft_errors[err].err_code, sk_ft_errors[err].err_msg);
371 : } else {
372 0 : s.appendf("<unknown> ");
373 : }
374 0 : if (msg) {
375 0 : s.appendf("%s", msg);
376 : }
377 0 : SkDebugf("%s\n", s.c_str());
378 0 : }
379 :
380 : # define SK_TRACEFTR(_err, _msg) SkTraceFTR(__FILE__, __LINE__, _err, _msg)
381 : #else
382 : # define SK_TRACEFTR(_err, _msg) sk_ignore_unused_variable(_err)
383 : #endif
384 :
385 : } // namespace
386 :
387 58 : void SkScalerContext_FreeType_Base::generateGlyphImage(
388 : FT_Face face,
389 : const SkGlyph& glyph,
390 : const SkMatrix& bitmapTransform)
391 : {
392 58 : const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
393 58 : const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
394 :
395 58 : switch ( face->glyph->format ) {
396 : case FT_GLYPH_FORMAT_OUTLINE: {
397 58 : FT_Outline* outline = &face->glyph->outline;
398 : FT_BBox bbox;
399 : FT_Bitmap target;
400 :
401 58 : int dx = 0, dy = 0;
402 58 : if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
403 0 : dx = SkFixedToFDot6(glyph.getSubXFixed());
404 0 : dy = SkFixedToFDot6(glyph.getSubYFixed());
405 : // negate dy since freetype-y-goes-up and skia-y-goes-down
406 0 : dy = -dy;
407 : }
408 58 : FT_Outline_Get_CBox(outline, &bbox);
409 : /*
410 : what we really want to do for subpixel is
411 : offset(dx, dy)
412 : compute_bounds
413 : offset(bbox & !63)
414 : but that is two calls to offset, so we do the following, which
415 : achieves the same thing with only one offset call.
416 : */
417 116 : FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
418 116 : dy - ((bbox.yMin + dy) & ~63));
419 :
420 58 : if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
421 58 : FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
422 58 : FT_RENDER_MODE_LCD);
423 58 : if (err) {
424 0 : SK_TRACEFTR(err, "Could not render glyph.");
425 0 : sk_bzero(glyph.fImage, glyph.computeImageSize());
426 0 : return;
427 : }
428 58 : SkMask mask;
429 58 : glyph.toMask(&mask);
430 58 : if (fPreBlend.isApplicable()) {
431 0 : copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
432 0 : fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
433 : } else {
434 58 : copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
435 116 : fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
436 : }
437 : } else {
438 0 : target.width = glyph.fWidth;
439 0 : target.rows = glyph.fHeight;
440 0 : target.pitch = glyph.rowBytes();
441 0 : target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
442 0 : target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
443 0 : target.num_grays = 256;
444 :
445 0 : memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
446 0 : FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
447 : }
448 58 : } break;
449 :
450 : case FT_GLYPH_FORMAT_BITMAP: {
451 0 : FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
452 0 : SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
453 :
454 : // Assume that the other formats do not exist.
455 0 : SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
456 : FT_PIXEL_MODE_GRAY == pixel_mode ||
457 : FT_PIXEL_MODE_BGRA == pixel_mode);
458 :
459 : // These are the only formats this ScalerContext should request.
460 0 : SkASSERT(SkMask::kBW_Format == maskFormat ||
461 : SkMask::kA8_Format == maskFormat ||
462 : SkMask::kARGB32_Format == maskFormat ||
463 : SkMask::kLCD16_Format == maskFormat);
464 :
465 : // If no scaling needed, directly copy glyph bitmap.
466 0 : if (bitmapTransform.isIdentity()) {
467 0 : SkMask dstMask;
468 0 : glyph.toMask(&dstMask);
469 0 : copyFTBitmap(face->glyph->bitmap, dstMask);
470 0 : break;
471 : }
472 :
473 : // Otherwise, scale the bitmap.
474 :
475 : // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
476 0 : SkBitmap unscaledBitmap;
477 : // TODO: mark this as sRGB when the blits will be sRGB.
478 0 : unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
479 0 : face->glyph->bitmap.rows,
480 : SkColorType_for_FTPixelMode(pixel_mode),
481 0 : kPremul_SkAlphaType));
482 :
483 0 : SkMask unscaledBitmapAlias;
484 0 : unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
485 0 : unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height());
486 0 : unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
487 0 : unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
488 0 : copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
489 :
490 : // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
491 : // BW requires an A8 target for resizing, which can then be down sampled.
492 : // LCD should use a 4x A8 target, which will then be down sampled.
493 : // For simplicity, LCD uses A8 and is replicated.
494 0 : int bitmapRowBytes = 0;
495 0 : if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) {
496 0 : bitmapRowBytes = glyph.rowBytes();
497 : }
498 0 : SkBitmap dstBitmap;
499 : // TODO: mark this as sRGB when the blits will be sRGB.
500 0 : dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
501 : SkColorType_for_SkMaskFormat(maskFormat),
502 : kPremul_SkAlphaType),
503 0 : bitmapRowBytes);
504 0 : if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
505 0 : dstBitmap.allocPixels();
506 : } else {
507 0 : dstBitmap.setPixels(glyph.fImage);
508 : }
509 :
510 : // Scale unscaledBitmap into dstBitmap.
511 0 : SkCanvas canvas(dstBitmap);
512 : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
513 : canvas.clear(0x33FF0000);
514 : #else
515 0 : canvas.clear(SK_ColorTRANSPARENT);
516 : #endif
517 0 : canvas.translate(-glyph.fLeft, -glyph.fTop);
518 0 : canvas.concat(bitmapTransform);
519 0 : canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top);
520 :
521 0 : SkPaint paint;
522 0 : paint.setFilterQuality(kMedium_SkFilterQuality);
523 0 : canvas.drawBitmap(unscaledBitmap, 0, 0, &paint);
524 :
525 : // If the destination is BW or LCD, convert from A8.
526 0 : if (SkMask::kBW_Format == maskFormat) {
527 : // Copy the A8 dstBitmap into the A1 glyph.fImage.
528 0 : SkMask dstMask;
529 0 : glyph.toMask(&dstMask);
530 0 : packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes());
531 0 : } else if (SkMask::kLCD16_Format == maskFormat) {
532 : // Copy the A8 dstBitmap into the LCD16 glyph.fImage.
533 0 : uint8_t* src = dstBitmap.getAddr8(0, 0);
534 0 : uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
535 0 : for (int y = dstBitmap.height(); y --> 0;) {
536 0 : for (int x = 0; x < dstBitmap.width(); ++x) {
537 0 : dst[x] = grayToRGB16(src[x]);
538 : }
539 0 : dst = (uint16_t*)((char*)dst + glyph.rowBytes());
540 0 : src += dstBitmap.rowBytes();
541 : }
542 : }
543 :
544 0 : } break;
545 :
546 : default:
547 0 : SkDEBUGFAIL("unknown glyph format");
548 0 : memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
549 0 : return;
550 : }
551 :
552 : // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum,
553 : // it is optional
554 : #if defined(SK_GAMMA_APPLY_TO_A8)
555 : if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) {
556 : uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
557 : unsigned rowBytes = glyph.rowBytes();
558 :
559 : for (int y = glyph.fHeight - 1; y >= 0; --y) {
560 : for (int x = glyph.fWidth - 1; x >= 0; --x) {
561 : dst[x] = fPreBlend.fG[dst[x]];
562 : }
563 : dst += rowBytes;
564 : }
565 : }
566 : #endif
567 : }
568 :
569 : ///////////////////////////////////////////////////////////////////////////////
570 :
571 : namespace {
572 :
573 0 : int move_proc(const FT_Vector* pt, void* ctx) {
574 0 : SkPath* path = (SkPath*)ctx;
575 0 : path->close(); // to close the previous contour (if any)
576 0 : path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
577 0 : return 0;
578 : }
579 :
580 0 : int line_proc(const FT_Vector* pt, void* ctx) {
581 0 : SkPath* path = (SkPath*)ctx;
582 0 : path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
583 0 : return 0;
584 : }
585 :
586 0 : int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
587 : void* ctx) {
588 0 : SkPath* path = (SkPath*)ctx;
589 0 : path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
590 0 : SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
591 0 : return 0;
592 : }
593 :
594 0 : int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
595 : const FT_Vector* pt2, void* ctx) {
596 0 : SkPath* path = (SkPath*)ctx;
597 0 : path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
598 0 : SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
599 0 : SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
600 0 : return 0;
601 : }
602 :
603 : } // namespace
604 :
605 0 : void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
606 : FT_Outline_Funcs funcs;
607 :
608 0 : funcs.move_to = move_proc;
609 0 : funcs.line_to = line_proc;
610 0 : funcs.conic_to = quad_proc;
611 0 : funcs.cubic_to = cubic_proc;
612 0 : funcs.shift = 0;
613 0 : funcs.delta = 0;
614 :
615 0 : FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path);
616 :
617 0 : if (err != 0) {
618 0 : path->reset();
619 0 : return;
620 : }
621 :
622 0 : path->close();
623 : }
|