diff options
Diffstat (limited to 'gtk/PlatGTK.cxx')
-rw-r--r-- | gtk/PlatGTK.cxx | 116 |
1 files changed, 85 insertions, 31 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index c94847825..e323b0ad1 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -9,6 +9,9 @@ #include <stddef.h> #include <math.h> +#include <vector> +#include <map> + #include <glib.h> #include <gmodule.h> #include <gdk/gdk.h> @@ -785,6 +788,7 @@ public: void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back); void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, ColourAllocated outline, int alphaOutline, int flags); + void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); @@ -1362,6 +1366,51 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated #endif } +void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { + if (rc.Width() > width) + rc.left += (rc.Width() - width) / 2; + rc.right = rc.left + width; + if (rc.Height() > height) + rc.top += (rc.Height() - height) / 2; + rc.bottom = rc.top + height; + +#ifdef USE_CAIRO + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + int ucs = stride * height; + std::vector<unsigned char> image(ucs); + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + unsigned char *pixel = &image[0] + y*stride + x * 4; + unsigned char alpha = pixelsImage[3]; + pixel[2] = (*pixelsImage++) * alpha / 255; + pixel[1] = (*pixelsImage++) * alpha / 255; + pixel[0] = (*pixelsImage++) * alpha / 255; + pixel[3] = *pixelsImage++; + } + } + + cairo_surface_t *psurf = cairo_image_surface_create_for_data(&image[0], CAIRO_FORMAT_ARGB32, width, height, stride); + cairo_set_source_surface(context, psurf, rc.left, rc.top); + cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + cairo_fill(context); + + cairo_surface_destroy(psurf); +#else + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(pixelsImage, + GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height, + width * 4, + NULL, + NULL); + gdk_draw_pixbuf(drawable, gc, pixbuf, + 0,0, rc.left,rc.top, width,height, GDK_RGB_DITHER_NORMAL, 0, 0); + g_object_unref(pixbuf); +#endif +} + void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(back); #ifdef USE_CAIRO @@ -2225,8 +2274,10 @@ PRectangle Window::GetMonitorRect(Point pt) { #endif } +typedef std::map<int, RGBAImage*> ImageMap; + struct ListImage { - const char *xpm_data; + const RGBAImage *rgba_data; GdkPixbuf *pixbuf; }; @@ -2254,7 +2305,7 @@ class ListBoxX : public ListBox { WindowID scroller; void *pixhash; GtkCellRenderer* pixbuf_renderer; - XPMSet xset; + RGBAImageSet images; int desiredVisibleRows; unsigned int maxItemCharacters; unsigned int aveCharWidth; @@ -2286,7 +2337,9 @@ public: virtual int GetSelection(); virtual int Find(const char *prefix); virtual void GetValue(int n, char *value, int len); + void RegisterRGBA(int type, RGBAImage *image); virtual void RegisterImage(int type, const char *xpm_data); + virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage); virtual void ClearRegisteredImages(); virtual void SetDoubleClickAction(CallBackAction action, void *data) { doubleClickAction = action; @@ -2511,25 +2564,21 @@ void ListBoxX::Clear() { } static void init_pixmap(ListImage *list_image) { - const char *textForm = list_image->xpm_data; - const char * const * xpm_lineform = reinterpret_cast<const char * const *>(textForm); - const char **xpm_lineformfromtext = 0; - // The XPM data can be either in atext form as will be read from a file - // or in a line form (array of char *) as will be used for images defined in code. - // Test for text form and convert to line form - if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) { - // Test done is two parts to avoid possibility of overstepping the memory - // if memcmp implemented strangely. Must be 4 bytes at least at destination. - xpm_lineformfromtext = XPM::LinesFormFromTextForm(textForm); - xpm_lineform = xpm_lineformfromtext; - } - - // Drop any existing pixmap/bitmap as data may have changed - if (list_image->pixbuf) - g_object_unref(list_image->pixbuf); - list_image->pixbuf = - gdk_pixbuf_new_from_xpm_data((const gchar**)xpm_lineform); - delete []xpm_lineformfromtext; + if (list_image->rgba_data) { + // Drop any existing pixmap/bitmap as data may have changed + if (list_image->pixbuf) + g_object_unref(list_image->pixbuf); + list_image->pixbuf = + gdk_pixbuf_new_from_data(list_image->rgba_data->Pixels(), + GDK_COLORSPACE_RGB, + TRUE, + 8, + list_image->rgba_data->GetWidth(), + list_image->rgba_data->GetHeight(), + list_image->rgba_data->GetWidth() * 4, + NULL, + NULL); + } } #define SPACING 5 @@ -2697,13 +2746,8 @@ void ListBoxX::GetValue(int n, char *value, int len) { #pragma warning(disable: 4127) #endif -void ListBoxX::RegisterImage(int type, const char *xpm_data) { - g_return_if_fail(xpm_data); - - // Saved and use the saved copy so caller's copy can disappear. - xset.Add(type, xpm_data); - XPM *pxpm = xset.Get(type); - xpm_data = reinterpret_cast<const char *>(pxpm->InLinesForm()); +void ListBoxX::RegisterRGBA(int type, RGBAImage *image) { + images.Add(type, image); if (!pixhash) { pixhash = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -2715,17 +2759,27 @@ void ListBoxX::RegisterImage(int type, const char *xpm_data) { if (list_image->pixbuf) g_object_unref(list_image->pixbuf); list_image->pixbuf = NULL; - list_image->xpm_data = xpm_data; + list_image->rgba_data = image; } else { list_image = g_new0(ListImage, 1); - list_image->xpm_data = xpm_data; + list_image->rgba_data = image; g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type), (gpointer) list_image); } } +void ListBoxX::RegisterImage(int type, const char *xpm_data) { + g_return_if_fail(xpm_data); + XPM xpmImage(xpm_data); + RegisterRGBA(type, new RGBAImage(xpmImage)); +} + +void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) { + RegisterRGBA(type, new RGBAImage(width, height, pixelsImage)); +} + void ListBoxX::ClearRegisteredImages() { - xset.Clear(); + images.Clear(); } void ListBoxX::SetList(const char *listText, char separator, char typesep) { |