mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Developing Painter2.0
git-svn-id: svn://ultimatepp.org/upp/trunk@848 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
6be9238f51
commit
5f7bdbb994
34 changed files with 1242 additions and 116 deletions
|
|
@ -55,7 +55,7 @@ private:
|
|||
const Pointf& a0, const Pointf& b0);
|
||||
|
||||
public:
|
||||
Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin);
|
||||
void Init(double width, double miterlimit, double tolerance, int linecap, int linejoin);
|
||||
};
|
||||
|
||||
class Dasher : public LinearPathFilter {
|
||||
|
|
@ -64,7 +64,7 @@ public:
|
|||
virtual void Line(const Pointf& p);
|
||||
|
||||
private:
|
||||
const Vector<double>& pattern;
|
||||
const Vector<double> *pattern;
|
||||
int patterni;
|
||||
double sum, rem;
|
||||
bool flag;
|
||||
|
|
@ -73,7 +73,7 @@ private:
|
|||
void Put(const Pointf& p);
|
||||
|
||||
public:
|
||||
Dasher(const Vector<double>& pattern, double distance);
|
||||
void Init(const Vector<double>& pattern, double distance);
|
||||
};
|
||||
|
||||
struct Transformer : public LinearPathFilter {
|
||||
|
|
@ -117,6 +117,11 @@ 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);
|
||||
|
|
@ -134,7 +139,6 @@ private:
|
|||
Rectf cliprect;
|
||||
Pointf p0;
|
||||
Buffer< Vector<Cell> > cell;
|
||||
int xmax, ymax;
|
||||
int min_y;
|
||||
int max_y;
|
||||
Size sz;
|
||||
|
|
@ -180,10 +184,31 @@ struct ScanLine {
|
|||
};
|
||||
|
||||
struct SpanSource {
|
||||
virtual void Get(RGBA *_span, int x, int y, unsigned len);
|
||||
virtual void Get(RGBA *span, int x, int y, unsigned len) = 0;
|
||||
};
|
||||
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd);
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, SpanSource *s, RGBA *buffer, int opacity8, bool evenodd);
|
||||
|
||||
Image MipMap(const Image& img);
|
||||
Image MakeMipMap(const Image& img, int level);
|
||||
|
||||
class LinearInterpolator {
|
||||
struct Dda2 {
|
||||
int count, lift, rem, mod, p;
|
||||
|
||||
void Set(int a, int b, int len);
|
||||
int Get();
|
||||
};
|
||||
|
||||
Xform2D xform;
|
||||
Dda2 ddax, dday;
|
||||
|
||||
public:
|
||||
void Begin(int x, int y, int len);
|
||||
void Get(int& x, int& y);
|
||||
void Set(const Xform2D& m) { xform = m; }
|
||||
};
|
||||
|
||||
class BufferPainter : public Painter {
|
||||
protected:
|
||||
|
|
@ -198,8 +223,23 @@ protected:
|
|||
virtual void CloseOp();
|
||||
|
||||
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 ColorStopOp(double pos, const RGBA& color);
|
||||
virtual void ClearStopsOp();
|
||||
|
|
@ -267,16 +307,21 @@ public:
|
|||
Rectf pathrect;
|
||||
|
||||
Rasterizer rasterizer;
|
||||
Buffer<RGBA> span;
|
||||
|
||||
void *PathAddRaw(int type, int size);
|
||||
template <class T> T& PathAdd(int type) { return *(T *)PathAddRaw(type, sizeof(T)); }
|
||||
|
||||
void DoMove0();
|
||||
void ClearPath();
|
||||
void RenderPath(LinearPathFilter *first_filter, LinearPathFilter *last_filter,
|
||||
const RGBA& color, bool evenodd);
|
||||
Pointf PathPoint(const Pointf& p, bool rel);
|
||||
Pointf EndPoint(const Pointf& p, bool rel);
|
||||
void DoMove0();
|
||||
void ClearPath();
|
||||
void RenderPath(double width, SpanSource *ss, const RGBA& color);
|
||||
void RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags);
|
||||
void RenderRadial(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style);
|
||||
void MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx);
|
||||
Image GetGradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2);
|
||||
void ColorStop0(Attr& a, double pos, const RGBA& color);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -29,26 +29,26 @@ void Dasher::Line(const Pointf& p)
|
|||
pos += rem;
|
||||
Put(pos / len * v + p0);
|
||||
flag = !flag;
|
||||
rem = pattern[patterni];
|
||||
patterni = (patterni + 1) % pattern.GetCount();
|
||||
rem = (*pattern)[patterni];
|
||||
patterni = (patterni + 1) % pattern->GetCount();
|
||||
}
|
||||
rem -= len - pos;
|
||||
Put(p);
|
||||
p0 = p;
|
||||
}
|
||||
|
||||
Dasher::Dasher(const Vector<double>& p, double distance)
|
||||
: pattern(p)
|
||||
void Dasher::Init(const Vector<double>& p, double distance)
|
||||
{
|
||||
sum = Sum0(pattern);
|
||||
pattern = &p;
|
||||
sum = Sum0(p);
|
||||
if(sum == 0)
|
||||
return;
|
||||
distance -= int(distance / sum) * sum;
|
||||
patterni = 0;
|
||||
flag = false;
|
||||
for(;;) {
|
||||
rem = pattern[patterni];
|
||||
patterni = (patterni + 1) % pattern.GetCount();
|
||||
rem = (*pattern)[patterni];
|
||||
patterni = (patterni + 1) % pattern->GetCount();
|
||||
flag = !flag;
|
||||
if(rem > distance) {
|
||||
rem -= distance;
|
||||
|
|
|
|||
114
uppdev/Painter/FontWin32.cpp
Normal file
114
uppdev/Painter/FontWin32.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all coM_PIes.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Recycled for U++ by Miroslav Fidler 2008
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
inline double fx_to_dbl(const FIXED& p) {
|
||||
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
|
||||
}
|
||||
|
||||
void RenderCharPath(const char* gbuf, unsigned total_size, Painter& sw, double xx, double yy)
|
||||
{
|
||||
const char* cur_glyph = gbuf;
|
||||
const char* end_glyph = gbuf + total_size;
|
||||
|
||||
while(cur_glyph < end_glyph) {
|
||||
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
||||
const char* end_poly = cur_glyph + th->cb;
|
||||
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
|
||||
sw.Move(xx + fx_to_dbl(th->pfxStart.x), yy - fx_to_dbl(th->pfxStart.y));
|
||||
while(cur_poly < end_poly) {
|
||||
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
||||
if (pc->wType == TT_PRIM_LINE)
|
||||
for(int i = 0; i < pc->cpfx; i++)
|
||||
sw.Line(xx + fx_to_dbl(pc->apfx[i].x), yy - fx_to_dbl(pc->apfx[i].y));
|
||||
if (pc->wType == TT_PRIM_QSPLINE) {
|
||||
int u;
|
||||
for (u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
|
||||
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
|
||||
POINTFX pnt_c = pc->apfx[u+1];
|
||||
if (u < pc->cpfx - 2) { // If not on last spline, compute C
|
||||
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
|
||||
*(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
|
||||
}
|
||||
sw.Quadratic(xx + fx_to_dbl(pnt_b.x), yy - fx_to_dbl(pnt_b.y),
|
||||
xx + fx_to_dbl(pnt_c.x), yy - fx_to_dbl(pnt_c.y));
|
||||
}
|
||||
}
|
||||
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
|
||||
}
|
||||
sw.Close();
|
||||
cur_glyph += th->cb;
|
||||
}
|
||||
}
|
||||
|
||||
struct FontChar {
|
||||
Font fnt;
|
||||
int chr;
|
||||
|
||||
bool operator==(const FontChar& b) const { return fnt == b.fnt && chr == b.chr; }
|
||||
unsigned GetHashValue() const { return CombineHash(fnt, chr); }
|
||||
};
|
||||
|
||||
struct sMakeCharOutline : LRUCache<String, FontChar>::Maker {
|
||||
FontChar fc;
|
||||
|
||||
FontChar Key() const { return fc; }
|
||||
int Make(String& s) const {
|
||||
static ScreenDraw w;
|
||||
w.SetFont(fc.fnt);
|
||||
GLYPHMETRICS gm;
|
||||
MAT2 m_matrix;
|
||||
memset(&m_matrix, 0, sizeof(m_matrix));
|
||||
m_matrix.eM11.value = 1;
|
||||
m_matrix.eM22.value = 1;
|
||||
s.Clear();
|
||||
int gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, 0, NULL, &m_matrix);
|
||||
if(gsz < 0)
|
||||
return 0;
|
||||
StringBuffer gb(gsz);
|
||||
gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, gsz, ~gb, &m_matrix);
|
||||
if(gsz < 0)
|
||||
return 0;
|
||||
s = gb;
|
||||
return gsz;
|
||||
}
|
||||
};
|
||||
|
||||
void Painter::CharacterOp(double x, double y, int ch, Font fnt)
|
||||
{
|
||||
PAINTER_TIMING("CharacterOp");
|
||||
String s;
|
||||
INTERLOCKED {
|
||||
static LRUCache<String, FontChar> cache;
|
||||
cache.Shrink(100000);
|
||||
sMakeCharOutline h;
|
||||
h.fc.fnt = fnt;
|
||||
h.fc.chr = ch;
|
||||
s = cache.Get(h);
|
||||
}
|
||||
RenderCharPath(s, s.GetLength(), *this, x, y + fnt.Info().GetAscent());
|
||||
EvenOdd(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
152
uppdev/Painter/FontX11.cpp
Normal file
152
uppdev/Painter/FontX11.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all coM_PIes.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Recycled for U++ by Miroslav Fidler 2008
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
static inline double ft_dbl(int p)
|
||||
{
|
||||
return double(p) / 64.0;
|
||||
}
|
||||
|
||||
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy)
|
||||
{
|
||||
FT_Vector v_last;
|
||||
FT_Vector v_control;
|
||||
FT_Vector v_start;
|
||||
double x1, y1, x2, y2, x3, y3;
|
||||
FT_Vector* point;
|
||||
FT_Vector* limit;
|
||||
char* tags;
|
||||
int n; // index of contour in outline
|
||||
char tag; // current point's state
|
||||
int first = 0; // index of first point in contour
|
||||
for(n = 0; n < outline.n_contours; n++) {
|
||||
int last = outline.contours[n];
|
||||
limit = outline.points + last;
|
||||
v_start = outline.points[first];
|
||||
v_last = outline.points[last];
|
||||
v_control = v_start;
|
||||
point = outline.points + first;
|
||||
tags = outline.tags + first;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
if(tag == FT_CURVE_TAG_CUBIC) return false;
|
||||
if(tag == FT_CURVE_TAG_CONIC) {
|
||||
if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) {
|
||||
// start at last point if it is on the curve
|
||||
v_start = v_last;
|
||||
limit--;
|
||||
}
|
||||
else {
|
||||
// if both first and last points are conic,
|
||||
// start at their middle and record its position
|
||||
// for closure
|
||||
v_start.x = (v_start.x + v_last.x) / 2;
|
||||
v_start.y = (v_start.y + v_last.y) / 2;
|
||||
v_last = v_start;
|
||||
}
|
||||
point--;
|
||||
tags--;
|
||||
}
|
||||
path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
while(point < limit) {
|
||||
point++;
|
||||
tags++;
|
||||
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
switch(tag) {
|
||||
case FT_CURVE_TAG_ON:
|
||||
path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy);
|
||||
continue;
|
||||
case FT_CURVE_TAG_CONIC:
|
||||
v_control.x = point->x;
|
||||
v_control.y = point->y;
|
||||
Do_Conic:
|
||||
if(point < limit) {
|
||||
FT_Vector vec;
|
||||
FT_Vector v_middle;
|
||||
point++;
|
||||
tags++;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
if(tag == FT_CURVE_TAG_ON) {
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
if(tag != FT_CURVE_TAG_CONIC) return false;
|
||||
v_middle.x = (v_control.x + vec.x) / 2;
|
||||
v_middle.y = (v_control.y + vec.y) / 2;
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy);
|
||||
v_control = vec;
|
||||
goto Do_Conic;
|
||||
}
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
|
||||
default:
|
||||
FT_Vector vec1, vec2;
|
||||
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
|
||||
return false;
|
||||
vec1.x = point[0].x;
|
||||
vec1.y = point[0].y;
|
||||
vec2.x = point[1].x;
|
||||
vec2.y = point[1].y;
|
||||
point += 2;
|
||||
tags += 2;
|
||||
if(point <= limit) {
|
||||
FT_Vector vec;
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
}
|
||||
}
|
||||
Close:
|
||||
path.Close();
|
||||
first = last + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Painter::CharacterOp(double x, double y, 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, x, y + fnt.Info().GetAscent());
|
||||
XftUnlockFace(fi.GetXftFont());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
58
uppdev/Painter/Gradient.cpp
Normal file
58
uppdev/Painter/Gradient.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void BufferPainter::MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx)
|
||||
{
|
||||
int l = 0;
|
||||
RGBA cl = color1;
|
||||
for(int i = 0; i <= pathattr.stop.GetCount(); i++) {
|
||||
int h;
|
||||
RGBA ch;
|
||||
if(i < pathattr.stop.GetCount()) {
|
||||
h = (int)(pathattr.stop[i] * (cx - 1));
|
||||
ch = pathattr.stop_color[i];
|
||||
}
|
||||
else {
|
||||
h = cx - 1;
|
||||
ch = color2;
|
||||
}
|
||||
int w = h - l;
|
||||
for(int j = 0; j < w; j++) {
|
||||
t->r = ((w - j) * cl.r + j * ch.r) / w;
|
||||
t->g = ((w - j) * cl.g + j * ch.g) / w;
|
||||
t->b = ((w - j) * cl.b + j * ch.b) / w;
|
||||
t->a = ((w - j) * cl.a + j * ch.a) / w;
|
||||
t++;
|
||||
}
|
||||
cl = ch;
|
||||
l = h;
|
||||
}
|
||||
*t = cl;
|
||||
}
|
||||
|
||||
Image BufferPainter::GetGradient(const RGBA& color1, const RGBA& color2, const Pointf& p1, const Pointf& p2)
|
||||
{
|
||||
int n = minmax(int(Distance(p1, p2) * pathattr.mtx.GetScale()), 2, 4096);
|
||||
ImageBuffer ib(n, 1);
|
||||
MakeGradient(ib, color1, color2, n);
|
||||
return ib;
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
Fill(GetGradient(color1, color2, p1, p2), p1.x, p1.y, p2.x, p2.y,
|
||||
FILL_VPAD | FILL_FAST |
|
||||
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
|
||||
? FILL_HREPEAT : FILL_HREFLECT));
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
Stroke(width, GetGradient(color1, color2, p1, p2), p1.x, p1.y, p2.x, p2.y,
|
||||
FILL_VPAD | FILL_FAST |
|
||||
(style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT
|
||||
? FILL_HREPEAT : FILL_HREFLECT));
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
240
uppdev/Painter/Image.cpp
Normal file
240
uppdev/Painter/Image.cpp
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#if 0 // does not seem to help...
|
||||
|
||||
Image MipMap(const Image& img)
|
||||
{
|
||||
Size ssz = img.GetSize() / 2;
|
||||
Size msz = (img.GetSize() + 1) / 2;
|
||||
ImageBuffer ib(msz);
|
||||
for(int y = 0; y < ssz.cy; y++) {
|
||||
const RGBA *s1 = img[2 * y];
|
||||
const RGBA *s2 = img[2 * y + 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[y];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r + s2[0].r + s2[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g + s2[0].g + s2[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b + s2[0].b + s2[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a + s2[0].a + s2[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
s2 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = (s1[0].r + s2[0].r) >> 2;
|
||||
t->g = (s1[0].g + s2[0].g) >> 2;
|
||||
t->b = (s1[0].b + s2[0].b) >> 2;
|
||||
t->a = (s1[0].a + s2[0].a) >> 2;
|
||||
}
|
||||
}
|
||||
if(ssz.cy < msz.cy) {
|
||||
const RGBA *s1 = img[img.GetSize().cy - 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[msz.cy - 1];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = s1[0].r >> 2;
|
||||
t->g = s1[0].g >> 2;
|
||||
t->b = s1[0].b >> 2;
|
||||
t->a = s1[0].a >> 2;
|
||||
}
|
||||
}
|
||||
return ib;
|
||||
}
|
||||
|
||||
Image MakeMipMap(const Image& m, int level);
|
||||
|
||||
struct MipMapMaker : ImageMaker {
|
||||
int level;
|
||||
Image image;
|
||||
|
||||
virtual String Key() const {
|
||||
String h;
|
||||
RawCat(h, image.GetSerialId());
|
||||
RawCat(h, level);
|
||||
return h;
|
||||
}
|
||||
virtual Image Make() const {
|
||||
Size sz = image.GetSize();
|
||||
if(sz.cx && sz.cx) {
|
||||
if(level <= 0)
|
||||
return image;
|
||||
return MipMap(MakeMipMap(image, level - 1));
|
||||
}
|
||||
return Image();
|
||||
}
|
||||
};
|
||||
|
||||
Image MakeMipMap(const Image& img, int level)
|
||||
{
|
||||
MipMapMaker m;
|
||||
m.image = img;
|
||||
m.level = level;
|
||||
return MakeImage(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct PainterImageSpan : SpanSource {
|
||||
struct RGBAV {
|
||||
dword r, g, b, a;
|
||||
|
||||
void Set(dword v) { r = g = b = a = v; }
|
||||
void Put(dword weight, const RGBA& src) {
|
||||
r += weight * src.r;
|
||||
g += weight * src.g;
|
||||
b += weight * src.b;
|
||||
a += weight * src.a;
|
||||
}
|
||||
};
|
||||
|
||||
LinearInterpolator interpolator;
|
||||
int ax, ay, cx, cy, maxx, maxy;
|
||||
byte style;
|
||||
byte hstyle, vstyle;
|
||||
bool fast;
|
||||
bool fixed;
|
||||
Image image;
|
||||
|
||||
void Set(const Xform2D& m, const Image& img) {
|
||||
int level = 0;
|
||||
#if 0 // no mipmap for now
|
||||
double q = 1;
|
||||
if(!fast) {
|
||||
double q = 1;
|
||||
Pointf sc = m.GetScaleXY();
|
||||
if(sc.x >= 0.01 && sc.y >= 0.01)
|
||||
while(sc.x < 0.5 && sc.y < 0.5) {
|
||||
level++;
|
||||
sc.x *= 2;
|
||||
sc.y *= 2;
|
||||
q /= 2;
|
||||
}
|
||||
}
|
||||
if(q != 1)
|
||||
interpolator.Set(Inverse(m) * Xform2D::Scale(q));
|
||||
else
|
||||
#endif
|
||||
interpolator.Set(Inverse(m));
|
||||
image = img;
|
||||
// image = MakeMipMap(img, level);
|
||||
cx = image.GetWidth();
|
||||
cy = image.GetHeight();
|
||||
maxx = cx - 1;
|
||||
maxy = cy - 1;
|
||||
ax = 6000000 / cx * cx;
|
||||
ay = 6000000 / cy * cy;
|
||||
}
|
||||
|
||||
RGBA Pixel(int x, int y) { return image[y][x]; }
|
||||
|
||||
RGBA GetPixel(int x, int y) {
|
||||
if(hstyle == FILL_HPAD)
|
||||
x = minmax(x, 0, maxx);
|
||||
else
|
||||
if(hstyle == FILL_HREFLECT)
|
||||
x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx;
|
||||
else
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
x = (x + ax) % cx;
|
||||
if(vstyle == FILL_VPAD)
|
||||
y = minmax(y, 0, maxy);
|
||||
else
|
||||
if(vstyle == FILL_VREFLECT)
|
||||
y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy;
|
||||
else
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
y = (y + ay) % cy;
|
||||
return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero();
|
||||
}
|
||||
|
||||
virtual void Get(RGBA *span, int x, int y, unsigned len)
|
||||
{
|
||||
interpolator.Begin(x, y, len);
|
||||
fixed = hstyle && vstyle;
|
||||
while(len--) {
|
||||
int x_hr;
|
||||
int y_hr;
|
||||
interpolator.Get(x_hr, y_hr);
|
||||
x_hr -= 128;
|
||||
y_hr -= 128;
|
||||
int x_lr = x_hr >> 8;
|
||||
int y_lr = y_hr >> 8;
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
x_lr = (x_lr + ax) % cx;
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
y_lr = (y_lr + ay) % cy;
|
||||
if(fast) {
|
||||
if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy)
|
||||
*span = Pixel(x_lr, y_lr);
|
||||
else
|
||||
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
|
||||
*span = RGBAZero();
|
||||
else
|
||||
*span = GetPixel(x_lr, y_lr);
|
||||
}
|
||||
else {
|
||||
RGBAV v;
|
||||
v.Set(256 * 256 / 2);
|
||||
x_hr &= 255;
|
||||
y_hr &= 255;
|
||||
if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy) {
|
||||
v.Put((256 - x_hr) * (256 - y_hr), Pixel(x_lr, y_lr));
|
||||
v.Put(x_hr * (256 - y_hr), Pixel(x_lr + 1, y_lr));
|
||||
v.Put((256 - x_hr) * y_hr, Pixel(x_lr, y_lr + 1));
|
||||
v.Put(x_hr * y_hr, Pixel(x_lr + 1, y_lr + 1));
|
||||
}
|
||||
else
|
||||
if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy))
|
||||
v.Set(0);
|
||||
else {
|
||||
v.Put((256 - x_hr) * (256 - y_hr), GetPixel(x_lr, y_lr));
|
||||
v.Put(x_hr * (256 - y_hr), GetPixel(x_lr + 1, y_lr));
|
||||
v.Put((256 - x_hr) * y_hr, GetPixel(x_lr, y_lr + 1));
|
||||
v.Put(x_hr * y_hr, GetPixel(x_lr + 1, y_lr + 1));
|
||||
}
|
||||
span->r = byte(v.r >> 16);
|
||||
span->g = byte(v.g >> 16);
|
||||
span->b = byte(v.b >> 16);
|
||||
span->a = byte(v.a >> 16);
|
||||
}
|
||||
++span;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BufferPainter::RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
Close();
|
||||
if(image.GetWidth() == 0 || image.GetHeight() == 0)
|
||||
return;
|
||||
PainterImageSpan ss;
|
||||
ss.style = flags & 15;
|
||||
ss.hstyle = flags & 3;
|
||||
ss.vstyle = flags & 12;
|
||||
ss.fast = flags & FILL_FAST;
|
||||
ss.Set(transsrc * pathattr.mtx, image);
|
||||
RenderPath(width, &ss, RGBAZero());
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
RenderImage(-1, image, transsrc, flags);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
RenderImage(width, image, transsrc, flags);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
46
uppdev/Painter/Interpolator.cpp
Normal file
46
uppdev/Painter/Interpolator.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void LinearInterpolator::Dda2::Set(int p1, int p2, int len)
|
||||
{
|
||||
count = len <= 0 ? 1 : len;
|
||||
lift = (p2 - p1) / count;
|
||||
rem = (p2 - p1) % count;
|
||||
mod = rem;
|
||||
p = p1;
|
||||
if(mod <= 0) {
|
||||
mod += count;
|
||||
rem += count;
|
||||
lift--;
|
||||
}
|
||||
mod -= count;
|
||||
}
|
||||
|
||||
int LinearInterpolator::Dda2::Get()
|
||||
{
|
||||
int pp = p;
|
||||
mod += rem;
|
||||
p += lift;
|
||||
if(mod > 0) {
|
||||
mod -= count;
|
||||
p++;
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
void LinearInterpolator::Begin(int x, int y, int len)
|
||||
{
|
||||
Pointf p1 = xform.Transform(Pointf(x, y) + 0.5);
|
||||
Pointf p2 = xform.Transform(Pointf(x + len, y) + 0.5);
|
||||
ddax.Set(Q8(p1.x), Q8(p2.x), len);
|
||||
dday.Set(Q8(p1.y), Q8(p2.y), len);
|
||||
}
|
||||
|
||||
void LinearInterpolator::Get(int& x, int& y)
|
||||
{
|
||||
x = ddax.Get();
|
||||
y = dday.Get();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -182,12 +182,81 @@ Painter& Painter::RelCubic(double x2, double y2, double x, double y)
|
|||
return *this;
|
||||
}
|
||||
|
||||
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
|
||||
{
|
||||
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
|
||||
m = m * Xform2D::Rotation(Bearing(p2 - p1));
|
||||
m = m * Xform2D::Translation(p1.x, p1.y);
|
||||
return m;
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, Pointf p1, Pointf p2, dword flags)
|
||||
{
|
||||
return Fill(image, GetLineSzXform(p1, p2, image.GetSize()), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, double x1, double y1,
|
||||
double x2, double y2, dword flags)
|
||||
{
|
||||
return Fill(image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Translate(double x, double y)
|
||||
{
|
||||
Transform(Xform2D::Translation(x, y));
|
||||
return *this;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Image& image, double x1, double y1, double x2, double y2, dword flags)
|
||||
{
|
||||
return Stroke(width, image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Rotate(double a)
|
||||
{
|
||||
Transform(Xform2D::Rotation(a));
|
||||
|
|
@ -222,4 +291,14 @@ Painter& Painter::Dash(const char *dash, double start)
|
|||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Rectangle(double x, double y, double cx, double cy)
|
||||
{
|
||||
Move(x, y);
|
||||
Line(x + cx, y);
|
||||
Line(x + cx, y + cy);
|
||||
Line(x, y + cy);
|
||||
Close();
|
||||
return *this;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ struct Xform2D {
|
|||
static Xform2D Scale(double scale);
|
||||
static Xform2D Rotation(double fi);
|
||||
static Xform2D Sheer(double fi);
|
||||
|
||||
Xform2D();
|
||||
};
|
||||
|
||||
Xform2D operator*(const Xform2D& a, const Xform2D& b);
|
||||
|
|
@ -69,8 +71,26 @@ protected:
|
|||
virtual void CloseOp() = 0;
|
||||
|
||||
virtual void FillOp(const RGBA& color) = 0;
|
||||
virtual void FillOp(const Image& image, const Xform2D& transsrc, dword flags) = 0;
|
||||
virtual void FillOp(const Pointf& p1, const RGBA& color1,
|
||||
const Pointf& p2, const RGBA& color2,
|
||||
int style) = 0;
|
||||
virtual void FillOp(const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2,
|
||||
int style) = 0;
|
||||
|
||||
virtual void StrokeOp(double width, const RGBA& rgba) = 0;
|
||||
virtual void StrokeOp(double width, const Image& image, const Xform2D& transsrc,
|
||||
dword flags) = 0;
|
||||
virtual void StrokeOp(double width, const Pointf& p1, const RGBA& color1,
|
||||
const Pointf& p2, const RGBA& color2,
|
||||
int style) = 0;
|
||||
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2,
|
||||
int style) = 0;
|
||||
|
||||
virtual void CharacterOp(double x, double y, int ch, Font fnt);
|
||||
virtual void TextOp(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL);
|
||||
|
||||
virtual void ColorStopOp(double pos, const RGBA& color) = 0;
|
||||
virtual void ClearStopsOp() = 0;
|
||||
|
|
@ -142,8 +162,47 @@ public:
|
|||
Painter& Path(const char *path);
|
||||
|
||||
Painter& Fill(const RGBA& color);
|
||||
Painter& Fill(const Image& image, const Xform2D& transsrc = Xform2D::Identity(), dword flags = 0);
|
||||
Painter& Fill(const Image& image, Pointf p1, Pointf p2, dword flags = 0);
|
||||
Painter& Fill(const Image& image, double x1, double y1, double x2, double y2,
|
||||
dword flags = 0);
|
||||
Painter& Fill(const Pointf& p1, const RGBA& color1,
|
||||
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Fill(double x1, double y1, const RGBA& color1,
|
||||
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Fill(const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Fill(double fx, double fy, const RGBA& color1,
|
||||
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Fill(const Pointf& c, const RGBA& color1,
|
||||
double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Fill(double x, double y, const RGBA& color1,
|
||||
double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
|
||||
Painter& Stroke(double width, const RGBA& color);
|
||||
Painter& Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags = 0);
|
||||
Painter& Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2,
|
||||
dword flags = 0);
|
||||
Painter& Stroke(double width, const Image& image, double x1, double y1, double x2, double y2,
|
||||
dword flags = 0);
|
||||
Painter& Stroke(double width, const Pointf& p1, const RGBA& color1,
|
||||
const Pointf& p2, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Stroke(double width, double x1, double y1, const RGBA& color1,
|
||||
double x2, double y2, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Stroke(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Stroke(double width, double fx, double fy, const RGBA& color1,
|
||||
double cx, double cy, double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Stroke(double width, const Pointf& c, const RGBA& color1,
|
||||
double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
Painter& Stroke(double width, double x, double y, const RGBA& color1,
|
||||
double r, const RGBA& color2, int style = GRADIENT_PAD);
|
||||
|
||||
Painter& Character(double x, double y, int ch, Font fnt);
|
||||
Painter& Text(double x, double y, const wchar *text, Font fnt, int n = -1, double *dx = NULL);
|
||||
Painter& Text(double x, double y, const WString& s, Font fnt, double *dx = NULL);
|
||||
Painter& Text(double x, double y, const String& s, Font fnt, double *dx = NULL);
|
||||
Painter& Text(double x, double y, const char *text, Font fnt, int n = -1, double *dx = NULL);
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
|
|
@ -164,6 +223,8 @@ public:
|
|||
Painter& Rotate(double a);
|
||||
Painter& Scale(double scalex, double scaley);
|
||||
Painter& Scale(double scale);
|
||||
|
||||
Painter& Rectangle(double x, double y, double cx, double cy);
|
||||
};
|
||||
|
||||
#include "Painter.hpp"
|
||||
|
|
|
|||
|
|
@ -60,6 +60,27 @@ Painter& Painter::Fill(const RGBA& color)
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Fill(const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
FillOp(image, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Fill(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
FillOp(p1, color1, p2, color2, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Fill(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
|
||||
{
|
||||
FillOp(f, color1, c, r, color2, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Stroke(double width, const RGBA& color)
|
||||
{
|
||||
|
|
@ -67,6 +88,27 @@ Painter& Painter::Stroke(double width, const RGBA& color)
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Stroke(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
StrokeOp(width, image, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Stroke(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style)
|
||||
{
|
||||
StrokeOp(width, p1, color1, p2, color2, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
|
||||
{
|
||||
StrokeOp(width, f, color1, c, r, color2, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Painter& Painter::ColorStop(double pos, const RGBA& color)
|
||||
{
|
||||
ColorStopOp(pos, color);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
optimize_speed;
|
||||
|
||||
uses
|
||||
Core,
|
||||
CtrlLib;
|
||||
|
|
@ -9,6 +7,9 @@ file
|
|||
Painter.hpp,
|
||||
Painter.cpp,
|
||||
PainterPath.cpp,
|
||||
FontWin32.cpp,
|
||||
FontX11.cpp,
|
||||
Text.cpp,
|
||||
BufferPainter.h,
|
||||
Math.cpp,
|
||||
Xform2D.cpp,
|
||||
|
|
@ -16,14 +17,18 @@ file
|
|||
Stroker.cpp,
|
||||
Dasher.cpp,
|
||||
Transformer.cpp,
|
||||
Rasterizer.cpp,
|
||||
RasterizerClip.cpp,
|
||||
Interpolator.cpp optimize_speed,
|
||||
Rasterizer.cpp optimize_speed,
|
||||
RasterizerClip.cpp optimize_speed,
|
||||
ScanLineFiller.cpp,
|
||||
SolidFiller.cpp,
|
||||
SolidFiller.cpp optimize_speed,
|
||||
SolidFillerMask.cpp,
|
||||
Path.cpp,
|
||||
Path.cpp optimize_speed,
|
||||
Context.cpp,
|
||||
Render.cpp;
|
||||
Render.cpp optimize_speed,
|
||||
Image.cpp optimize_speed,
|
||||
Gradient.cpp optimize_speed,
|
||||
RadialGradient.cpp optimize_speed;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
|
|
|||
219
uppdev/Painter/RadialGradient.cpp
Normal file
219
uppdev/Painter/RadialGradient.cpp
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
uint16 g_sqrt_table[1024] =
|
||||
{
|
||||
0,
|
||||
2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444,
|
||||
8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585,
|
||||
11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890,
|
||||
14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864,
|
||||
15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618,
|
||||
17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212,
|
||||
19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684,
|
||||
20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058,
|
||||
22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351,
|
||||
23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576,
|
||||
24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743,
|
||||
25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859,
|
||||
26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931,
|
||||
28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963,
|
||||
29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960,
|
||||
30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924,
|
||||
30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859,
|
||||
31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768,
|
||||
32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652,
|
||||
33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514,
|
||||
34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354,
|
||||
35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175,
|
||||
36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978,
|
||||
37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763,
|
||||
37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533,
|
||||
38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287,
|
||||
39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028,
|
||||
40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755,
|
||||
40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469,
|
||||
41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171,
|
||||
42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861,
|
||||
42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541,
|
||||
43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210,
|
||||
44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869,
|
||||
44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519,
|
||||
45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160,
|
||||
46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791,
|
||||
46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415,
|
||||
47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030,
|
||||
48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637,
|
||||
48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237,
|
||||
49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830,
|
||||
49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416,
|
||||
50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995,
|
||||
51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567,
|
||||
51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134,
|
||||
52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694,
|
||||
52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248,
|
||||
53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797,
|
||||
53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340,
|
||||
54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877,
|
||||
54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410,
|
||||
55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937,
|
||||
55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459,
|
||||
56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977,
|
||||
57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490,
|
||||
57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999,
|
||||
58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503,
|
||||
58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002,
|
||||
59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498,
|
||||
59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989,
|
||||
60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477,
|
||||
60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960,
|
||||
60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440,
|
||||
61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916,
|
||||
61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388,
|
||||
62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857,
|
||||
62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323,
|
||||
63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785,
|
||||
63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243,
|
||||
64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699,
|
||||
64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151,
|
||||
65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504
|
||||
};
|
||||
|
||||
|
||||
int8 g_elder_bit_table[256] = //---------g_elder_bit_table
|
||||
{
|
||||
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
|
||||
};
|
||||
|
||||
unsigned fastint_sqrt(unsigned val)
|
||||
{
|
||||
unsigned t = val;
|
||||
int bit=0;
|
||||
unsigned shift = 11;
|
||||
bit = t >> 24;
|
||||
if(bit)
|
||||
bit = g_elder_bit_table[bit] + 24;
|
||||
else {
|
||||
bit = (t >> 16) & 0xFF;
|
||||
if(bit)
|
||||
bit = g_elder_bit_table[bit] + 16;
|
||||
else {
|
||||
bit = (t >> 8) & 0xFF;
|
||||
if(bit)
|
||||
bit = g_elder_bit_table[bit] + 8;
|
||||
else
|
||||
bit = g_elder_bit_table[t];
|
||||
}
|
||||
}
|
||||
bit -= 9;
|
||||
if(bit > 0) {
|
||||
bit = (bit >> 1) + (bit & 1);
|
||||
shift -= bit;
|
||||
val >>= (bit << 1);
|
||||
}
|
||||
return g_sqrt_table[val] >> shift;
|
||||
}
|
||||
|
||||
struct PainterRadialSpan : SpanSource {
|
||||
LinearInterpolator interpolator;
|
||||
int cx, cy, r, fx, fy;
|
||||
int style;
|
||||
int alpha;
|
||||
RGBA gradient[2048];
|
||||
bool focus;
|
||||
double C;
|
||||
|
||||
void prepare() {}
|
||||
|
||||
void Set(int _x, int _y, int _r, int _fx, int _fy)
|
||||
{
|
||||
cx = _x;
|
||||
cy = _y;
|
||||
r = _r;
|
||||
fx = _fx;
|
||||
fy = _fy;
|
||||
focus = cx != fx || cy != fy;
|
||||
if(focus) {
|
||||
fx -= cx;
|
||||
fy -= cy;
|
||||
double fx2 = double(fx) * double(fx);
|
||||
double fy2 = double(fy) * double(fy);
|
||||
C = fx * fx + fy * fy - r * r;
|
||||
}
|
||||
else {//WRONG!
|
||||
cx <<= 6;
|
||||
cy <<= 6;
|
||||
r <<= 6;
|
||||
}
|
||||
}
|
||||
|
||||
void Get(RGBA *_span, int x, int y, unsigned len)
|
||||
{
|
||||
if(r <= 0)
|
||||
return;
|
||||
interpolator.Begin(x, y, len);
|
||||
RGBA *span = (RGBA *)_span;
|
||||
while(len--) {
|
||||
interpolator.Get(x, y);
|
||||
int h;
|
||||
if(focus) {
|
||||
const double q256 = 1 / 256.0;
|
||||
double dx = q256 * x - cx - fx;
|
||||
double dy = q256 * y - cy - fy;
|
||||
if(dx == 0 && dy == 0)
|
||||
h = 0;
|
||||
else {
|
||||
double A = dx * dx + dy * dy;
|
||||
double b = (fx * dx + fy * dy);
|
||||
double t = (sqrt(b * b - A * C) - b) / (A);
|
||||
h = t >= 0.001 ? int(2047 / t) : 2047;
|
||||
}
|
||||
}
|
||||
else {
|
||||
x >>= 2;
|
||||
y >>= 2;
|
||||
int dc = Upp::fastint_sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
|
||||
h = 2047 * dc / r;
|
||||
}
|
||||
if(style == GRADIENT_REPEAT)
|
||||
h = h & 2047;
|
||||
else
|
||||
if(style == GRADIENT_REFLECT)
|
||||
h = (h & 2048) ? (2047 - h & 2047) : (h & 2047);
|
||||
else
|
||||
h = minmax(h, 0, 2047);
|
||||
*span++ = gradient[h];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BufferPainter::RenderRadial(double width, const Pointf& f, const RGBA& color1,
|
||||
const Pointf& c, double r, const RGBA& color2, int style)
|
||||
{
|
||||
PainterRadialSpan sg;
|
||||
sg.interpolator.Set(Inverse(pathattr.mtx));
|
||||
sg.style = style;
|
||||
sg.Set((int)c.x, (int)c.y, (int)r, (int)f.x, (int)f.y);
|
||||
MakeGradient(sg.gradient, color1, color2, 2048);
|
||||
RenderPath(width, &sg, RGBAZero());
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
|
||||
{
|
||||
RenderRadial(-1, f, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style)
|
||||
{
|
||||
RenderRadial(width, f, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -30,6 +30,7 @@ Rasterizer::Rasterizer(int cx, int cy)
|
|||
sz.cy = cy;
|
||||
cell.Alloc(sz.cy + 1);
|
||||
cliprect = Sizef(sz);
|
||||
Init();
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,9 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
inline int Cv(double x)
|
||||
{
|
||||
return int(x * 256 + 0.5);
|
||||
}
|
||||
|
||||
void Rasterizer::CvLine(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
LineRaw(Cv(x1), Cv(y1), Cv(x2), Cv(y2));
|
||||
LineRaw(Q8(x1), Q8(y1), Q8(x2), Q8(y2));
|
||||
}
|
||||
|
||||
void Rasterizer::LineClip(double x1, double y1, double x2, double y2)
|
||||
|
|
|
|||
|
|
@ -7,19 +7,37 @@ void BufferPainter::ClearOp(const RGBA& color)
|
|||
UPP::Fill(~ib, color, ib.GetLength());
|
||||
}
|
||||
|
||||
void BufferPainter::RenderPath(LinearPathFilter *first_filter,
|
||||
LinearPathFilter *last_filter, const RGBA& color, bool evenodd)
|
||||
void BufferPainter::RenderPath(double width, SpanSource *ss, const RGBA& color)
|
||||
{
|
||||
if(width == 0)
|
||||
return;
|
||||
Transformer trans(pathattr.mtx);
|
||||
trans.target = &rasterizer;
|
||||
LinearPathConsumer *g;
|
||||
if(first_filter) {
|
||||
last_filter->target = &trans;
|
||||
g = first_filter;
|
||||
Stroker stroker;
|
||||
Dasher dasher;
|
||||
bool evenodd = pathattr.evenodd;
|
||||
if(width > 0) {
|
||||
stroker.Init(width, pathattr.miter_limit, pathattr.tolerance, pathattr.cap, pathattr.join);
|
||||
stroker.target = &trans;
|
||||
if(pathattr.dash.GetCount()) {
|
||||
dasher.Init(pathattr.dash, pathattr.dash_start);
|
||||
dasher.target = &stroker;
|
||||
g = &dasher;
|
||||
}
|
||||
else
|
||||
g = &stroker;
|
||||
evenodd = false;
|
||||
}
|
||||
else
|
||||
else {
|
||||
Close();
|
||||
g = &trans;
|
||||
}
|
||||
byte *data = path.data;
|
||||
int opacity = int(256 * pathattr.opacity);
|
||||
RGBA c;
|
||||
if(!ss)
|
||||
c = Mul8(color, opacity);
|
||||
Pointf pos = Pointf(0, 0);
|
||||
{
|
||||
PAINTER_TIMING("Pipeline");
|
||||
|
|
@ -59,27 +77,25 @@ void BufferPainter::RenderPath(LinearPathFilter *first_filter,
|
|||
}
|
||||
}
|
||||
g->End();
|
||||
Render(ib, rasterizer, color, evenodd);
|
||||
if(ss) {
|
||||
if(!span)
|
||||
span.Alloc(ib.GetWidth() + 1);
|
||||
Render(ib, rasterizer, ss, span, opacity, evenodd);
|
||||
}
|
||||
else
|
||||
Render(ib, rasterizer, c, evenodd);
|
||||
rasterizer.Reset();
|
||||
current = Null;
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const RGBA& color)
|
||||
{
|
||||
Close();
|
||||
RenderPath(NULL, NULL, color, pathattr.evenodd);
|
||||
RenderPath(-1, NULL, color);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const RGBA& color)
|
||||
{
|
||||
Stroker stroker(width, pathattr.miter_limit, pathattr.tolerance, pathattr.cap, pathattr.join);
|
||||
if(pathattr.dash.GetCount()) {
|
||||
Dasher dasher(pathattr.dash, pathattr.dash_start);
|
||||
dasher.target = &stroker;
|
||||
RenderPath(&dasher, &stroker, color, false);
|
||||
}
|
||||
else
|
||||
RenderPath(&stroker, &stroker, color, false);
|
||||
RenderPath(width, NULL, color);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -70,20 +70,41 @@ void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd)
|
|||
}
|
||||
|
||||
struct SpanFiller : Rasterizer::Target {
|
||||
RGBA *t;
|
||||
RGBA *t;
|
||||
const RGBA *s;
|
||||
int y;
|
||||
RGBA *buffer;
|
||||
SpanSource *ss;
|
||||
int alpha;
|
||||
|
||||
void Start(int minx, int maxx) { t += minx; }
|
||||
void Render(int val) { AlphaBlendCover8(*t++, *s++, val); }
|
||||
void Start(int minx, int maxx);
|
||||
void Render(int val);
|
||||
void Render(int val, int len);
|
||||
};
|
||||
|
||||
void SpanFiller::Start(int minx, int maxx)
|
||||
{
|
||||
t += minx;
|
||||
ss->Get(buffer, minx, y, maxx - minx + 1);
|
||||
s = buffer;
|
||||
}
|
||||
|
||||
void SpanFiller::Render(int val)
|
||||
{
|
||||
if(alpha != 256)
|
||||
val = alpha * val >> 8;
|
||||
AlphaBlendCover8(*t++, *s++, val);
|
||||
}
|
||||
|
||||
void SpanFiller::Render(int val, int len)
|
||||
{
|
||||
if(val == 0) {
|
||||
t += len;
|
||||
return;
|
||||
}
|
||||
const RGBA *e = t + len;
|
||||
if(alpha != 256)
|
||||
val = alpha * val >> 8;
|
||||
if(val == 256)
|
||||
while(t < e) {
|
||||
if(s->a == 255)
|
||||
|
|
@ -96,13 +117,16 @@ void SpanFiller::Render(int val, int len)
|
|||
AlphaBlendCover8(*t++, *s++, val);
|
||||
}
|
||||
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd)
|
||||
void Render(ImageBuffer& ib, Rasterizer& r, SpanSource *s, RGBA *buffer, int alpha, bool evenodd)
|
||||
{
|
||||
Size sz = ib.GetSize();
|
||||
SolidFiller f;
|
||||
f.c = color;
|
||||
SpanFiller f;
|
||||
f.ss = s;
|
||||
f.buffer = buffer;
|
||||
f.alpha = alpha;
|
||||
for(int y = r.MinY(); y <= r.MaxY(); y++) {
|
||||
f.t = ib[y];
|
||||
f.y = y;
|
||||
r.Render(y, f, evenodd);
|
||||
}
|
||||
r.Reset();
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
Stroker::Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin)
|
||||
: linecap(linecap),
|
||||
linejoin(linejoin)
|
||||
void Stroker::Init(double width, double miterlimit, double tolerance, int _linecap, int _linejoin)
|
||||
{
|
||||
linecap = _linecap;
|
||||
linejoin = _linejoin;
|
||||
w2 = width / 2;
|
||||
qmiter = miterlimit * w2;
|
||||
qmiter *= qmiter;
|
||||
|
|
|
|||
51
uppdev/Painter/Text.cpp
Normal file
51
uppdev/Painter/Text.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void Painter::TextOp(double x, double y, const wchar *text, Font fnt, int n, double *dx)
|
||||
{
|
||||
FontInfo fi = fnt.Info();
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
while(n) {
|
||||
int ch = *text++;
|
||||
Character(x, y, ch, fnt);
|
||||
if(dx)
|
||||
x += *dx++;
|
||||
else
|
||||
x += fi[ch];
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
Painter& Painter::Character(double x, double y, int ch, Font fnt)
|
||||
{
|
||||
CharacterOp(x, y, ch, fnt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, double *dx)
|
||||
{
|
||||
TextOp(x, y, text, fnt, n, dx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const WString& s, Font fnt, double *dx)
|
||||
{
|
||||
Text(x, y, s, fnt, s.GetLength(), dx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const String& s, Font fnt, double *dx)
|
||||
{
|
||||
Text(x, y, s.ToWString(), fnt, dx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, double *dx)
|
||||
{
|
||||
Text(x, y, ToUnicode(text, n < 0 ? strlen(text) : n, CHARSET_DEFAULT), fnt, dx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -24,6 +24,12 @@ bool Xform2D::IsRegular() const
|
|||
return abs(d.x - d.y) < 1e-10 * abs(max(d.x, d.y));
|
||||
}
|
||||
|
||||
Xform2D::Xform2D()
|
||||
{
|
||||
x.x = y.y = 1;
|
||||
x.y = y.x = t.x = t.y = 0;
|
||||
}
|
||||
|
||||
Xform2D operator*(const Xform2D& a, const Xform2D& b)
|
||||
{
|
||||
Xform2D r;
|
||||
|
|
@ -40,7 +46,6 @@ Xform2D Xform2D::Translation(double x, double y)
|
|||
{
|
||||
Xform2D m;
|
||||
m.x.x = m.y.y = 1;
|
||||
m.x.y = m.y.x = 0;
|
||||
m.t = Pointf(x, y);
|
||||
return m;
|
||||
}
|
||||
|
|
@ -50,7 +55,6 @@ Xform2D Xform2D::Scale(double sx, double sy)
|
|||
Xform2D m;
|
||||
m.x.x = sx;
|
||||
m.y.y = sy;
|
||||
m.x.y = m.y.x = m.t.x = m.t.y = 0;
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +80,6 @@ Xform2D Xform2D::Sheer(double fi)
|
|||
{
|
||||
Xform2D m;
|
||||
m.x.x = m.y.y = 1;
|
||||
m.y.x = m.t.x = m.t.y = 0;
|
||||
m.x.y = atan(fi);
|
||||
return m;
|
||||
}
|
||||
|
|
@ -85,7 +88,6 @@ Xform2D Xform2D::Identity()
|
|||
{
|
||||
Xform2D m;
|
||||
m.x.x = m.y.y = 1;
|
||||
m.x.y = m.y.x = m.t.x = m.t.y = 0;
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +102,8 @@ Xform2D Inverse(const Xform2D& m)
|
|||
double det = Determinant(m);
|
||||
r.x = Pointf(m.y.y, -m.x.y) / det;
|
||||
r.y = Pointf(-m.y.x, m.x.x) / det;
|
||||
r.t.x = -m.t.x * m.x.x - m.t.y * m.x.y;
|
||||
r.t.y = -m.t.x * m.y.x - m.t.y * m.y.y;
|
||||
r.t.x = -m.t.x * r.x.x - m.t.y * r.x.y;
|
||||
r.t.y = -m.t.x * r.y.x - m.t.y * r.y.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void GradientStop(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(20.5, 20.5, 500, 100)
|
||||
|
|
@ -15,5 +13,3 @@ void GradientStop(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Gradient stops", GradientStop);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,14 @@
|
|||
void Dash(Painter& sw)
|
||||
{
|
||||
sw.Move(50, 50).Line(400, 200).Dash("2").Stroke(5, Blue());
|
||||
sw.Translate(0, 10);
|
||||
sw.Move(50, 50).Line(400, 200).Dash("10 5").Stroke(5, Blue());
|
||||
sw.Translate(0, 10);
|
||||
sw.Move(50, 50).Line(400, 200).Dash("10 5 5 5").Stroke(5, Blue());
|
||||
sw.Translate(0, 10);
|
||||
sw.Move(50, 50).Line(400, 200).Dash("1").Stroke(5, Blue());
|
||||
sw.Translate(0, 10);
|
||||
sw.Move(50, 50).Line(400, 200).Dash("1 2 3 4 5").Stroke(5, Blue());
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void FillGradient(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(10, 10, 1000, 600)
|
||||
|
|
@ -28,5 +26,3 @@ INITBLOCK {
|
|||
RegisterExample("Linear gradient - REFLECT", FillGradientReflect);
|
||||
RegisterExample("Linear gradient - REPEAT", FillGradientRepeat);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,19 +1,30 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void ImageExact(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(10, 10, 1000, 600)
|
||||
// .Fill(TestImg::test(), 200, 100, 300, 300) _DBG_
|
||||
.Fill(TestImg::test(), 100, 100, 500, 100)
|
||||
.Stroke(2, Black());
|
||||
}
|
||||
|
||||
void ImageExactFast(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(10, 10, 1000, 600)
|
||||
.Fill(TestImg::test(), 100, 100, 500, 100, FILL_FAST)
|
||||
.Stroke(2, Black());
|
||||
/*
|
||||
int cx = 400;
|
||||
for(int l = 0; l < 5; l++) {
|
||||
sw.Translate(cx, 0);
|
||||
cx /= 2;
|
||||
sw.Rectangle(10, 10, 1000, 600)
|
||||
.Fill(MakeMipMap(TestImg::test(), l), 100, 100, 100 + cx, 100, FILL_FAST);
|
||||
}*/
|
||||
}
|
||||
|
||||
void ImageReflect(Painter& sw)
|
||||
{
|
||||
sw.Rectangle(10, 10, 1000, 600)
|
||||
// .Fill(TestImg::test(), 200, 100, 300, 300, GRADIENT_REFLECT) _DBG_
|
||||
.Fill(TestImg::test(), 100, 100, 500, 100, FILL_REFLECT)
|
||||
.Stroke(2, Black());
|
||||
}
|
||||
|
|
@ -41,10 +52,9 @@ void ImageRepeat(Painter& sw)
|
|||
|
||||
INITBLOCK {
|
||||
RegisterExample("Image fill exact", ImageExact);
|
||||
RegisterExample("Image fill exact fast", ImageExactFast);
|
||||
RegisterExample("Image fill reflect", ImageReflect);
|
||||
RegisterExample("Image fill pad", ImagePad);
|
||||
RegisterExample("Image fill repeat", ImageRepeat);
|
||||
RegisterExample("Image vpad&hreflect", ImageVPadHReflect);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -189,7 +189,6 @@ void PaintLion(Painter& sw)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void Demo(Painter& sw)
|
||||
{
|
||||
PaintLion(sw);
|
||||
|
|
@ -200,7 +199,6 @@ void Demo(Painter& sw)
|
|||
.Fill(TestImg::test(), 0, 400, 500, 400, FILL_REFLECT)
|
||||
.Stroke(5, 0, 500, Blue(), tsz.cx, 500, LtRed())
|
||||
.Stroke(1, White());
|
||||
|
||||
for(int i = 0; i < 10; i++) {
|
||||
sw.Begin();
|
||||
sw.Opacity(0.5);
|
||||
|
|
@ -211,9 +209,8 @@ void Demo(Painter& sw)
|
|||
sw.End();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
INITBLOCK {
|
||||
RegisterExample("Lion", PaintLion);
|
||||
// RegisterExample("U++ Painter", Demo);
|
||||
RegisterExample("U++ Painter", Demo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
description "Antialiased renderer class, Painter, examples";
|
||||
description "Antialiased renderer class, Painter, examples, version 2.0";
|
||||
|
||||
uses
|
||||
CtrlLib,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void Path(Painter& sw)
|
||||
{
|
||||
sw.Translate(52, 52);
|
||||
|
|
@ -19,5 +17,3 @@ void Path(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Path example", Path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ void DoRect(Painter &sw, double size, bool image)
|
|||
sw.Line(0, size);
|
||||
sw.Line(size, size);
|
||||
sw.Line(size, 0);
|
||||
#if 0
|
||||
if(image)
|
||||
sw.Fill(TestImg::test(), 0, 0, size, 0);
|
||||
else
|
||||
#endif
|
||||
sw.Fill(Blue());
|
||||
|
||||
sw.Begin();
|
||||
|
|
@ -38,8 +36,6 @@ void PythagorasTree(Painter& sw)
|
|||
sw.End();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
void PythagorasTreeImage(Painter& sw)
|
||||
{
|
||||
sw.Begin();
|
||||
|
|
@ -48,9 +44,8 @@ void PythagorasTreeImage(Painter& sw)
|
|||
DoRect(sw, 160, true);
|
||||
sw.End();
|
||||
}
|
||||
#endif
|
||||
|
||||
INITBLOCK {
|
||||
RegisterExample("Pythagoras tree", PythagorasTree);
|
||||
// RegisterExample("Pythagoras tree image", PythagorasTreeImage);
|
||||
RegisterExample("Pythagoras tree image", PythagorasTreeImage);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void RadialFocus(Painter& sw)
|
||||
{
|
||||
sw.Circle(400.5, 400.5, 200)
|
||||
.Fill(300, 300, White(), 400.5, 400.5, 200, LtBlue())
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RadialFocusPad(Painter& sw)
|
||||
{
|
||||
|
|
@ -34,10 +34,8 @@ void RadialFocusRepeat(Painter& sw)
|
|||
}
|
||||
|
||||
INITBLOCK {
|
||||
RegisterExample("Radial gradient - focus", RadialFocus);
|
||||
// RegisterExample("Radial gradient - focus", RadialFocus);
|
||||
RegisterExample("Radial gradient - focus - PAD", RadialFocusPad);
|
||||
RegisterExample("Radial gradient - focus - REFLECT", RadialFocusReflect);
|
||||
RegisterExample("Radial gradient - focus - REPEAT", RadialFocusRepeat);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void PathSpiral(Painter& sw)
|
||||
{
|
||||
sw.Path("M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 "
|
||||
|
|
@ -14,5 +12,3 @@ void PathSpiral(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Path spiral", PathSpiral);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void Stroke(Painter& sw)
|
||||
{
|
||||
const char *txt = "GRM";//ADIENT TEXT";
|
||||
const char *txt = "GRM";
|
||||
Font fnt = Arial(100).Bold();
|
||||
Size tsz = GetTextSize(txt, fnt);
|
||||
sw.Scale(3, 3);
|
||||
|
|
@ -18,5 +16,3 @@ void Stroke(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Stroke", Stroke);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void TextFillGradient(Painter& sw)
|
||||
{
|
||||
const char *txt = "GRADIENT TEXT";
|
||||
|
|
@ -14,5 +12,3 @@ void TextFillGradient(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Filling text with linear gradient", TextFillGradient);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void TextFillSolid(Painter& sw)
|
||||
{
|
||||
sw.Text(100, 100, "Hello world!", Roman(120).Italic().Bold())
|
||||
|
|
@ -11,5 +9,3 @@ void TextFillSolid(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Filling text with solid color", TextFillSolid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "Examples.h"
|
||||
|
||||
#if 0
|
||||
|
||||
void TextStrokeGradient(Painter& sw)
|
||||
{
|
||||
const char *txt = "GRADIENT TEXT";
|
||||
|
|
@ -14,5 +12,3 @@ void TextStrokeGradient(Painter& sw)
|
|||
INITBLOCK {
|
||||
RegisterExample("Stroking text with linear gradient", TextStrokeGradient);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
void ThinPolygon(Painter& sw)
|
||||
{
|
||||
// sw.Translate(52, 52);
|
||||
sw.Translate(52, 52);
|
||||
for(int i = 0; i < 2; i++) {
|
||||
sw.Move(36.000000, 142.000000);
|
||||
sw.Line(480.000000, 148.000000);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue