diff --git a/src/style.cpp b/src/style.cpp
index a05cef252c1d789d0e0a7b88d813c66c159df1f4..551dd658516b594ea794405040c0aa6427b0d73b 100644 (file)
--- a/src/style.cpp
+++ b/src/style.cpp
-#define __SP_STYLE_C__
-
/** @file
* @brief SVG stylesheets implementation.
*/
#include "svg/svg.h"
#include "svg/svg-color.h"
#include "svg/svg-icc-color.h"
-#include "svg/svg-device-color.h"
#include "display/canvas-bpath.h"
#include "attributes.h"
static void sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str);
static void sp_style_read_itextdecoration(SPITextDecoration *val, gchar const *str);
static void sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document);
-static void sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document);
static void sp_style_read_ifontsize(SPIFontSize *val, gchar const *str);
+static void sp_style_read_ibaselineshift(SPIBaselineShift *val, gchar const *str);
static void sp_style_read_ifilter(gchar const *str, SPStyle *style, SPDocument *document);
static void sp_style_read_penum(SPIEnum *val, Inkscape::XML::Node *repr, gchar const *key, SPStyleEnum const *dict, bool can_explicitly_inherit);
static void sp_style_read_plength(SPILength *val, Inkscape::XML::Node *repr, gchar const *key);
static void sp_style_read_pfontsize(SPIFontSize *val, Inkscape::XML::Node *repr, gchar const *key);
+static void sp_style_read_pbaselineshift(SPIBaselineShift *val, Inkscape::XML::Node *repr, gchar const *key);
static void sp_style_read_pfloat(SPIFloat *val, Inkscape::XML::Node *repr, gchar const *key);
static gint sp_style_write_ifloat(gchar *p, gint len, gchar const *key, SPIFloat const *val, SPIFloat const *base, guint flags);
@@ -102,6 +100,7 @@ static gint sp_style_write_istring(gchar *p, gint len, gchar const *key, SPIStri
static gint sp_style_write_ilength(gchar *p, gint len, gchar const *key, SPILength const *val, SPILength const *base, guint flags);
static gint sp_style_write_ipaint(gchar *b, gint len, gchar const *key, SPIPaint const *paint, SPIPaint const *base, guint flags);
static gint sp_style_write_ifontsize(gchar *p, gint len, gchar const *key, SPIFontSize const *val, SPIFontSize const *base, guint flags);
+static gint sp_style_write_ibaselineshift(gchar *p, gint len, gchar const *key, SPIBaselineShift const *val, SPIBaselineShift const *base, guint flags);
static gint sp_style_write_ilengthornormal(gchar *p, gint const len, gchar const *const key, SPILengthOrNormal const *const val, SPILengthOrNormal const *const base, guint const flags);
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);
#define SPS_READ_IFONTSIZE_IF_UNSET(v,s) if (!(v)->set) {sp_style_read_ifontsize((v), (s));}
#define SPS_READ_PFONTSIZE_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_pfontsize((v), (r), (k));}
+#define SPS_READ_IBASELINE_SHIFT_IF_UNSET(v,s) if (!(v)->set) {sp_style_read_ibaselineshift((v), (s));}
+#define SPS_READ_PBASELINE_SHIFT_IF_UNSET(v,r,k) if (!(v)->set) {sp_style_read_pbaselineshift((v), (r), (k));}
+
static void sp_style_merge_from_object_stylesheet(SPStyle *, SPObject const *);
struct SPStyleEnum {
{NULL, -1}
};
+static SPStyleEnum const enum_baseline_shift[] = {
+ {"baseline", SP_CSS_BASELINE_SHIFT_BASELINE},
+ {"sub", SP_CSS_BASELINE_SHIFT_SUB},
+ {"super", SP_CSS_BASELINE_SHIFT_SUPER},
+ {NULL, -1}
+};
+
static SPStyleEnum const enum_visibility[] = {
{"hidden", SP_CSS_VISIBILITY_HIDDEN},
{"collapse", SP_CSS_VISIBILITY_COLLAPSE},
g_return_val_if_fail(object != NULL, NULL);
g_return_val_if_fail(SP_IS_OBJECT(object), NULL);
- SPStyle *style = sp_style_new(SP_OBJECT_DOCUMENT(object));
+ SPStyle *style = sp_style_new( object->document );
style->object = object;
style->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_style_object_release), style));
- if (object && SP_OBJECT_IS_CLONED(object)) {
+ if (object && object->cloned) {
style->cloned = true;
}
sp_style_clear(style);
- if (object && SP_OBJECT_IS_CLONED(object)) {
+ if (object && object->cloned) {
style->cloned = true;
}
enum_writing_mode, true);
SPS_READ_PENUM_IF_UNSET(&style->text_anchor, repr, "text-anchor",
enum_text_anchor, true);
+ SPS_READ_PBASELINE_SHIFT_IF_UNSET(&style->baseline_shift, repr, "baseline-shift");
/* opacity */
if (!style->opacity.set) {
if (!style->fill.set) {
val = repr->attribute("fill");
if (val) {
- sp_style_read_ipaint(&style->fill, val, style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL);
+ style->fill.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL );
}
}
/* fill-opacity */
if (!style->stroke.set) {
val = repr->attribute("stroke");
if (val) {
- sp_style_read_ipaint(&style->stroke, val, style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL);
+ style->stroke.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL );
}
}
SPS_READ_PLENGTH_IF_UNSET(&style->stroke_width, repr, "stroke-width");
case SP_PROP_TEXT_ANCHOR:
SPS_READ_IENUM_IF_UNSET(&style->text_anchor, val, enum_text_anchor, true);
break;
+ case SP_PROP_BASELINE_SHIFT:
+ SPS_READ_IBASELINE_SHIFT_IF_UNSET(&style->baseline_shift, val);
+ break;
/* Text (unimplemented) */
case SP_PROP_TEXT_RENDERING: {
/* Ignore the hint. */
case SP_PROP_ALIGNMENT_BASELINE:
g_warning("Unimplemented style property SP_PROP_ALIGNMENT_BASELINE: value: %s", val);
break;
- case SP_PROP_BASELINE_SHIFT:
- g_warning("Unimplemented style property SP_PROP_BASELINE_SHIFT: value: %s", val);
- break;
case SP_PROP_DOMINANT_BASELINE:
g_warning("Unimplemented style property SP_PROP_DOMINANT_BASELINE: value: %s", val);
break;
}
case SP_PROP_FILL:
if (!style->fill.set) {
- sp_style_read_ipaint(&style->fill, val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL);
+ style->fill.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL );
}
break;
case SP_PROP_FILL_OPACITY:
case SP_PROP_STROKE:
if (!style->stroke.set) {
- sp_style_read_ipaint(&style->stroke, val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL);
+ style->stroke.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL );
}
break;
case SP_PROP_STROKE_WIDTH:
@@ -1342,6 +1352,50 @@ sp_style_merge_font_size_from_parent(SPIFontSize &child, SPIFontSize const &pare
}
}
+// Some shifts are defined relative to parent.
+static void
+sp_style_merge_baseline_shift_from_parent(SPIBaselineShift &child, SPIBaselineShift const &parent,
+ SPIFontSize const &pfont_size)
+{
+ /* 'baseline-shift' */
+ if (!child.set || child.inherit) {
+ /* Inherit the computed value. Reference: http://www.w3.org/TR/SVG11/styling.html#Inheritance */
+ child.computed = parent.computed; // Does this make sense (applying a shift a second time)?
+ } else if (child.type == SP_BASELINE_SHIFT_LITERAL) {
+ if( child.literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
+ child.computed = 0; // No change
+ } else if (child.literal == SP_CSS_BASELINE_SHIFT_SUB ) {
+ // Should use subscript position from font relative to alphabetic baseline
+ // OpenOffice, Adobe: -0.33, Word -0.14, LaTex about -0.2.
+ child.computed = -0.2 * pfont_size.computed;
+ } else if (child.literal == SP_CSS_BASELINE_SHIFT_SUPER ) {
+ // Should use superscript position from font relative to alphabetic baseline
+ // OpenOffice, Adobe: 0.33, Word 0.35, LaTex about 0.45.
+ child.computed = 0.4 * pfont_size.computed;
+ } else {
+ /* Illegal value */
+ }
+ } else if (child.type == SP_BASELINE_SHIFT_PERCENTAGE) {
+ // Percentage for baseline shift is relative to computed "line-height"
+ // which is just font-size (see SVG1.1 'font').
+ child.computed = pfont_size.computed * child.value;
+ } else if (child.type == SP_BASELINE_SHIFT_LENGTH) {
+ switch (child.unit) {
+ case SP_CSS_UNIT_EM:
+ child.computed = child.value * pfont_size.computed;
+ break;
+ case SP_CSS_UNIT_EX:
+ child.computed = child.value * 0.5 * pfont_size.computed;
+ break;
+ default:
+ /* No change */
+ break;
+ }
+ }
+ // baseline-shifts are relative to parent baseline
+ child.computed += parent.computed;
+}
+
/**
* Sets computed values in \a style, which may involve inheriting from (or in some other way
* calculating from) corresponding computed values of \a parent.
@@ -1483,6 +1537,10 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
style->text_anchor.computed = parent->text_anchor.computed;
}
+ /* Baseline Shift... Some shifts are relative to parent. */
+ sp_style_merge_baseline_shift_from_parent(style->baseline_shift, parent->baseline_shift,
+ parent->font_size);
+
if (style->opacity.inherit) {
style->opacity.value = parent->opacity.value;
}
p += sp_style_write_ienum(p, c + BMAX - p, "writing-mode", enum_writing_mode, &style->writing_mode, NULL, flags);
p += sp_style_write_ienum(p, c + BMAX - p, "text-anchor", enum_text_anchor, &style->text_anchor, NULL, flags);
+ p += sp_style_write_ibaselineshift(p, c + BMAX - p, "baseline-shift", &style->baseline_shift, NULL, flags);
+
/// \todo fixme: Per type methods need default flag too (lauris)
p += sp_style_write_ienum(p, c + BMAX - p, "writing-mode", enum_writing_mode, &from->writing_mode, &to->writing_mode, SP_STYLE_FLAG_IFDIFF);
p += sp_style_write_ienum(p, c + BMAX - p, "text-anchor", enum_text_anchor, &from->text_anchor, &to->text_anchor, SP_STYLE_FLAG_IFDIFF);
+ p += sp_style_write_ibaselineshift(p, c + BMAX - p, "baseline-shift", &from->baseline_shift, &to->baseline_shift, SP_STYLE_FLAG_IFDIFF);
/// \todo fixme: Per type methods need default flag too
if (from->opacity.set && from->opacity.value != SP_SCALE24_MAX) {
style->word_spacing.normal = TRUE;
style->word_spacing.value = style->word_spacing.computed = 0.0;
+ style->baseline_shift.set = FALSE;
+ style->baseline_shift.type = SP_BASELINE_SHIFT_LITERAL;
+ style->baseline_shift.unit = SP_CSS_UNIT_NONE;
+ style->baseline_shift.literal = SP_CSS_BASELINE_SHIFT_BASELINE;
+ style->baseline_shift.value = 0.0;
+ style->baseline_shift.computed = 0.0;
+
style->text_transform.set = FALSE;
style->text_transform.value = style->text_transform.computed = SP_CSS_TEXT_TRANSFORM_NONE;
style->writing_mode.set = FALSE;
style->writing_mode.value = style->writing_mode.computed = SP_CSS_WRITING_MODE_LR_TB;
-
style->text_anchor.set = FALSE;
style->text_anchor.value = style->text_anchor.computed = SP_CSS_TEXT_ANCHOR_START;
@@ -3130,18 +3197,17 @@ sp_style_read_icolor(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
*
* \pre paint == \&style.fill || paint == \&style.stroke.
*/
-static void
-sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocument *document)
+void SPIPaint::read( gchar const *str, SPStyle &style, SPDocument *document )
{
while (g_ascii_isspace(*str)) {
++str;
}
- paint->clear();
+ clear();
if (streq(str, "inherit")) {
- paint->set = TRUE;
- paint->inherit = TRUE;
+ set = TRUE;
+ inherit = TRUE;
} else {
if ( strneq(str, "url", 3) ) {
gchar *uri = extract_uri( str, &str );
@@ -3149,33 +3215,33 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
++str;
}
// TODO check on and comment the comparrison "paint != &style->color".
- if ( uri && *uri && (paint != &style->color) ) {
- paint->set = TRUE;
+ if ( uri && *uri && (this != &style.color) ) {
+ set = TRUE;
// it may be that this style's SPIPaint has not yet created its URIReference;
// now that we have a document, we can create it here
- if (!paint->value.href && document) {
- paint->value.href = new SPPaintServerReference(document);
- paint->value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((paint == &style->fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), style));
+ if (!value.href && document) {
+ value.href = new SPPaintServerReference(document);
+ value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun((this == &style.fill)? sp_style_fill_paint_server_ref_changed : sp_style_stroke_paint_server_ref_changed), &style));
}
// TODO check what this does in light of move away from union
- sp_style_set_ipaint_to_uri_string (style, paint, uri);
+ sp_style_set_ipaint_to_uri_string (&style, this, uri);
}
g_free( uri );
}
- if (streq(str, "currentColor") && paint != &style->color) {
- paint->set = TRUE;
- paint->currentcolor = TRUE;
- } else if (streq(str, "none") && paint != &style->color) {
- paint->set = TRUE;
- paint->noneSet = TRUE;
+ if (streq(str, "currentColor") && (this != &style.color)) {
+ set = TRUE;
+ currentcolor = TRUE;
+ } else if (streq(str, "none") && (this != &style.color)) {
+ set = TRUE;
+ noneSet = TRUE;
} else {
guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
if (rgb0 != 0xff) {
- paint->setColor( rgb0 );
- paint->set = TRUE;
+ setColor( rgb0 );
+ set = TRUE;
while (g_ascii_isspace(*str)) {
++str;
@@ -3186,18 +3252,7 @@ sp_style_read_ipaint(SPIPaint *paint, gchar const *str, SPStyle *style, SPDocume
delete tmp;
tmp = 0;
}
- paint->value.color.icc = tmp;
- }
- if (strneq(str, "device-gray(", 12) ||
- strneq(str, "device-rgb(", 11) ||
- strneq(str, "device-cmyk(", 12) ||
- strneq(str, "device-nchannel(", 16)) {
- SVGDeviceColor* tmp = new SVGDeviceColor();
- if ( ! sp_svg_read_device_color( str, &str, tmp ) ) {
- delete tmp;
- tmp = 0;
- }
- paint->value.color.device = tmp;
+ value.color.icc = tmp;
}
}
}
val->set = TRUE;
val->inherit = TRUE;
} else if ((*str == 'x') || (*str == 's') || (*str == 'm') || (*str == 'l')) {
+ // xx-small, x-small, etc.
for (unsigned i = 0; enum_font_size[i].key; i++) {
if (!strcmp(str, enum_font_size[i].key)) {
val->set = TRUE;
}
+/**
+ * Set SPIBaselineShift object from string.
+ */
+static void
+sp_style_read_ibaselineshift(SPIBaselineShift *val, gchar const *str)
+{
+ if (!strcmp(str, "inherit")) {
+ val->set = TRUE;
+ val->inherit = TRUE;
+ } else if ((*str == 'b') || (*str == 's')) {
+ // baseline or sub or super
+ for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
+ if (!strcmp(str, enum_baseline_shift[i].key)) {
+ val->set = TRUE;
+ val->inherit = FALSE;
+ val->type = SP_BASELINE_SHIFT_LITERAL;
+ val->literal = enum_baseline_shift[i].value;
+ return;
+ }
+ }
+ /* Invalid */
+ return;
+ } else {
+ SPILength length;
+ sp_style_read_ilength(&length, str);
+ val->set = length.set;
+ val->inherit = length.inherit;
+ val->unit = length.unit;
+ val->value = length.value;
+ val->computed = length.computed;
+ if( val->unit == SP_CSS_UNIT_PERCENT ) {
+ val->type = SP_BASELINE_SHIFT_PERCENTAGE;
+ } else {
+ val->type = SP_BASELINE_SHIFT_LENGTH;
+ }
+ return;
+ }
+}
+
/**
* Set SPIFilter object from string.
@@ -3368,6 +3463,19 @@ sp_style_read_pfontsize(SPIFontSize *val, Inkscape::XML::Node *repr, gchar const
}
+/**
+ * Set SPIBaselineShift object from repr attribute.
+ */
+static void
+sp_style_read_pbaselineshift(SPIBaselineShift *val, Inkscape::XML::Node *repr, gchar const *key)
+{
+ gchar const *str = repr->attribute(key);
+ if (str) {
+ sp_style_read_ibaselineshift(val, str);
+ }
+}
+
+
/**
* Set SPIFloat object from repr attribute.
*/
}
+/*
+ * baseline-shift is relative to parent. The only time it should
+ * not be written out is if it is zero (or not set).
+ */
+static bool
+sp_baseline_shift_notzero(SPIBaselineShift const *const a )
+{
+ if( a->type == SP_BASELINE_SHIFT_LITERAL ) {
+ if( a->literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
+ return false;
+ }
+ } else {
+ if( a->value == 0.0 ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Write SPIBaselineShift object into string.
+ */
+static gint
+sp_style_write_ibaselineshift(gchar *p, gint const len, gchar const *key,
+ SPIBaselineShift const *const val, SPIBaselineShift const *const base,
+ guint const flags)
+{
+ if ((flags & SP_STYLE_FLAG_ALWAYS)
+ || ((flags & SP_STYLE_FLAG_IFSET) && val->set)
+ || ((flags & SP_STYLE_FLAG_IFDIFF) && val->set
+ && (!base->set || sp_baseline_shift_notzero(val) )))
+ {
+ if (val->inherit) {
+ return g_snprintf(p, len, "%s:inherit;", key);
+ } else if (val->type == SP_BASELINE_SHIFT_LITERAL) {
+ for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
+ if (enum_baseline_shift[i].value == static_cast< gint > (val->literal) ) {
+ return g_snprintf(p, len, "%s:%s;", key, enum_baseline_shift[i].key);
+ }
+ }
+ } else if (val->type == SP_BASELINE_SHIFT_LENGTH) {
+ if( val->unit == SP_CSS_UNIT_EM || val->unit == SP_CSS_UNIT_EX ) {
+ Inkscape::CSSOStringStream os;
+ os << key << ":" << val->value << (val->unit == SP_CSS_UNIT_EM ? "em;" : "ex;");
+ return g_strlcpy(p, os.str().c_str(), len);
+ } else {
+ Inkscape::CSSOStringStream os;
+ os << key << ":" << val->computed << "px;"; // must specify px, see inkscape bug 1221626, mozilla bug 234789
+ return g_strlcpy(p, os.str().c_str(), len);
+ }
+ } else if (val->type == SP_BASELINE_SHIFT_PERCENTAGE) {
+ Inkscape::CSSOStringStream os;
+ os << key << ":" << (val->value * 100.0) << "%;";
+ return g_strlcpy(p, os.str().c_str(), len);
+ }
+ }
+ return 0;
+}
+
+
+
/**
* Write SPIFilter object into string.
*/
return 0;
}
+SPIPaint::SPIPaint() :
+ set(0),
+ inherit(0),
+ currentcolor(0),
+ colorSet(0),
+ noneSet(0),
+ value()
+{
+ value.color.set( 0 );
+ value.href = 0;
+}
void SPIPaint::clear()
{
sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet
sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet
- sp_repr_css_set_property(css, "baseline-shift", NULL); // not implemented yet
+ sp_repr_css_set_property(css, "baseline-shift", NULL);
return css;
}
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :