blob: 649fa7dd5db658809fed657096ff11d1ab18145e [file] [log] [blame]
bungeman@google.combbe50132012-07-24 20:33:21 +00001/*
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
15class 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
23struct 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