diff --git a/bazaar/GLPainter/Arc.cpp b/bazaar/GLPainter/Arc.cpp new file mode 100644 index 000000000..75e1aa8f7 --- /dev/null +++ b/bazaar/GLPainter/Arc.cpp @@ -0,0 +1,27 @@ +#include "GLPainter.h" + +namespace Upp { + +void GLDrawArc(const GLContext2D& dd, const Rectf& rc, Pointf start, Pointf end, int width, Color color, double alpha) +{ + if(rc.Width() <= 0 || rc.Height() <= 0) + return; + Sizef radius = Sizef(rc.Size()) / 2.0; + Pointf center = Pointf(rc.TopLeft()) + radius; + double ang1 = Direction((Pointf(start) - center) / radius); + double ang2 = Direction((Pointf(end) - center) / radius); + if(ang1 > ang2) + Swap(ang1, ang2); + + Vector> line; + line.Add(); + for(double a = ang1; a <= ang2 + M_PI / 200; a += M_PI / 200) { + line.Top().Add(radius * Polar(min(a, ang2)) + center); + } + + GLVertexData l; + GLPolylines(l, line); + GLDrawPolylines(dd, Pointf(0, 0), l, Sizef(1, 1), width, color, alpha); +} + +}; \ No newline at end of file diff --git a/bazaar/GLPainter/DrawGL.cpp b/bazaar/GLPainter/DrawGL.cpp new file mode 100644 index 000000000..aa09f9626 --- /dev/null +++ b/bazaar/GLPainter/DrawGL.cpp @@ -0,0 +1,216 @@ +#include "GLPainter.h" + +namespace Upp { + +void DrawGL::Init(Size sz, double alpha) +{ + Cloff& c = cloff.Add(); + c.clip = view_size = sz; + c.offset = Pointf(0.5, 0.5); + dd.Set(sz); + dd.alpha = alpha; + glEnable(GL_SCISSOR_TEST); + SyncScissor(); +} + +DrawGL::~DrawGL() +{ + glDisable(GL_SCISSOR_TEST); +} + +dword DrawGL::GetInfo() const +{ + return DRAWTEXTLINES; +} + +void DrawGL::BeginOp() +{ + Cloff c = cloff.Top(); + cloff.Add(c); +} + +bool DrawGL::ClipOp(const Rect& r) +{ + Cloff c = cloff.Top(); + Cloff& c1 = cloff.Add(); + c1.clip = c.clip & (r + c.offset); + c1.offset = c.offset; + SyncScissor(); + return !c1.clip.IsEmpty(); +} + +bool DrawGL::ClipoffOp(const Rect& r) +{ + Cloff c = cloff.Top(); + Cloff& c1 = cloff.Add(); + c1.clip = c.clip & (r + c.offset); + c1.offset = c.offset + (Pointf)r.TopLeft(); + SyncScissor(); + return !c1.clip.IsEmpty(); +} + +bool DrawGL::IntersectClipOp(const Rect& r) +{ + Cloff& c = cloff.Top(); + c.clip = c.clip & (r + c.offset); + SyncScissor(); + return !c.clip.IsEmpty(); +} + +bool DrawGL::ExcludeClipOp(const Rect& r) +{ + // does not work with DrawGL + return true; +} + +bool DrawGL::IsPaintingOp(const Rect& r) const +{ + return true; +} + +void DrawGL::OffsetOp(Point p) +{ + Cloff c = cloff.Top(); + Cloff& c1 = cloff.Add(); + c1.clip = c.clip; + c1.offset = c.offset + (Pointf)p; +} + +void DrawGL::EndOp() +{ + ASSERT(cloff.GetCount()); + if(cloff.GetCount()) + cloff.Drop(); + SyncScissor(); +} + +void DrawGL::SyncScissor() +{ + Rect clip = cloff.Top().clip; + Size sz = clip.GetSize(); + glScissor(clip.left, view_size.cy - sz.cy - clip.top, sz.cx, sz.cy); +} + +Pointf DrawGL::Offset(int x, int y) +{ + Pointf o = cloff.Top().offset; + return Pointf(x + o.x, y + o.y); +} + +Rectf DrawGL::Offset(int x, int y, int cx, int cy) +{ + Point o = cloff.Top().offset; + return RectfC(x + o.x, y + o.y, cx, cy); +} + +Rectf DrawGL::Offset(int x, int y, Size sz) +{ + return Offset(x, y, sz.cx, sz.cy); +} + +void DrawGL::SysDrawImageOp(int x, int y, const Image& img, Color color) +{ + GLDrawImage(dd, Offset(x, y, img.GetSize()), + IsNull(color) ? img : CachedSetColorKeepAlpha(img, color)); +} + +void DrawGL::SysDrawImageOp(int x, int y, const Image& img, const Rect& src, Color color) +{ + GLDrawImage(dd, Offset(x, y, img.GetSize()), IsNull(color) ? img : CachedSetColorKeepAlpha(img, color), + src); +} + +void DrawGL::DrawRectOp(int x, int y, int cx, int cy, Color color) +{ + Vector> polygon; + polygon.Add().Add(Offset(x, y)); + polygon.Top().Add(Offset(x + cx, y)); + polygon.Top().Add(Offset(x + cx, y + cy)); + polygon.Top().Add(Offset(x, y + cy)); + + GLVertexData data; + GLPolygons(data, polygon); + + GLDrawConvexPolygons(dd, Pointf(0, 0), data, Sizef(1, 1), color); +} + +void DrawGL::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) +{ + GLDrawText(dd, Offset(x, y), angle * M_2PI / 3600, text, font, ink, n, dx); +} + +void DrawGL::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) +{ + // TODO... +} + +void DrawGL::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) +{ + GLDrawEllipse(dd, Offset(r.CenterPoint()), Sizef(r.GetSize()) / 2, color, pen, pencolor); +} + +void DrawGL::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) +{ + Vector> poly; + poly.Add().Add(Offset(x1, y1)); + poly.Top().Add(Offset(x2, y2)); + + GLVertexData data; + GLPolylines(data, poly); + + GLDrawPolylines(dd, Pointf(0, 0), data, Sizef(1, 1), max(width, 1), color); +} + +void DrawGL::DoPath(Vector>& poly, const Point *pp, const Point *end) +{ + poly.Add().Add(Offset(*pp++)); + while(pp < end) + poly.Top().Add(Offset(*pp++)); +} + +void DrawGL::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor) +{ + if(vertex_count < 2 || IsNull(color)) + return; + Vector> poly; + while(--count_count >= 0) { + const Point *pp = vertices; + vertices += *counts++; + DoPath(poly, pp, vertices); + } + + GLVertexData data; + GLPolylines(data, poly); + GLDrawPolylines(dd, Pointf(0, 0), data, Sizef(1, 1), max(width, 1), color); +} + +void DrawGL::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) +{ + Vector> poly; + while(--dpcc >= 0) { + const Point *sp = vertices; + vertices += *disjunct_polygon_counts++; + while(sp < vertices) { + const Point *pp = sp; + sp += *subpolygon_counts++; + DoPath(poly, pp, sp); + } + } + + if(!IsNull(color)) { + GLVertexData data; + GLPolygons(data, poly); + GLDrawPolygons(dd, Pointf(0, 0), data, Sizef(1, 1), color); + } + if(!IsNull(outline)) { + GLVertexData data; + for(auto& pl : poly) + pl.Add(pl[0]); + GLPolylines(data, poly); + GLDrawPolylines(dd, Pointf(0, 0), data, Sizef(1, 1), max(width, 1), outline); + } +} + +}; \ No newline at end of file diff --git a/bazaar/GLPainter/Ellipse.cpp b/bazaar/GLPainter/Ellipse.cpp index 2ea9ce4a2..3b69cd50b 100644 --- a/bazaar/GLPainter/Ellipse.cpp +++ b/bazaar/GLPainter/Ellipse.cpp @@ -13,7 +13,8 @@ void GLDrawEllipse(const GLContext2D& dd, Pointf center, Sizef radius, Color fil for(int i = 0; i < N; i++) p.Top().Add(Polar(i * M_2PI / N)); GLPolygons(fill, p); - p.Add(p[0]); + Pointf f = p.Top()[0]; + p.Top().Add(f); GLPolylines(line, p); } diff --git a/bazaar/GLPainter/GLPainter.h b/bazaar/GLPainter/GLPainter.h index b59ee36e2..9f30d5222 100644 --- a/bazaar/GLPainter/GLPainter.h +++ b/bazaar/GLPainter/GLPainter.h @@ -21,7 +21,9 @@ struct GLContext2D { // TODO: This should be changed to regular matrix (later) Sizef vs; double alpha = 1; - GLContext2D(Size sz) { vs = Sizef(2.0 / sz.cx, -2.0 / sz.cy); } + void Set(Size sz) { vs = Sizef(2.0 / sz.cx, -2.0 / sz.cy); } + + GLContext2D(Size sz) { Set(sz); } GLContext2D() {} }; @@ -96,9 +98,9 @@ void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, int textureid, doub void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, const Image& img, double alpha = 1); void GLDrawImage(const GLContext2D& dd, const Rectf& rect, const Image& img, double alpha = 1); -void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, int textureid, Size tsz, const Rect& src, double alpha); -void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, const GLTexture& img, const Rect& src, double alpha); -void GLDrawImage(const GLContext2D& dd, const Rectf& rect, const Image& img, const Rect& src, double alpha); +void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, int textureid, Size tsz, const Rect& src, double alpha = 1); +void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, const GLTexture& img, const Rect& src, double alpha = 1); +void GLDrawImage(const GLContext2D& dd, const Rectf& rect, const Image& img, const Rect& src, double alpha = 1); class GLTextureDraw { GLuint framebuffer = 0; @@ -166,23 +168,24 @@ void GLDrawPolygon(Sizef vs, Point at, const GLVertexData& mesh, Sizef scale, Co template void GLPolygons(GLVertexData& mesh, const Src& polygon); -void GLDrawPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha); -void GLDrawConvexPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha); +void GLDrawPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha = 1); +void GLDrawConvexPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha = 1); template void GLPolylines(GLVertexData& data, const Src& polygon); -void GLDrawPolylines(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, double width, Color color, double alpha); +void DashPolyline(Vector>& polyline, const Vector& line, + const Vector& pattern, double distance); + +void GLDrawPolylines(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, double width, Color color, double alpha = 1); void GLDrawStencil(Color color, double alpha); void GLDrawEllipse(const GLContext2D& dd, Pointf center, Sizef radius, Color fill_color, double width = 0, Color line_color = Null, double alpha = 1); -/* -void GLDrawArc(const GLContext2D& dd, Pointf center, Sizef radius, Color color, double alpha); - virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) = 0; -*/ +void GLDrawArc(const GLContext2D& dd, const Rectf& rc, Pointf start, Pointf end, int width, + Color color, double alpha = 1); GLTexture GetGlyphGLTextureCached(double angle, int chr, Font font, Color color); @@ -191,6 +194,56 @@ void GLDrawText(const GLContext2D& dd, Pointf pos, double angle, const wchar *te #include "GLPainter.hpp" +class DrawGL : public Draw { +public: + virtual dword GetInfo() const; + + virtual void BeginOp(); + virtual bool ClipOp(const Rect& r); + virtual bool ClipoffOp(const Rect& r); + virtual bool IntersectClipOp(const Rect& r); + virtual void OffsetOp(Point p); + virtual bool ExcludeClipOp(const Rect& r); + virtual void EndOp(); + virtual bool IsPaintingOp(const Rect& r) const; + + virtual void SysDrawImageOp(int x, int y, const Image& img, Color color); + virtual void SysDrawImageOp(int x, int y, const Image& img, const Rect& src, Color color); + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); + + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx); + + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + virtual 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); + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor); + +private: + struct Cloff : Moveable { + Rect clip; + Pointf offset; + }; + + Vector cloff; + GLContext2D dd; + Size view_size; + + Pointf Offset(int x, int y); + Pointf Offset(Point p) { return Offset(p.x, p.y); } + Rectf Offset(int x, int y, int cx, int cy); + Rectf Offset(int x, int y, Size sz); + void SyncScissor(); + void DoPath(Vector>& poly, const Point *pp, const Point *end); + +public: + void Init(Size sz, double alpha = 1); + + DrawGL() {} + DrawGL(Size sz, double alpha = 1) { Init(sz, alpha); } + ~DrawGL(); +}; + }; #endif diff --git a/bazaar/GLPainter/GLPainter.hpp b/bazaar/GLPainter/GLPainter.hpp index dac109166..ebb54371a 100644 --- a/bazaar/GLPainter/GLPainter.hpp +++ b/bazaar/GLPainter/GLPainter.hpp @@ -42,7 +42,7 @@ void GLPolylines(GLVertexData& data, const Src& polygon) ndx << ii << ii + 1 << ii + 2 << ii + 3 << ii + 2 << ii + 1; - if(ii) // if line is not first, draw bevel join between current and previous line + if(i) // if line is not first, draw bevel join between current and previous line ndx << ii << ii + 1 << ii - 4 + 3 << ii - 4 + 2 << ii - 4 + 3 << ii; @@ -56,4 +56,3 @@ void GLPolylines(GLVertexData& data, const Src& polygon) data.Add(vertex, 4).Index(ndx); } - diff --git a/bazaar/GLPainter/GLPainter.upp b/bazaar/GLPainter/GLPainter.upp index 527dafd08..291adce31 100644 --- a/bazaar/GLPainter/GLPainter.upp +++ b/bazaar/GLPainter/GLPainter.upp @@ -17,6 +17,8 @@ file StencilPolygon.cpp, Line.cpp, Ellipse.cpp, + Arc.cpp, Text.cpp, + DrawGL.cpp, todo.txt; diff --git a/bazaar/GLPainter/Line.cpp b/bazaar/GLPainter/Line.cpp index 302be57d6..5f0646887 100644 --- a/bazaar/GLPainter/Line.cpp +++ b/bazaar/GLPainter/Line.cpp @@ -60,4 +60,28 @@ void GLDrawPolylines(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, } } +void DashPolyline(Vector>& polyline, const Vector& line, + const Vector& pattern, double distance = 0) +{ + struct LineStore : LinearPathConsumer { + Vector>& polyline; + + void Move(const Pointf& p) override { DLOG("MOVE " << p); polyline.Add().Add(p); } + void Line(const Pointf& p) override { DLOG("LINE " << p); polyline.Top().Add(p); } + + LineStore(Vector>& polyline) : polyline(polyline) {} + }; + + LineStore st(polyline); + Dasher dasher; + dasher.target = &st; + dasher.Init(pattern, distance); + for(int i = 0; i < line.GetCount(); i++) + if(i) + dasher.Line(line[i]); + else + dasher.Move(line[i]); + dasher.End(); +} + }; \ No newline at end of file diff --git a/bazaar/GLPainter/todo.txt b/bazaar/GLPainter/todo.txt index 49ca00360..4de1292c7 100644 --- a/bazaar/GLPainter/todo.txt +++ b/bazaar/GLPainter/todo.txt @@ -1,4 +1,13 @@ - make banded glyphs - make alpha textures - colored texture paints +- ARC +- DASHER +- optimize draw rect +- circle pen should be able to 'dash' +- arc pen should be able to 'dash' +- polygon pen should be able to 'dash' + +DONE: + - Texture change Rect -> Rectf