Code

Added example file for feTurbulence effect
[inkscape.git] / src / style.cpp
index 5817df3428e746eb08736edae748ff5ba45c599d..357fe5f0e2a81dd95eb3003a4468036699405142 100644 (file)
@@ -100,8 +100,6 @@ static gint sp_style_write_ilengthornormal(gchar *p, gint const len, gchar const
 static gint sp_style_write_itextdecoration(gchar *p, gint const len, gchar const *const key, SPITextDecoration const *const val, SPITextDecoration const *const base, guint const flags);
 static gint sp_style_write_ifilter(gchar *b, gint len, gchar const *key, SPIFilter const *filter, SPIFilter const *base, guint flags);
 
-static void sp_style_paint_clear(SPStyle *style, SPIPaint *paint);
-
 static void sp_style_filter_clear(SPStyle *style);
 
 #define SPS_READ_IENUM_IF_UNSET(v,s,d,i) if (!(v)->set) {sp_style_read_ienum((v), (s), (d), (i));}
@@ -328,6 +326,7 @@ static SPStyleEnum const enum_enable_background[] = {
 static void
 sp_style_object_release(SPObject *object, SPStyle *style)
 {
+    (void)object; // TODO
     style->object = NULL;
 }
 
@@ -337,6 +336,7 @@ sp_style_object_release(SPObject *object, SPStyle *style)
 static void
 sp_style_filter_ref_modified(SPObject *obj, guint flags, SPStyle *style)
 {
+    (void)flags; // TODO
     SPFilter *filter=static_cast<SPFilter *>(obj);
     if (style->getFilter() == filter)
     {
@@ -371,9 +371,10 @@ sp_style_filter_ref_changed(SPObject *old_ref, SPObject *ref, SPStyle *style)
 static void
 sp_style_paint_server_ref_modified(SPObject *obj, guint flags, SPStyle *style)
 {
+    (void)flags; // TODO
     SPPaintServer *server = static_cast<SPPaintServer *>(obj);
 
-    if ((style->fill.type == SP_PAINT_TYPE_PAINTSERVER)
+    if ((style->fill.isPaintserver())
         && style->getFillPaintServer() == server)
     {
         if (style->object) {
@@ -387,14 +388,14 @@ sp_style_paint_server_ref_modified(SPObject *obj, guint flags, SPStyle *style)
              */
             style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
         }
-    } else if ((style->stroke.type == SP_PAINT_TYPE_PAINTSERVER)
+    } else if ((style->stroke.isPaintserver())
         && style->getStrokePaintServer() == server)
     {
         if (style->object) {
             /// \todo fixme:
             style->object->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
         }
-    } else {
+    } else if (server) {
         g_assert_not_reached();
     }
 }
@@ -532,8 +533,8 @@ sp_style_unref(SPStyle *style)
         style->fill_ps_modified_connection.~connection();
         style->stroke_ps_modified_connection.~connection();
 
-        sp_style_paint_clear(style, &style->fill);
-        sp_style_paint_clear(style, &style->stroke);
+        style->fill.clear();
+        style->stroke.clear();
         sp_style_filter_clear(style);
 
         g_free(style->stroke_dash.dash);
@@ -714,6 +715,17 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
             style->stroke_dashoffset_set = FALSE;
         }
     }
+    
+    /* -inkscape-font-specification */
+    if (!style->text_private || !style->text->font_specification.set) {
+        val = repr->attribute("-inkscape-font-specification");
+        if (val) {
+            if (!style->text_private) sp_style_privatize_text(style);
+            gchar *val_unquoted = attribute_unquote(val);
+            sp_style_read_istring(&style->text->font_specification, val_unquoted);
+            if (val_unquoted) g_free (val_unquoted);
+        }
+    }
 
     /* font-family */
     if (!style->text_private || !style->text->font_family.set) {
@@ -816,6 +828,14 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
     g_return_if_fail(val != NULL);
 
     switch (id) {
+        case SP_PROP_INKSCAPE_FONT_SPEC:
+            if (!style->text_private) sp_style_privatize_text(style);
+            if (!style->text->font_specification.set) {
+                gchar *val_unquoted = attribute_unquote(val);
+                sp_style_read_istring(&style->text->font_specification, val_unquoted);
+                if (val_unquoted) g_free (val_unquoted);
+            }
+            break;
         /* CSS2 */
         /* Font */
         case SP_PROP_FONT_FAMILY:
@@ -1499,6 +1519,13 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
         }
     }
 
+    if (style->text && parent->text) {
+        if (!style->text->font_specification.set || style->text->font_specification.inherit) {
+            g_free(style->text->font_specification.value);
+            style->text->font_specification.value = g_strdup(parent->text->font_specification.value);
+        }
+    }
+
     /* Markers - Free the old value and make copy of the new */
     for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
         if (!style->marker[i].set || style->marker[i].inherit) {
@@ -1884,10 +1911,14 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare
     /* Font */
 
     if (style->text && parent->text) {
+        sp_style_merge_string_prop_from_dying_parent(style->text->font_specification,
+                                                     parent->text->font_specification);
+        
         sp_style_merge_string_prop_from_dying_parent(style->text->font_family,
                                                      parent->text->font_family);
     }
 
+
     /* Properties that don't inherit by default.  Most of these need special handling. */
     {
         /*
@@ -2090,30 +2121,26 @@ sp_style_set_to_uri_string (SPStyle *style, bool isfill, const gchar *uri)
 static void
 sp_style_merge_ipaint(SPStyle *style, SPIPaint *paint, SPIPaint const *parent)
 {
-    sp_style_paint_clear(style, paint);
-
     if ((paint->set && paint->currentcolor) || parent->currentcolor) {
+        paint->clear();
         paint->currentcolor = TRUE;
-        paint->type = SP_PAINT_TYPE_COLOR;
-        sp_color_copy(&paint->value.color, &style->color.value.color);
+        paint->setColor(style->color.value.color);
         return;
     }
 
-    paint->type = parent->type;
-    switch (paint->type) {
-        case SP_PAINT_TYPE_COLOR:
-            sp_color_copy(&paint->value.color, &parent->value.color);
-            break;
-        case SP_PAINT_TYPE_PAINTSERVER:
-            if (parent->value.href) {
-                sp_style_set_ipaint_to_uri(style, paint, parent->value.href->getURI(), parent->value.href->getOwnerDocument());
-            }
-            break;
-        case SP_PAINT_TYPE_NONE:
-            break;
-        default:
-            g_assert_not_reached();
-            break;
+    paint->clear();
+    if ( parent->isPaintserver() ) {
+        if (parent->value.href) {
+            sp_style_set_ipaint_to_uri(style, paint, parent->value.href->getURI(), parent->value.href->getOwnerDocument());
+        } else {
+            g_warning("Expected paint server not found.");
+        }
+    } else if ( parent->isColor() ) {
+        paint->setColor( parent->value.color );
+    } else if ( parent->isNone() ) {
+        //
+    } else {
+        g_assert_not_reached();
     }
 }
 
@@ -2414,11 +2441,11 @@ sp_style_clear(SPStyle *style)
 {
     g_return_if_fail(style != NULL);
 
-    sp_style_paint_clear(style, &style->fill);
-    sp_style_paint_clear(style, &style->stroke);
+    style->fill.clear();
+    style->stroke.clear();
     sp_style_filter_clear(style);
 
-    if (style->fill.value.href) 
+    if (style->fill.value.href)
         delete style->fill.value.href;
     if (style->stroke.value.href)
         delete style->stroke.value.href;
@@ -2456,7 +2483,7 @@ sp_style_clear(SPStyle *style)
     style->text = text;
     style->text_private = text_private;
 
-    /* fixme: */
+    style->text->font_specification.set = FALSE;
     style->text->font.set = FALSE;
     style->text->font_family.set = FALSE;
 
@@ -2528,17 +2555,15 @@ sp_style_clear(SPStyle *style)
     style->overflow.set = FALSE;
     style->overflow.value = style->overflow.computed = SP_CSS_OVERFLOW_VISIBLE;
 
-    style->color.type = SP_PAINT_TYPE_COLOR;
-    sp_color_set_rgb_float(&style->color.value.color, 0.0, 0.0, 0.0);
+    style->color.clear();
+    style->color.setColor(0.0, 0.0, 0.0);
 
-    style->fill.type = SP_PAINT_TYPE_COLOR;
-    sp_color_set_rgb_float(&style->fill.value.color, 0.0, 0.0, 0.0);
+    style->fill.clear();
+    style->fill.setColor(0.0, 0.0, 0.0);
     style->fill_opacity.value = SP_SCALE24_MAX;
     style->fill_rule.value = style->fill_rule.computed = SP_WIND_RULE_NONZERO;
 
-    style->stroke.type = SP_PAINT_TYPE_NONE;
-    style->stroke.set = FALSE;
-    sp_color_set_rgb_float(&style->stroke.value.color, 0.0, 0.0, 0.0);
+    style->stroke.clear();
     style->stroke_opacity.value = SP_SCALE24_MAX;
 
     style->stroke_width.set = FALSE;
@@ -2638,6 +2663,7 @@ sp_text_style_new()
     ts->refcount = 1;
     sp_text_style_clear(ts);
 
+    ts->font_specification.value = g_strdup("Bitstream Vera Sans");
     ts->font.value = g_strdup("Bitstream Vera Sans");
     ts->font_family.value = g_strdup("Bitstream Vera Sans");
 
@@ -2651,6 +2677,7 @@ sp_text_style_new()
 static void
 sp_text_style_clear(SPTextStyle *ts)
 {
+    ts->font_specification.set = FALSE;
     ts->font.set = FALSE;
     ts->font_family.set = FALSE;
 }
@@ -2666,6 +2693,7 @@ sp_text_style_unref(SPTextStyle *st)
     st->refcount -= 1;
 
     if (st->refcount < 1) {
+        g_free(st->font_specification.value);
         g_free(st->font.value);
         g_free(st->font_family.value);
         g_free(st);
@@ -2685,6 +2713,7 @@ sp_text_style_duplicate_unset(SPTextStyle *st)
     SPTextStyle *nt = g_new0(SPTextStyle, 1);
     nt->refcount = 1;
 
+    nt->font_specification.value = g_strdup(st->font_specification.value);
     nt->font.value = g_strdup(st->font.value);
     nt->font_family.value = g_strdup(st->font_family.value);
 
@@ -2706,6 +2735,7 @@ sp_text_style_write(gchar *p, guint const len, SPTextStyle const *const st, guin
         flags = SP_STYLE_FLAG_IFSET;
 
     d += sp_style_write_istring(p + d, len - d, "font-family", &st->font_family, NULL, flags);
+    d += sp_style_write_istring(p + d, len - d, "-inkscape-font-specification", &st->font_specification, NULL, flags);
     return d;
 }
 
@@ -2958,6 +2988,8 @@ sp_style_read_itextdecoration(SPITextDecoration *val, gchar const *str)
 static void
 sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document)
 {
+    (void)style; // TODO
+    (void)document; // TODO
     paint->currentcolor = FALSE;  /* currentColor not a valid <color>. */
     if (!strcmp(str, "inherit")) {
         paint->set = TRUE;
@@ -2965,9 +2997,7 @@ sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
     } else {
         guint32 const rgb0 = sp_svg_read_color(str, 0xff);
         if (rgb0 != 0xff) {
-            paint->type = SP_PAINT_TYPE_COLOR;
-            sp_color_set_rgb_rgba32(&paint->value.color, rgb0);
-            paint->set = TRUE;
+            paint->setColor(rgb0);
             paint->inherit = FALSE;
         }
     }
@@ -2986,19 +3016,12 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
         ++str;
     }
 
-    if (paint->value.href && paint->value.href->getObject()) {
-        paint->value.href->detach();
-    }
-    paint->colorSet = FALSE;
-    paint->currentcolor = FALSE;
-    paint->noneSet = FALSE;
+    paint->clear();
 
     if (streq(str, "inherit")) {
         paint->set = TRUE;
         paint->inherit = TRUE;
     } else {
-        paint->type = SP_PAINT_TYPE_NONE;
-        paint->inherit = FALSE;
         if ( strneq(str, "url", 3) ) {
             gchar *uri = extract_uri( str, &str );
             while ( g_ascii_isspace(*str) ) {
@@ -3006,7 +3029,6 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
             }
             // TODO check on and comment the comparrison "paint != &style->color".
             if ( uri && *uri && (paint != &style->color) ) {
-                paint->type = SP_PAINT_TYPE_PAINTSERVER;
                 paint->set = TRUE;
 
                 // it may be that this style's SPIPaint has not yet created its URIReference;
@@ -3031,12 +3053,8 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
         } else {
             guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
             if (rgb0 != 0xff) {
-                if ( paint->type != SP_PAINT_TYPE_PAINTSERVER ) {
-                    paint->type = SP_PAINT_TYPE_COLOR;
-                }
-                sp_color_set_rgb_rgba32(&paint->value.color, rgb0);
+                paint->setColor( rgb0 );
                 paint->set = TRUE;
-                paint->colorSet = true;
 
                 while (g_ascii_isspace(*str)) {
                     ++str;
@@ -3047,7 +3065,7 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
                         delete tmp;
                         tmp = 0;
                     }
-                    paint->value.iccColor = tmp;
+                    paint->value.color.icc = tmp;
                 }
             }
         }
@@ -3523,18 +3541,30 @@ sp_style_write_itextdecoration(gchar *p, gint const len, gchar const *const key,
 static bool
 sp_paint_differ(SPIPaint const *const a, SPIPaint const *const b)
 {
-    if (a->type != b->type)
+    if ( (a->isColor() != b->isColor())
+         || (a->isPaintserver() != b->isPaintserver())
+         || (a->set != b->set)
+         || (a->currentcolor != b->currentcolor)
+         || (a->inherit!= b->inherit) ) {
         return true;
-    if (a->type == SP_PAINT_TYPE_COLOR)
-        return !(sp_color_is_equal(&a->value.color, &b->value.color)
-                 && ((a->value.iccColor == b->value.iccColor)
-                     || (a->value.iccColor && b->value.iccColor
-                         && (a->value.iccColor->colorProfile == b->value.iccColor->colorProfile)
-                         && (a->value.iccColor->colors == b->value.iccColor->colors))));
+    }
+
+    // TODO refactor to allow for mixed paints (rgb() *and* url(), etc)
+
+    if ( a->isPaintserver() ) {
+        return (a->value.href == NULL || b->value.href == NULL || a->value.href->getObject() != b->value.href->getObject());
+    }
+
+    if ( a->isColor() ) {
+        return !( (a->value.color == b->value.color)
+                 && ((a->value.color.icc == b->value.color.icc)
+                     || (a->value.color.icc && b->value.color.icc
+                         && (a->value.color.icc->colorProfile == b->value.color.icc->colorProfile)
+                         && (a->value.color.icc->colors == b->value.color.icc->colors))));
     /* todo: Allow for epsilon differences in iccColor->colors, e.g. changes small enough not to show up
      * in the string representation. */
-    if (a->type == SP_PAINT_TYPE_PAINTSERVER)
-        return (a->value.href == NULL || b->value.href == NULL || a->value.href->getObject() != b->value.href->getObject());
+    }
+
     return false;
 }
 
@@ -3583,17 +3613,17 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key,
                     css << " ";
                 }
                 char color_buf[8];
-                sp_svg_write_color(color_buf, sizeof(color_buf), sp_color_get_rgba32_ualpha(&paint->value.color, 0));
+                sp_svg_write_color(color_buf, sizeof(color_buf), paint->value.color.toRGBA32( 0 ));
                 css << color_buf;
             }
 
-            if (paint->value.iccColor) {
+            if (paint->value.color.icc) {
                 if ( !css.str().empty() ) {
                     css << " ";
                 }
-                css << "icc-color(" << paint->value.iccColor->colorProfile;
-                for (vector<double>::const_iterator i(paint->value.iccColor->colors.begin()),
-                         iEnd(paint->value.iccColor->colors.end());
+                css << "icc-color(" << paint->value.color.icc->colorProfile;
+                for (vector<double>::const_iterator i(paint->value.color.icc->colors.begin()),
+                         iEnd(paint->value.color.icc->colors.end());
                      i != iEnd; ++i) {
                     css << ", " << *i;
                 }
@@ -3602,7 +3632,7 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key,
         }
 
         if ( !css.str().empty() ) {
-            retval = g_snprintf( b, len, "%s:%s;", key, css.gcharp() );
+            retval = g_snprintf( b, len, "%s:%s;", key, css.str().c_str() );
         }
     }
 
@@ -3672,6 +3702,7 @@ sp_style_write_ifilter(gchar *p, gint const len, gchar const *key,
                          SPIFilter const *const val, SPIFilter const *const base,
                          guint const flags)
 {
+    (void)base; // TODO
     if ((flags & SP_STYLE_FLAG_ALWAYS)
         || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
         || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set))
@@ -3688,18 +3719,18 @@ sp_style_write_ifilter(gchar *p, gint const len, gchar const *key,
 }
 
 
-/**
- * Clear paint object, and disconnect style from paintserver (if present).
- */
-static void
-sp_style_paint_clear(SPStyle *style, SPIPaint *paint)
+void SPIPaint::clear()
 {
-    if (paint->value.href && paint->value.href->getObject())
-        paint->value.href->detach(); 
-
-    paint->type = SP_PAINT_TYPE_NONE;
-    delete paint->value.iccColor;
-    paint->value.iccColor = NULL;
+    set = false;
+    inherit = false;
+    currentcolor = false;
+    colorSet = false;
+    noneSet = false;
+    value.color.set( 0 );
+    if ( value.href && value.href->getObject() )
+    {
+        value.href->detach();
+    }
 }
 
 
@@ -3710,7 +3741,7 @@ static void
 sp_style_filter_clear(SPStyle *style)
 {
     if (style->filter.href && style->filter.href->getObject())
-        style->filter.href->detach(); 
+        style->filter.href->detach();
 }
 
 
@@ -3801,6 +3832,9 @@ sp_style_unset_property_attrs(SPObject *o)
     if (style->stroke_dashoffset_set) {
         repr->setAttribute("stroke-dashoffset", NULL);
     }
+    if (style->text_private && style->text->font_specification.set) {
+        repr->setAttribute("-inkscape-font-specification", NULL);
+    }
     if (style->text_private && style->text->font_family.set) {
         repr->setAttribute("font-family", NULL);
     }
@@ -3860,6 +3894,7 @@ SPCSSAttr *
 sp_css_attr_unset_text(SPCSSAttr *css)
 {
     sp_repr_css_set_property(css, "font", NULL); // not implemented yet
+    sp_repr_css_set_property(css, "-inkscape-font-specification", NULL);
     sp_repr_css_set_property(css, "font-size", NULL);
     sp_repr_css_set_property(css, "font-size-adjust", NULL); // not implemented yet
     sp_repr_css_set_property(css, "font-style", NULL);