mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Fixing new draw in X11
git-svn-id: svn://ultimatepp.org/upp/trunk@1377 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
196488cf31
commit
dcbf79f623
5 changed files with 931 additions and 924 deletions
|
|
@ -1,436 +1,436 @@
|
|||
#include "SystemDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
struct Image::Data::SystemData {
|
||||
int cursor_cheat;
|
||||
XPicture picture;
|
||||
XPicture picture8;
|
||||
};
|
||||
|
||||
Image::Data::SystemData& Image::Data::Sys() const
|
||||
{
|
||||
ASSERT(sizeof(system_buffer) >= sizeof(SystemData));
|
||||
return *(SystemData *)system_buffer;
|
||||
}
|
||||
|
||||
void Image::SetCursorCheat(int id)
|
||||
{
|
||||
data->Sys().cursor_cheat = id;
|
||||
}
|
||||
|
||||
int Image::GetCursorCheat() const
|
||||
{
|
||||
return data ? data->Sys().cursor_cheat : -1;
|
||||
}
|
||||
|
||||
static void sInitXImage(XImage& ximg, Size sz)
|
||||
{
|
||||
Zero(ximg);
|
||||
ximg.width = sz.cx;
|
||||
ximg.height = sz.cy;
|
||||
ximg.xoffset = 0;
|
||||
ximg.format = ZPixmap;
|
||||
ximg.bitmap_bit_order = MSBFirst;
|
||||
#ifdef CPU_LITTLE_ENDIAN
|
||||
ximg.byte_order = LSBFirst;
|
||||
#else
|
||||
ximg.byte_order = MSBFirst;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
|
||||
{
|
||||
GuiLock __;
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, cx, cy, 24);
|
||||
XPicture picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardRGB24),
|
||||
0, 0
|
||||
);
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, Size(cx, cy));
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
Buffer<RGBA> pma;
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.depth = 24;
|
||||
ximg.data = (char *)pixels;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, cx, cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
0, 0, 0, 0, x, y, cx, cy);
|
||||
XRenderFreePicture(Xdisplay, picture);
|
||||
}
|
||||
|
||||
int Image::Data::GetResCount() const
|
||||
{
|
||||
return !!Sys().picture + !!Sys().picture8;
|
||||
}
|
||||
|
||||
void Image::Data::SysInit()
|
||||
{
|
||||
SystemData& sd = Sys();
|
||||
sd.picture = 0;
|
||||
sd.picture8 = 0;
|
||||
sd.cursor_cheat = -1;
|
||||
}
|
||||
|
||||
void Image::Data::SysRelease()
|
||||
{
|
||||
SystemData& sd = Sys();
|
||||
if(sd.picture) {
|
||||
GuiLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture);
|
||||
ResCount -= !paintonly;
|
||||
sd.picture = 0;
|
||||
}
|
||||
if(sd.picture8) {
|
||||
GuiLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture8);
|
||||
ResCount -= !paintonly;
|
||||
sd.picture8 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct XRSolidFill {
|
||||
Color color;
|
||||
XPicture picture;
|
||||
Pixmap pixmap;
|
||||
};
|
||||
|
||||
enum { XRSolidFillCount = 67 };
|
||||
|
||||
static XRSolidFill sFill[XRSolidFillCount];
|
||||
|
||||
inline int s255d16(int x)
|
||||
{
|
||||
return (x << 8)|x;
|
||||
}
|
||||
|
||||
static XPicture sGetSolidFill(Color c)
|
||||
{
|
||||
GuiLock __;
|
||||
int q = GetHashValue(c) % (int)XRSolidFillCount;
|
||||
XRSolidFill& f = sFill[q];
|
||||
if(f.color == c && f.picture)
|
||||
return f.picture;
|
||||
if(f.picture)
|
||||
XRenderFreePicture(Xdisplay, f.picture);
|
||||
if(f.pixmap)
|
||||
XFreePixmap(Xdisplay, f.pixmap);
|
||||
f.pixmap = XCreatePixmap(Xdisplay, Xroot, 1, 1, 32);
|
||||
XRenderPictureAttributes attr;
|
||||
attr.repeat = XTrue;
|
||||
f.picture = XRenderCreatePicture(Xdisplay, f.pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
|
||||
CPRepeat, &attr);
|
||||
f.color = c;
|
||||
XRenderColor xc;
|
||||
xc.red = s255d16(c.GetR());
|
||||
xc.green = s255d16(c.GetG());
|
||||
xc.blue = s255d16(c.GetB());
|
||||
xc.alpha = 65535;
|
||||
XRenderFillRectangle(Xdisplay, PictOpSrc, f.picture, &xc, 0, 0, 1, 1);
|
||||
return f.picture;
|
||||
}
|
||||
|
||||
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
||||
{
|
||||
GuiLock __;
|
||||
SystemData& sd = Sys();
|
||||
while(ResCount > 512) {
|
||||
Image::Data *l = ResData->GetPrev();
|
||||
l->SysRelease();
|
||||
l->Unlink();
|
||||
}
|
||||
x += w.GetOffset().x;
|
||||
y += w.GetOffset().y;
|
||||
Size sz = buffer.GetSize();
|
||||
int len = sz.cx * sz.cy;
|
||||
Rect sr = src & sz;
|
||||
Size ssz = sr.Size();
|
||||
if(sr.IsEmpty())
|
||||
return;
|
||||
if(GetKind() == IMAGE_EMPTY)
|
||||
return;
|
||||
if(GetKind() == IMAGE_OPAQUE && !IsNull(c)) {
|
||||
w.DrawRect(x, y, sz.cx, sz.cy, c);
|
||||
return;
|
||||
}
|
||||
if(GetKind() == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz)) {
|
||||
SetSurface(w, x, y, sz.cx, sz.cy, buffer);
|
||||
paintcount++;
|
||||
return;
|
||||
}
|
||||
Unlink();
|
||||
LinkAfter(ResData);
|
||||
if(IsNull(c)) {
|
||||
if(!sd.picture) {
|
||||
bool opaque = GetKind() == IMAGE_OPAQUE;
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32);
|
||||
sd.picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24
|
||||
: PictStandardARGB32),
|
||||
0, 0
|
||||
);
|
||||
ResCount++;
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * sz.cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.data = (char *)~buffer;
|
||||
ximg.depth = opaque ? 24 : 32;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
PaintOnlyShrink();
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
sd.picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
else {
|
||||
ASSERT(!paintonly);
|
||||
if(!sd.picture8) {
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8);
|
||||
sd.picture8 = XRenderCreatePicture(Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
|
||||
0, 0);
|
||||
ResCount++;
|
||||
Buffer<byte> ab(len);
|
||||
byte *t = ab;
|
||||
const RGBA *s = buffer;
|
||||
const RGBA *e = s + len;
|
||||
while(s < e)
|
||||
*t++ = (s++)->a;
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.data = (char *)~ab;
|
||||
ximg.bitmap_unit = 8;
|
||||
ximg.bitmap_pad = 8;
|
||||
ximg.depth = 8;
|
||||
ximg.bytes_per_line = sz.cx;
|
||||
ximg.bits_per_pixel = 8;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
sGetSolidFill(c), sd.picture8, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageDraw::Init()
|
||||
{
|
||||
GuiLock __;
|
||||
dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
|
||||
gc = XCreateGC(Xdisplay, dw, 0, 0);
|
||||
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
|
||||
|
||||
alpha.dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
|
||||
alpha.gc = XCreateGC(Xdisplay, alpha.dw, 0, 0);
|
||||
alpha.xftdraw = XftDrawCreate(Xdisplay, (Drawable) alpha.dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
|
||||
|
||||
Vector<Rect> clip;
|
||||
clip.Add(RectC(0, 0, size.cx, size.cy));
|
||||
SystemDraw::Init(clip, Point(0, 0));
|
||||
alpha.Init(clip, Point(0, 0));
|
||||
|
||||
has_alpha = false;
|
||||
}
|
||||
|
||||
ImageDraw::operator Image() const
|
||||
{
|
||||
GuiLock __;
|
||||
XImage *xim = XGetImage(Xdisplay, dw, 0, 0, max(size.cx, 1), max(size.cy, 1), AllPlanes, ZPixmap);
|
||||
Visual *v = DefaultVisual(Xdisplay, Xscreenno);
|
||||
RasterFormat fmt;
|
||||
|
||||
RGBA palette[256];
|
||||
|
||||
switch(xim->depth) {
|
||||
case 15:
|
||||
case 16:
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set16le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set16be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
break;
|
||||
case 8: {
|
||||
int n = min(v->map_entries, 256);
|
||||
XColor colors[256];
|
||||
for(int i = 0; i < 256; i++) {
|
||||
colors[i].pixel = i;
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
}
|
||||
XQueryColors(Xdisplay, Xcolormap, colors, n);
|
||||
XColor *s = colors;
|
||||
XColor *e = s + n;
|
||||
while(s < e) {
|
||||
RGBA& t = palette[s->pixel];
|
||||
t.r = s->red >> 8;
|
||||
t.g = s->green >> 8;
|
||||
t.b = s->blue >> 8;
|
||||
t.a = 255;
|
||||
s++;
|
||||
}
|
||||
fmt.Set8();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(xim->bits_per_pixel == 32)
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set32le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set32be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set24le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set24be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
ImageBuffer ib(size);
|
||||
const byte *s = (const byte *)xim->data;
|
||||
RGBA *t = ib;
|
||||
for(int y = 0; y < size.cy; y++) {
|
||||
fmt.Read(t, s, size.cx, palette);
|
||||
s += xim->bytes_per_line;
|
||||
t += size.cx;
|
||||
}
|
||||
XDestroyImage(xim);
|
||||
if(has_alpha) {
|
||||
xim = XGetImage(Xdisplay, alpha.dw, 0, 0, size.cx, size.cy, AllPlanes, ZPixmap);
|
||||
const byte *s = (const byte *)xim->data;
|
||||
t = ib;
|
||||
Buffer<RGBA> line(size.cx);
|
||||
for(int y = 0; y < size.cy; y++) {
|
||||
fmt.Read(line, s, size.cx, palette);
|
||||
for(int x = 0; x < size.cx; x++)
|
||||
(t++)->a = line[x].r;
|
||||
s += xim->bytes_per_line;
|
||||
}
|
||||
XDestroyImage(xim);
|
||||
}
|
||||
Premultiply(ib);
|
||||
return ib;
|
||||
}
|
||||
|
||||
ImageDraw::ImageDraw(Size sz)
|
||||
{
|
||||
size = sz;
|
||||
Init();
|
||||
}
|
||||
|
||||
ImageDraw::ImageDraw(int cx, int cy)
|
||||
{
|
||||
size = Size(cx, cy);
|
||||
Init();
|
||||
}
|
||||
|
||||
ImageDraw::~ImageDraw()
|
||||
{
|
||||
GuiLock __;
|
||||
XftDrawDestroy(xftdraw);
|
||||
XFreePixmap(Xdisplay, dw);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XftDrawDestroy(alpha.xftdraw);
|
||||
XFreePixmap(Xdisplay, alpha.dw);
|
||||
XFreeGC(Xdisplay, alpha.gc);
|
||||
}
|
||||
|
||||
Image sX11Cursor__(int c)
|
||||
{
|
||||
ImageBuffer b(32, 32);
|
||||
Image m(b);
|
||||
m.SetCursorCheat(c);
|
||||
return m;
|
||||
}
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
#define FCURSOR_(x) { Image h; INTERLOCKED { static Image m = sX11Cursor__(x); h = m; } return h; }
|
||||
|
||||
Image Image::Arrow() FCURSOR_(XC_left_ptr)
|
||||
Image Image::Wait() FCURSOR_(XC_watch)
|
||||
Image Image::IBeam() FCURSOR_(XC_xterm)
|
||||
Image Image::No() FCURSOR_(XC_circle)
|
||||
Image Image::SizeAll() FCURSOR_(XC_fleur)
|
||||
Image Image::SizeHorz() FCURSOR_(XC_sb_h_double_arrow)
|
||||
Image Image::SizeVert() FCURSOR_(XC_double_arrow)
|
||||
Image Image::SizeTopLeft() FCURSOR_(XC_top_left_corner)
|
||||
Image Image::SizeTop() FCURSOR_(XC_top_side)
|
||||
Image Image::SizeTopRight() FCURSOR_(XC_top_right_corner)
|
||||
Image Image::SizeLeft() FCURSOR_(XC_left_side)
|
||||
Image Image::SizeRight() FCURSOR_(XC_right_side)
|
||||
Image Image::SizeBottomLeft() FCURSOR_(XC_bottom_left_corner)
|
||||
Image Image::SizeBottom() FCURSOR_(XC_bottom_side)
|
||||
Image Image::SizeBottomRight() FCURSOR_(XC_bottom_right_corner)
|
||||
Image Image::Cross() FCURSOR_(XC_crosshair)
|
||||
Image Image::Hand() FCURSOR_(XC_hand1)
|
||||
|
||||
Cursor X11Cursor(const Image& img)
|
||||
{
|
||||
GuiLock __;
|
||||
int q = img.GetCursorCheat();
|
||||
if(q >= 0)
|
||||
return XCreateFontCursor(Xdisplay, q);
|
||||
int len = img.GetLength();
|
||||
Size sz = img.GetSize();
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 32);
|
||||
XPicture picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
|
||||
0, 0
|
||||
);
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * sz.cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
Buffer<RGBA> pma;
|
||||
pma.Alloc(len);
|
||||
memcpy(pma, ~img, len * sizeof(RGBA));
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.depth = 32;
|
||||
ximg.data = (char *)~pma;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
Point p = img.GetHotSpot();
|
||||
Cursor c = XRenderCreateCursor(Xdisplay, picture, p.x, p.y);
|
||||
XRenderFreePicture(Xdisplay, picture);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "SystemDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
struct Image::Data::SystemData {
|
||||
int cursor_cheat;
|
||||
XPicture picture;
|
||||
XPicture picture8;
|
||||
};
|
||||
|
||||
Image::Data::SystemData& Image::Data::Sys() const
|
||||
{
|
||||
ASSERT(sizeof(system_buffer) >= sizeof(SystemData));
|
||||
return *(SystemData *)system_buffer;
|
||||
}
|
||||
|
||||
void Image::SetCursorCheat(int id)
|
||||
{
|
||||
data->Sys().cursor_cheat = id;
|
||||
}
|
||||
|
||||
int Image::GetCursorCheat() const
|
||||
{
|
||||
return data ? data->Sys().cursor_cheat : -1;
|
||||
}
|
||||
|
||||
static void sInitXImage(XImage& ximg, Size sz)
|
||||
{
|
||||
Zero(ximg);
|
||||
ximg.width = sz.cx;
|
||||
ximg.height = sz.cy;
|
||||
ximg.xoffset = 0;
|
||||
ximg.format = ZPixmap;
|
||||
ximg.bitmap_bit_order = MSBFirst;
|
||||
#ifdef CPU_LITTLE_ENDIAN
|
||||
ximg.byte_order = LSBFirst;
|
||||
#else
|
||||
ximg.byte_order = MSBFirst;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
|
||||
{
|
||||
GuiLock __;
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, cx, cy, 24);
|
||||
XPicture picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardRGB24),
|
||||
0, 0
|
||||
);
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, Size(cx, cy));
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
Buffer<RGBA> pma;
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.depth = 24;
|
||||
ximg.data = (char *)pixels;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, cx, cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
0, 0, 0, 0, x, y, cx, cy);
|
||||
XRenderFreePicture(Xdisplay, picture);
|
||||
}
|
||||
|
||||
int Image::Data::GetResCount() const
|
||||
{
|
||||
return !!Sys().picture + !!Sys().picture8;
|
||||
}
|
||||
|
||||
void Image::Data::SysInit()
|
||||
{
|
||||
SystemData& sd = Sys();
|
||||
sd.picture = 0;
|
||||
sd.picture8 = 0;
|
||||
sd.cursor_cheat = -1;
|
||||
}
|
||||
|
||||
void Image::Data::SysRelease()
|
||||
{
|
||||
SystemData& sd = Sys();
|
||||
if(sd.picture) {
|
||||
GuiLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture);
|
||||
ResCount -= !paintonly;
|
||||
sd.picture = 0;
|
||||
}
|
||||
if(sd.picture8) {
|
||||
GuiLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture8);
|
||||
ResCount -= !paintonly;
|
||||
sd.picture8 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct XRSolidFill {
|
||||
Color color;
|
||||
XPicture picture;
|
||||
Pixmap pixmap;
|
||||
};
|
||||
|
||||
enum { XRSolidFillCount = 67 };
|
||||
|
||||
static XRSolidFill sFill[XRSolidFillCount];
|
||||
|
||||
inline int s255d16(int x)
|
||||
{
|
||||
return (x << 8)|x;
|
||||
}
|
||||
|
||||
static XPicture sGetSolidFill(Color c)
|
||||
{
|
||||
GuiLock __;
|
||||
int q = GetHashValue(c) % (int)XRSolidFillCount;
|
||||
XRSolidFill& f = sFill[q];
|
||||
if(f.color == c && f.picture)
|
||||
return f.picture;
|
||||
if(f.picture)
|
||||
XRenderFreePicture(Xdisplay, f.picture);
|
||||
if(f.pixmap)
|
||||
XFreePixmap(Xdisplay, f.pixmap);
|
||||
f.pixmap = XCreatePixmap(Xdisplay, Xroot, 1, 1, 32);
|
||||
XRenderPictureAttributes attr;
|
||||
attr.repeat = XTrue;
|
||||
f.picture = XRenderCreatePicture(Xdisplay, f.pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
|
||||
CPRepeat, &attr);
|
||||
f.color = c;
|
||||
XRenderColor xc;
|
||||
xc.red = s255d16(c.GetR());
|
||||
xc.green = s255d16(c.GetG());
|
||||
xc.blue = s255d16(c.GetB());
|
||||
xc.alpha = 65535;
|
||||
XRenderFillRectangle(Xdisplay, PictOpSrc, f.picture, &xc, 0, 0, 1, 1);
|
||||
return f.picture;
|
||||
}
|
||||
|
||||
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
||||
{
|
||||
GuiLock __;
|
||||
SystemData& sd = Sys();
|
||||
while(ResCount > 512) {
|
||||
Image::Data *l = ResData->GetPrev();
|
||||
l->SysRelease();
|
||||
l->Unlink();
|
||||
}
|
||||
x += w.GetOffset().x;
|
||||
y += w.GetOffset().y;
|
||||
Size sz = buffer.GetSize();
|
||||
int len = sz.cx * sz.cy;
|
||||
Rect sr = src & sz;
|
||||
Size ssz = sr.Size();
|
||||
if(sr.IsEmpty())
|
||||
return;
|
||||
if(GetKind() == IMAGE_EMPTY)
|
||||
return;
|
||||
if(GetKind() == IMAGE_OPAQUE && !IsNull(c)) {
|
||||
w.DrawRect(x, y, sz.cx, sz.cy, c);
|
||||
return;
|
||||
}
|
||||
if(GetKind() == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz)) {
|
||||
SetSurface(w, x, y, sz.cx, sz.cy, buffer);
|
||||
paintcount++;
|
||||
return;
|
||||
}
|
||||
Unlink();
|
||||
LinkAfter(ResData);
|
||||
if(IsNull(c)) {
|
||||
if(!sd.picture) {
|
||||
bool opaque = GetKind() == IMAGE_OPAQUE;
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32);
|
||||
sd.picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24
|
||||
: PictStandardARGB32),
|
||||
0, 0
|
||||
);
|
||||
ResCount++;
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * sz.cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.data = (char *)~buffer;
|
||||
ximg.depth = opaque ? 24 : 32;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
PaintOnlyShrink();
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
sd.picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
else {
|
||||
ASSERT(!paintonly);
|
||||
if(!sd.picture8) {
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8);
|
||||
sd.picture8 = XRenderCreatePicture(Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
|
||||
0, 0);
|
||||
ResCount++;
|
||||
Buffer<byte> ab(len);
|
||||
byte *t = ab;
|
||||
const RGBA *s = buffer;
|
||||
const RGBA *e = s + len;
|
||||
while(s < e)
|
||||
*t++ = (s++)->a;
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.data = (char *)~ab;
|
||||
ximg.bitmap_unit = 8;
|
||||
ximg.bitmap_pad = 8;
|
||||
ximg.depth = 8;
|
||||
ximg.bytes_per_line = sz.cx;
|
||||
ximg.bits_per_pixel = 8;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
sGetSolidFill(c), sd.picture8, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageDraw::Init()
|
||||
{
|
||||
GuiLock __;
|
||||
dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
|
||||
gc = XCreateGC(Xdisplay, dw, 0, 0);
|
||||
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
|
||||
|
||||
alpha.dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
|
||||
alpha.gc = XCreateGC(Xdisplay, alpha.dw, 0, 0);
|
||||
alpha.xftdraw = XftDrawCreate(Xdisplay, (Drawable) alpha.dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
|
||||
|
||||
Vector<Rect> clip;
|
||||
clip.Add(RectC(0, 0, size.cx, size.cy));
|
||||
SystemDraw::Init(clip, Point(0, 0));
|
||||
alpha.Init(clip, Point(0, 0));
|
||||
|
||||
has_alpha = false;
|
||||
}
|
||||
|
||||
ImageDraw::operator Image() const
|
||||
{
|
||||
GuiLock __;
|
||||
XImage *xim = XGetImage(Xdisplay, dw, 0, 0, max(size.cx, 1), max(size.cy, 1), AllPlanes, ZPixmap);
|
||||
Visual *v = DefaultVisual(Xdisplay, Xscreenno);
|
||||
RasterFormat fmt;
|
||||
|
||||
RGBA palette[256];
|
||||
|
||||
switch(xim->depth) {
|
||||
case 15:
|
||||
case 16:
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set16le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set16be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
break;
|
||||
case 8: {
|
||||
int n = min(v->map_entries, 256);
|
||||
XColor colors[256];
|
||||
for(int i = 0; i < 256; i++) {
|
||||
colors[i].pixel = i;
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
}
|
||||
XQueryColors(Xdisplay, Xcolormap, colors, n);
|
||||
XColor *s = colors;
|
||||
XColor *e = s + n;
|
||||
while(s < e) {
|
||||
RGBA& t = palette[s->pixel];
|
||||
t.r = s->red >> 8;
|
||||
t.g = s->green >> 8;
|
||||
t.b = s->blue >> 8;
|
||||
t.a = 255;
|
||||
s++;
|
||||
}
|
||||
fmt.Set8();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(xim->bits_per_pixel == 32)
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set32le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set32be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
if(xim->byte_order == LSBFirst)
|
||||
fmt.Set24le(v->red_mask, v->green_mask, v->blue_mask);
|
||||
else
|
||||
fmt.Set24be(v->red_mask, v->green_mask, v->blue_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
ImageBuffer ib(size);
|
||||
const byte *s = (const byte *)xim->data;
|
||||
RGBA *t = ib;
|
||||
for(int y = 0; y < size.cy; y++) {
|
||||
fmt.Read(t, s, size.cx, palette);
|
||||
s += xim->bytes_per_line;
|
||||
t += size.cx;
|
||||
}
|
||||
XDestroyImage(xim);
|
||||
if(has_alpha) {
|
||||
xim = XGetImage(Xdisplay, alpha.dw, 0, 0, size.cx, size.cy, AllPlanes, ZPixmap);
|
||||
const byte *s = (const byte *)xim->data;
|
||||
t = ib;
|
||||
Buffer<RGBA> line(size.cx);
|
||||
for(int y = 0; y < size.cy; y++) {
|
||||
fmt.Read(line, s, size.cx, palette);
|
||||
for(int x = 0; x < size.cx; x++)
|
||||
(t++)->a = line[x].r;
|
||||
s += xim->bytes_per_line;
|
||||
}
|
||||
XDestroyImage(xim);
|
||||
}
|
||||
Premultiply(ib);
|
||||
return ib;
|
||||
}
|
||||
|
||||
ImageDraw::ImageDraw(Size sz)
|
||||
{
|
||||
size = sz;
|
||||
Init();
|
||||
}
|
||||
|
||||
ImageDraw::ImageDraw(int cx, int cy)
|
||||
{
|
||||
size = Size(cx, cy);
|
||||
Init();
|
||||
}
|
||||
|
||||
ImageDraw::~ImageDraw()
|
||||
{
|
||||
GuiLock __;
|
||||
XftDrawDestroy(xftdraw);
|
||||
XFreePixmap(Xdisplay, dw);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XftDrawDestroy(alpha.xftdraw);
|
||||
XFreePixmap(Xdisplay, alpha.dw);
|
||||
XFreeGC(Xdisplay, alpha.gc);
|
||||
}
|
||||
|
||||
Image sX11Cursor__(int c)
|
||||
{
|
||||
ImageBuffer b(32, 32);
|
||||
Image m(b);
|
||||
m.SetCursorCheat(c);
|
||||
return m;
|
||||
}
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
#define FCURSOR_(x) { Image h; INTERLOCKED { static Image m = sX11Cursor__(x); h = m; } return h; }
|
||||
|
||||
Image Image::Arrow() FCURSOR_(XC_left_ptr)
|
||||
Image Image::Wait() FCURSOR_(XC_watch)
|
||||
Image Image::IBeam() FCURSOR_(XC_xterm)
|
||||
Image Image::No() FCURSOR_(XC_circle)
|
||||
Image Image::SizeAll() FCURSOR_(XC_fleur)
|
||||
Image Image::SizeHorz() FCURSOR_(XC_sb_h_double_arrow)
|
||||
Image Image::SizeVert() FCURSOR_(XC_double_arrow)
|
||||
Image Image::SizeTopLeft() FCURSOR_(XC_top_left_corner)
|
||||
Image Image::SizeTop() FCURSOR_(XC_top_side)
|
||||
Image Image::SizeTopRight() FCURSOR_(XC_top_right_corner)
|
||||
Image Image::SizeLeft() FCURSOR_(XC_left_side)
|
||||
Image Image::SizeRight() FCURSOR_(XC_right_side)
|
||||
Image Image::SizeBottomLeft() FCURSOR_(XC_bottom_left_corner)
|
||||
Image Image::SizeBottom() FCURSOR_(XC_bottom_side)
|
||||
Image Image::SizeBottomRight() FCURSOR_(XC_bottom_right_corner)
|
||||
Image Image::Cross() FCURSOR_(XC_crosshair)
|
||||
Image Image::Hand() FCURSOR_(XC_hand1)
|
||||
|
||||
void *X11Cursor(const Image& img)
|
||||
{
|
||||
GuiLock __;
|
||||
int q = img.GetCursorCheat();
|
||||
if(q >= 0)
|
||||
return (void *)XCreateFontCursor(Xdisplay, q);
|
||||
int len = img.GetLength();
|
||||
Size sz = img.GetSize();
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 32);
|
||||
XPicture picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
|
||||
0, 0
|
||||
);
|
||||
XImage ximg;
|
||||
sInitXImage(ximg, sz);
|
||||
ximg.bitmap_pad = 32;
|
||||
ximg.bytes_per_line = 4 * sz.cx;
|
||||
ximg.bits_per_pixel = 32;
|
||||
ximg.blue_mask = 0x00ff0000;
|
||||
ximg.green_mask = 0x0000ff00;
|
||||
ximg.red_mask = 0x000000ff;
|
||||
Buffer<RGBA> pma;
|
||||
pma.Alloc(len);
|
||||
memcpy(pma, ~img, len * sizeof(RGBA));
|
||||
ximg.bitmap_unit = 32;
|
||||
ximg.depth = 32;
|
||||
ximg.data = (char *)~pma;
|
||||
XInitImage(&ximg);
|
||||
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
|
||||
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
|
||||
XFreeGC(Xdisplay, gc);
|
||||
XFreePixmap(Xdisplay, pixmap);
|
||||
Point p = img.GetHotSpot();
|
||||
Cursor c = XRenderCreateCursor(Xdisplay, picture, p.x, p.y);
|
||||
XRenderFreePicture(Xdisplay, picture);
|
||||
return (void *)c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ void Ctrl::SetMouseCursor(const Image& image)
|
|||
static Cursor shc;
|
||||
if(img.GetSerialId() != image.GetSerialId()) {
|
||||
img = image;
|
||||
Cursor hc = X11Cursor(IsNull(img) ? Image::Arrow() : img);
|
||||
Cursor hc = (Cursor)X11Cursor(IsNull(img) ? Image::Arrow() : img);
|
||||
for(int i = 0; i < Xwindow().GetCount(); i++) {
|
||||
Window wnd = Xwindow().GetKey(i);
|
||||
if(wnd)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "Draw.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
|
@ -45,7 +48,7 @@ FcPattern *CreateFcPattern(Font font, int angle)
|
|||
FcPatternAddMatrix(p, FC_MATRIX, &mx);
|
||||
}
|
||||
FcResult result;
|
||||
FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result);
|
||||
FcPattern *m = FcFontMatch(0, p, &result);
|
||||
FcPatternDestroy(p);
|
||||
return m;
|
||||
}
|
||||
|
|
@ -198,7 +201,7 @@ Vector<FaceInfo> GetAllFacesSys()
|
|||
fi.info = (i == 3 || i == 6) ? Font::SCALEABLE|Font::FIXEDPITCH : Font::SCALEABLE;
|
||||
}
|
||||
FcPattern *p = FcPatternCreate();
|
||||
FcObjectSet *os = FcObjectSetBuild(XFT_FAMILY, XFT_SPACING, XFT_SCALABLE, (void *)0);
|
||||
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_SCALABLE, (void *)0);
|
||||
FcFontSet *fs = FcFontList(NULL, p, os);
|
||||
FcPatternDestroy(p);
|
||||
FcObjectSetDestroy(os);
|
||||
|
|
|
|||
|
|
@ -1,332 +1,332 @@
|
|||
#define NEWIMAGE
|
||||
|
||||
enum ImageKind {
|
||||
IMAGE_UNKNOWN,
|
||||
IMAGE_EMPTY,
|
||||
IMAGE_ALPHA,
|
||||
IMAGE_MASK,
|
||||
IMAGE_OPAQUE,
|
||||
};
|
||||
|
||||
inline bool operator==(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
inline bool operator!=(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
|
||||
|
||||
void Fill(RGBA *t, const RGBA& src, int n);
|
||||
void FillColor(RGBA *t, const RGBA& src, int n);
|
||||
|
||||
void Copy(RGBA *t, const RGBA *s, int n);
|
||||
|
||||
int Premultiply(RGBA *t, const RGBA *s, int len);
|
||||
int Unmultiply(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
|
||||
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
|
||||
|
||||
int GetChMaskPos32(dword mask);
|
||||
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
|
||||
|
||||
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
|
||||
String PackRLE(const RGBA *s, int len);
|
||||
|
||||
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
|
||||
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
|
||||
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
|
||||
|
||||
class Image;
|
||||
|
||||
class ImageBuffer : NoCopy {
|
||||
mutable int kind;
|
||||
Size size;
|
||||
Buffer<RGBA> pixels;
|
||||
Point hotspot;
|
||||
Point spot2;
|
||||
Size dots;
|
||||
|
||||
void Set(Image& img);
|
||||
void DeepCopy(const ImageBuffer& img);
|
||||
|
||||
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
|
||||
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
|
||||
|
||||
friend class Image;
|
||||
|
||||
public:
|
||||
void SetKind(int k) { kind = k; }
|
||||
int GetKind() const { return kind; }
|
||||
int ScanKind() const;
|
||||
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
|
||||
|
||||
void SetHotSpot(Point p) { hotspot = p; }
|
||||
Point GetHotSpot() const { return hotspot; }
|
||||
|
||||
void Set2ndSpot(Point p) { spot2 = p; }
|
||||
Point Get2ndSpot() const { return spot2; }
|
||||
|
||||
void SetDots(Size sz) { dots = sz; }
|
||||
Size GetDots() const { return dots; }
|
||||
|
||||
Size GetSize() const { return size; }
|
||||
int GetWidth() const { return size.cx; }
|
||||
int GetHeight() const { return size.cy; }
|
||||
int GetLength() const { return size.cx * size.cy; }
|
||||
|
||||
RGBA *operator[](int i) { return Line(i); }
|
||||
const RGBA *operator[](int i) const { return Line(i); }
|
||||
RGBA *operator~() { return pixels; }
|
||||
operator RGBA*() { return pixels; }
|
||||
const RGBA *operator~() const { return pixels; }
|
||||
operator const RGBA*() const { return pixels; }
|
||||
|
||||
void Create(int cx, int cy);
|
||||
void Create(Size sz) { Create(sz.cx, sz.cy); }
|
||||
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
|
||||
void Clear() { Create(0, 0); }
|
||||
|
||||
void operator=(Image& img);
|
||||
void operator=(ImageBuffer& img);
|
||||
|
||||
ImageBuffer() { Create(0, 0); }
|
||||
ImageBuffer(int cx, int cy) { Create(cx, cy); }
|
||||
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
|
||||
ImageBuffer(Image& img);
|
||||
ImageBuffer(ImageBuffer& b);
|
||||
};
|
||||
|
||||
void Premultiply(ImageBuffer& b);
|
||||
void Unmultiply(ImageBuffer& b);
|
||||
|
||||
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
|
||||
|
||||
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
|
||||
private:
|
||||
struct Data : Link<Data> {
|
||||
Atomic refcount;
|
||||
int64 serial;
|
||||
int paintcount;
|
||||
|
||||
static Link<Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Retain() { AtomicInc(refcount); }
|
||||
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
||||
|
||||
struct SystemData;
|
||||
|
||||
void *system_buffer[6];
|
||||
SystemData& Sys() const;
|
||||
int GetResCount() const;
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void CreateHBMP(HDC dc, const RGBA *data);
|
||||
#endif
|
||||
|
||||
ImageBuffer buffer;
|
||||
bool paintonly;
|
||||
|
||||
void SysInit();
|
||||
void SysRelease();
|
||||
int GetKind();
|
||||
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
|
||||
void PaintOnlyShrink();
|
||||
|
||||
Data(ImageBuffer& b);
|
||||
~Data();
|
||||
};
|
||||
|
||||
Data *data;
|
||||
|
||||
static Link<Image::Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Set(ImageBuffer& b);
|
||||
|
||||
friend class ImageBuffer;
|
||||
friend struct Data;
|
||||
|
||||
friend class SystemDraw;
|
||||
|
||||
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
|
||||
|
||||
friend void SetPaintOnly___(Image& m);
|
||||
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
void SetCursorCheat(LPCSTR id);
|
||||
LPCSTR GetCursorCheat() const;
|
||||
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
|
||||
friend HICON IconWin32(const Image& img, bool cursor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
void SetCursorCheat(int id);
|
||||
int GetCursorCheat() const;
|
||||
friend Cursor X11Cursor(const Image&);
|
||||
friend Image sX11Cursor__(int c);
|
||||
#endif
|
||||
|
||||
public:
|
||||
const RGBA* operator~() const;
|
||||
operator const RGBA*() const;
|
||||
const RGBA* operator[](int i) const;
|
||||
|
||||
Size GetSize() const;
|
||||
int GetWidth() const { return GetSize().cx; }
|
||||
int GetHeight() const { return GetSize().cy; }
|
||||
int GetLength() const;
|
||||
Point GetHotSpot() const;
|
||||
Point Get2ndSpot() const;
|
||||
Size GetDots() const;
|
||||
int GetKindNoScan() const;
|
||||
int GetKind() const;
|
||||
|
||||
int64 GetSerialId() const { return data ? data->serial : 0; }
|
||||
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
|
||||
|
||||
bool operator==(const Image& img) const;
|
||||
bool operator!=(const Image& img) const;
|
||||
dword GetHashValue() const;
|
||||
String ToString() const;
|
||||
|
||||
void Serialize(Stream& s);
|
||||
void Clear();
|
||||
|
||||
Image& operator=(const Image& img);
|
||||
Image& operator=(ImageBuffer& img);
|
||||
|
||||
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
|
||||
|
||||
bool IsEmpty() const { return IsNullInstance(); }
|
||||
operator Value() const { return RichValue<Image>(*this); }
|
||||
|
||||
Image() { data = NULL; }
|
||||
Image(const Nuller&) { data = NULL; }
|
||||
Image(const Value& src);
|
||||
Image(const Image& img);
|
||||
Image(Image (*fn)());
|
||||
Image(ImageBuffer& b);
|
||||
~Image();
|
||||
|
||||
|
||||
static Image Arrow();
|
||||
static Image Wait();
|
||||
static Image IBeam();
|
||||
static Image No();
|
||||
static Image SizeAll();
|
||||
static Image SizeHorz();
|
||||
static Image SizeVert();
|
||||
static Image SizeTopLeft();
|
||||
static Image SizeTop();
|
||||
static Image SizeTopRight();
|
||||
static Image SizeLeft();
|
||||
static Image SizeRight();
|
||||
static Image SizeBottomLeft();
|
||||
static Image SizeBottom();
|
||||
static Image SizeBottomRight();
|
||||
static Image Cross();
|
||||
static Image Hand();
|
||||
|
||||
// IML support ("private"), deprecated - legacy .iml
|
||||
struct Init {
|
||||
const char *const *scans;
|
||||
int16 scan_count;
|
||||
char info[24];
|
||||
};
|
||||
explicit Image(const Init& init);
|
||||
};
|
||||
|
||||
Image Premultiply(const Image& img);
|
||||
Image Unmultiply(const Image& img);
|
||||
|
||||
Vector<Image> UnpackImlData(const void *ptr, int len);
|
||||
Vector<Image> UnpackImlData(const String& d);
|
||||
|
||||
class Iml {
|
||||
struct IImage : Moveable<IImage> {
|
||||
bool loaded;
|
||||
Image image;
|
||||
|
||||
IImage() { loaded = false; }
|
||||
};
|
||||
struct Data : Moveable<Data> {
|
||||
const char *data;
|
||||
int len, count;
|
||||
};
|
||||
Vector<Data> data;
|
||||
VectorMap<String, IImage> map;
|
||||
const Image::Init *img_init;
|
||||
const char **name;
|
||||
bool premultiply;
|
||||
|
||||
void Init(int n);
|
||||
|
||||
public:
|
||||
void Enter();
|
||||
void Leave();
|
||||
void Reset();
|
||||
int GetCount() const { return map.GetCount(); }
|
||||
String GetId(int i) { return map.GetKey(i); }
|
||||
Image Get(int i);
|
||||
int Find(const String& s) const { return map.Find(s); }
|
||||
void Set(int i, const Image& img);
|
||||
void Premultiplied() { premultiply = false; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
int GetBinSize() const;
|
||||
#endif
|
||||
|
||||
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
|
||||
void AddData(const byte *data, int len, int count);
|
||||
};
|
||||
|
||||
void Register(const char *imageclass, Iml& iml);
|
||||
|
||||
int GetImlCount();
|
||||
String GetImlName(int i);
|
||||
Iml& GetIml(int i);
|
||||
int FindIml(const char *name);
|
||||
Image GetImlImage(const char *name);
|
||||
void SetImlImage(const char *name, const Image& m);
|
||||
|
||||
String StoreImageAsString(const Image& img);
|
||||
Image LoadImageFromString(const String& s);
|
||||
Size GetImageStringSize(const String& src);
|
||||
Size GetImageStringDots(const String& src);
|
||||
|
||||
#include "Raster.h"
|
||||
#include "ImageOp.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
|
||||
Image Win32Icon(LPCSTR id, int iconsize = 0);
|
||||
Image Win32Icon(int id, int iconsize = 0);
|
||||
Image Win32Cursor(LPCSTR id);
|
||||
Image Win32Cursor(int id);
|
||||
HICON IconWin32(const Image& img, bool cursor = false);
|
||||
Image Win32DllIcon(const char *dll, int ii, bool large);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
Cursor X11Cursor(const Image& img);
|
||||
#endif
|
||||
#define NEWIMAGE
|
||||
|
||||
enum ImageKind {
|
||||
IMAGE_UNKNOWN,
|
||||
IMAGE_EMPTY,
|
||||
IMAGE_ALPHA,
|
||||
IMAGE_MASK,
|
||||
IMAGE_OPAQUE,
|
||||
};
|
||||
|
||||
inline bool operator==(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
inline bool operator!=(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
|
||||
|
||||
void Fill(RGBA *t, const RGBA& src, int n);
|
||||
void FillColor(RGBA *t, const RGBA& src, int n);
|
||||
|
||||
void Copy(RGBA *t, const RGBA *s, int n);
|
||||
|
||||
int Premultiply(RGBA *t, const RGBA *s, int len);
|
||||
int Unmultiply(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
|
||||
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
|
||||
|
||||
int GetChMaskPos32(dword mask);
|
||||
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
|
||||
|
||||
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
|
||||
String PackRLE(const RGBA *s, int len);
|
||||
|
||||
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
|
||||
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
|
||||
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
|
||||
|
||||
class Image;
|
||||
|
||||
class ImageBuffer : NoCopy {
|
||||
mutable int kind;
|
||||
Size size;
|
||||
Buffer<RGBA> pixels;
|
||||
Point hotspot;
|
||||
Point spot2;
|
||||
Size dots;
|
||||
|
||||
void Set(Image& img);
|
||||
void DeepCopy(const ImageBuffer& img);
|
||||
|
||||
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
|
||||
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
|
||||
|
||||
friend class Image;
|
||||
|
||||
public:
|
||||
void SetKind(int k) { kind = k; }
|
||||
int GetKind() const { return kind; }
|
||||
int ScanKind() const;
|
||||
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
|
||||
|
||||
void SetHotSpot(Point p) { hotspot = p; }
|
||||
Point GetHotSpot() const { return hotspot; }
|
||||
|
||||
void Set2ndSpot(Point p) { spot2 = p; }
|
||||
Point Get2ndSpot() const { return spot2; }
|
||||
|
||||
void SetDots(Size sz) { dots = sz; }
|
||||
Size GetDots() const { return dots; }
|
||||
|
||||
Size GetSize() const { return size; }
|
||||
int GetWidth() const { return size.cx; }
|
||||
int GetHeight() const { return size.cy; }
|
||||
int GetLength() const { return size.cx * size.cy; }
|
||||
|
||||
RGBA *operator[](int i) { return Line(i); }
|
||||
const RGBA *operator[](int i) const { return Line(i); }
|
||||
RGBA *operator~() { return pixels; }
|
||||
operator RGBA*() { return pixels; }
|
||||
const RGBA *operator~() const { return pixels; }
|
||||
operator const RGBA*() const { return pixels; }
|
||||
|
||||
void Create(int cx, int cy);
|
||||
void Create(Size sz) { Create(sz.cx, sz.cy); }
|
||||
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
|
||||
void Clear() { Create(0, 0); }
|
||||
|
||||
void operator=(Image& img);
|
||||
void operator=(ImageBuffer& img);
|
||||
|
||||
ImageBuffer() { Create(0, 0); }
|
||||
ImageBuffer(int cx, int cy) { Create(cx, cy); }
|
||||
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
|
||||
ImageBuffer(Image& img);
|
||||
ImageBuffer(ImageBuffer& b);
|
||||
};
|
||||
|
||||
void Premultiply(ImageBuffer& b);
|
||||
void Unmultiply(ImageBuffer& b);
|
||||
|
||||
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
|
||||
|
||||
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
|
||||
private:
|
||||
struct Data : Link<Data> {
|
||||
Atomic refcount;
|
||||
int64 serial;
|
||||
int paintcount;
|
||||
|
||||
static Link<Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Retain() { AtomicInc(refcount); }
|
||||
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
||||
|
||||
struct SystemData;
|
||||
|
||||
void *system_buffer[6];
|
||||
SystemData& Sys() const;
|
||||
int GetResCount() const;
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void CreateHBMP(HDC dc, const RGBA *data);
|
||||
#endif
|
||||
|
||||
ImageBuffer buffer;
|
||||
bool paintonly;
|
||||
|
||||
void SysInit();
|
||||
void SysRelease();
|
||||
int GetKind();
|
||||
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
|
||||
void PaintOnlyShrink();
|
||||
|
||||
Data(ImageBuffer& b);
|
||||
~Data();
|
||||
};
|
||||
|
||||
Data *data;
|
||||
|
||||
static Link<Image::Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Set(ImageBuffer& b);
|
||||
|
||||
friend class ImageBuffer;
|
||||
friend struct Data;
|
||||
|
||||
friend class SystemDraw;
|
||||
|
||||
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
|
||||
|
||||
friend void SetPaintOnly___(Image& m);
|
||||
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
void SetCursorCheat(LPCSTR id);
|
||||
LPCSTR GetCursorCheat() const;
|
||||
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
|
||||
friend HICON IconWin32(const Image& img, bool cursor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
void SetCursorCheat(int id);
|
||||
int GetCursorCheat() const;
|
||||
friend void *X11Cursor(const Image&);
|
||||
friend Image sX11Cursor__(int c);
|
||||
#endif
|
||||
|
||||
public:
|
||||
const RGBA* operator~() const;
|
||||
operator const RGBA*() const;
|
||||
const RGBA* operator[](int i) const;
|
||||
|
||||
Size GetSize() const;
|
||||
int GetWidth() const { return GetSize().cx; }
|
||||
int GetHeight() const { return GetSize().cy; }
|
||||
int GetLength() const;
|
||||
Point GetHotSpot() const;
|
||||
Point Get2ndSpot() const;
|
||||
Size GetDots() const;
|
||||
int GetKindNoScan() const;
|
||||
int GetKind() const;
|
||||
|
||||
int64 GetSerialId() const { return data ? data->serial : 0; }
|
||||
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
|
||||
|
||||
bool operator==(const Image& img) const;
|
||||
bool operator!=(const Image& img) const;
|
||||
dword GetHashValue() const;
|
||||
String ToString() const;
|
||||
|
||||
void Serialize(Stream& s);
|
||||
void Clear();
|
||||
|
||||
Image& operator=(const Image& img);
|
||||
Image& operator=(ImageBuffer& img);
|
||||
|
||||
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
|
||||
|
||||
bool IsEmpty() const { return IsNullInstance(); }
|
||||
operator Value() const { return RichValue<Image>(*this); }
|
||||
|
||||
Image() { data = NULL; }
|
||||
Image(const Nuller&) { data = NULL; }
|
||||
Image(const Value& src);
|
||||
Image(const Image& img);
|
||||
Image(Image (*fn)());
|
||||
Image(ImageBuffer& b);
|
||||
~Image();
|
||||
|
||||
|
||||
static Image Arrow();
|
||||
static Image Wait();
|
||||
static Image IBeam();
|
||||
static Image No();
|
||||
static Image SizeAll();
|
||||
static Image SizeHorz();
|
||||
static Image SizeVert();
|
||||
static Image SizeTopLeft();
|
||||
static Image SizeTop();
|
||||
static Image SizeTopRight();
|
||||
static Image SizeLeft();
|
||||
static Image SizeRight();
|
||||
static Image SizeBottomLeft();
|
||||
static Image SizeBottom();
|
||||
static Image SizeBottomRight();
|
||||
static Image Cross();
|
||||
static Image Hand();
|
||||
|
||||
// IML support ("private"), deprecated - legacy .iml
|
||||
struct Init {
|
||||
const char *const *scans;
|
||||
int16 scan_count;
|
||||
char info[24];
|
||||
};
|
||||
explicit Image(const Init& init);
|
||||
};
|
||||
|
||||
Image Premultiply(const Image& img);
|
||||
Image Unmultiply(const Image& img);
|
||||
|
||||
Vector<Image> UnpackImlData(const void *ptr, int len);
|
||||
Vector<Image> UnpackImlData(const String& d);
|
||||
|
||||
class Iml {
|
||||
struct IImage : Moveable<IImage> {
|
||||
bool loaded;
|
||||
Image image;
|
||||
|
||||
IImage() { loaded = false; }
|
||||
};
|
||||
struct Data : Moveable<Data> {
|
||||
const char *data;
|
||||
int len, count;
|
||||
};
|
||||
Vector<Data> data;
|
||||
VectorMap<String, IImage> map;
|
||||
const Image::Init *img_init;
|
||||
const char **name;
|
||||
bool premultiply;
|
||||
|
||||
void Init(int n);
|
||||
|
||||
public:
|
||||
void Enter();
|
||||
void Leave();
|
||||
void Reset();
|
||||
int GetCount() const { return map.GetCount(); }
|
||||
String GetId(int i) { return map.GetKey(i); }
|
||||
Image Get(int i);
|
||||
int Find(const String& s) const { return map.Find(s); }
|
||||
void Set(int i, const Image& img);
|
||||
void Premultiplied() { premultiply = false; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
int GetBinSize() const;
|
||||
#endif
|
||||
|
||||
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
|
||||
void AddData(const byte *data, int len, int count);
|
||||
};
|
||||
|
||||
void Register(const char *imageclass, Iml& iml);
|
||||
|
||||
int GetImlCount();
|
||||
String GetImlName(int i);
|
||||
Iml& GetIml(int i);
|
||||
int FindIml(const char *name);
|
||||
Image GetImlImage(const char *name);
|
||||
void SetImlImage(const char *name, const Image& m);
|
||||
|
||||
String StoreImageAsString(const Image& img);
|
||||
Image LoadImageFromString(const String& s);
|
||||
Size GetImageStringSize(const String& src);
|
||||
Size GetImageStringDots(const String& src);
|
||||
|
||||
#include "Raster.h"
|
||||
#include "ImageOp.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
|
||||
Image Win32Icon(LPCSTR id, int iconsize = 0);
|
||||
Image Win32Icon(int id, int iconsize = 0);
|
||||
Image Win32Cursor(LPCSTR id);
|
||||
Image Win32Cursor(int id);
|
||||
HICON IconWin32(const Image& img, bool cursor = false);
|
||||
Image Win32DllIcon(const char *dll, int ii, bool large);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
void *X11Cursor(const Image& img);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,153 +1,157 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// 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 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, sw, p.x, p.y + fnt.Info().GetAscent());
|
||||
XftUnlockFace(fi.GetXftFont());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
//----------------------------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath);
|
||||
|
||||
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 PaintCharacterSys(Painter& sw, double x, double y, int ch, Font fnt)
|
||||
{
|
||||
DrawLock __;
|
||||
PAINTER_TIMING("CharacterOp");
|
||||
FT_Face face = FTFace(fnt, NULL);
|
||||
int glyph_index = FT_Get_Char_Index(face, ch);
|
||||
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)
|
||||
RenderOutline(face->glyph->outline, sw, x, y + fnt.GetAscent());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue