1// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2// Copyright 2012, SIL International, All rights reserved.
3
4#pragma once
5
6
7#include "graphite2/Font.h"
8#include "inc/Main.h"
9#include "inc/Position.h"
10#include "inc/GlyphFace.h"
11
12namespace graphite2 {
13
14class Face;
15class FeatureVal;
16class Segment;
17
18
19struct SlantBox
20{
21 static const SlantBox empty;
22
23// SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
24 float width() const { return sa - si; }
25 float height() const { return da - di; }
26 float si; // min
27 float di; // min
28 float sa; // max
29 float da; // max
30};
31
32
33struct BBox
34{
35 BBox(float pxi = 0, float pyi = 0., float pxa = 0., float pya = 0.) : xi(pxi), yi(pyi), xa(pxa), ya(pya) {};
36 float width() const { return xa - xi; }
37 float height() const { return ya - yi; }
38 float xi; // min
39 float yi; // min
40 float xa; // max
41 float ya; // max
42};
43
44
45class GlyphBox
46{
47 GlyphBox(const GlyphBox &);
48 GlyphBox & operator = (const GlyphBox &);
49
50public:
51 GlyphBox(uint8 numsubs, unsigned short bitmap, Rect *slanted) : _num(numsubs), _bitmap(bitmap), _slant(*slanted) {};
52
53 void addSubBox(int subindex, int boundary, Rect *val) { _subs[subindex * 2 + boundary] = *val; }
54 Rect &subVal(int subindex, int boundary) { return _subs[subindex * 2 + boundary]; }
55 const Rect &slant() const { return _slant; }
56 uint8 num() const { return _num; }
57 const Rect *subs() const { return _subs; }
58
59private:
60 uint8 _num;
61 unsigned short _bitmap;
62 Rect _slant;
63 Rect _subs[1];
64};
65
66class GlyphCache
67{
68 class Loader;
69
70 GlyphCache(const GlyphCache&);
71 GlyphCache& operator=(const GlyphCache&);
72
73public:
74 GlyphCache(const Face & face, const uint32 face_options);
75 ~GlyphCache();
76
77 unsigned short numGlyphs() const throw();
78 unsigned short numAttrs() const throw();
79 unsigned short unitsPerEm() const throw();
80
81 const GlyphFace *glyph(unsigned short glyphid) const; //result may be changed by subsequent call with a different glyphid
82 const GlyphFace *glyphSafe(unsigned short glyphid) const;
83 float getBoundingMetric(unsigned short glyphid, uint8 metric) const;
84 uint8 numSubBounds(unsigned short glyphid) const;
85 float getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const;
86 const Rect & slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : _empty_slant_box; }
87 const SlantBox & getBoundingSlantBox(unsigned short glyphid) const;
88 const BBox & getBoundingBBox(unsigned short glyphid) const;
89 const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
90 const BBox & getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
91 bool check(unsigned short glyphid) const;
92 bool hasBoxes() const { return _boxes != 0; }
93
94 CLASS_NEW_DELETE;
95
96private:
97 const Rect _empty_slant_box;
98 const Loader * _glyph_loader;
99 const GlyphFace * * _glyphs;
100 GlyphBox * * _boxes;
101 unsigned short _num_glyphs,
102 _num_attrs,
103 _upem;
104};
105
106inline
107unsigned short GlyphCache::numGlyphs() const throw()
108{
109 return _num_glyphs;
110}
111
112inline
113unsigned short GlyphCache::numAttrs() const throw()
114{
115 return _num_attrs;
116}
117
118inline
119unsigned short GlyphCache::unitsPerEm() const throw()
120{
121 return _upem;
122}
123
124inline
125bool GlyphCache::check(unsigned short glyphid) const
126{
127 return _boxes && glyphid < _num_glyphs;
128}
129
130inline
131const GlyphFace *GlyphCache::glyphSafe(unsigned short glyphid) const
132{
133 return glyphid < _num_glyphs ? glyph(glyphid) : NULL;
134}
135
136inline
137float GlyphCache::getBoundingMetric(unsigned short glyphid, uint8 metric) const
138{
139 if (glyphid >= _num_glyphs) return 0.;
140 switch (metric) {
141 case 0: return (float)(glyph(glyphid)->theBBox().bl.x); // x_min
142 case 1: return (float)(glyph(glyphid)->theBBox().bl.y); // y_min
143 case 2: return (float)(glyph(glyphid)->theBBox().tr.x); // x_max
144 case 3: return (float)(glyph(glyphid)->theBBox().tr.y); // y_max
145 case 4: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.x : 0.f); // sum_min
146 case 5: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.y : 0.f); // diff_min
147 case 6: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.x : 0.f); // sum_max
148 case 7: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.y : 0.f); // diff_max
149 default: return 0.;
150 }
151}
152
153inline const SlantBox &GlyphCache::getBoundingSlantBox(unsigned short glyphid) const
154{
155 return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : SlantBox::empty;
156}
157
158inline const BBox &GlyphCache::getBoundingBBox(unsigned short glyphid) const
159{
160 return *(BBox *)(&(glyph(glyphid)->theBBox()));
161}
162
163inline
164float GlyphCache::getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const
165{
166 GlyphBox *b = _boxes[glyphid];
167 if (b == NULL || subindex >= b->num()) return 0;
168
169 switch (metric) {
170 case 0: return b->subVal(subindex, 0).bl.x;
171 case 1: return b->subVal(subindex, 0).bl.y;
172 case 2: return b->subVal(subindex, 0).tr.x;
173 case 3: return b->subVal(subindex, 0).tr.y;
174 case 4: return b->subVal(subindex, 1).bl.x;
175 case 5: return b->subVal(subindex, 1).bl.y;
176 case 6: return b->subVal(subindex, 1).tr.x;
177 case 7: return b->subVal(subindex, 1).tr.y;
178 default: return 0.;
179 }
180}
181
182inline const SlantBox &GlyphCache::getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const
183{
184 GlyphBox *b = _boxes[glyphid];
185 return *(SlantBox *)(b->subs() + 2 * subindex + 1);
186}
187
188inline const BBox &GlyphCache::getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const
189{
190 GlyphBox *b = _boxes[glyphid];
191 return *(BBox *)(b->subs() + 2 * subindex);
192}
193
194inline
195uint8 GlyphCache::numSubBounds(unsigned short glyphid) const
196{
197 return _boxes[glyphid] ? _boxes[glyphid]->num() : 0;
198}
199
200} // namespace graphite2
201