1 force_inline
Mul8(const RGBA & s,int mul)2 RGBA Mul8(const RGBA& s, int mul)
3 {
4 	RGBA t;
5 	t.r = (mul * s.r) >> 8;
6 	t.g = (mul * s.g) >> 8;
7 	t.b = (mul * s.b) >> 8;
8 	t.a = (mul * s.a) >> 8;
9 	return t;
10 }
11 
12 struct SpanSource {
13 	virtual void Get(RGBA *span, int x, int y, unsigned len) = 0;
~SpanSourceSpanSource14 	virtual ~SpanSource() {}
15 };
16 
17 class ClippingLine : NoCopy {
18 	byte *data;
19 
20 public:
Clear()21 	void Clear()                         { if(!IsFull()) MemoryFree(data); data = NULL; }
Set(const byte * s,int len)22 	void Set(const byte *s, int len)     { data = (byte *)MemoryAlloc(len); memcpy8(data, s, len); }
SetFull()23 	void SetFull()                       { ASSERT(!data); data = (byte *)1; }
24 
IsEmpty()25 	bool IsEmpty() const                 { return !data; }
IsFull()26 	bool IsFull() const                  { return data == (byte *)1; }
27 	operator const byte*() const         { return data; }
28 
ClippingLine()29 	ClippingLine()                       { data = NULL; }
~ClippingLine()30 	~ClippingLine()                      { Clear(); }
31 };
32 
33 struct PainterTarget : LinearPathConsumer {
34 	virtual void Fill(double width, SpanSource *ss, const RGBA& color);
35 };
36 
37 class BufferPainter : public Painter {
38 protected:
39 	virtual void   ClearOp(const RGBA& color);
40 
41 	virtual void   MoveOp(const Pointf& p, bool rel);
42 	virtual void   LineOp(const Pointf& p, bool rel);
43 	virtual void   QuadraticOp(const Pointf& p1, const Pointf& p, bool rel);
44 	virtual void   QuadraticOp(const Pointf& p, bool rel);
45 	virtual void   CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel);
46 	virtual void   CubicOp(const Pointf& p2, const Pointf& p, bool rel);
47 	virtual void   ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel);
48 	virtual void   SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
49 	                        const Pointf& p, bool rel);
50 	virtual void   CloseOp();
51 	virtual void   DivOp();
52 
53 	virtual void   CharacterOp(const Pointf& p, int ch, Font fnt);
54 
55 	virtual void   FillOp(const RGBA& color);
56 	virtual void   FillOp(const Image& image, const Xform2D& transsrc, dword flags);
57 	virtual void   FillOp(const Pointf& p1, const RGBA& color1,
58 	                      const Pointf& p2, const RGBA& color2,
59 	                      int style);
60 	virtual void   FillOp(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc,
61 	                      int style);
62 	virtual void   FillOp(const Pointf& f, const RGBA& color1,
63 	                      const Pointf& c, double r, const RGBA& color2,
64 	                      int style);
65 	virtual void   FillOp(const Pointf& f, const RGBA& color1, const RGBA& color2,
66 	                      const Xform2D& transsrc, int style);
67 
68 	virtual void   StrokeOp(double width, const RGBA& rgba);
69 	virtual void   StrokeOp(double width, const Image& image, const Xform2D& transsrc,
70 	                        dword flags);
71 	virtual void   StrokeOp(double width, const Pointf& p1, const RGBA& color1,
72 	                        const Pointf& p2, const RGBA& color2,
73 	                        int style);
74 	virtual void   StrokeOp(double width, const RGBA& color1, const RGBA& color2,
75 	                        const Xform2D& transsrc,
76 	                        int style);
77 	virtual void   StrokeOp(double width, const Pointf& f, const RGBA& color1,
78 	                        const Pointf& c, double r, const RGBA& color2,
79 	                        int style);
80 	virtual void   StrokeOp(double width, const Pointf& f,
81 	                        const RGBA& color1, const RGBA& color2,
82 	                        const Xform2D& transsrc, int style);
83 
84 	virtual void   ClipOp();
85 
86 	virtual void   ColorStopOp(double pos, const RGBA& color);
87 	virtual void   ClearStopsOp();
88 
89 	virtual void   OpacityOp(double o);
90 	virtual void   LineCapOp(int linecap);
91 	virtual void   LineJoinOp(int linejoin);
92 	virtual void   MiterLimitOp(double l);
93 	virtual void   EvenOddOp(bool evenodd);
94 	virtual void   DashOp(const String& dash, double start);
95 	virtual void   DashOp(const Vector<double>& dash, double start);
96 	virtual void   InvertOp(bool invert);
97 
98 	virtual void   TransformOp(const Xform2D& m);
99 
100 	virtual void   BeginOp();
101 	virtual void   EndOp();
102 
103 	virtual void   BeginMaskOp();
104 	virtual void   BeginOnPathOp(double q, bool abs);
105 
106 private:
107 	enum {
108 		MOVE, LINE, QUADRATIC, CUBIC, CHAR
109 	};
110 	struct LinearData {
111 		int    type;
112 		Pointf p;
113 	};
114 	struct QuadraticData : LinearData {
115 		Pointf p1;
116 	};
117 	struct CubicData : QuadraticData {
118 		Pointf p2;
119 	};
120 	struct CharData : LinearData {
121 		int  ch;
122 		int  _filler;
123 		Font fnt;
124 	};
125 	struct PathLine : Moveable<PathLine> {
126 		Pointf p;
127 		double len;
128 	};
129 	struct DashInfo {
130 		WithDeepCopy<Vector<double>>    dash;
131 		double                          start;
132 	};
133 	struct ColorStop : Moveable<ColorStop> {
134 		double stop;
135 		RGBA   color;
136 
137 		bool operator<(const ColorStop& b) const { return stop < b.stop; }
SerializeColorStop138 		void Serialize(Stream& s)                { s % stop % color; }
139 	};
140 	struct SimpleAttr {
141 		Xform2D                         mtx;
142 		double                          miter_limit;
143 		double                          opacity;
144 		const DashInfo                 *dash;
145 		bool                            evenodd;
146 		byte                            join;
147 		byte                            cap;
148 		bool                            invert;
149 	};
150 	struct Attr : Moveable<Attr, SimpleAttr> {
151 		int                             mtx_serial; // used to detect changes to speedup preclip
152 		WithDeepCopy<Vector<ColorStop>> color_stop;
153 
154 		int                             cliplevel;
155 		bool                            hasclip;
156 		bool                            mask;
157 		bool                            onpath;
158 	};
159 
160 	PainterTarget             *alt = NULL;
161 	double                     alt_tolerance = Null;
162 	ImageBuffer                dummy;
163 	ImageBuffer               *ip;
164 	int                        mode = -1;
165 	Buffer<int16>              subpixel;
166 	Buffer<Buffer<int16>>      co_subpixel;
167 	int                        render_cx;
168 	int                        dopreclip = 0;
169 	Sizef                      size = Sizef(0, 0); // = ib.GetSize()
170 
171 	Attr                       attr;
172 	Array<Attr>                attrstack;
173 	Vector<Buffer<ClippingLine>> clip;
174 	Array< ImageBuffer >       mask;
175 	Vector<Vector<PathLine>>   onpathstack;
176 	Vector<double>             pathlenstack;
177 	int                        mtx_serial = 0;
178 	ArrayMap<String, DashInfo> dashes;
179 
180 	Rectf                      preclip;
181 	int                        preclip_mtx_serial = -1;
182 	bool                       regular;
183 
184 	struct PathInfo {
185 		Vector<Vector<byte>>               path;
186 		bool                               ischar;
187 		Pointf                             path_min, path_max;
188 	};
189 
190 	enum { BATCH_SIZE = 128 }; // must be 2^n
191 
192 	Buffer<PathInfo> paths;
193 	int              path_index = 0;
194 	PathInfo        *path_info;
195 	Attr             pathattr;
196 
197 	Pointf           current, ccontrol, qcontrol, move;
198 
199 	Rasterizer           rasterizer;
200 	Buffer<RGBA>         span;
201 	Buffer<Buffer<RGBA>> co_span;
202 
203 	Vector<PathLine> onpath;
204 	double           pathlen;
205 
206 	struct OnPathTarget;
207 	friend struct OnPathTarget;
208 
209 	bool co = false;
210 	bool imagecache = true;
211 
212 	struct OnPathTarget : LinearPathConsumer {
213 		Vector<BufferPainter::PathLine> path;
214 		Pointf pos;
215 		double len;
216 
MoveOnPathTarget217 		virtual void Move(const Pointf& p) {
218 			BufferPainter::PathLine& t = path.Add();
219 			t.len = 0;
220 			pos = t.p = p;
221 		}
LineOnPathTarget222 		virtual void Line(const Pointf& p) {
223 			BufferPainter::PathLine& t = path.Add();
224 			len += (t.len = Distance(pos, p));
225 			pos = t.p = p;
226 		}
227 
OnPathTargetOnPathTarget228 		OnPathTarget() { len = 0; pos = Pointf(0, 0); }
229 	};
230 
231 	struct PathJob {
232 		Transformer         trans;
233 		Stroker             stroker;
234 		Dasher              dasher;
235 		OnPathTarget        onpathtarget;
236 		LinearPathConsumer *g;
237 		double              tolerance;
238 		bool                evenodd;
239 		bool                regular;
240 		bool                preclipped;
241 
242 
243 		PathJob(Rasterizer& rasterizer, double width, const PathInfo *path_info,
244 		        const SimpleAttr& attr, const Rectf& preclip, bool regular);
245 	};
246 
247 	struct CoJob {
248 		SimpleAttr        attr;
249 		PathInfo         *path_info;
250 		Rectf             preclip;
251 		double            width;
252 		double            opacity;
253 		Rasterizer        rasterizer;
254 		RGBA              color;
255 		RGBA              c;
256 		int               subpath;
257 		bool              evenodd;
258 		bool              regular;
259 	};
260 
261 	friend struct CoJob;
262 
263 	Array<CoJob>     cojob, cofill;
264 	int              jobcount, fillcount;
265 
266 	CoWorkNX         fill_job;
267 
268 	template <class T> T& PathAdd(int type);
269 
270 	Pointf           PathPoint(const Pointf& p, bool rel);
271 	Pointf           EndPoint(const Pointf& p, bool rel);
272 	void             DoMove0();
273 	void             DoPath0();
DoPath()274 	void             DoPath()         { if(IsNull(current)) DoPath0(); }
275 	void             ClearPath();
276 	Buffer<ClippingLine> RenderPath(double width, Event<One<SpanSource>&> ss, const RGBA& color);
277 	void             RenderImage(double width, const Image& image, const Xform2D& transsrc,
278 	                             dword flags);
279 	void             RenderRadial(double width, const Pointf& f, const RGBA& color1,
280 	                              const Pointf& c, double r, const RGBA& color2,
281 	                              const Xform2D& m, int style);
282 	void             RenderRadial(double width, const Pointf& f, const RGBA& color1, const RGBA& color2,
283 	                              const Xform2D& transsrc, int style);
284 
285 	struct           GradientImageMaker;
286 	static Image     MakeGradient(RGBA color1, Vector<ColorStop>& color_stop, RGBA color2, int n);
287 	static Image     MakeGradientCached(RGBA color1, Vector<ColorStop>& color_stop, RGBA color2, int n);
288 	Image            Gradient(const RGBA& color1, const RGBA& color2, int n);
289 	Image            Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2);
290 	void             ColorStop0(Attr& a, double pos, const RGBA& color);
291 	void             FinishMask();
292 
293 	static void RenderPathSegments(LinearPathConsumer *g, const Vector<byte>& path, const SimpleAttr *attr, double tolerance);
294 
295 	void FinishPathJob();
FinishFillJob()296 	void FinishFillJob()                                       { fill_job.Finish(); }
297 
298 	void SyncCo();
299 
300 	enum { FILL = -1, CLIP = -2, ONPATH = -3 };
301 
302 public:
GetBuffer()303 	ImageBuffer&       GetBuffer()                             { return *ip; }
GetBuffer()304 	const ImageBuffer& GetBuffer() const                       { return *ip; }
305 
306 	BufferPainter&     Co(bool b = true)                       { Finish(); co = b; SyncCo(); return *this; }
307 	BufferPainter&     PreClip(bool b = true)                  { dopreclip = b; preclip_mtx_serial = -1; return *this; }
PreClipDashed()308 	BufferPainter&     PreClipDashed()                         { dopreclip = 2; preclip_mtx_serial = -1; return *this; }
309 	BufferPainter&     ImageCache(bool b = true)               { imagecache = b; return *this; }
310 	BufferPainter&     NoImageCache(bool b = true)             { return ImageCache(false); }
311 
312 	void               Create(ImageBuffer& ib, int mode = MODE_ANTIALIASED);
313 	void               Finish();
314 
315 	BufferPainter(ImageBuffer& ib, int mode = MODE_ANTIALIASED) { Create(ib, mode); }
316 	BufferPainter(PainterTarget& t, double tolerance = Null);
BufferPainter()317 	BufferPainter() : BufferPainter(dummy, MODE_ANTIALIASED)    {}
318 
~BufferPainter()319 	~BufferPainter()                                            { Finish(); }
320 };
321 
322 #include "Interpolator.hpp"
323