ultimatepp/uppdev/SDraw/SDraw.cpp
cxl 3d718b6028 SDraw dev
git-svn-id: svn://ultimatepp.org/upp/trunk@721 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-01-02 21:50:57 +00:00

296 lines
7 KiB
C++

#include "SDraw.h"
NAMESPACE_UPP
#define LTIMING(x) RTIMING(x)
SDraw& SDraw::MoveTo(double x, double y)
{
if(inpath)
path.close_polygon();
else
path.remove_all();
path.move_to(x, y);
inpath = true;
return *this;
}
SDraw& SDraw::LineTo(double x, double y)
{
if(!inpath)
path.remove_all();
path.line_to(x, y);
inpath = true;
return *this;
}
SDraw& SDraw::Quadratic(double x1, double y1, double x, double y)
{
path.curve3(x1, y1, x, y);
return *this;
}
SDraw& SDraw::Quadratic(double x, double y)
{
path.curve3(x, y);
return *this;
}
SDraw& SDraw::Cubic(double x1, double y1, double x2, double y2, double x, double y)
{
path.curve4(x1, y1, x2, y2, x, y);
return *this;
}
SDraw& SDraw::Cubic(double x2, double y2, double x, double y)
{
path.curve4(x2, y2, x, y);
return *this;
}
SDraw& SDraw::Close()
{
path.close_polygon();
return *this;
}
SDraw& SDraw::Fill()
{
LTIMING("Fill");
if(inpath)
path.close_polygon();
rasterizer.reset();
rasterizer.filling_rule(attr.evenodd ? agg::fill_even_odd : agg::fill_non_zero);
rasterizer.add_path(curved_trans);
renderer.color(*(color_type *)&attr.fill);
if(mask.GetCount()) {
agg::rendering_buffer mask_rbuf;
mask_rbuf.attach(~mask.Top(), size.cx, size.cy, size.cx);
agg::alpha_mask_gray8 mask(mask_rbuf);
agg::scanline_u8_am<agg::alpha_mask_gray8> sl(mask);
if(attr.antialiased) {
renderer.color(*(color_type *)&attr.fill);
agg::render_scanlines(rasterizer, sl, renderer);
}
else {
rendererb.color(*(color_type *)&attr.fill);
agg::render_scanlines(rasterizer, sl, rendererb);
}
}
else
if(attr.antialiased) {
renderer.color(*(color_type *)&attr.fill);
agg::render_scanlines(rasterizer, scanline_p, renderer);
}
else {
rendererb.color(*(color_type *)&attr.fill);
agg::render_scanlines(rasterizer, scanline_p, rendererb);
}
rasterizer.reset();
inpath = false;
return *this;
}
SDraw& SDraw::FillMask(int alpha)
{
if(mask.GetCount() == 0) {
mask.Add().Alloc(size.cx * size.cy);
memset(~mask.Top(), 255, size.cx * size.cy);
}
agg::rendering_buffer mask_rbuf;
mask_rbuf.attach(~mask.Top(), size.cx, size.cy, size.cx);
typedef agg::renderer_base<agg::pixfmt_gray8> ren_base;
agg::pixfmt_gray8 pixf(mask_rbuf);
ren_base rb(pixf);
agg::scanline_p8 sl;
if(inpath)
path.close_polygon();
rasterizer.reset();
rasterizer.filling_rule(attr.evenodd ? agg::fill_even_odd : agg::fill_non_zero);
rasterizer.add_path(curved_trans);
if(attr.antialiased) {
agg::renderer_scanline_aa_solid<ren_base> r(rb);
r.color(agg::gray8(alpha, 255));
agg::render_scanlines(rasterizer, sl, r);
}
else {
agg::renderer_scanline_bin_solid<ren_base> r(rb);
r.color(agg::gray8(alpha, 255));
agg::render_scanlines(rasterizer, sl, r);
}
rasterizer.reset();
inpath = false;
return *this;
}
SDraw& SDraw::Fill(const Image& image, const Matrix2D& transsrc, int alpha, bool tile)
{
if(image.GetWidth() == 0 || image.GetHeight() == 0)
return *this;
span_alloc sa;
Matrix2D m = attr.mtx * transsrc;
m.invert();
interpolator_type interpolator(m);
Size isz = image.GetSize();
agg::rendering_buffer buf((agg::int8u*)~image, isz.cx, isz.cy, isz.cx * sizeof(RGBA));
pixfmt img_pixf(buf);
if(inpath)
path.close_polygon();
rasterizer.reset();
rasterizer.filling_rule(attr.evenodd ? agg::fill_even_odd : agg::fill_non_zero);
path.arrange_orientations_all_paths(agg::path_flags_cw);
rasterizer.add_path(curved_trans);
span_gen_type sg(img_pixf, agg::rgba8_pre(0, 0, 0, 0), interpolator);
sg.alpha(alpha);
sg.tile(tile);
if(mask.GetCount()) {
agg::rendering_buffer mask_rbuf;
mask_rbuf.attach(~mask.Top(), size.cx, size.cy, size.cx);
agg::alpha_mask_gray8 mask(mask_rbuf);
agg::scanline_u8_am<agg::alpha_mask_gray8> sl(mask);
renderer.color(*(color_type *)&attr.fill);
agg::render_scanlines_aa(rasterizer, sl, renb, sa, sg);
}
else
agg::render_scanlines_aa(rasterizer, scanline_p, renb, sa, sg);
rasterizer.reset();
inpath = false;
return *this;
}
SDraw& SDraw::Stroke()
{
double scl = attr.mtx.scale();
curved.approximation_scale(scl);
curved.angle_tolerance(0.0);
curved_stroked.width(attr.width);
curved_stroked.line_join((agg::line_join_e)attr.join);
curved_stroked.line_cap((agg::line_cap_e)attr.cap);
curved_stroked.miter_limit(attr.miter_limit);
curved_stroked.approximation_scale(scl);
if(attr.width * scl > 1.0)
curved.angle_tolerance(0.2);
rasterizer.reset();
rasterizer.filling_rule(agg::fill_non_zero);
rasterizer.add_path(curved_stroked_trans);
if(mask.GetCount()) {
agg::rendering_buffer mask_rbuf;
mask_rbuf.attach(~mask.Top(), size.cx, size.cy, size.cx);
agg::alpha_mask_gray8 mask(mask_rbuf);
agg::scanline_u8_am<agg::alpha_mask_gray8> sl(mask);
if(attr.antialiased) {
renderer.color(*(color_type *)&attr.stroke);
agg::render_scanlines(rasterizer, sl, renderer);
}
else {
rendererb.color(*(color_type *)&attr.stroke);
agg::render_scanlines(rasterizer, sl, rendererb);
}
}
else
if(attr.antialiased) {
renderer.color(*(color_type *)&attr.stroke);
agg::render_scanlines(rasterizer, scanline_p, renderer);
}
else {
rendererb.color(*(color_type *)&attr.stroke);
agg::render_scanlines(rasterizer, scanline_p, rendererb);
}
rasterizer.reset();
inpath = false;
return *this;
}
Pointf SDraw::Current() const
{
return Pointf(path.last_x(), path.last_y());
}
SDraw& SDraw::Fill(const RGBA& rgba)
{
attr.fill = rgba;
Fill();
return *this;
}
SDraw& SDraw::Stroke(const RGBA& rgba, double width)
{
attr.stroke = rgba;
attr.width = width;
Stroke();
return *this;
}
SDraw& SDraw::Stroke(const RGBA& rgba)
{
attr.stroke = rgba;
Stroke();
return *this;
}
void SDraw::Translate(double x, double y)
{
attr.mtx.tx += x;
attr.mtx.ty += y;
}
void SDraw::Rotate(double a)
{
attr.mtx *= agg::trans_affine_rotation(a);
}
void SDraw::Scale(double scalex, double scaley)
{
attr.mtx *= agg::trans_affine_scaling(scalex, scaley);
}
void SDraw::Scale(double scale)
{
attr.mtx *= agg::trans_affine_scaling(scale);
}
void SDraw::Begin()
{
attrstack.Add(attr);
}
void SDraw::End()
{
if(attrstack.GetCount() == 0) {
ASSERT_(0, "SDraw::End: attribute stack is empty");
return;
}
attr = attrstack.Pop();
}
SDraw::SDraw(ImageBuffer& ib)
: buffer(ib),
curved(path),
curved_stroked(curved),
curved_stroked_trans(curved_stroked, attr.mtx),
curved_trans(curved, attr.mtx)
{
size = ib.GetSize();
UPP::Fill(~buffer, White(), buffer.GetLength()); //!!!
rbuf.attach((agg::int8u *)~buffer, size.cx, size.cy, size.cx * 4);
pixf.attach(rbuf);
renb.attach(pixf);
renderer.attach(renb);
rendererb.attach(renb);
inpath = false;
attr.cap = LINECAP_BUTT;
attr.join = LINEJOIN_MITER;
attr.miter_limit = 4;
attr.width = 1;
attr.evenodd = false;
attr.fill = attr.stroke = Black();
attr.antialiased = true;
}
END_UPP_NAMESPACE