1 #include "Painter.h"
2 
3 namespace Upp {
4 
5 struct GlyphPainter : NilPainter, LinearPathConsumer {
6 	Vector<float>       glyph;
7 	double              tolerance;
8 	Pointf              pos, move;
9 
10 	virtual void LineOp(const Pointf& p, bool);
11 	virtual void MoveOp(const Pointf& p, bool);
12 	virtual void QuadraticOp(const Pointf& p1, const Pointf& p, bool);
13 	virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool);
14 	virtual void CloseOp();
15 
16 	virtual void Line(const Pointf& p);
17 	virtual void Move(const Pointf& p);
18 };
19 
Move(const Pointf & p)20 void GlyphPainter::Move(const Pointf& p)
21 {
22 	glyph.Add((float)1e31);
23 	Line(p);
24 	move = pos;
25 }
26 
Line(const Pointf & p)27 void GlyphPainter::Line(const Pointf& p)
28 {
29 	glyph.Add((float)p.x);
30 	glyph.Add((float)p.y);
31 	pos = p;
32 }
33 
MoveOp(const Pointf & p,bool)34 void GlyphPainter::MoveOp(const Pointf& p, bool)
35 {
36 	Move(p);
37 }
38 
LineOp(const Pointf & p,bool)39 void GlyphPainter::LineOp(const Pointf& p, bool)
40 {
41 	Line(p);
42 }
43 
QuadraticOp(const Pointf & p1,const Pointf & p,bool)44 void GlyphPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool)
45 {
46 	ApproximateQuadratic(*this, pos, p1, p, tolerance);
47 	pos = p;
48 }
49 
CubicOp(const Pointf & p1,const Pointf & p2,const Pointf & p,bool)50 void GlyphPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool)
51 {
52 	ApproximateCubic(*this, pos, p1, p2, p, tolerance);
53 	pos = p;
54 }
55 
CloseOp()56 void GlyphPainter::CloseOp()
57 {
58 	if(move != pos && !IsNull(move))
59 		Line(move);
60 }
61 
62 struct GlyphKey {
63 	Font   fnt;
64 	int    chr;
65 	double tolerance;
66 
operator ==Upp::GlyphKey67 	bool operator==(const GlyphKey& b) const {
68 		return fnt == b.fnt && chr == b.chr && tolerance == b.tolerance;
69 	}
GetHashValueUpp::GlyphKey70 	hash_t GetHashValue() const {
71 		return CombineHash(fnt, chr, tolerance);
72 	}
73 };
74 
75 struct sMakeGlyph : LRUCache<Value, GlyphKey>::Maker {
76 	GlyphKey gk;
77 
KeyUpp::sMakeGlyph78 	GlyphKey Key() const     { return gk; }
MakeUpp::sMakeGlyph79 	int      Make(Value& v) const {
80 		GlyphPainter gp;
81 		gp.move = gp.pos = Null;
82 		gp.tolerance = gk.tolerance;
83 		PaintCharacter(gp, Pointf(0, 0), gk.chr, gk.fnt);
84 		int sz = gp.glyph.GetCount() * 4;
85 		v = RawPickToValue(pick(gp.glyph));
86 		return sz;
87 	}
88 };
89 
ApproximateChar(LinearPathConsumer & t,Pointf at,int ch,Font fnt,double tolerance)90 void ApproximateChar(LinearPathConsumer& t, Pointf at, int ch, Font fnt, double tolerance)
91 {
92 	PAINTER_TIMING("ApproximateChar");
93 	Value v;
94 	INTERLOCKED {
95 		PAINTER_TIMING("ApproximateChar::Fetch");
96 		static LRUCache<Value, GlyphKey> cache;
97 		cache.Shrink(500000);
98 		sMakeGlyph h;
99 		h.gk.fnt = fnt;
100 		h.gk.chr = ch;
101 		h.gk.tolerance = tolerance;
102 		v = cache.Get(h);
103 #ifdef _DEBUG0
104 		DLOG("==== ApproximateChar " << ch << " " << (char)ch << " " << fnt << ", tolerance: " << tolerance);
105 		DDUMP(ValueTo< Vector<float> >(v));
106 		GlyphPainter chp;
107 		chp.move = chp.pos = Null;
108 		chp.tolerance = tolerance;
109 		PaintCharacter(chp, Pointf(0, 0), ch, fnt);
110 		DDUMP(chp.glyph);
111 		ASSERT(ValueTo< Vector<float> >(v) == chp.glyph);
112 #endif
113 	}
114 	const Vector<float>& g = ValueTo< Vector<float> >(v);
115 	int i = 0;
116 	while(i < g.GetCount()) {
117 		Pointf p;
118 		p.x = g[i++];
119 		if(p.x > 1e30) {
120 			p.x = g[i++];
121 			p.y = g[i++];
122 			t.Move(p + at);
123 		}
124 		else {
125 			PAINTER_TIMING("ApproximateChar::Line");
126 			p.y = g[i++];
127 			t.Line(p + at);
128 		}
129 	}
130 }
131 
132 }
133