inline Slot * input_slot(const SlotMap & slots, const int n) { Slot * s = slots[slots.context() + n]; if (!s->isCopied()) return s; return s->prev() ? s->prev()->next() : (s->next() ? s->next()->prev() : slots.segment.last()); }
void Segment::splice(size_t offset, size_t length, Slot * const startSlot, Slot * endSlot, const Slot * srcSlot, const size_t numGlyphs) { size_t numChars = length; extendLength(numGlyphs - length); // remove any extra if (numGlyphs < length) { Slot * end = endSlot->next(); do { endSlot = endSlot->prev(); freeSlot(endSlot->next()); } while (numGlyphs < --length); endSlot->next(end); if (end) end->prev(endSlot); } else { // insert extra slots if needed while (numGlyphs > length) { Slot * extra = newSlot(); if (!extra) return; extra->prev(endSlot); extra->next(endSlot->next()); endSlot->next(extra); if (extra->next()) extra->next()->prev(extra); if (m_last == endSlot) m_last = extra; endSlot = extra; ++length; } } endSlot = endSlot->next(); assert(numGlyphs == length); assert(offset + numChars <= m_numCharinfo); Slot * indexmap[eMaxSpliceSize*3]; assert(numGlyphs < sizeof indexmap/sizeof *indexmap); Slot * slot = startSlot; for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i) indexmap[i] = slot; for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next()) { slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars); if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]); if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()]; if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()]; } }
SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime) : m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL), m_attr(NULL), m_justs(NULL), m_accessCount(0), m_lastAccess(cacheTime) { if (m_unicode) for (uint16 i = 0; i < length; i++) m_unicode[i] = cmapGlyphs[i]; const size_t glyphCount = seg->slotCount(), sizeof_sjust = SlotJustify::size_of(seg->silf()->numJustLevels()); if (!glyphCount) return; size_t num_justs = 0, justs_pos = 0; if (seg->hasJustification()) { for (const Slot * s = seg->first(); s; s = s->next()) { if (s->m_justs == 0) continue; ++num_justs; } m_justs = gralloc<byte>(sizeof_sjust * num_justs); } const Slot * slot = seg->first(); m_glyph = new Slot[glyphCount]; m_attr = gralloc<int16>(glyphCount * seg->numAttrs()); if (!m_glyph || (!m_attr && seg->numAttrs())) return; m_glyphLength = glyphCount; Slot * slotCopy = m_glyph; m_glyph->prev(NULL); uint16 pos = 0; while (slot) { slotCopy->userAttrs(m_attr + pos * seg->numAttrs()); slotCopy->m_justs = m_justs ? reinterpret_cast<SlotJustify *>(m_justs + justs_pos++ * sizeof_sjust) : 0; slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs(), seg->silf()->numJustLevels(), length); slotCopy->index(pos); if (slot->firstChild()) slotCopy->m_child = m_glyph + slot->firstChild()->index(); if (slot->attachedTo()) slotCopy->attachTo(m_glyph + slot->attachedTo()->index()); if (slot->nextSibling()) slotCopy->m_sibling = m_glyph + slot->nextSibling()->index(); slot = slot->next(); ++slotCopy; ++pos; if (slot) { slotCopy->prev(slotCopy-1); (slotCopy-1)->next(slotCopy); } } }
// reverse the slots but keep diacritics in their same position after their bases void Segment::reverseSlots() { m_dir = m_dir ^ 64; // invert the reverse flag if (m_first == m_last) return; // skip 0 or 1 glyph runs Slot *t = 0; Slot *curr = m_first; Slot *tlast; Slot *tfirst; Slot *out = 0; while (curr && getSlotBidiClass(curr) == 16) curr = curr->next(); if (!curr) return; tfirst = curr->prev(); tlast = curr; while (curr) { if (getSlotBidiClass(curr) == 16) { Slot *d = curr->next(); while (d && getSlotBidiClass(d) == 16) d = d->next(); d = d ? d->prev() : m_last; Slot *p = out->next(); // one after the diacritics. out can't be null if (p) p->prev(d); else tlast = d; t = d->next(); d->next(p); curr->prev(out); out->next(curr); } else // will always fire first time round the loop { if (out) out->prev(curr); t = curr->next(); curr->next(out); out = curr; } curr = t; } out->prev(tfirst); if (tfirst) tfirst->next(out); else m_first = out; m_last = tlast; }
void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset) { Slot *aSlot = newSlot(); if (!aSlot) return; m_charinfo[id].init(cid); m_charinfo[id].feats(iFeats); m_charinfo[id].base(coffset); const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid); m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0); aSlot->child(NULL); aSlot->setGlyph(this, gid, theGlyph); aSlot->originate(id); aSlot->before(id); aSlot->after(id); if (m_last) m_last->next(aSlot); aSlot->prev(m_last); m_last = aSlot; if (!m_first) m_first = aSlot; if (theGlyph && m_silf->aPassBits()) m_passBits &= theGlyph->attrs()[m_silf->aPassBits()] | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0); }
SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime) : m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL), m_attr(NULL), m_accessCount(0), m_lastAccess(cacheTime) { for (uint16 i = 0; i < length; i++) { m_unicode[i] = cmapGlyphs[i]; } size_t glyphCount = seg->slotCount(); const Slot * slot = seg->first(); m_glyph = new Slot[glyphCount]; m_attr = gralloc<uint16>(glyphCount * seg->numAttrs()); m_glyphLength = glyphCount; Slot * slotCopy = m_glyph; m_glyph->prev(NULL); struct Index2Slot { Index2Slot(uint16 i, const Slot * s) : m_i(i), m_slot(s) {}; Index2Slot() : m_i(0), m_slot(NULL) {}; uint16 m_i; const Slot * m_slot; }; struct Index2Slot parentGlyphs[eMaxSpliceSize]; struct Index2Slot childGlyphs[eMaxSpliceSize]; uint16 numParents = 0; uint16 numChildren = 0; uint16 pos = 0; while (slot) { slotCopy->userAttrs(m_attr + pos * seg->numAttrs()); slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs()); if (slot->firstChild()) { new(parentGlyphs + numParents) Index2Slot( pos, slot ); ++numParents; } if (slot->attachedTo()) { new(childGlyphs + numChildren) Index2Slot( pos, slot ); ++numChildren; } slot = slot->next(); ++slotCopy; ++pos; if (slot) { slotCopy->prev(slotCopy-1); (slotCopy-1)->next(slotCopy); } } // loop over the attached children finding their siblings and parents for (int16 i = 0; i < numChildren; i++) { if (childGlyphs[i].m_slot->nextSibling()) { for (int16 j = i; j < numChildren; j++) { if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i); break; } } if (!m_glyph[childGlyphs[i].m_i].nextSibling()) { // search backwards for (int16 j = i-1; j >= 0; j--) { if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i); break; } } } } // now find the parent glyph for (int16 j = 0; j < numParents; j++) { if (childGlyphs[i].m_slot->attachedTo() == parentGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].attachTo(m_glyph + parentGlyphs[j].m_i); if (parentGlyphs[j].m_slot->firstChild() == childGlyphs[i].m_slot) { m_glyph[parentGlyphs[j].m_i].child(m_glyph + childGlyphs[i].m_i); } } } } }
void SetDeferredRunClass(Slot *s, Slot *sRun, int nval) { if (!sRun || s == sRun) return; for (Slot *p = s->prev(); p != sRun; p = p->prev()) p->setBidiClass(nval); }