summaryrefslogtreecommitdiff
path: root/src/drivers/PostScript/Fl_PostScript_image.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/PostScript/Fl_PostScript_image.cxx')
-rw-r--r--src/drivers/PostScript/Fl_PostScript_image.cxx215
1 files changed, 179 insertions, 36 deletions
diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx
index 43f9b36c2..5c1f1d1f7 100644
--- a/src/drivers/PostScript/Fl_PostScript_image.cxx
+++ b/src/drivers/PostScript/Fl_PostScript_image.cxx
@@ -1,7 +1,7 @@
//
// Postscript image drawing implementation for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2020 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
@@ -22,10 +22,48 @@
#include <string.h>
#include <FL/Fl_PostScript.H>
+#include "Fl_PostScript_Graphics_Driver.H"
#include <FL/Fl.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Bitmap.H>
+#if USE_PANGO
+#include <cairo/cairo.h>
+#endif
+
+struct callback_data {
+ const uchar *data;
+ int D, LD;
+};
+
+static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
+ struct callback_data *cb_data;
+ const uchar *curdata;
+
+ cb_data = (struct callback_data*)data;
+ curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
+
+ memcpy(buf, curdata, w*cb_data->D);
+}
+
+void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
+ if (D<3){ //mono
+ draw_image_mono(data, ix, iy, iw, ih, D, LD);
+ return;
+ }
+
+ struct callback_data cb_data;
+
+ if (!LD) LD = iw*D;
+
+ cb_data.data = data;
+ cb_data.D = D;
+ cb_data.LD = LD;
+
+ draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D);
+}
+
+#if ! USE_PANGO
//
// Implementation of the /ASCII85Encode PostScript filter
@@ -345,41 +383,6 @@ static inline uchar swap_byte(const uchar b) {
return (swapped[b & 0xF] << 4) | swapped[b >> 4];
}
-
-struct callback_data {
- const uchar *data;
- int D, LD;
-};
-
-
-static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
- struct callback_data *cb_data;
- const uchar *curdata;
-
- cb_data = (struct callback_data*)data;
- curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
-
- memcpy(buf, curdata, w*cb_data->D);
-}
-
-
-void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
- if (D<3){ //mono
- draw_image_mono(data, ix, iy, iw, ih, D, LD);
- return;
- }
-
- struct callback_data cb_data;
-
- if (!LD) LD = iw*D;
-
- cb_data.data = data;
- cb_data.D = D;
- cb_data.LD = LD;
-
- draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D);
-}
-
void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) {
double x = ix, y = iy, w = iw, h = ih;
@@ -628,4 +631,144 @@ int Fl_PostScript_Graphics_Driver::scale_for_image_(Fl_Image *img, int XP, int Y
return 0;
}
+#else
+
+void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
+{
+ uchar *array = new uchar[iw * D * ih];
+ for (int l = 0; l < ih; l++) {
+ call(data, 0, l, iw, array + l*D*iw);
+ if (D%2 == 0) for (int i = 0; i < iw; i++) {
+ *(array + l*D*iw + i*D + D-1) = 0xff;
+ }
+ }
+ Fl_RGB_Image *rgb = new Fl_RGB_Image(array, iw, ih, D);
+ rgb->alloc_array = 1;
+ draw_rgb(rgb, ix, iy, iw, ih, 0, 0);
+ delete rgb;
+}
+
+void Fl_PostScript_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD)
+{
+ struct callback_data cb_data;
+ if (!LD) LD = iw*D;
+ cb_data.data = data;
+ cb_data.D = D;
+ cb_data.LD = LD;
+ draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D);
+}
+
+void Fl_PostScript_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
+{
+ draw_image(call, data, ix, iy, iw, ih, D);
+}
+
+static void destroy_BGRA(void *data) {
+ delete[] (uchar*)data;
+}
+
+void Fl_PostScript_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
+ Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
+ draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
+ delete rgb;
+}
+
+void Fl_PostScript_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
+ draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
+}
+
+void Fl_PostScript_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
+ draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy);
+}
+
+void Fl_PostScript_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy)
+{
+ cairo_surface_t *surf;
+ cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1);
+ int stride = cairo_format_stride_for_width(format, img->data_w());
+ uchar *BGRA = new uchar[stride * img->data_h()];
+ memset(BGRA, 0, stride * img->data_h());
+ if (img->d() >= 1) { // process Fl_RGB_Image of all depths
+ Fl_RGB_Image *rgb = (Fl_RGB_Image*)img;
+ int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
+ uchar A = 0xff, R,G,B, *q;
+ const uchar *r;
+ float f = 1;
+ if (rgb->d() >= 3) { // color images
+ for (int j = 0; j < rgb->data_h(); j++) {
+ r = rgb->array + j * lrgb;
+ q = BGRA + j * stride;
+ for (int i = 0; i < rgb->data_w(); i++) {
+ R = *r;
+ G = *(r+1);
+ B = *(r+2);
+ if (rgb->d() == 4) {
+ A = *(r+3);
+ f = float(A)/0xff;
+ }
+ *q = B * f;
+ *(q+1) = G * f;
+ *(q+2) = R * f;
+ *(q+3) = A;
+ r += rgb->d(); q += 4;
+ }
+ }
+ } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
+ for (int j = 0; j < rgb->data_h(); j++) {
+ r = rgb->array + j * lrgb;
+ q = BGRA + j * stride;
+ for (int i = 0; i < rgb->data_w(); i++) {
+ G = *r;
+ if (rgb->d() == 2) {
+ A = *(r+1);
+ f = float(A)/0xff;
+ }
+ *(q) = G * f;
+ *(q+1) = G * f;
+ *(q+2) = G * f;
+ *(q+3) = A;
+ r += rgb->d(); q += 4;
+ }
+ }
+ }
+ } else {
+ Fl_Bitmap *bm = (Fl_Bitmap*)img;
+ uchar *r, p;
+ unsigned *q;
+ for (int j = 0; j < bm->data_h(); j++) {
+ r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
+ q = (unsigned*)(BGRA + j * stride);
+ unsigned k = 0, mask32 = 1;
+ p = *r;
+ for (int i = 0; i < bm->data_w(); i++) {
+ if (p&1) (*q) |= mask32;
+ k++;
+ if (k % 8 != 0) p >>= 1; else p = *(++r);
+ if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
+ }
+ }
+ }
+ surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride);
+ if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
+ static cairo_user_data_key_t key = {};
+ (void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA);
+ cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
+ cairo_save(cairo_);
+ cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1);
+ cairo_clip(cairo_); // still to be tested
+ if (img->d() >= 1) cairo_set_source(cairo_, pat);
+ cairo_matrix_t matrix;
+ cairo_matrix_init_scale(&matrix, double(img->data_w())/img->w(), double(img->data_h())/img->h());
+ cairo_matrix_translate(&matrix, -XP+cx, -YP+cy);
+ cairo_pattern_set_matrix(pat, &matrix);
+ cairo_mask(cairo_, pat);
+ cairo_pattern_destroy(pat);
+ cairo_surface_destroy(surf);
+ cairo_restore(cairo_);
+ check_status();
+ }
+}
+
+#endif // USE_PANGO
+
#endif // !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT)