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