mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Draw: DDARasterizer, IconDes: Now using DDARasterizer
git-svn-id: svn://ultimatepp.org/upp/trunk@6058 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
d7440ace2a
commit
6055936466
10 changed files with 433 additions and 3 deletions
215
uppsrc/Draw/DDARasterizer.cpp
Normal file
215
uppsrc/Draw/DDARasterizer.cpp
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
DDARasterizer::DDARasterizer()
|
||||
{
|
||||
cy = 0;
|
||||
p0 = p1 = Point(0, 0);
|
||||
width = 1;
|
||||
}
|
||||
|
||||
void DDARasterizer::AHorz(int x, int y, int cx)
|
||||
{
|
||||
if(cx)
|
||||
if(cx < 0)
|
||||
PutHorz(x + cx + 1, y, -cx);
|
||||
else
|
||||
PutHorz(x, y, cx);
|
||||
}
|
||||
|
||||
void DDARasterizer::AVert(int x, int y, int cy)
|
||||
{
|
||||
if(cy)
|
||||
if(cy < 0)
|
||||
PutVert(x, y + cy + 1, -cy);
|
||||
else
|
||||
PutVert(x, y, cy);
|
||||
}
|
||||
|
||||
void DDARasterizer::DoLine(Point p1, Point p2, bool last)
|
||||
{
|
||||
dirx = sgn(p2.x - p1.x);
|
||||
diry = sgn(p2.y - p1.y);
|
||||
int dx = abs(p2.x - p1.x);
|
||||
int dy = abs(p2.y - p1.y);
|
||||
int x = p1.x;
|
||||
int y = p1.y;
|
||||
int x0 = x;
|
||||
int y0 = y;
|
||||
if(dx < dy) {
|
||||
int dda = dy >> 1;
|
||||
int n = dy + last;
|
||||
for(;;) {
|
||||
if(x != x0) {
|
||||
AVert(x0, y0, y - y0);
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
if(n-- <= 0)
|
||||
break;
|
||||
y += diry;
|
||||
dda -= dx;
|
||||
if(dda < 0) {
|
||||
dda += dy;
|
||||
x += dirx;
|
||||
}
|
||||
}
|
||||
AVert(x0, y0, y - y0);
|
||||
}
|
||||
else {
|
||||
int dda = dx >> 1;
|
||||
int n = dx + last;
|
||||
for(;;) {
|
||||
if(y != y0) {
|
||||
AHorz(x0, y0, x - x0);
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
if(n-- <= 0)
|
||||
break;
|
||||
x += dirx;
|
||||
dda -= dy;
|
||||
if(dda < 0) {
|
||||
dda += dx;
|
||||
y += diry;
|
||||
}
|
||||
}
|
||||
AHorz(x0, y0, x - x0);
|
||||
}
|
||||
}
|
||||
|
||||
struct DDARasterizer::Segments : DDARasterizer {
|
||||
int miny;
|
||||
int maxy;
|
||||
bool flag;
|
||||
Vector< Vector< Segment > > segment;
|
||||
|
||||
virtual void PutHorz(int x, int y, int cx) {
|
||||
if(y >= 0 && y < cy) {
|
||||
Segment& m = segment.At(y).Add();
|
||||
m.l = x;
|
||||
m.h = x + cx;
|
||||
m.flag = flag;
|
||||
flag = true;
|
||||
miny = min(y, miny);
|
||||
maxy = max(y, maxy);
|
||||
}
|
||||
}
|
||||
virtual void PutVert(int x, int y, int cy) {
|
||||
for(int i = 0; i < cy; i++)
|
||||
PutHorz(x, y + i, 1);
|
||||
}
|
||||
|
||||
Segments() { miny = INT_MAX; maxy = 0; }
|
||||
};
|
||||
|
||||
void DDARasterizer::FatLine(Point p1, Point p2, int n)
|
||||
{
|
||||
Point v = p2 - p1;
|
||||
Pointf shift = n * Orthogonal(Pointf(v) / Length((Pointf(v))));
|
||||
Point p = Pointf(p1) + shift / 2;
|
||||
Polygon();
|
||||
Move(p);
|
||||
Line(p += v);
|
||||
Line(p -= shift);
|
||||
Line(p - v);
|
||||
Fill();
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Move(Point p)
|
||||
{
|
||||
Close();
|
||||
p0 = p1 = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Line(Point p)
|
||||
{
|
||||
if(pseg) {
|
||||
Point a = p1;
|
||||
Point b = p;
|
||||
if(a.y > b.y)
|
||||
Swap(a, b);
|
||||
pseg->flag = false;
|
||||
pseg->DoLine(a, b, true);
|
||||
p1 = p;
|
||||
}
|
||||
else {
|
||||
if(width <= 1)
|
||||
DoLine(p1, p, false);
|
||||
else
|
||||
FatLine(p1, p, width);
|
||||
p1 = p;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Close()
|
||||
{
|
||||
if(p1 != p0)
|
||||
Line(p0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Polygon()
|
||||
{
|
||||
pseg.Create();
|
||||
pseg->Cy(cy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Fill()
|
||||
{
|
||||
ASSERT(pseg);
|
||||
Close();
|
||||
for(int y = pseg->miny; y <= pseg->maxy; y++) {
|
||||
Vector<Segment>& gg = pseg->segment[y];
|
||||
Sort(gg);
|
||||
int i = 0;
|
||||
bool flag = false;
|
||||
while(i < gg.GetCount()) {
|
||||
int l = gg[i].l;
|
||||
int h = gg[i].h;
|
||||
flag ^= gg[i++].flag;
|
||||
while(i < gg.GetCount() && flag) {
|
||||
h = gg[i].h;
|
||||
flag ^= gg[i++].flag;
|
||||
}
|
||||
PutHorz(l, y, h - l);
|
||||
}
|
||||
}
|
||||
pseg.Clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer& DDARasterizer::Ellipse(const Rect& rect)
|
||||
{
|
||||
Size size = rect.GetSize() / 2;
|
||||
int n = 16;
|
||||
Buffer<Point> p(n);
|
||||
for(int i = 0; i < n; i++) {
|
||||
double angle = M_PI * i / (n - 1) / 2;
|
||||
p[i].x = min(size.cx, int(sin(angle) * size.cx + 0.5));
|
||||
p[i].y = min(size.cy, int(cos(angle) * size.cy + 0.5));
|
||||
}
|
||||
Point center = rect.TopLeft() + size;
|
||||
Move(Point(center.x - p[0].x, center.y - p[0].y));
|
||||
for(int i = 1; i < n; i++)
|
||||
Line(Point(center.x - p[i].x, center.y - p[i].y));
|
||||
center.y = rect.bottom - 1 - size.cy;
|
||||
for(int i = n - 1; i >= 0; i--)
|
||||
Line(Point(center.x - p[i].x, center.y + p[i].y));
|
||||
center.x = rect.right - 1 - size.cx;
|
||||
for(int i = 0; i < n; i++)
|
||||
Line(Point(center.x + p[i].x, center.y + p[i].y));
|
||||
center.y = rect.top + size.cy;
|
||||
for(int i = n - 1; i >= 0; i--)
|
||||
Line(Point(center.x + p[i].x, center.y - p[i].y));
|
||||
Close();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DDARasterizer::~DDARasterizer() {}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
46
uppsrc/Draw/DDARasterizer.h
Normal file
46
uppsrc/Draw/DDARasterizer.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
class DDARasterizer {
|
||||
struct Segment : Moveable<Segment> {
|
||||
int l;
|
||||
int h;
|
||||
bool flag;
|
||||
|
||||
bool operator<(const Segment& b) const { return l < b.l; }
|
||||
};
|
||||
|
||||
struct Segments;
|
||||
|
||||
int cy;
|
||||
int diry;
|
||||
int dirx;
|
||||
One<Segments> pseg;
|
||||
Point p0, p1;
|
||||
int width;
|
||||
|
||||
void AHorz(int x, int y, int cx);
|
||||
void AVert(int x, int y, int cy);
|
||||
void DoLine(Point p1, Point p2, bool last);
|
||||
void FatLine(Point p1, Point p2, int n);
|
||||
|
||||
public:
|
||||
virtual void PutHorz(int x, int y, int cx) = 0;
|
||||
virtual void PutVert(int x, int y, int cy) = 0;
|
||||
|
||||
int GetDirx() const { return dirx; }
|
||||
int GetDiry() const { return diry; }
|
||||
|
||||
DDARasterizer& Move(Point p);
|
||||
DDARasterizer& Line(Point p);
|
||||
DDARasterizer& Close();
|
||||
|
||||
DDARasterizer& Polygon();
|
||||
DDARasterizer& Fill();
|
||||
|
||||
DDARasterizer& Ellipse(const Rect& rect);
|
||||
|
||||
DDARasterizer& Width(int width_) { width = width_; return *this; }
|
||||
|
||||
void Cy(int cy_) { cy = cy_; }
|
||||
|
||||
DDARasterizer();
|
||||
~DDARasterizer();
|
||||
};
|
||||
|
|
@ -884,6 +884,7 @@ DrawingToPdfFnType GetDrawingToPdfFn();
|
|||
|
||||
#include "Display.h"
|
||||
#include "Cham.h"
|
||||
#include "DDARasterizer.h"
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ file
|
|||
iml_header.h,
|
||||
iml_source.h,
|
||||
DrawImg.iml,
|
||||
DDA readonly separator,
|
||||
DDARasterizer.h,
|
||||
DDARasterizer.cpp,
|
||||
Chameleon readonly separator,
|
||||
Cham.h,
|
||||
Cham.cpp,
|
||||
|
|
|
|||
83
uppsrc/Draw/src.tpp/DDARasterizer$en-us.tpp
Normal file
83
uppsrc/Draw/src.tpp/DDARasterizer$en-us.tpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
topic "DDA Rasterizer";
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
|
||||
[l288;2 $$2,2#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:item]
|
||||
[l288;a4;*@5;1 $$6,6#70004532496200323422659154056402:requirement]
|
||||
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
|
||||
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
|
||||
[b42;2 $$9,9#13035079074754324216151401829390:normal]
|
||||
[{_}%EN-US
|
||||
[ {{10000@(113.42.0) [s0;%- [*@2;3 DDARasterizer]]}}&]
|
||||
[s3;%- &]
|
||||
[s1;:DDARasterizer`:`:class:%- [@(0.0.255)3 class][3 _][*3 DDARasterizer]&]
|
||||
[s2; Simple non`-antialiased rasterizer capable of drawing lines
|
||||
with [^http`:`/`/en`.wikipedia`.org`/wiki`/Bresenham`%27s`_line`_algorithm^ DDA]
|
||||
algorithm and polygons with even`-odd rule. Result is rendered
|
||||
to pure virtual methods that draw horizontal and vertical line
|
||||
segments.&]
|
||||
[s3;%- &]
|
||||
[ {{10000F(128)G(128)@1 [s0; [* Public Method List]]}}&]
|
||||
[s3;%- &]
|
||||
[s5;:DDARasterizer`:`:PutHorz`(int`,int`,int`):%- [@(0.0.255) virtual]
|
||||
[@(0.0.255) void]_[* PutHorz]([@(0.0.255) int]_[*@3 x], [@(0.0.255) int]_[*@3 y],
|
||||
[@(0.0.255) int]_[*@3 cx])_`=_[@3 0]&]
|
||||
[s2; Pure virtual method expected to paint horizontal line at [%-*@3 x],
|
||||
[%-*@3 y] with length [%-*@3 cx].&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:PutVert`(int`,int`,int`):%- [@(0.0.255) virtual]
|
||||
[@(0.0.255) void]_[* PutVert]([@(0.0.255) int]_[*@3 x], [@(0.0.255) int]_[*@3 y],
|
||||
[@(0.0.255) int]_[*@3 cy])_`=_[@3 0]&]
|
||||
[s2; Pure virtual method expected to paint horizontal line at [%-*@3 x],
|
||||
[%-*@3 y] with length [%-*@3 cy].&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Move`(Point`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* M
|
||||
ove]([_^Point^ Point]_[*@3 p])&]
|
||||
[s2; Moves the starting point of the next line to [%-*@3 p]. This point
|
||||
is also stored as path starting point so that it can be used
|
||||
in Close method.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Line`(Point`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* L
|
||||
ine]([_^Point^ Point]_[*@3 p])&]
|
||||
[s2; If rasterizer is in line drawing mode, draws line from starting
|
||||
point to [%-*@3 p]. [%-*@3 p] becomes a new starting point. Final
|
||||
point of line is not drawn. Line thickness can be affected by
|
||||
Width method. If rasterizer is in polygin drawing mode (started
|
||||
by Polygon), adds the line to polygon path instead.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Close`(`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* Close
|
||||
]()&]
|
||||
[s2; Draws line from starting point to the path starting point defined
|
||||
by Move.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Polygon`(`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* Pol
|
||||
ygon]()&]
|
||||
[s2; Starts a polygon mode.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Fill`(`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* Fill](
|
||||
)&]
|
||||
[s2; Finishes polygon and fills it.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Ellipse`(const Rect`&`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&
|
||||
]_[* Ellipse]([@(0.0.255) const]_[_^Rect^ Rect][@(0.0.255) `&]_[*@3 rect])&]
|
||||
[s2; Renders ellipse as serie of Move/Line commands.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Width`(int`):%- [_^DDARasterizer^ DDARasterizer][@(0.0.255) `&]_[* Wi
|
||||
dth]([@(0.0.255) int]_[*@3 width`_])&]
|
||||
[s2; [%-*@3 width`_] .&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:DDARasterizer`:`:Cy`(int`):%- [@(0.0.255) void]_[* Cy]([@(0.0.255) int]_[*@3 cy])&]
|
||||
[s2; Sets the total height of painting area. Rasterizer only emits
|
||||
PutHorz/PutVert with y >`= 0 and y < [%-*@3 cy].&]
|
||||
[s0; ]]
|
||||
|
|
@ -18,7 +18,6 @@ rectangular area. References to Displays are used in many widgets
|
|||
as attributes affecting the rendering of widget Values. Default
|
||||
implementation uses StdDisplay to perform all actions (see below
|
||||
for StdDisplay description).&]
|
||||
[s3; &]
|
||||
[s0; &]
|
||||
[s0; [* Visual style constants ]are used as `"style`" parameter bit
|
||||
flags of rendering methods and provide additional information
|
||||
|
|
@ -296,4 +295,4 @@ border.]
|
|||
::^ [s0;:DrawingDisplay: [* DrawingDisplay]]
|
||||
::= [s0; Displays Drawing scaled to fit the rectangle.]}}&]
|
||||
[s3; &]
|
||||
[s0; ]
|
||||
[s0; ]]
|
||||
|
|
@ -98,9 +98,27 @@ void MirrorVert(Image& img, const Rect& rect);
|
|||
String PackImlData(const Vector<Image>& image);
|
||||
Image DownSample3x(const Image& src);
|
||||
|
||||
/*
|
||||
struct IconDraw : ImagePainter {
|
||||
IconDraw(Size sz) : ImagePainter(sz, MODE_NOAA) {}
|
||||
};
|
||||
*/
|
||||
|
||||
struct IconDraw : NilDraw, DDARasterizer {
|
||||
RGBA docolor;
|
||||
ImageBuffer image;
|
||||
|
||||
virtual void PutHorz(int x, int y, int cx);
|
||||
virtual void PutVert(int x, int y, int cy);
|
||||
|
||||
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
|
||||
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
|
||||
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
|
||||
|
||||
operator Image() { return image; }
|
||||
|
||||
IconDraw(Size sz) { image.Create(sz); Cy(sz.cy); }
|
||||
};
|
||||
|
||||
class IconDes : public Ctrl {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ uses
|
|||
file
|
||||
IconDes.h,
|
||||
IconDes.key,
|
||||
IconDraw.cpp,
|
||||
AlphaCtrl.cpp,
|
||||
RGBACtrl.cpp,
|
||||
ImageOp.cpp optimize_speed,
|
||||
|
|
|
|||
64
uppsrc/IconDes/IconDraw.cpp
Normal file
64
uppsrc/IconDes/IconDraw.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include "IconDes.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void IconDraw::PutHorz(int x, int y, int cx)
|
||||
{
|
||||
if(y < 0 || y >= image.GetHeight())
|
||||
return;
|
||||
int r = minmax(x + cx, 0, image.GetWidth());
|
||||
x = minmax(x, 0, image.GetWidth());
|
||||
cx = r - x;
|
||||
if(cx <= 0)
|
||||
return;
|
||||
Upp::Fill(image[y] + x, docolor, cx);
|
||||
}
|
||||
|
||||
void IconDraw::PutVert(int x, int y, int cy)
|
||||
{
|
||||
if(x < 0 || x >= image.GetWidth())
|
||||
return;
|
||||
int b = minmax(y + cy, 0, image.GetHeight());
|
||||
y = minmax(y, 0, image.GetHeight());
|
||||
cy = b - y;
|
||||
RGBA *t = image[y] + x;
|
||||
while(cy-- > 0) {
|
||||
*t = docolor;
|
||||
t += image.GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void IconDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
|
||||
{
|
||||
docolor = color;
|
||||
int b = minmax(y + cy, 0, image.GetHeight());
|
||||
y = minmax(y, 0, image.GetHeight());
|
||||
cy = b - y;
|
||||
while(cy-- > 0)
|
||||
PutHorz(x, y++, cx);
|
||||
}
|
||||
|
||||
void IconDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
|
||||
{
|
||||
docolor = color;
|
||||
Width(width);
|
||||
Move(Point(x1, y1));
|
||||
Line(Point(x2, y2));
|
||||
}
|
||||
|
||||
void IconDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
|
||||
{
|
||||
if(!IsNull(color)) {
|
||||
docolor = color;
|
||||
Polygon().Ellipse(r).Fill();
|
||||
}
|
||||
if(!IsNull(pen) && !IsNull(pencolor)) {
|
||||
docolor = pencolor;
|
||||
if(pen == 1)
|
||||
Ellipse(r);
|
||||
else
|
||||
Polygon().Ellipse(r).Ellipse(r.Deflated(pen - 1)).Fill();
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -566,7 +566,7 @@ void MainConfigDlg::FlagDlg()
|
|||
cfg.accepts.Set(i, CC_NAME, accepts[i]);
|
||||
cfg.accepts.Set(i, CC_PACKAGES, Join(pkg, ","));
|
||||
}
|
||||
|
||||
|
||||
cfg.other.SetFilter(FlagFilterM);
|
||||
cfg.dll <<= cfg.gui <<= cfg.mt <<= cfg.sse2 <<= 0;
|
||||
String other;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue