mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 14:55:57 -06:00
developing newdraw
git-svn-id: svn://ultimatepp.org/upp/trunk@1162 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
ee152d30f4
commit
587b532024
46 changed files with 5755 additions and 81 deletions
|
|
@ -37,7 +37,7 @@ bool ScreenInPaletteMode()
|
|||
|
||||
Size GetScreenSize()
|
||||
{
|
||||
return ScreenInfo().GetPagePixels();
|
||||
return ScreenInfo().GetPageSize();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ dword DrawingDraw::GetInfo() const
|
|||
return DOTS;
|
||||
}
|
||||
|
||||
Size DrawingDraw::GetPagePixels() const
|
||||
Size DrawingDraw::GetPageSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
74
newdraw/Painter/Approximate.cpp
Normal file
74
newdraw/Painter/Approximate.cpp
Normal 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
|
||||
361
newdraw/Painter/BufferPainter.h
Normal file
361
newdraw/Painter/BufferPainter.h
Normal 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
133
newdraw/Painter/Context.cpp
Normal 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
21
newdraw/Painter/Copying
Normal 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.
|
||||
62
newdraw/Painter/Dasher.cpp
Normal file
62
newdraw/Painter/Dasher.cpp
Normal 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
137
newdraw/Painter/DrawOp.cpp
Normal 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
465
newdraw/Painter/Fillers.cpp
Normal 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
93
newdraw/Painter/Fillers.h
Normal 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
|
||||
86
newdraw/Painter/FontWin32.cpp
Normal file
86
newdraw/Painter/FontWin32.cpp
Normal 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
153
newdraw/Painter/FontX11.cpp
Normal 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
|
||||
65
newdraw/Painter/Gradient.cpp
Normal file
65
newdraw/Painter/Gradient.cpp
Normal 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
239
newdraw/Painter/Image.cpp
Normal 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
|
||||
45
newdraw/Painter/Interpolator.cpp
Normal file
45
newdraw/Painter/Interpolator.cpp
Normal 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
90
newdraw/Painter/Mask.cpp
Normal 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
|
||||
33
newdraw/Painter/OnPath.cpp
Normal file
33
newdraw/Painter/OnPath.cpp
Normal 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
|
||||
269
newdraw/Painter/PaintPainting.icpp
Normal file
269
newdraw/Painter/PaintPainting.icpp
Normal 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
554
newdraw/Painter/Painter.cpp
Normal 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
404
newdraw/Painter/Painter.h
Normal 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
232
newdraw/Painter/Painter.hpp
Normal 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;
|
||||
}
|
||||
42
newdraw/Painter/Painter.upp
Normal file
42
newdraw/Painter/Painter.upp
Normal 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;
|
||||
|
||||
107
newdraw/Painter/PainterPath.cpp
Normal file
107
newdraw/Painter/PainterPath.cpp
Normal 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
|
||||
287
newdraw/Painter/Painting.cpp
Normal file
287
newdraw/Painter/Painting.cpp
Normal 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
137
newdraw/Painter/Painting.h
Normal 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
136
newdraw/Painter/Path.cpp
Normal 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
|
||||
82
newdraw/Painter/RadialGradient.cpp
Normal file
82
newdraw/Painter/RadialGradient.cpp
Normal 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
|
||||
356
newdraw/Painter/Rasterizer.cpp
Normal file
356
newdraw/Painter/Rasterizer.cpp
Normal 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
|
||||
45
newdraw/Painter/Rasterizer3.h
Normal file
45
newdraw/Painter/Rasterizer3.h
Normal 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);
|
||||
};
|
||||
103
newdraw/Painter/RasterizerClip.cpp
Normal file
103
newdraw/Painter/RasterizerClip.cpp
Normal 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
230
newdraw/Painter/Render.cpp
Normal 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
|
||||
127
newdraw/Painter/RenderChar.cpp
Normal file
127
newdraw/Painter/RenderChar.cpp
Normal 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
162
newdraw/Painter/Stroker.cpp
Normal 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
|
||||
67
newdraw/Painter/SvgArc.cpp
Normal file
67
newdraw/Painter/SvgArc.cpp
Normal 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
|
||||
24
newdraw/Painter/Transformer.cpp
Normal file
24
newdraw/Painter/Transformer.cpp
Normal 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
115
newdraw/Painter/Xform2D.cpp
Normal 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
8
newdraw/Painter/init
Normal 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
|
||||
29
newdraw/Painter/srcimp.tpp/SubpixelFiller$en-us.tpp
Normal file
29
newdraw/Painter/srcimp.tpp/SubpixelFiller$en-us.tpp
Normal 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; ]
|
||||
|
|
@ -13,7 +13,7 @@ dword PdfDraw::GetInfo() const
|
|||
return DOTS;
|
||||
}
|
||||
|
||||
Size PdfDraw::GetPagePixels() const
|
||||
Size PdfDraw::GetPageSize() const
|
||||
{
|
||||
return pgsz;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue