예제 #1
0
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);
    }
}
예제 #2
0
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);
}
예제 #3
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;
}
예제 #4
0
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;
}