1c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com/* 2c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com * Copyright 2006-2012 The Android Open Source Project 3c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com * Copyright 2012 Mozilla Foundation 4c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com * 5c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com * Use of this source code is governed by a BSD-style license that can be 6c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com * found in the LICENSE file. 7c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com */ 8c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 9c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include "SkBitmap.h" 10c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include "SkCanvas.h" 11c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include "SkColor.h" 12c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include "SkColorPriv.h" 13c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include "SkFDot6.h" 14c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include "SkFontHost_FreeType_common.h" 15c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include "SkPath.h" 16c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 17c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include <ft2build.h> 18c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include FT_FREETYPE_H 19c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include FT_BITMAP_H 20c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include FT_IMAGE_H 21c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#include FT_OUTLINE_H 22c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 23c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include FT_SYNTHESIS_H 24c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 25c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 26c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// were introduced in FreeType 2.5.0. 27c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// The following may be removed once FreeType 2.5.0 is required to build. 28c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifndef FT_LOAD_COLOR 29c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com# define FT_LOAD_COLOR ( 1L << 20 ) 30c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com# define FT_PIXEL_MODE_BGRA 7 31c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 32c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 33c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com//#define SK_SHOW_TEXT_BLIT_COVERAGE 34c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 35c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comstatic FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { 36c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com switch (format) { 37c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com case SkMask::kBW_Format: 38c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com return FT_PIXEL_MODE_MONO; 39c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com case SkMask::kA8_Format: 40c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com default: 41c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com return FT_PIXEL_MODE_GRAY; 42c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 43c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 44c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 45c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com/////////////////////////////////////////////////////////////////////////////// 46c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 47c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) { 48c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifdef SK_SHOW_TEXT_BLIT_COVERAGE 49c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com r = SkTMax(r, (U8CPU)0x40); 50c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com g = SkTMax(g, (U8CPU)0x40); 51c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com b = SkTMax(b, (U8CPU)0x40); 52c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 53c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkPack888ToRGB16(r, g, b); 54c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 55c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 56c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comstatic uint16_t grayToRGB16(U8CPU gray) { 57c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifdef SK_SHOW_TEXT_BLIT_COVERAGE 58c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com gray = SkTMax(gray, (U8CPU)0x40); 59c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 60c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkPack888ToRGB16(gray, gray, gray); 61c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 62c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 63c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comstatic int bittst(const uint8_t data[], int bitOffset) { 64c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com SkASSERT(bitOffset >= 0); 65c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); 66c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com return lowBit & 1; 67c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 68c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 69c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com/** 70c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * Copies a FT_Bitmap into an SkMask with the same dimensions. 71c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * 72c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_MONO 73c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_GRAY 74c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_LCD 75c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_LCD_V 76c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com */ 77c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comtemplate<bool APPLY_PREBLEND> 78c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR, 79c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) 80c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com{ 81c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(SkMask::kLCD16_Format == mask.fFormat); 82c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) { 83c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(mask.fBounds.width() == bitmap.width); 84c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 85c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) { 86c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(mask.fBounds.height() == bitmap.rows); 87c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 88c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 89c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com const uint8_t* src = bitmap.buffer; 90c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage); 91c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const size_t dstRB = mask.fRowBytes; 92c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 93c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int width = mask.fBounds.width(); 94c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int height = mask.fBounds.height(); 95c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 96c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com switch (bitmap.pixel_mode) { 97c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_MONO: 98c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = height; y --> 0;) { 99c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com for (int x = 0; x < width; ++x) { 100c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst[x] = -bittst(src, x); 101c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 102c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst = (uint16_t*)((char*)dst + dstRB); 103c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com src += bitmap.pitch; 104c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 105c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 106c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_GRAY: 107c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = height; y --> 0;) { 108c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com for (int x = 0; x < width; ++x) { 109c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst[x] = grayToRGB16(src[x]); 110c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 111c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst = (uint16_t*)((char*)dst + dstRB); 112c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com src += bitmap.pitch; 113c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 114c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 115c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_LCD: 116c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(3 * mask.fBounds.width() == bitmap.width); 117c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = height; y --> 0;) { 118c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* triple = src; 119c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (lcdIsBGR) { 120c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com for (int x = 0; x < width; x++) { 121c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR), 122c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 123c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB)); 124c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com triple += 3; 125c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 126c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 127c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int x = 0; x < width; x++) { 128c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR), 129c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 130c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB)); 131c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com triple += 3; 132c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 133c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 134c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += bitmap.pitch; 135c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst = (uint16_t*)((char*)dst + dstRB); 136c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 137c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 138c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_LCD_V: 139c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(3 * mask.fBounds.height() == bitmap.rows); 140c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = height; y --> 0;) { 141c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* srcR = src; 142c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* srcG = srcR + bitmap.pitch; 143c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* srcB = srcG + bitmap.pitch; 144c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (lcdIsBGR) { 145c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkTSwap(srcR, srcB); 146c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 147c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int x = 0; x < width; x++) { 148c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR), 149c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG), 150c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB)); 151c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 152c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += 3 * bitmap.pitch; 153c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst = (uint16_t*)((char*)dst + dstRB); 154c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 155c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 156c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com default: 157c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode)); 158c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16"); 159c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 160c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 161c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 162c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 163c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com/** 164c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * Copies a FT_Bitmap into an SkMask with the same dimensions. 165c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * 166c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * Yes, No, Never Requested, Never Produced 167c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * 168c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * kBW kA8 k3D kARGB32 kLCD16 kLCD32 169c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_MONO Y Y NR N Y NR 170c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_GRAY N Y NR N Y NR 171c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP NR 172c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP NR 173c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_LCD NP NP NR NP NP NR 174c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_LCD_V NP NP NR NP NP NR 175c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * FT_PIXEL_MODE_BGRA N N NR Y N NR 176c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * 177c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com * TODO: All of these N need to be Y or otherwise ruled out. 178c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com */ 179c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) { 180c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(dstMask.fBounds.width() == srcFTBitmap.width); 181c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(dstMask.fBounds.height() == srcFTBitmap.rows); 182c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 183c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer); 184c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel_mode); 185c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // FT_Bitmap::pitch is an int and allowed to be negative. 186c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int srcPitch = srcFTBitmap.pitch; 187c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const size_t srcRowBytes = SkTAbs(srcPitch); 188c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 189c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t* dst = dstMask.fImage; 190c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat); 191c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const size_t dstRowBytes = dstMask.fRowBytes; 192c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 193c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const size_t width = srcFTBitmap.width; 194c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const size_t height = srcFTBitmap.rows; 195c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 196c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (SkMask::kLCD16_Format == dstFormat) { 197c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com copyFT2LCD16<false>(srcFTBitmap, dstMask, false, NULL, NULL, NULL); 198c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return; 199c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 200c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 201c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) || 202c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat)) 203c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com { 204c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes); 205c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (size_t y = height; y --> 0;) { 206c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com memcpy(dst, src, commonRowBytes); 207c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += srcPitch; 208c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst += dstRowBytes; 209c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 210c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) { 211c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (size_t y = height; y --> 0;) { 212c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t byte = 0; 213c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com int bits = 0; 214c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* src_row = src; 215c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t* dst_row = dst; 216c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (size_t x = width; x --> 0;) { 217c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (0 == bits) { 218c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com byte = *src_row++; 219c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bits = 8; 220c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 221c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com *dst_row++ = byte & 0x80 ? 0xff : 0x00; 222c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bits--; 223c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com byte <<= 1; 224c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 225c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += srcPitch; 226c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst += dstRowBytes; 227c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 228c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) { 229c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // FT_PIXEL_MODE_BGRA is pre-multiplied. 230c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (size_t y = height; y --> 0;) { 231c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const uint8_t* src_row = src; 232c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst); 233c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (size_t x = 0; x < width; ++x) { 234c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t b = *src_row++; 235c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t g = *src_row++; 236c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t r = *src_row++; 237c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t a = *src_row++; 238c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com *dst_row++ = SkPackARGB32(a, r, g, b); 239c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifdef SK_SHOW_TEXT_BLIT_COVERAGE 240c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE, 0x40); 241c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 242c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 243c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += srcPitch; 244c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst += dstRowBytes; 245c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 246c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 247c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat)); 248c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format"); 249c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 250c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 251c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 252c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic inline int convert_8_to_1(unsigned byte) { 253c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(byte <= 0xFF); 254c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better. 255c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return (byte >> 6) != 0; 256c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 257c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 258c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic uint8_t pack_8_to_1(const uint8_t alpha[8]) { 259c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com unsigned bits = 0; 260c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int i = 0; i < 8; ++i) { 261c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bits <<= 1; 262c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bits |= convert_8_to_1(alpha[i]); 263c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 264c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkToU8(bits); 265c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 266c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 267c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) { 268c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int height = mask.fBounds.height(); 269c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int width = mask.fBounds.width(); 270c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int octs = width >> 3; 271c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int leftOverBits = width & 7; 272c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 273c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t* dst = mask.fImage; 274c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int dstPad = mask.fRowBytes - SkAlign8(width)/8; 275c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(dstPad >= 0); 276c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 277c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com const int srcPad = srcRB - width; 278c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(srcPad >= 0); 279c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 280c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = 0; y < height; ++y) { 281c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int i = 0; i < octs; ++i) { 282c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com *dst++ = pack_8_to_1(src); 283c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += 8; 284c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 285c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (leftOverBits > 0) { 286c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com unsigned bits = 0; 287c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com int shift = 7; 288c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int i = 0; i < leftOverBits; ++i, --shift) { 289c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bits |= convert_8_to_1(*src++) << shift; 290c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 291c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com *dst++ = bits; 292c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 293c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += srcPad; 294c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst += dstPad; 295c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 296c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 297c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 2986c22573edb234ad14df947278cfed010669a39a7reedinline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) { 2996c22573edb234ad14df947278cfed010669a39a7reed switch (colorType) { 3006c22573edb234ad14df947278cfed010669a39a7reed case kAlpha_8_SkColorType: 301c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkMask::kA8_Format; 3026c22573edb234ad14df947278cfed010669a39a7reed case kN32_SkColorType: 303c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkMask::kARGB32_Format; 304c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com default: 305c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unsupported SkBitmap::Config"); 306c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return SkMask::kA8_Format; 307c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 308c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 309c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 3106c22573edb234ad14df947278cfed010669a39a7reedinline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) { 311c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com switch (pixel_mode) { 312c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_MONO: 313c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_GRAY: 3146c22573edb234ad14df947278cfed010669a39a7reed return kAlpha_8_SkColorType; 315c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_PIXEL_MODE_BGRA: 3166c22573edb234ad14df947278cfed010669a39a7reed return kN32_SkColorType; 317c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com default: 318c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); 3196c22573edb234ad14df947278cfed010669a39a7reed return kAlpha_8_SkColorType; 320c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 321c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 322c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 3236c22573edb234ad14df947278cfed010669a39a7reedinline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) { 324c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com switch (format) { 325c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case SkMask::kBW_Format: 326c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case SkMask::kA8_Format: 327c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case SkMask::kLCD16_Format: 3286c22573edb234ad14df947278cfed010669a39a7reed return kAlpha_8_SkColorType; 329c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case SkMask::kARGB32_Format: 3306c22573edb234ad14df947278cfed010669a39a7reed return kN32_SkColorType; 331c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com default: 332c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unsupported destination SkBitmap::Config"); 3336c22573edb234ad14df947278cfed010669a39a7reed return kAlpha_8_SkColorType; 334c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 335c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 336c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 337a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comvoid SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGlyph& glyph) { 338c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag); 339c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 340c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 341c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com switch ( face->glyph->format ) { 342c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com case FT_GLYPH_FORMAT_OUTLINE: { 343c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Outline* outline = &face->glyph->outline; 344c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_BBox bbox; 345c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Bitmap target; 346c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 347c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com int dx = 0, dy = 0; 348c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 349c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dx = SkFixedToFDot6(glyph.getSubXFixed()); 350c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dy = SkFixedToFDot6(glyph.getSubYFixed()); 351c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com // negate dy since freetype-y-goes-up and skia-y-goes-down 352c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dy = -dy; 353c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 354c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Outline_Get_CBox(outline, &bbox); 355c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com /* 356c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com what we really want to do for subpixel is 357c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com offset(dx, dy) 358c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com compute_bounds 359c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com offset(bbox & !63) 360c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com but that is two calls to offset, so we do the following, which 361c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com achieves the same thing with only one offset call. 362c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com */ 363c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), 364c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dy - ((bbox.yMin + dy) & ~63)); 365c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 366c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 367c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD); 368c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask mask; 369c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.toMask(&mask); 370a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 371c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR, 372a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 373c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } else { 374c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR, 375a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 376c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 377c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } else { 378c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com target.width = glyph.fWidth; 379c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com target.rows = glyph.fHeight; 380c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com target.pitch = glyph.rowBytes(); 381c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); 382c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat); 383c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com target.num_grays = 256; 384c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 385c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 386c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); 387c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 388c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } break; 389c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 390c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com case FT_GLYPH_FORMAT_BITMAP: { 391c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode); 392c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 393c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 394c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Assume that the other formats do not exist. 395c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode || 396c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_PIXEL_MODE_GRAY == pixel_mode || 397c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_PIXEL_MODE_BGRA == pixel_mode); 398c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 399c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // These are the only formats this ScalerContext should request. 400c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkASSERT(SkMask::kBW_Format == maskFormat || 401c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask::kA8_Format == maskFormat || 402c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask::kARGB32_Format == maskFormat || 403c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask::kLCD16_Format == maskFormat); 404c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 405c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && 406c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com !(face->style_flags & FT_STYLE_FLAG_BOLD)) 407c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com { 408c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_GlyphSlot_Own_Bitmap(face->glyph); 409c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, 410c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com kBitmapEmboldenStrength, 0); 411c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 412c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 413c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // If no scaling needed, directly copy glyph bitmap. 414c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (glyph.fWidth == face->glyph->bitmap.width && 415c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fHeight == face->glyph->bitmap.rows && 416c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fTop == -face->glyph->bitmap_top && 417c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fLeft == face->glyph->bitmap_left) 418c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com { 419c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask dstMask; 420c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.toMask(&dstMask); 421c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com copyFTBitmap(face->glyph->bitmap, dstMask); 422c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 423c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 424c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 425c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Otherwise, scale the bitmap. 426c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 427c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB) 428c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkBitmap unscaledBitmap; 4296c22573edb234ad14df947278cfed010669a39a7reed unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width, 4306c22573edb234ad14df947278cfed010669a39a7reed face->glyph->bitmap.rows, 4316c22573edb234ad14df947278cfed010669a39a7reed SkColorType_for_FTPixelMode(pixel_mode), 4326c22573edb234ad14df947278cfed010669a39a7reed kPremul_SkAlphaType)); 433c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 434c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask unscaledBitmapAlias; 435c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels()); 436c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height()); 437c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes(); 4386c22573edb234ad14df947278cfed010669a39a7reed unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType()); 439c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias); 440c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 441c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD. 442c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // BW requires an A8 target for resizing, which can then be down sampled. 443c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // LCD should use a 4x A8 target, which will then be down sampled. 444c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // For simplicity, LCD uses A8 and is replicated. 445c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com int bitmapRowBytes = 0; 446c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) { 447c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bitmapRowBytes = glyph.rowBytes(); 448c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 449c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkBitmap dstBitmap; 4506c22573edb234ad14df947278cfed010669a39a7reed dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight, 4516c22573edb234ad14df947278cfed010669a39a7reed SkColorType_for_SkMaskFormat(maskFormat), 4526c22573edb234ad14df947278cfed010669a39a7reed kPremul_SkAlphaType), 4536c22573edb234ad14df947278cfed010669a39a7reed bitmapRowBytes); 454c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) { 455c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dstBitmap.allocPixels(); 456c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } else { 457c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dstBitmap.setPixels(glyph.fImage); 458c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 459c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 460c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Scale unscaledBitmap into dstBitmap. 461c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkCanvas canvas(dstBitmap); 462c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com canvas.clear(SK_ColorTRANSPARENT); 463c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph->bitmap.width), 464c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyph->bitmap.rows)); 465c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkPaint paint; 466ef24b7d33826f9e71f01870b3bad9d52f2a8d220djsollen paint.setFilterLevel(SkPaint::kMedium_FilterLevel); 467c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); 468c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 469c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // If the destination is BW or LCD, convert from A8. 470c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (SkMask::kBW_Format == maskFormat) { 471c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Copy the A8 dstBitmap into the A1 glyph.fImage. 472c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkMask dstMask; 473c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.toMask(&dstMask); 474c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes()); 475c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (SkMask::kLCD16_Format == maskFormat) { 476c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Copy the A8 dstBitmap into the LCD16 glyph.fImage. 477c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint8_t* src = dstBitmap.getAddr8(0, 0); 478c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); 479c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int y = dstBitmap.height(); y --> 0;) { 480c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (int x = 0; x < dstBitmap.width(); ++x) { 481c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst[x] = grayToRGB16(src[x]); 482c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 483c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com dst = (uint16_t*)((char*)dst + glyph.rowBytes()); 484c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com src += dstBitmap.rowBytes(); 485c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 486c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 487c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 488c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } break; 489c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 490c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com default: 491c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGFAIL("unknown glyph format"); 492c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 493c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return; 494c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 495c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 496c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com// We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, 497c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com// it is optional 498c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#if defined(SK_GAMMA_APPLY_TO_A8) 499a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { 500c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 501c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com unsigned rowBytes = glyph.rowBytes(); 502d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 503c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com for (int y = glyph.fHeight - 1; y >= 0; --y) { 504c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com for (int x = glyph.fWidth - 1; x >= 0; --x) { 505a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com dst[x] = fPreBlend.fG[dst[x]]; 506c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 507c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com dst += rowBytes; 508c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 509c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 510c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#endif 511c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 512c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 5138ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com/////////////////////////////////////////////////////////////////////////////// 5148ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 5158ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.comstatic int move_proc(const FT_Vector* pt, void* ctx) { 5168ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkPath* path = (SkPath*)ctx; 5178ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->close(); // to close the previous contour (if any) 5188ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 5198ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com return 0; 5208ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com} 5218ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 5228ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.comstatic int line_proc(const FT_Vector* pt, void* ctx) { 5238ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkPath* path = (SkPath*)ctx; 5248ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 5258ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com return 0; 5268ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com} 5278ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 5288ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.comstatic int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1, 5298ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com void* ctx) { 5308ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkPath* path = (SkPath*)ctx; 5318ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 5328ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y)); 5338ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com return 0; 5348ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com} 5358ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 5368ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.comstatic int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1, 5378ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com const FT_Vector* pt2, void* ctx) { 5388ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkPath* path = (SkPath*)ctx; 5398ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 5408ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y), 5418ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y)); 5428ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com return 0; 5438ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com} 5448ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 545c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comvoid SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, 546c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com SkPath* path) 547c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com{ 548c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Outline_Funcs funcs; 549c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 550c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.move_to = move_proc; 551c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.line_to = line_proc; 552c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.conic_to = quad_proc; 553c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.cubic_to = cubic_proc; 554c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.shift = 0; 555c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com funcs.delta = 0; 556c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 557c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); 558c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 559c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com if (err != 0) { 560c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com path->reset(); 561c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com return; 562c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com } 563c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com 564c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com path->close(); 565c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com} 566