Painter: BufferPainter::PreClip #214

git-svn-id: svn://ultimatepp.org/upp/trunk@8094 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2015-01-26 15:11:14 +00:00
parent 3ebcfa4a7b
commit 3ab7b0d27a
10 changed files with 137 additions and 133 deletions

View file

@ -31,20 +31,23 @@ private:
double w2;
double qmiter;
double fid;
double tw;
Pointf p0, v0, o0, a0, b0;
Pointf p1, v1, o1, a1, b1;
Pointf p2;
int linecap;
int linejoin;
Rectf preclip;
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);
bool PreClipped(Pointf p2, Pointf p3);
public:
void Init(double width, double miterlimit, double tolerance, int linecap, int linejoin);
void Init(double width, double miterlimit, double tolerance, int linecap, int linejoin, const Rect& preclip);
};
class Dasher : public LinearPathFilter {
@ -150,7 +153,8 @@ public:
void LineRaw(int x1, int y1, int x2, int y2);
void SetClip(const Rectf& rect);
void SetClip(const Rectf& rect);
Rectf GetClip() const { return cliprect; }
int MinY() const { return min_y; }
int MaxY() const { return max_y; }
@ -318,6 +322,7 @@ private:
int mode;
Buffer<int16> subpixel;
int render_cx;
bool dopreclip;
Attr attr;
Attr pathattr;
@ -370,6 +375,8 @@ private:
public:
ImageBuffer& GetBuffer() { return ib; }
const ImageBuffer& GetBuffer() const { return ib; }
BufferPainter& PreClip(bool b = true) { dopreclip = b; return *this; }
BufferPainter(ImageBuffer& ib, int mode = MODE_ANTIALIASED);
};

View file

@ -136,6 +136,8 @@ BufferPainter::BufferPainter(ImageBuffer& ib, int mode)
pathattr = attr;
gradientn = Null;
dopreclip = false;
}
END_UPP_NAMESPACE

View file

@ -16,7 +16,7 @@ file
BufferPainter.h,
Xform2D.cpp,
Approximate.cpp,
Stroker.cpp,
Stroker.cpp optimize_speed,
Dasher.cpp,
Transformer.cpp,
Interpolator.cpp optimize_speed,

View file

