Home | History | Annotate | Download | only in core
      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 "SkTypes.h"
     12 #include "SkFixed.h"
     13 #include "SkMask.h"
     14 
     15 class SkPath;
     16 
     17 // needs to be != to any valid SkMask::Format
     18 #define MASK_FORMAT_UNKNOWN         (0xFF)
     19 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
     20 
     21 #define kMaxGlyphWidth (1<<13)
     22 
     23 struct SkGlyph {
     24     void*       fImage;
     25     SkPath*     fPath;
     26     SkFixed     fAdvanceX, fAdvanceY;
     27 
     28     uint32_t    fID;
     29     uint16_t    fWidth, fHeight;
     30     int16_t     fTop, fLeft;
     31 
     32     uint8_t     fMaskFormat;
     33     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
     34 
     35     void init(uint32_t id) {
     36         fID             = id;
     37         fImage          = NULL;
     38         fPath           = NULL;
     39         fMaskFormat     = MASK_FORMAT_UNKNOWN;
     40     }
     41 
     42     /**
     43      *  Compute the rowbytes for the specified width and mask-format.
     44      */
     45     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
     46         unsigned rb = width;
     47         if (SkMask::kBW_Format == format) {
     48             rb = (rb + 7) >> 3;
     49         } else if (SkMask::kARGB32_Format == format ||
     50                    SkMask::kLCD32_Format == format)
     51         {
     52             rb <<= 2;
     53         } else if (SkMask::kLCD16_Format == format) {
     54             rb = SkAlign4(rb << 1);
     55         } else {
     56             rb = SkAlign4(rb);
     57         }
     58         return rb;
     59     }
     60 
     61     unsigned rowBytes() const {
     62         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     63     }
     64 
     65     bool isJustAdvance() const {
     66         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     67     }
     68 
     69     bool isFullMetrics() const {
     70         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     71     }
     72 
     73     uint16_t getGlyphID() const {
     74         return ID2Code(fID);
     75     }
     76 
     77     unsigned getGlyphID(unsigned baseGlyphCount) const {
     78         unsigned code = ID2Code(fID);
     79         SkASSERT(code >= baseGlyphCount);
     80         return code - baseGlyphCount;
     81     }
     82 
     83     unsigned getSubX() const {
     84         return ID2SubX(fID);
     85     }
     86 
     87     SkFixed getSubXFixed() const {
     88         return SubToFixed(ID2SubX(fID));
     89     }
     90 
     91     SkFixed getSubYFixed() const {
     92         return SubToFixed(ID2SubY(fID));
     93     }
     94 
     95     size_t computeImageSize() const;
     96 
     97     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
     98         encounters an error measuring a glyph). Note: this does not alter the
     99         fImage, fPath, fID, fMaskFormat fields.
    100      */
    101     void zeroMetrics();
    102 
    103     enum {
    104         kSubBits = 2,
    105         kSubMask = ((1 << kSubBits) - 1),
    106         kSubShift = 24, // must be large enough for glyphs and unichars
    107         kCodeMask = ((1 << kSubShift) - 1),
    108         // relative offsets for X and Y subpixel bits
    109         kSubShiftX = kSubBits,
    110         kSubShiftY = 0
    111     };
    112 
    113     static unsigned ID2Code(uint32_t id) {
    114         return id & kCodeMask;
    115     }
    116 
    117     static unsigned ID2SubX(uint32_t id) {
    118         return id >> (kSubShift + kSubShiftX);
    119     }
    120 
    121     static unsigned ID2SubY(uint32_t id) {
    122         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    123     }
    124 
    125     static unsigned FixedToSub(SkFixed n) {
    126         return (n >> (16 - kSubBits)) & kSubMask;
    127     }
    128 
    129     static SkFixed SubToFixed(unsigned sub) {
    130         SkASSERT(sub <= kSubMask);
    131         return sub << (16 - kSubBits);
    132     }
    133 
    134     static uint32_t MakeID(unsigned code) {
    135         return code;
    136     }
    137 
    138     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    139         SkASSERT(code <= kCodeMask);
    140         x = FixedToSub(x);
    141         y = FixedToSub(y);
    142         return (x << (kSubShift + kSubShiftX)) |
    143                (y << (kSubShift + kSubShiftY)) |
    144                code;
    145     }
    146 
    147     void toMask(SkMask* mask) const;
    148 };
    149 
    150 #endif
    151