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