developing newdraw

git-svn-id: svn://ultimatepp.org/upp/trunk@1162 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-05-12 10:59:08 +00:00
parent ee152d30f4
commit 587b532024
46 changed files with 5755 additions and 81 deletions

View file

@ -37,7 +37,7 @@ bool ScreenInPaletteMode()
Size GetScreenSize()
{
return ScreenInfo().GetPagePixels();
return ScreenInfo().GetPageSize();
}
END_UPP_NAMESPACE

View file

@ -33,26 +33,24 @@ Draw::~Draw() {}
Size Draw::GetPixelsPerInch() const
{
return Dots() ? Size(600, 600) : Size(96, 96);
return IsNative() ? GetNativeDpi() : Dots() ? Size(600, 600) : Size(96, 96);
}
Size Draw::GetPageMMs() const
{
return GetPagePixels() * 254 / (10 * GetPixelsPerInch());
return GetPageSize() * 254 / (10 * GetPixelsPerInch());
}
int Draw::GetNativeX(int x) const
{
Size inchPixels = GetPixelsPerInch();
Size nativeDpi = GetNativeDpi();
return inchPixels != nativeDpi ? iscale(x, nativeDpi.cx, 600) : x;
Size sz = GetNativeDpi();
return Dots() && sz.cx != 600 ? iscale(x, sz.cx, 600) : x;
}
int Draw::GetNativeY(int y) const
{
Size inchPixels = GetPixelsPerInch();
Size nativeDpi = GetNativeDpi();
return inchPixels != nativeDpi ? iscale(y, nativeDpi.cy, 600) : y;
Size sz = GetNativeDpi();
return Dots() && sz.cx != 600 ? iscale(y, sz.cy, 600) : y;
}
void Draw::Native(int& x, int& y) const
@ -95,6 +93,8 @@ void LeaveDraw() {
sDrawLock.Leave();
}
Size Draw::GetPageSize() const { return Size(0, 0); }
void Draw::StartPage() {}
void Draw::EndPage() {}
@ -431,7 +431,7 @@ void Draw::Flush()
// ---------------------------
dword NilDraw::GetInfo() const { return DOTS; }
Size NilDraw::GetPagePixels() const { return Size(0, 0); }
Size NilDraw::GetPageSize() const { return Size(0, 0); }
void NilDraw::BeginOp() {}
void NilDraw::EndOp() {}
void NilDraw::OffsetOp(Point p) {}

View file

@ -1,6 +1,8 @@
#ifndef DRAW_H
#define DRAW_H
#define SYSTEMDRAW 1
#include <Core/Core.h>
#ifdef PLATFORM_X11
@ -563,8 +565,8 @@ public:
};
virtual dword GetInfo() const = 0;
virtual Size GetPagePixels() const = 0;
virtual Size GetPageSize() const;
virtual void StartPage();
virtual void EndPage();
@ -808,7 +810,7 @@ public:
class DrawingDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
@ -863,7 +865,7 @@ public:
class NilDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
@ -991,6 +993,8 @@ DrawingToPdfFnType GetDrawingToPdfFn();
#include "Debug.h"
#include "Cham.h"
typedef ImageDraw SystemImageDraw;
END_UPP_NAMESPACE
#endif

View file

@ -11,17 +11,17 @@ static COLORREF sLightGray;
dword SystemDraw::GetInfo() const
{
return native ? style|NATIVE : style;
return native || !(style & DOTS) ? style|NATIVE : style;
}
Size SystemDraw::GetPagePixels() const
Size SystemDraw::GetPageSize() const
{
return pagePixels;
return native && Dots() ? nativeSize : pageSize;
}
Size SystemDraw::GetNativeDpi() const
{
return nativeDpi;
return Dots() ? nativeDpi : Size(96, 96);
}
void StaticExitDraw_()
@ -257,7 +257,7 @@ void SystemDraw::LoadCaps() {
palette = (GetDeviceCaps(handle, RASTERCAPS) & RC_PALETTE);
if(palette)
color16 = GetDeviceCaps(handle, SIZEPALETTE) != 256;
pagePixels = GetSizeCaps(HORZRES, VERTRES);
nativeSize = pageSize = GetSizeCaps(HORZRES, VERTRES);
nativeDpi = GetSizeCaps(LOGPIXELSX, LOGPIXELSY);
is_mono = GetDeviceCaps(handle, BITSPIXEL) == 1 && GetDeviceCaps(handle, PLANES) == 1;
}
@ -420,6 +420,8 @@ void PrintDraw::InitPrinter()
native = 0;
actual_offset = Point(0, 0);
aborted = false;
pageSize.cx = 600 * nativeSize.cx / nativeDpi.cx;
pageSize.cy = 600 * nativeSize.cy / nativeDpi.cy;
}
void PrintDraw::StartPage()

View file

@ -3,7 +3,7 @@
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
@ -39,7 +39,8 @@ public:
virtual int GetCloffLevel() const;
private:
Size pagePixels;
Size pageSize;
Size nativeSize;
Size nativeDpi;
bool palette:1;
bool color16:1;
@ -135,22 +136,28 @@ public:
};
#ifndef PLATFORM_WINCE
class WinMetaFile {
class WinMetaFile/* : NoCopy */{
Size size;
mutable HENHMETAFILE hemf;
/*mutable */HENHMETAFILE hemf; //TODO: Remove picks
void ChkP() const { ASSERT(!IsPicked()); }
void ChkP() const { /*ASSERT(!IsPicked());*/ }
void Init();
void Pick(pick_ WinMetaFile& src);
void Copy(const WinMetaFile& src);
// void Pick(pick_ WinMetaFile& src);
// void Copy(const WinMetaFile& src);
public:
void Attach(HENHMETAFILE emf);
HENHMETAFILE *Detach();
void Set(const void *data, int len);
void Set(const String& data) { Set(~data, data.GetCount()); }
String Get() const;
bool IsPicked() const { return (uintptr_t) hemf == 0xffffffff; }
// bool IsPicked() const { return (uintptr_t) hemf == 0xffffffff; }
operator bool() const { ChkP(); return hemf; }
void SetSize(const Size& sz) { size = sz; }
Size GetSize() const { ChkP(); return hemf ? size : Size(0, 0); }
void Clear();
@ -162,17 +169,19 @@ public:
void ReadClipboard();
void WriteClipboard() const;
bool Load(const char *file);
void Load(const char *file) { Set(LoadFile(file)); }
WinMetaFile() { Init(); }
WinMetaFile() { Init(); }
WinMetaFile(HENHMETAFILE hemf);
WinMetaFile(HENHMETAFILE hemf, Size sz);
WinMetaFile(const char *file);
WinMetaFile(void *data, int len);
WinMetaFile(const String& data);
WinMetaFile(pick_ WinMetaFile& src) { Pick(src); }
WinMetaFile(const WinMetaFile& src, int) { Copy(src); }
void operator=(pick_ WinMetaFile& src) { Clear(); Pick(src); }
void operator<<=(const WinMetaFile& src) { Clear(); Copy(src); }
// WinMetaFile(pick_ WinMetaFile& src) { Pick(src); }
// WinMetaFile(const WinMetaFile& src, int) { Copy(src); }
// void operator=(pick_ WinMetaFile& src) { Clear(); Pick(src); }
// void operator<<=(const WinMetaFile& src) { Clear(); Copy(src); }
~WinMetaFile() { Clear(); }
@ -192,6 +201,14 @@ public:
WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL);
~WinMetaFileDraw();
};
void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf);
void DrawWMF(Draw& w, int x, int y, const String& wmf);
Drawing LoadWMF(const char *path, int cx, int cy);
Drawing LoadWMF(const char *path);
String AsWMF(const Drawing& iw);
#endif
class ScreenDraw : public SystemDraw {

View file

@ -189,7 +189,7 @@ public:
bool PaletteMode() const { return palette; }
bool IsMono() const { return is_mono; }
Size GetPagePixels() const { return native ? pagePixels : pageDots; }
Size GetPageSize() const { return native ? pagePixels : pageDots; }
Size GetPixelsPerInch() const { return native ? nativeDpi : inchPixels; }
Size GetPageMMs() const { return pageMMs; }
@ -219,7 +219,7 @@ public:
bool IsDrawing() const;
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void StartPage();
virtual void EndPage();
@ -539,7 +539,7 @@ public:
bool IsDrawing() const;
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void StartPage();
virtual void EndPage();

View file

@ -109,7 +109,7 @@ dword DrawingDraw::GetInfo() const
return DOTS;
}
Size DrawingDraw::GetPagePixels() const
Size DrawingDraw::GetPageSize() const
{
return size;
}

View file

