summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2014-02-19 10:48:41 +0000
committerJabiertxof <jtx@jtx.marker.es>2014-02-19 10:48:41 +0000
commitf15ac06ffd9cc8dbb098b18a6b273b32fc904fc9 (patch)
tree482bc967d7e637d3f8817aa2074362a461465603 /src
parentupdate to trunk (diff)
parentAdd SVG2 property 'paint-order'. (diff)
downloadinkscape-f15ac06ffd9cc8dbb098b18a6b273b32fc904fc9.tar.gz
inkscape-f15ac06ffd9cc8dbb098b18a6b273b32fc904fc9.zip
update to trunk
(bzr r11950.1.254)
Diffstat (limited to 'src')
-rw-r--r--src/attributes.cpp1
-rw-r--r--src/attributes.h1
-rw-r--r--src/display/drawing-shape.cpp132
-rw-r--r--src/display/drawing-shape.h7
-rw-r--r--src/display/drawing-text.cpp19
-rw-r--r--src/display/nr-style.cpp26
-rw-r--r--src/display/nr-style.h12
-rw-r--r--src/extension/internal/cairo-render-context.cpp23
-rw-r--r--src/extension/internal/gdkpixbuf-input.cpp22
-rw-r--r--src/extension/internal/pdfinput/svg-builder.cpp4
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp46
-rw-r--r--src/marker.cpp2
-rw-r--r--src/sp-symbol.cpp4
-rw-r--r--src/style.cpp199
-rw-r--r--src/style.h19
-rw-r--r--src/ui/dialog/document-properties.cpp11
-rw-r--r--src/ui/dialog/ocaldialogs.cpp5
-rw-r--r--src/ui/tools/spray-tool.cpp24
18 files changed, 465 insertions, 92 deletions
diff --git a/src/attributes.cpp b/src/attributes.cpp
index 40e11b023..ee2a80fd3 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -473,6 +473,7 @@ static SPStyleProp const props[] = {
{SP_PROP_MARKER_END, "marker-end"},
{SP_PROP_MARKER_MID, "marker-mid"},
{SP_PROP_MARKER_START, "marker-start"},
+ {SP_PROP_PAINT_ORDER, "paint-order" },
{SP_PROP_SHAPE_RENDERING, "shape-rendering"},
{SP_PROP_STROKE, "stroke"},
{SP_PROP_STROKE_DASHARRAY, "stroke-dasharray"},
diff --git a/src/attributes.h b/src/attributes.h
index ecf7ce966..b8843fcb7 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -474,6 +474,7 @@ enum SPAttributeEnum {
SP_PROP_MARKER_END,
SP_PROP_MARKER_MID,
SP_PROP_MARKER_START,
+ SP_PROP_PAINT_ORDER, /* SVG2 */
SP_PROP_SHAPE_RENDERING,
SP_PROP_STROKE,
SP_PROP_STROKE_DASHARRAY,
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
index f99f9442f..92d71fad3 100644
--- a/src/display/drawing-shape.cpp
+++ b/src/display/drawing-shape.cpp
@@ -149,6 +149,51 @@ DrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, u
return STATE_ALL;
}
+#ifdef WITH_SVG2
+void
+DrawingShape::_renderFill(DrawingContext &dc)
+{
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+
+ if( has_fill ) {
+ dc.path(_curve->get_pathvector());
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ dc.newPath(); // clear path
+ }
+}
+
+void
+DrawingShape::_renderStroke(DrawingContext &dc)
+{
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if( has_stroke ) {
+ // TODO: remove segments outside of bbox when no dashes present
+ dc.path(_curve->get_pathvector());
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ dc.newPath(); // clear path
+ }
+}
+#endif
+
+void
+DrawingShape::_renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ // marker rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(dc, area, flags, stop_at);
+ }
+}
+
unsigned
DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
{
@@ -160,6 +205,7 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
if (outline) {
guint32 rgba = _drawing.outlinecolor;
+ // paint-order doesn't matter
{ Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
dc.path(_curve->get_pathvector());
@@ -170,39 +216,67 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
dc.setTolerance(0.5);
dc.stroke();
}
- } else {
- bool has_stroke, has_fill;
- // we assume the context has no path
- Inkscape::DrawingContext::Save save(dc);
- dc.transform(_ctm);
-
- // update fill and stroke paints.
- // this cannot be done during nr_arena_shape_update, because we need a Cairo context
- // to render svg:pattern
- has_fill = _nrstyle.prepareFill(dc, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
- has_stroke &= (_nrstyle.stroke_width != 0);
-
- if (has_fill || has_stroke) {
- // TODO: remove segments outside of bbox when no dashes present
- dc.path(_curve->get_pathvector());
- if (has_fill) {
- _nrstyle.applyFill(dc);
- dc.fillPreserve();
- }
- if (has_stroke) {
- _nrstyle.applyStroke(dc);
- dc.strokePreserve();
- }
- dc.newPath(); // clear path
- } // has fill or stroke pattern
+
+ _renderMarkers(dc, area, flags, stop_at);
+ return RENDER_OK;
+
}
- // marker rendering
- for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- i->render(dc, area, flags, stop_at);
+#ifdef WITH_SVG2
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ) {
+ // This is the most common case, special case so we don't call get_pathvector(), etc. twice
+#endif
+ {
+ // we assume the context has no path
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ // update fill and stroke paints.
+ // this cannot be done during nr_arena_shape_update, because we need a Cairo context
+ // to render svg:pattern
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if (has_fill || has_stroke) {
+ // TODO: remove segments outside of bbox when no dashes present
+ dc.path(_curve->get_pathvector());
+ if (has_fill) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ }
+ dc.newPath(); // clear path
+ } // has fill or stroke pattern
+ }
+ _renderMarkers(dc, area, flags, stop_at);
+ return RENDER_OK;
+
+#ifdef WITH_SVG2
+ }
+
+ // Handle different paint orders
+ for (unsigned i = 0; i < NRStyle::PAINT_ORDER_LAYERS; ++i) {
+ switch (_nrstyle.paint_order_layer[i]) {
+ case NRStyle::PAINT_ORDER_FILL:
+ _renderFill(dc);
+ break;
+ case NRStyle::PAINT_ORDER_STROKE:
+ _renderStroke(dc);
+ break;
+ case NRStyle::PAINT_ORDER_MARKER:
+ _renderMarkers(dc, area, flags, stop_at);
+ break;
+ default:
+ // PAINT_ORDER_AUTO Should not happen
+ break;
+ }
}
return RENDER_OK;
+#endif
}
void DrawingShape::_clipItem(DrawingContext &dc, Geom::IntRect const & /*area*/)
diff --git a/src/display/drawing-shape.h b/src/display/drawing-shape.h
index 47b9e807e..405c789e0 100644
--- a/src/display/drawing-shape.h
+++ b/src/display/drawing-shape.h
@@ -39,6 +39,13 @@ protected:
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
+#ifdef WITH_SVG2
+ void _renderFill(DrawingContext &dc);
+ void _renderStroke(DrawingContext &dc);
+#endif
+ void _renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+
SPCurve *_curve;
SPStyle *_style;
NRStyle _nrstyle;
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index f5a0f0af5..a280e221a 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -450,7 +450,20 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are
// we need to apply this object's ctm again
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
+
+#ifdef WITH_SVG2
+ // Text doesn't have markers, we can do paint-order quick and dirty.
+ bool fill_first = false;
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
+ _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
+ _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
+ fill_first = true;
+ } // Won't get "stroke fill stroke" but that isn't 'valid'
+
+ if (has_fill && fill_first) {
+#else
if (has_fill) {
+#endif
_nrstyle.applyFill(dc);
dc.fillPreserve();
}
@@ -458,6 +471,12 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are
_nrstyle.applyStroke(dc);
dc.strokePreserve();
}
+#ifdef WITH_SVG2
+ if (has_fill && !fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+#endif
dc.newPath(); // clear path
// draw text decoration
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index 403b139e0..570ccd31e 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -68,7 +68,11 @@ NRStyle::NRStyle()
, line_through_thickness(0)
, line_through_position(0)
, font_size(0)
-{}
+{
+#ifdef WITH_SVG2
+ paint_order_layer[0] = PAINT_ORDER_NORMAL;
+#endif
+}
NRStyle::~NRStyle()
{
@@ -160,6 +164,26 @@ void NRStyle::set(SPStyle *style)
dash = NULL;
}
+
+#ifdef WITH_SVG2
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
+ switch (style->paint_order.layer[i]) {
+ case SP_CSS_PAINT_ORDER_NORMAL:
+ paint_order_layer[i]=PAINT_ORDER_NORMAL;
+ break;
+ case SP_CSS_PAINT_ORDER_FILL:
+ paint_order_layer[i]=PAINT_ORDER_FILL;
+ break;
+ case SP_CSS_PAINT_ORDER_STROKE:
+ paint_order_layer[i]=PAINT_ORDER_STROKE;
+ break;
+ case SP_CSS_PAINT_ORDER_MARKER:
+ paint_order_layer[i]=PAINT_ORDER_MARKER;
+ break;
+ }
+ }
+#endif
+
text_decoration_line = TEXT_DECORATION_LINE_CLEAR;
if(style->text_decoration_line.inherit ){ text_decoration_line |= TEXT_DECORATION_LINE_INHERIT; }
if(style->text_decoration_line.underline ){ text_decoration_line |= TEXT_DECORATION_LINE_UNDERLINE + TEXT_DECORATION_LINE_SET; }
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index e54eef547..717cda899 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -68,6 +68,18 @@ struct NRStyle {
cairo_pattern_t *fill_pattern;
cairo_pattern_t *stroke_pattern;
+#ifdef WITH_SVG2
+ enum PaintOrderType {
+ PAINT_ORDER_NORMAL,
+ PAINT_ORDER_FILL,
+ PAINT_ORDER_STROKE,
+ PAINT_ORDER_MARKER
+ };
+
+ static const size_t PAINT_ORDER_LAYERS = 3;
+ PaintOrderType paint_order_layer[PAINT_ORDER_LAYERS];
+#endif
+
#define TEXT_DECORATION_LINE_CLEAR 0x00
#define TEXT_DECORATION_LINE_SET 0x01
#define TEXT_DECORATION_LINE_INHERIT 0x02
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 47de62ac0..2916d9fa9 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -1433,7 +1433,7 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
}
bool CairoRenderContext::renderImage(Inkscape::Pixbuf *pb,
- Geom::Affine const &image_transform, SPStyle const * /*style*/)
+ Geom::Affine const &image_transform, SPStyle const *style)
{
g_assert( _is_valid );
@@ -1468,6 +1468,27 @@ bool CairoRenderContext::renderImage(Inkscape::Pixbuf *pb,
cairo_rectangle(_cr, 0, 0, w, h);
cairo_clip(_cr);
}
+
+ // Cairo filter method will be mapped to PS/PDF 'interpolate' true/false).
+ // See cairo-pdf-surface.c
+ if (style) {
+ // See: http://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty
+ // http://www.w3.org/TR/css4-images/#the-image-rendering
+ // style.h/style.cpp
+ switch (style->image_rendering.computed) {
+ case SP_CSS_COLOR_RENDERING_AUTO:
+ // Do nothing
+ break;
+ case SP_CSS_COLOR_RENDERING_OPTIMIZEQUALITY:
+ cairo_pattern_set_filter(cairo_get_source(_cr), CAIRO_FILTER_BEST );
+ break;
+ case SP_CSS_COLOR_RENDERING_OPTIMIZESPEED:
+ default:
+ cairo_pattern_set_filter(cairo_get_source(_cr), CAIRO_FILTER_NEAREST );
+ break;
+ }
+ }
+
cairo_paint_with_alpha(_cr, opacity);
cairo_restore(_cr);
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp
index ec04b1dad..a384c7bde 100644
--- a/src/extension/internal/gdkpixbuf-input.cpp
+++ b/src/extension/internal/gdkpixbuf-input.cpp
@@ -30,22 +30,31 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool ask = prefs->getBool("/dialogs/import/ask");
Glib::ustring link = prefs->getString("/dialogs/import/link");
+ bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi");
Glib::ustring scale = prefs->getString("/dialogs/import/scale");
// std::cout << "GkdpixbufInput::open: "
// << " ask: " << ask
// << ", link: " << link
+ // << ", forcexdpi: " << forcexdpi
// << ", scale: " << scale << std::endl;
// std::cout << " in preferences: "
// << " ask: " << !mod->get_param_bool("do_not_ask")
// << ", link: " << mod->get_param_optiongroup("link")
+ // << ", mod_dpi: " << mod->get_param_optiongroup("dpi")
// << ", scale: " << mod->get_param_optiongroup("scale") << std::endl;
if( ask ) {
Glib::ustring mod_link = mod->get_param_optiongroup("link");
+ Glib::ustring mod_dpi = mod->get_param_optiongroup("dpi");
+ bool mod_forcexdpi = ( mod_dpi.compare( "from_default" ) == 0 );
Glib::ustring mod_scale = mod->get_param_optiongroup("scale");
if( link.compare( mod_link ) != 0 ) {
link = mod_link;
}
prefs->setString("/dialogs/import/link", link );
+ if( forcexdpi != mod_forcexdpi ) {
+ forcexdpi = mod_forcexdpi;
+ }
+ prefs->setBool("/dialogs/import/forcexdpi", forcexdpi );
if( scale.compare( mod_scale ) != 0 ) {
scale = mod_scale;
}
@@ -68,7 +77,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
double width = pb->width();
double height = pb->height();
double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px"));
- bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi");
+ //bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi");
ImageResolution *ir = 0;
double xscale = 1;
double yscale = 1;
@@ -179,18 +188,21 @@ GdkpixbufInput::init(void)
"<name>%s</name>\n"
"<id>org.inkscape.input.gdkpixbuf.%s</id>\n"
- "<param name='link' type='optiongroup' appearance='full' _gui-text='" N_("Link or embed image:") "' >\n"
+ "<param name='link' type='optiongroup' appearance='full' _gui-text='" N_("Image Import Type:") "' _gui-description='" N_("Embed results in stand-alone, larger SVG files. Link references a file outside this SVG document and all files must be moved together.") "' >\n"
"<_option value='embed' >" N_("Embed") "</_option>\n"
"<_option value='link' >" N_("Link") "</_option>\n"
"</param>\n"
- "<_param name='help' type='description'>" N_("Embed results in stand-alone, larger SVG files. Link references a file outside this SVG document and all files must be moved together.") "</_param>\n"
- "<param name='scale' type='optiongroup' appearance='full' _gui-text='" N_("Scale image preference (image-rendering):") "' >\n"
+ "<param name='dpi' type='optiongroup' appearance='full' _gui-text='" N_("Image DPI:") "' _gui-description='" N_("Take information from file or use default bitmap import resolution as defined in the preferences.") "' >\n"
+ "<_option value='from_file' >" N_("From file") "</_option>\n"
+ "<_option value='from_default' >" N_("Default import resolution") "</_option>\n"
+ "</param>\n"
+
+ "<param name='scale' type='optiongroup' appearance='full' _gui-text='" N_("Image Rendering Mode:") "' _gui-description='" N_("When an image is upscaled, apply smoothing or keep blocky (pixelated). (Will not work in all browsers.)") "' >\n"
"<_option value='auto' >" N_("None (auto)") "</_option>\n"
"<_option value='optimizeQuality' >" N_("Smooth (optimizeQuality)") "</_option>\n"
"<_option value='optimizeSpeed' >" N_("Blocky (optimizeSpeed)") "</_option>\n"
"</param>\n"
- "<_param name='help' type='description'>" N_("When an image is upscaled, apply smoothing or keep blocky (pixelated). (Will not work in all browsers.)") "</_param>\n"
"<param name=\"do_not_ask\" _gui-description='" N_("Hide the dialog next time and always apply the same actions.") "' gui-text=\"" N_("Don't ask again") "\" type=\"boolean\" >false</param>\n"
"<input>\n"
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index b3f15bbff..20cd74cdb 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -1657,6 +1657,10 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height
Inkscape::XML::Node *image_node = _xml_doc->createElement("svg:image");
sp_repr_set_svg_double(image_node, "width", 1);
sp_repr_set_svg_double(image_node, "height", 1);
+
+ // PS/PDF images are placed via a transformation matrix, no preserveAspectRatio used
+ image_node->setAttribute("preserveAspectRatio", "none");
+
// Set transformation
svgSetTransform(image_node, 1.0, 0.0, 0.0, -1.0, 0.0, 1.0);
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 149f600b7..77534e706 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -538,17 +538,10 @@ Glib::ustring Layout::getFontFamily(unsigned span_index) const
Glib::ustring Layout::dumpAsText() const
{
Glib::ustring result;
- char line[256];
-
Glib::ustring::const_iterator icc;
+ char line[256];
- snprintf(line, sizeof(line), "spans %zu\n", _spans.size());
- result += line;
- snprintf(line, sizeof(line), "chars %zu\n", _characters.size());
- result += line;
- snprintf(line, sizeof(line), "glyphs %zu\n", _glyphs.size());
- result += line;
-
+ result = Glib::ustring::compose("spans %1\nchars %2\nglyphs %3\n", _spans.size(), _characters.size(), _glyphs.size());
if(_characters.size() > 1){
unsigned lastspan=5000;
for(unsigned j = 0; j < _characters.size() ; j++){
@@ -570,32 +563,23 @@ Glib::ustring Layout::dumpAsText() const
}
for (unsigned span_index = 0 ; span_index < _spans.size() ; span_index++) {
- snprintf(line, sizeof(line), "==== span %u \n", span_index);
- result += line;
- snprintf(line, sizeof(line), " in para %d (direction=%s)\n", _lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph,
- direction_to_text(_paragraphs[_lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph].base_direction));
- result += line;
- snprintf(line, sizeof(line), " in source %d (type=%d, cookie=%p)\n", _spans[span_index].in_input_stream_item,
+ result += Glib::ustring::compose("==== span %1 \n", span_index)
+ + Glib::ustring::compose(" in para %1 (direction=%2)\n", _lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph,
+ direction_to_text(_paragraphs[_lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph].base_direction))
+ + Glib::ustring::compose(" in source %1 (type=%2, cookie=%3)\n", _spans[span_index].in_input_stream_item,
_input_stream[_spans[span_index].in_input_stream_item]->Type(),
- _input_stream[_spans[span_index].in_input_stream_item]->source_cookie);
- result += line;
- snprintf(line, sizeof(line), " in line %d (baseline=%f, shape=%d)\n", _chunks[_spans[span_index].in_chunk].in_line,
+ _input_stream[_spans[span_index].in_input_stream_item]->source_cookie)
+ + Glib::ustring::compose(" in line %1 (baseline=%2, shape=%3)\n", _chunks[_spans[span_index].in_chunk].in_line,
_lines[_chunks[_spans[span_index].in_chunk].in_line].baseline_y,
- _lines[_chunks[_spans[span_index].in_chunk].in_line].in_shape);
- result += line;
- snprintf(line, sizeof(line), " in chunk %d (x=%f, baselineshift=%f)\n", _spans[span_index].in_chunk, _chunks[_spans[span_index].in_chunk].left_x, _spans[span_index].baseline_shift);
- result += line;
+ _lines[_chunks[_spans[span_index].in_chunk].in_line].in_shape)
+ + Glib::ustring::compose(" in chunk %1 (x=%2, baselineshift=%3)\n", _spans[span_index].in_chunk, _chunks[_spans[span_index].in_chunk].left_x, _spans[span_index].baseline_shift);
if (_spans[span_index].font) {
- snprintf(line, sizeof(line), " font '%s' %f %s %s\n", sp_font_description_get_family(_spans[span_index].font->descr), _spans[span_index].font_size, style_to_text(pango_font_description_get_style(_spans[span_index].font->descr)), weight_to_text(pango_font_description_get_weight(_spans[span_index].font->descr)));
- result += line;
+ result += Glib::ustring::compose(" font '%1' %2 %3 %4\n", sp_font_description_get_family(_spans[span_index].font->descr), _spans[span_index].font_size, style_to_text(pango_font_description_get_style(_spans[span_index].font->descr)), weight_to_text(pango_font_description_get_weight(_spans[span_index].font->descr)));
}
- snprintf(line, sizeof(line), " x_start = %f, x_end = %f\n", _spans[span_index].x_start, _spans[span_index].x_end);
- result += line;
- snprintf(line, sizeof(line), " line height: ascent %f, descent %f leading %f\n", _spans[span_index].line_height.ascent, _spans[span_index].line_height.descent, _spans[span_index].line_height.leading);
- result += line;
- snprintf(line, sizeof(line), " direction %s, block-progression %s\n", direction_to_text(_spans[span_index].direction), direction_to_text(_spans[span_index].block_progression));
- result += line;
- result += " ** characters:\n";
+ result += Glib::ustring::compose(" x_start = %1, x_end = %2\n", _spans[span_index].x_start, _spans[span_index].x_end)
+ + Glib::ustring::compose(" line height: ascent %1, descent %2 leading %3\n", _spans[span_index].line_height.ascent, _spans[span_index].line_height.descent, _spans[span_index].line_height.leading)
+ + Glib::ustring::compose(" direction %1, block-progression %2\n", direction_to_text(_spans[span_index].direction), direction_to_text(_spans[span_index].block_progression))
+ + " ** characters:\n";
Glib::ustring::const_iterator iter_char = _spans[span_index].input_stream_first_character;
// very inefficent code. what the hell, it's only debug stuff.
for (unsigned char_index = 0 ; char_index < _characters.size() ; char_index++) {
diff --git a/src/marker.cpp b/src/marker.cpp
index 900f8a2ca..fb7b0fd21 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -282,7 +282,7 @@ Inkscape::XML::Node* SPMarker::write(Inkscape::XML::Document *xml_doc, Inkscape:
return repr;
}
-Inkscape::DrawingItem* SPMarker::show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) {
+Inkscape::DrawingItem* SPMarker::show(Inkscape::Drawing &/*drawing*/, unsigned int /*key*/, unsigned int /*flags*/) {
// Markers in tree are never shown directly even if outside of <defs>.
return 0;
}
diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp
index 817411a32..3156680b3 100644
--- a/src/sp-symbol.cpp
+++ b/src/sp-symbol.cpp
@@ -57,13 +57,13 @@ void SPSymbol::set(unsigned int key, const gchar* value) {
switch (key) {
case SP_ATTR_VIEWBOX:
set_viewBox( value );
- std::cout << "Symbol: ViewBox: " << viewBox << std::endl;
+ // std::cout << "Symbol: ViewBox: " << viewBox << std::endl;
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
break;
case SP_ATTR_PRESERVEASPECTRATIO:
set_preserveAspectRatio( value );
- std::cout << "Symbol: Preserve aspect ratio: " << aspect_align << ", " << aspect_clip << std::endl;
+ // std::cout << "Symbol: Preserve aspect ratio: " << aspect_align << ", " << aspect_clip << std::endl;
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG);
break;
diff --git a/src/style.cpp b/src/style.cpp
index bb5603f1c..7ad9749f0 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -90,6 +90,8 @@ static void sp_style_read_istring(SPIString *val, gchar const *str);
static void sp_style_read_ilength(SPILength *val, gchar const *str);
static void sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str);
+static void sp_style_read_ipaintorder(SPIPaintOrder *val, gchar const *str);
+
static void sp_style_read_itextdecoration(SPITextDecorationLine *line, SPITextDecorationStyle *style, SPIPaint *color, gchar const *str);
static void sp_style_read_itextdecorationLine(SPITextDecorationLine *line, gchar const *str);
static void sp_style_read_itextdecorationStyle(SPITextDecorationStyle *style, gchar const *str);
@@ -112,6 +114,8 @@ static gint sp_style_write_ienum(gchar *p, gint len, gchar const *key, SPStyleEn
static gint sp_style_write_istring(gchar *p, gint len, gchar const *key, SPIString const *val, SPIString const *base, guint flags);
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_ipaintorder(gchar *p, gint len, gchar const *key, SPIPaintOrder const *paint_order, SPIPaintOrder 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);
@@ -666,6 +670,8 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
}
/* 2. Presentation attributes */
+ /* Attributes are only read in if not already set in a style sheet or style attribute above. */
+
/* CSS2 */
SPS_READ_PENUM_IF_UNSET(&style->visibility, repr, "visibility", enum_visibility, true);
SPS_READ_PENUM_IF_UNSET(&style->display, repr, "display", enum_display, true);
@@ -819,6 +825,16 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
}
}
+ /* paint-order */
+ if (!style->paint_order.set) {
+ val = repr->attribute("paint-order");
+ if (val) {
+ sp_style_read_ipaintorder(&style->paint_order, val);
+ } else {
+ style->paint_order.layer[0] = SP_CSS_PAINT_ORDER_NORMAL;
+ }
+ }
+
/* -inkscape-font-specification */
if (!style->text_private || !style->text->font_specification.set) {
val = repr->attribute("-inkscape-font-specification");
@@ -1435,6 +1451,11 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
sp_style_read_iscale24(&style->stroke_opacity, val);
}
break;
+ case SP_PROP_PAINT_ORDER:
+ if (!style->paint_order.set) {
+ sp_style_read_ipaintorder(&style->paint_order, val);
+ }
+ break;
default:
g_warning("Invalid style property id: %d value: %s", id, val);
@@ -1889,6 +1910,15 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
style->stroke_opacity.value = parent->stroke_opacity.value;
}
+ if (!style->paint_order.set || style->paint_order.inherit) {
+ g_free(style->paint_order.value);
+ style->paint_order.value = g_strdup(parent->paint_order.value);
+ for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
+ style->paint_order.layer[i] = parent->paint_order.layer[i];
+ style->paint_order.layer_set[i] = parent->paint_order.layer_set[i];
+ }
+ }
+
if (style->text && parent->text) {
if (!style->text->font_family.set || style->text->font_family.inherit) {
g_free(style->text->font_family.value);
@@ -2802,6 +2832,12 @@ sp_style_write_string(SPStyle const *const style, guint const flags)
}
}
+ if (style->paint_order.set) {
+ p += sp_style_write_ipaintorder(p, c + BMAX - p, "paint-order", &style->paint_order, NULL, flags);
+ } else if (flags == SP_STYLE_FLAG_ALWAYS) {
+ p += g_snprintf(p, c + BMAX - p, "paint-order:normal;");
+ }
+
bool marker_none = false;
gchar *master = style->marker[SP_MARKER_LOC].value;
if (style->marker[SP_MARKER_LOC].set) {
@@ -2974,6 +3010,11 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to)
p += sp_style_write_iscale24(p, c + BMAX - p, "stroke-opacity", &from->stroke_opacity, &to->stroke_opacity, SP_STYLE_FLAG_IFDIFF);
}
+ /* paint-order */
+ if( from->paint_order.set) {
+ p += sp_style_write_ipaintorder(p, c + BMAX - p, "paint-order", &from->paint_order, &to->paint_order, SP_STYLE_FLAG_IFDIFF);
+ }
+
/* markers */
gchar *master = from->marker[SP_MARKER_LOC].value;
if (master != NULL) {
@@ -3277,6 +3318,15 @@ sp_style_clear(SPStyle *style)
style->marker[i].value = NULL;
}
+ /* SVG 2 */
+ style->paint_order.set = FALSE;
+ style->paint_order.inherit = FALSE; // For now
+ for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
+ style->paint_order.layer[i] = SP_CSS_PAINT_ORDER_NORMAL;
+ style->paint_order.layer_set[i] = false;
+ }
+ style->paint_order.value = NULL;
+
style->filter.set = FALSE;
style->filter.inherit = FALSE;
style->filter.href = NULL;
@@ -3645,6 +3695,77 @@ sp_style_read_ilengthornormal(SPILengthOrNormal *val, gchar const *str)
}
/**
+ * Set SPIPaintOrder object from string.
+ */
+static void
+sp_style_read_ipaintorder(SPIPaintOrder *val, gchar const *str)
+{
+ g_free(val->value);
+
+ if (!strcmp(str, "inherit")) {
+ // NEED TO CHECK FINAL SPEC
+ val->set = TRUE;
+ val->inherit = TRUE;
+ val->value = NULL;
+ } else {
+ val->set = TRUE;
+ val->inherit = FALSE;
+ val->value = g_strdup(str);
+
+ if (!strcmp(str, "normal")) {
+ val->layer[0] = SP_CSS_PAINT_ORDER_NORMAL;
+ val->layer_set[0] = true;
+ } else {
+ // This certainly can be done more efficiently
+ gchar** c = g_strsplit(str, " ", PAINT_ORDER_LAYERS + 1);
+ bool used[3] = {false, false, false};
+ unsigned int i = 0;
+ for( ; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( c[i] ) {
+ val->layer_set[i] = false;
+ if( !strcmp( c[i], "fill")) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_FILL;
+ val->layer_set[i] = true;
+ used[0] = true;
+ } else if( !strcmp( c[i], "stroke")) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_STROKE;
+ val->layer_set[i] = true;
+ used[1] = true;
+ } else if( !strcmp( c[i], "marker")) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_MARKER;
+ val->layer_set[i] = true;
+ used[2] = true;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ g_strfreev(c);
+
+ // Fill out rest of the layers using the default order
+ if( !used[0] && i < PAINT_ORDER_LAYERS ) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_FILL;
+ val->layer_set[i] = false;
+ ++i;
+ }
+ if( !used[1] && i < PAINT_ORDER_LAYERS ) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_STROKE;
+ val->layer_set[i] = false;
+ ++i;
+ }
+ if( !used[2] && i < PAINT_ORDER_LAYERS ) {
+ val->layer[i] = SP_CSS_PAINT_ORDER_MARKER;
+ val->layer_set[i] = false;
+ }
+ }
+ }
+}
+
+
+
+/**
* Set SPITextDecoration object from string.
*/
static void
@@ -4557,6 +4678,81 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key,
*
*/
static bool
+sp_paint_order_differ(SPIPaintOrder const *const a, SPIPaintOrder const *const b)
+{
+ if( (a->set != b->set) ||
+ (a->inherit!= b->inherit) ) {
+ return true;
+ }
+
+ // Check this works when paint-order value is 'normal'
+ for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( (a->layer[i] != b->layer[i]) ||
+ (a->layer_set[i] != b->layer_set[i]) ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+/**
+ * Write SPIPaintOrder object into string.
+ */
+static gint
+sp_style_write_ipaintorder(gchar *p, gint len, gchar const *key, SPIPaintOrder const *paint_order, SPIPaintOrder const *base, guint flags)
+{
+ int retval = 0;
+
+ if ((flags & SP_STYLE_FLAG_ALWAYS)
+ || ((flags & SP_STYLE_FLAG_IFSET) && paint_order->set)
+ || ((flags & SP_STYLE_FLAG_IFDIFF) && paint_order->set
+ && (!base->set || sp_paint_order_differ(paint_order, base))))
+ {
+ CSSOStringStream css;
+
+ if (paint_order->inherit) {
+ css << "inherit";
+ } else {
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
+ if( paint_order->layer_set[i] == true ) {
+ switch (paint_order->layer[i]) {
+ case SP_CSS_PAINT_ORDER_NORMAL:
+ css << "normal";
+ assert( i == 0 );
+ break;
+ case SP_CSS_PAINT_ORDER_FILL:
+ if (i!=0) css << " ";
+ css << "fill";
+ break;
+ case SP_CSS_PAINT_ORDER_STROKE:
+ if (i!=0) css << " ";
+ css << "stroke";
+ break;
+ case SP_CSS_PAINT_ORDER_MARKER:
+ if (i!=0) css << " ";
+ css << "marker";
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ if ( !css.str().empty() ) {
+ retval = g_snprintf( p, len, "%s:%s;", key, css.str().c_str() );
+ }
+ }
+
+ return retval;
+}
+
+/**
+ *
+ */
+static bool
sp_fontsize_differ(SPIFontSize const *const a, SPIFontSize const *const b)
{
if (a->type != b->type)
@@ -4842,6 +5038,9 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->stroke_dashoffset_set) {
repr->setAttribute("stroke-dashoffset", NULL);
}
+ if (style->paint_order.set) {
+ repr->setAttribute("paint-order", NULL);
+ }
if (style->text_private && style->text->font_specification.set) {
repr->setAttribute("-inkscape-font-specification", NULL);
}
diff --git a/src/style.h b/src/style.h
index 014d2b72f..7366c2a24 100644
--- a/src/style.h
+++ b/src/style.h
@@ -173,6 +173,23 @@ struct SPIFilter {
SPFilterReference *href;
};
+// SVG 2
+enum SPPaintOrderLayer {
+ SP_CSS_PAINT_ORDER_NORMAL,
+ SP_CSS_PAINT_ORDER_FILL,
+ SP_CSS_PAINT_ORDER_STROKE,
+ SP_CSS_PAINT_ORDER_MARKER
+};
+
+const size_t PAINT_ORDER_LAYERS = 3;
+struct SPIPaintOrder {
+ unsigned set : 1;
+ unsigned inherit : 1;
+ SPPaintOrderLayer layer[PAINT_ORDER_LAYERS];
+ bool layer_set[PAINT_ORDER_LAYERS];
+ gchar *value; // Raw string
+};
+
enum {
SP_FONT_SIZE_LITERAL,
SP_FONT_SIZE_LENGTH,
@@ -405,6 +422,8 @@ struct SPStyle {
/** Marker list */
SPIString marker[SP_MARKER_LOC_QTY];
+ SPIPaintOrder paint_order;
+
/** Filter effect */
SPIFilter filter;
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index d324d2d1b..d344fb1d6 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -1703,9 +1703,14 @@ void DocumentProperties::onDocUnitChange()
repr->setAttribute("inkscape:document-units", os.str().c_str());
// Set viewBox
- Inkscape::Util::Quantity width = doc->getWidth();
- Inkscape::Util::Quantity height = doc->getHeight();
- doc->setViewBox(Geom::Rect::from_xywh(0, 0, width.value(doc_unit), height.value(doc_unit)));
+ if (doc->getRoot()->viewBox_set) {
+ gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit);
+ doc->setViewBox(doc->getRoot()->viewBox*Geom::Scale(scale));
+ } else {
+ Inkscape::Util::Quantity width = doc->getWidth();
+ Inkscape::Util::Quantity height = doc->getHeight();
+ doc->setViewBox(Geom::Rect::from_xywh(0, 0, width.value(doc_unit), height.value(doc_unit)));
+ }
// TODO: Fix bug in nodes tool instead of switching away from it
if (tools_active(getDesktop()) == TOOLS_NODES) {
diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp
index 93fcab863..f676e75fd 100644
--- a/src/ui/dialog/ocaldialogs.cpp
+++ b/src/ui/dialog/ocaldialogs.cpp
@@ -1166,8 +1166,6 @@ void ImportDialog::on_xml_file_read(const Glib::RefPtr<Gio::AsyncResult>& result
// free the document
xmlFreeDoc(doc);
- // free the global variables that may have been allocated by the parser
- xmlCleanupParser();
}
@@ -1336,7 +1334,8 @@ ImportDialog::ImportDialog(Gtk::Window& parent_window, FileDialogType file_types
*/
ImportDialog::~ImportDialog()
{
-
+ // free the global variables that may have been allocated by the parser
+ xmlCleanupParser();
}
/**
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 4ea482461..14a3acd9a 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -430,7 +430,6 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPItem *parent_item = NULL; // Initial object
SPItem *item_copied = NULL; // Projected object
SPItem *unionResult = NULL; // Previous union
- SPItem *child_item = NULL; // Parent copy
int i=1;
for (GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
@@ -453,21 +452,12 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Geom::OptRect a = parent_item->documentVisualBounds();
if (a) {
- if (i == 1) {
- Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc);
- parent->appendChild(copy1);
- SPObject *new_obj1 = doc->getObjectByRepr(copy1);
- child_item = SP_ITEM(new_obj1); // Conversion object->item
- unionResult = child_item;
- Inkscape::GC::release(copy1);
- }
-
if (_fid <= population) { // Rules the population of objects sprayed
// Duplicates the parent item
- Inkscape::XML::Node *copy2 = old_repr->duplicate(xml_doc);
- parent->appendChild(copy2);
- SPObject *new_obj2 = doc->getObjectByRepr(copy2);
- item_copied = SP_ITEM(new_obj2);
+ Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy);
+ SPObject *new_obj = doc->getObjectByRepr(copy);
+ item_copied = SP_ITEM(new_obj);
// Move around the cursor
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
@@ -481,10 +471,12 @@ static bool sp_spray_recursive(SPDesktop *desktop,
// Union and duplication
selection->clear();
selection->add(item_copied);
- selection->add(unionResult);
+ if (unionResult) { // No need to add the very first item (initialized with NULL).
+ selection->add(unionResult);
+ }
sp_selected_path_union_skip_undo(selection, selection->desktop());
selection->add(parent_item);
- Inkscape::GC::release(copy2);
+ Inkscape::GC::release(copy);
did = true;
}
}