Home | History | Annotate | Download | only in gpu
      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 
     10 #include "GrTemplates.h"
     11 #include "GrFontScaler.h"
     12 #include "SkDescriptor.h"
     13 #include "SkDistanceFieldGen.h"
     14 #include "SkGlyphCache.h"
     15 
     16 ///////////////////////////////////////////////////////////////////////////////
     17 
     18 GrFontDescKey::GrFontDescKey(const SkDescriptor& desc) : fHash(desc.getChecksum()) {
     19     size_t size = desc.getLength();
     20     if (size <= sizeof(fStorage)) {
     21         fDesc = GrTCast<SkDescriptor*>(fStorage);
     22     } else {
     23         fDesc = SkDescriptor::Alloc(size);
     24     }
     25     memcpy(fDesc, &desc, size);
     26 }
     27 
     28 GrFontDescKey::~GrFontDescKey() {
     29     if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
     30         SkDescriptor::Free(fDesc);
     31     }
     32 }
     33 
     34 bool GrFontDescKey::lt(const GrFontDescKey& rh) const {
     35     const SkDescriptor* srcDesc = (&rh)->fDesc;
     36     size_t lenLH = fDesc->getLength();
     37     size_t lenRH = srcDesc->getLength();
     38     int cmp = memcmp(fDesc, srcDesc, SkTMin<size_t>(lenLH, lenRH));
     39     if (0 == cmp) {
     40         return lenLH < lenRH;
     41     } else {
     42         return cmp < 0;
     43     }
     44 }
     45 
     46 bool GrFontDescKey::eq(const GrFontDescKey& rh) const {
     47     const SkDescriptor* srcDesc = (&rh)->fDesc;
     48     return fDesc->equals(*srcDesc);
     49 }
     50 
     51 ///////////////////////////////////////////////////////////////////////////////
     52 
     53 GrFontScaler::GrFontScaler(SkGlyphCache* strike) {
     54     fStrike = strike;
     55     fKey = NULL;
     56 }
     57 
     58 GrFontScaler::~GrFontScaler() {
     59     SkSafeUnref(fKey);
     60 }
     61 
     62 GrMaskFormat GrFontScaler::getMaskFormat() {
     63     SkMask::Format format = fStrike->getMaskFormat();
     64     switch (format) {
     65         case SkMask::kBW_Format:
     66             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
     67         case SkMask::kA8_Format:
     68             return kA8_GrMaskFormat;
     69         case SkMask::kLCD16_Format:
     70             return kA565_GrMaskFormat;
     71         case SkMask::kLCD32_Format:
     72             return kA888_GrMaskFormat;
     73         case SkMask::kARGB32_Format:
     74             return kARGB_GrMaskFormat;
     75         default:
     76             SkDEBUGFAIL("unsupported SkMask::Format");
     77             return kA8_GrMaskFormat;
     78     }
     79 }
     80 
     81 const GrFontDescKey* GrFontScaler::getKey() {
     82     if (NULL == fKey) {
     83         fKey = SkNEW_ARGS(GrFontDescKey, (fStrike->getDescriptor()));
     84     }
     85     return fKey;
     86 }
     87 
     88 bool GrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
     89     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
     90                                                       GrGlyph::UnpackFixedX(packed),
     91                                                       GrGlyph::UnpackFixedY(packed));
     92     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
     93 
     94     return true;
     95 }
     96 
     97 bool GrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
     98     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
     99                                                       GrGlyph::UnpackFixedX(packed),
    100                                                       GrGlyph::UnpackFixedY(packed));
    101     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
    102     bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
    103 
    104     return true;
    105 }
    106 
    107 namespace {
    108 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
    109 // A8, RGB565, or RGBA8888.
    110 template <typename INT_TYPE>
    111 void expand_bits(INT_TYPE* dst,
    112                  const uint8_t* src,
    113                  int width,
    114                  int height,
    115                  int dstRowBytes,
    116                  int srcRowBytes) {
    117     for (int i = 0; i < height; ++i) {
    118         int rowWritesLeft = width;
    119         const uint8_t* s = src;
    120         INT_TYPE* d = dst;
    121         while (rowWritesLeft > 0) {
    122             unsigned mask = *s++;
    123             for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
    124                 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
    125             }
    126         }
    127         dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
    128         src += srcRowBytes;
    129     }
    130 }
    131 }
    132 
    133 bool GrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
    134                                          int width, int height,
    135                                          int dstRB, void* dst) {
    136     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
    137                                                       GrGlyph::UnpackFixedX(packed),
    138                                                       GrGlyph::UnpackFixedY(packed));
    139     SkASSERT(glyph.fWidth == width);
    140     SkASSERT(glyph.fHeight == height);
    141     const void* src = fStrike->findImage(glyph);
    142     if (NULL == src) {
    143         return false;
    144     }
    145 
    146     int srcRB = glyph.rowBytes();
    147     // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
    148     // check the glyph's format, not the strike's format, and to be able to convert to any of the
    149     // GrMaskFormats.
    150     if (SkMask::kBW_Format == glyph.fMaskFormat) {
    151         // expand bits to our mask type
    152         const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
    153         switch (this->getMaskFormat()) {
    154             case kA8_GrMaskFormat:{
    155                 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
    156                 expand_bits(bytes, bits, width, height, dstRB, srcRB);
    157                 break;
    158             }
    159             case kA565_GrMaskFormat: {
    160                 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
    161                 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
    162                 break;
    163             }
    164             case kA888_GrMaskFormat: {
    165                 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst);
    166                 expand_bits(rgba8888, bits, width, height, dstRB, srcRB);
    167                 break;
    168             }
    169             default:
    170                 SkFAIL("Invalid GrMaskFormat");
    171         }
    172     } else if (srcRB == dstRB) {
    173         memcpy(dst, src, dstRB * height);
    174     } else {
    175         const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
    176         for (int y = 0; y < height; y++) {
    177             memcpy(dst, src, width * bbp);
    178             src = (const char*)src + srcRB;
    179             dst = (char*)dst + dstRB;
    180         }
    181     }
    182     return true;
    183 }
    184 
    185 bool GrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
    186                                            int width, int height,
    187                                            void* dst) {
    188     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
    189                                                       GrGlyph::UnpackFixedX(packed),
    190                                                       GrGlyph::UnpackFixedY(packed));
    191     SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
    192     SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
    193     const void* src = fStrike->findDistanceField(glyph);
    194     if (NULL == src) {
    195         return false;
    196     }
    197 
    198     memcpy(dst, src, width * height);
    199 
    200     return true;
    201 }
    202 
    203 // we should just return const SkPath* (NULL means false)
    204 bool GrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
    205 
    206     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
    207     const SkPath* skPath = fStrike->findPath(glyph);
    208     if (skPath) {
    209         *path = *skPath;
    210         return true;
    211     }
    212     return false;
    213 }
    214