Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* GRAPHITE2 LICENSING |
michael@0 | 2 | |
michael@0 | 3 | Copyright 2010, SIL International |
michael@0 | 4 | All rights reserved. |
michael@0 | 5 | |
michael@0 | 6 | This library is free software; you can redistribute it and/or modify |
michael@0 | 7 | it under the terms of the GNU Lesser General Public License as published |
michael@0 | 8 | by the Free Software Foundation; either version 2.1 of License, or |
michael@0 | 9 | (at your option) any later version. |
michael@0 | 10 | |
michael@0 | 11 | This program is distributed in the hope that it will be useful, |
michael@0 | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
michael@0 | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
michael@0 | 14 | Lesser General Public License for more details. |
michael@0 | 15 | |
michael@0 | 16 | You should also have received a copy of the GNU Lesser General Public |
michael@0 | 17 | License along with this library in the file named "LICENSE". |
michael@0 | 18 | If not, write to the Free Software Foundation, 51 Franklin Street, |
michael@0 | 19 | Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
michael@0 | 20 | internet at http://www.fsf.org/licenses/lgpl.html. |
michael@0 | 21 | |
michael@0 | 22 | Alternatively, the contents of this file may be used under the terms of the |
michael@0 | 23 | Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
michael@0 | 24 | License, as published by the Free Software Foundation, either version 2 |
michael@0 | 25 | of the License or (at your option) any later version. |
michael@0 | 26 | */ |
michael@0 | 27 | #pragma once |
michael@0 | 28 | |
michael@0 | 29 | #include "inc/Main.h" |
michael@0 | 30 | |
michael@0 | 31 | #include <cassert> |
michael@0 | 32 | |
michael@0 | 33 | #include "inc/CharInfo.h" |
michael@0 | 34 | #include "inc/Face.h" |
michael@0 | 35 | #include "inc/FeatureVal.h" |
michael@0 | 36 | #include "inc/GlyphCache.h" |
michael@0 | 37 | #include "inc/GlyphFace.h" |
michael@0 | 38 | //#include "inc/Silf.h" |
michael@0 | 39 | #include "inc/Slot.h" |
michael@0 | 40 | #include "inc/Position.h" |
michael@0 | 41 | #include "inc/List.h" |
michael@0 | 42 | #include "inc/Bidi.h" |
michael@0 | 43 | |
michael@0 | 44 | #define MAX_SEG_GROWTH_FACTOR 256 |
michael@0 | 45 | |
michael@0 | 46 | namespace graphite2 { |
michael@0 | 47 | |
michael@0 | 48 | typedef Vector<Features> FeatureList; |
michael@0 | 49 | typedef Vector<Slot *> SlotRope; |
michael@0 | 50 | typedef Vector<int16 *> AttributeRope; |
michael@0 | 51 | typedef Vector<SlotJustify *> JustifyRope; |
michael@0 | 52 | |
michael@0 | 53 | #ifndef GRAPHITE2_NSEGCACHE |
michael@0 | 54 | class SegmentScopeState; |
michael@0 | 55 | #endif |
michael@0 | 56 | class Font; |
michael@0 | 57 | class Segment; |
michael@0 | 58 | class Silf; |
michael@0 | 59 | |
michael@0 | 60 | enum SpliceParam { |
michael@0 | 61 | /** sub-Segments longer than this are not cached |
michael@0 | 62 | * (in Unicode code points) */ |
michael@0 | 63 | eMaxSpliceSize = 96 |
michael@0 | 64 | }; |
michael@0 | 65 | |
michael@0 | 66 | enum justFlags { |
michael@0 | 67 | gr_justStartInline = 1, |
michael@0 | 68 | gr_justEndInline = 2 |
michael@0 | 69 | }; |
michael@0 | 70 | |
michael@0 | 71 | class SegmentScopeState |
michael@0 | 72 | { |
michael@0 | 73 | private: |
michael@0 | 74 | friend class Segment; |
michael@0 | 75 | Slot * realFirstSlot; |
michael@0 | 76 | Slot * slotBeforeScope; |
michael@0 | 77 | Slot * slotAfterScope; |
michael@0 | 78 | Slot * realLastSlot; |
michael@0 | 79 | size_t numGlyphsOutsideScope; |
michael@0 | 80 | }; |
michael@0 | 81 | |
michael@0 | 82 | class Segment |
michael@0 | 83 | { |
michael@0 | 84 | // Prevent copying of any kind. |
michael@0 | 85 | Segment(const Segment&); |
michael@0 | 86 | Segment& operator=(const Segment&); |
michael@0 | 87 | |
michael@0 | 88 | public: |
michael@0 | 89 | unsigned int slotCount() const { return m_numGlyphs; } //one slot per glyph |
michael@0 | 90 | void extendLength(int num) { m_numGlyphs += num; } |
michael@0 | 91 | Position advance() const { return m_advance; } |
michael@0 | 92 | bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;}; |
michael@0 | 93 | void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); } |
michael@0 | 94 | const Silf *silf() const { return m_silf; } |
michael@0 | 95 | unsigned int charInfoCount() const { return m_numCharinfo; } |
michael@0 | 96 | const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; } |
michael@0 | 97 | CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; } |
michael@0 | 98 | int8 dir() const { return m_dir; } |
michael@0 | 99 | |
michael@0 | 100 | Segment(unsigned int numchars, const Face* face, uint32 script, int dir); |
michael@0 | 101 | ~Segment(); |
michael@0 | 102 | #ifndef GRAPHITE2_NSEGCACHE |
michael@0 | 103 | SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength); |
michael@0 | 104 | void removeScope(SegmentScopeState & state); |
michael@0 | 105 | void append(const Segment &other); |
michael@0 | 106 | void splice(size_t offset, size_t length, Slot * const startSlot, |
michael@0 | 107 | Slot * endSlot, const Slot * srcSlot, |
michael@0 | 108 | const size_t numGlyphs); |
michael@0 | 109 | #endif |
michael@0 | 110 | Slot *first() { return m_first; } |
michael@0 | 111 | void first(Slot *p) { m_first = p; } |
michael@0 | 112 | Slot *last() { return m_last; } |
michael@0 | 113 | void last(Slot *p) { m_last = p; } |
michael@0 | 114 | void appendSlot(int i, int cid, int gid, int fid, size_t coffset); |
michael@0 | 115 | Slot *newSlot(); |
michael@0 | 116 | void freeSlot(Slot *); |
michael@0 | 117 | SlotJustify *newJustify(); |
michael@0 | 118 | void freeJustify(SlotJustify *aJustify); |
michael@0 | 119 | Position positionSlots(const Font *font, Slot *first=0, Slot *last=0); |
michael@0 | 120 | void associateChars(int offset, int num); |
michael@0 | 121 | void linkClusters(Slot *first, Slot *last); |
michael@0 | 122 | uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); } |
michael@0 | 123 | uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); } |
michael@0 | 124 | int addFeatures(const Features& feats) { m_feats.push_back(feats); return m_feats.size() - 1; } |
michael@0 | 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]); } |
michael@0 | 126 | void dir(int8 val) { m_dir = val; } |
michael@0 | 127 | unsigned int passBits() const { return m_passBits; } |
michael@0 | 128 | void mergePassBits(const unsigned int val) { m_passBits &= val; } |
michael@0 | 129 | int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; } |
michael@0 | 130 | int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const; |
michael@0 | 131 | float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; } |
michael@0 | 132 | const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); } //warning value may become invalid when another glyph is accessed |
michael@0 | 133 | Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; } |
michael@0 | 134 | int numAttrs() const { return m_silf->numUser(); } |
michael@0 | 135 | int defaultOriginal() const { return m_defaultOriginal; } |
michael@0 | 136 | const Face * getFace() const { return m_face; } |
michael@0 | 137 | const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; } |
michael@0 | 138 | void bidiPass(uint8 aBidi, int paradir, uint8 aMirror); |
michael@0 | 139 | Slot *addLineEnd(Slot *nSlot); |
michael@0 | 140 | void delLineEnd(Slot *s); |
michael@0 | 141 | bool hasJustification() const { return m_justifies.size() != 0; } |
michael@0 | 142 | |
michael@0 | 143 | bool isWhitespace(const int cid) const; |
michael@0 | 144 | |
michael@0 | 145 | CLASS_NEW_DELETE |
michael@0 | 146 | |
michael@0 | 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); |
michael@0 | 148 | bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars); |
michael@0 | 149 | void prepare_pos(const Font *font); |
michael@0 | 150 | void finalise(const Font *font); |
michael@0 | 151 | float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast); |
michael@0 | 152 | |
michael@0 | 153 | private: |
michael@0 | 154 | Position m_advance; // whole segment advance |
michael@0 | 155 | SlotRope m_slots; // Vector of slot buffers |
michael@0 | 156 | AttributeRope m_userAttrs; // Vector of userAttrs buffers |
michael@0 | 157 | JustifyRope m_justifies; // Slot justification info buffers |
michael@0 | 158 | FeatureList m_feats; // feature settings referenced by charinfos in this segment |
michael@0 | 159 | Slot * m_freeSlots; // linked list of free slots |
michael@0 | 160 | SlotJustify * m_freeJustifies; // Slot justification blocks free list |
michael@0 | 161 | CharInfo * m_charinfo; // character info, one per input character |
michael@0 | 162 | const Face * m_face; // GrFace |
michael@0 | 163 | const Silf * m_silf; |
michael@0 | 164 | Slot * m_first; // first slot in segment |
michael@0 | 165 | Slot * m_last; // last slot in segment |
michael@0 | 166 | unsigned int m_bufSize, // how big a buffer to create when need more slots |
michael@0 | 167 | m_numGlyphs, |
michael@0 | 168 | m_numCharinfo, // size of the array and number of input characters |
michael@0 | 169 | m_passBits; // if bit set then skip pass |
michael@0 | 170 | int m_defaultOriginal; // number of whitespace chars in the string |
michael@0 | 171 | int8 m_dir; |
michael@0 | 172 | }; |
michael@0 | 173 | |
michael@0 | 174 | |
michael@0 | 175 | |
michael@0 | 176 | inline |
michael@0 | 177 | void Segment::finalise(const Font *font) |
michael@0 | 178 | { |
michael@0 | 179 | if (!m_first) return; |
michael@0 | 180 | |
michael@0 | 181 | m_advance = positionSlots(font); |
michael@0 | 182 | associateChars(0, m_numCharinfo); |
michael@0 | 183 | linkClusters(m_first, m_last); |
michael@0 | 184 | } |
michael@0 | 185 | |
michael@0 | 186 | inline |
michael@0 | 187 | int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const { |
michael@0 | 188 | if (attrLevel > 0) |
michael@0 | 189 | { |
michael@0 | 190 | Slot *is = findRoot(iSlot); |
michael@0 | 191 | return is->clusterMetric(this, metric, attrLevel); |
michael@0 | 192 | } |
michael@0 | 193 | else |
michael@0 | 194 | return m_face->getGlyphMetric(iSlot->gid(), metric); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | inline |
michael@0 | 198 | bool Segment::isWhitespace(const int cid) const |
michael@0 | 199 | { |
michael@0 | 200 | return ((cid >= 0x0009) * (cid <= 0x000D) |
michael@0 | 201 | + (cid == 0x0020) |
michael@0 | 202 | + (cid == 0x0085) |
michael@0 | 203 | + (cid == 0x00A0) |
michael@0 | 204 | + (cid == 0x1680) |
michael@0 | 205 | + (cid == 0x180E) |
michael@0 | 206 | + (cid >= 0x2000) * (cid <= 0x200A) |
michael@0 | 207 | + (cid == 0x2028) |
michael@0 | 208 | + (cid == 0x2029) |
michael@0 | 209 | + (cid == 0x202F) |
michael@0 | 210 | + (cid == 0x205F) |
michael@0 | 211 | + (cid == 0x3000)) != 0; |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | //inline |
michael@0 | 215 | //bool Segment::isWhitespace(const int cid) const |
michael@0 | 216 | //{ |
michael@0 | 217 | // switch (cid >> 8) |
michael@0 | 218 | // { |
michael@0 | 219 | // case 0x00: |
michael@0 | 220 | // switch (cid) |
michael@0 | 221 | // { |
michael@0 | 222 | // case 0x09: |
michael@0 | 223 | // case 0x0A: |
michael@0 | 224 | // case 0x0B: |
michael@0 | 225 | // case 0x0C: |
michael@0 | 226 | // case 0x0D: |
michael@0 | 227 | // case 0x20: |
michael@0 | 228 | // return true; |
michael@0 | 229 | // default: |
michael@0 | 230 | // break; |
michael@0 | 231 | // } |
michael@0 | 232 | // break; |
michael@0 | 233 | // case 0x16: |
michael@0 | 234 | // return cid == 0x1680; |
michael@0 | 235 | // break; |
michael@0 | 236 | // case 0x18: |
michael@0 | 237 | // return cid == 0x180E; |
michael@0 | 238 | // break; |
michael@0 | 239 | // case 0x20: |
michael@0 | 240 | // switch (cid) |
michael@0 | 241 | // { |
michael@0 | 242 | // case 0x00: |
michael@0 | 243 | // case 0x01: |
michael@0 | 244 | // case 0x02: |
michael@0 | 245 | // case 0x03: |
michael@0 | 246 | // case 0x04: |
michael@0 | 247 | // case 0x05: |
michael@0 | 248 | // case 0x06: |
michael@0 | 249 | // case 0x07: |
michael@0 | 250 | // case 0x08: |
michael@0 | 251 | // case 0x09: |
michael@0 | 252 | // case 0x0A: |
michael@0 | 253 | // case 0x28: |
michael@0 | 254 | // case 0x29: |
michael@0 | 255 | // case 0x2F: |
michael@0 | 256 | // case 0x5F: |
michael@0 | 257 | // return true |
michael@0 | 258 | // default: |
michael@0 | 259 | // break; |
michael@0 | 260 | // } |
michael@0 | 261 | // break; |
michael@0 | 262 | // case 0x30: |
michael@0 | 263 | // return cid == 0x3000; |
michael@0 | 264 | // break; |
michael@0 | 265 | // } |
michael@0 | 266 | // |
michael@0 | 267 | // return false; |
michael@0 | 268 | //} |
michael@0 | 269 | |
michael@0 | 270 | } // namespace graphite2 |
michael@0 | 271 | |
michael@0 | 272 | struct gr_segment : public graphite2::Segment {}; |
michael@0 | 273 |