[librsvg] Check that RsvgHandle finished loading correctly before rendering-stage functions



commit 026ac0b55e5cdb055804d51389ce982afe74f356
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Dec 11 10:02:00 2018 -0600

    Check that RsvgHandle finished loading correctly before rendering-stage functions
    
    This question:
    
    
https://stackoverflow.com/questions/53406129/librsvg-and-cairo-rsvg-handle-render-cairo-fails-what-am-i-doing-wrong
    
    Indicates that the user didn't call rsvg_handle_close() before using
    the rendering functions, and was getting unexpected results.
    
    This comit adds checks for the handle being finished loading before
    those functions do anything.

 librsvg/rsvg-handle.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 0e481ac8..a5367959 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -1071,6 +1071,32 @@ rsvg_handle_create_drawing_ctx(RsvgHandle *handle,
                                  handle->priv->is_testing);
 }
 
+static gboolean
+is_loaded (RsvgHandle *handle)
+{
+    switch (handle->priv->hstate) {
+    case RSVG_HANDLE_STATE_START:
+        g_warning ("RsvgHandle has not been loaded");
+        return FALSE;
+
+    case RSVG_HANDLE_STATE_LOADING:
+        g_warning ("RsvgHandle is still loading; call rsvg_handle_close() first");
+        return FALSE;
+
+    case RSVG_HANDLE_STATE_CLOSED_OK:
+        return TRUE;
+
+    case RSVG_HANDLE_STATE_CLOSED_ERROR:
+        g_warning ("RsvgHandle could not read or parse the SVG; did you check for errors\n"
+                   "during the loading stage?");
+        return FALSE;
+
+    default:
+        g_assert_not_reached();
+        return FALSE;
+    }
+}
+
 /**
  * rsvg_handle_render_cairo_sub:
  * @handle: A #RsvgHandle
@@ -1098,8 +1124,9 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
 
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
-    if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
+    if (!is_loaded (handle)) {
         return FALSE;
+    }
 
     status = cairo_status (cr);
 
@@ -1175,6 +1202,10 @@ rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_d
     g_return_if_fail (RSVG_IS_HANDLE (handle));
     g_return_if_fail (dimension_data != NULL);
 
+    if (!is_loaded (handle)) {
+        return;
+    }
+
     /* This function is probably called from the cairo_render functions.
      * To prevent an infinite loop we are saving the state.
      */
@@ -1246,6 +1277,10 @@ rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimensi
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (dimension_data, FALSE);
 
+    if (!is_loaded (handle)) {
+        return FALSE;
+    }
+
     memset (&ink_r, 0, sizeof (RsvgRectangle));
     memset (dimension_data, 0, sizeof (RsvgDimensionData));
 
@@ -1294,7 +1329,9 @@ rsvg_handle_get_geometry_sub (RsvgHandle * handle, RsvgRectangle * ink_rect, Rsv
     memset (&ink_r, 0, sizeof (RsvgRectangle));
     memset (&logical_r, 0, sizeof (RsvgRectangle));
 
-    g_return_val_if_fail (handle->priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK, FALSE);
+    if (!is_loaded (handle)) {
+        return FALSE;
+    }
 
     root = rsvg_handle_rust_get_root (handle->priv->rust_handle);
 
@@ -1372,6 +1409,10 @@ rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_d
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (position_data != NULL, FALSE);
 
+    if (!is_loaded (handle)) {
+        return FALSE;
+    }
+
     memset (position_data, 0, sizeof (*position_data));
 
     /* Short-cut when no id is given. */
@@ -1410,6 +1451,10 @@ rsvg_handle_has_sub (RsvgHandle * handle,
 {
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
+    if (!is_loaded (handle)) {
+        return FALSE;
+    }
+
     if (G_UNLIKELY (!id || !id[0]))
       return FALSE;
 
@@ -1448,8 +1493,9 @@ rsvg_handle_get_pixbuf_sub (RsvgHandle * handle, const char *id)
 
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
 
-    if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
+    if (!is_loaded (handle)) {
         return NULL;
+    }
 
     rsvg_handle_get_dimensions (handle, &dimensions);
     if (!(dimensions.width && dimensions.height))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]