aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-06-25 07:58:03 +1000
committernyamatongwe <unknown>2011-06-25 07:58:03 +1000
commit640bc7546d4d8ad5228e09ed2d280ea12b0690e9 (patch)
tree8b0e456078c1db7c0751a9edee6bfbe258a24792
parentaa198d68b4f938a20aadfb53267fab87f64a7004 (diff)
downloadscintilla-mirror-640bc7546d4d8ad5228e09ed2d280ea12b0690e9.tar.gz
Initial implementation of RGBA images.
-rw-r--r--cocoa/PlatCocoa.h1
-rw-r--r--cocoa/PlatCocoa.mm88
-rw-r--r--cocoa/ScintillaCocoa.h1
-rw-r--r--doc/ScintillaDoc.html69
-rw-r--r--gtk/PlatGTK.cxx116
-rw-r--r--gtk/ScintillaGTK.cxx1
-rw-r--r--include/Platform.h2
-rw-r--r--include/Scintilla.h5
-rw-r--r--include/Scintilla.iface15
-rw-r--r--macosx/PlatMacOSX.cxx12
-rw-r--r--macosx/PlatMacOSX.h1
-rw-r--r--macosx/ScintillaMacOSX.h1
-rw-r--r--src/Editor.cxx17
-rw-r--r--src/Editor.h1
-rw-r--r--src/LineMarker.cxx13
-rw-r--r--src/LineMarker.h7
-rw-r--r--src/PositionCache.cxx1
-rw-r--r--src/ScintillaBase.cxx5
-rw-r--r--src/ViewStyle.cxx3
-rw-r--r--src/XPM.cxx135
-rw-r--r--src/XPM.h49
-rw-r--r--win32/PlatWin.cxx74
-rw-r--r--win32/ScintillaWin.cxx1
23 files changed, 562 insertions, 56 deletions
diff --git a/cocoa/PlatCocoa.h b/cocoa/PlatCocoa.h
index 0653bc728..0e3c5f2e2 100644
--- a/cocoa/PlatCocoa.h
+++ b/cocoa/PlatCocoa.h
@@ -93,6 +93,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, Scintilla::Point from, Surface &surfaceSource);
void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore,
diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm
index 9397e9fbd..1e81fb6e1 100644
--- a/cocoa/PlatCocoa.mm
+++ b/cocoa/PlatCocoa.mm
@@ -639,6 +639,73 @@ void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, C
}
}
+static CGImageRef ImageFromRGBA(int width, int height, const unsigned char *pixelsImage, bool invert) {
+ CGImageRef image = 0;
+
+ // Create an RGB color space.
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ if (colorSpace) {
+ const int bitmapBytesPerRow = ((int) width * 4);
+ const int bitmapByteCount = (bitmapBytesPerRow * (int) height);
+
+ // Create a data provider.
+ CGDataProviderRef dataProvider = 0;
+ unsigned char *pixelsUpsideDown = 0;
+ if (invert) {
+ pixelsUpsideDown = new unsigned char[bitmapByteCount];
+
+ for (int y=0; y<height; y++) {
+ int yInverse = height - y - 1;
+ memcpy(pixelsUpsideDown + y * bitmapBytesPerRow,
+ pixelsImage + yInverse * bitmapBytesPerRow,
+ bitmapBytesPerRow);
+ }
+
+ dataProvider = CGDataProviderCreateWithData(
+ NULL, pixelsUpsideDown, bitmapByteCount, NULL);
+ } else {
+ dataProvider = CGDataProviderCreateWithData(
+ NULL, pixelsImage, bitmapByteCount, NULL);
+
+ }
+ if (dataProvider) {
+ // Create the CGImage.
+ image = CGImageCreate(width,
+ height,
+ 8,
+ 8 * 4,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaLast,
+ dataProvider,
+ NULL,
+ 0,
+ kCGRenderingIntentDefault);
+
+ CGDataProviderRelease(dataProvider);
+ }
+ delete []pixelsUpsideDown;
+
+ // The image retains the color space, so we can release it.
+ CGColorSpaceRelease(colorSpace);
+ }
+ return image;
+}
+
+void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+ CGImageRef image = ImageFromRGBA(width, height, pixelsImage, true);
+ if (image) {
+ //CGContextSaveGState(gc);
+ //CGRect dst = PRectangleToCGRect(rc);
+ //CGContextClipToRect(gc, dst);
+ CGRect drawRect = CGRectMake (0, 0, width, height);
+ CGContextDrawImage(gc, drawRect, image);
+ //CGContextRestoreGState (gc);
+
+ CGImageRelease(image);
+ }
+}
+
void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
// Drawing an ellipse with bezier curves. Code modified from:
// http://www.codeguru.com/gdi/ellipse.shtml
@@ -1410,6 +1477,7 @@ public:
int Find(const char* prefix);
void GetValue(int n, char* value, int len);
void RegisterImage(int type, const char* xpm_data);
+ void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
void ClearRegisteredImages();
void SetDoubleClickAction(CallBackAction action, void* data)
{
@@ -1721,6 +1789,26 @@ void ListBoxImpl::RegisterImage(int type, const char* xpm_data)
}
}
+void ListBoxImpl::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
+ NSImage *img = [NSImage alloc];
+ [img autorelease];
+ CGImageRef imageRef = ImageFromRGBA(width, height, pixelsImage, false);
+ NSSize sz = {width, height};
+ [img initWithCGImage:imageRef size:sz];
+ CGImageRelease(imageRef);
+ [img retain];
+ ImageMap::iterator it=images.find(type);
+ if (it == images.end())
+ {
+ images[type] = img;
+ }
+ else
+ {
+ [it->second release];
+ it->second = img;
+ }
+}
+
void ListBoxImpl::ClearRegisteredImages()
{
for (ImageMap::iterator it=images.begin();
diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h
index b24938d05..80a483b06 100644
--- a/cocoa/ScintillaCocoa.h
+++ b/cocoa/ScintillaCocoa.h
@@ -20,6 +20,7 @@
#include <time.h>
#include <vector>
+#include <map>
#include "ILexer.h"
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index a156897c7..5f36dbd9f 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -79,7 +79,7 @@
<h1>Scintilla Documentation</h1>
- <p>Last edited 18/June/2011 NH</p>
+ <p>Last edited 24/June/2011 NH</p>
<p>There is <a class="jump" href="Design.html">an overview of the internal design of
Scintilla</a>.<br />
@@ -3306,6 +3306,10 @@ struct Sci_TextToFind {
markerSymbols)</a><br />
<a class="message" href="#SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber,
const char *xpm)</a><br />
+ <a class="message" href="#SCI_RGBAIMAGESETWIDTH">SCI_RGBAIMAGESETWIDTH(int width)</a><br />
+ <a class="message" href="#SCI_RGBAIMAGESETHEIGHT">SCI_RGBAIMAGESETHEIGHT(int height)</a><br />
+ <a class="message" href="#SCI_MARKERDEFINERGBAIMAGE">SCI_MARKERDEFINERGBAIMAGE(int markerNumber,
+ const char *pixels)</a><br />
<a class="message" href="#SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)
</a><br />
<a class="message" href="#SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int
@@ -3487,12 +3491,23 @@ struct Sci_TextToFind {
<p><b id="SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber, const char
*xpm)</b><br />
Markers can be set to pixmaps with this message. The
- <a class="jump" href="#Images">XPM format</a> is used for the pixmap.
+ <a class="jump" href="#XPM">XPM format</a> is used for the pixmap.
Pixmaps use the <code>SC_MARK_PIXMAP</code> marker symbol. </p>
+ <p>
+ <b id="SCI_RGBAIMAGESETWIDTH">SCI_RGBAIMAGESETWIDTH(int width)</b><br />
+ <b id="SCI_RGBAIMAGESETHEIGHT">SCI_RGBAIMAGESETHEIGHT(int height)</b><br />
+ <b id="SCI_MARKERDEFINERGBAIMAGE">SCI_MARKERDEFINERGBAIMAGE(int markerNumber, const char *pixels)</b><br />
+ Markers can be set to translucent pixmaps with this message. The
+ <a class="jump" href="#RGBA">RGBA format</a> is used for the pixmap.
+ The width and height must previously been set with the <code>SCI_RGBAIMAGESETWIDTH</code> and
+ <code>SCI_RGBAIMAGESETHEIGHT</code> messages.
+ Pixmaps use the <code>SC_MARK_RGBAIMAGE</code> marker symbol. </p>
+
<p><b id="SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)</b><br />
Returns the symbol defined for a markerNumber with <code>SCI_MARKERDEFINE</code>
- or <code>SC_MARK_PIXMAP</code> if defined with <code>SCI_MARKERDEFINEPIXMAP</code>.</p>
+ or <code>SC_MARK_PIXMAP</code> if defined with <code>SCI_MARKERDEFINEPIXMAP</code>
+ or <code>SC_MARK_RGBAIMAGE</code> if defined with <code>SCI_MARKERDEFINERGBAIMAGE</code>.</p>
<p><b id="SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int <a class="jump"
href="#colour">colour</a>)</b><br />
@@ -3882,7 +3897,8 @@ struct Sci_TextToFind {
<a class="message" href="#SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool
dropRestOfWord)</a><br />
<a class="message" href="#SCI_AUTOCGETDROPRESTOFWORD">SCI_AUTOCGETDROPRESTOFWORD</a><br />
- <a class="message" href="#SCI_REGISTERIMAGE">SCI_REGISTERIMAGE</a><br />
+ <a class="message" href="#SCI_REGISTERIMAGE">SCI_REGISTERIMAGE(int type, const char *xpmData)</a><br />
+ <a class="message" href="#SCI_REGISTERRGBAIMAGE">SCI_REGISTERRGBAIMAGE(int type, const char *pixels)</a><br />
<a class="message" href="#SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</a><br />
<a class="message" href="#SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</a><br />
<a class="message" href="#SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</a><br />
@@ -3995,6 +4011,7 @@ struct Sci_TextToFind {
<p>
<b id="SCI_REGISTERIMAGE">SCI_REGISTERIMAGE(int type, const char *xpmData)</b><br />
+ <b id="SCI_REGISTERRGBAIMAGE">SCI_REGISTERRGBAIMAGE(int type, const char *pixels)</b><br />
<b id="SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</b><br />
<b id="SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</b><br />
<b id="SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</b><br />
@@ -4002,7 +4019,11 @@ struct Sci_TextToFind {
Autocompletion list items may display an image as well as text. Each image is first registered with an integer
type. Then this integer is included in the text of the list separated by a '?' from the text. For example,
"fclose?2 fopen" displays image 2 before the string "fclose" and no image before "fopen".
- The images are in <a class="jump" href="#Images">XPM format.</a>
+ The images are in either the <a class="jump" href="#XPM">XPM format</a> (<code>SCI_REGISTERIMAGE</code>) or
+ <a class="jump" href="#RGBA">RGBA format</a> (<code>SCI_REGISTERRGBAIMAGE</code>).
+ For <code>SCI_REGISTERRGBAIMAGE</code> the width and height must previously been set with
+ the <a class="message" href="#SCI_RGBAIMAGESETWIDTH"><code>SCI_RGBAIMAGESETWIDTH</code></a> and
+ <a class="message" href="#SCI_RGBAIMAGESETHEIGHT"><code>SCI_RGBAIMAGESETHEIGHT</code></a> messages.
The set of registered images can be cleared with <code>SCI_CLEARREGISTEREDIMAGES</code> and the '?' separator changed
with <code>SCI_AUTOCSETTYPESEPARATOR</code>.
</p>
@@ -6595,8 +6616,40 @@ for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
There is no other information in SCNotification.</p>
<h2 id="Images">Images</h2>
- <p>The XPM format is supported for images.
- This format is <a class="jump" href="http://en.wikipedia.org/wiki/X_PixMap">described here</a>.
+
+ <p>Two formats are supported for images used in margin markers and autocompletion lists, RGBA and XPM.</p>
+
+ <h3 id="RGBA">RGBA</h3>
+
+ <p>The RGBA format allows translucency with an <a class="jump" href="#alpha">alpha</a>
+ value for each pixel. It is simpler than
+ <code>XPM</code> and more capable.</p>
+
+ <p>The data is a sequence of 4 byte pixel values starting with the pixels for the top line, with the
+ leftmost pixel first, then continuing with the pixels for subsequent lines. There is no gap between
+ lines for alignment reasons.</p>
+
+ <p>Each pixel consists of, in order, a red byte, a green byte, a blue byte and an alpha byte.
+ The colour bytes are not premultiplied by the alpha value. That is, a fully red pixel that is
+ 25% opaque will be [FF, 00, 00, 3F]</p>
+
+ <p>Since the RGBA pixel data does not include any size information the
+ width and height must previously been set with the
+ <a class="message" href="#SCI_RGBAIMAGESETWIDTH"><code>SCI_RGBAIMAGESETWIDTH</code></a> and
+ <a class="message" href="#SCI_RGBAIMAGESETHEIGHT"><code>SCI_RGBAIMAGESETHEIGHT</code></a> messages.</p>
+
+ <p>GUI platforms often include functions for reading image file formats like PNG into memory
+ in the RGBA form or a similar form.
+ If there is no suitable platform support, the <a href="http://lodev.org/lodepng/">LodePNG and picoPNG</a> libraries are small libraries
+ for loading and decoding PNG files available under a BSD-style license.</p>
+
+ <p>RGBA format is supported on Windows, GTK+ and OS X Cocoa.
+ It is not supported on OS X Carbon.</p>
+
+ <h3 id="XPM">XPM</h3>
+
+ <p>The XPM format is
+ <a class="jump" href="http://en.wikipedia.org/wiki/X_PixMap">described here</a>.
Scintilla is only able to handle XPM pixmaps that use one character per pixel with no named colours.
There may be a completely transparent colour named "None".</p>
<p>There are two forms of data structure used for XPM images, the first "lines form" format is well suited
@@ -6609,6 +6662,8 @@ for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
to determine which format: if the bytes start with "/* XPM */" then it is treated as text form,
otherwise it is treated as lines form.</p>
+ <p>XPM format is supported on on all platforms.</p>
+
<h2 id="GTK">GTK+</h2>
<p>On GTK+, the following functions create a Scintilla widget, communicate with it and allow
resources to be released after all Scintilla widgets have been destroyed.</p>
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) {
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index c03841b22..0683b413d 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include <map>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
diff --git a/include/Platform.h b/include/Platform.h
index 1e9aeda44..8180b0a6d 100644
--- a/include/Platform.h
+++ b/include/Platform.h
@@ -339,6 +339,7 @@ public:
virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int flags)=0;
+ virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0;
virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
@@ -446,6 +447,7 @@ public:
virtual int Find(const char *prefix)=0;
virtual void GetValue(int n, char *value, int len)=0;
virtual void RegisterImage(int type, const char *xpm_data)=0;
+ virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0;
virtual void ClearRegisteredImages()=0;
virtual void SetDoubleClickAction(CallBackAction, void *)=0;
virtual void SetList(const char* list, char separator, char typesep)=0;
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 308281d1b..99100d11c 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -124,6 +124,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_MARK_LEFTRECT 27
#define SC_MARK_AVAILABLE 28
#define SC_MARK_UNDERLINE 29
+#define SC_MARK_RGBAIMAGE 30
#define SC_MARK_CHARACTER 10000
#define SC_MARKNUM_FOLDEREND 25
#define SC_MARKNUM_FOLDEROPENMID 26
@@ -811,6 +812,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_MOVESELECTEDLINESDOWN 2621
#define SCI_SETIDENTIFIER 2622
#define SCI_GETIDENTIFIER 2623
+#define SCI_RGBAIMAGESETWIDTH 2624
+#define SCI_RGBAIMAGESETHEIGHT 2625
+#define SCI_MARKERDEFINERGBAIMAGE 2626
+#define SCI_REGISTERRGBAIMAGE 2627
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_SETLEXER 4001
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index d9272a1dc..28273f012 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -268,6 +268,7 @@ val SC_MARK_FULLRECT=26
val SC_MARK_LEFTRECT=27
val SC_MARK_AVAILABLE=28
val SC_MARK_UNDERLINE=29
+val SC_MARK_RGBAIMAGE=30
val SC_MARK_CHARACTER=10000
@@ -2153,6 +2154,20 @@ set void SetIdentifier=2622(int identifier,)
# Get the identifier.
get int GetIdentifier=2623(,)
+# Set the width for future RGBA image data.
+set void RGBAImageSetWidth=2624(int width,)
+
+# Set the height for future RGBA image data.
+set void RGBAImageSetHeight=2625(int height,)
+
+# Define a marker from RGBA data.
+# It has the width and height from RGBAImageSetWidth/Height
+fun void MarkerDefineRGBAImage=2626(int markerNumber, string pixels)
+
+# Register an RGBA image for use in autocompletion lists.
+# It has the width and height from RGBAImageSetWidth/Height
+fun void RegisterRGBAImage=2627(int type, string pixels)
+
# Start notifying the container of all key presses and commands.
fun void StartRecord=3001(,)
diff --git a/macosx/PlatMacOSX.cxx b/macosx/PlatMacOSX.cxx
index 56c9d32c2..381be992d 100644
--- a/macosx/PlatMacOSX.cxx
+++ b/macosx/PlatMacOSX.cxx
@@ -12,6 +12,9 @@
#include <sys/time.h>
+#include <vector>
+#include <map>
+
#include <Carbon/Carbon.h>
#include "QuartzTextLayout.h"
#include "TCarbonEvent.h"
@@ -482,6 +485,10 @@ void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, C
}
}
+void SurfaceImpl::DrawRGBAImage(PRectangle /* rc */, int /* width */, int /* height */, const unsigned char * /* pixelsImage*/) {
+ // Not supported for Carbon
+}
+
void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
// Drawing an ellipse with bezier curves. Code modified from:
// http://www.codeguru.com/gdi/ellipse.shtml
@@ -1128,6 +1135,7 @@ public:
int Find(const char *prefix);
void GetValue(int n, char *value, int len);
void RegisterImage(int type, const char *xpm_data);
+ void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
void ClearRegisteredImages();
void SetDoubleClickAction(CallBackAction action, void *data) {
doubleClickAction = action;
@@ -1635,6 +1643,10 @@ void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
xset.Add(type, xpm_data);
}
+void ListBoxImpl::RegisterRGBAImage(int /* type */, int /* width */, int /* height */, const unsigned char * /*pixelsImage */) {
+ // Not supported for Carbon
+}
+
void ListBoxImpl::ClearRegisteredImages() {
xset.Clear();
}
diff --git a/macosx/PlatMacOSX.h b/macosx/PlatMacOSX.h
index 58e1bc6d7..492c0d18a 100644
--- a/macosx/PlatMacOSX.h
+++ b/macosx/PlatMacOSX.h
@@ -70,6 +70,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, Scintilla::Point from, Surface &surfaceSource);
diff --git a/macosx/ScintillaMacOSX.h b/macosx/ScintillaMacOSX.h
index df3e1c8e1..fe871119b 100644
--- a/macosx/ScintillaMacOSX.h
+++ b/macosx/ScintillaMacOSX.h
@@ -17,6 +17,7 @@
#include <time.h>
#include <vector>
+#include <map>
#include "Platform.h"
#include "Scintilla.h"
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 26c260101..ff9872e58 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include <map>
#include <algorithm>
#include <memory>
@@ -8020,6 +8021,22 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
RedrawSelMargin();
break;
+ case SCI_RGBAIMAGESETWIDTH:
+ sizeRGBAImage.x = wParam;
+ break;
+
+ case SCI_RGBAIMAGESETHEIGHT:
+ sizeRGBAImage.y = wParam;
+ break;
+
+ case SCI_MARKERDEFINERGBAIMAGE:
+ if (wParam <= MARKER_MAX) {
+ vs.markers[wParam].SetRGBAImage(sizeRGBAImage, reinterpret_cast<unsigned char *>(lParam));
+ };
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
case SCI_SETMARGINTYPEN:
if (ValidMargin(wParam)) {
vs.ms[wParam].style = lParam;
diff --git a/src/Editor.h b/src/Editor.h
index 74f0eff86..f1a500b74 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -131,6 +131,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
* When a style attribute is changed, this cache is flushed. */
bool stylesValid;
ViewStyle vs;
+ Point sizeRGBAImage;
Palette palette;
int printMagnification;
diff --git a/src/LineMarker.cxx b/src/LineMarker.cxx
index 747c5ff12..1415c609b 100644
--- a/src/LineMarker.cxx
+++ b/src/LineMarker.cxx
@@ -7,6 +7,9 @@
#include <string.h>
+#include <vector>
+#include <map>
+
#include "Platform.h"
#include "Scintilla.h"
@@ -38,6 +41,12 @@ void LineMarker::SetXPM(const char *const *linesForm) {
markType = SC_MARK_PIXMAP;
}
+void LineMarker::SetRGBAImage(Point sizeRGBAImage, const unsigned char *pixelsRGBAImage) {
+ delete image;
+ image = new RGBAImage(sizeRGBAImage.x, sizeRGBAImage.y, pixelsRGBAImage);
+ markType = SC_MARK_RGBAIMAGE;
+}
+
static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
PRectangle rc;
rc.left = centreX - armSize;
@@ -96,6 +105,10 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
pxpm->Draw(surface, rcWhole);
return;
}
+ if ((markType == SC_MARK_RGBAIMAGE) && (image)) {
+ surface->DrawRGBAImage(rcWhole, image->GetWidth(), image->GetHeight(), image->Pixels());
+ return;
+ }
// Restrict most shapes a bit
PRectangle rc = rcWhole;
rc.top++;
diff --git a/src/LineMarker.h b/src/LineMarker.h
index 39c38fa41..722c44b62 100644
--- a/src/LineMarker.h
+++ b/src/LineMarker.h
@@ -25,6 +25,7 @@ public:
ColourPair backSelected;
int alpha;
XPM *pxpm;
+ RGBAImage *image;
LineMarker() {
markType = SC_MARK_CIRCLE;
fore = ColourDesired(0,0,0);
@@ -32,6 +33,7 @@ public:
backSelected = ColourDesired(0xff,0x00,0x00);
alpha = SC_ALPHA_NOALPHA;
pxpm = NULL;
+ image = NULL;
}
LineMarker(const LineMarker &) {
// Defined to avoid pxpm being blindly copied, not as real copy constructor
@@ -41,9 +43,11 @@ public:
backSelected = ColourDesired(0xff,0x00,0x00);
alpha = SC_ALPHA_NOALPHA;
pxpm = NULL;
+ image = NULL;
}
~LineMarker() {
delete pxpm;
+ delete image;
}
LineMarker &operator=(const LineMarker &) {
// Defined to avoid pxpm being blindly copied, not as real assignment operator
@@ -54,11 +58,14 @@ public:
alpha = SC_ALPHA_NOALPHA;
delete pxpm;
pxpm = NULL;
+ delete image;
+ image = NULL;
return *this;
}
void RefreshColourPalette(Palette &pal, bool want);
void SetXPM(const char *textForm);
void SetXPM(const char *const *linesForm);
+ void SetRGBAImage(Point sizeRGBAImage, const unsigned char *pixelsRGBAImage);
void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold);
};
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index e59c12630..5f3ce81b3 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -12,6 +12,7 @@
#include <string>
#include <vector>
+#include <map>
#include "Platform.h"
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index 3de4a4583..380ed2424 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include <map>
#include "Platform.h"
@@ -760,6 +761,10 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
break;
+ case SCI_REGISTERRGBAIMAGE:
+ ac.lb->RegisterRGBAImage(wParam, sizeRGBAImage.x, sizeRGBAImage.y, reinterpret_cast<unsigned char *>(lParam));
+ break;
+
case SCI_CLEARREGISTEREDIMAGES:
ac.lb->ClearRegisteredImages();
break;
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 03a2fb42f..9ba69b1ce 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -7,6 +7,9 @@
#include <string.h>
+#include <vector>
+#include <map>
+
#include "Platform.h"
#include "Scintilla.h"
diff --git a/src/XPM.cxx b/src/XPM.cxx
index d1389efa0..6c615dd94 100644
--- a/src/XPM.cxx
+++ b/src/XPM.cxx
@@ -8,6 +8,13 @@
#include <string.h>
#include <stdlib.h>
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#include <vector>
+#include <map>
+
#include "Platform.h"
#include "XPM.h"
@@ -38,6 +45,10 @@ static size_t MeasureLength(const char *s) {
return i;
}
+ColourDesired XPM::ColourDesiredFromCode(int ch) const {
+ return colourCodeTable[ch]->desired;
+}
+
ColourAllocated XPM::ColourFromCode(int ch) const {
return colourCodeTable[ch]->allocated;
#ifdef SLOW
@@ -200,6 +211,21 @@ void XPM::Draw(Surface *surface, PRectangle &rc) {
}
}
+void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const {
+ if (!data || !codes || !colours || !lines || (x<0) || (x >= width) || (y<0) || (y >= height)) {
+ colour = 0;
+ transparent = true;
+ return;
+ }
+ int code = lines[y+nColours+1][x];
+ transparent = code == codeTransparent;
+ if (transparent) {
+ colour = 0;
+ } else {
+ colour = ColourDesiredFromCode(code).AsLong();
+ }
+}
+
const char **XPM::LinesFormFromTextForm(const char *textForm) {
// Build the lines form out of the text form
const char **linesForm = 0;
@@ -261,14 +287,14 @@ void XPMSet::Clear() {
width = -1;
}
-void XPMSet::Add(int id, const char *textForm) {
+void XPMSet::Add(int ident, const char *textForm) {
// Invalidate cached dimensions
height = -1;
width = -1;
// Replace if this id already present
for (int i = 0; i < len; i++) {
- if (set[i]->GetId() == id) {
+ if (set[i]->GetId() == ident) {
set[i]->Init(textForm);
set[i]->CopyDesiredColours();
return;
@@ -278,7 +304,7 @@ void XPMSet::Add(int id, const char *textForm) {
// Not present, so add to end
XPM *pxpm = new XPM(textForm);
if (pxpm) {
- pxpm->SetId(id);
+ pxpm->SetId(ident);
pxpm->CopyDesiredColours();
if (len == maximum) {
maximum += 64;
@@ -294,9 +320,9 @@ void XPMSet::Add(int id, const char *textForm) {
}
}
-XPM *XPMSet::Get(int id) {
+XPM *XPMSet::Get(int ident) {
for (int i = 0; i < len; i++) {
- if (set[i]->GetId() == id) {
+ if (set[i]->GetId() == ident) {
return set[i];
}
}
@@ -324,3 +350,102 @@ int XPMSet::GetWidth() {
}
return (width > 0) ? width : 0;
}
+
+RGBAImage::RGBAImage(int width_, int height_, const unsigned char *pixels_) :
+ height(height_), width(width_) {
+ pixelBytes.assign(pixels_, pixels_ + CountBytes());
+}
+
+RGBAImage::RGBAImage(const XPM &xpm) {
+ height = xpm.GetHeight();
+ width = xpm.GetWidth();
+ pixelBytes.resize(CountBytes());
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ ColourDesired colour;
+ bool transparent = false;
+ xpm.PixelAt(x, y, colour, transparent);
+ unsigned char *pixel = &pixelBytes[0] + (y*width+x) * 4;
+ // RGBA
+ pixel[0] = colour.GetRed();
+ pixel[1] = colour.GetGreen();
+ pixel[2] = colour.GetBlue();
+ pixel[3] = transparent ? 0 : 255;
+ }
+ }
+}
+
+RGBAImage::~RGBAImage() {
+}
+
+int RGBAImage::CountBytes() const {
+ return width * height * 4;
+}
+
+const unsigned char *RGBAImage::Pixels() const {
+ return &pixelBytes[0];
+}
+
+RGBAImageSet::RGBAImageSet() : height(-1), width(-1){
+}
+
+RGBAImageSet::~RGBAImageSet() {
+ Clear();
+}
+
+/// Remove all images.
+void RGBAImageSet::Clear() {
+ for (ImageMap::iterator it=images.begin(); it != images.end(); ++it) {
+ delete it->second;
+ it->second = 0;
+ }
+ images.clear();
+ height = -1;
+ width = -1;
+}
+
+/// Add an image.
+void RGBAImageSet::Add(int ident, RGBAImage *image) {
+ ImageMap::iterator it=images.find(ident);
+ if (it == images.end()) {
+ images[ident] = image;
+ } else {
+ delete it->second;
+ it->second = image;
+ }
+ height = -1;
+ width = -1;
+}
+
+/// Get image by id.
+RGBAImage *RGBAImageSet::Get(int ident) {
+ ImageMap::iterator it = images.find(ident);
+ if (it != images.end()) {
+ return it->second;
+ }
+ return NULL;
+}
+
+/// Give the largest height of the set.
+int RGBAImageSet::GetHeight() const {
+ if (height < 0) {
+ for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
+ if (height < it->second->GetHeight()) {
+ height = it->second->GetHeight();
+ }
+ }
+ }
+ return (height > 0) ? height : 0;
+}
+
+/// Give the largest width of the set.
+int RGBAImageSet::GetWidth() const {
+ if (width < 0) {
+ for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
+ if (width < it->second->GetWidth()) {
+ width = it->second->GetWidth();
+ }
+ }
+ }
+ return (width > 0) ? width : 0;
+}
diff --git a/src/XPM.h b/src/XPM.h
index cb05aae3e..8b72ef08d 100644
--- a/src/XPM.h
+++ b/src/XPM.h
@@ -24,6 +24,7 @@ class XPM {
char codeTransparent;
char *codes;
ColourPair *colours;
+ ColourDesired ColourDesiredFromCode(int ch) const;
ColourAllocated ColourFromCode(int ch) const;
void FillRun(Surface *surface, int code, int startX, int y, int x);
char **lines;
@@ -46,6 +47,7 @@ public:
int GetId() const { return pid; }
int GetHeight() const { return height; }
int GetWidth() const { return width; }
+ void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const;
static const char **LinesFormFromTextForm(const char *textForm);
};
@@ -64,15 +66,58 @@ public:
/// Remove all XPMs.
void Clear();
/// Add a XPM.
- void Add(int id, const char *textForm);
+ void Add(int ident, const char *textForm);
/// Get XPM by id.
- XPM *Get(int id);
+ XPM *Get(int ident);
/// Give the largest height of the set.
int GetHeight();
/// Give the largest width of the set.
int GetWidth();
};
+/**
+ * An translucent image stoed as a sequence of RGBA bytes.
+ */
+class RGBAImage {
+ // Private so RGBAImage objects can not be copied
+ RGBAImage(const RGBAImage &);
+ RGBAImage &operator=(const RGBAImage &);
+ int height;
+ int width;
+ std::vector<unsigned char> pixelBytes;
+public:
+ RGBAImage(int width_, int height_, const unsigned char *pixels_);
+ RGBAImage(const XPM &xpm);
+ virtual ~RGBAImage();
+ int GetHeight() const { return height; }
+ int GetWidth() const { return width; }
+ int CountBytes() const;
+ const unsigned char *Pixels() const;
+};
+
+/**
+ * A collection of RGBAImage pixmaps indexed by integer id.
+ */
+class RGBAImageSet {
+ typedef std::map<int, RGBAImage*> ImageMap;
+ ImageMap images;
+ mutable int height; ///< Memorize largest height of the set.
+ mutable int width; ///< Memorize largest width of the set.
+public:
+ RGBAImageSet();
+ ~RGBAImageSet();
+ /// Remove all images.
+ void Clear();
+ /// Add an image.
+ void Add(int ident, RGBAImage *image);
+ /// Get image by id.
+ RGBAImage *Get(int ident);
+ /// Give the largest height of the set.
+ int GetHeight() const;
+ /// Give the largest width of the set.
+ int GetWidth() const;
+};
+
#ifdef SCI_NAMESPACE
}
#endif
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 7ef0e7b2c..35d66030f 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -13,6 +13,13 @@
#include <time.h>
#include <limits.h>
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#include <vector>
+#include <map>
+
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#include <windows.h>
@@ -404,6 +411,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);
@@ -696,6 +704,45 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated
}
}
+void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+ if (AlphaBlendFn && rc.Width() > 0) {
+ HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
+ 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;
+
+ BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
+ unsigned char *image = 0;
+ HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih,
+ DIB_RGB_COLORS, reinterpret_cast<void **>(&image), NULL, 0);
+ HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem);
+
+ for (int y=height-1; y>=0; y--) {
+ for (int x=0; x<width; x++) {
+ unsigned char *pixel = image + (y*width+x) * 4;
+ unsigned char alpha = pixelsImage[3];
+ // Input is RGBA, output is BGRA with premultiplied alpha
+ pixel[2] = (*pixelsImage++) * alpha / 255;
+ pixel[1] = (*pixelsImage++) * alpha / 255;
+ pixel[0] = (*pixelsImage++) * alpha / 255;
+ pixel[3] = *pixelsImage++;
+ }
+ }
+
+ BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, rc.Width(), rc.Height(), hMemDC, 0, 0, width, height, merge);
+
+ SelectBitmap(hMemDC, hbmOld);
+ ::DeleteObject(hbmMem);
+ ::DeleteDC(hMemDC);
+
+ }
+}
+
void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
@@ -1318,7 +1365,7 @@ ListBox::~ListBox() {
class ListBoxX : public ListBox {
int lineHeight;
FontID fontCopy;
- XPMSet xset;
+ RGBAImageSet images;
LineToItem lti;
HWND lb;
bool unicodeMode;
@@ -1385,6 +1432,7 @@ public:
virtual int Find(const char *prefix);
virtual void GetValue(int n, char *value, int len);
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;
@@ -1491,7 +1539,7 @@ PRectangle ListBoxX::GetDesiredRect() {
}
int ListBoxX::TextOffset() const {
- int pixWidth = const_cast<XPMSet*>(&xset)->GetWidth();
+ int pixWidth = images.GetWidth();
return pixWidth == 0 ? ItemInset.x : ItemInset.x + pixWidth + (ImageInset.x * 2);
}
@@ -1550,11 +1598,16 @@ void ListBoxX::GetValue(int n, char *value, int len) {
}
void ListBoxX::RegisterImage(int type, const char *xpm_data) {
- xset.Add(type, xpm_data);
+ XPM xpmImage(xpm_data);
+ images.Add(type, new RGBAImage(xpmImage));
+}
+
+void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
+ images.Add(type, new RGBAImage(width, height, pixelsImage));
}
void ListBoxX::ClearRegisteredImages() {
- xset.Clear();
+ images.Clear();
}
void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
@@ -1594,17 +1647,16 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
}
// Draw the image, if any
- XPM *pxpm = xset.Get(pixId);
- if (pxpm) {
+ RGBAImage *pimage = images.Get(pixId);
+ if (pimage) {
Surface *surfaceItem = Surface::Allocate();
if (surfaceItem) {
surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
- //surfaceItem->SetUnicodeMode(unicodeMode);
- //surfaceItem->SetDBCSMode(codePage);
int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
PRectangle rcImage(left, pDrawItem->rcItem.top,
- left + xset.GetWidth(), pDrawItem->rcItem.bottom);
- pxpm->Draw(surfaceItem, rcImage);
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
delete surfaceItem;
::SetTextAlign(pDrawItem->hDC, TA_TOP);
}
@@ -1678,7 +1730,7 @@ void ListBoxX::AdjustWindowRect(PRectangle *rc) const {
int ListBoxX::ItemHeight() const {
int itemHeight = lineHeight + (TextInset.y * 2);
- int pixHeight = const_cast<XPMSet*>(&xset)->GetHeight() + (ImageInset.y * 2);
+ int pixHeight = images.GetHeight() + (ImageInset.y * 2);
if (itemHeight < pixHeight) {
itemHeight = pixHeight;
}
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 8092edcd8..f86d649c7 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -15,6 +15,7 @@
#include <string>
#include <vector>
+#include <map>
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500