LCOV - code coverage report
Current view: directory - gfx/graphite2/src - Segment.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 183 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

       1                 : /*  GRAPHITE2 LICENSING
       2                 : 
       3                 :     Copyright 2010, SIL International
       4                 :     All rights reserved.
       5                 : 
       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.
      10                 : 
      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.
      15                 : 
      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.
      21                 : 
      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/UtfCodec.h"
      28                 : #include <cstring>
      29                 : #include <cstdlib>
      30                 : 
      31                 : #include "inc/Segment.h"
      32                 : #include "graphite2/Font.h"
      33                 : #include "inc/CharInfo.h"
      34                 : #include "inc/Slot.h"
      35                 : #include "inc/Main.h"
      36                 : #include "inc/CmapCache.h"
      37                 : #include "graphite2/Segment.h"
      38                 : 
      39                 : 
      40                 : using namespace graphite2;
      41                 : 
      42               0 : Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir) :
      43                 :         m_freeSlots(NULL),
      44                 :         m_first(NULL),
      45                 :         m_last(NULL),
      46                 :         m_numGlyphs(numchars),
      47                 :         m_numCharinfo(numchars),
      48                 :         m_defaultOriginal(0),
      49               0 :         m_charinfo(new CharInfo[numchars]),
      50                 :         m_face(face),
      51               0 :         m_silf(face->chooseSilf(script)),
      52                 :         m_bbox(Rect(Position(0, 0), Position(0, 0))),
      53               0 :         m_dir(textDir)
      54                 : {
      55                 :     unsigned int i, j;
      56               0 :     m_bufSize = numchars + 10;
      57               0 :     freeSlot(newSlot());
      58               0 :     for (i = 0, j = 1; j < numchars; i++, j <<= 1) {}
      59               0 :     if (!i) i = 1;
      60               0 :     m_bufSize = i;                  // log2(numchars)
      61               0 : }
      62                 : 
      63               0 : Segment::~Segment()
      64                 : {
      65               0 :     for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
      66               0 :         free(*i);
      67               0 :     for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j)
      68               0 :         free(*j);
      69               0 :     delete[] m_charinfo;
      70               0 : }
      71                 : 
      72                 : #ifndef GRAPHITE2_NSEGCACHE
      73                 : SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
      74                 : {
      75                 :     SegmentScopeState state;
      76                 :     state.numGlyphsOutsideScope = m_numGlyphs - subLength;
      77                 :     state.realFirstSlot = m_first;
      78                 :     state.slotBeforeScope = firstSlot->prev();
      79                 :     state.slotAfterScope = lastSlot->next();
      80                 :     state.realLastSlot = m_last;
      81                 :     firstSlot->prev(NULL);
      82                 :     lastSlot->next(NULL);
      83                 :     assert(m_defaultOriginal == 0);
      84                 :     m_defaultOriginal = firstSlot->original();
      85                 :     m_numGlyphs = subLength;
      86                 :     m_first = firstSlot;
      87                 :     m_last = lastSlot;
      88                 :     return state;
      89                 : }
      90                 : 
      91                 : void Segment::removeScope(SegmentScopeState & state)
      92                 : {
      93                 :     m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs;
      94                 :     if (state.slotBeforeScope)
      95                 :     {
      96                 :         state.slotBeforeScope->next(m_first);
      97                 :         m_first->prev(state.slotBeforeScope);
      98                 :         m_first = state.realFirstSlot;
      99                 :     }
     100                 :     if (state.slotAfterScope)
     101                 :     {
     102                 :         state.slotAfterScope->prev(m_last);
     103                 :         m_last->next(state.slotAfterScope);
     104                 :         m_last = state.realLastSlot;
     105                 :     }
     106                 :     m_defaultOriginal = 0;
     107                 : }
     108                 : 
     109                 : 
     110                 : void Segment::append(const Segment &other)
     111                 : {
     112                 :     Rect bbox = other.m_bbox + m_advance;
     113                 : 
     114                 :     m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end());
     115                 :     CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo];           //since CharInfo has no constructor, this doesn't do much
     116                 :     for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
     117                 :         pNewCharInfo[i] = m_charinfo[i];
     118                 :     m_last->next(other.m_first);
     119                 :     other.m_last->prev(m_last);
     120                 :     m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end());
     121                 :     
     122                 :     delete[] m_charinfo;
     123                 :     m_charinfo = pNewCharInfo;
     124                 :     pNewCharInfo += m_numCharinfo ;
     125                 :     for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
     126                 :         pNewCharInfo[i] = other.m_charinfo[i];
     127                 :  
     128                 :     m_numCharinfo += other.m_numCharinfo;
     129                 :     m_numGlyphs += other.m_numGlyphs;
     130                 :     m_advance = m_advance + other.m_advance;
     131                 :     m_bbox = m_bbox.widen(bbox);
     132                 : }
     133                 : #endif // GRAPHITE2_NSEGCACHE
     134                 : 
     135               0 : void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
     136                 : {
     137               0 :     Slot *aSlot = newSlot();
     138                 :     
     139               0 :     m_charinfo[id].init(cid);
     140               0 :     m_charinfo[id].feats(iFeats);
     141               0 :     m_charinfo[id].base(coffset);
     142               0 :     const GlyphFace * theGlyph = m_face->getGlyphFaceCache()->glyphSafe(gid);
     143               0 :     if (theGlyph)
     144                 :     {
     145               0 :         m_charinfo[id].breakWeight(theGlyph->getAttr(m_silf->aBreak()));
     146                 :     }
     147                 :     else
     148                 :     {
     149               0 :         m_charinfo[id].breakWeight(0);
     150                 :     }
     151                 :     
     152               0 :     aSlot->child(NULL);
     153               0 :     aSlot->setGlyph(this, gid, theGlyph);
     154               0 :     aSlot->originate(id);
     155               0 :     aSlot->before(id);
     156               0 :     aSlot->after(id);
     157               0 :     if (m_last) m_last->next(aSlot);
     158               0 :     aSlot->prev(m_last);
     159               0 :     m_last = aSlot;
     160               0 :     if (!m_first) m_first = aSlot;
     161               0 : }
     162                 : 
     163               0 : Slot *Segment::newSlot()
     164                 : {
     165               0 :     if (!m_freeSlots)
     166                 :     {
     167               0 :         int numUser = m_silf->numUser();
     168               0 :         Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
     169               0 :         int16 *newAttrs = grzeroalloc<int16>(numUser * m_bufSize);
     170               0 :         newSlots[0].userAttrs(newAttrs);
     171               0 :         for (size_t i = 1; i < m_bufSize - 1; i++)
     172                 :         {
     173               0 :             newSlots[i].next(newSlots + i + 1);
     174               0 :             newSlots[i].userAttrs(newAttrs + i * numUser);
     175                 :         }
     176               0 :         newSlots[m_bufSize - 1].userAttrs(newAttrs + (m_bufSize - 1) * numUser);
     177               0 :         newSlots[m_bufSize - 1].next(NULL);
     178               0 :         m_slots.push_back(newSlots);
     179               0 :         m_userAttrs.push_back(newAttrs);
     180               0 :         m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
     181               0 :         return newSlots;
     182                 :     }
     183               0 :     Slot *res = m_freeSlots;
     184               0 :     m_freeSlots = m_freeSlots->next();
     185               0 :     res->next(NULL);
     186               0 :     return res;
     187                 : }
     188                 : 
     189               0 : void Segment::freeSlot(Slot *aSlot)
     190                 : {
     191               0 :     if (m_last == aSlot) m_last = aSlot->prev();
     192               0 :     if (m_first == aSlot) m_first = aSlot->next();
     193                 :     // reset the slot incase it is reused
     194               0 :     ::new (aSlot) Slot;
     195               0 :     memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
     196                 :     // Update generation counter for debug
     197               0 :     aSlot->index(aSlot->index()+1);
     198                 :     // update next pointer
     199               0 :     if (!m_freeSlots)
     200               0 :         aSlot->next(NULL);
     201                 :     else
     202               0 :         aSlot->next(m_freeSlots);
     203               0 :     m_freeSlots = aSlot;
     204               0 : }
     205                 : 
     206                 : #ifndef GRAPHITE2_NSEGCACHE
     207                 : void Segment::splice(size_t offset, size_t length, Slot * startSlot,
     208                 :                        Slot * endSlot, const Slot * firstSpliceSlot,
     209                 :                        size_t numGlyphs)
     210                 : {
     211                 :     const Slot * replacement = firstSpliceSlot;
     212                 :     Slot * slot = startSlot;
     213                 :     extendLength(numGlyphs - length);
     214                 :     // insert extra slots if needed
     215                 :     while (numGlyphs > length)
     216                 :     {
     217                 :         Slot * extra = newSlot();
     218                 :         extra->prev(endSlot);
     219                 :         extra->next(endSlot->next());
     220                 :         endSlot->next(extra);
     221                 :         if (extra->next())
     222                 :             extra->next()->prev(extra);
     223                 :         if (m_last == endSlot)
     224                 :             m_last = extra;
     225                 :         endSlot = extra;
     226                 :         ++length;
     227                 :     }
     228                 :     // remove any extra
     229                 :     if (numGlyphs < length)
     230                 :     {
     231                 :         Slot * afterSplice = endSlot->next();
     232                 :         do
     233                 :         {
     234                 :             endSlot = endSlot->prev();
     235                 :             freeSlot(endSlot->next());
     236                 :             --length;
     237                 :         } while (numGlyphs < length);
     238                 :         endSlot->next(afterSplice);
     239                 :         if (afterSplice)
     240                 :             afterSplice->prev(endSlot);
     241                 :     }
     242                 :     assert(numGlyphs == length);
     243                 :     // keep a record of consecutive slots wrt start of splice to minimize
     244                 :     // iterative next/prev calls
     245                 :     Slot * slotArray[eMaxSpliceSize];
     246                 :     uint16 slotPosition = 0;
     247                 :     for (uint16 i = 0; i < numGlyphs; i++)
     248                 :     {
     249                 :         if (slotPosition <= i)
     250                 :         {
     251                 :             slotArray[i] = slot;
     252                 :             slotPosition = i;
     253                 :         }
     254                 :         slot->set(*replacement, offset, m_silf->numUser());
     255                 :         if (replacement->attachedTo())
     256                 :         {
     257                 :             uint16 parentPos = replacement->attachedTo() - firstSpliceSlot;
     258                 :             while (slotPosition < parentPos)
     259                 :             {
     260                 :                 slotArray[slotPosition+1] = slotArray[slotPosition]->next();
     261                 :                 ++slotPosition;
     262                 :             }
     263                 :             slot->attachTo(slotArray[parentPos]);
     264                 :         }
     265                 :         if (replacement->nextSibling())
     266                 :         {
     267                 :             uint16 pos = replacement->nextSibling() - firstSpliceSlot;
     268                 :             while (slotPosition < pos)
     269                 :             {
     270                 :                 slotArray[slotPosition+1] = slotArray[slotPosition]->next();
     271                 :                 ++slotPosition;
     272                 :             }
     273                 :             slot->sibling(slotArray[pos]);
     274                 :         }
     275                 :         if (replacement->firstChild())
     276                 :         {
     277                 :             uint16 pos = replacement->firstChild() - firstSpliceSlot;
     278                 :             while (slotPosition < pos)
     279                 :             {
     280                 :                 slotArray[slotPosition+1] = slotArray[slotPosition]->next();
     281                 :                 ++slotPosition;
     282                 :             }
     283                 :             slot->child(slotArray[pos]);
     284                 :         }
     285                 :         slot = slot->next();
     286                 :         replacement = replacement->next();
     287                 :     }
     288                 : }
     289                 : #endif // GRAPHITE2_NSEGCACHE
     290                 : 
     291               0 : void Segment::linkClusters(Slot *s, Slot * end)
     292                 : {
     293               0 :         end = end->next();
     294                 : 
     295               0 :         for (; s != end && !s->isBase(); s = s->next());
     296               0 :         Slot * ls = s;
     297                 : 
     298               0 :         if (m_dir & 1)
     299                 :         {
     300               0 :                 for (; s != end; s = s->next())
     301                 :                 {
     302               0 :                         if (!s->isBase())    continue;
     303                 : 
     304               0 :                         s->sibling(ls);
     305               0 :                         ls = s;
     306                 :                 }
     307                 :         }
     308                 :         else
     309                 :         {
     310               0 :                 for (; s != end; s = s->next())
     311                 :                 {
     312               0 :                         if (!s->isBase())    continue;
     313                 : 
     314               0 :                         ls->sibling(s);
     315               0 :                         ls = s;
     316                 :                 }
     317                 :         }
     318               0 : }
     319                 : 
     320               0 : Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd)
     321                 : {
     322               0 :     Position currpos(0., 0.);
     323               0 :     Rect bbox;
     324               0 :     float cMin = 0.;
     325               0 :     float clusterMin = 0.;
     326                 : 
     327               0 :     if (!iStart)        iStart = m_first;
     328               0 :     if (!iEnd)          iEnd   = m_last;
     329                 : 
     330               0 :     if (m_dir & 1)
     331                 :     {
     332               0 :         for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
     333                 :         {
     334               0 :             if (s->isBase())
     335               0 :                 currpos = s->finalise(this, font, currpos, bbox, cMin, 0, clusterMin = currpos.x);
     336                 :         }
     337                 :     }
     338                 :     else
     339                 :     {
     340               0 :         for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
     341                 :         {
     342               0 :             if (s->isBase())
     343               0 :                 currpos = s->finalise(this, font, currpos, bbox, cMin, 0, clusterMin = currpos.x);
     344                 :         }
     345                 :     }
     346                 :     return currpos;
     347                 : }
     348                 : 
     349                 : 
     350                 : template <typename utf_iter>
     351               0 : inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
     352                 : {
     353               0 :         const Cmap    & cmap = face.cmap();
     354               0 :         int slotid = 0;
     355                 : 
     356               0 :         const typename utf_iter::codeunit_type * const base = c;
     357               0 :         for (; n_chars; --n_chars, ++c, ++slotid)
     358                 :         {
     359               0 :                 const uint32 usv = *c;
     360               0 :                 uint16 gid = cmap[usv];
     361               0 :                 if (!gid)       gid = face.findPseudo(usv);
     362               0 :                 seg.appendSlot(slotid, usv, gid, fid, c - base);
     363                 :         }
     364               0 : }
     365                 : 
     366                 : 
     367               0 : void Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars)
     368                 : {
     369               0 :         assert(face);
     370               0 :         assert(pFeats);
     371                 : 
     372               0 :         switch (enc)
     373                 :         {
     374               0 :         case gr_utf8:   process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
     375               0 :         case gr_utf16:  process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
     376               0 :         case gr_utf32:  process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
     377                 :         }
     378               0 : }
     379                 : 
     380               0 : void Segment::prepare_pos(const Font * /*font*/)
     381                 : {
     382                 :     // copy key changeable metrics into slot (if any);
     383               0 : }
     384                 : 
     385               0 : void Segment::finalise(const Font *font)
     386                 : {
     387               0 :         if (!m_first) return;
     388                 : 
     389               0 :     m_advance = positionSlots(font);
     390               0 :     int i = 0;
     391               0 :     for (Slot * s = m_first; s; s->index(i++), s = s->next())
     392                 :     {
     393               0 :         int j = s->before();
     394               0 :         if (j < 0)   continue;
     395                 : 
     396               0 :         for (const int after = s->after(); j <= after; ++j)
     397                 :                 {
     398               0 :                         CharInfo & c = *charinfo(j);
     399               0 :                         if (c.before() == -1 || i < c.before())      c.before(i);
     400               0 :                         if (c.after() < i)                                                   c.after(i);
     401                 :                 }
     402                 :     }
     403               0 :     linkClusters(m_first, m_last);
     404                 : }
     405                 : 
     406               0 : void Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags flags, Slot *pFirst, Slot *pLast)
     407                 : {
     408               0 :     Slot *pEnd = pSlot;
     409                 :     Slot *s, *end;
     410               0 :     int numBase = 0;
     411               0 :     float currWidth = 0.;
     412               0 :     float scale = font ? font->scale() : 1.0;
     413                 :     float base;
     414                 : 
     415               0 :     if (!pFirst) pFirst = pSlot;
     416               0 :     base = pFirst->origin().x / scale;
     417               0 :     width = width / scale;
     418               0 :     end = pLast ? pLast->next() : NULL;
     419                 : 
     420               0 :     for (s = pFirst; s != end; s=s->next())
     421                 :     {
     422               0 :         float w = s->origin().x / scale + s->advance() - base;
     423               0 :         if (w > currWidth) currWidth = w;
     424               0 :         pEnd = s;
     425               0 :         if (!s->attachedTo())       // what about trailing whitespace?
     426               0 :             numBase++;
     427                 :     }
     428               0 :     if (pLast)
     429               0 :         while (s)
     430                 :         {
     431               0 :             pEnd = s;
     432               0 :             s = s->next();
     433                 :         }
     434                 :     else
     435               0 :         pLast = pEnd;
     436                 :         
     437               0 :     if (!numBase) return;
     438                 : 
     439               0 :     Slot *oldFirst = m_first;
     440               0 :     Slot *oldLast = m_last;
     441                 :     // add line end contextuals to linked list
     442               0 :     m_first = pSlot;
     443               0 :     m_last = pEnd;
     444                 :     // process the various silf justification stuff returning updated currwidth
     445                 : 
     446                 :     // now fallback to spreading the remaining space among all the bases
     447               0 :     float nShift = (width - currWidth) / (numBase - 1);
     448               0 :     for (s = pFirst->nextSibling(); s != end; s = s->nextSibling())
     449               0 :         s->just(nShift + s->just());
     450               0 :     positionSlots(font, pSlot, pEnd);
     451                 : 
     452               0 :     m_first = oldFirst;
     453               0 :     m_last = oldLast;
     454                 :     // dump line end contextual markers
     455                 : }
     456                 : 
     457                 : Slot *resolveExplicit(int level, int dir, Slot *s, int nNest = 0);
     458                 : void resolveWeak(int baseLevel, Slot *s);
     459                 : void resolveNeutrals(int baseLevel, Slot *s);
     460                 : void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
     461                 : void resolveWhitespace(int baseLevel, Segment *seg, uint8 aBidi, Slot *s);
     462                 : Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
     463                 : 
     464               0 : void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
     465                 : {
     466               0 :         if (slotCount() == 0)
     467               0 :                 return;
     468                 : 
     469                 :     Slot *s;
     470               0 :     int baseLevel = paradir ? 1 : 0;
     471               0 :     unsigned int bmask = 0;
     472               0 :     for (s = first(); s; s = s->next())
     473                 :     {
     474               0 :         unsigned int bAttr = glyphAttr(s->gid(), aBidi);
     475               0 :         s->setBidiClass((bAttr <= 16) * bAttr);
     476               0 :         bmask |= (1 << s->getBidiClass());
     477               0 :         s->setBidiLevel(baseLevel);
     478                 :     }
     479               0 :     if (bmask & (paradir ? 0x92 : 0x9C))
     480                 :     {
     481               0 :         if (bmask & 0xF800)
     482               0 :             resolveExplicit(baseLevel, 0, first(), 0);
     483               0 :         if (bmask & 0x10178)
     484               0 :             resolveWeak(baseLevel, first());
     485               0 :         if (bmask & 0x161)
     486               0 :             resolveNeutrals(baseLevel, first());
     487               0 :         resolveImplicit(first(), this, aMirror);
     488               0 :         resolveWhitespace(baseLevel, this, aBidi, last());
     489               0 :         s = resolveOrder(s = first(), baseLevel);
     490               0 :         first(s); last(s->prev());
     491               0 :         s->prev()->next(0); s->prev(0);
     492                 :     }
     493               0 :     else if (!(dir() & 4) && baseLevel && aMirror)
     494                 :     {
     495               0 :         for (s = first(); s; s = s->next())
     496                 :         {
     497               0 :             unsigned short g = glyphAttr(s->gid(), aMirror);
     498               0 :             if (g) s->setGlyph(this, g);
     499                 :         }
     500                 :     }
     501                 : }
     502                 : 

Generated by: LCOV version 1.7