|
1 /* GRAPHITE2 LICENSING |
|
2 |
|
3 Copyright 2010, 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 #include "inc/Main.h" |
|
30 |
|
31 #include <cassert> |
|
32 |
|
33 #include "inc/CharInfo.h" |
|
34 #include "inc/Face.h" |
|
35 #include "inc/FeatureVal.h" |
|
36 #include "inc/GlyphCache.h" |
|
37 #include "inc/GlyphFace.h" |
|
38 //#include "inc/Silf.h" |
|
39 #include "inc/Slot.h" |
|
40 #include "inc/Position.h" |
|
41 #include "inc/List.h" |
|
42 #include "inc/Bidi.h" |
|
43 |
|
44 #define MAX_SEG_GROWTH_FACTOR 256 |
|
45 |
|
46 namespace graphite2 { |
|
47 |
|
48 typedef Vector<Features> FeatureList; |
|
49 typedef Vector<Slot *> SlotRope; |
|
50 typedef Vector<int16 *> AttributeRope; |
|
51 typedef Vector<SlotJustify *> JustifyRope; |
|
52 |
|
53 #ifndef GRAPHITE2_NSEGCACHE |
|
54 class SegmentScopeState; |
|
55 #endif |
|
56 class Font; |
|
57 class Segment; |
|
58 class Silf; |
|
59 |
|
60 enum SpliceParam { |
|
61 /** sub-Segments longer than this are not cached |
|
62 * (in Unicode code points) */ |
|
63 eMaxSpliceSize = 96 |
|
64 }; |
|
65 |
|
66 enum justFlags { |
|
67 gr_justStartInline = 1, |
|
68 gr_justEndInline = 2 |
|
69 }; |
|
70 |
|
71 class SegmentScopeState |
|
72 { |
|
73 private: |
|
74 friend class Segment; |
|
75 Slot * realFirstSlot; |
|
76 Slot * slotBeforeScope; |
|
77 Slot * slotAfterScope; |
|
78 Slot * realLastSlot; |
|
79 size_t numGlyphsOutsideScope; |
|
80 }; |
|
81 |
|
82 class Segment |
|
83 { |
|
84 // Prevent copying of any kind. |
|
85 Segment(const Segment&); |
|
86 Segment& operator=(const Segment&); |
|
87 |
|
88 public: |
|
89 unsigned int slotCount() const { return m_numGlyphs; } //one slot per glyph |
|
90 void extendLength(int num) { m_numGlyphs += num; } |
|
91 Position advance() const { return m_advance; } |
|
92 bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;}; |
|
93 void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); } |
|
94 const Silf *silf() const { return m_silf; } |
|
95 unsigned int charInfoCount() const { return m_numCharinfo; } |
|
96 const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; } |
|
97 CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; } |
|
98 int8 dir() const { return m_dir; } |
|
99 |
|
100 Segment(unsigned int numchars, const Face* face, uint32 script, int dir); |
|
101 ~Segment(); |
|
102 #ifndef GRAPHITE2_NSEGCACHE |
|
103 SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength); |
|
104 void removeScope(SegmentScopeState & state); |
|
105 void append(const Segment &other); |
|
106 void splice(size_t offset, size_t length, Slot * const startSlot, |
|
107 Slot * endSlot, const Slot * srcSlot, |
|
108 const size_t numGlyphs); |
|
109 #endif |
|
110 Slot *first() { return m_first; } |
|
111 void first(Slot *p) { m_first = p; } |
|
112 Slot *last() { return m_last; } |
|
113 void last(Slot *p) { m_last = p; } |
|
114 void appendSlot(int i, int cid, int gid, int fid, size_t coffset); |
|
115 Slot *newSlot(); |
|
116 void freeSlot(Slot *); |
|
117 SlotJustify *newJustify(); |
|
118 void freeJustify(SlotJustify *aJustify); |
|
119 Position positionSlots(const Font *font, Slot *first=0, Slot *last=0); |
|
120 void associateChars(int offset, int num); |
|
121 void linkClusters(Slot *first, Slot *last); |
|
122 uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); } |
|
123 uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); } |
|
124 int addFeatures(const Features& feats) { m_feats.push_back(feats); return m_feats.size() - 1; } |
|
125 uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); } |
|
126 void dir(int8 val) { m_dir = val; } |
|
127 unsigned int passBits() const { return m_passBits; } |
|
128 void mergePassBits(const unsigned int val) { m_passBits &= val; } |
|
129 int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; } |
|
130 int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const; |
|
131 float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; } |
|
132 const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); } //warning value may become invalid when another glyph is accessed |
|
133 Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; } |
|
134 int numAttrs() const { return m_silf->numUser(); } |
|
135 int defaultOriginal() const { return m_defaultOriginal; } |
|
136 const Face * getFace() const { return m_face; } |
|
137 const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; } |
|
138 void bidiPass(uint8 aBidi, int paradir, uint8 aMirror); |
|
139 Slot *addLineEnd(Slot *nSlot); |
|
140 void delLineEnd(Slot *s); |
|
141 bool hasJustification() const { return m_justifies.size() != 0; } |
|
142 |
|
143 bool isWhitespace(const int cid) const; |
|
144 |
|
145 CLASS_NEW_DELETE |
|
146 |
|
147 public: //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir); |
|
148 bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars); |
|
149 void prepare_pos(const Font *font); |
|
150 void finalise(const Font *font); |
|
151 float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast); |
|
152 |
|
153 private: |
|
154 Position m_advance; // whole segment advance |
|
155 SlotRope m_slots; // Vector of slot buffers |
|
156 AttributeRope m_userAttrs; // Vector of userAttrs buffers |
|
157 JustifyRope m_justifies; // Slot justification info buffers |
|
158 FeatureList m_feats; // feature settings referenced by charinfos in this segment |
|
159 Slot * m_freeSlots; // linked list of free slots |
|
160 SlotJustify * m_freeJustifies; // Slot justification blocks free list |
|
161 CharInfo * m_charinfo; // character info, one per input character |
|
162 const Face * m_face; // GrFace |
|
163 const Silf * m_silf; |
|
164 Slot * m_first; // first slot in segment |
|
165 Slot * m_last; // last slot in segment |
|
166 unsigned int m_bufSize, // how big a buffer to create when need more slots |
|
167 m_numGlyphs, |
|
168 m_numCharinfo, // size of the array and number of input characters |
|
169 m_passBits; // if bit set then skip pass |
|
170 int m_defaultOriginal; // number of whitespace chars in the string |
|
171 int8 m_dir; |
|
172 }; |
|
173 |
|
174 |
|
175 |
|
176 inline |
|
177 void Segment::finalise(const Font *font) |
|
178 { |
|
179 if (!m_first) return; |
|
180 |
|
181 m_advance = positionSlots(font); |
|
182 associateChars(0, m_numCharinfo); |
|
183 linkClusters(m_first, m_last); |
|
184 } |
|
185 |
|
186 inline |
|
187 int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const { |
|
188 if (attrLevel > 0) |
|
189 { |
|
190 Slot *is = findRoot(iSlot); |
|
191 return is->clusterMetric(this, metric, attrLevel); |
|
192 } |
|
193 else |
|
194 return m_face->getGlyphMetric(iSlot->gid(), metric); |
|
195 } |
|
196 |
|
197 inline |
|
198 bool Segment::isWhitespace(const int cid) const |
|
199 { |
|
200 return ((cid >= 0x0009) * (cid <= 0x000D) |
|
201 + (cid == 0x0020) |
|
202 + (cid == 0x0085) |
|
203 + (cid == 0x00A0) |
|
204 + (cid == 0x1680) |
|
205 + (cid == 0x180E) |
|
206 + (cid >= 0x2000) * (cid <= 0x200A) |
|
207 + (cid == 0x2028) |
|
208 + (cid == 0x2029) |
|
209 + (cid == 0x202F) |
|
210 + (cid == 0x205F) |
|
211 + (cid == 0x3000)) != 0; |
|
212 } |
|
213 |
|
214 //inline |
|
215 //bool Segment::isWhitespace(const int cid) const |
|
216 //{ |
|
217 // switch (cid >> 8) |
|
218 // { |
|
219 // case 0x00: |
|
220 // switch (cid) |
|
221 // { |
|
222 // case 0x09: |
|
223 // case 0x0A: |
|
224 // case 0x0B: |
|
225 // case 0x0C: |
|
226 // case 0x0D: |
|
227 // case 0x20: |
|
228 // return true; |
|
229 // default: |
|
230 // break; |
|
231 // } |
|
232 // break; |
|
233 // case 0x16: |
|
234 // return cid == 0x1680; |
|
235 // break; |
|
236 // case 0x18: |
|
237 // return cid == 0x180E; |
|
238 // break; |
|
239 // case 0x20: |
|
240 // switch (cid) |
|
241 // { |
|
242 // case 0x00: |
|
243 // case 0x01: |
|
244 // case 0x02: |
|
245 // case 0x03: |
|
246 // case 0x04: |
|
247 // case 0x05: |
|
248 // case 0x06: |
|
249 // case 0x07: |
|
250 // case 0x08: |
|
251 // case 0x09: |
|
252 // case 0x0A: |
|
253 // case 0x28: |
|
254 // case 0x29: |
|
255 // case 0x2F: |
|
256 // case 0x5F: |
|
257 // return true |
|
258 // default: |
|
259 // break; |
|
260 // } |
|
261 // break; |
|
262 // case 0x30: |
|
263 // return cid == 0x3000; |
|
264 // break; |
|
265 // } |
|
266 // |
|
267 // return false; |
|
268 //} |
|
269 |
|
270 } // namespace graphite2 |
|
271 |
|
272 struct gr_segment : public graphite2::Segment {}; |
|
273 |