FLTK logo

[master] 231159e - Fix for issue #155 - continued

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 231159e - Fix for issue #155 - continued "ManoloFLTK" Nov 11, 2020  
 
commit 231159e16c7bd8438f3e567507f5ad394d00c760
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Thu Nov 12 07:46:00 2020 +0100
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Thu Nov 12 07:46:12 2020 +0100

    Fix for issue #155 - continued
    
    The issue lies in details how floating point scaled coordinates are converted
    to integer values and its impact on the drawing of large SVG images.
    This commit fixes the X11 platform.
    The macOS platform is immune because drawing uses floating point
    coordinates.
    The Windows platform still needs fixing.

 FL/Fl_Graphics_Driver.H                            |  2 +-
 FL/Fl_SVG_Image.H                                  |  2 ++
 src/Fl_Graphics_Driver.cxx                         | 13 +++++++++----
 src/Fl_SVG_Image.cxx                               | 17 ++++++++++++++---
 src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx   |  8 ++++----
 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H     |  2 +-
 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx   |  2 +-
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx       |  2 +-
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 10 +++++-----
 9 files changed, 38 insertions(+), 20 deletions(-)

diff --git FL/Fl_Graphics_Driver.H FL/Fl_Graphics_Driver.H
index 813613f..be5dbe4 100644
--- FL/Fl_Graphics_Driver.H
+++ FL/Fl_Graphics_Driver.H
@@ -236,7 +236,7 @@ protected:
   static void draw_empty(Fl_Image* img, int X, int Y) {img->draw_empty(X, Y);}
 
   Fl_Graphics_Driver();
-  virtual void cache_size(int &width, int &height);
+  virtual void cache_size(Fl_Image *img, int &width, int &height);
   static unsigned need_pixmap_bg_color;
 public:
   virtual ~Fl_Graphics_Driver() {} ///< Destructor
