diff --git a/uppdev/Painter/BufferPainter.h b/uppdev/Painter/BufferPainter.h index 82fe43d89..fd4abd0a4 100644 --- a/uppdev/Painter/BufferPainter.h +++ b/uppdev/Painter/BufferPainter.h @@ -177,32 +177,11 @@ struct SpanSource { virtual void Get(RGBA *span, int x, int y, unsigned len) = 0; }; -struct SolidFiller : Rasterizer::Filler { - RGBA *t; - RGBA c; - - void Start(int minx, int maxx) { t += minx; } - void Render(int val) { AlphaBlendCover8(*t++, c, val); } - void Render(int val, int len); -}; - -struct SpanFiller : Rasterizer::Filler { - RGBA *t; - const RGBA *s; - int y; - RGBA *buffer; - SpanSource *ss; - int alpha; - - void Start(int minx, int maxx); - void Render(int val); - void Render(int val, int len); -}; - -class ClipLine { +class ClipLine : NoCopy { byte *data; public: + void Clear() { if(!IsFull()) delete[] data; data = NULL; } void Set(const byte *s, int len) { data = new byte[len]; memcpy(data, s, len); } void SetFull() { ASSERT(!data); data = (byte *)1; } @@ -211,52 +190,7 @@ public: operator const byte*() const { return data; } ClipLine() { data = NULL; } - ~ClipLine() { if(!IsFull()) delete[] data; } -}; - -struct ClipFiller : Rasterizer::Filler { - Buffer buffer; - byte *t; - int x; - int cx; - int last; - byte *lastn; - bool empty; - bool full; - - void Span(int c, int len); - - virtual void Render(int val); - virtual void Render(int val, int len); - virtual void Start(int x, int len); - - void Clear(); - void Finish(ClipLine& cl); - - ClipFiller(int cx); -}; - -struct MaskFillerFilter : Rasterizer::Filler { - Rasterizer::Filler *t; - const byte *mask; - int empty; - int full; - - void Start(int minx, int maxx); - void Render(int val, int len); - void Render(int val); - - void Set(Rasterizer::Filler *f, const byte *m) { t = f; mask = m; empty = full = 0; } -}; - -struct NoAAFillerFilter : Rasterizer::Filler { - Rasterizer::Filler *t; - - void Start(int minx, int maxx); - void Render(int val, int len); - void Render(int val); - - void Set(Rasterizer::Filler *f) { t = f; } + ~ClipLine() { Clear(); } }; Image MipMap(const Image& img); @@ -331,6 +265,8 @@ protected: virtual void BeginOp(); virtual void EndOp(); + virtual void BeginMaskOp(); + public: enum { MOVE, LINE, QUADRATIC, CUBIC, ARC, DIV @@ -372,12 +308,14 @@ public: bool noaa; }; - ImageBuffer& ib; + ImageBuffer& ib; Attr attr; Attr pathattr; Array attrstack; Vector< Buffer > clip; + Array< ImageBuffer > mask; + Image gradient; RGBA gradient1, gradient2; @@ -405,6 +343,7 @@ public: void MakeGradient(RGBA color1, RGBA color2, int cx); void Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2); void ColorStop0(Attr& a, double pos, const RGBA& color); + void FinishMask(); public: BufferPainter(ImageBuffer& ib); diff --git a/uppdev/Painter/Context.cpp b/uppdev/Painter/Context.cpp index c79f1f9a1..66af03b35 100644 --- a/uppdev/Painter/Context.cpp +++ b/uppdev/Painter/Context.cpp @@ -17,10 +17,8 @@ void BufferPainter::EndOp() pathattr = attr = attrstack.Top(); attrstack.Drop(); clip.SetCount(attr.cliplevel); -#if 0 if(attr.mask) FinishMask(); -#endif } void BufferPainter::TransformOp(const Xform2D& m) diff --git a/uppdev/Painter/DrawOp.cpp b/uppdev/Painter/DrawOp.cpp new file mode 100644 index 000000000..1f3805ff2 --- /dev/null +++ b/uppdev/Painter/DrawOp.cpp @@ -0,0 +1,137 @@ +#include "Painter.h" + +NAMESPACE_UPP + +void Painter::OffsetOp(Point p) +{ + Begin(); + Translate(p.x, p.y); +} + +void Painter::RectPath(int x, int y, int cx, int cy) +{ + Move(x, y).Line(x + cx, y).Line(x + cx, y + cy).Line(x, y + cy).Close(); +} + +void Painter::RectPath(const Rect& r) +{ + RectPath(r.left, r.top, r.GetWidth(), r.GetHeight()); +} + +bool Painter::ClipOp(const Rect& r) +{ + Begin(); + RectPath(r); + Clip(); + return true; +} + +bool Painter::ClipoffOp(const Rect& r) +{ + Begin(); + RectPath(r); + Clip(); + Translate(r.left, r.top); + return true; +} + +bool Painter::ExcludeClipOp(const Rect& r) +{ + return true; +} + +bool Painter::IntersectClipOp(const Rect& r) +{ + return true; + RectPath(r); + Clip(); + return true; +} + +Rect Painter::GetClipOp() const +{ + return Rect(0, 0, 0, 0); +} + +bool Painter::IsPaintingOp(const Rect& r) const +{ + return true; +} + +void Painter::DrawRectOp(int x, int y, int cx, int cy, Color color) +{ + RectPath(x, y, cx, cy); + Fill(color); +} + +void Painter::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) +{ + // Color and src support!!! + RectPath(x, y, cx, cy); + Fill(img, Xform2D::Translation(x, y)); +} + +void Painter::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) +{ + double h = width / 2; + Move(x1 + h, y1 + h); + Line(x2 + h, y2 + h); + Stroke(max(width, 0), color); +} + +void Painter::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, + int count_count, int width, Color color, Color doxor) +{ +} + +void Painter::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts, + int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor) +{ +} + +void Painter::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) +{ +} + +void Painter::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) +{ + Sizef sz = r.GetSize(); + Ellipse(r.left + sz.cx / 2, r.top + sz.cy / 2, sz.cx / 2, sz.cy / 2); + Fill(color); + Stroke(max(pen, 0), pencolor); +} + +void Painter::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) +{ + Begin(); + EvenOdd(true); + if(angle) + Rotate(angle * M_2PI / 36000); + if(n < 0) + n = wstrlen(text); + double *ddx = NULL; + Buffer h; + if(dx) { + h.Alloc(n); + ddx = h; + for(int i = 0; i < n; i++) + ddx[i] = dx[i]; + } + Text(x, y, text, font, n, ddx); + Fill(ink); + End(); +} + +void Painter::DrawPaintingOp(const Rect& target, const Painting& p) +{ + Size sz = target.GetSize(); + Sizef psz = p.GetSize(); + Begin(); + Translate(target.left, target.top); + Scale(sz.cx / psz.cx, sz.cy / psz.cy); + Paint(p); + End(); +} + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Filler.cpp b/uppdev/Painter/Filler.cpp deleted file mode 100644 index ce404bc82..000000000 --- a/uppdev/Painter/Filler.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "Painter.h" - -NAMESPACE_UPP - -void SolidFiller::Render(int val, int len) -{ - if(val == 0) { - t += len; - return; - } - if(((val - 256) | (c.a - 255)) == 0) { - while(len >= 16) { - t[0] = c; t[1] = c; t[2] = c; t[3] = c; - t[4] = c; t[5] = c; t[6] = c; t[7] = c; - t[8] = c; t[9] = c; t[10] = c; t[11] = c; - t[12] = c; t[13] = c; t[14] = c; t[15] = c; - t += 16; - len -= 16; - } - switch(len) { - case 15: t[14] = c; - case 14: t[13] = c; - case 13: t[12] = c; - case 12: t[11] = c; - case 11: t[10] = c; - case 10: t[9] = c; - case 9: t[8] = c; - case 8: t[7] = c; - case 7: t[6] = c; - case 6: t[5] = c; - case 5: t[4] = c; - case 4: t[3] = c; - case 3: t[2] = c; - case 2: t[1] = c; - case 1: t[0] = c; - } - t += len; - } - else { - RGBA c1; - if(val != 256) - c1 = Mul8(c, val); - else - c1 = c; - RGBA *e = t + len; - while(t < e) - AlphaBlend(*t++, c1); - } -} - -void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd) -{ - Size sz = ib.GetSize(); - SolidFiller f; - f.c = color; - for(int y = r.MinY(); y <= r.MaxY(); y++) { - f.t = ib[y]; - r.Render(y, f, evenodd); - } - r.Reset(); -} - -void SpanFiller::Start(int minx, int maxx) -{ - t += minx; - ss->Get(buffer, minx, y, maxx - minx + 1); - s = buffer; -} - -void SpanFiller::Render(int val) -{ - if(alpha != 256) - val = alpha * val >> 8; - AlphaBlendCover8(*t++, *s++, val); -} - -void SpanFiller::Render(int val, int len) -{ - if(val == 0) { - t += len; - s += len; - return; - } - const RGBA *e = t + len; - if(alpha != 256) - val = alpha * val >> 8; - if(val == 256) - while(t < e) { - if(s->a == 255) - *t++ = *s++; - else - AlphaBlend(*t++, *s++); - } - else - while(t < e) - AlphaBlendCover8(*t++, *s++, val); -} - -void NoAAFillerFilter::Start(int minx, int maxx) -{ - t->Start(minx, maxx); -} - -void NoAAFillerFilter::Render(int val, int len) -{ - t->Render(val < 128 ? 0 : 256, len); -} - -void NoAAFillerFilter::Render(int val) -{ - t->Render(val < 128 ? 0 : 256); -} - -END_UPP_NAMESPACE diff --git a/uppdev/Painter/Fillers.cpp b/uppdev/Painter/Fillers.cpp new file mode 100644 index 000000000..e2c73ac2e --- /dev/null +++ b/uppdev/Painter/Fillers.cpp @@ -0,0 +1,272 @@ +#include "Painter.h" +#include "Fillers.h" + +NAMESPACE_UPP + +void SolidFiller::Start(int minx, int maxx) +{ + t += minx; +} + +void SolidFiller::Render(int val) +{ + AlphaBlendCover8(*t++, c, val); +} + +void SolidFiller::Render(int val, int len) +{ + if(val == 0) { + t += len; + return; + } + if(((val - 256) | (c.a - 255)) == 0) { + while(len >= 16) { + t[0] = c; t[1] = c; t[2] = c; t[3] = c; + t[4] = c; t[5] = c; t[6] = c; t[7] = c; + t[8] = c; t[9] = c; t[10] = c; t[11] = c; + t[12] = c; t[13] = c; t[14] = c; t[15] = c; + t += 16; + len -= 16; + } + switch(len) { + case 15: t[14] = c; + case 14: t[13] = c; + case 13: t[12] = c; + case 12: t[11] = c; + case 11: t[10] = c; + case 10: t[9] = c; + case 9: t[8] = c; + case 8: t[7] = c; + case 7: t[6] = c; + case 6: t[5] = c; + case 5: t[4] = c; + case 4: t[3] = c; + case 3: t[2] = c; + case 2: t[1] = c; + case 1: t[0] = c; + } + t += len; + } + else { + RGBA c1; + if(val != 256) + c1 = Mul8(c, val); + else + c1 = c; + RGBA *e = t + len; + while(t < e) + AlphaBlend(*t++, c1); + } +} + +void SpanFiller::Start(int minx, int maxx) +{ + t += minx; + ss->Get(buffer, minx, y, maxx - minx + 1); + s = buffer; +} + +void SpanFiller::Render(int val) +{ + if(alpha != 256) + val = alpha * val >> 8; + AlphaBlendCover8(*t++, *s++, val); +} + +void SpanFiller::Render(int val, int len) +{ + if(val == 0) { + t += len; + s += len; + return; + } + const RGBA *e = t + len; + if(alpha != 256) + val = alpha * val >> 8; + if(val == 256) + while(t < e) { + if(s->a == 255) + *t++ = *s++; + else + AlphaBlend(*t++, *s++); + } + else + while(t < e) + AlphaBlendCover8(*t++, *s++, val); +} + +ClipFiller::ClipFiller(int _cx) +{ + cx = _cx; + buffer.Alloc(2 * cx); +} + +void ClipFiller::Clear() +{ + t = ~buffer; + x = 0; + empty = true; + full = true; + last = -1; +} + +void ClipFiller::Start(int xmin, int xmax) +{ + Render(0, xmin); +} + +void ClipFiller::Span(int val, int len) +{ + int v = val >> 1; + if(last == val) { + int n = min(v + 128 - *lastn - 1, len); + *lastn += n; + len -= n; + } + last = -1; + while(len > 128) { + int n = min(len, 128); + *t++ = 0; + *t++ = v + n - 1; + len -= n; + } + if(len) { + *t++ = 0; + last = val; + lastn = t; + *t++ = v + len - 1; + } +} + +void ClipFiller::Render(int val, int len) +{ + if(val == 256) { + Span(256, len); + empty = false; + } + else { + full = false; + if(val == 0) + Span(0, len); + else { + memset(t, val, len); + t += len; + empty = false; + last = -1; + } + } + x += len; +} + +void ClipFiller::Render(int val) +{ + Render(val, 1); +} + +void ClipFiller::Finish(ClipLine& cl) +{ + if(empty) + return; + while(x < cx) { + int n = min(cx - x, 128); + *t++ = 0; + *t++ = n - 1; + x += n; + full = false; + } + if(full) + cl.SetFull(); + else + cl.Set(~buffer, t - ~buffer); +} + +void MaskFillerFilter::Render(int val) +{ + for(;;) { + if(empty) { + t->Render(0); + empty--; + return; + } + if(full) { + t->Render(val); + full--; + return; + } + byte m = *mask++; + if(m) { + t->Render(val * m >> 8); + return; + } + m = *mask++; + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } +} + +void MaskFillerFilter::Render(int val, int len) +{ + while(len) + if(empty) { + int n = min(len, empty); + t->Render(0, n); + empty -= n; + len -= n; + } + else + if(full) { + int n = min(len, full); + t->Render(val, n); + full -= n; + len -= n; + } + else { + byte m = *mask++; + if(m) { + t->Render(val * m >> 8); + len--; + } + else { + m = *mask++; + if(m < 128) + empty = m + 1; + else + full = m - 128 + 1; + } + } +} + +struct NilFiller : Rasterizer::Filler { + void Start(int minx, int maxx) {} + void Render(int val, int len) {} + void Render(int val) {} +}; + +void MaskFillerFilter::Start(int minx, int maxx) +{ + t->Start(minx, maxx); + Rasterizer::Filler *h = t; + NilFiller nil; + t = &nil; + Render(0, minx); + t = h; +} + +void NoAAFillerFilter::Start(int minx, int maxx) +{ + t->Start(minx, maxx); +} + +void NoAAFillerFilter::Render(int val, int len) +{ + t->Render(val < 128 ? 0 : 256, len); +} + +void NoAAFillerFilter::Render(int val) +{ + t->Render(val < 128 ? 0 : 256); +} + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Fillers.h b/uppdev/Painter/Fillers.h new file mode 100644 index 000000000..f1dc16062 --- /dev/null +++ b/uppdev/Painter/Fillers.h @@ -0,0 +1,70 @@ +NAMESPACE_UPP + +struct SolidFiller : Rasterizer::Filler { + RGBA *t; + RGBA c; + + void Start(int minx, int maxx); + void Render(int val); + void Render(int val, int len); +}; + +struct SpanFiller : Rasterizer::Filler { + RGBA *t; + const RGBA *s; + int y; + RGBA *buffer; + SpanSource *ss; + int alpha; + + void Start(int minx, int maxx); + void Render(int val); + void Render(int val, int len); +}; + +struct ClipFiller : Rasterizer::Filler { + Buffer buffer; + byte *t; + int x; + int cx; + int last; + byte *lastn; + bool empty; + bool full; + + void Span(int c, int len); + + virtual void Render(int val); + virtual void Render(int val, int len); + virtual void Start(int x, int len); + + void Clear(); + void Finish(ClipLine& cl); + + ClipFiller(int cx); +}; + +struct MaskFillerFilter : Rasterizer::Filler { + Rasterizer::Filler *t; + const byte *mask; + int empty; + int full; + + void Start(int minx, int maxx); + void Render(int val, int len); + void Render(int val); + + void Set(Rasterizer::Filler *f, const byte *m) { t = f; mask = m; empty = full = 0; } +}; + +struct NoAAFillerFilter : Rasterizer::Filler { + Rasterizer::Filler *t; + + void Start(int minx, int maxx); + void Render(int val, int len); + void Render(int val); + + void Set(Rasterizer::Filler *f) { t = f; } +}; + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/FontWin32.cpp b/uppdev/Painter/FontWin32.cpp index ef212462c..5bf2bb487 100644 --- a/uppdev/Painter/FontWin32.cpp +++ b/uppdev/Painter/FontWin32.cpp @@ -93,7 +93,7 @@ struct sMakeCharOutline : LRUCache::Maker { } }; -void Painter::CharacterOp(double x, double y, int ch, Font fnt) +void Painter::CharacterOp(const Pointf& p, int ch, Font fnt) { PAINTER_TIMING("CharacterOp"); String s; @@ -105,7 +105,7 @@ void Painter::CharacterOp(double x, double y, int ch, Font fnt) h.fc.chr = ch; s = cache.Get(h); } - RenderCharPath(s, s.GetLength(), *this, x, y + fnt.Info().GetAscent()); + RenderCharPath(s, s.GetLength(), *this, p.x, p.y + fnt.Info().GetAscent()); EvenOdd(true); } diff --git a/uppdev/Painter/FontX11.cpp b/uppdev/Painter/FontX11.cpp index 827722fbf..f6587fc64 100644 --- a/uppdev/Painter/FontX11.cpp +++ b/uppdev/Painter/FontX11.cpp @@ -1,152 +1,152 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.4 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all coM_PIes. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -// Recycled for U++ by Miroslav Fidler 2008 - -#include "Painter.h" - -NAMESPACE_UPP - -#ifdef PLATFORM_X11 - -static inline double ft_dbl(int p) -{ - return double(p) / 64.0; -} - -bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy) -{ - FT_Vector v_last; - FT_Vector v_control; - FT_Vector v_start; - double x1, y1, x2, y2, x3, y3; - FT_Vector* point; - FT_Vector* limit; - char* tags; - int n; // index of contour in outline - char tag; // current point's state - int first = 0; // index of first point in contour - for(n = 0; n < outline.n_contours; n++) { - int last = outline.contours[n]; - limit = outline.points + last; - v_start = outline.points[first]; - v_last = outline.points[last]; - v_control = v_start; - point = outline.points + first; - tags = outline.tags + first; - tag = FT_CURVE_TAG(tags[0]); - if(tag == FT_CURVE_TAG_CUBIC) return false; - if(tag == FT_CURVE_TAG_CONIC) { - if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { - // start at last point if it is on the curve - v_start = v_last; - limit--; - } - else { - // if both first and last points are conic, - // start at their middle and record its position - // for closure - v_start.x = (v_start.x + v_last.x) / 2; - v_start.y = (v_start.y + v_last.y) / 2; - v_last = v_start; - } - point--; - tags--; - } - path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); - while(point < limit) { - point++; - tags++; - - tag = FT_CURVE_TAG(tags[0]); - switch(tag) { - case FT_CURVE_TAG_ON: - path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy); - continue; - case FT_CURVE_TAG_CONIC: - v_control.x = point->x; - v_control.y = point->y; - Do_Conic: - if(point < limit) { - FT_Vector vec; - FT_Vector v_middle; - point++; - tags++; - tag = FT_CURVE_TAG(tags[0]); - vec.x = point->x; - vec.y = point->y; - if(tag == FT_CURVE_TAG_ON) { - path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, - ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); - continue; - } - if(tag != FT_CURVE_TAG_CONIC) return false; - v_middle.x = (v_control.x + vec.x) / 2; - v_middle.y = (v_control.y + vec.y) / 2; - path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, - ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy); - v_control = vec; - goto Do_Conic; - } - path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, - ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); - goto Close; - - default: - FT_Vector vec1, vec2; - if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) - return false; - vec1.x = point[0].x; - vec1.y = point[0].y; - vec2.x = point[1].x; - vec2.y = point[1].y; - point += 2; - tags += 2; - if(point <= limit) { - FT_Vector vec; - vec.x = point->x; - vec.y = point->y; - path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, - ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, - ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); - continue; - } - path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, - ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, - ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); - goto Close; - } - } - Close: - path.Close(); - first = last + 1; - } - return true; -} - -void Painter::CharacterOp(double x, double y, int ch, Font fnt) -{ - PAINTER_TIMING("CharacterOp"); - FontInfo fi = fnt.Info(); - FT_Face face = XftLockFace(fi.GetXftFont()); - int glyph_index = FT_Get_Char_Index(face, ch); - if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) - RenderOutline(face->glyph->outline, *this, x, y + fnt.Info().GetAscent()); - XftUnlockFace(fi.GetXftFont()); -} - -#endif - -END_UPP_NAMESPACE +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all coM_PIes. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +// Recycled for U++ by Miroslav Fidler 2008 + +#include "Painter.h" + +NAMESPACE_UPP + +#ifdef PLATFORM_X11 + +static inline double ft_dbl(int p) +{ + return double(p) / 64.0; +} + +bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy) +{ + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + double x1, y1, x2, y2, x3, y3; + FT_Vector* point; + FT_Vector* limit; + char* tags; + int n; // index of contour in outline + char tag; // current point's state + int first = 0; // index of first point in contour + for(n = 0; n < outline.n_contours; n++) { + int last = outline.contours[n]; + limit = outline.points + last; + v_start = outline.points[first]; + v_last = outline.points[last]; + v_control = v_start; + point = outline.points + first; + tags = outline.tags + first; + tag = FT_CURVE_TAG(tags[0]); + if(tag == FT_CURVE_TAG_CUBIC) return false; + if(tag == FT_CURVE_TAG_CONIC) { + if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { + // start at last point if it is on the curve + v_start = v_last; + limit--; + } + else { + // if both first and last points are conic, + // start at their middle and record its position + // for closure + v_start.x = (v_start.x + v_last.x) / 2; + v_start.y = (v_start.y + v_last.y) / 2; + v_last = v_start; + } + point--; + tags--; + } + path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); + while(point < limit) { + point++; + tags++; + + tag = FT_CURVE_TAG(tags[0]); + switch(tag) { + case FT_CURVE_TAG_ON: + path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy); + continue; + case FT_CURVE_TAG_CONIC: + v_control.x = point->x; + v_control.y = point->y; + Do_Conic: + if(point < limit) { + FT_Vector vec; + FT_Vector v_middle; + point++; + tags++; + tag = FT_CURVE_TAG(tags[0]); + vec.x = point->x; + vec.y = point->y; + if(tag == FT_CURVE_TAG_ON) { + path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, + ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); + continue; + } + if(tag != FT_CURVE_TAG_CONIC) return false; + v_middle.x = (v_control.x + vec.x) / 2; + v_middle.y = (v_control.y + vec.y) / 2; + path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, + ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy); + v_control = vec; + goto Do_Conic; + } + path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, + ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); + goto Close; + + default: + FT_Vector vec1, vec2; + if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) + return false; + vec1.x = point[0].x; + vec1.y = point[0].y; + vec2.x = point[1].x; + vec2.y = point[1].y; + point += 2; + tags += 2; + if(point <= limit) { + FT_Vector vec; + vec.x = point->x; + vec.y = point->y; + path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, + ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, + ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); + continue; + } + path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, + ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, + ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); + goto Close; + } + } + Close: + path.Close(); + first = last + 1; + } + return true; +} + +void Painter::CharacterOp(const Pointf& p, int ch, Font fnt) +{ + PAINTER_TIMING("CharacterOp"); + FontInfo fi = fnt.Info(); + FT_Face face = XftLockFace(fi.GetXftFont()); + int glyph_index = FT_Get_Char_Index(face, ch); + if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) + RenderOutline(face->glyph->outline, *this, p.x, p.y + fnt.Info().GetAscent()); + XftUnlockFace(fi.GetXftFont()); +} + +#endif + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Mask.cpp b/uppdev/Painter/Mask.cpp index 127bc285c..b18eee9bb 100644 --- a/uppdev/Painter/Mask.cpp +++ b/uppdev/Painter/Mask.cpp @@ -2,164 +2,81 @@ NAMESPACE_UPP -ClipFiller::ClipFiller(int _cx) +void BufferPainter::BeginMaskOp() { - cx = _cx; - buffer.Alloc(2 * cx + 2); + attr.mask = true; + Size sz = ib.GetSize(); + mask.Add() = ib; + ib.Create(sz); + Clear(RGBAZero()); + Begin(); } -void ClipFiller::Clear() +static inline byte *sSpan(byte *t, int c, int& len) { - t = ~buffer; - x = 0; - empty = true; - full = true; - last = -1; -} - -void ClipFiller::Start(int xmin, int xmax) -{ - Render(0, xmin); -} - -void ClipFiller::Span(int val, int len) -{ - int v = val >> 1; - if(last == val) { - int n = min(v + 128 - *lastn - 1, len); - *lastn += n; - len -= n; - } - last = -1; while(len > 128) { int n = min(len, 128); *t++ = 0; - *t++ = v + n - 1; + *t++ = c + n - 1; len -= n; } if(len) { *t++ = 0; - last = val; - lastn = t; - *t++ = v + len - 1; + *t++ = c + len - 1; + len = 0; } + return t; } -void ClipFiller::Render(int val, int len) +void BufferPainter::FinishMask() { - if(val == 256) { - Span(256, len); - empty = false; + Buffer wb(2 * ib.GetWidth()); + bool creating = false; + if(!attr.hasclip) { + clip.Add().Alloc(ib.GetHeight()); + attr.hasclip = true; + attr.cliplevel = clip.GetCount(); + creating = true; } - else { - full = false; - if(val == 0) - Span(0, len); - else { - memset(t, val, len); - t += len; - empty = false; - last = -1; - } - } - x += len; -} - -void ClipFiller::Render(int val) -{ - Render(val, 1); -} - -void ClipFiller::Finish(ClipLine& cl) -{ - if(empty) - return; - while(x < cx) { - int n = min(cx - x, 128); - *t++ = 0; - *t++ = n - 1; - x += n; - full = false; - } - if(full) - cl.SetFull(); - else - cl.Set(~buffer, t - ~buffer); -} - -void MaskFillerFilter::Render(int val) -{ - for(;;) { - if(empty) { - t->Render(0); - empty--; - return; - } - if(full) { - t->Render(val); - full--; - return; - } - byte m = *mask++; - if(m) { - t->Render(val * m >> 8); - return; - } - m = *mask++; - if(m < 128) - empty = m + 1; - else - full = m - 128 + 1; - } -} - -void MaskFillerFilter::Render(int val, int len) -{ - while(len) - if(empty) { - int n = min(len, empty); - t->Render(0, n); - empty -= n; - len -= n; - } - else - if(full) { - int n = min(len, full); - t->Render(val, n); - full -= n; - len -= n; - } - else { - byte m = *mask++; - if(m) { - int r = val * m >> 8; - t->Render(r); - len--; - } - else { - m = *mask++; - if(m < 128) - empty = m + 1; + Buffer& cl = clip.Top(); + for(int y = 0; y < ib.GetHeight(); y++) + if(creating || !cl[y].IsEmpty()) { + bool full = true; + bool empty = true; + int c0 = 0; + int c256 = 0; + const RGBA *s = ib[y]; + const RGBA *e = ib[y] + ib.GetWidth(); + byte *t = wb; + while(s < e) { + int val = s->a * (56 * s->r + 183 * s->g + 20 * s->b) >> 16; + if(val == 0) { + if(c256) t = sSpan(t, 128, c256); + c0++; + full = false; + } else - full = m - 128 + 1; + if(val == 256) { + if(c0) t = sSpan(t, 0, c0); + c256++; + empty = false; + } + else { + if(c256) t = sSpan(t, 128, c256); + if(c0) t = sSpan(t, 0, c0); + *t++ = val; + full = empty = false; + } + s++; } + if(c256) t = sSpan(t, 128, c256); + if(c0) t = sSpan(t, 0, c0); + cl[y].Clear(); + cl[y].Set(~wb, t - ~wb); } -} - -struct NilFiller : Rasterizer::Filler { - void Start(int minx, int maxx) {} - void Render(int val, int len) {} - void Render(int val) {} -}; - -void MaskFillerFilter::Start(int minx, int maxx) -{ - t->Start(minx, maxx); - Rasterizer::Filler *h = t; - NilFiller nil; - t = &nil; - Render(0, minx); - t = h; + ib = mask.Top(); + mask.Drop(); + attr.mask = false; } END_UPP_NAMESPACE diff --git a/uppdev/Painter/PaintPainting.icpp b/uppdev/Painter/PaintPainting.icpp new file mode 100644 index 000000000..f543762a5 --- /dev/null +++ b/uppdev/Painter/PaintPainting.icpp @@ -0,0 +1,260 @@ +#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; + 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_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_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_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_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_NOAA: + NoAAOp(ss.Get()); + 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; + } + } +} + +void PaintImageBufferPaintingFn(ImageBuffer& ib, const Painting& p, Size sz, Point pos, bool noaa) +{ + BufferPainter sw(ib); + sw.NoAA(noaa); + 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, bool noaa) +{ + BufferPainter sw(ib); + sw.NoAA(noaa); + 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, bool noaa), + void (*iw)(ImageBuffer& ib, const Drawing& p, bool noaa)); + + +INITBLOCK +{ + RegisterPaintingFns__(PaintImageBufferPaintingFn, PaintImageBufferDrawingFn); +} + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Painter.cpp b/uppdev/Painter/Painter.cpp index c933d6815..6c81e1acd 100644 --- a/uppdev/Painter/Painter.cpp +++ b/uppdev/Painter/Painter.cpp @@ -362,6 +362,64 @@ Painter& Painter::Dash(const char *dash, double start) return *this; } +Painter& Painter::Character(double x, double y, int ch, Font fnt) +{ + return Character(Pointf(x, y), ch, fnt); +} + +void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, double *dx) +{ + FontInfo fi = fnt.Info(); + double x = p.x; + while(n) { + int ch = *text++; + Character(x, p.y, ch, fnt); + Div(); + if(dx) + x += *dx++; + else + x += fi[ch]; + n--; + } +} + +Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, double *dx) +{ + return Text(Pointf(x, y), text, fnt, n < 0 ? wstrlen(text) : n, dx); +} + +Painter& Painter::Text(const Pointf& p, const WString& s, Font fnt, double *dx) +{ + return Text(p, ~s, fnt, s.GetLength(), dx); +} + +Painter& Painter::Text(double x, double y, const WString& s, Font fnt, double *dx) +{ + return Text(Pointf(x, y), s, fnt, dx); +} + +Painter& Painter::Text(const Pointf& p, const String& s, Font fnt, double *dx) +{ + return Text(p, s.ToWString(), fnt, dx); +} + +Painter& Painter::Text(double x, double y, const String& s, Font fnt, double *dx) +{ + return Text(Pointf(x, y), s, fnt, dx); +} + +Painter& Painter::Text(const Pointf& p, const char *text, Font fnt, int n, double *dx) +{ + if(n < 0) + n = strlen(text); + return Text(p, ToUnicode(text, n, CHARSET_DEFAULT), fnt, n, dx); +} + +Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, double *dx) +{ + return Text(Pointf(x, y), text, fnt, n, dx); +} + Painter& Painter::Rectangle(double x, double y, double cx, double cy) { return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close(); diff --git a/uppdev/Painter/Painter.h b/uppdev/Painter/Painter.h index 2cc7227ee..bc4aefc1a 100644 --- a/uppdev/Painter/Painter.h +++ b/uppdev/Painter/Painter.h @@ -58,7 +58,31 @@ enum { GRADIENT_REFLECT = 2, }; -class Painter { +class Painter : public Draw { +public: + void OffsetOp(Point p); + void RectPath(int x, int y, int cx, int cy); + void RectPath(const Rect& r); + bool ClipOp(const Rect& r); + bool ClipoffOp(const Rect& r); + bool ExcludeClipOp(const Rect& r); + bool IntersectClipOp(const Rect& r); + Rect GetClipOp() const; + bool IsPaintingOp(const Rect& r) const; + void DrawRectOp(int x, int y, int cx, int cy, Color color); + void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + void DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, + int count_count, int width, Color color, Color doxor); + void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, + const int *disjunct_polygon_counts, int dpcc, Color color, + int width, Color outline, uint64 pattern, Color doxor); + void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx); + void DrawPaintingOp(const Rect& target, const Painting& p); + protected: virtual void ClearOp(const RGBA& color) = 0; @@ -93,8 +117,9 @@ protected: virtual void ClipOp() = 0; - virtual void CharacterOp(double x, double y, int ch, Font fnt); - virtual void TextOp(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL); + virtual void CharacterOp(const Pointf& p, int ch, Font fnt); + virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1, + double *dx = NULL); virtual void ColorStopOp(double pos, const RGBA& color) = 0; virtual void ClearStopsOp() = 0; @@ -112,6 +137,8 @@ protected: virtual void BeginOp() = 0; virtual void EndOp() = 0; + virtual void BeginMaskOp() = 0; + protected: Pointf ReadPoint(CParser& p); @@ -219,15 +246,22 @@ public: Painter& Clip(); + Painter& Character(const Pointf& p, int ch, Font fnt); Painter& Character(double x, double y, int ch, Font fnt); + Painter& Text(const Pointf& p, const wchar *text, Font fnt, int n = -1, double *dx = NULL); Painter& Text(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL); + Painter& Text(const Pointf& p, const WString& s, Font fnt, double *dx = NULL); Painter& Text(double x, double y, const WString& s, Font fnt, double *dx = NULL); + Painter& Text(const Pointf& p, const String& s, Font fnt, double *dx = NULL); Painter& Text(double x, double y, const String& s, Font fnt, double *dx = NULL); + Painter& Text(const Pointf& p, const char *text, Font fnt, int n = -1, double *dx = NULL); Painter& Text(double x, double y, const char *text, Font fnt, int n = -1, double *dx = NULL); void Begin(); void End(); + void BeginMask(); + Painter& ColorStop(double pos, const RGBA& color); Painter& ClearStops(); Painter& Opacity(double o); @@ -245,12 +279,15 @@ public: Painter& Scale(double scalex, double scaley); Painter& Scale(double scale); + void Paint(const Painting& p); + Painter& Rectangle(double x, double y, double cx, double cy); Painter& Ellipse(double x, double y, double rx, double ry); Painter& Circle(double x, double y, double r); }; #include "Painter.hpp" +#include "Painting.h" #include "BufferPainter.h" END_UPP_NAMESPACE diff --git a/uppdev/Painter/Painter.hpp b/uppdev/Painter/Painter.hpp index 0c997859a..9bb87f8eb 100644 --- a/uppdev/Painter/Painter.hpp +++ b/uppdev/Painter/Painter.hpp @@ -206,3 +206,21 @@ inline void Painter::End() { EndOp(); } + +inline void Painter::BeginMask() +{ + BeginMaskOp(); +} + +inline Painter& Painter::Character(const Pointf& p, int ch, Font fnt) +{ + CharacterOp(p, ch, fnt); + return *this; +} + +inline +Painter& Painter::Text(const Pointf& p, const wchar *text, Font fnt, int n, double *dx) +{ + TextOp(p, text, fnt, n, dx); + return *this; +} diff --git a/uppdev/Painter/Painter.upp b/uppdev/Painter/Painter.upp index 4c9aed8b0..68ca2a39a 100644 --- a/uppdev/Painter/Painter.upp +++ b/uppdev/Painter/Painter.upp @@ -9,7 +9,10 @@ file PainterPath.cpp, FontWin32.cpp optimize_speed, FontX11.cpp optimize_speed, - Text.cpp, + DrawOp.cpp, + Painting.h, + Painting.cpp, + PaintPainting.icpp, BufferPainter.h, Math.cpp, Xform2D.cpp, @@ -20,12 +23,13 @@ file Interpolator.cpp optimize_speed, Rasterizer.cpp optimize_speed, RasterizerClip.cpp optimize_speed, - Filler.cpp optimize_speed, - Mask.cpp, Path.cpp optimize_speed, Context.cpp, + Fillers.h, + Fillers.cpp optimize_speed, Render.cpp optimize_speed, Image.cpp optimize_speed, + Mask.cpp optimize_speed, Gradient.cpp optimize_speed, RadialGradient.cpp optimize_speed; diff --git a/uppdev/Painter/Painting.cpp b/uppdev/Painter/Painting.cpp new file mode 100644 index 000000000..eb8755fe4 --- /dev/null +++ b/uppdev/Painter/Painting.cpp @@ -0,0 +1,276 @@ +#include "Painter.h" + +NAMESPACE_UPP + +void PaintingPainter::ClearOp(const RGBA& color) +{ + Put(PAINTING_CLEAR); + Put(color); +} + +void PaintingPainter::MoveOp(const Pointf& p, bool rel) +{ + Put(PAINTING_MOVE + rel); + Putf(p); +} + +void PaintingPainter::LineOp(const Pointf& p, bool rel) +{ + Put(PAINTING_LINE + rel); + Putf(p); +} + +void PaintingPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel) +{ + Put(PAINTING_QUADRATIC + rel); + Putf(p1); + Putf(p); +} + +void PaintingPainter::QuadraticOp(const Pointf& p, bool rel) +{ + Put(PAINTING_QUADRATIC_S + rel); + Putf(p); +} + +void PaintingPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) +{ + Put(PAINTING_CUBIC + rel); + Putf(p1); + Putf(p2); + Putf(p); +} + +void PaintingPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel) +{ + Put(PAINTING_CUBIC_S + rel); + Putf(p2); + Putf(p); +} + +void PaintingPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) +{ + Put(PAINTING_ARC + rel); + Putf(c); + Putf(r); + Putf(angle); + Putf(sweep); +} + +void PaintingPainter::CloseOp() +{ + Put(PAINTING_CLOSE); +} + +void PaintingPainter::DivOp() +{ + Put(PAINTING_DIV); +} + +void PaintingPainter::FillOp(const RGBA& color) +{ + Put(PAINTING_FILL_SOLID); + Put(color); +} + +void PaintingPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags) +{ + Put(PAINTING_FILL_IMAGE); + Putf(transsrc); + Put(flags); + data.Add(image); +} + +void PaintingPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, + const RGBA& color2, int style) +{ + Put(PAINTING_FILL_GRADIENT); + Putf(p1); + Put(color1); + Putf(p2); + Put(color2); + Put(style); +} + +void PaintingPainter::FillOp(const Pointf& f, const RGBA& color1, + const Pointf& p, double r, const RGBA& color2, int style) +{ + Put(PAINTING_FILL_RADIAL); + Putf(f); + Put(color1); + Putf(p); + Putf(r); + Put(color2); + Put(style); +} + +void PaintingPainter::StrokeOp(double width, const RGBA& color) +{ + Put(PAINTING_STROKE_SOLID); + Putf(width); + Put(color); +} + +void PaintingPainter::StrokeOp(double width, const Image& image, + const Xform2D& transsrc, dword flags) +{ + Put(PAINTING_STROKE_IMAGE); + Putf(width); + Putf(transsrc); + Put(flags); + data.Add(image); +} + +void PaintingPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, + const Pointf& p2, const RGBA& color2, int style) +{ + Put(PAINTING_STROKE_GRADIENT); + Putf(width); + Putf(p1); + Put(color1); + Putf(p2); + Put(color2); + Put(style); +} + +void PaintingPainter::StrokeOp(double width, const Pointf& f, + const RGBA& color1, const Pointf& p, double r, + const RGBA& color2, int style) +{ + Put(PAINTING_STROKE_RADIAL); + Putf(width); + Putf(f); + Put(color1); + Putf(p); + Putf(r); + Put(color2); + Put(style); +} + +void PaintingPainter::ClipOp() +{ + Put(PAINTING_CLIP); +} + +void PaintingPainter::CharacterOp(const Pointf& p, int ch, Font fnt) +{ + Put(PAINTING_CHARACTER); + Putf(p); + Put32(ch); + Put(fnt); +} + +void PaintingPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, double *dx) +{ + Put(PAINTING_TEXT); + Putf(p); + Put32(n); + Put((bool)dx); + Put(fnt); + for(int i = 0; i < n; i++) { + Put32(text[i]); + if(dx) + Putf(dx[i]); + } +} + +void PaintingPainter::ColorStopOp(double pos, const RGBA& color) +{ + Put(PAINTING_COLORSTOP); + Putf(pos); + Put(color); +} + +void PaintingPainter::ClearStopsOp() +{ + Put(PAINTING_CLEARSTOPS); +} + +void PaintingPainter::OpacityOp(double o) +{ + Put(PAINTING_OPACITY); + Putf(o); +} + +void PaintingPainter::LineCapOp(int linecap) +{ + Put(PAINTING_LINECAP); + Put(linecap); +} + +void PaintingPainter::LineJoinOp(int linejoin) +{ + Put(PAINTING_LINEJOIN); + Put(linejoin); +} + +void PaintingPainter::MiterLimitOp(double l) +{ + Put(PAINTING_MITERLIMIT); + Putf(l); +} + +void PaintingPainter::EvenOddOp(bool evenodd) +{ + Put(PAINTING_EVENODD); + Put(evenodd); +} + +void PaintingPainter::DashOp(const Vector& dash, double start) +{ + Put(PAINTING_DASH); + Put32(dash.GetCount()); + for(int i = 0; i < dash.GetCount(); i++) + Putf(dash[i]); + Putf(start); +} + +void PaintingPainter::NoAAOp(bool noaa) +{ + Put(PAINTING_NOAA); + Put(noaa); +} + +void PaintingPainter::TransformOp(const Xform2D& m) +{ + Put(PAINTING_TRANSFORM); + Putf(m); +} + +void PaintingPainter::BeginOp() +{ + Put(PAINTING_BEGIN); +} + +void PaintingPainter::EndOp() +{ + Put(PAINTING_END); +} + +void PaintingPainter::BeginMaskOp() +{ + Put(PAINTING_BEGINMASK); +} + +Painting PaintingPainter::GetResult() +{ + Painting p; + p.cmd = cmd.GetResult(); + p.data = data; + p.size = size; + return p; +} + +void PaintingPainter::Create(double cx, double cy) +{ + cmd.Create(); + size.cx = cx; + size.cy = cy; +} + +void PaintingPainter::Create(Sizef sz) +{ + Create(sz.cx, sz.cy); +} + +END_UPP_NAMESPACE diff --git a/uppdev/Painter/Painting.h b/uppdev/Painter/Painting.h new file mode 100644 index 000000000..ae551b2bd --- /dev/null +++ b/uppdev/Painter/Painting.h @@ -0,0 +1,133 @@ +enum { + PAINTING_CLEAR, + + PAINTING_MOVE = 4, + PAINTING_MOVE_REL, + PAINTING_LINE, + PAINTING_LINE_REL, + PAINTING_QUADRATIC, + PAINTING_QUADRATIC_REL, + PAINTING_QUADRATIC_S, + PAINTING_QUADRATIC_S_REL, + PAINTING_CUBIC, + PAINTING_CUBIC_REL, + PAINTING_CUBIC_S, + PAINTING_CUBIC_S_REL, + PAINTING_ARC, + PAINTING_ARC_REL, + PAINTING_CLOSE, + PAINTING_DIV, + + PAINTING_FILL_SOLID, + PAINTING_FILL_IMAGE, + PAINTING_FILL_GRADIENT, + PAINTING_FILL_RADIAL, + + PAINTING_STROKE_SOLID, + PAINTING_STROKE_IMAGE, + PAINTING_STROKE_GRADIENT, + PAINTING_STROKE_RADIAL, + + PAINTING_CLIP, + + PAINTING_CHARACTER, + PAINTING_TEXT, + + PAINTING_COLORSTOP, + PAINTING_CLEARSTOPS, + PAINTING_OPACITY, + PAINTING_LINECAP, + PAINTING_LINEJOIN, + PAINTING_MITERLIMIT, + PAINTING_EVENODD, + PAINTING_DASH, + PAINTING_NOAA, + + PAINTING_TRANSFORM, + PAINTING_BEGIN, + PAINTING_END, + PAINTING_BEGINMASK, +}; + +class PaintingPainter : public Painter { + StringStream cmd; + ValueArray data; + Sizef size; + + void Put(int c) { cmd.Put(c); } + void Put32(int c) { cmd.Put32(c); } + void Put(const RGBA& c) { cmd.Put(&c, sizeof(RGBA)); } + void Putf(const double& d) { cmd.Put(&d, sizeof(double)); } + void Putf(const Pointf& p) { cmd.Put(&p, sizeof(p)); } + void Putf(const Xform2D& m) { cmd.Put(&m, sizeof(m)); } + void Put(const Font& f) { cmd.Put(&f, sizeof(Font)); } + +protected: + virtual void ClearOp(const RGBA& color); + + virtual void MoveOp(const Pointf& p, bool rel); + virtual void LineOp(const Pointf& p, bool rel); + virtual void QuadraticOp(const Pointf& p1, const Pointf& p, bool rel); + virtual void QuadraticOp(const Pointf& p, bool rel); + virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel); + virtual void CubicOp(const Pointf& p2, const Pointf& p, bool rel); + virtual void ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel); + virtual void CloseOp(); + virtual void DivOp(); + + virtual void FillOp(const RGBA& color); + virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags); + virtual void FillOp(const Pointf& p1, const RGBA& color1, + const Pointf& p2, const RGBA& color2, + int style); + virtual void FillOp(const Pointf& f, const RGBA& color1, + const Pointf& c, double r, const RGBA& color2, + int style); + + virtual void StrokeOp(double width, const RGBA& rgba); + virtual void StrokeOp(double width, const Image& image, const Xform2D& transsrc, + dword flags); + virtual void StrokeOp(double width, const Pointf& p1, const RGBA& color1, + const Pointf& p2, const RGBA& color2, + int style); + virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1, + const Pointf& c, double r, const RGBA& color2, + int style); + + virtual void ClipOp(); + + virtual void CharacterOp(const Pointf& p, int ch, Font fnt); + virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1, + double *dx = NULL); + + virtual void ColorStopOp(double pos, const RGBA& color); + virtual void ClearStopsOp(); + + virtual void OpacityOp(double o); + virtual void LineCapOp(int linecap); + virtual void LineJoinOp(int linejoin); + virtual void MiterLimitOp(double l); + virtual void EvenOddOp(bool evenodd); + virtual void DashOp(const Vector& dash, double start); + virtual void NoAAOp(bool noaa); + + virtual void TransformOp(const Xform2D& m); + + virtual void BeginOp(); + virtual void EndOp(); + + virtual void BeginMaskOp(); + +public: + Painting GetResult(); + operator Painting() { return GetResult(); } + + void Create(double cx, double cy); + void Create(Sizef sz); + + Sizef GetSize() const { return size; } + + PaintingPainter() {} + PaintingPainter(double cx, double cy) { Create(cx, cy); } + PaintingPainter(Sizef sz) { Create(sz); } +}; diff --git a/uppdev/Painter/Rasterizer.cpp b/uppdev/Painter/Rasterizer.cpp index 1b7634932..fe7eb37be 100644 --- a/uppdev/Painter/Rasterizer.cpp +++ b/uppdev/Painter/Rasterizer.cpp @@ -1,5 +1,7 @@ #include "Painter.h" +// The genesis of this code can be dated back to LibART + #define LLOG(x) // LOG(x) NAMESPACE_UPP diff --git a/uppdev/Painter/Render.cpp b/uppdev/Painter/Render.cpp index 9ca08c93d..be638d674 100644 --- a/uppdev/Painter/Render.cpp +++ b/uppdev/Painter/Render.cpp @@ -1,4 +1,5 @@ #include "Painter.h" +#include "Fillers.h" NAMESPACE_UPP diff --git a/uppdev/Painter/Text.cpp b/uppdev/Painter/Text.cpp deleted file mode 100644 index 7239ae405..000000000 --- a/uppdev/Painter/Text.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "Painter.h" - -NAMESPACE_UPP - -void Painter::TextOp(double x, double y, const wchar *text, Font fnt, int n, double *dx) -{ - FontInfo fi = fnt.Info(); - if(n < 0) - n = wstrlen(text); - while(n) { - int ch = *text++; - Character(x, y, ch, fnt); - Div(); - if(dx) - x += *dx++; - else - x += fi[ch]; - n--; - } -} - -Painter& Painter::Character(double x, double y, int ch, Font fnt) -{ - CharacterOp(x, y, ch, fnt); - return *this; -} - -Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, double *dx) -{ - TextOp(x, y, text, fnt, n, dx); - return *this; -} - -Painter& Painter::Text(double x, double y, const WString& s, Font fnt, double *dx) -{ - Text(x, y, s, fnt, s.GetLength(), dx); - return *this; -} - -Painter& Painter::Text(double x, double y, const String& s, Font fnt, double *dx) -{ - Text(x, y, s.ToWString(), fnt, dx); - return *this; -} - -Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, double *dx) -{ - Text(x, y, ToUnicode(text, n < 0 ? strlen(text) : n, CHARSET_DEFAULT), fnt, dx); - return *this; -} - -END_UPP_NAMESPACE diff --git a/uppdev/Painter/init b/uppdev/Painter/init index d40b5884f..c15029df4 100644 --- a/uppdev/Painter/init +++ b/uppdev/Painter/init @@ -2,4 +2,7 @@ #define _Painter_icpp_init_stub #include "Core/init" #include "CtrlLib/init" +#define BLITZ_INDEX__ F8939D4A0BC2FDAEDB6EE5CF1693AFE34 +#include "PaintPainting.icpp" +#undef BLITZ_INDEX__ #endif diff --git a/uppdev/PainterExamples/Big.cpp b/uppdev/PainterExamples/Big.cpp index 6e934eb1c..06cd3dd01 100644 --- a/uppdev/PainterExamples/Big.cpp +++ b/uppdev/PainterExamples/Big.cpp @@ -1,5 +1,7 @@ #include "Examples.h" - + +#ifndef _DEBUG + void Big(Painter& sw) { int n = 0; @@ -45,3 +47,5 @@ INITBLOCK { RegisterExample("Really Big Polygon", Big); RegisterExample("Really Big Stroke", BigStroke); } + +#endif \ No newline at end of file diff --git a/uppdev/PainterExamples/Examples.h b/uppdev/PainterExamples/Examples.h index e2cfe9c42..10f1688d3 100644 --- a/uppdev/PainterExamples/Examples.h +++ b/uppdev/PainterExamples/Examples.h @@ -23,7 +23,7 @@ struct App : TopWindow { FrameBottom< WithCtrlLayout > ctrl; typedef App CLASSNAME; - + void DoPaint0(Painter& sw); void DoPaint(Painter& sw); void Print(); diff --git a/uppdev/PainterExamples/MaskBlending.cpp b/uppdev/PainterExamples/MaskBlending.cpp index 0f0824890..1d5ccd1e8 100644 --- a/uppdev/PainterExamples/MaskBlending.cpp +++ b/uppdev/PainterExamples/MaskBlending.cpp @@ -1,7 +1,5 @@ #include "Examples.h" -#if 0 - void MaskBlending(Painter& sw) { const char *txt = "This is just a test of alpha mask blending"; @@ -25,5 +23,3 @@ void MaskBlending(Painter& sw) INITBLOCK { RegisterExample("Blending using alpha mask", MaskBlending); } - -#endif diff --git a/uppdev/PainterExamples/RadialMaskBlending.cpp b/uppdev/PainterExamples/RadialMaskBlending.cpp index 32cd01bb6..887e7cb56 100644 --- a/uppdev/PainterExamples/RadialMaskBlending.cpp +++ b/uppdev/PainterExamples/RadialMaskBlending.cpp @@ -1,7 +1,5 @@ #include "Examples.h" -#if 0 - void RadialMaskBlending(Painter& sw) { const char *txt = "This is just a test of radial mask blending"; @@ -31,5 +29,3 @@ void RadialMaskBlending(Painter& sw) INITBLOCK { RegisterExample("Blending using radial alpha mask", RadialMaskBlending); } - -#endif diff --git a/uppdev/PainterExamples/RichText.cpp b/uppdev/PainterExamples/RichText.cpp index 1989eaa04..50e1eaf45 100644 --- a/uppdev/PainterExamples/RichText.cpp +++ b/uppdev/PainterExamples/RichText.cpp @@ -1,7 +1,5 @@ #include "Examples.h" -#if 0 - void RichTextExample(Painter& sw) { const char *qtf = @@ -79,5 +77,3 @@ INITBLOCK { RegisterExample("RichText", RichTextExample); } - -#endif diff --git a/uppdev/PainterExamples/main.cpp b/uppdev/PainterExamples/main.cpp index 1b9cb1ddc..1f3551856 100644 --- a/uppdev/PainterExamples/main.cpp +++ b/uppdev/PainterExamples/main.cpp @@ -40,26 +40,22 @@ void App::DoPaint0(Painter& sw) void App::DoPaint(Painter& sw) { -#if 0 if(ctrl.painting) { PaintingPainter h(2000, 2000); DoPaint0(h); sw.Paint(h); } else -#endif DoPaint0(sw); } void App::Print() { -#if 0 PaintingPainter sw(1000, 1000); DoPaint(sw); PrinterJob pb; if(pb.Execute()) pb.GetDraw().DrawPainting(0, 0, 4000, 4000, sw); -#endif } void App::Benchmark() diff --git a/uppdev/plugin/png/png.upp b/uppdev/plugin/png/png.upp index 4a0ef7d0e..8d024d216 100644 --- a/uppdev/plugin/png/png.upp +++ b/uppdev/plugin/png/png.upp @@ -1,60 +1,60 @@ -description "PNG image file format U++ encapsulation"; - -uses - Core, - Draw; - -library(!WIN32) png; - -options - -DPNG_NO_READ_SHIFT, - -DPNG_NO_READ_SWAP, - -DPNG_NO_READ_INVERT, - -DPNG_NO_READ_DITHER, - -DPNG_NO_READ_BACKGROUND, - -DPNG_NO_READ_GAMMA, - -DPNG_NO_READ_SWAP_ALPHA, - -DPNG_NO_READ_INVERT_ALPHA, - -DPNG_NO_READ_STRIP_ALPHA, - -DPNG_NO_READ_USER_TRANSFORM, - -DPNG_NO_READ_RGB_TO_GRAY, - -DPNG_NO_PROGRESSIVE_READ, - -DPNG_NO_READ_COMPOSITE_NODIV, - -DPNG_NO_MNG_FEATURES, - -DPNG_NO_READ_EMPTY_PLTE, - -DPNG_NO_WRITE_SHIFT, - -DPNG_NO_WRITE_PACK, - -DPNG_NO_WRITE_SWAP, - -DPNG_NO_WRITE_PACKSWAP, - -DPNG_NO_WRITE_INVERT, - -DPNG_NO_WRITE_FILLER, - -DPNG_NO_WRITE_SWAP_ALPHA, - -DPNG_NO_WRITE_INVERT_ALPHA, - -DPNG_NO_USER_TRANSFORM_PTR, - -DPNG_NO_WRITE_EMPTY_PLTE, - -DPNG_NO_EASY_ACCESS, - -DPNG_NO_READ_bKGD, - -DPNG_NO_READ_cHRM, - -DPNG_NO_READ_gAMA, - -DPNG_NO_READ_iCCP, - -DPNG_NO_READ_oFFs, - -DPNG_NO_READ_pCAL, - -DPNG_NO_READ_sCAL, - -DPNG_NO_READ_sBIT, - -DPNG_NO_READ_sPLT, - -DPNG_NO_READ_sRGB, - -DPNG_NO_READ_tIME, - -DPNG_NO_READ_zTXt, - -DPNG_NO_READ_OPT_PLTE, - -DPNG_NO_INFO_IMAGE; - -options(MSC8ARM) "-D_WIN32_WCE -DARM -D_ARM_ -DUNDER_CE -DUNICODE -D_UNICODE"; - -file - png.h, - pnglib.c, - pngupp.cpp, - pngreg.icpp, - Info readonly separator, - Copying; - +description "PNG image file format U++ encapsulation"; + +uses + Core, + Draw; + +library(!WIN32) png; + +options + -DPNG_NO_READ_SHIFT, + -DPNG_NO_READ_SWAP, + -DPNG_NO_READ_INVERT, + -DPNG_NO_READ_DITHER, + -DPNG_NO_READ_BACKGROUND, + -DPNG_NO_READ_GAMMA, + -DPNG_NO_READ_SWAP_ALPHA, + -DPNG_NO_READ_INVERT_ALPHA, + -DPNG_NO_READ_STRIP_ALPHA, + -DPNG_NO_READ_USER_TRANSFORM, + -DPNG_NO_READ_RGB_TO_GRAY, + -DPNG_NO_PROGRESSIVE_READ, + -DPNG_NO_READ_COMPOSITE_NODIV, + -DPNG_NO_MNG_FEATURES, + -DPNG_NO_READ_EMPTY_PLTE, + -DPNG_NO_WRITE_SHIFT, + -DPNG_NO_WRITE_PACK, + -DPNG_NO_WRITE_SWAP, + -DPNG_NO_WRITE_PACKSWAP, + -DPNG_NO_WRITE_INVERT, + -DPNG_NO_WRITE_FILLER, + -DPNG_NO_WRITE_SWAP_ALPHA, + -DPNG_NO_WRITE_INVERT_ALPHA, + -DPNG_NO_USER_TRANSFORM_PTR, + -DPNG_NO_WRITE_EMPTY_PLTE, + -DPNG_NO_EASY_ACCESS, + -DPNG_NO_READ_bKGD, + -DPNG_NO_READ_cHRM, + -DPNG_NO_READ_gAMA, + -DPNG_NO_READ_iCCP, + -DPNG_NO_READ_oFFs, + -DPNG_NO_READ_pCAL, + -DPNG_NO_READ_sCAL, + -DPNG_NO_READ_sBIT, + -DPNG_NO_READ_sPLT, + -DPNG_NO_READ_sRGB, + -DPNG_NO_READ_tIME, + -DPNG_NO_READ_zTXt, + -DPNG_NO_READ_OPT_PLTE, + -DPNG_NO_INFO_IMAGE; + +options(MSC8ARM) "-D_WIN32_WCE -DARM -D_ARM_ -DUNDER_CE -DUNICODE -D_UNICODE"; + +file + png.h, + pnglib.c, + pngupp.cpp, + pngreg.icpp, + Info readonly separator, + Copying; +