@ -11,9 +11,17 @@ void WinMetaFile::Init() {
void WinMetaFile::Paint(Draw& w, const Rect& r) const {
ChkP();
if(!hemf)
return;
SystemDraw *h = dynamic_cast<SystemDraw *>(&w);
if(hemf && h)
if(h)
PlayEnhMetaFile(h->GetHandle(), hemf, r);
else {
Size sz = r.GetSize();
SystemImageDraw iw(sz);
Paint(iw, sz);
w.DrawImage(r.left, r.top, iw);
}
}
void WinMetaFile::Paint(Draw& w, int x, int y, int cx, int cy) const {
@ -38,11 +46,12 @@ void WinMetaFile::WriteClipboard() const {
}
void WinMetaFile::Clear() {
if(hemf && !IsPicked())
if(hemf/* && !IsPicked()*/) //TODO
::DeleteEnhMetaFile(hemf);
hemf = NULL;
}
/* TODO: Remove picks
void WinMetaFile::Pick(pick_ WinMetaFile& src) {
hemf = src.hemf;
size = src.size;
@ -53,7 +62,7 @@ void WinMetaFile::Copy(const WinMetaFile& src) {
hemf = ::CopyEnhMetaFile(src.hemf, NULL);
size = src.size;
}
*/
void WinMetaFile::Attach(HENHMETAFILE _hemf) {
Clear();
ENHMETAHEADER info;
@ -64,8 +73,9 @@ void WinMetaFile::Attach(HENHMETAFILE _hemf) {
if(_hemf && ::GetEnhMetaFileHeader(_hemf, sizeof(info), &info)
&& info.rclFrame.left < info.rclFrame.right
&& info.rclFrame.top < info.rclFrame.bottom) {
size.cx = 600 * (info.rclFrame.right - info.rclFrame.left) / 2540;
size.cy = 600 * (info.rclFrame.bottom - info.rclFrame.top) / 2540;
size.cx = info.rclFrame.right - info.rclFrame.left;
size.cy = info.rclFrame.bottom - info.rclFrame.top;
size = 600 * size / 2540;
hemf = _hemf;
}
}
@ -82,52 +92,35 @@ struct PLACEABLE_METAFILEHEADER
};
#pragma pack(pop)
bool WinMetaFile::Load(const char* path) {
void WinMetaFile::Set(const void *data, int len)
{
Clear();
FileIn file(path);
if(!file.Open(path) || file.GetSize() <= sizeof(ENHMETAHEADER))
return false;
int first = file.Get32le();
file.Seek(0);
if(len <= sizeof(ENHMETAHEADER))
return;
int first = Peek32le(data);
HENHMETAFILE hemf;
HMETAFILE hMF;
Size sz(1000, 1000);
if(first == 0x9AC6CDD7) {
PLACEABLE_METAFILEHEADER mfh;
file.Get(&mfh, 22);
String bits = LoadStream(file);
if((hMF = ::SetMetaFileBitsEx(bits.GetLength(), bits)) == NULL)
return false;
sz = Size(mfh.right - mfh.left, mfh.bottom - mfh.top);
}
else
if((hemf = ::GetEnhMetaFile(path)) != NULL) {
if((hemf = ::SetEnhMetaFileBits(len, (const BYTE *)data)) != NULL)
Attach(hemf);
return true;
else
if(first == 0x9AC6CDD7) {
const PLACEABLE_METAFILEHEADER *mfh = (const PLACEABLE_METAFILEHEADER *)data;
Attach(::SetWinMetaFileBits(len - 22, (const BYTE *)data + 22, NULL, NULL));
size = 600 * Size(mfh->right - mfh->left, mfh->bottom - mfh->top) / 2540;
return;
}
else
if((LOWORD(first) == 1 || LOWORD(first) == 2) && HIWORD(first) >= sizeof(METAHEADER) / 2) {
METAHEADER mh;
if(!file.GetAll(&mh, sizeof(mh)))
return false;
if(mh.mtVersion != 0x100 && mh.mtVersion != 0x300)
return false;
if((hMF = ::GetMetaFile(path)) == NULL)
return false;
}
else
return false;
Attach(::SetWinMetaFileBits(len, (const BYTE *)data, NULL, NULL));
}
dword len = ::GetMetaFileBitsEx(hMF, 0, NULL);
Buffer<byte> bits(len);
::GetMetaFileBitsEx(hMF, len, bits);
Attach(::SetWinMetaFileBits(len, bits, NULL, NULL));
::DeleteMetaFile(hMF);
size = sz;
return true;
String WinMetaFile::Get() const
{
int size = ::GetEnhMetaFileBits(hemf, 0, 0);
StringBuffer b(size);
::GetEnhMetaFileBits(hemf, size, (BYTE *)~b);
return b;
}
void WinMetaFile::Serialize(Stream& s) {
@ -155,6 +148,18 @@ void WinMetaFile::Serialize(Stream& s) {
}
}
WinMetaFile::WinMetaFile(void *data, int len)
{
Init();
Set(data, len);
}
WinMetaFile::WinMetaFile(const String& data)
{
Init();
Set(data);
}
WinMetaFile::WinMetaFile(HENHMETAFILE hemf) {
Init();
Attach(hemf);
@ -171,6 +176,71 @@ WinMetaFile::WinMetaFile(const char *file) {
Load(file);
}
struct cDrawWMF : DataDrawer {
int y;
Size sz;
WinMetaFile wmf;
virtual void Open(const String& data, int cx, int cy);
virtual void Render(ImageBuffer& ib);
};
void cDrawWMF::Open(const String& data, int cx, int cy)
{
y = 0;
wmf.Set(data);
sz = Size(cx, cy);
}
void cDrawWMF::Render(ImageBuffer& ib)
{
if(wmf) {
ImageDraw iw(ib.GetSize());
wmf.Paint(iw, 0, -y, sz.cx, sz.cy);
y += ib.GetHeight();
ib = (Image)iw;
}
else
Fill(~ib, RGBAZero(), ib.GetLength());
}
INITBLOCK
{
DataDrawer::Register<cDrawWMF>("wmf");
};
void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf)
{
w.DrawData(x, y, cx, cy, wmf, "wmf");
}
void DrawWMF(Draw& w, int x, int y, const String& wmf)
{
WinMetaFile h(wmf);
Size sz = h.GetSize();
DrawWMF(w, x, y, sz.cx, sz.cy, wmf);
}
Drawing LoadWMF(const char *path, int cx, int cy)
{
DrawingDraw iw(cx, cy);
DrawWMF(iw, 0, 0, cx, cy, LoadFile(path));
return iw;
}
Drawing LoadWMF(const char *path)
{
String wmf = LoadFile(path);
WinMetaFile h(wmf);
if(h) {
Size sz = h.GetSize();
DrawingDraw iw(sz.cx, sz.cy);
DrawWMF(iw, 0, 0, sz.cx, sz.cy, wmf);
return iw;
}
return Null;
}
bool WinMetaFileDraw::Create(HDC hdc, int cx, int cy, const char *app, const char *name, const char *file) {
if(handle) Close();
@ -240,6 +310,14 @@ WinMetaFileDraw::WinMetaFileDraw(int cx, int cy, const char *app, const char *na
Create(cx, cy, app, name, file);
}
String AsWMF(const Drawing& iw)
{
Size sz = iw.GetSize();
WinMetaFileDraw wd(sz.cx, sz.cy);
wd.DrawDrawing(0, 0, sz.cx, sz.cy, iw);
return wd.Close().Get();
}
#endif
#endif

View file

@ -0,0 +1,74 @@
#include "Painter.h"
NAMESPACE_UPP
static void sQuadratic(LinearPathConsumer& t, const Pointf& p1, const Pointf& p2, const Pointf& p3,
double qt, int lvl)
{
if(lvl < 16) {
PAINTER_TIMING("Quadratic approximation");
Pointf d = p3 - p1;
double q = Squared(d);
if(q > 1e-30) {
Pointf pd = p2 - p1;
double u = (pd.x * d.x + pd.y * d.y) / q;
if(u <= 0 || u >= 1 || SquaredDistance(u * d, pd) > qt) {
Pointf p12 = Mid(p1, p2);
Pointf p23 = Mid(p2, p3);
Pointf div = Mid(p12, p23);
sQuadratic(t, p1, p12, div, qt, lvl + 1);
sQuadratic(t, div, p23, p3, qt, lvl + 1);
return;
}
}
}
t.Line(p3);
}
void ApproximateQuadratic(LinearPathConsumer& t, const Pointf& p1, const Pointf& p2, const Pointf& p3,
double tolerance)
{
sQuadratic(t, p1, p2, p3, tolerance * tolerance, 0);
// t.Line(p3);
}
static void sCubic(LinearPathConsumer& t,
const Pointf& p1, const Pointf& p2, const Pointf& p3, const Pointf& p4,
double qt, int lvl)
{
if(lvl < 16) {
PAINTER_TIMING("Cubic approximation");
Pointf d = p4 - p1;
double q = d.x * d.x + d.y * d.y;
if(q >= 1e-30) {
Pointf d2 = p2 - p1;
Pointf d3 = p3 - p1;
double u1 = (d2.x * d.x + d2.y * d.y) / q;
double u2 = (d3.x * d.x + d3.y * d.y) / q;
if(u1 <= 0 || u1 >= 1 || u2 <= 0 || u2 >= 1 ||
SquaredDistance(u1 * d, d2) > qt || SquaredDistance(u2 * d, d3) > qt) {
Pointf p12 = Mid(p1, p2);
Pointf p23 = Mid(p2, p3);
Pointf p34 = Mid(p3, p4);
Pointf p123 = Mid(p12, p23);
Pointf p234 = Mid(p23, p34);
Pointf div = Mid(p123, p234);
Pointf p14 = Mid(p1, p4);
sCubic(t, p1, p12, p123, div, qt, lvl + 1);
sCubic(t, div, p234, p34, p4, qt, lvl + 1);
return;
}
}
}
t.Line(p4);
}
void ApproximateCubic(LinearPathConsumer& t,
const Pointf& p1, const Pointf& p2, const Pointf& p3, const Pointf& p4,
double tolerance)
{
sCubic(t, p1, p2, p3, p4, tolerance * tolerance, 0);
t.Line(p4);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,361 @@
struct LinearPathConsumer {
virtual void Move(const Pointf& p) = 0;
virtual void Line(const Pointf& p) = 0;
virtual void End();
};
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);
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(); }
};
class Stroker : public LinearPathFilter {
public:
virtual void Move(const Pointf& p);
virtual void Line(const Pointf& p);
virtual void End();
private:
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:
void Init(double width, double miterlimit, double tolerance, int linecap, int linejoin);
};
class Dasher : public LinearPathFilter {
public:
virtual void Move(const Pointf& p);
virtual void Line(const Pointf& p);
private:
const Vector<double> *pattern;
int patterni;
double sum, rem;
bool flag;
Pointf p0;
void Put(const Pointf& p);
public:
void Init(const Vector<double>& pattern, double distance);
};
struct Transformer : public LinearPathFilter {
public:
virtual void Move(const Pointf& p);
virtual void Line(const Pointf& p);
private:
const Xform2D& xform;
public:
Transformer(const Xform2D& xform) : xform(xform) {}
};
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);
}
class Rasterizer : public LinearPathConsumer {
public:
virtual void Move(const Pointf& p);
virtual void Line(const Pointf& p);
private:
struct Cell : Moveable<Cell> {
int16 x;
int16 cover;
int area;
bool operator<(const Cell& b) const { return x < b.x; }
};
Rectf cliprect;
Pointf p0;
Buffer< Vector<Cell> > cell;
int min_y;
int max_y;
Size sz;
double mx;
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);
static int Q8Y(double y) { return int(y * 256 + 0.5); }
int Q8X(double x) { return int(x * mx + 0.5); }
public:
struct Filler {
virtual void Start(int x, int len) = 0;
virtual void Render(int val) = 0;
virtual void Render(int val, int len) = 0;
virtual void End();
};
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, Filler& g, bool evenodd);
void Reset();
Rasterizer(int cx, int cy, bool subpixel);
};
struct SpanSource {
virtual void Get(RGBA *span, int x, int y, unsigned len) = 0;
};
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; }
bool IsEmpty() const { return !data; }
bool IsFull() const { return data == (byte *)1; }
operator const byte*() const { return data; }
ClipLine() { data = NULL; }
~ClipLine() { Clear(); }
};
Image MipMap(const Image& img);
Image MakeMipMap(const Image& img, int level);
class LinearInterpolator {
struct Dda2 {
int count, lift, rem, mod, p;
void Set(int a, int b, int len);
int Get();
};
Xform2D xform;
Dda2 ddax, dday;
static int Q8(double x) { return int(256 * x + 0.5); }
public:
void Set(const Xform2D& m) { xform = m; }
void Begin(int x, int y, int len);
Point Get();
};
class BufferPainter : public Painter {
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 SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
const Pointf& p, bool rel);
virtual void CloseOp();
virtual void DivOp();
virtual void CharacterOp(const Pointf& p, int ch, Font fnt);
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 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<double>& dash, double start);
virtual void TransformOp(const Xform2D& m);
virtual void BeginOp();
virtual void EndOp();
virtual void BeginMaskOp();
virtual void BeginOnPathOp(double q, bool abs);
private:
enum {
MOVE, LINE, QUADRATIC, CUBIC, DIV, CHAR
};
struct LinearData {
Pointf p;
};
struct QuadraticData : LinearData {
Pointf p1;
};
struct CubicData : QuadraticData {
Pointf p2;
};
struct CharData : LinearData {
int ch;
int _filler;
Font fnt;
};
struct Path {
Vector<byte> type;
Vector<byte> data;
};
struct PathLine : Moveable<PathLine> {
Pointf p;
double len;
};
struct Attr : Moveable<Attr> {
Xform2D mtx;
bool evenodd;
byte join;
byte cap;
double miter_limit;
WithDeepCopy< Vector<double> > dash;
WithDeepCopy< Vector<double> > stop;
WithDeepCopy< Vector<RGBA> > stop_color;
double dash_start;
double opacity;
int cliplevel;
bool hasclip;
bool mask;
bool onpath;
};
ImageBuffer& ib;
int mode;
Buffer<int16> subpixel;
int render_cx;
Attr attr;
Attr pathattr;
Array<Attr> attrstack;
Vector< Buffer<ClipLine> > clip;
Array< ImageBuffer > mask;
Vector< Vector<PathLine> > onpathstack;
Vector<double> pathlenstack;
Image gradient;
RGBA gradient1, gradient2;
int gradientn;
Path path;
Pointf current, ccontrol, qcontrol, move;
Rectf pathrect;
bool ischar;
Rasterizer rasterizer;
Buffer<RGBA> span;
Vector<PathLine> onpath;
double pathlen;
struct OnPathTarget;
friend struct OnPathTarget;
void *PathAddRaw(int type, int size);
template <class T> T& PathAdd(int type) { return *(T *)PathAddRaw(type, sizeof(T)); }
Pointf PathPoint(const Pointf& p, bool rel);
Pointf EndPoint(const Pointf& p, bool rel);
void DoMove0();
void ClearPath();
void ApproximateChar(LinearPathConsumer& t, const CharData& ch, double tolerance);
Buffer<ClipLine> RenderPath(double width, SpanSource *ss, const RGBA& color);
void RenderImage(double width, const Image& image, const Xform2D& transsrc,
dword flags);
void RenderRadial(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style);
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();
enum { FILL = -1, CLIP = -2, ONPATH = -3 };
public:
BufferPainter(ImageBuffer& ib, int mode = MODE_ANTIALIASED);
};

133
newdraw/Painter/Context.cpp Normal file
View file

@ -0,0 +1,133 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::BeginOp()
{
attr.onpath = false;
attrstack.Add(attr);
attr.hasclip = false;
}
void BufferPainter::EndOp()
{
if(attrstack.GetCount() == 0) {
NEVER_("Painter::End: attribute stack is empty");
return;
}
pathattr = attr = attrstack.Top();
attrstack.Drop();
clip.SetCount(attr.cliplevel);
if(attr.mask)
FinishMask();
if(attr.onpath) {
attr.onpath = false;
onpath = onpathstack.Top();
onpathstack.Drop();
pathlen = pathlenstack.Pop();
}
}
void BufferPainter::TransformOp(const Xform2D& m)
{
ASSERT_(IsNull(current), "Cannot change transformation during path definition");
pathattr.mtx = attr.mtx = m * attr.mtx;
}
void BufferPainter::OpacityOp(double o)
{
pathattr.opacity *= o;
if(IsNull(current))
attr.opacity *= o;
}
void BufferPainter::LineCapOp(int linecap)
{
pathattr.cap = linecap;
if(IsNull(current))
attr.cap = linecap;
}
void BufferPainter::LineJoinOp(int linejoin)
{
pathattr.join = linejoin;
if(IsNull(current))
attr.join = linejoin;
}
void BufferPainter::MiterLimitOp(double l)
{
pathattr.miter_limit = l;
if(IsNull(current))
attr.miter_limit = l;
}
void BufferPainter::EvenOddOp(bool evenodd)
{
pathattr.evenodd = evenodd;
if(IsNull(current))
attr.evenodd = evenodd;
}
void BufferPainter::DashOp(const Vector<double>& dash, double start)
{
pathattr.dash <<= dash;
pathattr.dash_start = start;
if(IsNull(current)) {
attr.dash <<= dash;
attr.dash_start = start;
}
}
void BufferPainter::ColorStop0(Attr& a, double pos, const RGBA& color)
{
pos = minmax(pos, 0.0, 1.0);
int i = FindLowerBound(a.stop, pos);
a.stop.Insert(i, pos);
a.stop_color.Insert(i, color);
}
void BufferPainter::ColorStopOp(double pos, const RGBA& color)
{
ColorStop0(pathattr, pos, color);
if(IsNull(current))
ColorStop0(attr, pos, color);
}
void BufferPainter::ClearStopsOp()
{
pathattr.stop.Clear();
pathattr.stop_color.Clear();
if(IsNull(current)) {
attr.stop.Clear();
attr.stop_color.Clear();
}
}
BufferPainter::BufferPainter(ImageBuffer& ib, int mode)
: ib(ib),
mode(mode),
rasterizer(ib.GetWidth(), ib.GetHeight(), mode == MODE_SUBPIXEL)
{
ClearPath();
render_cx = ib.GetWidth();
if(mode == MODE_SUBPIXEL) {
render_cx *= 3;
subpixel.Alloc(render_cx + 30);
}
attr.cap = LINECAP_BUTT;
attr.join = LINEJOIN_MITER;
attr.miter_limit = 4;
attr.evenodd = false;
attr.hasclip = false;
attr.cliplevel = 0;
attr.dash_start = 0.0;
attr.opacity = 1.0;
attr.mask = false;
pathattr = attr;
gradientn = Null;
}
END_UPP_NAMESPACE

21
newdraw/Painter/Copying Normal file
View file

@ -0,0 +1,21 @@
Copyright 1998-2009 The U++ Project. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE U++ PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,62 @@
#include "Painter.h"
NAMESPACE_UPP
void Dasher::Put(const Pointf& p)
{
if(flag)
PutLine(p);
else
PutMove(p);
}
void Dasher::Move(const Pointf& p)
{
PutMove(p);
p0 = p;
}
void Dasher::Line(const Pointf& p)
{
if(sum == 0) {
PutLine(p);
return;
}
Pointf v = p - p0;
double len = Length(v);
double pos = 0;
while(pos + rem < len) {
pos += rem;
Put(pos / len * v + p0);
flag = !flag;
rem = (*pattern)[patterni];
patterni = (patterni + 1) % pattern->GetCount();
}
rem -= len - pos;
Put(p);
p0 = p;
}
void Dasher::Init(const Vector<double>& p, double distance)
{
pattern = &p;
sum = Sum0(p);
if(sum == 0)
return;
distance -= int(distance / sum) * sum;
patterni = 0;
flag = false;
for(;;) {
rem = (*pattern)[patterni];
patterni = (patterni + 1) % pattern->GetCount();
flag = !flag;
if(rem > distance) {
rem -= distance;
break;
}
distance -= rem;
}
p0 = Pointf(0, 0);
}
END_UPP_NAMESPACE

137
newdraw/Painter/DrawOp.cpp Normal file
View file

@ -0,0 +1,137 @@
#include "Painter.h"
NAMESPACE_UPP
dword Painter::GetInfo() const
{
return DOTS;
}
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;
}
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<double> 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

465
newdraw/Painter/Fillers.cpp Normal file
View file

