1 /* GRAPHITE2 LICENSING
2
3 Copyright 2012, SIL International
4 All rights reserved.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should also have received a copy of the GNU Lesser General Public
17 License along with this library in the file named "LICENSE".
18 If not, write to the Free Software Foundation, 51 Franklin Street,
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 internet at http://www.fsf.org/licenses/lgpl.html.
21
22 Alternatively, the contents of this file may be used under the terms of the
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 License, as published by the Free Software Foundation, either version 2
25 of the License or (at your option) any later version.
26 */
27 #pragma once
28
29
30 #include "graphite2/Font.h"
31 #include "inc/Main.h"
32 #include "inc/Position.h"
33 #include "inc/GlyphFace.h"
34
35 namespace graphite2 {
36
37 class Face;
38 class FeatureVal;
39 class Segment;
40
41
42 struct SlantBox
43 {
44 static const SlantBox empty;
45
46 // SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
widthSlantBox47 float width() const { return sa - si; }
heightSlantBox48 float height() const { return da - di; }
49 float si; // min
50 float di; // min
51 float sa; // max
52 float da; // max
53 };
54
55
56 struct BBox
57 {
xiBBox58 BBox(float pxi = 0, float pyi = 0., float pxa = 0., float pya = 0.) : xi(pxi), yi(pyi), xa(pxa), ya(pya) {};
widthBBox59 float width() const { return xa - xi; }
heightBBox60 float height() const { return ya - yi; }
61 float xi; // min
62 float yi; // min
63 float xa; // max
64 float ya; // max
65 };
66
67
68 class GlyphBox
69 {
70 GlyphBox(const GlyphBox &);
71 GlyphBox & operator = (const GlyphBox &);
72
73 public:
GlyphBox(uint8 numsubs,unsigned short bitmap,Rect * slanted)74 GlyphBox(uint8 numsubs, unsigned short bitmap, Rect *slanted) : _num(numsubs), _bitmap(bitmap), _slant(*slanted) {};
75
addSubBox(int subindex,int boundary,Rect * val)76 void addSubBox(int subindex, int boundary, Rect *val) { _subs[subindex * 2 + boundary] = *val; }
subVal(int subindex,int boundary)77 Rect &subVal(int subindex, int boundary) { return _subs[subindex * 2 + boundary]; }
slant()78 const Rect &slant() const { return _slant; }
num()79 uint8 num() const { return _num; }
subs()80 const Rect *subs() const { return _subs; }
81
82 private:
83 uint8 _num;
84 unsigned short _bitmap;
85 Rect _slant;
86 Rect _subs[1];
87 };
88
89 class GlyphCache
90 {
91 class Loader;
92
93 GlyphCache(const GlyphCache&);
94 GlyphCache& operator=(const GlyphCache&);
95
96 public:
97 GlyphCache(const Face & face, const uint32 face_options);
98 ~GlyphCache();
99
100 unsigned short numGlyphs() const throw();
101 unsigned short numAttrs() const throw();
102 unsigned short unitsPerEm() const throw();
103
104 const GlyphFace *glyph(unsigned short glyphid) const; //result may be changed by subsequent call with a different glyphid
105 const GlyphFace *glyphSafe(unsigned short glyphid) const;
106 float getBoundingMetric(unsigned short glyphid, uint8 metric) const;
107 uint8 numSubBounds(unsigned short glyphid) const;
108 float getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const;
slant(unsigned short glyphid)109 const Rect & slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : _empty_slant_box; }
110 const SlantBox & getBoundingSlantBox(unsigned short glyphid) const;
111 const BBox & getBoundingBBox(unsigned short glyphid) const;
112 const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
113 const BBox & getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
114 bool check(unsigned short glyphid) const;
hasBoxes()115 bool hasBoxes() const { return _boxes != 0; }
116
117 CLASS_NEW_DELETE;
118
119 private:
120 const Rect _empty_slant_box;
121 const Loader * _glyph_loader;
122 const GlyphFace * * _glyphs;
123 GlyphBox * * _boxes;
124 unsigned short _num_glyphs,
125 _num_attrs,
126 _upem;
127 };
128
129 inline
numGlyphs()130 unsigned short GlyphCache::numGlyphs() const throw()
131 {
132 return _num_glyphs;
133 }
134
135 inline
numAttrs()136 unsigned short GlyphCache::numAttrs() const throw()
137 {
138 return _num_attrs;
139 }
140
141 inline
unitsPerEm()142 unsigned short GlyphCache::unitsPerEm() const throw()
143 {
144 return _upem;
145 }
146
147 inline
check(unsigned short glyphid)148 bool GlyphCache::check(unsigned short glyphid) const
149 {
150 return _boxes && glyphid < _num_glyphs;
151 }
152
153 inline
glyphSafe(unsigned short glyphid)154 const GlyphFace *GlyphCache::glyphSafe(unsigned short glyphid) const
155 {
156 return glyphid < _num_glyphs ? glyph(glyphid) : NULL;
157 }
158
159 inline
getBoundingMetric(unsigned short glyphid,uint8 metric)160 float GlyphCache::getBoundingMetric(unsigned short glyphid, uint8 metric) const
161 {
162 if (glyphid >= _num_glyphs) return 0.;
163 switch (metric) {
164 case 0: return (float)(glyph(glyphid)->theBBox().bl.x); // x_min
165 case 1: return (float)(glyph(glyphid)->theBBox().bl.y); // y_min
166 case 2: return (float)(glyph(glyphid)->theBBox().tr.x); // x_max
167 case 3: return (float)(glyph(glyphid)->theBBox().tr.y); // y_max
168 case 4: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.x : 0.f); // sum_min
169 case 5: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.y : 0.f); // diff_min
170 case 6: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.x : 0.f); // sum_max
171 case 7: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.y : 0.f); // diff_max
172 default: return 0.;
173 }
174 }
175
getBoundingSlantBox(unsigned short glyphid)176 inline const SlantBox &GlyphCache::getBoundingSlantBox(unsigned short glyphid) const
177 {
178 return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : SlantBox::empty;
179 }
180
getBoundingBBox(unsigned short glyphid)181 inline const BBox &GlyphCache::getBoundingBBox(unsigned short glyphid) const
182 {
183 return *(BBox *)(&(glyph(glyphid)->theBBox()));
184 }
185
186 inline
getSubBoundingMetric(unsigned short glyphid,uint8 subindex,uint8 metric)187 float GlyphCache::getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const
188 {
189 GlyphBox *b = _boxes[glyphid];
190 if (b == NULL || subindex >= b->num()) return 0;
191
192 switch (metric) {
193 case 0: return b->subVal(subindex, 0).bl.x;
194 case 1: return b->subVal(subindex, 0).bl.y;
195 case 2: return b->subVal(subindex, 0).tr.x;
196 case 3: return b->subVal(subindex, 0).tr.y;
197 case 4: return b->subVal(subindex, 1).bl.x;
198 case 5: return b->subVal(subindex, 1).bl.y;
199 case 6: return b->subVal(subindex, 1).tr.x;
200 case 7: return b->subVal(subindex, 1).tr.y;
201 default: return 0.;
202 }
203 }
204
getSubBoundingSlantBox(unsigned short glyphid,uint8 subindex)205 inline const SlantBox &GlyphCache::getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const
206 {
207 GlyphBox *b = _boxes[glyphid];
208 return *(SlantBox *)(b->subs() + 2 * subindex + 1);
209 }
210
getSubBoundingBBox(unsigned short glyphid,uint8 subindex)211 inline const BBox &GlyphCache::getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const
212 {
213 GlyphBox *b = _boxes[glyphid];
214 return *(BBox *)(b->subs() + 2 * subindex);
215 }
216
217 inline
numSubBounds(unsigned short glyphid)218 uint8 GlyphCache::numSubBounds(unsigned short glyphid) const
219 {
220 return _boxes[glyphid] ? _boxes[glyphid]->num() : 0;
221 }
222
223 } // namespace graphite2
224