Home | History | Annotate | Download | only in text
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "GrFontScaler.h"
     10 #include "SkDescriptor.h"
     11 #include "SkDistanceFieldGen.h"
     12 #include "SkGlyphCache.h"
     13 
     14 ///////////////////////////////////////////////////////////////////////////////
     15 
     16 GrFontScaler::GrFontScaler(SkGlyphCache* strike) {
     17     fStrike = strike;
     18     fKey = nullptr;
     19 }
     20 
     21 GrFontScaler::~GrFontScaler() {
     22     SkSafeUnref(fKey);
     23 }
     24 
     25 GrMaskFormat GrFontScaler::getMaskFormat() const {
     26     SkMask::Format format = fStrike->getMaskFormat();
     27     switch (format) {
     28         case SkMask::kBW_Format:
     29             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
     30         case SkMask::kA8_Format:
     31             return kA8_GrMaskFormat;
     32         case SkMask::kLCD16_Format:
     33             return kA565_GrMaskFormat;
     34         case SkMask::kARGB32_Format:
     35             return kARGB_GrMaskFormat;
     36         default:
     37             SkDEBUGFAIL("unsupported SkMask::Format");
     38             return kA8_GrMaskFormat;
     39     }
     40 }
     41 
     42 const GrFontDescKey* GrFontScaler::getKey() {
     43     if (nullptr == fKey) {
     44         fKey = new GrFontDescKey(fStrike->getDescriptor());
     45     }
     46     return fKey;
     47 }
     48 
     49 GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(const SkGlyph& glyph) const {
     50     SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
     51     switch (format) {
     52         case SkMask::kBW_Format:
     53             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
     54         case SkMask::kA8_Format:
     55             return kA8_GrMaskFormat;
     56         case SkMask::kLCD16_Format:
     57             return kA565_GrMaskFormat;
     58         case SkMask::kARGB32_Format:
     59             return kARGB_GrMaskFormat;
     60         default:
     61             SkDEBUGFAIL("unsupported SkMask::Format");
     62             return kA8_GrMaskFormat;
     63     }
     64 }
     65 
     66 bool GrFontScaler::getPackedGlyphBounds(const SkGlyph& glyph, SkIRect* bounds) {
     67 #if 1
     68     // crbug:510931
     69     // Retrieving the image from the cache can actually change the mask format.
     70     fStrike->findImage(glyph);
     71 #endif
     72     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
     73 
     74     return true;
     75 }
     76 
     77 bool GrFontScaler::getPackedGlyphDFBounds(const SkGlyph& glyph, SkIRect* bounds) {
     78 #if 1
     79     // crbug:510931
     80     // Retrieving the image from the cache can actually change the mask format.
     81     fStrike->findImage(glyph);
     82 #endif
     83     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
     84     bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
     85 
     86     return true;
     87 }
     88 
     89 namespace {
     90 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
     91 // A8, RGB565, or RGBA8888.
     92 template <typename INT_TYPE>
     93 void expand_bits(INT_TYPE* dst,
     94                  const uint8_t* src,
     95                  int width,
     96                  int height,
     97                  int dstRowBytes,
     98                  int srcRowBytes) {
     99     for (int i = 0; i < height; ++i) {
    100         int rowWritesLeft = width;
    101         const uint8_t* s = src;
    102         INT_TYPE* d = dst;
    103         while (rowWritesLeft > 0) {
    104             unsigned mask = *s++;
    105             for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
    106                 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
    107             }
    108         }
    109         dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
    110         src += srcRowBytes;
    111     }
    112 }
    113 }
    114 
    115 bool GrFontScaler::getPackedGlyphImage(const SkGlyph& glyph, int width, int height, int dstRB,
    116                                        GrMaskFormat expectedMaskFormat, void* dst) {
    117     SkASSERT(glyph.fWidth == width);
    118     SkASSERT(glyph.fHeight == height);
    119     const void* src = fStrike->findImage(glyph);
    120     if (nullptr == src) {
    121         return false;
    122     }
    123 
    124     // crbug:510931
    125     // Retrieving the image from the cache can actually change the mask format.  This case is very
    126     // uncommon so for now we just draw a clear box for these glyphs.
    127     if (getPackedGlyphMaskFormat(glyph) != expectedMaskFormat) {
    128         const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
    129         for (int y = 0; y < height; y++) {
    130             sk_bzero(dst, width * bpp);
    131             dst = (char*)dst + dstRB;
    132         }
    133         return true;
    134     }
    135 
    136     int srcRB = glyph.rowBytes();
    137     // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
    138     // check the glyph's format, not the strike's format, and to be able to convert to any of the
    139     // GrMaskFormats.
    140     if (SkMask::kBW_Format == glyph.fMaskFormat) {
    141         // expand bits to our mask type
    142         const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
    143         switch (expectedMaskFormat) {
    144             case kA8_GrMaskFormat:{
    145                 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
    146                 expand_bits(bytes, bits, width, height, dstRB, srcRB);
    147                 break;
    148             }
    149             case kA565_GrMaskFormat: {
    150                 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
    151                 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
    152                 break;
    153             }
    154             default:
    155                 SkFAIL("Invalid GrMaskFormat");
    156         }
    157     } else if (srcRB == dstRB) {
    158         memcpy(dst, src, dstRB * height);
    159     } else {
    160         const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
    161         for (int y = 0; y < height; y++) {
    162             memcpy(dst, src, width * bbp);
    163             src = (const char*)src + srcRB;
    164             dst = (char*)dst + dstRB;
    165         }
    166     }
    167     return true;
    168 }
    169 
    170 bool GrFontScaler::getPackedGlyphDFImage(const SkGlyph& glyph, int width, int height, void* dst) {
    171     SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
    172     SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
    173     const void* image = fStrike->findImage(glyph);
    174     if (nullptr == image) {
    175         return false;
    176     }
    177     // now generate the distance field
    178     SkASSERT(dst);
    179     SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
    180     if (SkMask::kA8_Format == maskFormat) {
    181         // make the distance field from the image
    182         SkGenerateDistanceFieldFromA8Image((unsigned char*)dst,
    183                                            (unsigned char*)image,
    184                                            glyph.fWidth, glyph.fHeight,
    185                                            glyph.rowBytes());
    186     } else if (SkMask::kBW_Format == maskFormat) {
    187         // make the distance field from the image
    188         SkGenerateDistanceFieldFromBWImage((unsigned char*)dst,
    189                                            (unsigned char*)image,
    190                                            glyph.fWidth, glyph.fHeight,
    191                                            glyph.rowBytes());
    192     } else {
    193         return false;
    194     }
    195 
    196     return true;
    197 }
    198 
    199 const SkPath* GrFontScaler::getGlyphPath(const SkGlyph& glyph) {
    200     return fStrike->findPath(glyph);
    201 }
    202 
    203 const SkGlyph& GrFontScaler::grToSkGlyph(GrGlyph::PackedID id) {
    204     return fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(id),
    205                                       GrGlyph::UnpackFixedX(id),
    206                                       GrGlyph::UnpackFixedY(id));
    207 }
    208