void PaintCharacterSys(Painter& sw, double x, double y, int ch, Font fnt) { DrawLock __; PAINTER_TIMING("CharacterOp"); FT_Face face = FTFace(fnt, NULL); int glyph_index = FT_Get_Char_Index(face, ch); if(glyph_index && FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) RenderOutline(face->glyph->outline, sw, x, y + fnt.GetAscent()); sw.EvenOdd(true); }
void BufferPainter::ApproximateChar(LinearPathConsumer& t, const CharData& ch, double tolerance) { PAINTER_TIMING("ApproximateChar"); Value v; INTERLOCKED { PAINTER_TIMING("ApproximateChar::Fetch"); static LRUCache<Value, GlyphKey> cache; cache.Shrink(500000); sMakeGlyph h; h.gk.fnt = ch.fnt; h.gk.chr = ch.ch; h.gk.tolerance = tolerance; v = cache.Get(h); } #if 0 GlyphPainter chp; chp.move = chp.pos = Null; chp.tolerance = tolerance; PaintCharacter(chp, ch.p, ch.ch, ch.fnt); Vector<float>& g = chp.glyph; #else const Vector<float>& g = ValueTo< Vector<float> >(v); #endif int i = 0; while(i < g.GetCount()) { Pointf p; p.x = g[i++]; if(p.x > 1e30) { p.x = g[i++]; p.y = g[i++]; t.Move(p + ch.p); } else { PAINTER_TIMING("ApproximateChar::Line"); p.y = g[i++]; t.Line(p + ch.p); } } }
void Painter::CharacterOp(double x, double y, int ch, Font fnt) { PAINTER_TIMING("CharacterOp"); String s; INTERLOCKED { static LRUCache<String, FontChar> cache; cache.Shrink(100000); sMakeCharOutline h; h.fc.fnt = fnt; h.fc.chr = ch; s = cache.Get(h); } RenderCharPath(s, s.GetLength(), *this, x, y + fnt.Info().GetAscent()); EvenOdd(true); }
NAMESPACE_UPP static void sQuadratic(LinearPathConsumer& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, double qt, int lvl) { if(lvl < 16) { PAINTER_TIMING("Quadratic approximation"); Pointf d = p3 - p1; double q = Squared(d); if(q > 1e-30) { Pointf pd = p2 - p1; double u = (pd.x * d.x + pd.y * d.y) / q; if(u <= 0 || u >= 1 || SquaredDistance(u * d, pd) > qt) { Pointf p12 = Mid(p1, p2); Pointf p23 = Mid(p2, p3); Pointf div = Mid(p12, p23); sQuadratic(t, p1, p12, div, qt, lvl + 1); sQuadratic(t, div, p23, p3, qt, lvl + 1); return; } } } t.Line(p3); }