#ifndef _ScanLine_ScanLine_h_ #define _ScanLine_ScanLine_h_ #include using namespace Upp; #define PAINTER_TIMING(x) // RTIMING(x) inline RGBA Mul8(const RGBA& s, int mul) { RGBA t; t.r = (mul * s.r) >> 8; t.g = (mul * s.g) >> 8; t.b = (mul * s.b) >> 8; t.a = (mul * s.a) >> 8; return t; } inline void AlphaBlend(RGBA& t, const RGBA& c) { int alpha = 256 - (c.a + (c.a >> 7)); t.r = c.r + (alpha * t.r >> 8); t.g = c.g + (alpha * t.g >> 8); t.b = c.b + (alpha * t.b >> 8); t.a = c.a + (alpha * t.a >> 8); } inline void AlphaBlendCover8(RGBA& t, const RGBA& c, int cover) { int a = c.a * cover >> 8; int alpha = 256 - (a + (a >> 7)); t.r = (c.r * cover >> 8) + (alpha * t.r >> 8); t.g = (c.g * cover >> 8) + (alpha * t.g >> 8); t.b = (c.b * cover >> 8) + (alpha * t.b >> 8); t.a = a + (alpha * t.a >> 8); } struct ScanLine { int xmin, xmax; Buffer data; int datalen; bool IsFull(); bool IsEmpty(); String ToString() const; }; double SquareDist(const Pointf& p1, const Pointf& p2); Pointf Mid(const Pointf& a, const Pointf& b); Pointf Ortogonal(const Pointf& p); double SquareLength(const Pointf& p); double Length(const Pointf& p); double Bearing(const Pointf& p); double Distance(const Pointf& p1, const Pointf& p2); double SquareDistance(const Pointf& p1, const Pointf& p2); Pointf PolarPointf(double a); Pointf Polar(const Pointf& p, double r, double a); struct LinearPathConsumer { virtual void Move(const Pointf& p) = 0; virtual void Line(const Pointf& p) = 0; virtual void End(); }; struct LinearPathFilter : LinearPathConsumer { virtual void End(); LinearPathConsumer *target; void PutMove(const Pointf& p) { target->Move(p); } void PutLine(const Pointf& p) { target->Line(p); } void PutEnd() { target->End(); } template T& operator|(T& b) { target = &b; return b; } }; enum { LINECAP_BUTT, LINECAP_SQUARE, LINECAP_ROUND, LINEJOIN_MITER, LINEJOIN_ROUND, LINEJOIN_BEVEL, }; class Stroker : public LinearPathFilter { double w2; double qmiter; double fid; Pointf p0, v0, o0, a0, b0; Pointf p1, v1, o1, a1, b1; Pointf p2; int linecap; int linejoin; void Finish(); void Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double r); void Cap(const Pointf& p0, const Pointf& v0, const Pointf& o0, const Pointf& a0, const Pointf& b0); public: virtual void Move(const Pointf& p); virtual void Line(const Pointf& p); virtual void End(); Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin); }; struct Dasher : public LinearPathFilter { Vector pattern; int patterni; double rem; bool flag; Pointf p0; void Put(const Pointf& p); public: virtual void Move(const Pointf& p); virtual void Line(const Pointf& p); Dasher(double width, const Vector& pattern, double distance); }; void ApproximateQuadratic(LinearPathConsumer& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, double tolerance); void ApproximateCubic(LinearPathConsumer& t, const Pointf& x0, const Pointf& x1, const Pointf& x2, const Pointf& x, double tolerance); class Rasterizer : public LinearPathConsumer { public: virtual void Move(const Pointf& p); virtual void Line(const Pointf& p); private: struct Cell : MoveableWithSwap { int16 x; int16 cover; int area; bool operator<(const Cell& b) const { return x < b.x; } }; Rectf cliprect; Pointf p0; Buffer< Vector > cell; int xmax, ymax; int min_y; int max_y; Size sz; void Init(); Cell *AddCells(int y, int n); void RenderHLine(int ey, int x1, int y1, int x2, int y2); void LineClip(double x1, double y1, double x2, double y2); int CvX(double x); int CvY(double y); void CvLine(double x1, double y1, double x2, double y2); bool BeginRender(int y, const Cell *&c, const Cell *&e); public: struct Target { virtual void Start(int x, int len) = 0; virtual void Render(int val) = 0; virtual void Render(int val, int len) = 0; }; void LineRaw(int x1, int y1, int x2, int y2); void SetClip(const Rectf& rect); int MinY() const { return min_y; } int MaxY() const { return max_y; } void Render(int y, Target& g, bool evenodd); void Reset(); Rasterizer(int cx, int cy); }; void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd); struct Xform2D { Pointf x, y, t; Pointf GetScaleXY() const; double GetScale() const; bool IsRegular() const; Pointf Transform(const Pointf& f) const; static Xform2D Identity(); static Xform2D Translation(double x, double y); static Xform2D Scale(double sx, double sy); static Xform2D Scale(double scale); static Xform2D Rotation(double fi); static Xform2D Sheer(double fi); }; Xform2D operator*(const Xform2D& a, const Xform2D& b); Xform2D Inverse(const Xform2D& m); class BufferPainter { enum { MOVE, LINE, QUADRATIC, CUBIC }; struct Segment { byte kind; Pointf p; }; struct QuadraticSegment : Segment{ Pointf p1; }; struct CubicSegment : QuadraticSegment { Pointf p2; }; Vector path; template T& PathAdd() { int q = path.GetCount(); path.SetCount(q + sizeof(T)); return *(T *)&path[q]; } public: void Move(Pointf p); void Line(Pointf p); void Quadratic(Pointf p1, Pointf p); void Cubic(Pointf p1, Pointf p2, Pointf p); }; #endif