diff --git FL/Fl_SVG_Image.H FL/Fl_SVG_Image.H
index 9a2504c..7ced23c 100644
--- FL/Fl_SVG_Image.H
+++ FL/Fl_SVG_Image.H
@@ -133,6 +133,7 @@ struct NSVGimage;
 
  */
 class FL_EXPORT Fl_SVG_Image : public Fl_RGB_Image {
+  friend class Fl_Graphics_Driver;
 private:
   typedef struct {
     NSVGimage* svg_image;
@@ -146,6 +147,7 @@ private:
   float average_weight_;
   float svg_scaling_(int W, int H);
   void rasterize_(int W, int H);
+  void cache_size(int &width, int &height);
   void init_(const char *filename, const char *filedata, Fl_SVG_Image *copy_source);
   Fl_SVG_Image(Fl_SVG_Image *source);
 public:
diff --git src/Fl_Graphics_Driver.cxx src/Fl_Graphics_Driver.cxx
index 7b46d69..c5cd9d6 100644
--- src/Fl_Graphics_Driver.cxx
+++ src/Fl_Graphics_Driver.cxx
@@ -29,6 +29,7 @@
 #include <FL/Fl_Image_Surface.H>
 #include <FL/math.h>
 #include <FL/platform.H>
+#include <FL/Fl_SVG_Image.H>
 
 FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current driver of graphics operations
 
@@ -201,7 +202,7 @@ unsigned Fl_Graphics_Driver::font_desc_size() {
 /** Converts \p width and \p height from FLTK units to drawing units.
  The conversion performed consists in multiplying \p width and \p height by
  scale() and in slightly modifying that to help support tiled images. */
-void Fl_Graphics_Driver::cache_size(int &width, int &height)
+void Fl_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height)
 {
   if ( int(scale()) == scale() ) {
     width  = width * scale();
@@ -210,6 +211,10 @@ void Fl_Graphics_Driver::cache_size(int &width, int &height)
     width  = (width+1) * scale();
     height = (height+1) * scale();
   }
+  if (img->d() == 4 && ((Fl_RGB_Image*)img)->as_svg_image()) { // check for SVG image
+    Fl_SVG_Image *svg = (Fl_SVG_Image*)img;
+    svg->cache_size(width, height);
+  }
 }
 
 /** Draws an Fl_Pixmap object using this graphics driver.
@@ -223,7 +228,7 @@ void Fl_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int
   }
   // to allow rescale at runtime
   int w2=pxm->w(), h2=pxm->h();
-  cache_size(w2, h2); // after this, w2 x h2 is size of desired cached image
+  cache_size(pxm, w2, h2); // after this, w2 x h2 is size of desired cached image
   int *pw, *ph;
   cache_w_h(pxm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap
   if (*id(pxm) && (*pw != w2 || *ph != h2)) {
@@ -256,7 +261,7 @@ void Fl_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int
     return;
   }
   int w2 = bm->w(), h2 = bm->h();
-  cache_size(w2, h2); // after this, w2 x h2 is size of desired cached image
+  cache_size(bm, w2, h2); // after this, w2 x h2 is size of desired cached image
   int *pw, *ph;
   cache_w_h(bm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap
   if (*id(bm) && (*pw != w2 || *ph != h2)) {
@@ -296,7 +301,7 @@ void Fl_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int
   int w2, h2, *pw, *ph;
   if (need_scaled_drawing) {
     w2 = img->w(); h2 = img->h();
-    cache_size(w2, h2);
+    cache_size(img, w2, h2);
   } else {
     w2 = img->data_w(); h2 = img->data_h();
   } // after this, w2 x h2 is desired cached image size
diff --git src/Fl_SVG_Image.cxx src/Fl_SVG_Image.cxx
index 93aaee2..6b241f8 100644
--- src/Fl_SVG_Image.cxx
+++ src/Fl_SVG_Image.cxx
@@ -221,8 +221,8 @@ void Fl_SVG_Image::resize(int width, int height) {
   int w1 = width, h1 = height;
   if (proportional) {
     float f = svg_scaling_(width, height);
-    w1 = int( int(counted_svg_image_->svg_image->width+0.5)*f + 0.5 );
-    h1 = int( int(counted_svg_image_->svg_image->height+0.5)*f + 0.5 );
+    w1 = int( counted_svg_image_->svg_image->width*f + 0.5 );
+    h1 = int( counted_svg_image_->svg_image->height*f + 0.5 );
   }
   w(w1); h(h1);
   if (rasterized_ && w1 == raster_w_ && h1 == raster_h_) return;
@@ -235,6 +235,17 @@ void Fl_SVG_Image::resize(int width, int height) {
 }
 
 
+void Fl_SVG_Image::cache_size(int &width, int &height) {
+  if (proportional) {
+    // Keep the rasterized image proportional to its source-level width and height
+    // while maintaining it large enough to allow image tiling.
+    float f = counted_svg_image_->svg_image->width / counted_svg_image_->svg_image->height;
+    if (height * f >= width) width =  height * f + 0.5;
+    else height = width/f + 0.5;
+  }
+}
+
+
 void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
   /* There may be several pixels per FLTK unit in an area
    of size w() x h() of the display. This occurs, e.g., with Apple retina displays
@@ -246,7 +257,7 @@ void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) {
   int w1 = w(), h1 = h();
   int f = fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER) ? 2 : 1;
   int w2 = f*w(), h2 = f*h();
-  fl_graphics_driver->cache_size(w2, h2);
+  fl_graphics_driver->cache_size(this, w2, h2);
   resize(w2, h2);
   scale(w1, h1, 0, 1);
   Fl_RGB_Image::draw(X, Y, W, H, cx, cy);
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 37507b4..6bc9ad8 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -400,7 +400,7 @@ void Fl_GDI_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) {
   X = X*scale();
   Y = Y*scale();
-  cache_size(W, H);
+  cache_size(bm, W, H);
   cx *= scale(); cy *= scale();
 
   HDC tempdc = CreateCompatibleDC(gc_);
@@ -500,7 +500,7 @@ void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img)
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
   X = X*scale();
   Y = Y*scale();
-  cache_size(W, H);
+  cache_size(img, W, H);
   cx *= scale(); cy *= scale();
   if (W + cx > img->data_w()) W = img->data_w() - cx;
   if (H + cy > img->data_h()) H = img->data_h() - cy;
@@ -538,7 +538,7 @@ void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP,
   float scaleW = float(rgb->data_w())/rgb->w();
   float scaleH = float(rgb->data_h())/rgb->h();
   int W = WP, H = HP;
-  cache_size(W, H);
+  cache_size(rgb, W, H);
   HDC new_gc = CreateCompatibleDC(gc_);
   int save = SaveDC(new_gc);
   SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
@@ -628,7 +628,7 @@ void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) {
 void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) {
   X = X*scale();
   Y = Y*scale();
-  cache_size(W, H);
+  cache_size(pxm, W, H);
   cx *= scale(); cy *= scale();
   Fl_Region r2 = scale_clip(scale());
   if (*Fl_Graphics_Driver::mask(pxm)) {
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
index 67265c3..76edc41 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
@@ -59,7 +59,7 @@ protected:
   CGLineJoin quartz_line_join_;
   CGFloat *quartz_line_pattern;
   int quartz_line_pattern_size;
-  virtual void cache_size(int &width, int &height);
+  virtual void cache_size(Fl_Image* img, int &width, int &height);
 public:
   Fl_Quartz_Graphics_Driver();
   virtual ~Fl_Quartz_Graphics_Driver() { if (p) free(p); }
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
index f8fab11..1c5c7e9 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
@@ -154,7 +154,7 @@ void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r) {
   }
 }
 
-void Fl_Quartz_Graphics_Driver::cache_size(int &width, int &height) {
+void Fl_Quartz_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) {
   width *= 2 * scale();
   height *= 2 * scale();
 }
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
index c98cb54..15ea319 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
@@ -86,7 +86,7 @@ void Fl_Xlib_Graphics_Driver::scale(float f) {
      Setting line_delta_ to 1 and offsetting all line, rectangle, text and clip
      coordinates by line_delta_ achieves what is wanted until scale_ <= 3.5.
      */
-    line_delta_ =  (scale() > 1.75 ? 1 : 0);
+    line_delta_ =  (scale() > 1.9/*1.75*/ ? 1 : 0);
   }
 #endif
 }
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
index 2e0b4af..b20a84c 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
@@ -625,7 +625,7 @@ void Fl_Xlib_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
 void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) {
   X = (X+offset_x_)*scale();
   Y = (Y+offset_y_)*scale();
-  cache_size(W, H);
+  cache_size(bm, W, H);
   cx *= scale(); cy *= scale();
   XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm));
   int ox = X-cx; if (ox < 0) ox += bm->w()*scale();
@@ -727,7 +727,7 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) {
 void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
   X = (X+offset_x_)*scale();
   Y = (Y+offset_y_)*scale();
-  cache_size(W, H);
+  cache_size(img, W, H);
   cx *= scale(); cy *= scale();
   if (img->d() == 1 || img->d() == 3) {
     XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y);
@@ -764,9 +764,9 @@ void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP
   if (!*Fl_Graphics_Driver::id(rgb)) {
     cache(rgb);
   }
-  cache_size(W, H);
+  cache_size(rgb, W, H);
   int Wfull = rgb->w(), Hfull = rgb->h();
-  cache_size(Wfull, Hfull);
+  cache_size(rgb, Wfull, Hfull);
   scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(),
                                  rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull),
                           cx*scale(), cy*scale(), (X + offset_x_)*scale(), (Y + offset_y_)*scale(), W, H);
@@ -829,7 +829,7 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) {
 void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) {
   X = (X+offset_x_)*scale();
   Y = (Y+offset_y_)*scale();
-  cache_size(W, H);
+  cache_size(pxm, W, H);
   cx *= scale(); cy *= scale();
   Fl_Region r2 = scale_clip(scale());
   if (*Fl_Graphics_Driver::mask(pxm)) {
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.