1 #include "Painter.h"
2 
3 namespace Upp {
4 
MakeGradient(RGBA color1,Vector<ColorStop> & color_stop,RGBA color2,int n)5 Image BufferPainter::MakeGradient(RGBA color1, Vector<ColorStop>& color_stop, RGBA color2, int n)
6 {
7 	ImageBuffer ib(n, 1);
8 	RGBA *t = ib[0];
9 	int l = 0;
10 	RGBA cl = color1;
11 	for(int i = 0; i <= color_stop.GetCount(); i++) {
12 		int h;
13 		RGBA ch;
14 		if(i < color_stop.GetCount()) {
15 			h = (int)(color_stop[i].stop * (n - 1));
16 			ch = color_stop[i].color;
17 		}
18 		else {
19 			h = n - 1;
20 			ch = color2;
21 		}
22 		int w = h - l;
23 		for(int j = 0; j < w; j++) {
24 			t->r = ((w - j) * cl.r + j * ch.r) / w;
25 			t->g = ((w - j) * cl.g + j * ch.g) / w;
26 			t->b = ((w - j) * cl.b + j * ch.b) / w;
27 			t->a = ((w - j) * cl.a + j * ch.a) / w;
28 			t++;
29 		}
30 		cl = ch;
31 		l = h;
32 	}
33 	*t = cl;
34 	return ib;
35 }
36 
37 struct BufferPainter::GradientImageMaker : public ImageMaker {
38 	RGBA color1;
39 	Vector<ColorStop> *color_stop;
40 	RGBA color2;
41 	int n;
42 
43 	virtual String Key() const;
44 	virtual Image  Make() const;
45 };
46 
Key() const47 String BufferPainter::GradientImageMaker::Key() const
48 {
49 	StringStream ss;
50 	auto cc = const_cast<GradientImageMaker *>(this);
51 	ss % cc->color1 % *cc->color_stop % cc->color2 % cc->n;
52 	return ss.GetResult();
53 }
54 
Make() const55 Image BufferPainter::GradientImageMaker::Make() const
56 {
57 	return MakeGradient(color1, *color_stop, color2, n);
58 }
59 
MakeGradientCached(RGBA color1,Vector<ColorStop> & color_stop,RGBA color2,int n)60 Image BufferPainter::MakeGradientCached(RGBA color1, Vector<ColorStop>& color_stop, RGBA color2, int n)
61 {
62 	GradientImageMaker m;
63 	m.color1 = color1;
64 	m.color_stop = &color_stop;
65 	m.color2 = color2;
66 	m.n = n;
67 	return MakeImage(m);
68 }
69 
Gradient(const RGBA & color1,const RGBA & color2,int n)70 Image BufferPainter::Gradient(const RGBA& color1, const RGBA& color2, int n)
71 {
72 	return (imagecache ? MakeGradientCached : MakeGradient)(color1, pathattr.color_stop, color2, n);
73 }
74 
Gradient(const RGBA & color1,const RGBA & color2,const Pointf & p1,const Pointf & p2)75 Image BufferPainter::Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2)
76 {
77 	return Gradient(color1, color2, minmax(int(Distance(p1, p2) * pathattr.mtx.GetScale()), 2, 16384));
78 }
79 
sLinearStyle(int style)80 static dword sLinearStyle(int style)
81 {
82 	dword s = style & ~FILL_FAST;
83 	return FILL_VPAD | (style & FILL_FAST) |
84 	       decode(s, GRADIENT_PAD, FILL_HPAD, GRADIENT_REPEAT, FILL_HREPEAT, FILL_HREFLECT);
85 }
86 
FillOp(const Pointf & p1,const RGBA & color1,const Pointf & p2,const RGBA & color2,int style)87 void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
88 {
89 	Fill(Gradient(color1, color2, p1, p2), p1, p2, sLinearStyle(style));
90 }
91 
FillOp(const RGBA & color1,const RGBA & color2,const Xform2D & transsrc,int style)92 void BufferPainter::FillOp(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
93 {
94 	Fill(Gradient(color1, color2, 500), Xform2D::Scale(1.0 / 500) * transsrc, sLinearStyle(style));
95 }
96 
StrokeOp(double width,const Pointf & p1,const RGBA & color1,const Pointf & p2,const RGBA & color2,int style)97 void BufferPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
98 {
99 	Stroke(width, Gradient(color1, color2, p1, p2), p1, p2, sLinearStyle(style));
100 }
101 
StrokeOp(double width,const RGBA & color1,const RGBA & color2,const Xform2D & transsrc,int style)102 void BufferPainter::StrokeOp(double width, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
103 {
104 	Stroke(width, Gradient(color1, color2, 500), Xform2D::Scale(1.0 / 500) * transsrc, sLinearStyle(style));
105 }
106 
107 }
108