Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* GRAPHITE2 LICENSING
3 Copyright 2010, SIL International
4 All rights reserved.
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.
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.
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.
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
29 #include "inc/Main.h"
31 #include <cassert>
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"
44 #define MAX_SEG_GROWTH_FACTOR 256
46 namespace graphite2 {
48 typedef Vector<Features> FeatureList;
49 typedef Vector<Slot *> SlotRope;
50 typedef Vector<int16 *> AttributeRope;
51 typedef Vector<SlotJustify *> JustifyRope;
53 #ifndef GRAPHITE2_NSEGCACHE
54 class SegmentScopeState;
55 #endif
56 class Font;
57 class Segment;
58 class Silf;
60 enum SpliceParam {
61 /** sub-Segments longer than this are not cached
62 * (in Unicode code points) */
63 eMaxSpliceSize = 96
64 };
66 enum justFlags {
67 gr_justStartInline = 1,
68 gr_justEndInline = 2
69 };
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 };
82 class Segment
83 {
84 // Prevent copying of any kind.
85 Segment(const Segment&);
86 Segment& operator=(const Segment&);
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; }
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; }
143 bool isWhitespace(const int cid) const;
145 CLASS_NEW_DELETE
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);
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 };
176 inline
177 void Segment::finalise(const Font *font)
178 {
179 if (!m_first) return;
181 m_advance = positionSlots(font);
182 associateChars(0, m_numCharinfo);
183 linkClusters(m_first, m_last);
184 }
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 }
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 }
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 //}
270 } // namespace graphite2
272 struct gr_segment : public graphite2::Segment {};