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