void Segment::doMirror(uint16 aMirror) { Slot * s; for (s = m_first; s; s = s->next()) { unsigned short g = glyphAttr(s->gid(), aMirror); if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1))) s->setGlyph(this, g); } }
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); }
bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass) const { assert(seg != 0); SlotMap map(*seg); FiniteStateMachine fsm(map, seg->getFace()->logger()); vm::Machine m(map); unsigned int initSize = seg->slotCount(); #if !defined GRAPHITE2_NTRACING json * const dbgout = seg->getFace()->logger(); #endif if (lastPass == 0) { if (firstPass == lastPass) return true; lastPass = m_numPasses; } for (size_t i = firstPass; i < lastPass; ++i) { // bidi and mirroring if (i == m_bPass) { #if !defined GRAPHITE2_NTRACING if (dbgout) { *dbgout << json::item << json::object << "id" << -1 << "slots" << json::array; seg->positionSlots(0); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close << "rules" << json::array << json::close << json::close; } #endif if (!(seg->dir() & 2)) seg->bidiPass(m_aBidi, seg->dir() & 1, m_aMirror); else if (m_aMirror) { Slot * s; for (s = seg->first(); s; s = s->next()) { unsigned short g = seg->glyphAttr(s->gid(), m_aMirror); if (g && (!(seg->dir() & 4) || !seg->glyphAttr(s->gid(), m_aMirror + 1))) s->setGlyph(seg, g); } } } #if !defined GRAPHITE2_NTRACING if (dbgout) { *dbgout << json::item << json::object << "id" << i+1 << "slots" << json::array; seg->positionSlots(0); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close; } #endif // test whether to reorder, prepare for positioning m_passes[i].runGraphite(m, fsm); // only subsitution passes can change segment length, cached subsegments are short for their text if (m.status() != vm::Machine::finished || (i < m_pPass && (seg->slotCount() > initSize * MAX_SEG_GROWTH_FACTOR || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize)))) return false; } return true; }
bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass) const { assert(seg != 0); SlotMap map(*seg); FiniteStateMachine fsm(map); vm::Machine m(map); unsigned int initSize = seg->slotCount(); if (lastPass == 0) { if (firstPass == lastPass) return true; lastPass = m_numPasses; } #if !defined GRAPHITE2_NTRACING if (dbgout) { char version[64]; sprintf(version, "%d.%d.%d", GR2_VERSION_MAJOR, GR2_VERSION_MINOR, GR2_VERSION_BUGFIX); *dbgout << json::object << "version" << version << "passes" << json::array; } #endif for (size_t i = firstPass; i < lastPass; ++i) { // bidi and mirroring if (i == m_bPass) { #if !defined GRAPHITE2_NTRACING if (dbgout) { *dbgout << json::item << json::object << "id" << -1 << "slots" << json::array; seg->positionSlots(0); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close << "rules" << json::array << json::close << json::close; } #endif if (!(seg->dir() & 2)) seg->bidiPass(m_aBidi, seg->dir() & 1, m_aMirror); else if (m_aMirror) { Slot * s; for (s = seg->first(); s; s = s->next()) { unsigned short g = seg->glyphAttr(s->gid(), m_aMirror); if (g && (!(seg->dir() & 4) || !seg->glyphAttr(s->gid(), m_aMirror + 1))) s->setGlyph(seg, g); } } } #if !defined GRAPHITE2_NTRACING if (dbgout) { *dbgout << json::item << json::object << "id" << i+1 << "slots" << json::array; seg->positionSlots(0); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close; } #endif // test whether to reorder, prepare for positioning m_passes[i].runGraphite(m, fsm); // only subsitution passes can change segment length, cached subsegments are short for their text if (m.status() != vm::Machine::finished || (i < m_pPass && (seg->slotCount() > initSize * MAX_SEG_GROWTH_FACTOR || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize)))) return false; } #if !defined GRAPHITE2_NTRACING if (dbgout) { *dbgout << json::item << json::close // Close up the passes array << "output" << json::array; for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); seg->finalise(0); // Call this here to fix up charinfo back indexes. *dbgout << json::close << "advance" << seg->advance() << "chars" << json::array; for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i) *dbgout << json::flat << *seg->charinfo(i); *dbgout << json::close // Close up the chars array << json::close; // Clsoe up the segment object } #endif return true; }