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_OUTLINE_H 19 #include FT_BITMAP_H 20 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 21 #include FT_SYNTHESIS_H 22 23 static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { 24 switch (format) { 25 case SkMask::kBW_Format: 26 return FT_PIXEL_MODE_MONO; 27 case SkMask::kA8_Format: 28 default: 29 return FT_PIXEL_MODE_GRAY; 30 } 31 } 32 33 /////////////////////////////////////////////////////////////////////////////// 34 35 // hand-tuned value to reduce outline embolden strength 36 #ifndef SK_OUTLINE_EMBOLDEN_DIVISOR 37 #ifdef SK_BUILD_FOR_ANDROID 38 #define SK_OUTLINE_EMBOLDEN_DIVISOR 34 39 #else 40 #define SK_OUTLINE_EMBOLDEN_DIVISOR 24 41 #endif 42 #endif 43 44 /////////////////////////////////////////////////////////////////////////////// 45 46 static uint16_t packTriple(unsigned r, unsigned g, unsigned b) { 47 return SkPackRGB16(r >> 3, g >> 2, b >> 3); 48 } 49 50 static uint16_t grayToRGB16(U8CPU gray) { 51 SkASSERT(gray <= 255); 52 return SkPackRGB16(gray >> 3, gray >> 2, gray >> 3); 53 } 54 55 static int bittst(const uint8_t data[], int bitOffset) { 56 SkASSERT(bitOffset >= 0); 57 int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); 58 return lowBit & 1; 59 } 60 61 template<bool APPLY_PREBLEND> 62 static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap, 63 int lcdIsBGR, bool lcdIsVert, const uint8_t* tableR, 64 const uint8_t* tableG, const uint8_t* tableB) { 65 if (lcdIsVert) { 66 SkASSERT(3 * glyph.fHeight == bitmap.rows); 67 } else { 68 SkASSERT(glyph.fHeight == bitmap.rows); 69 } 70 71 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); 72 const size_t dstRB = glyph.rowBytes(); 73 const int width = glyph.fWidth; 74 const uint8_t* src = bitmap.buffer; 75 76 switch (bitmap.pixel_mode) { 77 case FT_PIXEL_MODE_MONO: 78 for (int y = 0; y < glyph.fHeight; ++y) { 79 for (int x = 0; x < width; ++x) { 80 dst[x] = -bittst(src, x); 81 } 82 dst = (uint16_t*)((char*)dst + dstRB); 83 src += bitmap.pitch; 84 } 85 break; 86 case FT_PIXEL_MODE_GRAY: 87 for (int y = 0; y < glyph.fHeight; ++y) { 88 for (int x = 0; x < width; ++x) { 89 dst[x] = grayToRGB16(src[x]); 90 } 91 dst = (uint16_t*)((char*)dst + dstRB); 92 src += bitmap.pitch; 93 } 94 break; 95 default: 96 SkASSERT(lcdIsVert || (glyph.fWidth * 3 == bitmap.width)); 97 for (int y = 0; y < glyph.fHeight; y++) { 98 if (lcdIsVert) { // vertical stripes 99 const uint8_t* srcR = src; 100 const uint8_t* srcG = srcR + bitmap.pitch; 101 const uint8_t* srcB = srcG + bitmap.pitch; 102 if (lcdIsBGR) { 103 SkTSwap(srcR, srcB); 104 } 105 for (int x = 0; x < width; x++) { 106 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR), 107 sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG), 108 sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB)); 109 } 110 src += 3 * bitmap.pitch; 111 } else { // horizontal stripes 112 const uint8_t* triple = src; 113 if (lcdIsBGR) { 114 for (int x = 0; x < width; x++) { 115 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR), 116 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 117 sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB)); 118 triple += 3; 119 } 120 } else { 121 for (int x = 0; x < width; x++) { 122 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR), 123 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 124 sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB)); 125 triple += 3; 126 } 127 } 128 src += bitmap.pitch; 129 } 130 dst = (uint16_t*)((char*)dst + dstRB); 131 } 132 break; 133 } 134 } 135 136 // copies an FT_Bitmap's pixel data into a buffer with identical dimensions 137 static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, uint8_t* dst, uint8_t dstFormat, 138 size_t dstRowBytes) { 139 const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer); 140 size_t width = srcFTBitmap.width; 141 size_t height = srcFTBitmap.rows; 142 size_t srcRowBytes = srcFTBitmap.pitch; 143 144 if ((SkMask::kA8_Format == dstFormat && 145 FT_PIXEL_MODE_GRAY == srcFTBitmap.pixel_mode) || 146 (SkMask::kBW_Format == dstFormat && 147 FT_PIXEL_MODE_MONO == srcFTBitmap.pixel_mode)) { 148 // TODO: test 1bpp bitmap font into kBW_Format glyph 149 size_t minRowBytes = SkMin32(srcRowBytes, dstRowBytes); 150 size_t extraRowBytes = dstRowBytes - minRowBytes; 151 for (int y = height - 1; y >= 0; --y) { 152 memcpy(dst, src, minRowBytes); 153 memset(dst + minRowBytes, 0, extraRowBytes); 154 src += srcRowBytes; 155 dst += dstRowBytes; 156 } 157 } else if (SkMask::kA8_Format == dstFormat && 158 FT_PIXEL_MODE_MONO == srcFTBitmap.pixel_mode) { 159 // TODO: test 1bpp bitmap font into kA8_Format glyph 160 for (size_t y = 0; y < height; ++y) { 161 uint8_t byte = 0; 162 int bits = 0; 163 const uint8_t* src_row = src; 164 uint8_t* dst_row = dst; 165 for (size_t x = 0; x < width; ++x) { 166 if (!bits) { 167 byte = *src_row++; 168 bits = 8; 169 } 170 *dst_row++ = byte & 0x80 ? 0xff : 0; 171 bits--; 172 byte <<= 1; 173 } 174 src += srcRowBytes; 175 dst += dstRowBytes; 176 } 177 #ifdef FT_LOAD_COLOR 178 } else if (SkMask::kARGB32_Format == dstFormat && 179 FT_PIXEL_MODE_BGRA == srcFTBitmap.pixel_mode) { 180 size_t minWidth = SkMin32(width, SkMin32(srcRowBytes, dstRowBytes) / 4); 181 size_t extraRowBytes = dstRowBytes - (4 * minWidth); 182 for (size_t y = 0; y < height; ++y) { 183 const uint8_t* src_row = src; 184 uint8_t* dst_row = dst; 185 for (size_t x = 0; x < minWidth; ++x) { 186 uint8_t blue = *src_row++; 187 uint8_t green = *src_row++; 188 uint8_t red = *src_row++; 189 uint8_t alpha = *src_row++; 190 *dst_row++ = red; 191 *dst_row++ = green; 192 *dst_row++ = blue; 193 *dst_row++ = alpha; 194 } 195 memset(dst_row, 0, extraRowBytes); 196 src += srcRowBytes; 197 dst += dstRowBytes; 198 } 199 #endif 200 } else { 201 SkDEBUGFAIL("unsupported combination of FT_PIXEL_MODE and SkMask::Format"); 202 } 203 } 204 205 inline uint8_t skFormatForFTPixelMode(char pixel_mode) { 206 switch (pixel_mode) { 207 case FT_PIXEL_MODE_GRAY: 208 return SkMask::kA8_Format; 209 case FT_PIXEL_MODE_MONO: 210 return SkMask::kBW_Format; 211 #ifdef FT_LOAD_COLOR 212 case FT_PIXEL_MODE_BGRA: 213 return SkMask::kARGB32_Format; 214 #endif 215 default: 216 SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); 217 return SkMask::kA8_Format; 218 } 219 } 220 221 inline SkBitmap::Config skConfigForFTPixelMode(char pixel_mode) { 222 switch (pixel_mode) { 223 case FT_PIXEL_MODE_GRAY: 224 return SkBitmap::kA8_Config; 225 case FT_PIXEL_MODE_MONO: 226 return SkBitmap::kA1_Config; 227 #ifdef FT_LOAD_COLOR 228 case FT_PIXEL_MODE_BGRA: 229 return SkBitmap::kARGB_8888_Config; 230 #endif 231 default: 232 SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); 233 return SkBitmap::kA8_Config; 234 } 235 } 236 237 inline SkBitmap::Config skConfigForFormat(uint8_t format) { 238 switch (format) { 239 case SkMask::kA8_Format: 240 return SkBitmap::kA8_Config; 241 case SkMask::kBW_Format: 242 return SkBitmap::kA1_Config; 243 #ifdef FT_LOAD_COLOR 244 case SkMask::kARGB32_Format: 245 return SkBitmap::kARGB_8888_Config; 246 #endif 247 default: 248 SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); 249 return SkBitmap::kA8_Config; 250 } 251 } 252 253 void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGlyph& glyph) { 254 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag); 255 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 256 257 switch ( face->glyph->format ) { 258 case FT_GLYPH_FORMAT_OUTLINE: 259 { 260 FT_Outline* outline = &face->glyph->outline; 261 FT_BBox bbox; 262 FT_Bitmap target; 263 264 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && 265 !(face->style_flags & FT_STYLE_FLAG_BOLD)) { 266 emboldenOutline(face, outline); 267 } 268 269 int dx = 0, dy = 0; 270 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 271 dx = SkFixedToFDot6(glyph.getSubXFixed()); 272 dy = SkFixedToFDot6(glyph.getSubYFixed()); 273 // negate dy since freetype-y-goes-up and skia-y-goes-down 274 dy = -dy; 275 } 276 FT_Outline_Get_CBox(outline, &bbox); 277 /* 278 what we really want to do for subpixel is 279 offset(dx, dy) 280 compute_bounds 281 offset(bbox & !63) 282 but that is two calls to offset, so we do the following, which 283 achieves the same thing with only one offset call. 284 */ 285 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), 286 dy - ((bbox.yMin + dy) & ~63)); 287 288 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 289 FT_Render_Glyph(face->glyph, 290 doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD); 291 if (fPreBlend.isApplicable()) { 292 copyFT2LCD16<true>(glyph, face->glyph->bitmap, doBGR, doVert, 293 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 294 } else { 295 copyFT2LCD16<false>(glyph, face->glyph->bitmap, doBGR, doVert, 296 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 297 } 298 } else { 299 target.width = glyph.fWidth; 300 target.rows = glyph.fHeight; 301 target.pitch = glyph.rowBytes(); 302 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); 303 target.pixel_mode = compute_pixel_mode( 304 (SkMask::Format)fRec.fMaskFormat); 305 target.num_grays = 256; 306 307 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 308 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); 309 } 310 } 311 break; 312 313 case FT_GLYPH_FORMAT_BITMAP: 314 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && 315 !(face->style_flags & FT_STYLE_FLAG_BOLD)) { 316 FT_GlyphSlot_Own_Bitmap(face->glyph); 317 FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, kBitmapEmboldenStrength, 0); 318 } 319 320 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 321 // special-case kLCD16_Format - no scaling currently supported 322 SkASSERT_CONTINUE(glyph.fWidth == face->glyph->bitmap.width); 323 SkASSERT_CONTINUE(glyph.fHeight == face->glyph->bitmap.rows); 324 SkASSERT_CONTINUE(glyph.fTop == -face->glyph->bitmap_top); 325 SkASSERT_CONTINUE(glyph.fLeft == face->glyph->bitmap_left); 326 if (fPreBlend.isApplicable()) { 327 copyFT2LCD16<true>(glyph, face->glyph->bitmap, doBGR, doVert, 328 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 329 } else { 330 copyFT2LCD16<false>(glyph, face->glyph->bitmap, doBGR, doVert, 331 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 332 } 333 } else { 334 if (glyph.fWidth != face->glyph->bitmap.width || 335 glyph.fHeight != face->glyph->bitmap.rows || 336 glyph.fTop != -face->glyph->bitmap_top || 337 glyph.fLeft != face->glyph->bitmap_left) { 338 // glyph image needs scaling 339 // start by copying FT2 image into an SkBitmap 340 SkBitmap unscaledBitmap; 341 unscaledBitmap.setConfig(skConfigForFTPixelMode(face->glyph->bitmap.pixel_mode), 342 face->glyph->bitmap.width, 343 face->glyph->bitmap.rows); 344 unscaledBitmap.allocPixels(); 345 copyFTBitmap(face->glyph->bitmap, 346 reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels()), 347 skFormatForFTPixelMode(face->glyph->bitmap.pixel_mode), 348 unscaledBitmap.rowBytes()); 349 // wrap the destination SkGlyph's image data into a bitmap 350 SkBitmap dstBitmap; 351 dstBitmap.setConfig(skConfigForFormat(glyph.fMaskFormat), 352 glyph.fWidth, glyph.fHeight, glyph.rowBytes()); 353 dstBitmap.setPixels(glyph.fImage); 354 // scale unscaledBitmap into dstBitmap 355 SkCanvas canvas(dstBitmap); 356 canvas.clear(SK_ColorTRANSPARENT); 357 canvas.scale(SkIntToScalar(glyph.fWidth) 358 / SkIntToScalar(face->glyph->bitmap.width), 359 SkIntToScalar(glyph.fHeight) 360 / SkIntToScalar(face->glyph->bitmap.rows)); 361 SkPaint paint; 362 paint.setFilterLevel(SkPaint::kLow_FilterLevel); 363 canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); 364 } else { 365 // no scaling needed - directly copy glyph data 366 copyFTBitmap(face->glyph->bitmap, reinterpret_cast<uint8_t*>(glyph.fImage), 367 glyph.fMaskFormat, glyph.rowBytes()); 368 } 369 } 370 break; 371 372 default: 373 SkDEBUGFAIL("unknown glyph format"); 374 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 375 return; 376 } 377 378 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, 379 // it is optional 380 #if defined(SK_GAMMA_APPLY_TO_A8) 381 if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { 382 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 383 unsigned rowBytes = glyph.rowBytes(); 384 385 for (int y = glyph.fHeight - 1; y >= 0; --y) { 386 for (int x = glyph.fWidth - 1; x >= 0; --x) { 387 dst[x] = fPreBlend.fG[dst[x]]; 388 } 389 dst += rowBytes; 390 } 391 } 392 #endif 393 } 394 395 /////////////////////////////////////////////////////////////////////////////// 396 397 static int move_proc(const FT_Vector* pt, void* ctx) { 398 SkPath* path = (SkPath*)ctx; 399 path->close(); // to close the previous contour (if any) 400 path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 401 return 0; 402 } 403 404 static int line_proc(const FT_Vector* pt, void* ctx) { 405 SkPath* path = (SkPath*)ctx; 406 path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 407 return 0; 408 } 409 410 static int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1, 411 void* ctx) { 412 SkPath* path = (SkPath*)ctx; 413 path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 414 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y)); 415 return 0; 416 } 417 418 static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1, 419 const FT_Vector* pt2, void* ctx) { 420 SkPath* path = (SkPath*)ctx; 421 path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 422 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y), 423 SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y)); 424 return 0; 425 } 426 427 void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, 428 SkPath* path) 429 { 430 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && !(face->style_flags & FT_STYLE_FLAG_BOLD)) { 431 emboldenOutline(face, &face->glyph->outline); 432 } 433 434 FT_Outline_Funcs funcs; 435 436 funcs.move_to = move_proc; 437 funcs.line_to = line_proc; 438 funcs.conic_to = quad_proc; 439 funcs.cubic_to = cubic_proc; 440 funcs.shift = 0; 441 funcs.delta = 0; 442 443 FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); 444 445 if (err != 0) { 446 path->reset(); 447 return; 448 } 449 450 path->close(); 451 } 452 453 void SkScalerContext_FreeType_Base::emboldenOutline(FT_Face face, FT_Outline* outline) 454 { 455 FT_Pos strength; 456 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) 457 / SK_OUTLINE_EMBOLDEN_DIVISOR; 458 FT_Outline_Embolden(outline, strength); 459 } 460