@ -56,7 +56,24 @@ Buffer<ClippingLine> BufferPainter::RenderPath(double width, SpanSource *ss, con
}
else
if(width > 0) {
stroker.Init(width, pathattr.miter_limit, tolerance, pathattr.cap, pathattr.join);
Rectf preclip = Null;
if(dopreclip) {
preclip = rasterizer.GetClip();
Xform2D imx = Inverse(pathattr.mtx);
Pointf tl, br, a;
tl = br = imx.Transform(preclip.TopLeft());
a = imx.Transform(preclip.TopRight());
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(preclip.BottomLeft());
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(preclip.BottomRight());
tl = min(a, tl);
br = max(a, br);
preclip = Rectf(tl, br);
}
stroker.Init(width, pathattr.miter_limit, tolerance, pathattr.cap, pathattr.join, preclip);
stroker.target = g;
if(pathattr.dash.GetCount()) {
dasher.Init(pathattr.dash, pathattr.dash_start);

View file

@ -1,15 +1,18 @@
#include "Painter.h"
#define LLOG(x) // DLOG(x)
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
void Stroker::Init(double width, double miterlimit, double tolerance, int _linecap, int _linejoin)
void Stroker::Init(double width, double miterlimit, double tolerance, int _linecap, int _linejoin, const Rect& preclip_)
{
linecap = _linecap;
linejoin = _linejoin;
preclip = preclip_;
w2 = width / 2;
qmiter = miterlimit * w2;
if(!IsNull(preclip))
tw = 4 * max(qmiter, w2); // preclipping width
qmiter *= qmiter;
fid = acos(1 - tolerance / w2);
p0 = p1 = p2 = Null;
@ -35,6 +38,14 @@ void Stroker::Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double
}
}
inline bool Stroker::PreClipped(Pointf p2, Pointf p3)
{
return p2.x + tw < preclip.left && p3.x + tw < preclip.left ||
p2.x - tw > preclip.right && p3.x - tw > preclip.right ||
p2.y + tw < preclip.top && p3.y + tw < preclip.top ||
p2.y - tw > preclip.bottom && p3.y - tw > preclip.bottom;
}
void Stroker::Line(const Pointf& p3)
{
LLOG("Stroker::Line " << p3);
@ -70,50 +81,54 @@ void Stroker::Line(const Pointf& p3)
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) {
if(IsNull(preclip) || !PreClipped(p2, p3)) {
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);
}
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);
}
LLOG("PRECLIPPED " << p2 << " - " << p3);
p1 = p2;
v1 = v2;
o1 = o2;
@ -125,6 +140,11 @@ void Stroker::Line(const Pointf& p3)
void Stroker::Cap(const Pointf& p, const Pointf& v, const Pointf& o,
const Pointf& a, const Pointf& b)
{
if(!IsNull(preclip) &&
(p.x + tw < preclip.left || p.x - tw > preclip.right || p.y + tw < preclip.top || p.y - tw > preclip.bottom)) {
LLOG("Cap was preclipped out");
return;
}
PutMove(a);
if(linecap == LINECAP_SQUARE) {
Pointf nv = Orthogonal(o);
@ -140,13 +160,18 @@ void Stroker::Finish()
{
if(IsNull(p1) || IsNull(p2) || IsNull(p0))
return;
LLOG("-- Finish " << p1 << " " << p2);
if(p2 == p0)
Line(p0 + v0);
else {
PutMove(a1);
PutLine(a1 + v1);
PutMove(b1 + v1);
PutLine(b1);
if(IsNull(preclip) || !PreClipped(p1, p2)) {
PutMove(a1);
PutLine(a1 + v1);
PutMove(b1 + v1);
PutLine(b1);
}
else
LLOG("FINISH PRECLIPPED " << p1 << " - " << p2);
Cap(p0, v0, o0, b0, a0);
Cap(p2, -v1, -o1, a1 + v1, b1 + v1);
}

View file

@ -1,6 +1,6 @@
#include "Debuggers.h"
#define LLOG(x) // LOG(x)
#define LLOG(x) LOG(x)
#define IMAGECLASS DbgImg
#define IMAGEFILE <ide/Debuggers/Debuggers.iml>
@ -100,27 +100,31 @@ String Dbg::Cmd(const char *command)
Lock();
if(command) {
LLOG("Cmd: " << command);
dbg->Write(String(command) + "\n"); // TRC 04/10/11: must not use \r\n, LINUX doesn't like it
dbg->Write(String(command) + "\n"); _DBG_ // TRC 04/10/11: must not use \r\n, LINUX doesn't like it
PutVerbose(command);
}
String result;
int sleep = 0;
int ms0 = msecs();
while(dbg) {
String s;
LLOG("About to read");
if(!dbg->Read(s)) {
LLOG(result);
LLOG("Read: " << result);
PutVerbose(result);
PutVerbose("Debugger terminated");
break;
}
if(!s.IsEmpty() && Result(result, s)) {
LLOG(result);
LLOG("Processed " << result);
PutVerbose(result);
break;
}
GuiSleep(sleep);
Ctrl::ProcessEvents();
sleep = min(20, sleep + max(1, 3 * sleep / 2));
LLOG("Unprocessed Result length: " << s);
GuiSleep(0);
if(ms0 != msecs()) {
ProcessEvents();
ms0 = msecs();
}
if(TTYQuit())
Stop();
}

View file

@ -6,7 +6,7 @@ uses
HexView;
file
Debuggers.h options PCH,
Debuggers.h options(BUILDER_OPTION) PCH,
Debuggers.iml,
Gdb.lay,
Terminal.cpp,

View file

@ -116,6 +116,8 @@ void DbgDisas::Clear()
void DbgDisas::Add(adr_t adr, const String& code, const String& args, const String& bytes)
{
DDUMP(code);
DDUMP(args);
if(adr < low)
low = adr;
if(adr > high)

View file

@ -1,6 +1,6 @@
#include "Debuggers.h"
#define PROMPT "<\xcd\xeb>"
#define PROMPT "<wksuiherk" "bnuiohnsfoptmb>"
bool Gdb::Result(String& result, const String& s)
{
@ -87,81 +87,28 @@ void Gdb::SetDisas(const String& text)
StringStream ss(text);
while(!ss.IsEof()) {
String ln = ss.GetLine();
CParser p(ln);
try {
if(p.Char2('0', 'x')) {
adr_t adr = p.IsNumber(16) ? (adr_t)p.ReadNumber64(16) : 0;
String code;
String args;
int level = 0;
while(!p.IsEof()) {
if(p.Char(':') && level == 0)
break;
else
if(p.Char('<'))
level++;
else
if(p.Char('>'))
level--;
else
p.GetChar();
}
p.Spaces();
if(p.IsId()) {
code = p.ReadId();
for(;;) {
if(p.Spaces())
args.Cat(' ');
if(p.IsEof())
break;
if(p.Char2('0', 'x')) {
adr_t adr = 0;
if(p.IsNumber(16))
adr = (adr_t)p.ReadNumber64(16);
String fname;
bool usefname = false;
if(p.Char('<')) {
const char *b = p.GetPtr();
int level = 1;
usefname = true;
while(!p.IsEof()) {
if(p.Char('>') && --level == 0) {
fname = String(b, p.GetPtr() - 1);
break;
}
if(p.Char('<'))
level++;
if(p.Char('+'))
usefname = false;
else {
p.GetChar();
p.Spaces();
}
}
}
args << (usefname ? fname : Sprintf("0x%X", adr));
disas.AddT(adr);
}
else
if(p.Id("DWORD"))
args.Cat("dword ");
else
if(p.Id("WORD"))
args.Cat("word ");
else
if(p.Id("BYTE"))
args.Cat("byte ");
else
if(p.Id("PTR"))
args.Cat("ptr ");
else
args.Cat(p.GetChar());
}
}
disas.Add(adr, code, args);
}
const char *s = ln;
while(*s && !IsDigit(*s))
s++;
adr_t adr = 0;
String code, args;
if(s[0] == '0' && ToLower(s[1]) == 'x')
adr = (adr_t)ScanInt64(s + 2, NULL, 16);
int q = ln.Find(">:");
if(q >= 0) {
s = ~ln + q + 2;
while(IsSpace(*s))
s++;
while(*s && !IsSpace(*s))
code.Cat(*s++);
while(IsSpace(*s))
s++;
args = s;
q = args.Find("0x");
if(q >= 0)
disas.AddT(ScanInt(~args + q + 2, NULL, 16));
disas.Add(adr, code, args);
}
catch(CParser::Error) {}
}
}

View file

@ -3,7 +3,7 @@
#include "ide\Common/init"
#include "plugin\ndisasm/init"
#include "HexView/init"
#define BLITZ_INDEX__ F2300ec0d3d2de4bde7af30102b728c5d
#define BLITZ_INDEX__ Fa2117e771964dad617cdd6a1792596ea
#include "UppSimplifiers.icpp"
#undef BLITZ_INDEX__
#endif