#include "Painter.h" namespace Upp { template void sGet(T& r, StringStream& ss) { ss.Get(&r, sizeof(T)); } template T sGet(StringStream& ss) { T r; ss.Get(&r, sizeof(T)); return r; } void Painter::Paint(const Painting& pic) { StringStream ss(pic.cmd); Pointf p, p1, p2; RGBA c, c1; Value v; int f, ch, n, hasdx; Xform2D m; double r, w; Font fnt; int ii = 0; bool large, sweep; for(;;) { int cmd = ss.Get(); if(cmd < 0) return; bool rel = cmd & 1; switch(cmd) { case PAINTING_CLEAR: ClearOp(sGet(ss)); break; case PAINTING_MOVE: case PAINTING_MOVE_REL: sGet(p, ss); MoveOp(p, rel); break; case PAINTING_LINE: case PAINTING_LINE_REL: sGet(p, ss); LineOp(p, rel); break; case PAINTING_QUADRATIC: case PAINTING_QUADRATIC_REL: sGet(p1, ss); sGet(p, ss); QuadraticOp(p1, p, rel); break; case PAINTING_QUADRATIC_S: case PAINTING_QUADRATIC_S_REL: sGet(p, ss); QuadraticOp(p, rel); break; case PAINTING_CUBIC: case PAINTING_CUBIC_REL: sGet(p1, ss); sGet(p2, ss); sGet(p, ss); CubicOp(p1, p2, p, rel); break; case PAINTING_CUBIC_S: case PAINTING_CUBIC_S_REL: sGet(p2, ss); sGet(p, ss); CubicOp(p2, p, rel); break; case PAINTING_ARC: case PAINTING_ARC_REL: sGet(p, ss); sGet(p1, ss); sGet(r, ss); sGet(w, ss); ArcOp(p, p1, r, w, rel); break; case PAINTING_SVGARC: case PAINTING_SVGARC_REL: sGet(p1, ss); sGet(r, ss); sGet(large, ss); sGet(sweep, ss); sGet(p, ss); SvgArcOp(p1, r, large, sweep, p, rel); break; case PAINTING_CLOSE: CloseOp(); break; case PAINTING_DIV: DivOp(); break; case PAINTING_FILL_SOLID: FillOp(sGet(ss)); break; case PAINTING_FILL_IMAGE: sGet(m, ss); f = ss.Get(); if(ii >= pic.data.GetCount()) return; v = pic.data[ii++]; if(!v.Is()) return; FillOp((Image)v, m, f); break; case PAINTING_FILL_GRADIENT: sGet(p, ss); sGet(c, ss); sGet(p1, ss); sGet(c1, ss); f = ss.Get(); FillOp(p, c, p1, c1, f); break; case PAINTING_FILL_GRADIENT_X: sGet(c, ss); sGet(c1, ss); sGet(m, ss); f = ss.Get(); FillOp(c, c1, m, f); break; case PAINTING_FILL_RADIAL_X: sGet(p1, ss); sGet(c, ss); sGet(c1, ss); sGet(m, ss); f = ss.Get(); FillOp(p1, c, c1, m, f); break; case PAINTING_FILL_RADIAL: sGet(p, ss); sGet(c, ss); sGet(p1, ss); sGet(r, ss); sGet(c1, ss); f = ss.Get(); FillOp(p, c, p1, r, c1, f); break; case PAINTING_STROKE_SOLID: sGet(w, ss); sGet(c, ss); StrokeOp(w, c); break; case PAINTING_STROKE_IMAGE: sGet(w, ss); sGet(m, ss); f = ss.Get(); if(ii >= pic.data.GetCount()) return; v = pic.data[ii++]; if(!v.Is()) return; StrokeOp(w, (Image)v, m, f); break; case PAINTING_STROKE_GRADIENT: sGet(w, ss); sGet(p, ss); sGet(c, ss); sGet(p1, ss); sGet(c1, ss); f = ss.Get(); StrokeOp(w, p, c, p1, c1, f); break; case PAINTING_STROKE_GRADIENT_X: sGet(w, ss); sGet(c, ss); sGet(c1, ss); sGet(m, ss); f = ss.Get(); FillOp(c, c1, m, f); StrokeOp(w, c, c1, m, f); break; case PAINTING_STROKE_RADIAL_X: sGet(w, ss); sGet(p1, ss); sGet(c, ss); sGet(c1, ss); sGet(m, ss); f = ss.Get(); FillOp(c, c1, m, f); StrokeOp(w, p1, c, c1, m, f); break; case PAINTING_STROKE_RADIAL: sGet(w, ss); sGet(p, ss); sGet(c, ss); sGet(p1, ss); sGet(r, ss); sGet(c1, ss); f = ss.Get(); StrokeOp(w, p, c, p1, r, c1, f); break; case PAINTING_CLIP: ClipOp(); break; case PAINTING_CHARACTER: sGet(p, ss); ch = ss.Get32(); sGet(fnt, ss); CharacterOp(p, ch, fnt); break; case PAINTING_TEXT: { sGet(p, ss); n = ss.Get32(); hasdx = ss.Get(); sGet(fnt, ss); Buffer txt(n); Buffer dx(hasdx * n); for(int i = 0; i < n; i++) { txt[i] = ss.Get32(); if(hasdx) sGet(dx[i], ss); } TextOp(p, txt, fnt, n, hasdx ? ~dx : NULL); } break; case PAINTING_COLORSTOP: sGet(r, ss); sGet(c, ss); ColorStopOp(r, c); break; case PAINTING_CLEARSTOPS: ClearStopsOp(); break; case PAINTING_OPACITY: OpacityOp(sGet(ss)); break; case PAINTING_LINECAP: LineCapOp(ss.Get()); break; case PAINTING_LINEJOIN: LineJoinOp(ss.Get()); break; case PAINTING_MITERLIMIT: MiterLimitOp(ss.Get()); break; case PAINTING_EVENODD: EvenOddOp(ss.Get()); break; case PAINTING_INVERT: InvertOp(ss.Get()); break; case PAINTING_IMAGE_FILTER: ImageFilterOp(ss.Get()); break; case PAINTING_DASH: { n = ss.Get32(); Vector dash; for(int i = 0; i < n; i++) dash.Add(sGet(ss)); r = sGet(ss); DashOp(dash, r); } break; case PAINTING_TRANSFORM: sGet(m, ss); TransformOp(m); break; case PAINTING_BEGIN: BeginOp(); break; case PAINTING_END: EndOp(); break; case PAINTING_BEGINMASK: BeginMaskOp(); break; case PAINTING_BEGINONPATH: sGet(r, ss); BeginOnPathOp(r, ss.Get()); break; } } } void PaintImageBufferPaintingFn(ImageBuffer& ib, const Painting& p, Size sz, Point pos, int mode) { BufferPainter sw(ib, mode); Sizef psz = p.GetSize(); sw.Translate(-pos.x, -pos.y); sw.Scale(sz.cx / psz.cx, sz.cy / psz.cy); sw.Paint(p); } void PaintImageBufferDrawingFn(ImageBuffer& ib, const Drawing& iw, int mode) { BufferPainter sw(ib, mode); Sizef sz = ib.GetSize(); Size isz = iw.GetSize(); sw.Scale(sz.cx / isz.cx, sz.cy / isz.cy); sw.DrawDrawing(0, 0, isz.cx, isz.cy, iw); } void RegisterPaintingFns__(void (*ig)(ImageBuffer& ib, const Painting& pw, Size sz, Point pos, int mode), void (*iw)(ImageBuffer& ib, const Drawing& p, int mode), Image (*rg)(Point at, int angle, int chr, Font fnt, Color color, Size sz)); void ImageAnyDrawPainter(Draw *(*f)(Size sz), Image (*e)(Draw *w)); static Draw *sCP(Size sz) { return new ImagePainter(sz); } static Image sEP(Draw *w) { ImagePainter *ip = dynamic_cast(w); return ip ? (Image)(*ip) : Image(); } static Image sRenderGlyph(Point at, int angle, int chr, Font fnt, Color color, Size sz) { ImageBuffer ib(sz); BufferPainter sw(ib); sw.Clear(RGBAZero()); sw.DrawText(at.x, at.y, angle, WString(chr, 1), fnt, color); Image h = ib; return Premultiply(h); } INITIALIZER(PaintPainting) { RegisterPaintingFns__(PaintImageBufferPaintingFn, PaintImageBufferDrawingFn, sRenderGlyph); ImageAnyDrawPainter(sCP, sEP); } }