@ -0,0 +1,465 @@
#include "Painter.h"
#include "Fillers.h"
NAMESPACE_UPP
void FillRGBA(RGBA *t, RGBA c, int len)
{
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;
}
}
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) {
FillRGBA(t, c, len);
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 SubpixelFiller::Start(int minx, int maxx)
{
int x = minx / 3;
if(x > 0) {
begin = sbuffer;
x--;
}
else
begin = sbuffer + 3;
t += x;
sbuffer[0] = sbuffer[1] = sbuffer[2] = sbuffer[3] =
sbuffer[4] = sbuffer[5] = sbuffer[6] = sbuffer[7] = 0;
v = sbuffer + 3 + minx % 3;
if(ss) {
int xx = maxx / 3;
ss->Get(buffer, x, y, xx - x + 2);
s = buffer;
}
}
void SubpixelFiller::Render(int val)
{
int16 *w = v;
int h = val / 9;
int h2 = h + h;
w[-2] += h;
w[2] += h;
w[-1] += h2;
w[1] += h2;
w[0] += val - h2 - h2 - h2;
w[3] = 0;
v++;
}
void SubpixelFiller::RenderN(int val, int h, int n)
{
int16 *w = v;
int h2 = h + h;
int hv2 = val - h2 - h2;
int h3 = h2 + h;
int hh;
v += n;
switch(n) {
case 1:
w[-2] += h;
w[-1] += h2;
w[1] += h2;
w[0] += hv2 - h2;
w[2] += h;
w[3] = 0;
break;
case 2:
w[-2] += h;
w[3] = h;
w[-1] += h3;
w[2] += h3;
w[0] += hv2;
w[1] += hv2;
w[4] = 0;
break;
case 3:
w[-2] += h;
w[4] = h;
w[-1] += h3;
w[3] = h3;
hh = hv2 + h;
w[0] += hh;
w[2] += hh;
w[1] += hv2 + h2;
w[5] = 0;
break;
case 4:
w[-2] += h;
w[5] = h;
w[-1] += h3;
w[4] = h3;
hh = hv2 + h;
w[0] += hh;
w[3] = hh;
hh = hv2 + h3;
w[1] += hh;
w[2] += hh;
w[6] = 0;
break;
case 5:
w[-2] += h;
w[6] = h;
w[-1] += h3;
w[5] = h3;
hh = hv2 + h;
w[0] += hh;
w[4] = hh;
hh = h3 + hv2;
w[1] += hh;
w[3] = hh;
w[2] += h3 + hv2 + h;
w[7] = 0;
break;
case 6:
w[-2] += h;
w[7] = h;
w[-1] += h3;
w[6] = h3;
hh = hv2 + h;
w[0] += hh;
w[5] = hh;
hh = h3 + hv2;
w[1] += hh;
w[4] = hh;
hh = h3 + hv2 + h;
w[2] += hh;
w[3] = hh;
w[8] = 0;
break;
}
}
void SubpixelFiller::Render(int val, int len)
{
int h = val / 9;
if(len > 6) {
int q = (3333333 - (v + 2 - begin)) % 3;
len -= q + 2;
int l = v + 2 + q - begin;
RenderN(val, h, q + 4);
Write(l / 3);
l = len / 3;
len -= 3 * l;
RGBA *e = min(t + l, end);
if(val == 256)
if(!ss && color.a == 255) {
FillRGBA(t, color, e - t);
t = e;
}
else
while(t < e)
AlphaBlend(*t++, ss ? Mul8(*s++, alpha) : color);
else
if(ss)
while(t < e)
AlphaBlendCover8(*t++, Mul8(*s++, alpha), val);
else {
RGBA c = Mul8(color, val);
while(t < e)
AlphaBlend(*t++, c);
}
v = begin = sbuffer + 3;
v[0] = h + h + h;
v[1] = h;
v[2] = 0;
}
RenderN(val, h, len);
}
void SubpixelFiller::Write(int len)
{
RGBA *e = min(t + len, end);
int16 *q = begin;
while(t < e) {
RGBA c = ss ? Mul8(*s++, alpha) : color;
int a;
if(t->a != 255)
AlphaBlendCover8(*t, c, (q[0] + q[1] + q[2]) / 3);
else
if(c.a == 255) {
t->r = (c.r * q[0] >> 8) + ((257 - q[0]) * t->r >> 8);
t->g = (c.g * q[1] >> 8) + ((257 - q[1]) * t->g >> 8);
t->b = (c.b * q[2] >> 8) + ((257 - q[2]) * t->b >> 8);
}
else {
a = c.a * q[0] >> 8;
t->r = (c.r * q[0] >> 8) + ((256 - a - (a >> 7)) * t->r >> 8);
a = c.a * q[1] >> 8;
t->g = (c.g * q[1] >> 8) + ((256 - a - (a >> 7)) * t->g >> 8);
a = c.a * q[2] >> 8;
t->b = (c.b * q[2] >> 8) + ((256 - a - (a >> 7)) * t->b >> 8);
}
t++;
q += 3;
}
}
void SubpixelFiller::End()
{
v[3] = v[4] = v[5] = 0;
Write((v + 3 - begin) / 3);
}
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

93
newdraw/Painter/Fillers.h Normal file
View file

@ -0,0 +1,93 @@
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 SubpixelFiller : Rasterizer::Filler {
int16 *sbuffer;
int16 *begin;
RGBA *t, *end;
int16 *v;
RGBA *s;
RGBA color;
SpanSource *ss;
int alpha;
RGBA *buffer;
int y;
void Write(int len);
void RenderN(int val, int h, int n);
void Start(int minx, int maxx);
void Render(int val);
void Render(int val, int len);
void End();
};
struct ClipFiller : Rasterizer::Filler {
Buffer<byte> 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 End() { t->End(); }
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 End() { t->End(); }
void Set(Rasterizer::Filler *f) { t = f; }
};
END_UPP_NAMESPACE

View file

@ -0,0 +1,86 @@
//----------------------------------------------------------------------------
// 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_WIN32
double fx_to_dbl(const FIXED& p) {
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
Pointf fx_to_dbl(const Pointf& pp, const POINTFX& p) {
return Pointf(pp.x + fx_to_dbl(p.x), pp.y - fx_to_dbl(p.y));
}
void RenderCharPath(const char* gbuf, unsigned total_size, Painter& sw, double xx, double yy)
{
PAINTER_TIMING("RenderCharPath");
const char* cur_glyph = gbuf;
const char* end_glyph = gbuf + total_size;
Pointf pp(xx, yy);
while(cur_glyph < end_glyph) {
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
const char* end_poly = cur_glyph + th->cb;
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
sw.Move(fx_to_dbl(pp, th->pfxStart));
while(cur_poly < end_poly) {
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
if (pc->wType == TT_PRIM_LINE)
for(int i = 0; i < pc->cpfx; i++)
sw.Line(fx_to_dbl(pp, pc->apfx[i]));
if (pc->wType == TT_PRIM_QSPLINE)
for(int u = 0; u < pc->cpfx - 1; u++) {
Pointf b = fx_to_dbl(pp, pc->apfx[u]);
Pointf c = fx_to_dbl(pp, pc->apfx[u + 1]);
if (u < pc->cpfx - 2)
c = Mid(b, c);
sw.Quadratic(b, c);
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
sw.Close();
cur_glyph += th->cb;
}
}
void PaintCharacter(Painter& sw, const Pointf& p, int ch, Font fnt)
{
PAINTER_TIMING("CharacterOp");
static ScreenDraw w;
w.SetFont(fnt);
GLYPHMETRICS gm;
MAT2 m_matrix;
memset(&m_matrix, 0, sizeof(m_matrix));
m_matrix.eM11.value = 1;
m_matrix.eM22.value = 1;
int gsz = GetGlyphOutlineW(w.GetHandle(), ch, GGO_NATIVE, &gm, 0, NULL, &m_matrix);
if(gsz < 0)
return;
StringBuffer gb(gsz);
gsz = GetGlyphOutlineW(w.GetHandle(), ch, GGO_NATIVE, &gm, gsz, ~gb, &m_matrix);
if(gsz < 0)
return;
RenderCharPath(~gb, gsz, sw, p.x, p.y + fnt.Info().GetAscent());
sw.EvenOdd(true);
}
#endif
END_UPP_NAMESPACE

153
newdraw/Painter/FontX11.cpp Normal file
View file

@ -0,0 +1,153 @@
//----------------------------------------------------------------------------
// 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 PaintCharacter(Painter& sw, 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, sw, p.x, p.y + fnt.Info().GetAscent());
XftUnlockFace(fi.GetXftFont());
sw.EvenOdd(true);
}
#endif
END_UPP_NAMESPACE

View file

@ -0,0 +1,65 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::MakeGradient(RGBA color1, RGBA color2, int n)
{
if(n == gradientn && color1 == gradient1 && color2 == gradient2)
return;
gradientn = n;
gradient1 = color1;
gradient2 = color2;
ImageBuffer ib(n, 1);
RGBA *t = ib[0];
int l = 0;
RGBA cl = color1;
for(int i = 0; i <= pathattr.stop.GetCount(); i++) {
int h;
RGBA ch;
if(i < pathattr.stop.GetCount()) {
h = (int)(pathattr.stop[i] * (n - 1));
ch = pathattr.stop_color[i];
}
else {
h = n - 1;
ch = color2;
}
int w = h - l;
for(int j = 0; j < w; j++) {
t->r = ((w - j) * cl.r + j * ch.r) / w;
t->g = ((w - j) * cl.g + j * ch.g) / w;
t->b = ((w - j) * cl.b + j * ch.b) / w;
t->a = ((w - j) * cl.a + j * ch.a) / w;
t++;
}
cl = ch;
l = h;
}
*t = cl;
gradient = ib;
}
void BufferPainter::Gradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2)
{
MakeGradient(color1, color2, minmax(int(Distance(p1, p2) * pathattr.mtx.GetScale()), 2, 4096));
}
void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
Gradient(color1, color2, p1, p2);
Fill(gradient, p1, p2,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));
}
void BufferPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
Gradient(color1, color2, p1, p2);
Stroke(width, gradient, p1, p2,
FILL_VPAD | FILL_FAST |
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
? FILL_HREPEAT : FILL_HREFLECT));
}
END_UPP_NAMESPACE

239
newdraw/Painter/Image.cpp Normal file
View file

@ -0,0 +1,239 @@
#include "Painter.h"
NAMESPACE_UPP
#if 0 // does not seem to help...
Image MipMap(const Image& img)
{
Size ssz = img.GetSize() / 2;
Size msz = (img.GetSize() + 1) / 2;
ImageBuffer ib(msz);
for(int y = 0; y < ssz.cy; y++) {
const RGBA *s1 = img[2 * y];
const RGBA *s2 = img[2 * y + 1];
const RGBA *e = s1 + 2 * ssz.cx;
RGBA *t = ib[y];
while(s1 < e) {
t->r = (s1[0].r + s1[1].r + s2[0].r + s2[1].r) >> 2;
t->g = (s1[0].g + s1[1].g + s2[0].g + s2[1].g) >> 2;
t->b = (s1[0].b + s1[1].b + s2[0].b + s2[1].b) >> 2;
t->a = (s1[0].a + s1[1].a + s2[0].a + s2[1].a) >> 2;
t++;
s1 += 2;
s2 += 2;
}
if(ssz.cx < msz.cx) {
t->r = (s1[0].r + s2[0].r) >> 2;
t->g = (s1[0].g + s2[0].g) >> 2;
t->b = (s1[0].b + s2[0].b) >> 2;
t->a = (s1[0].a + s2[0].a) >> 2;
}
}
if(ssz.cy < msz.cy) {
const RGBA *s1 = img[img.GetSize().cy - 1];
const RGBA *e = s1 + 2 * ssz.cx;
RGBA *t = ib[msz.cy - 1];
while(s1 < e) {
t->r = (s1[0].r + s1[1].r) >> 2;
t->g = (s1[0].g + s1[1].g) >> 2;
t->b = (s1[0].b + s1[1].b) >> 2;
t->a = (s1[0].a + s1[1].a) >> 2;
t++;
s1 += 2;
}
if(ssz.cx < msz.cx) {
t->r = s1[0].r >> 2;
t->g = s1[0].g >> 2;
t->b = s1[0].b >> 2;
t->a = s1[0].a >> 2;
}
}
return ib;
}
Image MakeMipMap(const Image& m, int level);
struct MipMapMaker : ImageMaker {
int level;
Image image;
virtual String Key() const {
String h;
RawCat(h, image.GetSerialId());
RawCat(h, level);
return h;
}
virtual Image Make() const {
Size sz = image.GetSize();
if(sz.cx && sz.cx) {
if(level <= 0)
return image;
return MipMap(MakeMipMap(image, level - 1));
}
return Image();
}
};
Image MakeMipMap(const Image& img, int level)
{
MipMapMaker m;
m.image = img;
m.level = level;
return MakeImage(m);
}
#endif
struct PainterImageSpan : SpanSource {
struct RGBAV {
dword r, g, b, a;
void Set(dword v) { r = g = b = a = v; }
void Put(dword weight, const RGBA& src) {
r += weight * src.r;
g += weight * src.g;
b += weight * src.b;
a += weight * src.a;
}
};
LinearInterpolator interpolator;
int ax, ay, cx, cy, maxx, maxy;
byte style;
byte hstyle, vstyle;
bool fast;
bool fixed;
Image image;
void Set(const Xform2D& m, const Image& img) {
int level = 0;
#if 0 // no mipmap for now
double q = 1;
if(!fast) {
double q = 1;
Pointf sc = m.GetScaleXY();
if(sc.x >= 0.01 && sc.y >= 0.01)
while(sc.x < 0.5 && sc.y < 0.5) {
level++;
sc.x *= 2;
sc.y *= 2;
q /= 2;
}
}
if(q != 1)
interpolator.Set(Inverse(m) * Xform2D::Scale(q));
else
#endif
interpolator.Set(Inverse(m));
image = img;
// image = MakeMipMap(img, level);
cx = image.GetWidth();
cy = image.GetHeight();
maxx = cx - 1;
maxy = cy - 1;
ax = 6000000 / cx * cx * 2;
ay = 6000000 / cy * cy * 2;
}
RGBA Pixel(int x, int y) { return image[y][x]; }
RGBA GetPixel(int x, int y) {
if(hstyle == FILL_HPAD)
x = minmax(x, 0, maxx);
else
if(hstyle == FILL_HREFLECT)
x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx;
else
if(hstyle == FILL_HREPEAT)
x = (x + ax) % cx;
if(vstyle == FILL_VPAD)
y = minmax(y, 0, maxy);
else
if(vstyle == FILL_VREFLECT)
y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy;
else
if(vstyle == FILL_VREPEAT)
y = (y + ay) % cy;
return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero();
}
virtual void Get(RGBA *span, int x, int y, unsigned len)
{
interpolator.Begin(x, y, len);
fixed = hstyle && vstyle;
while(len--) {
Point h = interpolator.Get();
// h -= 128;
Point l = h >> 8;
if(hstyle == FILL_HREPEAT)
l.x = (l.x + ax) % cx;
if(vstyle == FILL_VREPEAT)
l.y = (l.y + ay) % cy;
if(fast) {
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy)
*span = Pixel(l.x, l.y);
else
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
*span = RGBAZero();
else
*span = GetPixel(l.x, l.y);
}
else {
RGBAV v;
v.Set(0);
// v.Set(256 * 256 / 2);
h.x &= 255;
h.y &= 255;
Point u = -h + 256;
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) {
v.Put(u.x * u.y, Pixel(l.x, l.y));
v.Put(h.x * u.y, Pixel(l.x + 1, l.y));
v.Put(u.x * h.y, Pixel(l.x, l.y + 1));
v.Put(h.x * h.y, Pixel(l.x + 1, l.y + 1));
}
else
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
v.Set(0);
else {
v.Put(u.x * u.y, GetPixel(l.x, l.y));
v.Put(h.x * u.y, GetPixel(l.x + 1, l.y));
v.Put(u.x * h.y, GetPixel(l.x, l.y + 1));
v.Put(h.x * h.y, GetPixel(l.x + 1, l.y + 1));
}
span->r = byte(v.r >> 16);
span->g = byte(v.g >> 16);
span->b = byte(v.b >> 16);
span->a = byte(v.a >> 16);
}
++span;
}
}
};
void BufferPainter::RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
if(image.GetWidth() == 0 || image.GetHeight() == 0)
return;
PainterImageSpan ss;
ss.style = byte(flags & 15);
ss.hstyle = byte(flags & 3);
ss.vstyle = byte(flags & 12);
ss.fast = flags & FILL_FAST;
Xform2D m = transsrc * pathattr.mtx;
ss.Set(m, image);
RenderPath(width, &ss, RGBAZero());
}
void BufferPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
{
Close();
RenderImage(-1, image, transsrc, flags);
}
void BufferPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
RenderImage(width, image, transsrc, flags);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,45 @@
#include "Painter.h"
NAMESPACE_UPP
void LinearInterpolator::Dda2::Set(int p1, int p2, int len)
{
count = len <= 0 ? 1 : len;
lift = (p2 - p1) / count;
rem = (p2 - p1) % count;
mod = rem;
p = p1;
if(mod <= 0) {
mod += count;
rem += count;
lift--;
}
mod -= count;
}
int LinearInterpolator::Dda2::Get()
{
int pp = p;
mod += rem;
p += lift;
if(mod > 0) {
mod -= count;
p++;
}
return pp;
}
void LinearInterpolator::Begin(int x, int y, int len)
{
Pointf p1 = xform.Transform(Pointf(x, y)/* + 0.5*/);
Pointf p2 = xform.Transform(Pointf(x + len, y)/* + 0.5*/);
ddax.Set(Q8(p1.x), Q8(p2.x), len);
dday.Set(Q8(p1.y), Q8(p2.y), len);
}
Point LinearInterpolator::Get()
{
return Point(ddax.Get(), dday.Get());
}
END_UPP_NAMESPACE

