180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006-2012 The Android Open Source Project
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Mozilla Foundation
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease#include "SkBitmap.h"
10924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease#include "SkCanvas.h"
11924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease#include "SkColor.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFDot6.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFontHost_FreeType_common.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <ft2build.h>
18910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include FT_FREETYPE_H
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include FT_BITMAP_H
20910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include FT_IMAGE_H
21910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include FT_OUTLINE_H
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include FT_SYNTHESIS_H
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
26910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger// were introduced in FreeType 2.5.0.
27910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger// The following may be removed once FreeType 2.5.0 is required to build.
28910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#ifndef FT_LOAD_COLOR
29910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#    define FT_LOAD_COLOR ( 1L << 20 )
30910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#    define FT_PIXEL_MODE_BGRA 7
31910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
32910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
33910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger//#define SK_SHOW_TEXT_BLIT_COVERAGE
34910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (format) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkMask::kBW_Format:
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return FT_PIXEL_MODE_MONO;
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkMask::kA8_Format:
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return FT_PIXEL_MODE_GRAY;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
476699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru// hand-tuned value to reduce outline embolden strength
486699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru#ifndef SK_OUTLINE_EMBOLDEN_DIVISOR
496699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru    #ifdef SK_BUILD_FOR_ANDROID
506699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru        #define SK_OUTLINE_EMBOLDEN_DIVISOR   34
516699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru    #else
526699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru        #define SK_OUTLINE_EMBOLDEN_DIVISOR   24
536699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru    #endif
546699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru#endif
556699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru
566699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
576699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru
58910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
59910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#ifdef SK_SHOW_TEXT_BLIT_COVERAGE
60910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    r = SkTMax(r, (U8CPU)0x40);
61910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    g = SkTMax(g, (U8CPU)0x40);
62910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    b = SkTMax(b, (U8CPU)0x40);
63910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
64910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return SkPack888ToRGB16(r, g, b);
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t grayToRGB16(U8CPU gray) {
68910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#ifdef SK_SHOW_TEXT_BLIT_COVERAGE
69910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    gray = SkTMax(gray, (U8CPU)0x40);
70910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
71910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return SkPack888ToRGB16(gray, gray, gray);
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int bittst(const uint8_t data[], int bitOffset) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(bitOffset >= 0);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7);
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return lowBit & 1;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/**
81910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  Copies a FT_Bitmap into an SkMask with the same dimensions.
82910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *
83910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_MONO
84910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_GRAY
85910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_LCD
86910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_LCD_V
87910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<bool APPLY_PREBLEND>
89910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR,
90910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB)
91910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger{
92910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(SkMask::kLCD16_Format == mask.fFormat);
93910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) {
94910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkASSERT(mask.fBounds.width() == bitmap.width);
95910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
96910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) {
97910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkASSERT(mask.fBounds.height() == bitmap.rows);
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* src = bitmap.buffer;
101910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage);
102910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const size_t dstRB = mask.fRowBytes;
103910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
104910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int width = mask.fBounds.width();
105910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int height = mask.fBounds.height();
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (bitmap.pixel_mode) {
108924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case FT_PIXEL_MODE_MONO:
109910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (int y = height; y --> 0;) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                for (int x = 0; x < width; ++x) {
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[x] = -bittst(src, x);
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst = (uint16_t*)((char*)dst + dstRB);
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                src += bitmap.pitch;
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
116924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            break;
117924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case FT_PIXEL_MODE_GRAY:
118910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (int y = height; y --> 0;) {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                for (int x = 0; x < width; ++x) {
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[x] = grayToRGB16(src[x]);
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst = (uint16_t*)((char*)dst + dstRB);
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                src += bitmap.pitch;
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
125924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            break;
126910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case FT_PIXEL_MODE_LCD:
127910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkASSERT(3 * mask.fBounds.width() == bitmap.width);
128910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (int y = height; y --> 0;) {
129910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                const uint8_t* triple = src;
130910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                if (lcdIsBGR) {
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    for (int x = 0; x < width; x++) {
132910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR),
133910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                            sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
134910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                            sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB));
135910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        triple += 3;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
137910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                } else {
138910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    for (int x = 0; x < width; x++) {
139910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR),
140910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                            sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
141910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                            sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB));
142910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        triple += 3;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
145910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                src += bitmap.pitch;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst = (uint16_t*)((char*)dst + dstRB);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
148924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            break;
149910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case FT_PIXEL_MODE_LCD_V:
150910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkASSERT(3 * mask.fBounds.height() == bitmap.rows);
151910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (int y = height; y --> 0;) {
152910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                const uint8_t* srcR = src;
153910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                const uint8_t* srcG = srcR + bitmap.pitch;
154910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                const uint8_t* srcB = srcG + bitmap.pitch;
155910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                if (lcdIsBGR) {
156910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    SkTSwap(srcR, srcB);
157910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                }
158910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                for (int x = 0; x < width; x++) {
159910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR),
160910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                        sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG),
161910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                        sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB));
162910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                }
163910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                src += 3 * bitmap.pitch;
164910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                dst = (uint16_t*)((char*)dst + dstRB);
165910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            }
166910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            break;
167910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        default:
168910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode));
169910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16");
170910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            break;
171924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    }
172924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease}
173924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease
174910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/**
175910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  Copies a FT_Bitmap into an SkMask with the same dimensions.
176910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *
177910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  Yes, No, Never Requested, Never Produced
178910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *
179910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *                        kBW kA8 k3D kARGB32 kLCD16 kLCD32
180910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_MONO     Y   Y  NR     N       Y     NR
181910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_GRAY     N   Y  NR     N       Y     NR
182910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_GRAY2   NP  NP  NR    NP      NP     NR
183910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_GRAY4   NP  NP  NR    NP      NP     NR
184910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_LCD     NP  NP  NR    NP      NP     NR
185910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_LCD_V   NP  NP  NR    NP      NP     NR
186910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  FT_PIXEL_MODE_BGRA     N   N  NR     Y       N     NR
187910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *
188910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *  TODO: All of these N need to be Y or otherwise ruled out.
189910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */
190910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
191910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(dstMask.fBounds.width() == srcFTBitmap.width);
192910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(dstMask.fBounds.height() == srcFTBitmap.rows);
193910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
194924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer);
195910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel_mode);
196910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    // FT_Bitmap::pitch is an int and allowed to be negative.
197910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int srcPitch = srcFTBitmap.pitch;
198910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const size_t srcRowBytes = SkTAbs(srcPitch);
199910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
200910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    uint8_t* dst = dstMask.fImage;
201910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat);
202910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const size_t dstRowBytes = dstMask.fRowBytes;
203910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
204910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const size_t width = srcFTBitmap.width;
205910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const size_t height = srcFTBitmap.rows;
206910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
207910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (SkMask::kLCD16_Format == dstFormat) {
208910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        copyFT2LCD16<false>(srcFTBitmap, dstMask, false, NULL, NULL, NULL);
209910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        return;
210910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
211910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
212910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) ||
213910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat))
214910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    {
215910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes);
216910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        for (size_t y = height; y --> 0;) {
217910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            memcpy(dst, src, commonRowBytes);
218910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            src += srcPitch;
219924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            dst += dstRowBytes;
220924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        }
221910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) {
222910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        for (size_t y = height; y --> 0;) {
223924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            uint8_t byte = 0;
224924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            int bits = 0;
225924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            const uint8_t* src_row = src;
226924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            uint8_t* dst_row = dst;
227910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (size_t x = width; x --> 0;) {
228910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                if (0 == bits) {
229924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                    byte = *src_row++;
230924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                    bits = 8;
231924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                }
232910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                *dst_row++ = byte & 0x80 ? 0xff : 0x00;
233924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                bits--;
234924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                byte <<= 1;
235924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            }
236910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            src += srcPitch;
237924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            dst += dstRowBytes;
238924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        }
239910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) {
240910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // FT_PIXEL_MODE_BGRA is pre-multiplied.
241910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        for (size_t y = height; y --> 0;) {
242924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            const uint8_t* src_row = src;
243910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst);
244910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (size_t x = 0; x < width; ++x) {
245910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint8_t b = *src_row++;
246910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint8_t g = *src_row++;
247910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint8_t r = *src_row++;
248910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint8_t a = *src_row++;
249910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                *dst_row++ = SkPackARGB32(a, r, g, b);
250910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#ifdef SK_SHOW_TEXT_BLIT_COVERAGE
251910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE, 0x40);
252910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#endif
253924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            }
254910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            src += srcPitch;
255924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            dst += dstRowBytes;
256924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        }
257924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    } else {
258910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat));
259910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format");
260924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    }
261924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease}
262924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease
263910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline int convert_8_to_1(unsigned byte) {
264910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(byte <= 0xFF);
265910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better.
266910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return (byte >> 6) != 0;
267910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
268910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
269910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic uint8_t pack_8_to_1(const uint8_t alpha[8]) {
270910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    unsigned bits = 0;
271910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    for (int i = 0; i < 8; ++i) {
272910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        bits <<= 1;
273910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        bits |= convert_8_to_1(alpha[i]);
274910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
275910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return SkToU8(bits);
276910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
277910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
278910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
279910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int height = mask.fBounds.height();
280910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int width = mask.fBounds.width();
281910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int octs = width >> 3;
282910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int leftOverBits = width & 7;
283910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
284910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    uint8_t* dst = mask.fImage;
285910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
286910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(dstPad >= 0);
287910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
288910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const int srcPad = srcRB - width;
289910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkASSERT(srcPad >= 0);
290910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
291910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    for (int y = 0; y < height; ++y) {
292910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        for (int i = 0; i < octs; ++i) {
293910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            *dst++ = pack_8_to_1(src);
294910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            src += 8;
295910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        }
296910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        if (leftOverBits > 0) {
297910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unsigned bits = 0;
298910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            int shift = 7;
299910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            for (int i = 0; i < leftOverBits; ++i, --shift) {
300910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                bits |= convert_8_to_1(*src++) << shift;
301910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            }
302910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            *dst++ = bits;
303910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        }
304910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        src += srcPad;
305910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        dst += dstPad;
306910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
307910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
308910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
309910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerinline SkMask::Format SkMaskFormat_for_SkBitmapConfig(SkBitmap::Config config) {
310910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    switch (config) {
311910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case SkBitmap::kA8_Config:
312924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkMask::kA8_Format;
313910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case SkBitmap::kARGB_8888_Config:
314924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkMask::kARGB32_Format;
315924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        default:
316910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkDEBUGFAIL("unsupported SkBitmap::Config");
317924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkMask::kA8_Format;
318924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    }
319924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease}
320924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease
321910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerinline SkBitmap::Config SkBitmapConfig_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
322924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    switch (pixel_mode) {
323910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case FT_PIXEL_MODE_MONO:
324924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case FT_PIXEL_MODE_GRAY:
325924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kA8_Config;
326924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case FT_PIXEL_MODE_BGRA:
327924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kARGB_8888_Config;
328924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        default:
329924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            SkDEBUGFAIL("unsupported FT_PIXEL_MODE");
330924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kA8_Config;
331924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    }
332924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease}
333924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease
334910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerinline SkBitmap::Config SkBitmapConfig_for_SkMaskFormat(SkMask::Format format) {
335924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease    switch (format) {
336910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case SkMask::kBW_Format:
337924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case SkMask::kA8_Format:
338910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        case SkMask::kLCD16_Format:
339924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kA8_Config;
340924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        case SkMask::kARGB32_Format:
341924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kARGB_8888_Config;
342924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        default:
343910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkDEBUGFAIL("unsupported destination SkBitmap::Config");
344924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return SkBitmap::kA8_Config;
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
348363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGlyph& glyph) {
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch ( face->glyph->format ) {
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case FT_GLYPH_FORMAT_OUTLINE: {
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            FT_Outline* outline = &face->glyph->outline;
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            FT_BBox     bbox;
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            FT_Bitmap   target;
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
358924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            if (fRec.fFlags & SkScalerContext::kEmbolden_Flag &&
359924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                !(face->style_flags & FT_STYLE_FLAG_BOLD)) {
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                emboldenOutline(face, outline);
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int dx = 0, dy = 0;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dx = SkFixedToFDot6(glyph.getSubXFixed());
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dy = SkFixedToFDot6(glyph.getSubYFixed());
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // negate dy since freetype-y-goes-up and skia-y-goes-down
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dy = -dy;
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            FT_Outline_Get_CBox(outline, &bbox);
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            /*
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                what we really want to do for subpixel is
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    offset(dx, dy)
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    compute_bounds
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    offset(bbox & !63)
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                but that is two calls to offset, so we do the following, which
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                achieves the same thing with only one offset call.
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            */
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                          dy - ((bbox.yMin + dy) & ~63));
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
382924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD);
384910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                SkMask mask;
385910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.toMask(&mask);
386363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (fPreBlend.isApplicable()) {
387910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
388363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                       fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
390910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
391363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target.width = glyph.fWidth;
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target.rows = glyph.fHeight;
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target.pitch = glyph.rowBytes();
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
398910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                target.num_grays = 256;
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case FT_GLYPH_FORMAT_BITMAP: {
407910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
408910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
409910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
410910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // Assume that the other formats do not exist.
411910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
412910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                     FT_PIXEL_MODE_GRAY == pixel_mode ||
413910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                     FT_PIXEL_MODE_BGRA == pixel_mode);
414910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
415910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // These are the only formats this ScalerContext should request.
416910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkASSERT(SkMask::kBW_Format == maskFormat ||
417910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                     SkMask::kA8_Format == maskFormat ||
418910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                     SkMask::kARGB32_Format == maskFormat ||
419910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                     SkMask::kLCD16_Format == maskFormat);
420910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
421910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            if (fRec.fFlags & SkScalerContext::kEmbolden_Flag &&
422910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                !(face->style_flags & FT_STYLE_FLAG_BOLD))
423910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            {
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                FT_GlyphSlot_Own_Bitmap(face->glyph);
425910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap,
426910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                   kBitmapEmboldenStrength, 0);
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
429910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // If no scaling needed, directly copy glyph bitmap.
430910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            if (glyph.fWidth == face->glyph->bitmap.width &&
431910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.fHeight == face->glyph->bitmap.rows &&
432910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.fTop == -face->glyph->bitmap_top &&
433910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.fLeft == face->glyph->bitmap_left)
434910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            {
435910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                SkMask dstMask;
436910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.toMask(&dstMask);
437910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                copyFTBitmap(face->glyph->bitmap, dstMask);
438910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                break;
439910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            }
440910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
441910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // Otherwise, scale the bitmap.
442910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
443910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
444910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkBitmap unscaledBitmap;
445910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmap.setConfig(SkBitmapConfig_for_FTPixelMode(pixel_mode),
446910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                     face->glyph->bitmap.width, face->glyph->bitmap.rows);
447910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmap.allocPixels();
448910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
449910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkMask unscaledBitmapAlias;
450910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
451910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height());
452910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
453910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkBitmapConfig(unscaledBitmap.config());
454910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
455910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
456910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
457910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // BW requires an A8 target for resizing, which can then be down sampled.
458910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // LCD should use a 4x A8 target, which will then be down sampled.
459910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // For simplicity, LCD uses A8 and is replicated.
460910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            int bitmapRowBytes = 0;
461910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) {
462910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                bitmapRowBytes = glyph.rowBytes();
463910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            }
464910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkBitmap dstBitmap;
465910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            dstBitmap.setConfig(SkBitmapConfig_for_SkMaskFormat(maskFormat),
466910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                glyph.fWidth, glyph.fHeight, bitmapRowBytes);
467910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
468910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                dstBitmap.allocPixels();
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
470910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                dstBitmap.setPixels(glyph.fImage);
471910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            }
472910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
473910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // Scale unscaledBitmap into dstBitmap.
474910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkCanvas canvas(dstBitmap);
475910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            canvas.clear(SK_ColorTRANSPARENT);
476910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph->bitmap.width),
477910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                         SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyph->bitmap.rows));
478910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            SkPaint paint;
479910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            paint.setFilterLevel(SkPaint::kLow_FilterLevel);
480910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            canvas.drawBitmap(unscaledBitmap, 0, 0, &paint);
481910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
482910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            // If the destination is BW or LCD, convert from A8.
483910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            if (SkMask::kBW_Format == maskFormat) {
484910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                // Copy the A8 dstBitmap into the A1 glyph.fImage.
485910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                SkMask dstMask;
486910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                glyph.toMask(&dstMask);
487910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes());
488910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger            } else if (SkMask::kLCD16_Format == maskFormat) {
489910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                // Copy the A8 dstBitmap into the LCD16 glyph.fImage.
490910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint8_t* src = dstBitmap.getAddr8(0, 0);
491910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
492910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                for (int y = dstBitmap.height(); y --> 0;) {
493910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    for (int x = 0; x < dstBitmap.width(); ++x) {
494910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        dst[x] = grayToRGB16(src[x]);
495910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    }
496910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    dst = (uint16_t*)((char*)dst + glyph.rowBytes());
497910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                    src += dstBitmap.rowBytes();
498924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease                }
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
500910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
503924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease        default:
504924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            SkDEBUGFAIL("unknown glyph format");
505924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
506924ac31ce033167b1d7b4e3ddbb640e706c64cccVictoria Lease            return;
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum,
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// it is optional
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_GAMMA_APPLY_TO_A8)
512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) {
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned rowBytes = glyph.rowBytes();
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int y = glyph.fHeight - 1; y >= 0; --y) {
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int x = glyph.fWidth - 1; x >= 0; --x) {
518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                dst[x] = fPreBlend.fG[dst[x]];
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst += rowBytes;
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int move_proc(const FT_Vector* pt, void* ctx) {
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath* path = (SkPath*)ctx;
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->close();  // to close the previous contour (if any)
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int line_proc(const FT_Vector* pt, void* ctx) {
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath* path = (SkPath*)ctx;
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     void* ctx) {
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath* path = (SkPath*)ctx;
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      const FT_Vector* pt2, void* ctx) {
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath* path = (SkPath*)ctx;
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                      SkPath* path)
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5616699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru    if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && !(face->style_flags & FT_STYLE_FLAG_BOLD)) {
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        emboldenOutline(face, &face->glyph->outline);
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FT_Outline_Funcs    funcs;
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.move_to   = move_proc;
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.line_to   = line_proc;
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.conic_to  = quad_proc;
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.cubic_to  = cubic_proc;
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.shift     = 0;
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    funcs.delta     = 0;
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path);
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (err != 0) {
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        path->reset();
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path->close();
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScalerContext_FreeType_Base::emboldenOutline(FT_Face face, FT_Outline* outline)
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FT_Pos strength;
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale)
5886699e7ea2e981dccc2f3c41b5dcf1c860b11558dJean-Baptiste Queru               / SK_OUTLINE_EMBOLDEN_DIVISOR;
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FT_Outline_Embolden(outline, strength);
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
591