michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkGlyph_DEFINED michael@0: #define SkGlyph_DEFINED michael@0: michael@0: #include "SkTypes.h" michael@0: #include "SkFixed.h" michael@0: #include "SkMask.h" michael@0: michael@0: class SkPath; michael@0: michael@0: // needs to be != to any valid SkMask::Format michael@0: #define MASK_FORMAT_UNKNOWN (0xFF) michael@0: #define MASK_FORMAT_JUST_ADVANCE MASK_FORMAT_UNKNOWN michael@0: michael@0: #define kMaxGlyphWidth (1<<13) michael@0: michael@0: struct SkGlyph { michael@0: void* fImage; michael@0: SkPath* fPath; michael@0: SkFixed fAdvanceX, fAdvanceY; michael@0: michael@0: uint32_t fID; michael@0: uint16_t fWidth, fHeight; michael@0: int16_t fTop, fLeft; michael@0: michael@0: uint8_t fMaskFormat; michael@0: int8_t fRsbDelta, fLsbDelta; // used by auto-kerning michael@0: michael@0: void init(uint32_t id) { michael@0: fID = id; michael@0: fImage = NULL; michael@0: fPath = NULL; michael@0: fMaskFormat = MASK_FORMAT_UNKNOWN; michael@0: } michael@0: michael@0: /** michael@0: * Compute the rowbytes for the specified width and mask-format. michael@0: */ michael@0: static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) { michael@0: unsigned rb = width; michael@0: if (SkMask::kBW_Format == format) { michael@0: rb = (rb + 7) >> 3; michael@0: } else if (SkMask::kARGB32_Format == format || michael@0: SkMask::kLCD32_Format == format) michael@0: { michael@0: rb <<= 2; michael@0: } else if (SkMask::kLCD16_Format == format) { michael@0: rb = SkAlign4(rb << 1); michael@0: } else { michael@0: rb = SkAlign4(rb); michael@0: } michael@0: return rb; michael@0: } michael@0: michael@0: unsigned rowBytes() const { michael@0: return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); michael@0: } michael@0: michael@0: bool isJustAdvance() const { michael@0: return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; michael@0: } michael@0: michael@0: bool isFullMetrics() const { michael@0: return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; michael@0: } michael@0: michael@0: uint16_t getGlyphID() const { michael@0: return ID2Code(fID); michael@0: } michael@0: michael@0: unsigned getGlyphID(unsigned baseGlyphCount) const { michael@0: unsigned code = ID2Code(fID); michael@0: SkASSERT(code >= baseGlyphCount); michael@0: return code - baseGlyphCount; michael@0: } michael@0: michael@0: unsigned getSubX() const { michael@0: return ID2SubX(fID); michael@0: } michael@0: michael@0: SkFixed getSubXFixed() const { michael@0: return SubToFixed(ID2SubX(fID)); michael@0: } michael@0: michael@0: SkFixed getSubYFixed() const { michael@0: return SubToFixed(ID2SubY(fID)); michael@0: } michael@0: michael@0: size_t computeImageSize() const; michael@0: michael@0: /** Call this to set all of the metrics fields to 0 (e.g. if the scaler michael@0: encounters an error measuring a glyph). Note: this does not alter the michael@0: fImage, fPath, fID, fMaskFormat fields. michael@0: */ michael@0: void zeroMetrics(); michael@0: michael@0: enum { michael@0: kSubBits = 2, michael@0: kSubMask = ((1 << kSubBits) - 1), michael@0: kSubShift = 24, // must be large enough for glyphs and unichars michael@0: kCodeMask = ((1 << kSubShift) - 1), michael@0: // relative offsets for X and Y subpixel bits michael@0: kSubShiftX = kSubBits, michael@0: kSubShiftY = 0 michael@0: }; michael@0: michael@0: static unsigned ID2Code(uint32_t id) { michael@0: return id & kCodeMask; michael@0: } michael@0: michael@0: static unsigned ID2SubX(uint32_t id) { michael@0: return id >> (kSubShift + kSubShiftX); michael@0: } michael@0: michael@0: static unsigned ID2SubY(uint32_t id) { michael@0: return (id >> (kSubShift + kSubShiftY)) & kSubMask; michael@0: } michael@0: michael@0: static unsigned FixedToSub(SkFixed n) { michael@0: return (n >> (16 - kSubBits)) & kSubMask; michael@0: } michael@0: michael@0: static SkFixed SubToFixed(unsigned sub) { michael@0: SkASSERT(sub <= kSubMask); michael@0: return sub << (16 - kSubBits); michael@0: } michael@0: michael@0: static uint32_t MakeID(unsigned code) { michael@0: return code; michael@0: } michael@0: michael@0: static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) { michael@0: SkASSERT(code <= kCodeMask); michael@0: x = FixedToSub(x); michael@0: y = FixedToSub(y); michael@0: return (x << (kSubShift + kSubShiftX)) | michael@0: (y << (kSubShift + kSubShiftY)) | michael@0: code; michael@0: } michael@0: michael@0: void toMask(SkMask* mask) const; michael@0: }; michael@0: michael@0: #endif