90
newdraw/Painter/Mask.cpp Normal file
View file

@ -0,0 +1,90 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::BeginMaskOp()
{
attr.mask = true;
Size sz = ib.GetSize();
mask.Add() = ib;
ib.Create(sz);
Clear(RGBAZero());
Begin();
}
static inline byte *sSpan(byte *t, int c, int& len)
{
while(len > 128) {
int n = min(len, 128);
*t++ = 0;
*t++ = c + n - 1;
len -= n;
}
if(len) {
*t++ = 0;
*t++ = c + len - 1;
len = 0;
}
return t;
}
void BufferPainter::FinishMask()
{
Buffer<byte> wb(mode == MODE_SUBPIXEL ? 6 * ib.GetWidth() : 2 * ib.GetWidth());
bool creating = false;
if(!attr.hasclip) {
clip.Add().Alloc(ib.GetHeight());
attr.hasclip = true;
attr.cliplevel = clip.GetCount();
creating = true;
}
Buffer<ClipLine>& 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++;
if(mode == MODE_SUBPIXEL)
c0 += 2;
full = false;
}
else
if(val == 256) {
if(c0) t = sSpan(t, 0, c0);
c256++;
if(mode == MODE_SUBPIXEL)
c256 += 2;
empty = false;
}
else {
if(c256) t = sSpan(t, 128, c256);
if(c0) t = sSpan(t, 0, c0);
*t++ = val;
if(mode == MODE_SUBPIXEL) {
*t++ = val;
*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);
}
ib = mask.Top();
mask.Drop();
attr.mask = false;
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,33 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::BeginOnPathOp(double q, bool abs)
{
if(onpath.GetCount() == 0)
RenderPath(ONPATH, NULL, RGBAZero());
Begin();
if(pathlen > 0) {
if(!abs)
q *= pathlen;
Pointf pos(0, 0);
for(int i = 0; i < onpath.GetCount(); i++) {
PathLine& l = onpath[i];
if(l.len > 0 && (l.len > q || q >= 1.0 && i == onpath.GetCount() - 1)) {
Pointf v = l.p - pos;
Translate(q / l.len * v + pos);
Rotate(Bearing(v));
break;
}
q -= l.len;
pos = l.p;
}
}
attrstack.Top().onpath = true;
onpathstack.Add() = onpath;
pathlenstack.Add(pathlen);
onpath.Clear();
pathlen = 0;
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,269 @@
#include "Painter.h"
NAMESPACE_UPP
template <class T>
void sGet(T& r, StringStream& ss)
{
ss.Get(&r, sizeof(T));
}
template <class T>
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<RGBA>(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<RGBA>(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<Image>())
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<Image>())
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<wchar> txt(n);
Buffer<double> 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<double>(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<double> dash;
for(int i = 0; i < n; i++)
dash.Add(sGet<double>(ss));
r = sGet<double>(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));
INITBLOCK
{
RegisterPaintingFns__(PaintImageBufferPaintingFn, PaintImageBufferDrawingFn);
}
END_UPP_NAMESPACE

554
newdraw/Painter/Painter.cpp Normal file
View file

@ -0,0 +1,554 @@
#include "Painter.h"
NAMESPACE_UPP
Painter& Painter::Move(const Pointf& p)
{
Move(p, false);
return *this;
}
Painter& Painter::Line(const Pointf& p)
{
Line(p, false);
return *this;
}
Painter& Painter::Quadratic(const Pointf& p1, const Pointf& p)
{
QuadraticOp(p1, p, false);
return *this;
}
Painter& Painter::Quadratic(const Pointf& p)
{
QuadraticOp(p, false);
return *this;
}
Painter& Painter::Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p)
{
CubicOp(p1, p2, p, false);
return *this;
}
Painter& Painter::Cubic(const Pointf& p2, const Pointf& p)
{
CubicOp(p2, p, false);
return *this;
}
Painter& Painter::RelMove(const Pointf& p)
{
MoveOp(p, true);
return *this;
}
Painter& Painter::RelLine(const Pointf& p)
{
LineOp(p, true);
return *this;
}
Painter& Painter::RelQuadratic(const Pointf& p1, const Pointf& p)
{
QuadraticOp(p1, p, true);
return *this;
}
Painter& Painter::RelQuadratic(const Pointf& p)
{
QuadraticOp(p, true);
return *this;
}
Painter& Painter::RelCubic(const Pointf& p1, const Pointf& p2, const Pointf& p)
{
CubicOp(p1, p2, p, true);
return *this;
}
Painter& Painter::RelCubic(const Pointf& p2, const Pointf& p)
{
CubicOp(p2, p, true);
return *this;
}
Painter& Painter::Move(double x, double y, bool rel)
{
MoveOp(Pointf(x, y), rel);
return *this;
}
Painter& Painter::Line(double x, double y, bool rel)
{
LineOp(Pointf(x, y), rel);
return *this;
}
Painter& Painter::Quadratic(double x1, double y1, double x, double y, bool rel)
{
QuadraticOp(Pointf(x1, y1), Pointf(x, y), rel);
return *this;
}
Painter& Painter::Quadratic(double x, double y, bool rel)
{
QuadraticOp(Pointf(x, y), rel);
return *this;
}
Painter& Painter::Cubic(double x1, double y1, double x2, double y2, double x, double y, bool rel)
{
CubicOp(Pointf(x1, y1), Pointf(x2, y2), Pointf(x, y), rel);
return *this;
}
Painter& Painter::Cubic(double x2, double y2, double x, double y, bool rel)
{
CubicOp(Pointf(x2, y2), Pointf(x, y), rel);
return *this;
}
Painter& Painter::Move(double x, double y)
{
Move(x, y, false);
return *this;
}
Painter& Painter::Line(double x, double y)
{
Line(x, y, false);
return *this;
}
Painter& Painter::Quadratic(double x1, double y1, double x, double y)
{
Quadratic(x1, y1, x, y, false);
return *this;
}
Painter& Painter::Quadratic(double x, double y)
{
Quadratic(x, y, false);
return *this;
}
Painter& Painter::Cubic(double x1, double y1, double x2, double y2, double x, double y)
{
Cubic(x1, y1, x2, y2, x, y, false);
return *this;
}
Painter& Painter::Cubic(double x2, double y2, double x, double y)
{
Cubic(x2, y2, x, y, false);
return *this;
}
Painter& Painter::RelMove(double x, double y)
{
Move(x, y, true);
return *this;
}
Painter& Painter::RelLine(double x, double y)
{
Line(x, y, true);
return *this;
}
Painter& Painter::RelQuadratic(double x1, double y1, double x, double y)
{
Quadratic(x1, y1, x, y, true);
return *this;
}
Painter& Painter::RelQuadratic(double x, double y)
{
Quadratic(x, y, true);
return *this;
}
Painter& Painter::RelCubic(double x1, double y1, double x2, double y2, double x, double y)
{
Cubic(x1, y1, x2, y2, x, y, true);
return *this;
}
Painter& Painter::RelCubic(double x2, double y2, double x, double y)
{
Cubic(x2, y2, x, y, true);
return *this;
}
Painter& Painter::Arc(const Pointf& c, double rx, double ry, double angle, double sweep, bool rel)
{
return Arc(c, Pointf(rx, ry), angle, sweep, rel);
}
Painter& Painter::Arc(const Pointf& c, double r, double angle, double sweep, bool rel)
{
return Arc(c, Pointf(r, r), angle, sweep, rel);
}
Painter& Painter::Arc(double x, double y, double rx, double ry, double angle, double sweep, bool rel)
{
return Arc(Pointf(x, y), rx, ry, angle, sweep, rel);
}
Painter& Painter::Arc(double x, double y, double r, double angle, double sweep, bool rel)
{
return Arc(Pointf(x, y), r, angle, sweep, rel);
}
Painter& Painter::Arc(const Pointf& c, const Pointf& r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, false);
}
Painter& Painter::Arc(const Pointf& c, double rx, double ry, double angle, double sweep)
{
return Arc(c, rx, ry, angle, sweep, false);
}
Painter& Painter::Arc(const Pointf& c, double r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, false);
}
Painter& Painter::Arc(double x, double y, double rx, double ry, double angle, double sweep)
{
return Arc(x, y, rx, ry, angle, sweep, false);
}
Painter& Painter::Arc(double x, double y, double r, double angle, double sweep)
{
return Arc(x, y, r, angle, sweep, false);
}
Painter& Painter::RelArc(const Pointf& c, const Pointf& r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, true);
}
Painter& Painter::RelArc(const Pointf& c, double rx, double ry, double angle, double sweep)
{
return Arc(c, rx, ry, angle, sweep, true);
}
Painter& Painter::RelArc(const Pointf& c, double r, double angle, double sweep)
{
return Arc(c, r, angle, sweep, true);
}
Painter& Painter::RelArc(double x, double y, double rx, double ry, double angle, double sweep)
{
return Arc(x, y, rx, ry, angle, sweep, true);
}
Painter& Painter::RelArc(double x, double y, double r, double angle, double sweep)
{
return Arc(x, y, r, angle, sweep, true);
}
Painter& Painter::SvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p, bool rel)
{
return SvgArc(Pointf(rx, ry), xangle, large, sweep, p, rel);
}
Painter& Painter::SvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y, bool rel)
{
return SvgArc(Pointf(rx, ry), xangle, large, sweep, Pointf(x, y), rel);
}
Painter& Painter::SvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p)
{
return SvgArc(r, xangle, large, sweep, p, false);
}
Painter& Painter::SvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p)
{
return SvgArc(rx, ry, xangle, large, sweep, p, false);
}
Painter& Painter::SvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y)
{
return SvgArc(rx, ry, xangle, large, sweep, x, y, false);
}
Painter& Painter::RelSvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p)
{
return SvgArc(r, xangle, large, sweep, p, true);
}
Painter& Painter::RelSvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p)
{
return SvgArc(rx, ry, xangle, large, sweep, p, true);
}
Painter& Painter::RelSvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y)
{
return SvgArc(rx, ry, xangle, large, sweep, x, y, true);
}
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
{
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
m = m * Xform2D::Rotation(Bearing(p2 - p1));
m = m * Xform2D::Translation(p1.x, p1.y);
return m;
}
Painter& Painter::Fill(const Image& image, Pointf p1, Pointf p2, dword flags)
{
return Fill(image, GetLineSzXform(p1, p2, image.GetSize()), flags);
}
Painter& Painter::Fill(const Image& image, double x1, double y1,
double x2, double y2, dword flags)
{
return Fill(image, Pointf(x1, y1), Pointf(x2, y2), flags);
}
Painter& Painter::Fill(double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
{
return Fill(Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
}
Painter& Painter::Fill(double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
{
return Fill(Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
}
Painter& Painter::Fill(const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Fill(c, color1, c, r, color2, style);
}
Painter& Painter::Fill(double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Fill(Pointf(x, y), color1, r, color2, style);
}
Painter& Painter::Translate(double x, double y)
{
Transform(Xform2D::Translation(x, y));
return *this;
}
Painter& Painter::Translate(const Pointf& p)
{
return Translate(p.x, p.y);
}
Painter& Painter::Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2, dword flags)
{
return Stroke(width, image, GetLineSzXform(p1, p2, image.GetSize()), flags);
}
Painter& Painter::Stroke(double width, const Image& image, double x1, double y1, double x2, double y2, dword flags)
{
return Stroke(width, image, Pointf(x1, y1), Pointf(x2, y2), flags);
}
Painter& Painter::Stroke(double width, double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
{
return Stroke(width, Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
}
Painter& Painter::Stroke(double width, double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
{
return Stroke(width, Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
}
Painter& Painter::Stroke(double width, const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Stroke(width, c, color1, c, r, color2, style);
}
Painter& Painter::Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
{
return Stroke(width, Pointf(x, y), color1, r, color2, style);
}
Painter& Painter::Rotate(double a)
{
Transform(Xform2D::Rotation(a));
return *this;
}
Painter& Painter::Scale(double scalex, double scaley)
{
Transform(Xform2D::Scale(scalex, scaley));
return *this;
}
Painter& Painter::Scale(double scale)
{
Scale(scale, scale);
return *this;
}
Painter& Painter::Dash(const char *dash, double start)
{
Vector<double> d;
CParser p(dash);
try {
while(!p.IsEof())
if(p.Char(':'))
start = p.ReadDouble();
else
d.Add(p.ReadDouble());
}
catch(CParser::Error) {}
Dash(d, 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)
{
if(n == 0) {
Move(0, 0);
return;
}
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)
{
if (cx < 0) { x += cx; cx = -cx;}
if (cy < 0) { y += cy; cy = -cy;}
return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close();
}
Painter& Painter::RoundedRectangle(double x, double y, double cx, double cy, double r)
{
ASSERT(r >= 0);
if (cx < 0) { x += cx; cx = -cx;}
if (cy < 0) { y += cy; cy = -cy;}
Move(x + r, y).Arc(x + r, y + r, r, r, -M_PI / 2, -M_PI / 2)
.Line(x, y + cy - r).Arc(x + r, y + cy - r, r, r, M_PI, -M_PI / 2)
.Line(x + cx - r, y + cy).Arc(x + cx - r, y + cy - r, r, r, M_PI / 2, -M_PI / 2)
.Line(x + cx, y + r).Arc(x + cx - r, y + r, r, r, 0, -M_PI / 2).Line(x + r, y);
return *this;
}
Painter& Painter::Ellipse(double x, double y, double rx, double ry)
{
return Move(x + rx, y).Arc(x, y, rx, ry, 0, 2 * M_PI).Close();
}
Painter& Painter::Circle(double x, double y, double r)
{
return Ellipse(x, y, r, r);
}
void NilPainter::ClearOp(const RGBA& color) {}
void NilPainter::MoveOp(const Pointf& p, bool rel) {}
void NilPainter::LineOp(const Pointf& p, bool rel) {}
void NilPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel) {}
void NilPainter::QuadraticOp(const Pointf& p, bool rel) {}
void NilPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) {}
void NilPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel) {}
void NilPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) {}
void NilPainter::SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel) {}
void NilPainter::CloseOp() {}
void NilPainter::DivOp() {}
void NilPainter::FillOp(const RGBA& color) {}
void NilPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags) {}
void NilPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
void NilPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
void NilPainter::StrokeOp(double width, const RGBA& rgba) {}
void NilPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags) {}
void NilPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
void NilPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
void NilPainter::ClipOp() {}
void NilPainter::CharacterOp(const Pointf& p, int ch, Font fnt) {}
void NilPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, double *dx) {}
void NilPainter::ColorStopOp(double pos, const RGBA& color) {}
void NilPainter::ClearStopsOp() {}
void NilPainter::OpacityOp(double o) {}
void NilPainter::LineCapOp(int linecap) {}
void NilPainter::LineJoinOp(int linejoin) {}
void NilPainter::MiterLimitOp(double l) {}
void NilPainter::EvenOddOp(bool evenodd) {}
void NilPainter::DashOp(const Vector<double>& dash, double start) {}
void NilPainter::TransformOp(const Xform2D& m) {}
void NilPainter::BeginOp() {}
void NilPainter::EndOp() {}
void NilPainter::BeginMaskOp() {}
void NilPainter::BeginOnPathOp(double, bool) {}
ImagePainter::ImagePainter(Size sz, int mode)
: ImageBuffer__(sz), BufferPainter(ImageBuffer__::ib, mode)
{}
ImagePainter::ImagePainter(int cx, int cy, int mode)
: ImageBuffer__(Size(cx, cy)), BufferPainter(ImageBuffer__::ib, mode)
{}
DrawPainter::DrawPainter(Draw& w, Size sz, int mode)
: ImagePainter(sz, mode), w(w)
{}
DrawPainter::~DrawPainter()
{
w.DrawImage(0, 0, *this);
}
END_UPP_NAMESPACE

