diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-01-26 22:20:15 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-01-26 22:20:15 +0000 |
| commit | 87e29cef828548c397692473683eebd9613b661c (patch) | |
| tree | 367282e8eb68b51f0de993710192e6485a90dafb /src | |
| parent | 034a4f3f2a15302b1a1ea3df6033cbffdc7b7418 (diff) | |
Moving image drawing code into the driver system
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11060 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Gl_Device_Plugin.cxx | 1 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx (renamed from src/fl_draw_image_win32.cxx) | 0 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx | 2 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_image.cxx | 24 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx (renamed from src/fl_draw_image_mac.cxx) | 0 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 605 | ||||
| -rw-r--r-- | src/fl_draw.cxx | 11 | ||||
| -rw-r--r-- | src/fl_draw_image.cxx | 585 |
8 files changed, 636 insertions, 592 deletions
diff --git a/src/Fl_Gl_Device_Plugin.cxx b/src/Fl_Gl_Device_Plugin.cxx index 9845c9f4f..ded54219b 100644 --- a/src/Fl_Gl_Device_Plugin.cxx +++ b/src/Fl_Gl_Device_Plugin.cxx @@ -57,6 +57,7 @@ const char *Fl_OpenGL_Display_Device::class_id = "Fl_OpenGL_Display_Device"; #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.cxx" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.cxx" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx" +#include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_image.cxx" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.cxx" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx" diff --git a/src/fl_draw_image_win32.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index 465e73dca..465e73dca 100644 --- a/src/fl_draw_image_win32.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx diff --git a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx index afba28c73..0fe187d91 100644 --- a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx +++ b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx @@ -73,7 +73,7 @@ int Fl_OpenGL_Graphics_Driver::descent() { } int Fl_OpenGL_Graphics_Driver::height() { - return (int)(size_*0.8); + return (int)(size_); } void Fl_OpenGL_Graphics_Driver::text_extents(const char *str, int n, int& dx, int& dy, int& w, int& h) diff --git a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_image.cxx b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_image.cxx new file mode 100644 index 000000000..4cb96e6f5 --- /dev/null +++ b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_image.cxx @@ -0,0 +1,24 @@ +// +// "$Id$" +// +// Image drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// FIXME add code to draw various imge types in OpenGL + + +// +// End of "$Id$". +// diff --git a/src/fl_draw_image_mac.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index 87fcbc068..87fcbc068 100644 --- a/src/fl_draw_image_mac.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx new file mode 100644 index 000000000..5ec63fd06 --- /dev/null +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -0,0 +1,605 @@ +// +// "$Id$" +// +// Image drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// I hope a simple and portable method of drawing color and monochrome +// images. To keep this simple, only a single storage type is +// supported: 8 bit unsigned data, byte order RGB, and pixels are +// stored packed into rows with the origin at the top-left. It is +// possible to alter the size of pixels with the "delta" argument, to +// add alpha or other information per pixel. It is also possible to +// change the origin and direction of the image data by messing with +// the "delta" and "linedelta", making them negative, though this may +// defeat some of the shortcuts in translating the image for X. + + +// A list of assumptions made about the X display: + +// bits_per_pixel must be one of 8, 16, 24, 32. + +// scanline_pad must be a power of 2 and greater or equal to 8. + +// PsuedoColor visuals must have 8 bits_per_pixel (although the depth +// may be less than 8). This is the only limitation that affects any +// modern X displays, you can't use 12 or 16 bit colormaps. + +// The mask bits in TrueColor visuals for each color are +// contiguous and have at least one bit of each color. This +// is not checked for. + +// For 24 and 32 bit visuals there must be at least 8 bits of each color. + +//////////////////////////////////////////////////////////////// + +# include <FL/Fl.H> +# include <FL/fl_draw.H> +# include <FL/x.H> +# include "Fl_XColor.H" +# include "flstring.h" + +static XImage xi; // template used to pass info to X +static int bytes_per_pixel; +static int scanline_add; +static int scanline_mask; + +static void (*converter)(const uchar *from, uchar *to, int w, int delta); +static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta); + +static int dir; // direction-alternator +static int ri,gi,bi; // saved error-diffusion value + +# if USE_COLORMAP +//////////////////////////////////////////////////////////////// +// 8-bit converter with error diffusion + +static void color8_converter(const uchar *from, uchar *to, int w, int delta) { + int r=ri, g=gi, b=bi; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; + g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; + b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; + Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); + Fl_XColor& xmap = fl_xmap[0][i]; + if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} + r -= xmap.r; + g -= xmap.g; + b -= xmap.b; + *to = uchar(xmap.pixel); + } + ri = r; gi = g; bi = b; +} + +static void mono8_converter(const uchar *from, uchar *to, int w, int delta) { + int r=ri, g=gi, b=bi; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + to = to+(w-1); + d = -delta; + td = -1; + } else { + dir = 1; + d = delta; + td = 1; + } + for (; w--; from += d, to += td) { + r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; + g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255; + b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255; + Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); + Fl_XColor& xmap = fl_xmap[0][i]; + if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} + r -= xmap.r; + g -= xmap.g; + b -= xmap.b; + *to = uchar(xmap.pixel); + } + ri = r; gi = g; bi = b; +} + +# endif + +//////////////////////////////////////////////////////////////// +// 16 bit TrueColor converters with error diffusion +// Cray computers have no 16-bit type, so we use character pointers +// (which may be slow) + +# ifdef U16 +# define OUTTYPE U16 +# define OUTSIZE 1 +# define OUTASSIGN(v) *t = v +# else +# define OUTTYPE uchar +# define OUTSIZE 2 +# define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt) +# endif + +static void color16_converter(const uchar *from, uchar *to, int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri, g=gi, b=bi; + for (; w--; from += d, t += td) { + r = (r&~fl_redmask) +from[0]; if (r>255) r = 255; + g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255; + b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255; + OUTASSIGN(( + ((r&fl_redmask)<<fl_redshift)+ + ((g&fl_greenmask)<<fl_greenshift)+ + ((b&fl_bluemask)<<fl_blueshift) + ) >> fl_extrashift); + } + ri = r; gi = g; bi = b; +} + +static void mono16_converter(const uchar *from,uchar *to,int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + uchar mask = fl_redmask & fl_greenmask & fl_bluemask; + int r=ri; + for (; w--; from += d, t += td) { + r = (r&~mask) + *from; if (r > 255) r = 255; + uchar m = r&mask; + OUTASSIGN(( + (m<<fl_redshift)+ + (m<<fl_greenshift)+ + (m<<fl_blueshift) + ) >> fl_extrashift); + } + ri = r; +} + +// special-case the 5r6g5b layout used by XFree86: + +static void c565_converter(const uchar *from, uchar *to, int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri, g=gi, b=bi; + for (; w--; from += d, t += td) { + r = (r&7)+from[0]; if (r>255) r = 255; + g = (g&3)+from[1]; if (g>255) g = 255; + b = (b&7)+from[2]; if (b>255) b = 255; + OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3)); + } + ri = r; gi = g; bi = b; +} + +static void m565_converter(const uchar *from,uchar *to,int w, int delta) { + OUTTYPE *t = (OUTTYPE *)to; + int d, td; + if (dir) { + dir = 0; + from = from+(w-1)*delta; + t = t+(w-1)*OUTSIZE; + d = -delta; + td = -OUTSIZE; + } else { + dir = 1; + d = delta; + td = OUTSIZE; + } + int r=ri; + for (; w--; from += d, t += td) { + r = (r&7) + *from; if (r > 255) r = 255; + OUTASSIGN((r>>3) * 0x841); + } + ri = r; +} + +//////////////////////////////////////////////////////////////// +// 24bit TrueColor converters: + +static void rgb_converter(const uchar *from, uchar *to, int w, int delta) { + int d = delta-3; + for (; w--; from += d) { + *to++ = *from++; + *to++ = *from++; + *to++ = *from++; + } +} + +static void bgr_converter(const uchar *from, uchar *to, int w, int delta) { + for (; w--; from += delta) { + uchar r = from[0]; + uchar g = from[1]; + *to++ = from[2]; + *to++ = g; + *to++ = r; + } +} + +static void rrr_converter(const uchar *from, uchar *to, int w, int delta) { + for (; w--; from += delta) { + *to++ = *from; + *to++ = *from; + *to++ = *from; + } +} + +//////////////////////////////////////////////////////////////// +// 32bit TrueColor converters on a 32 or 64-bit machine: + +# ifdef U64 +# define STORETYPE U64 +# if WORDS_BIGENDIAN +# define INNARDS32(f) \ + U64 *t = (U64*)to; \ + int w1 = w/2; \ + for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} \ + if (w&1) *t++ = (U64)(f)<<32; +# else +# define INNARDS32(f) \ + U64 *t = (U64*)to; \ + int w1 = w/2; \ + for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = ((U64)(f)<<32)|i;} \ + if (w&1) *t++ = (U64)(f); +# endif +# else +# define STORETYPE U32 +# define INNARDS32(f) \ + U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f +# endif + +static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8)); +} + +static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16)); +} + +static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2])); +} + +static void argb_premul_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((unsigned(from[3]) << 24) + + (((from[0] * from[3]) / 255) << 16) + + (((from[1] * from[3]) / 255) << 8) + + ((from[2] * from[3]) / 255)); +} + +static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24)); +} + +static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32(unsigned(*from) * 0x1010100U); +} + +static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32(*from * 0x10101U); +} + +static void +color32_converter(const uchar *from, uchar *to, int w, int delta) { + INNARDS32( + (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift)); +} + +static void +mono32_converter(const uchar *from,uchar *to,int w, int delta) { + INNARDS32( + (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift)); +} + +//////////////////////////////////////////////////////////////// + +static void figure_out_visual() { + + fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx + fl_xpixel(FL_WHITE); // also make sure white is allocated + + static XPixmapFormatValues *pfvlist; + static int FL_NUM_pfv; + if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv); + XPixmapFormatValues *pfv; + for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++) + if (pfv->depth == fl_visual->depth) break; + xi.format = ZPixmap; + xi.byte_order = ImageByteOrder(fl_display); +//i.bitmap_unit = 8; +//i.bitmap_bit_order = MSBFirst; +//i.bitmap_pad = 8; + xi.depth = fl_visual->depth; + xi.bits_per_pixel = pfv->bits_per_pixel; + + if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error + else bytes_per_pixel = xi.bits_per_pixel/8; + + unsigned int n = pfv->scanline_pad/8; + if (pfv->scanline_pad & 7 || (n&(n-1))) + Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad); + if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE); + scanline_add = n-1; + scanline_mask = -n; + +# if USE_COLORMAP + if (bytes_per_pixel == 1) { + converter = color8_converter; + mono_converter = mono8_converter; + return; + } + if (!fl_visual->red_mask) + Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel); +# endif + + // otherwise it is a TrueColor visual: + + int rs = fl_redshift; + int gs = fl_greenshift; + int bs = fl_blueshift; + + switch (bytes_per_pixel) { + + case 2: + // All 16-bit TrueColor visuals are supported on any machine with + // 24 or more bits per integer. +# ifdef U16 + xi.byte_order = WORDS_BIGENDIAN; +# else + xi.byte_order = 1; +# endif + if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) { + converter = c565_converter; + mono_converter = m565_converter; + } else { + converter = color16_converter; + mono_converter = mono16_converter; + } + break; + + case 3: + if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;} + if (rs == 0 && gs == 8 && bs == 16) { + converter = rgb_converter; + mono_converter = rrr_converter; + } else if (rs == 16 && gs == 8 && bs == 0) { + converter = bgr_converter; + mono_converter = rrr_converter; + } else { + Fl::fatal("Can't do arbitrary 24bit color"); + } + break; + + case 4: + if ((xi.byte_order!=0) != WORDS_BIGENDIAN) + {rs = 24-rs; gs = 24-gs; bs = 24-bs;} + if (rs == 0 && gs == 8 && bs == 16) { + converter = xbgr_converter; + mono_converter = xrrr_converter; + } else if (rs == 24 && gs == 16 && bs == 8) { + converter = rgbx_converter; + mono_converter = rrrx_converter; + } else if (rs == 8 && gs == 16 && bs == 24) { + converter = bgrx_converter; + mono_converter = rrrx_converter; + } else if (rs == 16 && gs == 8 && bs == 0) { + converter = xrgb_converter; + mono_converter = xrrr_converter; + } else { + xi.byte_order = WORDS_BIGENDIAN; + converter = color32_converter; + mono_converter = mono32_converter; + } + break; + + default: + Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel); + } + +} + +# define MAXBUFFER 0x40000 // 256k + +static void innards(const uchar *buf, int X, int Y, int W, int H, + int delta, int linedelta, int mono, + Fl_Draw_Image_Cb cb, void* userdata, + const bool alpha) +{ + if (!linedelta) linedelta = W*delta; + + int dx, dy, w, h; + fl_clip_box(X,Y,W,H,dx,dy,w,h); + if (w<=0 || h<=0) return; + dx -= X; + dy -= Y; + + if (!bytes_per_pixel) figure_out_visual(); + const unsigned oldbpp = bytes_per_pixel; + const GC oldgc = fl_gc; + static GC gc32 = None; + xi.width = w; + xi.height = h; + + void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter; + if (mono) conv = mono_converter; + if (alpha) { + // This flag states the destination format is ARGB32 (big-endian), pre-multiplied. + bytes_per_pixel = 4; + conv = argb_premul_converter; + xi.depth = 32; + xi.bits_per_pixel = 32; + + // Do we need a new GC? + if (fl_visual->depth != 32) { + if (gc32 == None) + gc32 = XCreateGC(fl_display, fl_window, 0, NULL); + fl_gc = gc32; + } + } + + // See if the data is already in the right format. Unfortunately + // some 32-bit x servers (XFree86) care about the unknown 8 bits + // and they must be zero. I can't confirm this for user-supplied + // data, so the 32-bit shortcut is disabled... + // This can set bytes_per_line negative if image is bottom-to-top + // I tested it on Linux, but it may fail on other Xlib implementations: + if (buf && ( +# if 0 // set this to 1 to allow 32-bit shortcut + delta == 4 && +# if WORDS_BIGENDIAN + conv == rgbx_converter +# else + conv == xbgr_converter +# endif + || +# endif + conv == rgb_converter && delta==3 + ) && !(linedelta&scanline_add)) { + xi.data = (char *)(buf+delta*dx+linedelta*dy); + xi.bytes_per_line = linedelta; + + } else { + int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE); + int blocking = h; + static STORETYPE *buffer; // our storage, always word aligned + static long buffer_size; + {int size = linesize*h; + if (size > MAXBUFFER) { + size = MAXBUFFER; + blocking = MAXBUFFER/linesize; + } + if (size > buffer_size) { + delete[] buffer; + buffer_size = size; + buffer = new STORETYPE[size]; + }} + xi.data = (char *)buffer; + xi.bytes_per_line = linesize*sizeof(STORETYPE); + if (buf) { + buf += delta*dx+linedelta*dy; + for (int j=0; j<h; ) { + STORETYPE *to = buffer; + int k; + for (k = 0; j<h && k<blocking; k++, j++) { + conv(buf, (uchar*)to, w, delta); + buf += linedelta; + to += linesize; + } + XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); + } + } else { + STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)]; + for (int j=0; j<h; ) { + STORETYPE *to = buffer; + int k; + for (k = 0; j<h && k<blocking; k++, j++) { + cb(userdata, dx, dy+j, w, (uchar*)linebuf); + conv((uchar*)linebuf, (uchar*)to, w, delta); + to += linesize; + } + XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); + } + + delete[] linebuf; + } + } + + if (alpha) { + bytes_per_pixel = oldbpp; + xi.depth = fl_visual->depth; + xi.bits_per_pixel = oldbpp * 8; + + if (fl_visual->depth != 32) { + fl_gc = oldgc; + } + } +} + +void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ + + const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA); + d &= ~FL_IMAGE_WITH_ALPHA; + + innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0,alpha); +} +void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + + const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA); + d &= ~FL_IMAGE_WITH_ALPHA; + + innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data,alpha); +} +void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ + innards(buf,x,y,w,h,d,l,1,0,0,0); +} +void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, + int x, int y, int w, int h,int d) { + innards(0,x,y,w,h,d,0,1,cb,data,0); +} + +void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { + if (fl_visual->depth > 16) { + fl_color(r,g,b); + fl_rectf(x,y,w,h); + } else { + uchar c[3]; + c[0] = r; c[1] = g; c[2] = b; + innards(c,x,y,w,h,0,0,0,0,0,0); + } +} + +// +// End of "$Id$". +// diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index 5cc41d78c..e74df72d2 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -96,17 +96,6 @@ static const char* expand_text_(const char* from, char*& buf, int maxbuf, double } else if (c < ' ' || c == 127) { // ^X *o++ = '^'; *o++ = c ^ 0x40; -/* This is in fact not useful: the point is that a valid UTF-8 sequence for a non-ascii char contains no ascii char, - thus no tab, space, control, & or @ we want to process differently. - Also, invalid UTF-8 sequences are copied unchanged by this procedure. - Therefore, checking for tab, space, control, & or @, and copying the byte otherwise, is enough. - } else if (handle_utf8_seq(p, o)) { // figure out if we have an utf8 valid sequence before we determine the nbsp test validity: -#ifdef __APPLE__ - } else if (c == 0xCA) { // non-breaking space in MacRoman -#else - } else if (c == 0xA0) { // non-breaking space in ISO 8859 -#endif - *o++ = ' ';*/ } else if (c == '@' && draw_symbols) { // Symbol??? if (p[1] && p[1] != '@') break; *o++ = c; diff --git a/src/fl_draw_image.cxx b/src/fl_draw_image.cxx index 70718e657..bcd7e9e4a 100644 --- a/src/fl_draw_image.cxx +++ b/src/fl_draw_image.cxx @@ -26,589 +26,14 @@ // the "delta" and "linedelta", making them negative, though this may // defeat some of the shortcuts in translating the image for X. +// FIXME: use the correct macros for these conditions +// FIXME: eventuay get rid of this file and use the source files as modules. #ifdef WIN32 -# include "fl_draw_image_win32.cxx" +# include "drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx" #elif defined(__APPLE__) -# include "fl_draw_image_mac.cxx" -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement image drawing in its own file" -# include <FL/x.H> -void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { } +# include "drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx" #else - -// A list of assumptions made about the X display: - -// bits_per_pixel must be one of 8, 16, 24, 32. - -// scanline_pad must be a power of 2 and greater or equal to 8. - -// PsuedoColor visuals must have 8 bits_per_pixel (although the depth -// may be less than 8). This is the only limitation that affects any -// modern X displays, you can't use 12 or 16 bit colormaps. - -// The mask bits in TrueColor visuals for each color are -// contiguous and have at least one bit of each color. This -// is not checked for. - -// For 24 and 32 bit visuals there must be at least 8 bits of each color. - -//////////////////////////////////////////////////////////////// - -# include <FL/Fl.H> -# include <FL/fl_draw.H> -# include <FL/x.H> -# include "Fl_XColor.H" -# include "flstring.h" - -static XImage xi; // template used to pass info to X -static int bytes_per_pixel; -static int scanline_add; -static int scanline_mask; - -static void (*converter)(const uchar *from, uchar *to, int w, int delta); -static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta); - -static int dir; // direction-alternator -static int ri,gi,bi; // saved error-diffusion value - -# if USE_COLORMAP -//////////////////////////////////////////////////////////////// -// 8-bit converter with error diffusion - -static void color8_converter(const uchar *from, uchar *to, int w, int delta) { - int r=ri, g=gi, b=bi; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - to = to+(w-1); - d = -delta; - td = -1; - } else { - dir = 1; - d = delta; - td = 1; - } - for (; w--; from += d, to += td) { - r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; - g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; - b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; - Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); - Fl_XColor& xmap = fl_xmap[0][i]; - if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} - r -= xmap.r; - g -= xmap.g; - b -= xmap.b; - *to = uchar(xmap.pixel); - } - ri = r; gi = g; bi = b; -} - -static void mono8_converter(const uchar *from, uchar *to, int w, int delta) { - int r=ri, g=gi, b=bi; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - to = to+(w-1); - d = -delta; - td = -1; - } else { - dir = 1; - d = delta; - td = 1; - } - for (; w--; from += d, to += td) { - r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; - g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255; - b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255; - Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); - Fl_XColor& xmap = fl_xmap[0][i]; - if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} - r -= xmap.r; - g -= xmap.g; - b -= xmap.b; - *to = uchar(xmap.pixel); - } - ri = r; gi = g; bi = b; -} - -# endif - -//////////////////////////////////////////////////////////////// -// 16 bit TrueColor converters with error diffusion -// Cray computers have no 16-bit type, so we use character pointers -// (which may be slow) - -# ifdef U16 -# define OUTTYPE U16 -# define OUTSIZE 1 -# define OUTASSIGN(v) *t = v -# else -# define OUTTYPE uchar -# define OUTSIZE 2 -# define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt) -# endif - -static void color16_converter(const uchar *from, uchar *to, int w, int delta) { - OUTTYPE *t = (OUTTYPE *)to; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - t = t+(w-1)*OUTSIZE; - d = -delta; - td = -OUTSIZE; - } else { - dir = 1; - d = delta; - td = OUTSIZE; - } - int r=ri, g=gi, b=bi; - for (; w--; from += d, t += td) { - r = (r&~fl_redmask) +from[0]; if (r>255) r = 255; - g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255; - b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255; - OUTASSIGN(( - ((r&fl_redmask)<<fl_redshift)+ - ((g&fl_greenmask)<<fl_greenshift)+ - ((b&fl_bluemask)<<fl_blueshift) - ) >> fl_extrashift); - } - ri = r; gi = g; bi = b; -} - -static void mono16_converter(const uchar *from,uchar *to,int w, int delta) { - OUTTYPE *t = (OUTTYPE *)to; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - t = t+(w-1)*OUTSIZE; - d = -delta; - td = -OUTSIZE; - } else { - dir = 1; - d = delta; - td = OUTSIZE; - } - uchar mask = fl_redmask & fl_greenmask & fl_bluemask; - int r=ri; - for (; w--; from += d, t += td) { - r = (r&~mask) + *from; if (r > 255) r = 255; - uchar m = r&mask; - OUTASSIGN(( - (m<<fl_redshift)+ - (m<<fl_greenshift)+ - (m<<fl_blueshift) - ) >> fl_extrashift); - } - ri = r; -} - -// special-case the 5r6g5b layout used by XFree86: - -static void c565_converter(const uchar *from, uchar *to, int w, int delta) { - OUTTYPE *t = (OUTTYPE *)to; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - t = t+(w-1)*OUTSIZE; - d = -delta; - td = -OUTSIZE; - } else { - dir = 1; - d = delta; - td = OUTSIZE; - } - int r=ri, g=gi, b=bi; - for (; w--; from += d, t += td) { - r = (r&7)+from[0]; if (r>255) r = 255; - g = (g&3)+from[1]; if (g>255) g = 255; - b = (b&7)+from[2]; if (b>255) b = 255; - OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3)); - } - ri = r; gi = g; bi = b; -} - -static void m565_converter(const uchar *from,uchar *to,int w, int delta) { - OUTTYPE *t = (OUTTYPE *)to; - int d, td; - if (dir) { - dir = 0; - from = from+(w-1)*delta; - t = t+(w-1)*OUTSIZE; - d = -delta; - td = -OUTSIZE; - } else { - dir = 1; - d = delta; - td = OUTSIZE; - } - int r=ri; - for (; w--; from += d, t += td) { - r = (r&7) + *from; if (r > 255) r = 255; - OUTASSIGN((r>>3) * 0x841); - } - ri = r; -} - -//////////////////////////////////////////////////////////////// -// 24bit TrueColor converters: - -static void rgb_converter(const uchar *from, uchar *to, int w, int delta) { - int d = delta-3; - for (; w--; from += d) { - *to++ = *from++; - *to++ = *from++; - *to++ = *from++; - } -} - -static void bgr_converter(const uchar *from, uchar *to, int w, int delta) { - for (; w--; from += delta) { - uchar r = from[0]; - uchar g = from[1]; - *to++ = from[2]; - *to++ = g; - *to++ = r; - } -} - -static void rrr_converter(const uchar *from, uchar *to, int w, int delta) { - for (; w--; from += delta) { - *to++ = *from; - *to++ = *from; - *to++ = *from; - } -} - -//////////////////////////////////////////////////////////////// -// 32bit TrueColor converters on a 32 or 64-bit machine: - -# ifdef U64 -# define STORETYPE U64 -# if WORDS_BIGENDIAN -# define INNARDS32(f) \ - U64 *t = (U64*)to; \ - int w1 = w/2; \ - for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} \ - if (w&1) *t++ = (U64)(f)<<32; -# else -# define INNARDS32(f) \ - U64 *t = (U64*)to; \ - int w1 = w/2; \ - for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = ((U64)(f)<<32)|i;} \ - if (w&1) *t++ = (U64)(f); -# endif -# else -# define STORETYPE U32 -# define INNARDS32(f) \ - U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f -# endif - -static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8)); -} - -static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16)); -} - -static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2])); -} - -static void argb_premul_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32((unsigned(from[3]) << 24) + - (((from[0] * from[3]) / 255) << 16) + - (((from[1] * from[3]) / 255) << 8) + - ((from[2] * from[3]) / 255)); -} - -static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24)); -} - -static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32(unsigned(*from) * 0x1010100U); -} - -static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32(*from * 0x10101U); -} - -static void -color32_converter(const uchar *from, uchar *to, int w, int delta) { - INNARDS32( - (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift)); -} - -static void -mono32_converter(const uchar *from,uchar *to,int w, int delta) { - INNARDS32( - (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift)); -} - -//////////////////////////////////////////////////////////////// - -static void figure_out_visual() { - - fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx - fl_xpixel(FL_WHITE); // also make sure white is allocated - - static XPixmapFormatValues *pfvlist; - static int FL_NUM_pfv; - if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv); - XPixmapFormatValues *pfv; - for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++) - if (pfv->depth == fl_visual->depth) break; - xi.format = ZPixmap; - xi.byte_order = ImageByteOrder(fl_display); -//i.bitmap_unit = 8; -//i.bitmap_bit_order = MSBFirst; -//i.bitmap_pad = 8; - xi.depth = fl_visual->depth; - xi.bits_per_pixel = pfv->bits_per_pixel; - - if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error - else bytes_per_pixel = xi.bits_per_pixel/8; - - unsigned int n = pfv->scanline_pad/8; - if (pfv->scanline_pad & 7 || (n&(n-1))) - Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad); - if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE); - scanline_add = n-1; - scanline_mask = -n; - -# if USE_COLORMAP - if (bytes_per_pixel == 1) { - converter = color8_converter; - mono_converter = mono8_converter; - return; - } - if (!fl_visual->red_mask) - Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel); -# endif - - // otherwise it is a TrueColor visual: - - int rs = fl_redshift; - int gs = fl_greenshift; - int bs = fl_blueshift; - - switch (bytes_per_pixel) { - - case 2: - // All 16-bit TrueColor visuals are supported on any machine with - // 24 or more bits per integer. -# ifdef U16 - xi.byte_order = WORDS_BIGENDIAN; -# else - xi.byte_order = 1; -# endif - if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) { - converter = c565_converter; - mono_converter = m565_converter; - } else { - converter = color16_converter; - mono_converter = mono16_converter; - } - break; - - case 3: - if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;} - if (rs == 0 && gs == 8 && bs == 16) { - converter = rgb_converter; - mono_converter = rrr_converter; - } else if (rs == 16 && gs == 8 && bs == 0) { - converter = bgr_converter; - mono_converter = rrr_converter; - } else { - Fl::fatal("Can't do arbitrary 24bit color"); - } - break; - - case 4: - if ((xi.byte_order!=0) != WORDS_BIGENDIAN) - {rs = 24-rs; gs = 24-gs; bs = 24-bs;} - if (rs == 0 && gs == 8 && bs == 16) { - converter = xbgr_converter; - mono_converter = xrrr_converter; - } else if (rs == 24 && gs == 16 && bs == 8) { - converter = rgbx_converter; - mono_converter = rrrx_converter; - } else if (rs == 8 && gs == 16 && bs == 24) { - converter = bgrx_converter; - mono_converter = rrrx_converter; - } else if (rs == 16 && gs == 8 && bs == 0) { - converter = xrgb_converter; - mono_converter = xrrr_converter; - } else { - xi.byte_order = WORDS_BIGENDIAN; - converter = color32_converter; - mono_converter = mono32_converter; - } - break; - - default: - Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel); - } - -} - -# define MAXBUFFER 0x40000 // 256k - -static void innards(const uchar *buf, int X, int Y, int W, int H, - int delta, int linedelta, int mono, - Fl_Draw_Image_Cb cb, void* userdata, - const bool alpha) -{ - if (!linedelta) linedelta = W*delta; - - int dx, dy, w, h; - fl_clip_box(X,Y,W,H,dx,dy,w,h); - if (w<=0 || h<=0) return; - dx -= X; - dy -= Y; - - if (!bytes_per_pixel) figure_out_visual(); - const unsigned oldbpp = bytes_per_pixel; - const GC oldgc = fl_gc; - static GC gc32 = None; - xi.width = w; - xi.height = h; - - void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter; - if (mono) conv = mono_converter; - if (alpha) { - // This flag states the destination format is ARGB32 (big-endian), pre-multiplied. - bytes_per_pixel = 4; - conv = argb_premul_converter; - xi.depth = 32; - xi.bits_per_pixel = 32; - - // Do we need a new GC? - if (fl_visual->depth != 32) { - if (gc32 == None) - gc32 = XCreateGC(fl_display, fl_window, 0, NULL); - fl_gc = gc32; - } - } - - // See if the data is already in the right format. Unfortunately - // some 32-bit x servers (XFree86) care about the unknown 8 bits - // and they must be zero. I can't confirm this for user-supplied - // data, so the 32-bit shortcut is disabled... - // This can set bytes_per_line negative if image is bottom-to-top - // I tested it on Linux, but it may fail on other Xlib implementations: - if (buf && ( -# if 0 // set this to 1 to allow 32-bit shortcut - delta == 4 && -# if WORDS_BIGENDIAN - conv == rgbx_converter -# else - conv == xbgr_converter -# endif - || -# endif - conv == rgb_converter && delta==3 - ) && !(linedelta&scanline_add)) { - xi.data = (char *)(buf+delta*dx+linedelta*dy); - xi.bytes_per_line = linedelta; - - } else { - int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE); - int blocking = h; - static STORETYPE *buffer; // our storage, always word aligned - static long buffer_size; - {int size = linesize*h; - if (size > MAXBUFFER) { - size = MAXBUFFER; - blocking = MAXBUFFER/linesize; - } - if (size > buffer_size) { - delete[] buffer; - buffer_size = size; - buffer = new STORETYPE[size]; - }} - xi.data = (char *)buffer; - xi.bytes_per_line = linesize*sizeof(STORETYPE); - if (buf) { - buf += delta*dx+linedelta*dy; - for (int j=0; j<h; ) { - STORETYPE *to = buffer; - int k; - for (k = 0; j<h && k<blocking; k++, j++) { - conv(buf, (uchar*)to, w, delta); - buf += linedelta; - to += linesize; - } - XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); - } - } else { - STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)]; - for (int j=0; j<h; ) { - STORETYPE *to = buffer; - int k; - for (k = 0; j<h && k<blocking; k++, j++) { - cb(userdata, dx, dy+j, w, (uchar*)linebuf); - conv((uchar*)linebuf, (uchar*)to, w, delta); - to += linesize; - } - XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); - } - - delete[] linebuf; - } - } - - if (alpha) { - bytes_per_pixel = oldbpp; - xi.depth = fl_visual->depth; - xi.bits_per_pixel = oldbpp * 8; - - if (fl_visual->depth != 32) { - fl_gc = oldgc; - } - } -} - -void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ - - const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA); - d &= ~FL_IMAGE_WITH_ALPHA; - - innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0,alpha); -} -void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, - int x, int y, int w, int h,int d) { - - const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA); - d &= ~FL_IMAGE_WITH_ALPHA; - - innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data,alpha); -} -void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ - innards(buf,x,y,w,h,d,l,1,0,0,0); -} -void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, - int x, int y, int w, int h,int d) { - innards(0,x,y,w,h,d,0,1,cb,data,0); -} - -void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { - if (fl_visual->depth > 16) { - fl_color(r,g,b); - fl_rectf(x,y,w,h); - } else { - uchar c[3]; - c[0] = r; c[1] = g; c[2] = b; - innards(c,x,y,w,h,0,0,0,0,0,0); - } -} - +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx" #endif // |
