1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/Slot.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,427 @@ 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/Segment.h" 1.31 +#include "inc/Slot.h" 1.32 +#include "inc/Silf.h" 1.33 +#include "inc/CharInfo.h" 1.34 +#include "inc/Rule.h" 1.35 + 1.36 + 1.37 +using namespace graphite2; 1.38 + 1.39 +Slot::Slot() : 1.40 + m_next(NULL), m_prev(NULL), 1.41 + m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0), 1.42 + m_index(0), m_parent(NULL), m_child(NULL), m_sibling(NULL), 1.43 + m_position(0, 0), m_shift(0, 0), m_advance(0, 0), 1.44 + m_attach(0, 0), m_with(0, 0), m_just(0.), 1.45 + m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), m_justs(NULL) 1.46 + // Do not set m_userAttr since it is set *before* new is called since this 1.47 + // is used as a positional new to reset the GrSlot 1.48 +{ 1.49 +} 1.50 + 1.51 +// take care, this does not copy any of the GrSlot pointer fields 1.52 +void Slot::set(const Slot & orig, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars) 1.53 +{ 1.54 + // leave m_next and m_prev unchanged 1.55 + m_glyphid = orig.m_glyphid; 1.56 + m_realglyphid = orig.m_realglyphid; 1.57 + m_original = orig.m_original + charOffset; 1.58 + if (charOffset + int(orig.m_before) < 0) 1.59 + m_before = 0; 1.60 + else 1.61 + m_before = orig.m_before + charOffset; 1.62 + if (charOffset <= 0 && orig.m_after + charOffset >= numChars) 1.63 + m_after = numChars - 1; 1.64 + else 1.65 + m_after = orig.m_after + charOffset; 1.66 + m_parent = NULL; 1.67 + m_child = NULL; 1.68 + m_sibling = NULL; 1.69 + m_position = orig.m_position; 1.70 + m_shift = orig.m_shift; 1.71 + m_advance = orig.m_advance; 1.72 + m_attach = orig.m_attach; 1.73 + m_with = orig.m_with; 1.74 + m_flags = orig.m_flags; 1.75 + m_attLevel = orig.m_attLevel; 1.76 + m_bidiCls = orig.m_bidiCls; 1.77 + m_bidiLevel = orig.m_bidiLevel; 1.78 + if (m_userAttr && orig.m_userAttr) 1.79 + memcpy(m_userAttr, orig.m_userAttr, numUserAttr * sizeof(*m_userAttr)); 1.80 + if (m_justs && orig.m_justs) 1.81 + memcpy(m_justs, orig.m_justs, SlotJustify::size_of(justLevels)); 1.82 +} 1.83 + 1.84 +void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos) 1.85 +{ 1.86 + m_before += numCharInfo; 1.87 + m_after += numCharInfo; 1.88 + m_position = m_position + relpos; 1.89 +} 1.90 + 1.91 +Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin) 1.92 +{ 1.93 + if (attrLevel && m_attLevel > attrLevel) return Position(0, 0); 1.94 + float scale = 1.0; 1.95 + Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y); 1.96 + float tAdvance = m_advance.x + m_just; 1.97 + const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph()); 1.98 + if (font) 1.99 + { 1.100 + scale = font->scale(); 1.101 + shift *= scale; 1.102 + if (font->isHinted() && glyphFace) 1.103 + tAdvance = (m_advance.x - glyphFace->theAdvance().x + m_just) * scale + font->advance(m_glyphid); 1.104 + else 1.105 + tAdvance *= scale; 1.106 + } 1.107 + Position res; 1.108 + 1.109 + m_position = base + shift; 1.110 + if (!m_parent) 1.111 + { 1.112 + res = base + Position(tAdvance, m_advance.y * scale); 1.113 + clusterMin = base.x; 1.114 + } 1.115 + else 1.116 + { 1.117 + float tAdv; 1.118 + m_position += (m_attach - m_with) * scale; 1.119 + tAdv = m_advance.x >= 0.5 ? m_position.x + tAdvance - shift.x : 0.f; 1.120 + res = Position(tAdv, 0); 1.121 + if ((m_advance.x >= 0.5 || m_position.x < 0) && m_position.x < clusterMin) clusterMin = m_position.x; 1.122 + } 1.123 + 1.124 + if (glyphFace) 1.125 + { 1.126 + Rect ourBbox = glyphFace->theBBox() * scale + m_position; 1.127 + bbox = bbox.widen(ourBbox); 1.128 + } 1.129 + 1.130 + if (m_child && m_child != this && m_child->attachedTo() == this) 1.131 + { 1.132 + Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin); 1.133 + if ((!m_parent || m_advance.x >= 0.5) && tRes.x > res.x) res = tRes; 1.134 + } 1.135 + 1.136 + if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent) 1.137 + { 1.138 + Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin); 1.139 + if (tRes.x > res.x) res = tRes; 1.140 + } 1.141 + 1.142 + if (!m_parent && clusterMin < base.x) 1.143 + { 1.144 + Position adj = Position(base.x - clusterMin, 0.); 1.145 + res += adj; 1.146 + m_position += adj; 1.147 + if (m_child) m_child->floodShift(adj); 1.148 + } 1.149 + return res; 1.150 +} 1.151 + 1.152 +int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel) 1.153 +{ 1.154 + Position base; 1.155 + Rect bbox = seg->theGlyphBBoxTemporary(glyph()); 1.156 + float clusterMin = 0.; 1.157 + Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin); 1.158 + 1.159 + switch (metrics(metric)) 1.160 + { 1.161 + case kgmetLsb : 1.162 + return static_cast<uint32>(bbox.bl.x); 1.163 + case kgmetRsb : 1.164 + return static_cast<uint32>(res.x - bbox.tr.x); 1.165 + case kgmetBbTop : 1.166 + return static_cast<uint32>(bbox.tr.y); 1.167 + case kgmetBbBottom : 1.168 + return static_cast<uint32>(bbox.bl.y); 1.169 + case kgmetBbLeft : 1.170 + return static_cast<uint32>(bbox.bl.x); 1.171 + case kgmetBbRight : 1.172 + return static_cast<uint32>(bbox.tr.x); 1.173 + case kgmetBbWidth : 1.174 + return static_cast<uint32>(bbox.tr.x - bbox.bl.x); 1.175 + case kgmetBbHeight : 1.176 + return static_cast<uint32>(bbox.tr.y - bbox.bl.y); 1.177 + case kgmetAdvWidth : 1.178 + return static_cast<uint32>(res.x); 1.179 + case kgmetAdvHeight : 1.180 + return static_cast<uint32>(res.y); 1.181 + default : 1.182 + return 0; 1.183 + } 1.184 +} 1.185 + 1.186 +int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const 1.187 +{ 1.188 + if (!this) return 0; 1.189 + if (ind == gr_slatUserDefnV1) 1.190 + { 1.191 + ind = gr_slatUserDefn; 1.192 + subindex = 0; 1.193 + } 1.194 + else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth) 1.195 + { 1.196 + int indx = ind - gr_slatJStretch; 1.197 + return getJustify(seg, indx / 5, indx % 5); 1.198 + } 1.199 + 1.200 + switch (ind) 1.201 + { 1.202 + case gr_slatAdvX : return int(m_advance.x); 1.203 + case gr_slatAdvY : return int(m_advance.y); 1.204 + case gr_slatAttTo : return m_parent ? 1 : 0; 1.205 + case gr_slatAttX : return int(m_attach.x); 1.206 + case gr_slatAttY : return int(m_attach.y); 1.207 + case gr_slatAttXOff : 1.208 + case gr_slatAttYOff : return 0; 1.209 + case gr_slatAttWithX : return int(m_with.x); 1.210 + case gr_slatAttWithY : return int(m_with.y); 1.211 + case gr_slatAttWithXOff: 1.212 + case gr_slatAttWithYOff:return 0; 1.213 + case gr_slatAttLevel : return m_attLevel; 1.214 + case gr_slatBreak : return seg->charinfo(m_original)->breakWeight(); 1.215 + case gr_slatCompRef : return 0; 1.216 + case gr_slatDir : if (m_bidiCls == -1) 1.217 + const_cast<Slot *>(this)->setBidiClass(seg->glyphAttr(gid(), seg->silf()->aBidi())); 1.218 + return m_bidiCls; 1.219 + case gr_slatInsert : return isInsertBefore(); 1.220 + case gr_slatPosX : return int(m_position.x); // but need to calculate it 1.221 + case gr_slatPosY : return int(m_position.y); 1.222 + case gr_slatShiftX : return int(m_shift.x); 1.223 + case gr_slatShiftY : return int(m_shift.y); 1.224 + case gr_slatMeasureSol: return -1; // err what's this? 1.225 + case gr_slatMeasureEol: return -1; 1.226 + case gr_slatJWidth: return int(m_just); 1.227 + case gr_slatUserDefn : return m_userAttr[subindex]; 1.228 + case gr_slatSegSplit : return seg->charinfo(m_original)->flags() & 3; 1.229 + case gr_slatBidiLevel: return m_bidiLevel; 1.230 + default : return 0; 1.231 + } 1.232 +} 1.233 + 1.234 +void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map) 1.235 +{ 1.236 + if (!this) return; 1.237 + if (ind == gr_slatUserDefnV1) 1.238 + { 1.239 + ind = gr_slatUserDefn; 1.240 + subindex = 0; 1.241 + } 1.242 + else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth) 1.243 + { 1.244 + int indx = ind - gr_slatJStretch; 1.245 + return setJustify(seg, indx / 5, indx % 5, value); 1.246 + } 1.247 + 1.248 + switch (ind) 1.249 + { 1.250 + case gr_slatAdvX : m_advance.x = value; break; 1.251 + case gr_slatAdvY : m_advance.y = value; break; 1.252 + case gr_slatAttTo : 1.253 + { 1.254 + const uint16 idx = uint16(value); 1.255 + if (idx < map.size() && map[idx]) 1.256 + { 1.257 + Slot *other = map[idx]; 1.258 + if (other == this) break; 1.259 + if (m_parent) m_parent->removeChild(this); 1.260 + if (other->child(this)) 1.261 + { 1.262 + attachTo(other); 1.263 + if (((seg->dir() & 1) != 0) ^ (idx > subindex)) 1.264 + m_with = Position(advance(), 0); 1.265 + else // normal match to previous root 1.266 + m_attach = Position(other->advance(), 0); 1.267 + } 1.268 + } 1.269 + break; 1.270 + } 1.271 + case gr_slatAttX : m_attach.x = value; break; 1.272 + case gr_slatAttY : m_attach.y = value; break; 1.273 + case gr_slatAttXOff : 1.274 + case gr_slatAttYOff : break; 1.275 + case gr_slatAttWithX : m_with.x = value; break; 1.276 + case gr_slatAttWithY : m_with.y = value; break; 1.277 + case gr_slatAttWithXOff : 1.278 + case gr_slatAttWithYOff : break; 1.279 + case gr_slatAttLevel : 1.280 + m_attLevel = byte(value); 1.281 + break; 1.282 + case gr_slatBreak : 1.283 + seg->charinfo(m_original)->breakWeight(value); 1.284 + break; 1.285 + case gr_slatCompRef : break; // not sure what to do here 1.286 + case gr_slatDir : m_bidiCls = value; break; 1.287 + case gr_slatInsert : 1.288 + markInsertBefore(value? true : false); 1.289 + break; 1.290 + case gr_slatPosX : break; // can't set these here 1.291 + case gr_slatPosY : break; 1.292 + case gr_slatShiftX : m_shift.x = value; break; 1.293 + case gr_slatShiftY : m_shift.y = value; break; 1.294 + case gr_slatMeasureSol : break; 1.295 + case gr_slatMeasureEol : break; 1.296 + case gr_slatJWidth : just(value); break; 1.297 + case gr_slatSegSplit : seg->charinfo(m_original)->addflags(value & 3); break; 1.298 + case gr_slatUserDefn : m_userAttr[subindex] = value; break; 1.299 + default : 1.300 + break; 1.301 + } 1.302 +} 1.303 + 1.304 +int Slot::getJustify(const Segment *seg, uint8 level, uint8 subindex) const 1.305 +{ 1.306 + if (level && level >= seg->silf()->numJustLevels()) return 0; 1.307 + 1.308 + if (m_justs) 1.309 + return m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex]; 1.310 + 1.311 + if (level >= seg->silf()->numJustLevels()) return 0; 1.312 + Justinfo *jAttrs = seg->silf()->justAttrs() + level; 1.313 + 1.314 + switch (subindex) { 1.315 + case 0 : return seg->glyphAttr(gid(), jAttrs->attrStretch()); 1.316 + case 1 : return seg->glyphAttr(gid(), jAttrs->attrShrink()); 1.317 + case 2 : return seg->glyphAttr(gid(), jAttrs->attrStep()); 1.318 + case 3 : return seg->glyphAttr(gid(), jAttrs->attrWeight()); 1.319 + case 4 : return 0; // not been set yet, so clearly 0 1.320 + default: return 0; 1.321 + } 1.322 +} 1.323 + 1.324 +void Slot::setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value) 1.325 +{ 1.326 + if (level && level >= seg->silf()->numJustLevels()) return; 1.327 + if (!m_justs) 1.328 + { 1.329 + SlotJustify *j = seg->newJustify(); 1.330 + if (!j) return; 1.331 + j->LoadSlot(this, seg); 1.332 + m_justs = j; 1.333 + } 1.334 + m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex] = value; 1.335 +} 1.336 + 1.337 +bool Slot::child(Slot *ap) 1.338 +{ 1.339 + if (this == ap) return false; 1.340 + else if (ap == m_child) return true; 1.341 + else if (!m_child) 1.342 + m_child = ap; 1.343 + else 1.344 + return m_child->sibling(ap); 1.345 + return true; 1.346 +} 1.347 + 1.348 +bool Slot::sibling(Slot *ap) 1.349 +{ 1.350 + if (this == ap) return false; 1.351 + else if (ap == m_sibling) return true; 1.352 + else if (!m_sibling || !ap) 1.353 + m_sibling = ap; 1.354 + else 1.355 + return m_sibling->sibling(ap); 1.356 + return true; 1.357 +} 1.358 + 1.359 +bool Slot::removeChild(Slot *ap) 1.360 +{ 1.361 + if (this == ap || !m_child) return false; 1.362 + else if (ap == m_child) 1.363 + { 1.364 + Slot *nSibling = m_child->nextSibling(); 1.365 + m_child->sibling(NULL); 1.366 + m_child = nSibling; 1.367 + return true; 1.368 + } 1.369 + else 1.370 + return m_child->removeSibling(ap); 1.371 + return true; 1.372 +} 1.373 + 1.374 +bool Slot::removeSibling(Slot *ap) 1.375 +{ 1.376 + if (this == ap || !m_sibling) return false; 1.377 + else if (ap == m_sibling) 1.378 + { 1.379 + m_sibling = m_sibling->nextSibling(); 1.380 + return true; 1.381 + } 1.382 + else 1.383 + return m_sibling->removeSibling(ap); 1.384 + return true; 1.385 +} 1.386 + 1.387 +void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph) 1.388 +{ 1.389 + m_glyphid = glyphid; 1.390 + if (!theGlyph) 1.391 + { 1.392 + theGlyph = seg->getFace()->glyphs().glyphSafe(glyphid); 1.393 + if (!theGlyph) 1.394 + { 1.395 + m_realglyphid = 0; 1.396 + m_advance = Position(0.,0.); 1.397 + return; 1.398 + } 1.399 + } 1.400 + m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()]; 1.401 + const GlyphFace *aGlyph = theGlyph; 1.402 + if (m_realglyphid) 1.403 + { 1.404 + aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid); 1.405 + if (!aGlyph) aGlyph = theGlyph; 1.406 + } 1.407 + m_advance = Position(aGlyph->theAdvance().x, 0.); 1.408 + if (seg->silf()->aPassBits()) 1.409 + seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]); 1.410 +} 1.411 + 1.412 +void Slot::floodShift(Position adj) 1.413 +{ 1.414 + m_position += adj; 1.415 + if (m_child) m_child->floodShift(adj); 1.416 + if (m_sibling) m_sibling->floodShift(adj); 1.417 +} 1.418 + 1.419 +void SlotJustify::LoadSlot(const Slot *s, const Segment *seg) 1.420 +{ 1.421 + for (int i = seg->silf()->numJustLevels() - 1; i >= 0; --i) 1.422 + { 1.423 + Justinfo *justs = seg->silf()->justAttrs() + i; 1.424 + int16 *v = values + i * NUMJUSTPARAMS; 1.425 + v[0] = seg->glyphAttr(s->gid(), justs->attrStretch()); 1.426 + v[1] = seg->glyphAttr(s->gid(), justs->attrShrink()); 1.427 + v[2] = seg->glyphAttr(s->gid(), justs->attrStep()); 1.428 + v[3] = seg->glyphAttr(s->gid(), justs->attrWeight()); 1.429 + } 1.430 +}