mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-31 07:12:39 -06:00
Painter: OnPath, text optimizations
git-svn-id: svn://ultimatepp.org/upp/trunk@916 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
35058c97fa
commit
81e1a7d802
23 changed files with 598 additions and 171 deletions
|
|
@ -87,6 +87,8 @@ inline void LockLog() {}
|
|||
inline void UnlockLog() {}
|
||||
#endif
|
||||
|
||||
#define STATIC_ASSERT(x)
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
#define _DBG_
|
||||
|
|
|
|||
|
|
@ -116,11 +116,6 @@ inline void AlphaBlendCover8(RGBA& t, const RGBA& c, int cover)
|
|||
t.a = a + (alpha * t.a >> 8);
|
||||
}
|
||||
|
||||
inline int Q8(double x)
|
||||
{
|
||||
return int(x * 256 + 0.5);
|
||||
}
|
||||
|
||||
class Rasterizer : public LinearPathConsumer {
|
||||
public:
|
||||
virtual void Move(const Pointf& p);
|
||||
|
|
@ -141,6 +136,7 @@ private:
|
|||
int min_y;
|
||||
int max_y;
|
||||
Size sz;
|
||||
double mx;
|
||||
|
||||
void Init();
|
||||
Cell *AddCells(int y, int n);
|
||||
|
|
@ -151,6 +147,9 @@ private:
|
|||
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;
|
||||
|
|
@ -169,7 +168,7 @@ public:
|
|||
|
||||
void Reset();
|
||||
|
||||
Rasterizer(int cx, int cy);
|
||||
Rasterizer(int cx, int cy, bool subpixel);
|
||||
};
|
||||
|
||||
struct SpanSource {
|
||||
|
|
@ -205,6 +204,8 @@ class LinearInterpolator {
|
|||
|
||||
Xform2D xform;
|
||||
Dda2 ddax, dday;
|
||||
|
||||
static int Q8(double x) { return int(256 * x + 0.5); }
|
||||
|
||||
public:
|
||||
void Set(const Xform2D& m) { xform = m; }
|
||||
|
|
@ -229,6 +230,8 @@ protected:
|
|||
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,
|
||||
|
|
@ -266,10 +269,11 @@ protected:
|
|||
virtual void EndOp();
|
||||
|
||||
virtual void BeginMaskOp();
|
||||
virtual void BeginOnPathOp(double q, bool abs);
|
||||
|
||||
public:
|
||||
private:
|
||||
enum {
|
||||
MOVE, LINE, QUADRATIC, CUBIC, DIV
|
||||
MOVE, LINE, QUADRATIC, CUBIC, DIV, CHAR
|
||||
};
|
||||
struct LinearData {
|
||||
Pointf p;
|
||||
|
|
@ -280,13 +284,21 @@ public:
|
|||
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;
|
||||
double tolerance;
|
||||
bool evenodd;
|
||||
byte join;
|
||||
byte cap;
|
||||
|
|
@ -296,9 +308,11 @@ public:
|
|||
WithDeepCopy< Vector<RGBA> > stop_color;
|
||||
double dash_start;
|
||||
double opacity;
|
||||
|
||||
int cliplevel;
|
||||
bool hasclip;
|
||||
bool mask;
|
||||
bool onpath;
|
||||
};
|
||||
|
||||
ImageBuffer& ib;
|
||||
|
|
@ -311,6 +325,8 @@ public:
|
|||
Array<Attr> attrstack;
|
||||
Vector< Buffer<ClipLine> > clip;
|
||||
Array< ImageBuffer > mask;
|
||||
Vector< Vector<PathLine> > onpathstack;
|
||||
Vector<double> pathlenstack;
|
||||
|
||||
Image gradient;
|
||||
RGBA gradient1, gradient2;
|
||||
|
|
@ -319,9 +335,16 @@ public:
|
|||
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)); }
|
||||
|
|
@ -330,6 +353,7 @@ public:
|
|||
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);
|
||||
|
|
@ -339,6 +363,8 @@ public:
|
|||
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 = 0);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ void BufferPainter::BeginOp()
|
|||
{
|
||||
attrstack.Add(attr);
|
||||
attr.hasclip = false;
|
||||
attr.onpath = false;
|
||||
}
|
||||
|
||||
void BufferPainter::EndOp()
|
||||
|
|
@ -19,13 +20,18 @@ void BufferPainter::EndOp()
|
|||
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;
|
||||
pathattr.tolerance = attr.tolerance = 0.3 / attr.mtx.GetScale();
|
||||
}
|
||||
|
||||
void BufferPainter::OpacityOp(double o)
|
||||
|
|
@ -101,7 +107,7 @@ void BufferPainter::ClearStopsOp()
|
|||
BufferPainter::BufferPainter(ImageBuffer& ib, int mode)
|
||||
: ib(ib),
|
||||
mode(mode),
|
||||
rasterizer(mode == MODE_SUBPIXEL ? 3 * ib.GetWidth() : ib.GetWidth(), ib.GetHeight())
|
||||
rasterizer(ib.GetWidth(), ib.GetHeight(), mode == MODE_SUBPIXEL)
|
||||
{
|
||||
ClearPath();
|
||||
|
||||
|
|
@ -110,8 +116,6 @@ BufferPainter::BufferPainter(ImageBuffer& ib, int mode)
|
|||
render_cx *= 3;
|
||||
subpixel.Alloc(render_cx + 30);
|
||||
}
|
||||
attr.mtx = Xform2D::Scale(subpixel ? 3 : 1, 1);
|
||||
attr.tolerance = 0.3;
|
||||
attr.cap = LINECAP_BUTT;
|
||||
attr.join = LINEJOIN_MITER;
|
||||
attr.miter_limit = 4;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ struct sMakeCharOutline : LRUCache<String, FontChar>::Maker {
|
|||
}
|
||||
};
|
||||
|
||||
void Painter::CharacterOp(const Pointf& p, int ch, Font fnt)
|
||||
void PaintCharacter(Painter& sw, const Pointf& p, int ch, Font fnt)
|
||||
{
|
||||
PAINTER_TIMING("CharacterOp");
|
||||
String s;
|
||||
|
|
@ -105,8 +105,8 @@ void Painter::CharacterOp(const Pointf& p, int ch, Font fnt)
|
|||
h.fc.chr = ch;
|
||||
s = cache.Get(h);
|
||||
}
|
||||
RenderCharPath(s, s.GetLength(), *this, p.x, p.y + fnt.Info().GetAscent());
|
||||
EvenOdd(true);
|
||||
RenderCharPath(s, s.GetLength(), sw, p.x, p.y + fnt.Info().GetAscent());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -136,15 +136,16 @@ bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double y
|
|||
return true;
|
||||
}
|
||||
|
||||
void Painter::CharacterOp(const Pointf& p, int ch, Font fnt)
|
||||
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, *this, p.x, p.y + fnt.Info().GetAscent());
|
||||
RenderOutline(face->glyph->outline, sw, p.x, p.y + fnt.Info().GetAscent());
|
||||
XftUnlockFace(fi.GetXftFont());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -221,8 +221,6 @@ void BufferPainter::RenderImage(double width, const Image& image, const Xform2D&
|
|||
ss.vstyle = byte(flags & 12);
|
||||
ss.fast = flags & FILL_FAST;
|
||||
Xform2D m = transsrc * pathattr.mtx;
|
||||
if(subpixel)
|
||||
m = m * Xform2D::Scale(1 / 3.0, 1);
|
||||
ss.Set(m, image);
|
||||
RenderPath(width, &ss, RGBAZero());
|
||||
}
|
||||
|
|
|
|||
33
uppsrc/Painter/OnPath.cpp
Normal file
33
uppsrc/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
|
||||
|
|
@ -231,6 +231,10 @@ void Painter::Paint(const Painting& pic)
|
|||
case PAINTING_BEGINMASK:
|
||||
BeginMaskOp();
|
||||
break;
|
||||
case PAINTING_BEGINONPATH:
|
||||
sGet(r, ss);
|
||||
BeginOnPathOp(r, ss.Get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,6 +338,11 @@ Painter& Painter::Translate(double x, double 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);
|
||||
|
|
@ -475,4 +480,40 @@ 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) {}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <Draw/Draw.h>
|
||||
|
||||
#define PAINTER_TIMING(x) // RTIMING(x)
|
||||
#define PAINTER_TIMING(x) RTIMING(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ protected:
|
|||
|
||||
virtual void ClipOp() = 0;
|
||||
|
||||
virtual void CharacterOp(const Pointf& p, int ch, Font fnt);
|
||||
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);
|
||||
|
||||
|
|
@ -140,6 +140,7 @@ protected:
|
|||
virtual void EndOp() = 0;
|
||||
|
||||
virtual void BeginMaskOp() = 0;
|
||||
virtual void BeginOnPathOp(double q, bool absolute) = 0;
|
||||
|
||||
protected:
|
||||
static bool ReadBool(CParser& p);
|
||||
|
|
@ -279,6 +280,7 @@ public:
|
|||
void End();
|
||||
|
||||
void BeginMask();
|
||||
void BeginOnPath(double q, bool absolute = false);
|
||||
|
||||
Painter& ColorStop(double pos, const RGBA& color);
|
||||
Painter& ClearStops();
|
||||
|
|
@ -292,6 +294,7 @@ public:
|
|||
|
||||
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);
|
||||
|
|
@ -303,10 +306,72 @@ public:
|
|||
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 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
|
||||
|
|
|
|||
|
|
@ -213,6 +213,11 @@ 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);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@ file
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -256,6 +256,13 @@ 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;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ enum {
|
|||
PAINTING_BEGIN,
|
||||
PAINTING_END,
|
||||
PAINTING_BEGINMASK,
|
||||
PAINTING_BEGINONPATH,
|
||||
};
|
||||
|
||||
class PaintingPainter : public Painter {
|
||||
|
|
@ -119,6 +120,7 @@ protected:
|
|||
virtual void EndOp();
|
||||
|
||||
virtual void BeginMaskOp();
|
||||
virtual void BeginOnPathOp(double q, bool abs);
|
||||
|
||||
public:
|
||||
Painting GetResult();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ void BufferPainter::ClearPath()
|
|||
path.data.Clear();
|
||||
current = move = Null;
|
||||
ccontrol = qcontrol = Pointf(0, 0);
|
||||
ischar = false;
|
||||
}
|
||||
|
||||
Pointf BufferPainter::PathPoint(const Pointf& p, bool rel)
|
||||
|
|
@ -116,4 +117,20 @@ void BufferPainter::DivOp()
|
|||
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
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ struct PainterRadialSpan : SpanSource {
|
|||
const RGBA *gradient;
|
||||
double C;
|
||||
|
||||
void prepare() {}
|
||||
|
||||
void Set(double _x, double _y, double _r, double _fx, double _fy)
|
||||
{
|
||||
cx = _x;
|
||||
|
|
@ -63,8 +61,6 @@ void BufferPainter::RenderRadial(double width, const Pointf& f, const RGBA& colo
|
|||
{
|
||||
PainterRadialSpan sg;
|
||||
Xform2D m = pathattr.mtx;
|
||||
if(subpixel)
|
||||
m = m * Xform2D::Scale(1.0 / 3, 1);
|
||||
sg.interpolator.Set(Inverse(m));
|
||||
sg.style = style;
|
||||
sg.Set(c.x, c.y, r, f.x, f.y);
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ void Rasterizer::SetClip(const Rectf& rect)
|
|||
cliprect = rect & Sizef(sz);
|
||||
}
|
||||
|
||||
Rasterizer::Rasterizer(int cx, int cy)
|
||||
Rasterizer::Rasterizer(int cx, int cy, bool subpixel)
|
||||
{
|
||||
sz.cx = cx;
|
||||
mx = subpixel ? 3 * 256 : 256;
|
||||
sz.cx = subpixel ? 3 * cx : cx;
|
||||
sz.cy = cy;
|
||||
cell.Alloc(sz.cy + 1);
|
||||
cliprect = Sizef(sz);
|
||||
|
|
|
|||
|
|
@ -1,103 +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(Q8(x1), Q8(y1), Q8(x2), Q8(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
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -8,20 +8,53 @@ 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);
|
||||
trans.target = &rasterizer;
|
||||
LinearPathConsumer *g;
|
||||
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, pathattr.tolerance, pathattr.cap, pathattr.join);
|
||||
stroker.target = &trans;
|
||||
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;
|
||||
|
|
@ -31,10 +64,8 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
g = &stroker;
|
||||
evenodd = false;
|
||||
}
|
||||
else {
|
||||
else
|
||||
Close();
|
||||
g = &trans;
|
||||
}
|
||||
byte *data = path.data;
|
||||
int opacity = int(256 * pathattr.opacity);
|
||||
Pointf pos = Pointf(0, 0);
|
||||
|
|
@ -46,7 +77,7 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
ClipFiller clip_filler(render_cx);
|
||||
NoAAFillerFilter noaa_filler;
|
||||
MaskFillerFilter mf;
|
||||
bool doclip = width == -2;
|
||||
bool doclip = width == CLIP;
|
||||
subpixel_filler.sbuffer = subpixel;
|
||||
if(doclip) {
|
||||
rg = &clip_filler;
|
||||
|
|
@ -55,7 +86,7 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
else
|
||||
if(ss) {
|
||||
if(!span)
|
||||
span.Alloc(ib.GetWidth() + 3);
|
||||
span.Alloc((subpixel ? 3 : 1) * ib.GetWidth() + 3);
|
||||
if(subpixel) {
|
||||
subpixel_filler.ss = ss;
|
||||
subpixel_filler.buffer = span;
|
||||
|
|
@ -87,27 +118,29 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
for(;;) {
|
||||
if(i >= path.type.GetCount() || path.type[i] == DIV) {
|
||||
g->End();
|
||||
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(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:;
|
||||
}
|
||||
if(doclip)
|
||||
clip_filler.Clear();
|
||||
rasterizer.Render(y, *rf, evenodd);
|
||||
if(doclip)
|
||||
clip_filler.Finish(newclip[y]);
|
||||
empty:;
|
||||
rasterizer.Reset();
|
||||
}
|
||||
rasterizer.Reset();
|
||||
if(i >= path.type.GetCount())
|
||||
break;
|
||||
}
|
||||
|
|
@ -116,29 +149,48 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
case MOVE: {
|
||||
const LinearData *d = (LinearData *)data;
|
||||
data += sizeof(LinearData);
|
||||
g->Move(pos = d->p);
|
||||
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 = d->p);
|
||||
g->Line(pos = regular ? pathattr.mtx.Transform(d->p) : d->p);
|
||||
break;
|
||||
}
|
||||
case QUADRATIC: {
|
||||
const QuadraticData *d = (QuadraticData *)data;
|
||||
data += sizeof(QuadraticData);
|
||||
ApproximateQuadratic(*g, pos, d->p1, d->p, pathattr.tolerance);
|
||||
pos = d->p;
|
||||
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);
|
||||
ApproximateCubic(*g, pos, d->p1, d->p2, d->p, pathattr.tolerance);
|
||||
pos = d->p;
|
||||
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;
|
||||
|
|
@ -146,12 +198,16 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
|
|||
i++;
|
||||
}
|
||||
current = Null;
|
||||
if(width == ONPATH) {
|
||||
onpath = onpathtarget.path;
|
||||
pathlen = onpathtarget.len;
|
||||
}
|
||||
return newclip;
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const RGBA& color)
|
||||
{
|
||||
RenderPath(-1, NULL, color);
|
||||
RenderPath(FILL, NULL, color);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const RGBA& color)
|
||||
|
|
@ -161,7 +217,7 @@ void BufferPainter::StrokeOp(double width, const RGBA& color)
|
|||
|
||||
void BufferPainter::ClipOp()
|
||||
{
|
||||
Buffer<ClipLine> newclip = RenderPath(-2, NULL, RGBAZero());
|
||||
Buffer<ClipLine> newclip = RenderPath(CLIP, NULL, RGBAZero());
|
||||
if(attr.hasclip)
|
||||
clip.Top() = newclip;
|
||||
else {
|
||||
|
|
|
|||
127
uppsrc/Painter/RenderChar.cpp
Normal file
127
uppsrc/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
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#define _Painter_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#include "CtrlLib/init"
|
||||
#define BLITZ_INDEX__ F18922416C44F220B741A74F8D9F1A79C
|
||||
#define BLITZ_INDEX__ F1639763DEC2ACC960A83B650F7C86CE2
|
||||
#include "PaintPainting.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ bool Sqlite3PerformScript(const String& text,
|
|||
Gate2<int, int> progress_canceled = false
|
||||
);
|
||||
|
||||
class Sqlite3Connection;
|
||||
|
||||
class Sqlite3Session : public SqlSession {
|
||||
public:
|
||||
virtual bool IsOpen() const { return NULL != db; }
|
||||
|
|
@ -32,9 +34,14 @@ protected:
|
|||
virtual SqlConnection *CreateConnection();
|
||||
|
||||
private:
|
||||
friend class Sqlite3Connection;
|
||||
|
||||
sqlite3 *db;
|
||||
String current_filename;
|
||||
String current_dbname;
|
||||
Link<Sqlite3Connection> clink;
|
||||
|
||||
void Reset();
|
||||
|
||||
public:
|
||||
bool Open(const char *filename);
|
||||
|
|
@ -46,8 +53,8 @@ public:
|
|||
virtual void Commit();
|
||||
virtual void Rollback();
|
||||
|
||||
Sqlite3Session() { db = NULL; Dialect(SQLITE3); }
|
||||
~Sqlite3Session() { Close(); }
|
||||
Sqlite3Session();
|
||||
~Sqlite3Session();
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ NAMESPACE_UPP
|
|||
|
||||
#define LLOG(x) // LOG(x)
|
||||
|
||||
class Sqlite3Connection : public SqlConnection {
|
||||
class Sqlite3Connection : public SqlConnection, public Link<Sqlite3Connection> {
|
||||
protected:
|
||||
virtual void SetParam(int i, const Value& r);
|
||||
virtual bool Execute();
|
||||
|
|
@ -34,6 +34,7 @@ private:
|
|||
|
||||
friend class Sqlite3Session;
|
||||
void BindParam(int i, const Value& r);
|
||||
void Reset();
|
||||
|
||||
public:
|
||||
Sqlite3Connection(Sqlite3Session& the_session, sqlite3 *the_db);
|
||||
|
|
@ -42,11 +43,14 @@ public:
|
|||
|
||||
Sqlite3Connection::Sqlite3Connection(Sqlite3Session& the_session, sqlite3 *the_db)
|
||||
: session(the_session), db(the_db), current_stmt(NULL), got_first_row(false), got_row_data(false)
|
||||
{}
|
||||
{
|
||||
LinkBefore(&session.clink);
|
||||
}
|
||||
|
||||
Sqlite3Connection::~Sqlite3Connection()
|
||||
{
|
||||
Cancel();
|
||||
Unlink();
|
||||
}
|
||||
|
||||
void Sqlite3Connection::Cancel()
|
||||
|
|
@ -58,9 +62,16 @@ void Sqlite3Connection::Cancel()
|
|||
session.SetError(sqlite3_errmsg(db), "Finalizing statement: "+ current_stmt_string);
|
||||
current_stmt = NULL;
|
||||
current_stmt_string.Clear();
|
||||
parse = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Sqlite3Connection::Reset()
|
||||
{
|
||||
if(current_stmt && sqlite3_reset(current_stmt) != SQLITE_OK)
|
||||
session.SetError(sqlite3_errmsg(db), "Resetting statement: " + current_stmt_string);
|
||||
}
|
||||
|
||||
void Sqlite3Connection::SetParam(int i, const Value& r)
|
||||
{
|
||||
LLOG(Format("SetParam(%d,%s)",i,r.ToString()));
|
||||
|
|
@ -299,20 +310,42 @@ void Sqlite3Session::Close() {
|
|||
SqlConnection *Sqlite3Session::CreateConnection() {
|
||||
return new Sqlite3Connection(*this, db);
|
||||
}
|
||||
|
||||
void Sqlite3Session::Reset()
|
||||
{
|
||||
for(Sqlite3Connection *s = clink.GetNext(); s != &clink; s = s->GetNext())
|
||||
s->Reset();
|
||||
}
|
||||
|
||||
Sqlite3Session::Sqlite3Session()
|
||||
{
|
||||
db = NULL;
|
||||
Dialect(SQLITE3);
|
||||
}
|
||||
|
||||
Sqlite3Session::~Sqlite3Session()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void Sqlite3Session::Begin() {
|
||||
static const char begin[] = "BEGIN;";
|
||||
if(trace)
|
||||
*trace << begin << "\n";
|
||||
Reset();
|
||||
if(SQLITE_OK != sqlite3_exec(db,begin,NULL,NULL,NULL))
|
||||
SetError(sqlite3_errmsg(db), begin);
|
||||
}
|
||||
|
||||
void Sqlite3Session::Commit() {
|
||||
static const char commit[] = "COMMIT;";
|
||||
if(trace)
|
||||
*trace << commit << "\n";
|
||||
Reset();
|
||||
if(SQLITE_OK != sqlite3_exec(db,commit,NULL,NULL,NULL))
|
||||
SetError(sqlite3_errmsg(db), commit);
|
||||
}
|
||||
|
||||
void Sqlite3Session::Rollback() {
|
||||
static const char rollback[] = "ROLLBACK;";
|
||||
if(trace)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue