gfx/graphite2/src/Slot.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*  GRAPHITE2 LICENSING
     3     Copyright 2010, SIL International
     4     All rights reserved.
     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.
    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.
    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.
    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 #include "inc/Segment.h"
    28 #include "inc/Slot.h"
    29 #include "inc/Silf.h"
    30 #include "inc/CharInfo.h"
    31 #include "inc/Rule.h"
    34 using namespace graphite2;
    36 Slot::Slot() :
    37     m_next(NULL), m_prev(NULL),
    38     m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0),
    39     m_index(0), m_parent(NULL), m_child(NULL), m_sibling(NULL),
    40     m_position(0, 0), m_shift(0, 0), m_advance(0, 0),
    41     m_attach(0, 0), m_with(0, 0), m_just(0.),
    42     m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), m_justs(NULL)
    43     // Do not set m_userAttr since it is set *before* new is called since this
    44     // is used as a positional new to reset the GrSlot
    45 {
    46 }
    48 // take care, this does not copy any of the GrSlot pointer fields
    49 void Slot::set(const Slot & orig, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars)
    50 {
    51     // leave m_next and m_prev unchanged
    52     m_glyphid = orig.m_glyphid;
    53     m_realglyphid = orig.m_realglyphid;
    54     m_original = orig.m_original + charOffset;
    55     if (charOffset + int(orig.m_before) < 0)
    56         m_before = 0;
    57     else
    58         m_before = orig.m_before + charOffset;
    59     if (charOffset <= 0 && orig.m_after + charOffset >= numChars)
    60         m_after = numChars - 1;
    61     else
    62         m_after = orig.m_after + charOffset;
    63     m_parent = NULL;
    64     m_child = NULL;
    65     m_sibling = NULL;
    66     m_position = orig.m_position;
    67     m_shift = orig.m_shift;
    68     m_advance = orig.m_advance;
    69     m_attach = orig.m_attach;
    70     m_with = orig.m_with;
    71     m_flags = orig.m_flags;
    72     m_attLevel = orig.m_attLevel;
    73     m_bidiCls = orig.m_bidiCls;
    74     m_bidiLevel = orig.m_bidiLevel;
    75     if (m_userAttr && orig.m_userAttr)
    76         memcpy(m_userAttr, orig.m_userAttr, numUserAttr * sizeof(*m_userAttr));
    77     if (m_justs && orig.m_justs)
    78         memcpy(m_justs, orig.m_justs, SlotJustify::size_of(justLevels));
    79 }
    81 void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
    82 {
    83     m_before += numCharInfo;
    84     m_after += numCharInfo;
    85     m_position = m_position + relpos;
    86 }
    88 Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin)
    89 {
    90     if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
    91     float scale = 1.0;
    92     Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y);
    93     float tAdvance = m_advance.x + m_just;
    94     const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph());
    95     if (font)
    96     {
    97         scale = font->scale();
    98         shift *= scale;
    99         if (font->isHinted() && glyphFace)
   100             tAdvance = (m_advance.x - glyphFace->theAdvance().x + m_just) * scale + font->advance(m_glyphid);
   101         else
   102             tAdvance *= scale;
   103     }    
   104     Position res;
   106     m_position = base + shift;
   107     if (!m_parent)
   108     {
   109         res = base + Position(tAdvance, m_advance.y * scale);
   110         clusterMin = base.x;
   111     }
   112     else
   113     {
   114         float tAdv;
   115         m_position += (m_attach - m_with) * scale;
   116         tAdv = m_advance.x >= 0.5 ? m_position.x + tAdvance - shift.x : 0.f;
   117         res = Position(tAdv, 0);
   118         if ((m_advance.x >= 0.5 || m_position.x < 0) && m_position.x < clusterMin) clusterMin = m_position.x;
   119     }
   121     if (glyphFace)
   122     {
   123         Rect ourBbox = glyphFace->theBBox() * scale + m_position;
   124         bbox = bbox.widen(ourBbox);
   125     }
   127     if (m_child && m_child != this && m_child->attachedTo() == this)
   128     {
   129         Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin);
   130         if ((!m_parent || m_advance.x >= 0.5) && tRes.x > res.x) res = tRes;
   131     }
   133     if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
   134     {
   135         Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin);
   136         if (tRes.x > res.x) res = tRes;
   137     }
   139     if (!m_parent && clusterMin < base.x)
   140     {
   141         Position adj = Position(base.x - clusterMin, 0.);
   142         res += adj;
   143         m_position += adj;
   144         if (m_child) m_child->floodShift(adj);
   145     }
   146     return res;
   147 }
   149 int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
   150 {
   151     Position base;
   152     Rect bbox = seg->theGlyphBBoxTemporary(glyph());
   153     float clusterMin = 0.;
   154     Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin);
   156     switch (metrics(metric))
   157     {
   158     case kgmetLsb :
   159         return static_cast<uint32>(bbox.bl.x);
   160     case kgmetRsb :
   161         return static_cast<uint32>(res.x - bbox.tr.x);
   162     case kgmetBbTop :
   163         return static_cast<uint32>(bbox.tr.y);
   164     case kgmetBbBottom :
   165         return static_cast<uint32>(bbox.bl.y);
   166     case kgmetBbLeft :
   167         return static_cast<uint32>(bbox.bl.x);
   168     case kgmetBbRight :
   169         return static_cast<uint32>(bbox.tr.x);
   170     case kgmetBbWidth :
   171         return static_cast<uint32>(bbox.tr.x - bbox.bl.x);
   172     case kgmetBbHeight :
   173         return static_cast<uint32>(bbox.tr.y - bbox.bl.y);
   174     case kgmetAdvWidth :
   175         return static_cast<uint32>(res.x);
   176     case kgmetAdvHeight :
   177         return static_cast<uint32>(res.y);
   178     default :
   179         return 0;
   180     }
   181 }
   183 int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
   184 {
   185     if (!this) return 0;
   186     if (ind == gr_slatUserDefnV1)
   187     {
   188         ind = gr_slatUserDefn;
   189         subindex = 0;
   190     }
   191     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
   192     {
   193         int indx = ind - gr_slatJStretch;
   194         return getJustify(seg, indx / 5, indx % 5);
   195     }
   197     switch (ind)
   198     {
   199     case gr_slatAdvX :      return int(m_advance.x);
   200     case gr_slatAdvY :      return int(m_advance.y);
   201     case gr_slatAttTo :     return m_parent ? 1 : 0;
   202     case gr_slatAttX :      return int(m_attach.x);
   203     case gr_slatAttY :      return int(m_attach.y);
   204     case gr_slatAttXOff :
   205     case gr_slatAttYOff :   return 0;
   206     case gr_slatAttWithX :  return int(m_with.x);
   207     case gr_slatAttWithY :  return int(m_with.y);
   208     case gr_slatAttWithXOff:
   209     case gr_slatAttWithYOff:return 0;
   210     case gr_slatAttLevel :  return m_attLevel;
   211     case gr_slatBreak :     return seg->charinfo(m_original)->breakWeight();
   212     case gr_slatCompRef :   return 0;
   213     case gr_slatDir :       if (m_bidiCls == -1)
   214                                 const_cast<Slot *>(this)->setBidiClass(seg->glyphAttr(gid(), seg->silf()->aBidi()));
   215                             return m_bidiCls;
   216     case gr_slatInsert :    return isInsertBefore();
   217     case gr_slatPosX :      return int(m_position.x); // but need to calculate it
   218     case gr_slatPosY :      return int(m_position.y);
   219     case gr_slatShiftX :    return int(m_shift.x);
   220     case gr_slatShiftY :    return int(m_shift.y);
   221     case gr_slatMeasureSol: return -1; // err what's this?
   222     case gr_slatMeasureEol: return -1;
   223     case gr_slatJWidth:     return int(m_just);
   224     case gr_slatUserDefn :  return m_userAttr[subindex];
   225     case gr_slatSegSplit :  return seg->charinfo(m_original)->flags() & 3;
   226     case gr_slatBidiLevel:  return m_bidiLevel;
   227     default :               return 0;
   228     }
   229 }
   231 void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
   232 {
   233     if (!this) return;
   234     if (ind == gr_slatUserDefnV1)
   235     {
   236         ind = gr_slatUserDefn;
   237         subindex = 0;
   238     }
   239     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
   240     {
   241         int indx = ind - gr_slatJStretch;
   242         return setJustify(seg, indx / 5, indx % 5, value);
   243     }
   245     switch (ind)
   246     {
   247     case gr_slatAdvX :  m_advance.x = value; break;
   248     case gr_slatAdvY :  m_advance.y = value; break;
   249     case gr_slatAttTo :
   250     {
   251         const uint16 idx = uint16(value);
   252         if (idx < map.size() && map[idx])
   253         {
   254             Slot *other = map[idx];
   255             if (other == this) break;
   256             if (m_parent) m_parent->removeChild(this);
   257             if (other->child(this))
   258             {
   259                 attachTo(other);
   260                 if (((seg->dir() & 1) != 0) ^ (idx > subindex))
   261                     m_with = Position(advance(), 0);
   262                 else        // normal match to previous root
   263                     m_attach = Position(other->advance(), 0);
   264             }
   265         }
   266         break;
   267     }
   268     case gr_slatAttX :          m_attach.x = value; break;
   269     case gr_slatAttY :          m_attach.y = value; break;
   270     case gr_slatAttXOff :
   271     case gr_slatAttYOff :       break;
   272     case gr_slatAttWithX :      m_with.x = value; break;
   273     case gr_slatAttWithY :      m_with.y = value; break;
   274     case gr_slatAttWithXOff :
   275     case gr_slatAttWithYOff :   break;
   276     case gr_slatAttLevel :
   277         m_attLevel = byte(value);
   278         break;
   279     case gr_slatBreak :
   280         seg->charinfo(m_original)->breakWeight(value);
   281         break;
   282     case gr_slatCompRef :   break;      // not sure what to do here
   283     case gr_slatDir :       m_bidiCls = value; break;
   284     case gr_slatInsert :
   285         markInsertBefore(value? true : false);
   286         break;
   287     case gr_slatPosX :      break; // can't set these here
   288     case gr_slatPosY :      break;
   289     case gr_slatShiftX :    m_shift.x = value; break;
   290     case gr_slatShiftY :    m_shift.y = value; break;
   291     case gr_slatMeasureSol :    break;
   292     case gr_slatMeasureEol :    break;
   293     case gr_slatJWidth :    just(value); break;
   294     case gr_slatSegSplit :  seg->charinfo(m_original)->addflags(value & 3); break;
   295     case gr_slatUserDefn :  m_userAttr[subindex] = value; break;
   296     default :
   297         break;
   298     }
   299 }
   301 int Slot::getJustify(const Segment *seg, uint8 level, uint8 subindex) const
   302 {
   303     if (level && level >= seg->silf()->numJustLevels()) return 0;
   305     if (m_justs)
   306         return m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex];
   308     if (level >= seg->silf()->numJustLevels()) return 0;
   309     Justinfo *jAttrs = seg->silf()->justAttrs() + level;
   311     switch (subindex) {
   312         case 0 : return seg->glyphAttr(gid(), jAttrs->attrStretch());
   313         case 1 : return seg->glyphAttr(gid(), jAttrs->attrShrink());
   314         case 2 : return seg->glyphAttr(gid(), jAttrs->attrStep());
   315         case 3 : return seg->glyphAttr(gid(), jAttrs->attrWeight());
   316         case 4 : return 0;      // not been set yet, so clearly 0
   317         default: return 0;
   318     }
   319 }
   321 void Slot::setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value)
   322 {
   323     if (level && level >= seg->silf()->numJustLevels()) return;
   324     if (!m_justs)
   325     {
   326         SlotJustify *j = seg->newJustify();
   327         if (!j) return;
   328         j->LoadSlot(this, seg);
   329         m_justs = j;
   330     }
   331     m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex] = value;
   332 }
   334 bool Slot::child(Slot *ap)
   335 {
   336     if (this == ap) return false;
   337     else if (ap == m_child) return true;
   338     else if (!m_child)
   339         m_child = ap;
   340     else
   341         return m_child->sibling(ap);
   342     return true;
   343 }
   345 bool Slot::sibling(Slot *ap)
   346 {
   347     if (this == ap) return false;
   348     else if (ap == m_sibling) return true;
   349     else if (!m_sibling || !ap)
   350         m_sibling = ap;
   351     else
   352         return m_sibling->sibling(ap);
   353     return true;
   354 }
   356 bool Slot::removeChild(Slot *ap)
   357 {
   358     if (this == ap || !m_child) return false;
   359     else if (ap == m_child)
   360     {
   361         Slot *nSibling = m_child->nextSibling();
   362         m_child->sibling(NULL);
   363         m_child = nSibling;
   364         return true;
   365     }
   366     else
   367         return m_child->removeSibling(ap);
   368     return true;
   369 }
   371 bool Slot::removeSibling(Slot *ap)
   372 {
   373     if (this == ap || !m_sibling) return false;
   374     else if (ap == m_sibling)
   375     {
   376         m_sibling = m_sibling->nextSibling();
   377         return true;
   378     }
   379     else
   380         return m_sibling->removeSibling(ap);
   381     return true;
   382 }
   384 void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
   385 {
   386     m_glyphid = glyphid;
   387     if (!theGlyph)
   388     {
   389         theGlyph = seg->getFace()->glyphs().glyphSafe(glyphid);
   390         if (!theGlyph)
   391         {
   392             m_realglyphid = 0;
   393             m_advance = Position(0.,0.);
   394             return;
   395         }
   396     }
   397     m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()];
   398     const GlyphFace *aGlyph = theGlyph;
   399     if (m_realglyphid)
   400     {
   401         aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid);
   402         if (!aGlyph) aGlyph = theGlyph;
   403     }
   404     m_advance = Position(aGlyph->theAdvance().x, 0.);
   405     if (seg->silf()->aPassBits())
   406         seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
   407 }
   409 void Slot::floodShift(Position adj)
   410 {
   411     m_position += adj;
   412     if (m_child) m_child->floodShift(adj);
   413     if (m_sibling) m_sibling->floodShift(adj);
   414 }
   416 void SlotJustify::LoadSlot(const Slot *s, const Segment *seg)
   417 {
   418     for (int i = seg->silf()->numJustLevels() - 1; i >= 0; --i)
   419     {
   420         Justinfo *justs = seg->silf()->justAttrs() + i;
   421         int16 *v = values + i * NUMJUSTPARAMS;
   422         v[0] = seg->glyphAttr(s->gid(), justs->attrStretch());
   423         v[1] = seg->glyphAttr(s->gid(), justs->attrShrink());
   424         v[2] = seg->glyphAttr(s->gid(), justs->attrStep());
   425         v[3] = seg->glyphAttr(s->gid(), justs->attrWeight());
   426     }
   427 }

mercurial