Fixing new draw in X11

git-svn-id: svn://ultimatepp.org/upp/trunk@1377 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-07-06 22:45:26 +00:00
parent 196488cf31
commit dcbf79f623
5 changed files with 931 additions and 924 deletions

View file

@ -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

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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