Author: AlbrechtS
Date: 2009-04-07 10:25:24 -0700 (Tue, 07 Apr 2009)
New Revision: 6742
Log:
Fix image handling in Fl_Help_View (STR #2163).


Modified:
   branches/branch-1.1/src/Fl_Help_View.cxx

Modified: branches/branch-1.1/src/Fl_Help_View.cxx
===================================================================
--- branches/branch-1.1/src/Fl_Help_View.cxx    2009-04-03 07:31:51 UTC (rev 
6741)
+++ branches/branch-1.1/src/Fl_Help_View.cxx    2009-04-07 17:25:24 UTC (rev 
6742)
@@ -97,7 +97,12 @@
 static void    scrollbar_callback(Fl_Widget *s, void *);
 static void    hscrollbar_callback(Fl_Widget *s, void *);
 
+//
+// global flag for image loading (see get_image).
+//
 
+static char initial_load = 0;
+
 //
 // Broken image...
 //
@@ -892,7 +897,6 @@
            if (img) {
              img->draw(xx + x() - leftline_,
                        yy + y() - fl_height() + fl_descent() + 2);
-             img->release();
            }
 
            xx += ww;
@@ -2305,7 +2309,7 @@
 
 void
 Fl_Help_View::free_data() {
-  // Releae all images...
+  // Release all images...
   if (value_) {
     const char *ptr,           // Pointer into block
                *attrs;         // Pointer to start of element attributes
@@ -2315,7 +2319,6 @@
                wattr[1024],    // Width attribute buffer
                hattr[1024];    // Height attribute buffer
 
-
     for (ptr = value_; *ptr;)
     {
       if (*ptr == '<')
@@ -2358,17 +2361,17 @@
          int           width;
          int           height;
 
-
           get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
           get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
          width  = get_length(wattr);
          height = get_length(hattr);
 
          if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
-           // Release the image twice to free it from memory...
+           // Get and release the image to free it from memory...
            img = get_image(attr, width, height);
-           img->release();
-           img->release();
+           if ((void*)img != &broken_image) {
+             img->release();
+           }
          }
        }
       }
@@ -2505,7 +2508,7 @@
 
 
 //
-// 'Fl_Help_View::get_color()' - Get an alignment attribute.
+// 'Fl_Help_View::get_color()' - Get a color attribute.
 //
 
 Fl_Color                               // O - Color value
@@ -2570,6 +2573,48 @@
 // 'Fl_Help_View::get_image()' - Get an inline image.
 //
 
+/** Gets an inline image.
+
+  The image reference count is maintained accordingly, such that
+  the image can be released exactly once when the document is closed.
+
+  \return a pointer to a cached Fl_Shared_Image, if the image can be loaded,
+         otherwise a pointer to an internal Fl_Pixmap (broken_image).
+
+  \todo Fl_Help_View::get_image() returns a pointer to the internal
+  Fl_Pixmap broken_image, but this is _not_ compatible with the
+  return type Fl_Shared_Image (release() must not be called).
+*/
+
+/* Implementation note: (A.S. Apr 05, 2009)
+
+  Fl_Help_View::get_image() uses a static global flag (initial_load)
+  to determine, if it is called from the initial loading of a document
+  (load() or value()), or from resize() or draw().
+
+  A better solution would be to manage all loaded images in an own
+  structure like Fl_Help_Target (Fl_Help_Image ?) to avoid using this
+  global flag, but this would break the ABI !
+
+  This should be fixed in FLTK 1.3 !
+
+
+  If initial_load is true, then Fl_Shared_Image::get() is called to
+  load the image, and the reference count of the shared image is
+  increased by one.
+
+  If initial_load is false, then Fl_Shared_Image::find() is called to
+  load the image, and the image is released immediately. This avoids
+  increasing the reference count when calling get_image() from draw()
+  or resize().
+
+  Calling Fl_Shared_Image::find() instead of Fl_Shared_Image::get() avoids
+  doing unnecessary i/o for "broken images" within each resize/redraw.
+
+  Each image must be released exactly once in the destructor or before
+  a new document is loaded: see free_data().
+*/
+
 Fl_Shared_Image *
 Fl_Help_View::get_image(const char *name, int W, int H) {
   const char   *localname;             // Local filename
@@ -2610,8 +2655,17 @@
 
   if (strncmp(localname, "file:", 5) == 0) localname += 5;
 
-  if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL)
-    ip = (Fl_Shared_Image *)&broken_image;
+  if (initial_load) {
+    if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL) {
+      ip = (Fl_Shared_Image *)&broken_image;
+    }
+  } else { // draw or resize
+    if ((ip = Fl_Shared_Image::find(localname, W, H)) == NULL) {
+      ip = (Fl_Shared_Image *)&broken_image;
+    } else {
+      ip->release();
+    }
+  }
 
   return ip;
 }
@@ -2656,6 +2710,7 @@
   char         target[32];     // Current target
 
   clear_selection();
+  free_data();
 
   strlcpy(target, linkp->name, sizeof(target));
 
@@ -3079,8 +3134,8 @@
   char         error[1024];    // Error buffer
   char         newname[1024];  // New filename buffer
 
-
   clear_selection();
+  free_data();
 
   strlcpy(newname, f, sizeof(newname));
   if ((target = strrchr(newname, '#')) != NULL)
@@ -3104,12 +3159,6 @@
   else if (slash > directory_ && slash[-1] != '/')
     *slash = '\0';
 
-  if (value_ != NULL)
-  {
-    free((void *)value_);
-    value_ = NULL;
-  }
-
   if (strncmp(localname, "ftp:", 4) == 0 ||
       strncmp(localname, "http:", 5) == 0 ||
       strncmp(localname, "https:", 6) == 0 ||
@@ -3153,7 +3202,9 @@
     }
   }
 
+  initial_load = 1;
   format();
+  initial_load = 0;
 
   if (target)
     topline(target);
@@ -3279,7 +3330,9 @@
 
   value_ = strdup(v);
 
+  initial_load = 1;
   format();
+  initial_load = 0;
 
   topline(0);
   leftline(0);

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to