1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/Segment.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,494 @@ 1.4 +/* GRAPHITE2 LICENSING 1.5 + 1.6 + Copyright 2010, SIL International 1.7 + All rights reserved. 1.8 + 1.9 + This library is free software; you can redistribute it and/or modify 1.10 + it under the terms of the GNU Lesser General Public License as published 1.11 + by the Free Software Foundation; either version 2.1 of License, or 1.12 + (at your option) any later version. 1.13 + 1.14 + This program is distributed in the hope that it will be useful, 1.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + Lesser General Public License for more details. 1.18 + 1.19 + You should also have received a copy of the GNU Lesser General Public 1.20 + License along with this library in the file named "LICENSE". 1.21 + If not, write to the Free Software Foundation, 51 Franklin Street, 1.22 + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 1.23 + internet at http://www.fsf.org/licenses/lgpl.html. 1.24 + 1.25 +Alternatively, the contents of this file may be used under the terms of the 1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 1.27 +License, as published by the Free Software Foundation, either version 2 1.28 +of the License or (at your option) any later version. 1.29 +*/ 1.30 +#include "inc/UtfCodec.h" 1.31 +#include <cstring> 1.32 +#include <cstdlib> 1.33 + 1.34 +#include "inc/bits.h" 1.35 +#include "inc/Segment.h" 1.36 +#include "graphite2/Font.h" 1.37 +#include "inc/CharInfo.h" 1.38 +#include "inc/debug.h" 1.39 +#include "inc/Slot.h" 1.40 +#include "inc/Main.h" 1.41 +#include "inc/CmapCache.h" 1.42 +#include "inc/Bidi.h" 1.43 +#include "graphite2/Segment.h" 1.44 + 1.45 + 1.46 +using namespace graphite2; 1.47 + 1.48 +Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir) 1.49 +: m_freeSlots(NULL), 1.50 + m_freeJustifies(NULL), 1.51 + m_charinfo(new CharInfo[numchars]), 1.52 + m_face(face), 1.53 + m_silf(face->chooseSilf(script)), 1.54 + m_first(NULL), 1.55 + m_last(NULL), 1.56 + m_bufSize(numchars + 10), 1.57 + m_numGlyphs(numchars), 1.58 + m_numCharinfo(numchars), 1.59 + m_passBits(m_silf->aPassBits() ? -1 : 0), 1.60 + m_defaultOriginal(0), 1.61 + m_dir(textDir) 1.62 +{ 1.63 + freeSlot(newSlot()); 1.64 + m_bufSize = log_binary(numchars)+1; 1.65 +} 1.66 + 1.67 +Segment::~Segment() 1.68 +{ 1.69 + for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i) 1.70 + free(*i); 1.71 + for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j) 1.72 + free(*j); 1.73 + delete[] m_charinfo; 1.74 +} 1.75 + 1.76 +#ifndef GRAPHITE2_NSEGCACHE 1.77 +SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength) 1.78 +{ 1.79 + SegmentScopeState state; 1.80 + state.numGlyphsOutsideScope = m_numGlyphs - subLength; 1.81 + state.realFirstSlot = m_first; 1.82 + state.slotBeforeScope = firstSlot->prev(); 1.83 + state.slotAfterScope = lastSlot->next(); 1.84 + state.realLastSlot = m_last; 1.85 + firstSlot->prev(NULL); 1.86 + lastSlot->next(NULL); 1.87 + assert(m_defaultOriginal == 0); 1.88 + m_defaultOriginal = firstSlot->original(); 1.89 + m_numGlyphs = subLength; 1.90 + m_first = firstSlot; 1.91 + m_last = lastSlot; 1.92 + return state; 1.93 +} 1.94 + 1.95 +void Segment::removeScope(SegmentScopeState & state) 1.96 +{ 1.97 + m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs; 1.98 + if (state.slotBeforeScope) 1.99 + { 1.100 + state.slotBeforeScope->next(m_first); 1.101 + m_first->prev(state.slotBeforeScope); 1.102 + m_first = state.realFirstSlot; 1.103 + } 1.104 + if (state.slotAfterScope) 1.105 + { 1.106 + state.slotAfterScope->prev(m_last); 1.107 + m_last->next(state.slotAfterScope); 1.108 + m_last = state.realLastSlot; 1.109 + } 1.110 + m_defaultOriginal = 0; 1.111 +} 1.112 + 1.113 +#if 0 1.114 +void Segment::append(const Segment &other) 1.115 +{ 1.116 + Rect bbox = other.m_bbox + m_advance; 1.117 + 1.118 + m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end()); 1.119 + CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo]; //since CharInfo has no constructor, this doesn't do much 1.120 + for (unsigned int i=0 ; i<m_numCharinfo ; ++i) 1.121 + pNewCharInfo[i] = m_charinfo[i]; 1.122 + m_last->next(other.m_first); 1.123 + other.m_last->prev(m_last); 1.124 + m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end()); 1.125 + 1.126 + delete[] m_charinfo; 1.127 + m_charinfo = pNewCharInfo; 1.128 + pNewCharInfo += m_numCharinfo ; 1.129 + for (unsigned int i=0 ; i<m_numCharinfo ; ++i) 1.130 + pNewCharInfo[i] = other.m_charinfo[i]; 1.131 + 1.132 + m_numCharinfo += other.m_numCharinfo; 1.133 + m_numGlyphs += other.m_numGlyphs; 1.134 + m_advance = m_advance + other.m_advance; 1.135 + m_bbox = m_bbox.widen(bbox); 1.136 + m_passBits &= other.passBits(); 1.137 +} 1.138 +#endif 1.139 +#endif // GRAPHITE2_NSEGCACHE 1.140 + 1.141 +void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset) 1.142 +{ 1.143 + Slot *aSlot = newSlot(); 1.144 + 1.145 + if (!aSlot) return; 1.146 + m_charinfo[id].init(cid); 1.147 + m_charinfo[id].feats(iFeats); 1.148 + m_charinfo[id].base(coffset); 1.149 + const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid); 1.150 + m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0); 1.151 + 1.152 + aSlot->child(NULL); 1.153 + aSlot->setGlyph(this, gid, theGlyph); 1.154 + aSlot->originate(id); 1.155 + aSlot->before(id); 1.156 + aSlot->after(id); 1.157 + if (m_last) m_last->next(aSlot); 1.158 + aSlot->prev(m_last); 1.159 + m_last = aSlot; 1.160 + if (!m_first) m_first = aSlot; 1.161 + if (theGlyph && m_silf->aPassBits()) 1.162 + m_passBits &= theGlyph->attrs()[m_silf->aPassBits()] 1.163 + | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0); 1.164 +} 1.165 + 1.166 +Slot *Segment::newSlot() 1.167 +{ 1.168 + if (!m_freeSlots) 1.169 + { 1.170 + int numUser = m_silf->numUser(); 1.171 +#if !defined GRAPHITE2_NTRACING 1.172 + if (m_face->logger()) ++numUser; 1.173 +#endif 1.174 + Slot *newSlots = grzeroalloc<Slot>(m_bufSize); 1.175 + int16 *newAttrs = grzeroalloc<int16>(numUser * m_bufSize); 1.176 + if (!newSlots || !newAttrs) return NULL; 1.177 + for (size_t i = 0; i < m_bufSize; i++) 1.178 + { 1.179 + newSlots[i].next(newSlots + i + 1); 1.180 + newSlots[i].userAttrs(newAttrs + i * numUser); 1.181 + newSlots[i].setBidiClass(-1); 1.182 + } 1.183 + newSlots[m_bufSize - 1].next(NULL); 1.184 + newSlots[0].next(NULL); 1.185 + m_slots.push_back(newSlots); 1.186 + m_userAttrs.push_back(newAttrs); 1.187 + m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL; 1.188 + return newSlots; 1.189 + } 1.190 + Slot *res = m_freeSlots; 1.191 + m_freeSlots = m_freeSlots->next(); 1.192 + res->next(NULL); 1.193 + return res; 1.194 +} 1.195 + 1.196 +void Segment::freeSlot(Slot *aSlot) 1.197 +{ 1.198 + if (m_last == aSlot) m_last = aSlot->prev(); 1.199 + if (m_first == aSlot) m_first = aSlot->next(); 1.200 + if (aSlot->attachedTo()) 1.201 + aSlot->attachedTo()->removeChild(aSlot); 1.202 + while (aSlot->firstChild()) 1.203 + { 1.204 + aSlot->firstChild()->attachTo(NULL); 1.205 + aSlot->removeChild(aSlot->firstChild()); 1.206 + } 1.207 + // reset the slot incase it is reused 1.208 + ::new (aSlot) Slot; 1.209 + memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16)); 1.210 + // Update generation counter for debug 1.211 +#if !defined GRAPHITE2_NTRACING 1.212 + if (m_face->logger()) 1.213 + ++aSlot->userAttrs()[m_silf->numUser()]; 1.214 +#endif 1.215 + // update next pointer 1.216 + if (!m_freeSlots) 1.217 + aSlot->next(NULL); 1.218 + else 1.219 + aSlot->next(m_freeSlots); 1.220 + m_freeSlots = aSlot; 1.221 +} 1.222 + 1.223 +SlotJustify *Segment::newJustify() 1.224 +{ 1.225 + if (!m_freeJustifies) 1.226 + { 1.227 + const size_t justSize = SlotJustify::size_of(m_silf->numJustLevels()); 1.228 + byte *justs = grzeroalloc<byte>(justSize * m_bufSize); 1.229 + if (!justs) return NULL; 1.230 + for (int i = m_bufSize - 2; i >= 0; --i) 1.231 + { 1.232 + SlotJustify *p = reinterpret_cast<SlotJustify *>(justs + justSize * i); 1.233 + SlotJustify *next = reinterpret_cast<SlotJustify *>(justs + justSize * (i + 1)); 1.234 + p->next = next; 1.235 + } 1.236 + m_freeJustifies = (SlotJustify *)justs; 1.237 + m_justifies.push_back(m_freeJustifies); 1.238 + } 1.239 + SlotJustify *res = m_freeJustifies; 1.240 + m_freeJustifies = m_freeJustifies->next; 1.241 + res->next = NULL; 1.242 + return res; 1.243 +} 1.244 + 1.245 +void Segment::freeJustify(SlotJustify *aJustify) 1.246 +{ 1.247 + int numJust = m_silf->numJustLevels(); 1.248 + if (m_silf->numJustLevels() <= 0) numJust = 1; 1.249 + aJustify->next = m_freeJustifies; 1.250 + memset(aJustify->values, 0, numJust*SlotJustify::NUMJUSTPARAMS*sizeof(int16)); 1.251 + m_freeJustifies = aJustify; 1.252 +} 1.253 + 1.254 +#ifndef GRAPHITE2_NSEGCACHE 1.255 +void Segment::splice(size_t offset, size_t length, Slot * const startSlot, 1.256 + Slot * endSlot, const Slot * srcSlot, 1.257 + const size_t numGlyphs) 1.258 +{ 1.259 + size_t numChars = length; 1.260 + extendLength(numGlyphs - length); 1.261 + // remove any extra 1.262 + if (numGlyphs < length) 1.263 + { 1.264 + Slot * end = endSlot->next(); 1.265 + do 1.266 + { 1.267 + endSlot = endSlot->prev(); 1.268 + freeSlot(endSlot->next()); 1.269 + } while (numGlyphs < --length); 1.270 + endSlot->next(end); 1.271 + if (end) 1.272 + end->prev(endSlot); 1.273 + } 1.274 + else 1.275 + { 1.276 + // insert extra slots if needed 1.277 + while (numGlyphs > length) 1.278 + { 1.279 + Slot * extra = newSlot(); 1.280 + if (!extra) return; 1.281 + extra->prev(endSlot); 1.282 + extra->next(endSlot->next()); 1.283 + endSlot->next(extra); 1.284 + if (extra->next()) 1.285 + extra->next()->prev(extra); 1.286 + if (m_last == endSlot) 1.287 + m_last = extra; 1.288 + endSlot = extra; 1.289 + ++length; 1.290 + } 1.291 + } 1.292 + 1.293 + endSlot = endSlot->next(); 1.294 + assert(numGlyphs == length); 1.295 + assert(offset + numChars <= m_numCharinfo); 1.296 + Slot * indexmap[eMaxSpliceSize*3]; 1.297 + assert(numGlyphs < sizeof indexmap/sizeof *indexmap); 1.298 + Slot * slot = startSlot; 1.299 + for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i) 1.300 + indexmap[i] = slot; 1.301 + 1.302 + for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next()) 1.303 + { 1.304 + slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars); 1.305 + if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]); 1.306 + if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()]; 1.307 + if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()]; 1.308 + } 1.309 +} 1.310 +#endif // GRAPHITE2_NSEGCACHE 1.311 + 1.312 +void Segment::linkClusters(Slot *s, Slot * end) 1.313 +{ 1.314 + end = end->next(); 1.315 + 1.316 + for (; s != end && !s->isBase(); s = s->next()); 1.317 + Slot * ls = s; 1.318 + 1.319 + if (m_dir & 1) 1.320 + { 1.321 + for (; s != end; s = s->next()) 1.322 + { 1.323 + if (!s->isBase()) continue; 1.324 + 1.325 + s->sibling(ls); 1.326 + ls = s; 1.327 + } 1.328 + } 1.329 + else 1.330 + { 1.331 + for (; s != end; s = s->next()) 1.332 + { 1.333 + if (!s->isBase()) continue; 1.334 + 1.335 + ls->sibling(s); 1.336 + ls = s; 1.337 + } 1.338 + } 1.339 +} 1.340 + 1.341 +Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd) 1.342 +{ 1.343 + Position currpos(0., 0.); 1.344 + float clusterMin = 0.; 1.345 + Rect bbox; 1.346 + 1.347 + if (!iStart) iStart = m_first; 1.348 + if (!iEnd) iEnd = m_last; 1.349 + 1.350 + if (m_dir & 1) 1.351 + { 1.352 + for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev()) 1.353 + { 1.354 + if (s->isBase()) 1.355 + currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x); 1.356 + } 1.357 + } 1.358 + else 1.359 + { 1.360 + for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next()) 1.361 + { 1.362 + if (s->isBase()) 1.363 + currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x); 1.364 + } 1.365 + } 1.366 + return currpos; 1.367 +} 1.368 + 1.369 + 1.370 +void Segment::associateChars(int offset, int numChars) 1.371 +{ 1.372 + int i = 0, j = 0; 1.373 + CharInfo *c, *cend; 1.374 + for (c = m_charinfo + offset, cend = m_charinfo + offset + numChars; c != cend; ++c) 1.375 + { 1.376 + c->before(-1); 1.377 + c->after(-1); 1.378 + } 1.379 + for (Slot * s = m_first; s; s->index(i++), s = s->next()) 1.380 + { 1.381 + j = s->before(); 1.382 + if (j < 0) continue; 1.383 + 1.384 + for (const int after = s->after(); j <= after; ++j) 1.385 + { 1.386 + c = charinfo(j); 1.387 + if (c->before() == -1 || i < c->before()) c->before(i); 1.388 + if (c->after() < i) c->after(i); 1.389 + } 1.390 + } 1.391 + for (Slot *s = m_first; s; s = s->next()) 1.392 + { 1.393 + int a; 1.394 + for (a = s->after() + 1; a < offset + numChars && charinfo(a)->after() < 0; ++a) 1.395 + { charinfo(a)->after(s->index()); } 1.396 + --a; 1.397 + s->after(a); 1.398 + 1.399 + for (a = s->before() - 1; a >= offset && charinfo(a)->before() < 0; --a) 1.400 + { charinfo(a)->before(s->index()); } 1.401 + ++a; 1.402 + s->before(a); 1.403 + } 1.404 +} 1.405 + 1.406 + 1.407 +template <typename utf_iter> 1.408 +inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars) 1.409 +{ 1.410 + const Cmap & cmap = face.cmap(); 1.411 + int slotid = 0; 1.412 + 1.413 + const typename utf_iter::codeunit_type * const base = c; 1.414 + for (; n_chars; --n_chars, ++c, ++slotid) 1.415 + { 1.416 + const uint32 usv = *c; 1.417 + uint16 gid = cmap[usv]; 1.418 + if (!gid) gid = face.findPseudo(usv); 1.419 + seg.appendSlot(slotid, usv, gid, fid, c - base); 1.420 + } 1.421 +} 1.422 + 1.423 + 1.424 +bool Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars) 1.425 +{ 1.426 + assert(face); 1.427 + assert(pFeats); 1.428 + if (!m_charinfo) return false; 1.429 + 1.430 + // utf iterator is self recovering so we don't care about the error state of the iterator. 1.431 + switch (enc) 1.432 + { 1.433 + case gr_utf8: process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break; 1.434 + case gr_utf16: process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break; 1.435 + case gr_utf32: process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break; 1.436 + } 1.437 + return true; 1.438 +} 1.439 + 1.440 +void Segment::prepare_pos(const Font * /*font*/) 1.441 +{ 1.442 + // copy key changeable metrics into slot (if any); 1.443 +} 1.444 + 1.445 +Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &stack); 1.446 +void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror); 1.447 +void resolveWhitespace(int baseLevel, Slot *s); 1.448 +Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0); 1.449 + 1.450 +void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror) 1.451 +{ 1.452 + if (slotCount() == 0) 1.453 + return; 1.454 + 1.455 + Slot *s; 1.456 + int baseLevel = paradir ? 1 : 0; 1.457 + unsigned int bmask = 0; 1.458 + unsigned int ssize = 0; 1.459 + for (s = first(); s; s = s->next()) 1.460 + { 1.461 + if (s->getBidiClass() == -1) 1.462 + { 1.463 + unsigned int bAttr = glyphAttr(s->gid(), aBidi); 1.464 + s->setBidiClass((bAttr <= 22) * bAttr); 1.465 + } 1.466 + bmask |= (1 << s->getBidiClass()); 1.467 + s->setBidiLevel(baseLevel); 1.468 + if (glyphAttr(s->gid(), aMirror) && s->getBidiClass() == 21) 1.469 + ++ssize; 1.470 + } 1.471 + 1.472 + BracketPairStack bstack(ssize); 1.473 + if (bmask & (paradir ? 0x2E7892 : 0x2E789C)) 1.474 + { 1.475 + // O(8N) algorithm, with no working data beyond what is needed for processParens 1.476 + int nextLevel = paradir; 1.477 + int e, i, c; 1.478 + process_bidi(first(), baseLevel, paradir, nextLevel, 0, 0, c = 0, i = 0, e = 0, 1, this, aMirror, bstack); 1.479 + resolveImplicit(first(), this, aMirror); 1.480 + resolveWhitespace(baseLevel, last()); 1.481 + s = resolveOrder(s = first(), baseLevel != 0); 1.482 + if (s) 1.483 + { 1.484 + first(s); last(s->prev()); 1.485 + s->prev()->next(0); s->prev(0); 1.486 + } 1.487 + } 1.488 + else if (!(dir() & 4) && baseLevel && aMirror) 1.489 + { 1.490 + for (s = first(); s; s = s->next()) 1.491 + { 1.492 + unsigned short g = glyphAttr(s->gid(), aMirror); 1.493 + if (g) s->setGlyph(this, g); 1.494 + } 1.495 + } 1.496 +} 1.497 +