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