ultimatepp/uppsrc/Painter/Context.cpp
mirek-fidler 2d0f19053a
Painter2 (#182)
Painter improvements: Multithreaded rendering improved, new image filter (like Lanczos 3) option, image mapping is now more precise
2023-12-24 15:21:23 +01:00

229 lines
4.4 KiB
C++

#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();
if(clip.GetCount() != attr.cliplevel || attr.mask)
Finish();
clip.SetCount(attr.cliplevel);
if(attr.mask)
FinishMask();
if(attr.onpath) {
attr.onpath = false;
onpath = pick(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;
pathattr.mtx_serial = attr.mtx_serial = ++mtx_serial;
}
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::InvertOp(bool invert)
{
pathattr.invert = invert;
if(IsNull(current))
attr.invert = invert;
}
void BufferPainter::ImageFilterOp(int filter)
{
pathattr.filter = filter;
if(IsNull(current))
attr.invert = filter;
}
Vector<double> StringToDash(const String& dash, double& start);
void BufferPainter::DashOp(const String& dash, double start)
{
String key;
if(start) {
key.Cat(1);
RawCat(key, start);
}
else
key.Cat(2);
RawCat(key, dash);
const DashInfo *d = dashes.FindPtr(key);
if(!d) {
DashInfo& h = dashes.Add(key);
h.dash = StringToDash(dash, start);
h.start = start;
d = &h;
}
pathattr.dash = d;
if(IsNull(current))
attr.dash = d;
}
void BufferPainter::DashOp(const Vector<double>& dash, double start)
{
String key;
RawCat(key, 0);
RawCat(key, start);
for(double h : dash)
RawCat(key, h);
const DashInfo *d = dashes.FindPtr(key);
if(!d) {
DashInfo& h = dashes.Add(key);
h.start = start;
h.dash = clone(dash);
d = &h;
}
pathattr.dash = d;
if(IsNull(current))
attr.dash = d;
}
void BufferPainter::ColorStop0(Attr& a, double pos, const RGBA& color)
{
pos = minmax(pos, 0.0, 1.0);
ColorStop c;
c.color = color;
c.stop = pos;
int i = FindLowerBound(a.color_stop, c);
a.color_stop.Insert(i, c);
}
void BufferPainter::ColorStopOp(double pos, const RGBA& color)
{
ColorStop0(pathattr, pos, color);
if(IsNull(current))
ColorStop0(attr, pos, color);
}
void BufferPainter::ClearStopsOp()
{
pathattr.color_stop.Clear();
if(IsNull(current))
attr.color_stop.Clear();
}
void BufferPainter::Create(ImageBuffer& ib, int mode_)
{
ip = &ib;
ip->SetKind(IMAGE_ALPHA);
if(mode_ != mode || (Size)size != ib.GetSize()) {
mode = mode_;
rasterizer.Create(ib.GetWidth(), ib.GetHeight(), mode == MODE_SUBPIXEL);
cojob.Clear();
cofill.Clear();
render_cx = ib.GetWidth();
if(mode == MODE_SUBPIXEL) {
render_cx *= 3;
subpixel.Alloc(render_cx + 30);
}
else
subpixel.Clear();
size = ib.GetSize();
co_subpixel.Clear();
co_span.Clear();
span.Clear();
co_clear.Clear();
}
SyncCo();
if(!paths)
paths.Alloc(BATCH_SIZE);
path_info = paths;
attr.mtx = Xform2D::Identity();
attr.cap = LINECAP_BUTT;
attr.join = LINEJOIN_MITER;
attr.miter_limit = 4;
attr.evenodd = false;
attr.hasclip = false;
attr.cliplevel = 0;
attr.opacity = 1;
attr.dash = NULL;
attr.mask = false;
attr.invert = false;
attr.mtx_serial = 0;
pathattr = attr;
ClearPath();
jobcount = fillcount = emptycount = 0;
attrstack.Clear();
clip.Clear();
mask.Clear();
onpathstack.Clear();
pathlenstack.Clear();
onpath.Clear();
preclip_mtx_serial = -1;
path_index = 0;
}
BufferPainter::BufferPainter(PainterTarget& t, double tolerance)
: BufferPainter(dummy, MODE_ANTIALIASED)
{
alt = &t;
alt_tolerance = tolerance;
dummy.Create(1, 1);
}
}