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