404
newdraw/Painter/Painter.h Normal file
View file

@ -0,0 +1,404 @@
#ifndef _Painter_Painter_h_
#define _Painter_Painter_h_
#include <Draw/Draw.h>
#define PAINTER_TIMING(x) // RTIMING(x)
NAMESPACE_UPP
struct Xform2D {
Pointf x, y, t;
Pointf GetScaleXY() const;
double GetScale() const;
bool IsRegular() const;
Pointf Transform(const Pointf& f) const;
Pointf Transform(double x, double y) 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();
};
Xform2D operator*(const Xform2D& a, const Xform2D& b);
Xform2D Inverse(const Xform2D& m);
enum {
LINECAP_BUTT,
LINECAP_SQUARE,
LINECAP_ROUND,
LINEJOIN_MITER,
LINEJOIN_ROUND,
LINEJOIN_BEVEL,
FILL_EXACT = 0,
FILL_HPAD = 1,
FILL_HREPEAT = 2,
FILL_HREFLECT = 3,
FILL_VPAD = 4,
FILL_VREPEAT = 8,
FILL_VREFLECT = 12,
FILL_PAD = FILL_HPAD|FILL_VPAD,
FILL_REPEAT = FILL_HREPEAT|FILL_VREPEAT,
FILL_REFLECT = FILL_HREFLECT|FILL_VREFLECT,
FILL_FAST = 128,
GRADIENT_PAD = 0,
GRADIENT_REPEAT = 1,
GRADIENT_REFLECT = 2,
};
class Painter : public Draw {
public:
virtual dword GetInfo() const;
virtual void OffsetOp(Point p);
virtual void RectPath(int x, int y, int cx, int cy);
virtual void RectPath(const Rect& r);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts,
int count_count, int width, Color color, Color doxor);
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 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 DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx);
virtual void DrawPaintingOp(const Rect& target, const Painting& p);
protected:
virtual void ClearOp(const RGBA& color) = 0;
virtual void MoveOp(const Pointf& p, bool rel) = 0;
virtual void LineOp(const Pointf& p, bool rel) = 0;
virtual void QuadraticOp(const Pointf& p1, const Pointf& p, bool rel) = 0;
virtual void QuadraticOp(const Pointf& p, bool rel) = 0;
virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) = 0;
virtual void CubicOp(const Pointf& p2, const Pointf& p, bool rel) = 0;
virtual void ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) = 0;
virtual void SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
const Pointf& p, bool rel) = 0;
virtual void CloseOp() = 0;
virtual void DivOp() = 0;
virtual void FillOp(const RGBA& color) = 0;
virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags) = 0;
virtual void FillOp(const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style) = 0;
virtual void FillOp(const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style) = 0;
virtual void StrokeOp(double width, const RGBA& rgba) = 0;
virtual void StrokeOp(double width, const Image& image, const Xform2D& transsrc,
dword flags) = 0;
virtual void StrokeOp(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2,
int style) = 0;
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style) = 0;
virtual void ClipOp() = 0;
virtual void CharacterOp(const Pointf& p, int ch, Font fnt) = 0;
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;
virtual void OpacityOp(double o) = 0;
virtual void LineCapOp(int linecap) = 0;
virtual void LineJoinOp(int linejoin) = 0;
virtual void MiterLimitOp(double l) = 0;
virtual void EvenOddOp(bool evenodd) = 0;
virtual void DashOp(const Vector<double>& dash, double start = 0) = 0;
virtual void TransformOp(const Xform2D& m) = 0;
virtual void BeginOp() = 0;
virtual void EndOp() = 0;
virtual void BeginMaskOp() = 0;
virtual void BeginOnPathOp(double q, bool absolute) = 0;
protected:
static bool ReadBool(CParser& p);
static double ReadDouble(CParser& p);
static Pointf ReadPoint(CParser& p);
void DoArc0(double theta, double th_sweep, const Xform2D& m);
void DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle);
void DoSvgArc(const Pointf& rr, double xangle, int large, int sweep,
const Pointf& p, const Pointf& p0);
public:
void Clear(const RGBA& color);
Painter& Move(const Pointf& p, bool rel);
Painter& Move(const Pointf& p);
Painter& Move(double x, double y, bool rel);
Painter& Move(double x, double y);
Painter& RelMove(const Pointf& p);
Painter& RelMove(double x, double y);
Painter& Line(const Pointf& p, bool rel);
Painter& Line(const Pointf& p);
Painter& Line(double x, double y, bool rel);
Painter& Line(double x, double y);
Painter& RelLine(const Pointf& p);
Painter& RelLine(double x, double y);
Painter& Quadratic(const Pointf& p1, const Pointf& p, bool rel);
Painter& Quadratic(const Pointf& p1, const Pointf& p);
Painter& Quadratic(const Pointf& p);
Painter& Quadratic(double x, double y, bool rel);
Painter& Quadratic(double x1, double y1, double x, double y, bool rel);
Painter& Quadratic(const Pointf& p, bool rel);
Painter& Quadratic(double x1, double y1, double x, double y);
Painter& Quadratic(double x, double y);
Painter& RelQuadratic(const Pointf& p1, const Pointf& p);
Painter& RelQuadratic(double x1, double y1, double x, double y);
Painter& RelQuadratic(double x, double y);
Painter& RelQuadratic(const Pointf& p);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p2, const Pointf& p, bool rel);
Painter& Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& Cubic(const Pointf& p2, const Pointf& p);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y, bool rel);
Painter& Cubic(double x2, double y2, double x, double y, bool rel);
Painter& Cubic(double x1, double y1, double x2, double y2, double x, double y);
Painter& Cubic(double x2, double y2, double x, double y);
Painter& RelCubic(const Pointf& p1, const Pointf& p2, const Pointf& p);
Painter& RelCubic(const Pointf& p2, const Pointf& p);
Painter& RelCubic(double x1, double y1, double x2, double y2, double x, double y);
Painter& RelCubic(double x2, double y2, double x, double y);
Painter& Arc(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, double rx, double ry, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, double r, double angle, double sweep, bool rel);
Painter& Arc(double x, double y, double rx, double ry, double angle, double sweep, bool rel);
Painter& Arc(double x, double y, double r, double angle, double sweep, bool rel);
Painter& Arc(const Pointf& c, const Pointf& r, double angle, double sweep);
Painter& Arc(const Pointf& c, double rx, double ry, double angle, double sweep);
Painter& Arc(const Pointf& c, double r, double angle, double sweep);
Painter& Arc(double x, double y, double rx, double ry, double angle, double sweep);
Painter& Arc(double x, double y, double r, double angle, double sweep);
Painter& RelArc(const Pointf& c, const Pointf& r, double angle, double sweep);
Painter& RelArc(const Pointf& c, double rx, double ry, double angle, double sweep);
Painter& RelArc(const Pointf& c, double r, double angle, double sweep);
Painter& RelArc(double x, double y, double rx, double ry, double angle, double sweep);
Painter& RelArc(double x, double y, double r, double angle, double sweep);
Painter& SvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel);
Painter& SvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p, bool rel);
Painter& SvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y, bool rel);
Painter& SvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p);
Painter& SvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p);
Painter& SvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y);
Painter& RelSvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p);
Painter& RelSvgArc(double rx, double ry, double xangle, bool large, bool sweep, const Pointf& p);
Painter& RelSvgArc(double rx, double ry, double xangle, bool large, bool sweep, double x, double y);
Painter& Close();
Painter& Div();
Painter& Path(CParser& p);
Painter& Path(const char *path);
Painter& Fill(const RGBA& color);
Painter& Fill(const Image& image, const Xform2D& transsrc = Xform2D::Identity(), dword flags = 0);
Painter& Fill(const Image& image, Pointf p1, Pointf p2, dword flags = 0);
Painter& Fill(const Image& image, double x1, double y1, double x2, double y2,
dword flags = 0);
Painter& Fill(const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double x1, double y1, const RGBA& color1,
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double fx, double fy, const RGBA& color1,
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(const Pointf& c, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Fill(double x, double y, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const RGBA& color);
Painter& Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags = 0);
Painter& Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2,
dword flags = 0);
Painter& Stroke(double width, const Image& image, double x1, double y1, double x2, double y2,
dword flags = 0);
Painter& Stroke(double width, const Pointf& p1, const RGBA& color1,
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double x1, double y1, const RGBA& color1,
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double fx, double fy, const RGBA& color1,
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, const Pointf& c, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
Painter& Stroke(double width, double x, double y, const RGBA& color1,
double r, const RGBA& color2, int style = GRADIENT_PAD);
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();
void BeginOnPath(double q, bool absolute = false);
Painter& ColorStop(double pos, const RGBA& color);
Painter& ClearStops();
Painter& Opacity(double o);
Painter& LineCap(int linecap);
Painter& LineJoin(int linejoin);
Painter& MiterLimit(double l);
Painter& EvenOdd(bool evenodd = true);
Painter& Dash(const Vector<double>& dash, double start);
Painter& Dash(const char *dash, double start = 0);
Painter& Transform(const Xform2D& m);
Painter& Translate(double x, double y);
Painter& Translate(const Pointf& p);
Painter& Rotate(double a);
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& RoundedRectangle(double x, double y, double cx, double cy, double r);
Painter& Ellipse(double x, double y, double rx, double ry);
Painter& Circle(double x, double y, double r);
};
void PaintCharacter(Painter& sw, const Pointf& p, int ch, Font fnt);
#include "Painter.hpp"
#include "Painting.h"
#include "BufferPainter.h"
class ImageBuffer__ {
protected:
ImageBuffer ib;
public:
ImageBuffer__(Size sz) : ib(sz) {}
};
class ImagePainter : private ImageBuffer__, public BufferPainter {
public:
ImagePainter(Size sz, int mode = MODE_ANTIALIASED);
ImagePainter(int cx, int cy, int mode = MODE_ANTIALIASED);
Image GetResult() { return ImageBuffer__::ib; }
operator Image() { return GetResult(); }
};
class DrawPainter : public ImagePainter {
Draw& w;
public:
DrawPainter(Draw& w, Size sz, int mode = MODE_ANTIALIASED);
~DrawPainter();
};
class NilPainter : public Painter {
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 SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
const Pointf& p, 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<double>& dash, double start);
virtual void TransformOp(const Xform2D& m);
virtual void BeginOp();
virtual void EndOp();
virtual void BeginMaskOp();
virtual void BeginOnPathOp(double q, bool abs);
};
END_UPP_NAMESPACE
#endif

232
newdraw/Painter/Painter.hpp Normal file
View file

@ -0,0 +1,232 @@
inline
void Painter::Clear(const RGBA& color)
{
ClearOp(color);
}
inline
Painter& Painter::Move(const Pointf& p, bool rel)
{
MoveOp(p, rel);
return *this;
}
inline
Painter& Painter::Line(const Pointf& p, bool rel)
{
LineOp(p, rel);
return *this;
}
inline
Painter& Painter::Quadratic(const Pointf& p1, const Pointf& p, bool rel)
{
QuadraticOp(p1, p, rel);
return *this;
}
inline
Painter& Painter::Quadratic(const Pointf& p, bool rel)
{
QuadraticOp(p, rel);
return *this;
}
inline
Painter& Painter::Cubic(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel)
{
CubicOp(p1, p2, p, rel);
return *this;
}
inline
Painter& Painter::Cubic(const Pointf& p2, const Pointf& p, bool rel)
{
CubicOp(p2, p, rel);
return *this;
}
inline
Painter& Painter::Arc(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel)
{
ArcOp(c, r, angle, sweep, rel);
return *this;
}
inline
Painter& Painter::SvgArc(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel)
{
SvgArcOp(r, xangle, large, sweep, p, rel);
return *this;
}
inline
Painter& Painter::Close()
{
CloseOp();
return *this;
}
inline
Painter& Painter::Div()
{
DivOp();
return *this;
}
inline
Painter& Painter::Fill(const RGBA& color)
{
FillOp(color);
return *this;
}
inline
Painter& Painter::Fill(const Image& image, const Xform2D& transsrc, dword flags)
{
FillOp(image, transsrc, flags);
return *this;
}
inline
Painter& Painter::Fill(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
FillOp(p1, color1, p2, color2, style);
return *this;
}
inline
Painter& Painter::Fill(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
FillOp(f, color1, c, r, color2, style);
return *this;
}
inline
Painter& Painter::Stroke(double width, const RGBA& color)
{
StrokeOp(width, color);
return *this;
}
inline
Painter& Painter::Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags)
{
StrokeOp(width, image, transsrc, flags);
return *this;
}
inline
Painter& Painter::Stroke(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
{
StrokeOp(width, p1, color1, p2, color2, style);
return *this;
}
inline
Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
StrokeOp(width, f, color1, c, r, color2, style);
return *this;
}
inline
Painter& Painter::Clip()
{
ClipOp();
return *this;
}
inline Painter& Painter::ColorStop(double pos, const RGBA& color)
{
ColorStopOp(pos, color);
return *this;
}
inline Painter& Painter::ClearStops()
{
ClearStopsOp();
return *this;
}
inline Painter& Painter::Opacity(double o)
{
OpacityOp(o);
return *this;
}
inline Painter& Painter::LineCap(int linecap)
{
LineCapOp(linecap);
return *this;
}
inline Painter& Painter::LineJoin(int linejoin)
{
LineJoinOp(linejoin);
return *this;
}
inline Painter& Painter::MiterLimit(double l)
{
MiterLimitOp(l);
return *this;
}
inline Painter& Painter::EvenOdd(bool evenodd)
{
EvenOddOp(evenodd);
return *this;
}
inline Painter& Painter::Dash(const Vector<double>& dash, double start)
{
if(dash.GetCount() & 1) {
Vector<double> dash1;
dash1.Append(dash);
dash1.Append(dash);
DashOp(dash1, start);
}
else
DashOp(dash, start);
return *this;
}
inline Painter& Painter::Transform(const Xform2D& m)
{
TransformOp(m);
return *this;
}
inline void Painter::Begin()
{
BeginOp();
}
inline void Painter::End()
{
EndOp();
}
inline void Painter::BeginMask()
{
BeginMaskOp();
}
inline void Painter::BeginOnPath(double q, bool abs)
{
BeginOnPathOp(q, abs);
}
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;
}

