diff --git a/uppsrc/CtrlCore/ImageX11.cpp b/uppsrc/CtrlCore/ImageX11.cpp index a2f9b9faf..5ad19e149 100644 --- a/uppsrc/CtrlCore/ImageX11.cpp +++ b/uppsrc/CtrlCore/ImageX11.cpp @@ -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 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 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 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 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 - -#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 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 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 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 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 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 + +#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 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 diff --git a/uppsrc/CtrlCore/X11Wnd.cpp b/uppsrc/CtrlCore/X11Wnd.cpp index 5f36a6a7d..5a6a5c116 100644 --- a/uppsrc/CtrlCore/X11Wnd.cpp +++ b/uppsrc/CtrlCore/X11Wnd.cpp @@ -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) diff --git a/uppsrc/Draw/FontFc.cpp b/uppsrc/Draw/FontFc.cpp index 06b38b6f7..792b8799b 100644 --- a/uppsrc/Draw/FontFc.cpp +++ b/uppsrc/Draw/FontFc.cpp @@ -1,5 +1,8 @@ #include "Draw.h" +#include +#include + 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 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); diff --git a/uppsrc/Draw/Image.h b/uppsrc/Draw/Image.h index e139d9600..15b396076 100644 --- a/uppsrc/Draw/Image.h +++ b/uppsrc/Draw/Image.h @@ -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 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 > { -private: - struct Data : Link { - Atomic refcount; - int64 serial; - int paintcount; - - static Link 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 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(*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 UnpackImlData(const void *ptr, int len); -Vector UnpackImlData(const String& d); - -class Iml { - struct IImage : Moveable { - bool loaded; - Image image; - - IImage() { loaded = false; } - }; - struct Data : Moveable { - const char *data; - int len, count; - }; - Vector data; - VectorMap 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 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 > { +private: + struct Data : Link { + Atomic refcount; + int64 serial; + int paintcount; + + static Link 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 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(*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 UnpackImlData(const void *ptr, int len); +Vector UnpackImlData(const String& d); + +class Iml { + struct IImage : Moveable { + bool loaded; + Image image; + + IImage() { loaded = false; } + }; + struct Data : Moveable { + const char *data; + int len, count; + }; + Vector data; + VectorMap 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 diff --git a/uppsrc/Painter/FontX11.cpp b/uppsrc/Painter/FontX11.cpp index 25a0a400a..4d40f4598 100644 --- a/uppsrc/Painter/FontX11.cpp +++ b/uppsrc/Painter/FontX11.cpp @@ -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 +#include + +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