summaryrefslogtreecommitdiff
path: root/src/drivers/PostScript/Fl_PostScript_image.cxx
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2020-10-28 17:19:05 +0100
committerGitHub <noreply@github.com>2020-10-28 17:19:05 +0100
commit8accc6e8409819316fa296642c1d23e5638fcb2d (patch)
tree33c6237919989f120f2179cb1e7b410cb7cdd01e /src/drivers/PostScript/Fl_PostScript_image.cxx
parentf718943e6fbcf89297e61466068405452d7f8ae6 (diff)
Pango ps (#148)
Use cairo-PostScript to output PostScript when pango is available. This allows to draw in vectorial form any script. Before, only the Latin script could be drawn to PostScript in vectorial form.
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)