View file

@ -0,0 +1,42 @@
description "2D software rendering with PDF/SVG strength\377";
uses
Core,
CtrlLib;
file
Painter.h,
Painter.hpp,
Painter.cpp,
SvgArc.cpp,
PainterPath.cpp,
FontWin32.cpp,
FontX11.cpp,
DrawOp.cpp,
Painting.h,
Painting.cpp,
PaintPainting.icpp,
BufferPainter.h,
Xform2D.cpp,
Approximate.cpp,
Stroker.cpp,
Dasher.cpp,
Transformer.cpp,
Interpolator.cpp optimize_speed,
Rasterizer.cpp optimize_speed,
RasterizerClip.cpp optimize_speed,
Path.cpp optimize_speed,
Context.cpp,
Fillers.h,
Fillers.cpp optimize_speed,
RenderChar.cpp,
Render.cpp optimize_speed,
Image.cpp optimize_speed,
Mask.cpp optimize_speed,
Gradient.cpp optimize_speed,
RadialGradient.cpp optimize_speed,
OnPath.cpp,
srcimp.tpp,
Info readonly separator,
Copying;

View file

@ -0,0 +1,107 @@
#include "Painter.h"
NAMESPACE_UPP
bool Painter::ReadBool(CParser& p)
{
while(p.Char(','));
if(p.Char('1')) return true;
p.Char('0');
return false;
}
double Painter::ReadDouble(CParser& p)
{
while(p.Char(','));
return p.IsDouble() ? p.ReadDouble() : 0;
}
Pointf Painter::ReadPoint(CParser& p)
{
Pointf t;
t.x = ReadDouble(p);
t.y = ReadDouble(p);
return t;
}
Painter& Painter::Path(CParser& p)
{
while(!p.IsEof()) {
int c = p.GetChar();
p.Spaces();
bool rel = IsLower(c);
Pointf t, t1, t2;
switch(ToUpper(c)) {
case 'M':
t = ReadPoint(p);
Move(t, rel);
case 'L':
while(p.IsDouble()) {
t = ReadPoint(p);
Line(t, rel);
}
break;
case 'Z':
Close();
break;
case 'H':
while(p.IsDouble())
Line(p.ReadDouble(), Null, rel);
break;
case 'V':
while(p.IsDouble())
Line(Null, p.ReadDouble(), rel);
break;
case 'C':
while(p.IsDouble()) {
t1 = ReadPoint(p);
t2 = ReadPoint(p);
t = ReadPoint(p);
Cubic(t1, t2, t, rel);
}
break;
case 'S':
while(p.IsDouble()) {
t2 = ReadPoint(p);
t = ReadPoint(p);
Cubic(t2, t, rel);
}
break;
case 'Q':
while(p.IsDouble()) {
t1 = ReadPoint(p);
t = ReadPoint(p);
Quadratic(t1, t, rel);
}
break;
case 'T':
while(p.IsDouble()) {
t = ReadPoint(p);
Quadratic(t, rel);
}
break;
case 'A':
while(p.IsDouble()) {
t1 = ReadPoint(p);
double xangle = ReadDouble(p);
bool large = ReadBool(p);
bool sweep = ReadBool(p);
t = ReadPoint(p);
SvgArc(t1, xangle * M_PI / 180.0, large, sweep, t, rel);
}
break;
default:
return *this;
}
}
return *this;
}
Painter& Painter::Path(const char *path)
{
CParser p(path);
Path(p);
return *this;
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,287 @@
#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::SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel)
{
Put(PAINTING_SVGARC + rel);
Putf(r);
Putf(xangle);
Put(large);
Put(sweep);
Putf(p);
}
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<double>& dash, double start)
{
Put(PAINTING_DASH);
Put32(dash.GetCount());
for(int i = 0; i < dash.GetCount(); i++)
Putf(dash[i]);
Putf(start);
}
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);
}
void PaintingPainter::BeginOnPathOp(double q, bool abs)
{
Put(PAINTING_BEGINONPATH);
Putf(q);
Put(abs);
}
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

137
newdraw/Painter/Painting.h Normal file
View file

@ -0,0 +1,137 @@
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_SVGARC,
PAINTING_SVGARC_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_TRANSFORM,
PAINTING_BEGIN,
PAINTING_END,
PAINTING_BEGINMASK,
PAINTING_BEGINONPATH,
};
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 SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
const Pointf& p, 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<double>& dash, double start);
virtual void TransformOp(const Xform2D& m);
virtual void BeginOp();
virtual void EndOp();
virtual void BeginMaskOp();
virtual void BeginOnPathOp(double q, bool abs);
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); }
};

136
newdraw/Painter/Path.cpp Normal file
View file

@ -0,0 +1,136 @@
#include "Painter.h"
NAMESPACE_UPP
void BufferPainter::ClearPath()
{
path.type.Clear();
path.data.Clear();
current = move = Null;
ccontrol = qcontrol = Pointf(0, 0);
ischar = false;
}
Pointf BufferPainter::PathPoint(const Pointf& p, bool rel)
{
Pointf r;
r.x = IsNull(p.x) ? current.x : rel ? p.x + current.x : p.x;
r.y = IsNull(p.y) ? current.y : rel ? p.y + current.y : p.y;
if(IsNull(current)) {
ClearPath();
pathrect.left = pathrect.right = r.x;
pathrect.top = pathrect.bottom = r.y;
pathattr = attr;
}
else {
pathrect.left = min(pathrect.left, r.x);
pathrect.top = min(pathrect.top, r.y);
pathrect.right = max(pathrect.right, r.x);
pathrect.bottom = max(pathrect.bottom, r.y);
}
return r;
}
Pointf BufferPainter::EndPoint(const Pointf& p, bool rel)
{
return current = PathPoint(p, rel);
}
void *BufferPainter::PathAddRaw(int type, int size)
{
int q = path.data.GetCount();
path.type.Add(type);
path.data.SetCount(q + size);
return &path.data[q];
}
void BufferPainter::MoveOp(const Pointf& p, bool rel)
{
move = ccontrol = qcontrol = EndPoint(p, rel);
PathAdd<LinearData>(MOVE).p = move;
}
void BufferPainter::DoMove0()
{
if(IsNull(move))
MoveOp(Pointf(0, 0), false);
}
void BufferPainter::LineOp(const Pointf& p, bool rel)
{
DoMove0();
PathAdd<LinearData>(LINE).p = ccontrol = qcontrol = EndPoint(p, rel);
}
void BufferPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel)
{
DoMove0();
QuadraticData& m = PathAdd<QuadraticData>(QUADRATIC);
qcontrol = m.p1 = PathPoint(p1, rel);
m.p = EndPoint(p, rel);
}
void BufferPainter::QuadraticOp(const Pointf& p, bool rel)
{
QuadraticOp(2.0 * current - qcontrol, p, rel);
}
void BufferPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel)
{
DoMove0();
CubicData& m = PathAdd<CubicData>(CUBIC);
m.p1 = PathPoint(p1, rel);
ccontrol = m.p2 = PathPoint(p2, rel);
m.p = EndPoint(p, rel);
}
void BufferPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel)
{
CubicOp(2.0 * current - ccontrol, p2, p, rel);
}
void BufferPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel)
{
DoMove0();
DoArc(PathPoint(c, rel), r, angle, sweep, 0);
}
void BufferPainter::SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep,
const Pointf& p, bool rel)
{
DoMove0();
Pointf c = current;
DoSvgArc(r, xangle, large, sweep, EndPoint(p, rel), c);
}
void BufferPainter::CloseOp()
{
if(!IsNull(move) && !IsNull(current) && current != move) {
Line(move);
move = Null;
}
}
void BufferPainter::DivOp()
{
CloseOp();
path.type.Add(DIV);
}
void BufferPainter::CharacterOp(const Pointf& p, int ch, Font fnt)
{
#if 0
DoMove0();
PaintCharacter(*this, p, ch, fnt);
#else
move = current = EndPoint(p, false);
CharData& m = PathAdd<CharData>(CHAR);
m.p = EndPoint(p, false);
m.ch = ch;
m.fnt = fnt;
ischar = true;
EvenOdd();
#endif
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,82 @@
#include "Painter.h"
NAMESPACE_UPP
struct PainterRadialSpan : SpanSource {
LinearInterpolator interpolator;
double cx, cy, r, fx, fy;
int style;
int alpha;
const RGBA *gradient;
double C;
void Set(double _x, double _y, double _r, double _fx, double _fy)
{
cx = _x;
cy = _y;
r = _r;
fx = _fx;
fy = _fy;
fx -= cx;
fy -= cy;
double fx2 = double(fx) * double(fx);
double fy2 = double(fy) * double(fy);
C = fx * fx + fy * fy - r * r;
}
void Get(RGBA *_span, int x, int y, unsigned len)
{
if(r <= 0)
return;
interpolator.Begin(x, y, len);
RGBA *span = (RGBA *)_span;
while(len--) {
Point p = interpolator.Get();
int h;
const double q256 = 1 / 256.0;
double dx = q256 * p.x - cx - fx;
double dy = q256 * p.y - cy - fy;
if(dx == 0 && dy == 0)
h = 0;
else {
double A = dx * dx + dy * dy;
double b = (fx * dx + fy * dy);
double t = (sqrt(b * b - A * C) - b) / (A);
h = t >= 0.001 ? int(2047 / t) : 2047;
}
if(style == GRADIENT_REPEAT)
h = h & 2047;
else
if(style == GRADIENT_REFLECT)
h = (h & 2048) ? (2047 - h & 2047) : (h & 2047);
else
h = minmax(h, 0, 2047);
*span++ = gradient[h];
}
}
};
void BufferPainter::RenderRadial(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2, int style)
{
PainterRadialSpan sg;
Xform2D m = pathattr.mtx;
sg.interpolator.Set(Inverse(m));
sg.style = style;
sg.Set(c.x, c.y, r, f.x, f.y);
MakeGradient(color1, color2, 2048);
sg.gradient = gradient[0];
RenderPath(width, &sg, RGBAZero());
}
void BufferPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
RenderRadial(-1, f, color1, c, r, color2, style);
}
void BufferPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
{
RenderRadial(width, f, color1, c, r, color2, style);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,356 @@
#include "Painter.h"
// This code is based in AGG rasterizer with this original information:
//----------------------------------------------------------------------------
// 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 copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#define LLOG(x) // LOG(x)
NAMESPACE_UPP
void Rasterizer::Init()
{
p0 = Pointf(0, 0);
min_y = INT_MAX;
max_y = INT_MIN;
}
void Rasterizer::Reset()
{
PAINTER_TIMING("Rasterizer::Reset");
for(int i = min_y; i <= max_y; i++)
cell[i].SetCount(0);
Init();
}
void Rasterizer::SetClip(const Rectf& rect)
{
cliprect = rect & Sizef(sz);
}
Rasterizer::Rasterizer(int cx, int cy, bool subpixel)
{
mx = subpixel ? 3 * 256 : 256;
sz.cx = subpixel ? 3 * cx : cx;
sz.cy = cy;
cell.Alloc(sz.cy + 1);
cliprect = Sizef(sz);
Init();
Reset();
}
inline Rasterizer::Cell *Rasterizer::AddCells(int y, int n)
{
Vector<Cell>& v = cell[y];
if(v.GetAlloc() == 0) {
v.Reserve(16);
v.SetCount(n);
return &v[0];
}
y = v.GetCount();
v.SetCount(y + n);
return &v[y];
}
inline void Rasterizer::RenderHLine(int ey, int x1, int y1, int x2, int y2)
{
int ex1 = x1 >> 8;
int ex2 = x2 >> 8;
int fx1 = x1 & 255;
int fx2 = x2 & 255;
Cell *c;
if(y1 == y2)
return;
int dy = y2 - y1;
if(ex1 == ex2) {
c = AddCells(ey, 1);
c->x = ex1;
c->cover = dy;
c->area = (fx1 + fx2) * dy;
return;
}
int dx = x2 - x1;
if(dx < 0) {
int p = fx1 * dy;
dx = -dx;
int delta = p / dx;
int mod = p % dx;
if(mod < 0) {
delta--;
mod += dx;
}
c = AddCells(ey, abs(ex2 - ex1) + 1);
c->x = ex1;
c->cover = delta;
c->area = fx1 * delta;
c++;
ex1--;
y1 += delta;
if(ex1 != ex2) {
p = (y2 - y1 + delta) * 256;
int lift = p / dx;
int rem = p % dx;
if (rem < 0) {
lift--;
rem += dx;
}
mod -= dx;
while(ex1 != ex2) {
delta = lift;
mod += rem;
if(mod >= 0) {
mod -= dx;
delta++;
}
c->x = ex1;
c->cover = delta;
c->area = delta * 256;
c++;
y1 += delta;
ex1--;
}
}
c->x = ex2;
dy = y2 - y1;
c->cover = dy;
c->area = (fx2 + 256) * dy;
}
else {
int p = (256 - fx1) * dy;
int delta = p / dx;
int mod = p % dx;
if(mod < 0) {
delta--;
mod += dx;
}
c = AddCells(ey, abs(ex2 - ex1) + 1);
c->x = ex1;
c->cover = delta;
c->area = (fx1 + 256) * delta;
c++;
ex1++;
y1 += delta;
if(ex1 != ex2) {
p = (y2 - y1 + delta) * 256;
int lift = p / dx;
int rem = p % dx;
if (rem < 0) {
lift--;
rem += dx;
}
mod -= dx;
while(ex1 != ex2) {
delta = lift;
mod += rem;
if(mod >= 0) {
mod -= dx;
delta++;
}
c->x = ex1;
c->cover = delta;
c->area = delta * 256;
c++;
y1 += delta;
ex1++;
}
}
c->x = ex2;
dy = y2 - y1;
c->cover = dy;
c->area = fx2 * dy;
}
}
void Rasterizer::LineRaw(int x1, int y1, int x2, int y2)
{
PAINTER_TIMING("LineRaw");
LLOG("Rasterizer::LineRaw " << x1 / 256.0 << ':' << y1 / 256.0
<< " - " << x2 / 256.0 << ':' << y2 / 256.0);
int ex1 = x1 >> 8;
int ex2 = x2 >> 8;
int ey1 = y1 >> 8;
int ey2 = y2 >> 8;
ASSERT(ey1 >= 0 && ey1 <= sz.cy && ey2 >= 0 && ey2 <= sz.cy);
if(ey1 < min_y) {
if(ey1 < 0) return;
min_y = ey1;
}
if(ey1 > max_y) {
if(ey1 > sz.cy) return;
max_y = min(ey1, sz.cy - 1);
}
if(ey2 < min_y) {
if(ey2 < 0) return;
min_y = ey2;
}
if(ey2 > max_y) {
if(ey2 > sz.cy) return;
max_y = min(ey2, sz.cy - 1);
}
enum dx_limit_e { dx_limit = 16384 << 8 };
int dx = x2 - x1;
if(dx >= dx_limit || dx <= -dx_limit) {
int cx = (x1 + x2) >> 1;
int cy = (y1 + y2) >> 1;
LineRaw(x1, y1, cx, cy);
LineRaw(cx, cy, x2, y2);
return;
}
int dy = y2 - y1;
int fy1 = y1 & 255;
int fy2 = y2 & 255;
Cell *c;
int x_from, x_to;
int p, rem, mod, lift, delta, first, incr;
if(ey1 == ey2) {
RenderHLine(ey1, x1, fy1, x2, fy2);
return;
}
incr = 1;
if(dx == 0) {
int ex = x1 >> 8;
int two_fx = (x1 - (ex << 8)) << 1;
int area;
first = 256;
if(dy < 0) {
first = 0;
incr = -1;
}
x_from = x1;
delta = first - fy1;
c = AddCells(ey1, 1);
c->x = ex1;
c->cover = delta;
c->area = two_fx * delta;
ey1 += incr;
delta = first + first - 256;
area = two_fx * delta;
while(ey1 != ey2) {
c = AddCells(ey1, 1);
c->x = ex1;
c->cover = delta;
c->area = area;
ey1 += incr;
}
delta = fy2 - 256 + first;
c = AddCells(ey1, 1);
c->x = ex1;
c->cover = delta;
c->area = two_fx * delta;
return;
}
p = (256 - fy1) * dx;
first = 256;
if(dy < 0) {
p = fy1 * dx;
first = 0;
incr = -1;
dy = -dy;
}
delta = p / dy;
mod = p % dy;
if(mod < 0) {
delta--;
mod += dy;
}
x_from = x1 + delta;
RenderHLine(ey1, x1, fy1, x_from, first);
ey1 += incr;
if(ey1 != ey2) {
p = dx << 8;
lift = p / dy;
rem = p % dy;
if(rem < 0) {
lift--;
rem += dy;
}
mod -= dy;
while(ey1 != ey2) {
delta = lift;
mod += rem;
if(mod >= 0) {
mod -= dy;
delta++;
}
x_to = x_from + delta;
RenderHLine(ey1, x_from, 256 - first, x_to, first);
x_from = x_to;
ey1 += incr;
}
}
RenderHLine(ey1, x_from, 256 - first, x2, fy2);
}
void Rasterizer::Filler::End() {}
void Rasterizer::Render(int y, Rasterizer::Filler& g, bool evenodd)
{
PAINTER_TIMING("Render");
const Cell *c, *e;
if(y < min_y || y > max_y) return;
Vector<Cell>& cl = cell[y];
if(cl.GetCount() == 0) return;
Sort(cl);
c = cl;
e = cl.End();
g.Start(c->x, (e - 1)->x);
int cover = 0;
while(c < e) {
int x = c->x;
int area = c->area;
cover += c->cover;
c++;
while(c < e && c->x == x) {
area += c->area;
cover += c->cover;
c++;
}
if(evenodd) {
if(area) {
int h = abs(((cover << 9) - area) >> 9) & 511;
g.Render(h > 256 ? 512 - h : h);
x++;
}
if(c < e && c->x > x) {
int h = abs(cover) & 511;
g.Render(h > 256 ? 512 - h : h, c->x - x);
}
}
else {
if(area) {
g.Render(min(abs(((cover << 9) - area) >> 9), 256));
x++;
}
if(c < e && c->x > x)
g.Render(min(abs(cover), 256), c->x - x);
}
}
g.End();
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,45 @@
class Rasterizer {
Rectf cliprect;
double x1, y1;
Buffer< Vector<dword> > cell;
int xmax, ymax;
int min_y;
int max_y;
Size sz;
inline dword Cell(int x, int w, int c) { return (x << 18) + (w << 9) + c; }
inline int GetX(dword cell) { return cell >> 18; }
inline int GetW(dword cell) { return (cell >> 9) & 511; }
inline int GetC(dword cell) { return (cell & 256) ? -512 | (cell & 511) : (cell & 511); }
void Init();
dword *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);
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 Move(double x, double y);
void Line(double x, double y);
int MinY() const { return min_y; }
int MaxY() const { return max_y; }
void SetClip(const Rectf& rect);
void Render(int y, Target& g);
void Reset();
Rasterizer(int cx, int cy);
};

View file

@ -0,0 +1,103 @@
#include "Painter.h"
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
void Rasterizer::CvLine(double x1, double y1, double x2, double y2)
{
LLOG("CvLine " << x1 << ", " << y1 << " - " << x2 << ", " << y2);
LineRaw(Q8X(x1), Q8Y(y1), Q8X(x2), Q8Y(y2));
}
void Rasterizer::LineClip(double x1, double y1, double x2, double y2)
{
if(y1 < cliprect.top) {
if(y2 < cliprect.top)
return;
x1 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1;
y1 = cliprect.top;
}
else
if(y1 > cliprect.bottom) {
if(y2 > cliprect.bottom)
return;
x1 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1;
y1 = cliprect.bottom;
}
if(y2 < cliprect.top) {
x2 = (x2 - x1) * (cliprect.top - y1) / (y2 - y1) + x1;
y2 = cliprect.top;
}
else
if(y2 > cliprect.bottom) {
x2 = (x2 - x1) * (cliprect.bottom - y1) / (y2 - y1) + x1;
y2 = cliprect.bottom;
}
double y, yy;
if(x1 < cliprect.left) {
if(x2 < cliprect.left) {
CvLine(cliprect.left, y1, cliprect.left, y2);
return;
}
y = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1;
if(x2 > cliprect.right) {
yy = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1;
CvLine(cliprect.left, y1, cliprect.left, y);
CvLine(cliprect.left, y, cliprect.right, yy);
CvLine(cliprect.right, yy, cliprect.right, y2);
return;
}
CvLine(cliprect.left, y1, cliprect.left, y);
CvLine(cliprect.left, y, x2, y2);
return;
}
else
if(x1 > cliprect.right) {
if(x2 > cliprect.right) {
CvLine(cliprect.right, y1, cliprect.right, y2);
return;
}
y = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1;
if(x2 < cliprect.left) {
yy = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1;
CvLine(cliprect.right, y1, cliprect.right, y);
CvLine(cliprect.right, y, cliprect.left, yy);
CvLine(cliprect.left, yy, cliprect.left, y2);
return;
}
CvLine(cliprect.right, y1, cliprect.right, y);
CvLine(cliprect.right, y, x2, y2);
return;
}
if(x2 < cliprect.left) {
y = (y2 - y1) * (cliprect.left - x1) / (x2 - x1) + y1;
CvLine(x1, y1, cliprect.left, y);
CvLine(cliprect.left, y, cliprect.left, y2);
return;
}
else
if(x2 > cliprect.right) {
y = (y2 - y1) * (cliprect.right - x1) / (x2 - x1) + y1;
CvLine(x1, y1, cliprect.right, y);
CvLine(cliprect.right, y, cliprect.right, y2);
return;
}
CvLine(x1, y1, x2, y2);
}
void Rasterizer::Move(const Pointf& p)
{
LLOG("Rasterizer::Move " << p);
p0 = p;
}
void Rasterizer::Line(const Pointf& p)
{
PAINTER_TIMING("Line");
LLOG("Rasterizer::Line " << p);
LineClip(p0.x, p0.y, p.x, p.y);
p0 = p;
}
END_UPP_NAMESPACE

230
newdraw/Painter/Render.cpp Normal file
View file

@ -0,0 +1,230 @@
#include "Painter.h"
#include "Fillers.h"
NAMESPACE_UPP
void BufferPainter::ClearOp(const RGBA& color)
{
UPP::Fill(~ib, color, ib.GetLength());
}
struct BufferPainter::OnPathTarget : LinearPathConsumer {
Vector<BufferPainter::PathLine> path;
Pointf pos;
double len;
virtual void Move(const Pointf& p) {
BufferPainter::PathLine& t = path.Add();
t.len = 0;
pos = t.p = p;
}
virtual void Line(const Pointf& p) {
BufferPainter::PathLine& t = path.Add();
len += (t.len = Distance(pos, p));
pos = t.p = p;
}
OnPathTarget() { len = 0; pos = Pointf(0, 0); }
};
Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
{
Buffer<ClipLine> newclip;
if(width == 0)
return newclip;
Transformer trans(pathattr.mtx);
Stroker stroker;
Dasher dasher;
OnPathTarget onpathtarget;
bool evenodd = pathattr.evenodd;
bool regular = pathattr.mtx.IsRegular() && width < 0 && !ischar;
double tolerance;
LinearPathConsumer *g = &rasterizer;
if(regular)
tolerance = 0.3;
else {
trans.target = g;
g = &trans;
tolerance = 0.3 / attr.mtx.GetScale();
}
if(width == ONPATH) {
g = &onpathtarget;
regular = false;
}
else
if(width > 0) {
stroker.Init(width, pathattr.miter_limit, tolerance, pathattr.cap, pathattr.join);
stroker.target = g;
if(pathattr.dash.GetCount()) {
dasher.Init(pathattr.dash, pathattr.dash_start);
dasher.target = &stroker;
g = &dasher;
}
else
g = &stroker;
evenodd = false;
}
else
Close();
byte *data = path.data;
int opacity = int(256 * pathattr.opacity);
Pointf pos = Pointf(0, 0);
int i = 0;
Rasterizer::Filler *rg;
SpanFiller span_filler;
SolidFiller solid_filler;
SubpixelFiller subpixel_filler;
ClipFiller clip_filler(render_cx);
NoAAFillerFilter noaa_filler;
MaskFillerFilter mf;
bool doclip = width == CLIP;
subpixel_filler.sbuffer = subpixel;
if(doclip) {
rg = &clip_filler;
newclip.Alloc(ib.GetHeight());
}
else
if(ss) {
if(!span)
span.Alloc((subpixel ? 3 : 1) * ib.GetWidth() + 3);
if(subpixel) {
subpixel_filler.ss = ss;
subpixel_filler.buffer = span;
subpixel_filler.alpha = opacity;
rg = &subpixel_filler;
}
else {
span_filler.ss = ss;
span_filler.buffer = span;
span_filler.alpha = opacity;
rg = &span_filler;
}
}
else {
if(subpixel) {
subpixel_filler.color = Mul8(color, opacity);
subpixel_filler.ss = NULL;
rg = &subpixel_filler;
}
else {
solid_filler.c = Mul8(color, opacity);
rg = &solid_filler;
}
}
if(mode == MODE_NOAA) {
noaa_filler.Set(rg);
rg = &noaa_filler;
}
for(;;) {
if(i >= path.type.GetCount() || path.type[i] == DIV) {
g->End();
if(width != ONPATH) {
for(int y = rasterizer.MinY(); y <= rasterizer.MaxY(); y++) {
solid_filler.t = subpixel_filler.t = span_filler.t = ib[y];
subpixel_filler.end = subpixel_filler.t + ib.GetWidth();
span_filler.y = subpixel_filler.y = y;
Rasterizer::Filler *rf = rg;
if(clip.GetCount()) {
const ClipLine& s = clip.Top()[y];
if(s.IsEmpty()) goto empty;
if(!s.IsFull()) {
mf.Set(rg, s);
rf = &mf;
}
}
if(doclip)
clip_filler.Clear();
rasterizer.Render(y, *rf, evenodd);
if(doclip)
clip_filler.Finish(newclip[y]);
empty:;
}
rasterizer.Reset();
}
if(i >= path.type.GetCount())
break;
}
else
switch(path.type[i]) {
case MOVE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Move(pos = regular ? pathattr.mtx.Transform(d->p) : d->p);
break;
}
case LINE: {
const LinearData *d = (LinearData *)data;
data += sizeof(LinearData);
g->Line(pos = regular ? pathattr.mtx.Transform(d->p) : d->p);
break;
}
case QUADRATIC: {
const QuadraticData *d = (QuadraticData *)data;
data += sizeof(QuadraticData);
if(regular) {
Pointf p = pathattr.mtx.Transform(d->p);
ApproximateQuadratic(*g, pos, pathattr.mtx.Transform(d->p1), p, tolerance);
pos = p;
}
else {
ApproximateQuadratic(*g, pos, d->p1, d->p, tolerance);
pos = d->p;
}
break;
}
case CUBIC: {
const CubicData *d = (CubicData *)data;
data += sizeof(CubicData);
if(regular) {
Pointf p = pathattr.mtx.Transform(d->p);
ApproximateCubic(*g, pos, pathattr.mtx.Transform(d->p1),
pathattr.mtx.Transform(d->p2), p, tolerance);
pos = p;
}
else {
ApproximateCubic(*g, pos, d->p1, d->p2, d->p, tolerance);
pos = d->p;
}
break;
}
case CHAR:
ApproximateChar(*g, *(CharData *)data, tolerance);
data += sizeof(CharData);
break;
default:
NEVER();
return newclip;
}
i++;
}
current = Null;
if(width == ONPATH) {
onpath = onpathtarget.path;
pathlen = onpathtarget.len;
}
return newclip;
}
void BufferPainter::FillOp(const RGBA& color)
{
RenderPath(FILL, NULL, color);
}
void BufferPainter::StrokeOp(double width, const RGBA& color)
{
RenderPath(width, NULL, color);
}
void BufferPainter::ClipOp()
{
Buffer<ClipLine> newclip = RenderPath(CLIP, NULL, RGBAZero());
if(attr.hasclip)
clip.Top() = newclip;
else {
clip.Add() = newclip;
attr.hasclip = true;
attr.cliplevel = clip.GetCount();
}
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,127 @@
#include "Painter.h"
NAMESPACE_UPP
struct GlyphPainter : NilPainter, LinearPathConsumer {
Vector<float> glyph;
double tolerance;
Pointf pos, move;
virtual void LineOp(const Pointf& p, bool);
virtual void MoveOp(const Pointf& p, bool);
virtual void QuadraticOp(const Pointf& p1, const Pointf& p, bool);
virtual void CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool);
virtual void CloseOp();
virtual void Line(const Pointf& p);
virtual void Move(const Pointf& p);
};
void GlyphPainter::Move(const Pointf& p)
{
glyph.Add((float)1e31);
Line(p);
move = pos;
}
void GlyphPainter::Line(const Pointf& p)
{
glyph.Add((float)p.x);
glyph.Add((float)p.y);
pos = p;
}
void GlyphPainter::MoveOp(const Pointf& p, bool)
{
Move(p);
}
void GlyphPainter::LineOp(const Pointf& p, bool)
{
Line(p);
}
void GlyphPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool)
{
ApproximateQuadratic(*this, pos, p1, p, tolerance);
pos = p;
}
void GlyphPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool)
{
ApproximateCubic(*this, pos, p1, p2, p, tolerance);
pos = p;
}
void GlyphPainter::CloseOp()
{
if(move != pos && !IsNull(move))
Line(move);
}
struct GlyphKey {
Font fnt;
int chr;
double tolerance;
bool operator==(const GlyphKey& b) const {
return fnt == b.fnt && chr == b.chr && tolerance == b.tolerance;
}
unsigned GetHashValue() const {
return CombineHash(fnt, chr, tolerance);
}
};
struct sMakeGlyph : LRUCache<Value, GlyphKey>::Maker {
GlyphKey gk;
GlyphKey Key() const { return gk; }
int Make(Value& v) const {
GlyphPainter gp;
gp.move = gp.pos = Null;
gp.tolerance = gk.tolerance;
PaintCharacter(gp, Pointf(0, 0), gk.chr, gk.fnt);
int sz = gp.glyph.GetCount() * 4;
v = RawPickToValue(gp.glyph);
return sz;
}
};
void BufferPainter::ApproximateChar(LinearPathConsumer& t, const CharData& ch, double tolerance)
{
Value v;
INTERLOCKED {
static LRUCache<Value, GlyphKey> cache;
cache.Shrink(500000);
sMakeGlyph h;
h.gk.fnt = ch.fnt;
h.gk.chr = ch.ch;
h.gk.tolerance = tolerance;
v = cache.Get(h);
}
#if 0
GlyphPainter chp;
chp.move = chp.pos = Null;
chp.tolerance = tolerance;
PaintCharacter(chp, ch.p, ch.ch, ch.fnt);
Vector<float>& g = chp.glyph;
#else
const Vector<float>& g = ValueTo< Vector<float> >(v);
#endif
int i = 0;
while(i < g.GetCount()) {
Pointf p;
p.x = g[i++];
if(p.x > 1e30) {
p.x = g[i++];
p.y = g[i++];
t.Move(p + ch.p);
}
else {
p.y = g[i++];
t.Line(p + ch.p);
}
}
}
END_UPP_NAMESPACE

162
newdraw/Painter/Stroker.cpp Normal file
View file

@ -0,0 +1,162 @@
#include "Painter.h"
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
void Stroker::Init(double width, double miterlimit, double tolerance, int _linecap, int _linejoin)
{
linecap = _linecap;
linejoin = _linejoin;
w2 = width / 2;
qmiter = miterlimit * w2;
qmiter *= qmiter;
fid = acos(1 - tolerance / w2);
p0 = p1 = p2 = Null;
}
void Stroker::Move(const Pointf& p)
{
LLOG("Stroker::Move " << p);
Finish();
p1 = p;
p0 = p2 = Null;
}
void Stroker::Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double r)
{
double a1 = Bearing(v1);
double a2 = Bearing(v2);
if(a1 < a2)
a1 += 2 * M_PI;
while(a1 > a2) {
PutLine(Polar(p, r, a1));
a1 -= fid;
}
}
void Stroker::Line(const Pointf& p3)
{
LLOG("Stroker::Line " << p3);
if(IsNull(p1)) {
Move(p3);
return;
}
if(IsNull(p2)) {
Pointf v = p3 - p1;
double l = Length(v);
if(l < 1e-30)
return;
p2 = p3;
v1 = v;
o1 = Orthogonal(v1) * w2 / l;
a1 = p1 + o1;
b1 = p1 - o1;
if(IsNull(p0)) {
p0 = p1;
v0 = v1;
o0 = o1;
a0 = a1;
b0 = b1;
}
return;
}
Pointf v2 = p3 - p2;
double l = Length(v2);
if(l < 1e-30)
return;
Pointf o2 = Orthogonal(v2) * w2 / l;
Pointf a2 = p2 + o2;
Pointf b2 = p2 - o2;
double d = v1.y * v2.x - v2.y * v1.x;
if(d > 1e-30) {
Pointf ts = a1 + v1 * (v2.y * (a1.x - a2.x) - v2.x * (a1.y - a2.y)) / d;
PutMove(a1);
if(linejoin != LINEJOIN_MITER || SquaredDistance(ts, p2) > qmiter) {
PutLine(a1 + v1);
if(linejoin == LINEJOIN_ROUND)
Round(p2, o1, o2, w2);
}
else
PutLine(ts);
PutLine(a2);
PutMove(b2);
PutLine(p2);
PutLine(b1 + v1);
PutLine(b1);
}
else
if(d < -1e-30) {
Pointf ts = b2 + v2 * (v1.y * (a2.x - a1.x) - v1.x * (a2.y - a1.y)) / d;
PutMove(b2);
if(linejoin != LINEJOIN_MITER || SquaredDistance(ts, p2) > qmiter) {
if(linejoin == LINEJOIN_ROUND)
Round(p2, -o2, -o1, w2);
PutLine(b1 + v1);
}
else
PutLine(ts);
PutLine(b1);
PutMove(a1);
PutLine(a1 + v1);
PutLine(p2);
PutLine(a2);
}
else {
PutMove(a1);
PutLine(a1 + v1);
if(linejoin == LINEJOIN_ROUND)
Round(p2, o1, o2, w2);
PutLine(a2);
PutMove(b2);
PutLine(b1 + v1);
PutLine(b1);
}
p1 = p2;
v1 = v2;
o1 = o2;
a1 = a2;
b1 = b2;
p2 = p3;
}
void Stroker::Cap(const Pointf& p, const Pointf& v, const Pointf& o,
const Pointf& a, const Pointf& b)
{
PutMove(a);
if(linecap == LINECAP_SQUARE) {
Pointf nv = Orthogonal(o);
PutLine(a + nv);
PutLine(b + nv);
}
if(linecap == LINECAP_ROUND)
Round(p, -o, o, w2);
PutLine(b);
}
void Stroker::Finish()
{
if(IsNull(p1) || IsNull(p2) || IsNull(p0))
return;
if(p2 == p0)
Line(p0 + v0);
else {
PutMove(a1);
PutLine(a1 + v1);
PutMove(b1 + v1);
PutLine(b1);
Cap(p0, v0, o0, b0, a0);
Cap(p2, -v1, -o1, a1 + v1, b1 + v1);
}
p0 = p1 = p2 = Null;
}
void Stroker::End()
{
Finish();
PutEnd();
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,67 @@
#include "Painter.h"
NAMESPACE_UPP
void Painter::DoArc0(double theta, double th_sweep, const Xform2D& m)
{
int nsegs = int(ceil(fabs(th_sweep / (M_PI * 0.5 + 0.001))));
for(int i = 0; i < nsegs; i++) {
double th0 = theta + i * th_sweep / nsegs;
double th1 = theta + (i + 1) * th_sweep / nsegs;
double thHalf = 0.5 * (th1 - th0);
double t = (8.0 / 3.0) * sin(thHalf * 0.5) * sin(thHalf * 0.5) / sin(thHalf);
double x3 = cos(th1);
double y3 = sin(th1);
Cubic(m.Transform(cos(th0) - t * sin(th0), sin(th0) + t * cos(th0)),
m.Transform(x3 + t * sin(th1), y3 - t * cos(th1)),
m.Transform(x3, y3));
}
}
void Painter::DoArc(const Pointf& c, const Pointf& r, double angle, double sweep, double xangle)
{
Xform2D m = Xform2D::Scale(r.x, r.y);
m = m * Xform2D::Translation(c.x, c.y);
Line(m.Transform(cos(angle), sin(angle)));
DoArc0(angle, sweep, m);
}
void Painter::DoSvgArc(const Pointf& rr, double xangle, int large, int sweep,
const Pointf& p1, const Pointf& p0)
{
Pointf r(fabs(rr.x), fabs(rr.y));
Xform2D m = Xform2D::Rotation(-xangle);
Pointf d1 = m.Transform(0.5 * (p0 - p1));
Pointf pr = r * r;
Pointf p = d1 * d1;
double check = p.x / pr.x + p.y / pr.y;
if(check > 1)
r *= sqrt(check);
m.x /= r.x;
m.y /= r.y;
Pointf q0 = m.Transform(p0);
Pointf q1 = m.Transform(p1);
double d = SquaredDistance(q0, q1);
double sfactor_sq = 1.0 / d - 0.25;
if(sfactor_sq < 0)
sfactor_sq = 0;
double sfactor = sqrt(sfactor_sq);
if(sweep == large)
sfactor = -sfactor;
Pointf c(0.5 * (q0.x + q1.x) - sfactor * (q1.y - q0.y),
0.5 * (q0.y + q1.y) + sfactor * (q1.x - q0.x));
double theta = Bearing(q0 - c);
double th_sweep = Bearing(q1 - c) - theta;
if(th_sweep < 0 && sweep)
th_sweep += 2 * M_PI;
else
if(th_sweep > 0 && !sweep)
th_sweep -= 2 * M_PI;
m = Xform2D::Rotation(xangle);
m.x *= r;
m.y *= r;
m = Xform2D::Translation(c.x, c.y) * m;
DoArc0(theta, th_sweep, m);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,24 @@
#include "Painter.h"
NAMESPACE_UPP
void LinearPathConsumer::End()
{
}
void LinearPathFilter::End()
{
PutEnd();
}
void Transformer::Move(const Pointf& p)
{
PutMove(xform.Transform(p));
}
void Transformer::Line(const Pointf& p)
{
PutLine(xform.Transform(p));
}
END_UPP_NAMESPACE

115
newdraw/Painter/Xform2D.cpp Normal file
View file

@ -0,0 +1,115 @@
#include "Painter.h"
NAMESPACE_UPP
Pointf Xform2D::Transform(const Pointf& f) const
{
PAINTER_TIMING("Transform");
return Pointf(f.x * x.x + f.y * x.y + t.x, f.x * y.x + f.y * y.y + t.y);
}
Pointf Xform2D::Transform(double x, double y) const
{
return Transform(Pointf(x, y));
}
Pointf Xform2D::GetScaleXY() const
{
return Pointf(sqrt(x.x * x.x + y.x * y.x), sqrt(x.y * x.y + y.y * y.y));
}
double Xform2D::GetScale() const
{
Pointf d = GetScaleXY();
return Length(d) / M_SQRT2;
}
bool Xform2D::IsRegular() const
{
Pointf d = GetScaleXY();
return fabs(d.x - d.y) < 1e-10 * fabs(max(d.x, d.y));
}
Xform2D::Xform2D()
{
x.x = y.y = 1;
x.y = y.x = t.x = t.y = 0;
}
Xform2D operator*(const Xform2D& a, const Xform2D& b)
{
Xform2D r;
r.x.x = a.x.x * b.x.x + a.y.x * b.x.y;
r.x.y = a.x.y * b.x.x + a.y.y * b.x.y;
r.y.x = a.x.x * b.y.x + a.y.x * b.y.y;
r.y.y = a.x.y * b.y.x + a.y.y * b.y.y;
r.t.x = a.t.x * b.x.x + a.t.y * b.x.y + b.t.x;
r.t.y = a.t.x * b.y.x + a.t.y * b.y.y + b.t.y;
return r;
}
Xform2D Xform2D::Translation(double x, double y)
{
Xform2D m;
m.x.x = m.y.y = 1;
m.t = Pointf(x, y);
return m;
}
Xform2D Xform2D::Scale(double sx, double sy)
{
Xform2D m;
m.x.x = sx;
m.y.y = sy;
return m;
}
Xform2D Xform2D::Scale(double scale)
{
return Scale(scale, scale);
}
Xform2D Xform2D::Rotation(double fi)
{
double cosf = cos(fi);
double sinf = sin(fi);
Xform2D m;
m.x.x = cosf;
m.x.y = -sinf;
m.y.x = sinf;
m.y.y = cosf;
m.t.x = m.t.y = 0;
return m;
}
Xform2D Xform2D::Sheer(double fi)
{
Xform2D m;
m.x.x = m.y.y = 1;
m.x.y = atan(fi);
return m;
}
Xform2D Xform2D::Identity()
{
Xform2D m;
return m;
}
double Determinant(const Xform2D& m)
{
return m.x.x * m.y.y - m.y.x * m.x.y;
}
Xform2D Inverse(const Xform2D& m)
{
Xform2D r;
double det = Determinant(m);
r.x = Pointf(m.y.y, -m.x.y) / det;
r.y = Pointf(-m.y.x, m.x.x) / det;
r.t.x = -m.t.x * r.x.x - m.t.y * r.x.y;
r.t.y = -m.t.x * r.y.x - m.t.y * r.y.y;
return r;
}
END_UPP_NAMESPACE

8
newdraw/Painter/init Normal file
View file

@ -0,0 +1,8 @@
#ifndef _Painter_icpp_init_stub
#define _Painter_icpp_init_stub
#include "Core/init"
#include "CtrlLib/init"
#define BLITZ_INDEX__ FE26D1A011428E19BAEAFE2F1E9FA2F00
#include "PaintPainting.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -0,0 +1,29 @@
topic "";
[ $$0,0#00000000000000000000000000000000:Default]
[H6;0 $$1,0#05600065144404261032431302351956:begin]
[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem]
[l288;2 $$3,0#27521748481378242620020725143825:desc]
[0 $$4,0#96390100711032703541132217272105:end]
[{_}%EN-US
[s1;%- &]
[s2;:SubpixelFiller`:`:Write`(int`):%- [@(0.0.255) void]_[* Write]([@(0.0.255) int]_[*@3 len])
&]
[s3; This function writes the filtered subpixel buffer to RGBA output,
performing per`-channel (subpixel) alpha blending. Note that
it is only possible to do correct per`-channel blending when
target is opaque (a `=`= 255). If it is not, normal anti`-aliasing
is used, using average.&]
[s3; Important note: due to rounding errors during filtering, sometimes
the subpixel value can be 257. This is remedied by using 257
instead of 256 in the pixel blending command.&]
[s0; &]
[s4; &]
[s1;%- &]
[s2;:SubpixelFiller`:`:RenderN`(int`,int`,int`):%- [@(0.0.255) void]_[* RenderN]([@(0.0.255) i
nt]_[*@3 val], [@(0.0.255) int]_[*@3 h], [@(0.0.255) int]_[*@3 n])&]
[s3; This function adds 1 `- 6 val values to filtered subpixel buffer
in single pass (6 is just enough needed for Render optimizations).
Case variants are created by adding shifted Render filtering
procedures.&]
[s4; &]
[s0; ]

View file

@ -13,7 +13,7 @@ dword PdfDraw::GetInfo() const
return DOTS;
}
Size PdfDraw::GetPagePixels() const
Size PdfDraw::GetPageSize() const
{
return pgsz;
}

View file

@ -228,7 +228,7 @@ public:
class PdfDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPagePixels() const;
virtual Size GetPageSize() const;
virtual void StartPage();
virtual void EndPage();