LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkGlyph.h (source / functions) Hit Total Coverage
Test: output.info Lines: 51 96 53.1 %
Date: 2017-07-14 16:53:18 Functions: 18 33 54.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkGlyph_DEFINED
       9             : #define SkGlyph_DEFINED
      10             : 
      11             : #include "SkArenaAlloc.h"
      12             : #include "SkChecksum.h"
      13             : #include "SkFixed.h"
      14             : #include "SkMask.h"
      15             : #include "SkTypes.h"
      16             : 
      17             : 
      18             : class SkPath;
      19             : class SkGlyphCache;
      20             : 
      21             : // needs to be != to any valid SkMask::Format
      22             : #define MASK_FORMAT_UNKNOWN         (0xFF)
      23             : #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
      24             : 
      25             : #define kMaxGlyphWidth (1<<13)
      26             : 
      27             : /** (glyph-index or unicode-point) + subpixel-pos */
      28             : struct SkPackedID {
      29             :     static constexpr uint32_t kImpossibleID = ~0;
      30             :     enum {
      31             :         kSubBits = 2,
      32             :         kSubMask = ((1 << kSubBits) - 1),
      33             :         kSubShift = 24, // must be large enough for glyphs and unichars
      34             :         kCodeMask = ((1 << kSubShift) - 1),
      35             :         // relative offsets for X and Y subpixel bits
      36             :         kSubShiftX = kSubBits,
      37             :         kSubShiftY = 0
      38             :     };
      39             : 
      40         448 :     SkPackedID(uint32_t code) {
      41         448 :         SkASSERT(code <= kCodeMask);
      42         448 :         SkASSERT(code != kImpossibleID);
      43         448 :         fID = code;
      44         448 :     }
      45             : 
      46           0 :     SkPackedID(uint32_t code, SkFixed x, SkFixed y) {
      47           0 :         SkASSERT(code <= kCodeMask);
      48           0 :         x = FixedToSub(x);
      49           0 :         y = FixedToSub(y);
      50           0 :         uint32_t ID = (x << (kSubShift + kSubShiftX)) |
      51           0 :                       (y << (kSubShift + kSubShiftY)) |
      52           0 :                       code;
      53           0 :         SkASSERT(ID != kImpossibleID);
      54           0 :         fID = ID;
      55           0 :     }
      56             : 
      57         362 :     constexpr SkPackedID() : fID(kImpossibleID) {}
      58             : 
      59         448 :     bool operator==(const SkPackedID& that) const {
      60         448 :         return fID == that.fID;
      61             :     }
      62          60 :     bool operator!=(const SkPackedID& that) const {
      63          60 :         return !(*this == that);
      64             :     }
      65             : 
      66         118 :     uint32_t code() const {
      67         118 :         return fID & kCodeMask;
      68             :     }
      69             : 
      70           0 :     SkFixed getSubXFixed() const {
      71           0 :         return SubToFixed(ID2SubX(fID));
      72             :     }
      73             : 
      74           0 :     SkFixed getSubYFixed() const {
      75           0 :         return SubToFixed(ID2SubY(fID));
      76             :     }
      77             : 
      78         574 :     uint32_t hash() const {
      79         574 :         return SkChecksum::CheapMix(fID);
      80             :     }
      81             : 
      82             : // FIXME - This is needed because the Android framework directly accesses fID.
      83             : // Remove when fID accesses are cleaned up.
      84             : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
      85             :     operator uint32_t() const { return fID; }
      86             : #endif
      87             : 
      88             : private:
      89           0 :     static unsigned ID2SubX(uint32_t id) {
      90           0 :         return id >> (kSubShift + kSubShiftX);
      91             :     }
      92             : 
      93           0 :     static unsigned ID2SubY(uint32_t id) {
      94           0 :         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
      95             :     }
      96             : 
      97           0 :     static unsigned FixedToSub(SkFixed n) {
      98           0 :         return (n >> (16 - kSubBits)) & kSubMask;
      99             :     }
     100             : 
     101           0 :     static SkFixed SubToFixed(unsigned sub) {
     102           0 :         SkASSERT(sub <= kSubMask);
     103           0 :         return sub << (16 - kSubBits);
     104             :     }
     105             : 
     106             :     uint32_t fID;
     107             : };
     108             : 
     109             : struct SkPackedGlyphID : public SkPackedID {
     110         448 :     SkPackedGlyphID(SkGlyphID code) : SkPackedID(code) { }
     111           0 :     SkPackedGlyphID(SkGlyphID code, SkFixed x, SkFixed y) : SkPackedID(code, x, y) { }
     112         362 :     SkPackedGlyphID() : SkPackedID() { }
     113         118 :     SkGlyphID code() const {
     114         118 :         return SkTo<SkGlyphID>(SkPackedID::code());
     115             :     }
     116             : };
     117             : 
     118             : struct SkPackedUnicharID : public SkPackedID {
     119           0 :     SkPackedUnicharID(SkUnichar code) : SkPackedID(code) { }
     120           0 :     SkPackedUnicharID(SkUnichar code, SkFixed x, SkFixed y) : SkPackedID(code, x, y) { }
     121           0 :     SkPackedUnicharID() : SkPackedID() { }
     122             :     SkUnichar code() const {
     123             :         return SkTo<SkUnichar>(SkPackedID::code());
     124             :     }
     125             : };
     126             : 
     127             : SK_BEGIN_REQUIRE_DENSE
     128         302 : class SkGlyph {
     129             :     // Support horizontal and vertical skipping strike-through / underlines.
     130             :     // The caller walks the linked list looking for a match. For a horizontal underline,
     131             :     // the fBounds contains the top and bottom of the underline. The fInterval pair contains the
     132             :     // beginning and end of of the intersection of the bounds and the glyph's path.
     133             :     // If interval[0] >= interval[1], no intesection was found.
     134             :     struct Intercept {
     135             :         Intercept* fNext;
     136             :         SkScalar   fBounds[2];    // for horz underlines, the boundaries in Y
     137             :         SkScalar   fInterval[2];  // the outside intersections of the axis and the glyph
     138             :     };
     139             : 
     140             :     struct PathData {
     141             :         Intercept* fIntercept;
     142             :         SkPath*    fPath;
     143             :     };
     144             : 
     145             : public:
     146             :     static const SkFixed kSubpixelRound = SK_FixedHalf >> SkPackedID::kSubBits;
     147             :     void*       fImage;
     148             :     PathData*   fPathData;
     149             :     float       fAdvanceX, fAdvanceY;
     150             : 
     151             :     uint16_t    fWidth, fHeight;
     152             :     int16_t     fTop, fLeft;
     153             : 
     154             :     uint8_t     fMaskFormat;
     155             :     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
     156             :     int8_t      fForceBW;
     157             : 
     158          60 :     void initWithGlyphID(SkPackedGlyphID glyph_id) {
     159          60 :         fID             = glyph_id;
     160          60 :         fImage          = nullptr;
     161          60 :         fPathData       = nullptr;
     162          60 :         fMaskFormat     = MASK_FORMAT_UNKNOWN;
     163          60 :         fForceBW        = 0;
     164          60 :     }
     165             : 
     166           0 :     static size_t BitsToBytes(size_t bits) {
     167           0 :         return (bits + 7) >> 3;
     168             :     }
     169             : 
     170             :     /**
     171             :      *  Compute the rowbytes for the specified width and mask-format.
     172             :      */
     173         387 :     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
     174         387 :         unsigned rb = width;
     175         387 :         if (SkMask::kBW_Format == format) {
     176           0 :             rb = BitsToBytes(rb);
     177         387 :         } else if (SkMask::kARGB32_Format == format) {
     178           0 :             rb <<= 2;
     179         387 :         } else if (SkMask::kLCD16_Format == format) {
     180         387 :             rb = SkAlign4(rb << 1);
     181             :         } else {
     182           0 :             rb = SkAlign4(rb);
     183             :         }
     184         387 :         return rb;
     185             :     }
     186             : 
     187          58 :     size_t allocImage(SkArenaAlloc* alloc) {
     188             :         size_t allocSize;
     189          58 :         if (SkMask::kBW_Format == fMaskFormat) {
     190           0 :             allocSize = BitsToBytes(fWidth) * fHeight;
     191           0 :             fImage = alloc->makeArrayDefault<char>(allocSize);
     192          58 :         } else if (SkMask::kARGB32_Format == fMaskFormat) {
     193           0 :             allocSize = fWidth * fHeight;
     194           0 :             fImage = alloc->makeArrayDefault<uint32_t>(fWidth * fHeight);
     195           0 :             allocSize *= sizeof(uint32_t);
     196          58 :         } else if (SkMask::kLCD16_Format == fMaskFormat) {
     197          58 :             allocSize = SkAlign2(fWidth) * fHeight;
     198          58 :             fImage = alloc->makeArrayDefault<uint16_t>(allocSize);
     199          58 :             allocSize *= sizeof(uint16_t);
     200             :         } else {
     201           0 :             allocSize = SkAlign4(fWidth) * fHeight;
     202           0 :             fImage = alloc->makeArrayDefault<char>(allocSize);
     203             :         }
     204          58 :         return allocSize;
     205             :     }
     206             : 
     207         387 :     unsigned rowBytes() const {
     208         387 :         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     209             :     }
     210             : 
     211         388 :     bool isJustAdvance() const {
     212         388 :         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     213             :     }
     214             : 
     215             :     bool isFullMetrics() const {
     216             :         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     217             :     }
     218             : 
     219         118 :     SkGlyphID getGlyphID() const {
     220         118 :         return fID.code();
     221             :     }
     222             : 
     223           0 :     SkPackedGlyphID getPackedID() const {
     224           0 :         return fID;
     225             :     }
     226             : 
     227           0 :     SkFixed getSubXFixed() const {
     228           0 :         return fID.getSubXFixed();
     229             :     }
     230             : 
     231           0 :     SkFixed getSubYFixed() const {
     232           0 :         return fID.getSubYFixed();
     233             :     }
     234             : 
     235             :     size_t computeImageSize() const;
     236             : 
     237             :     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
     238             :         encounters an error measuring a glyph). Note: this does not alter the
     239             :         fImage, fPath, fID, fMaskFormat fields.
     240             :      */
     241             :     void zeroMetrics();
     242             : 
     243             :     void toMask(SkMask* mask) const;
     244             : 
     245             :     class HashTraits {
     246             :     public:
     247         514 :         static SkPackedGlyphID GetKey(const SkGlyph& glyph) {
     248         514 :             return glyph.fID;
     249             :         }
     250         574 :         static uint32_t Hash(SkPackedGlyphID glyphId) {
     251         574 :             return glyphId.hash();
     252             :         }
     253             :     };
     254             : 
     255             :  private:
     256             :     // TODO(herb) remove friend statement after SkGlyphCache cleanup.
     257             :     friend class SkGlyphCache;
     258             : 
     259             : // FIXME - This is needed because the Android frame work directly accesses fID.
     260             : // Remove when fID accesses are cleaned up.
     261             : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     262             :   public:
     263             : #endif
     264             :     SkPackedGlyphID fID;
     265             : };
     266             : SK_END_REQUIRE_DENSE
     267             : 
     268             : #endif

Generated by: LCOV version 1.13