style.cpp revision 79eb00a020a316a6d51a2683b5ac256a6e041b14
/**
* @file
* SVG stylesheets implementation.
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Peter Moulder <pmoulder@mail.csse.monash.edu.au>
* bulia byak <buliabyak@users.sf.net>
* Abhishek Sharma
* Tavmjong Bah <tavmjong@free.fr>
* Kris De Gussem <Kris.DeGussem@gmail.com>
*
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
* Copyright (C) 2005 Monash University
* Copyright (C) 2012 Kris De Gussem
* Copyright (C) 2014 Tavmjong Bah
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cstring>
#include <string>
#include <algorithm>
#include "libcroco/cr-sel-eng.h"
#include "xml/croco-node-iface.h"
#include "svg/svg-color.h"
#include "svg/svg-icc-color.h"
#include "display/canvas-bpath.h"
#include "attributes.h"
#include "document.h"
#include "extract-uri.h"
#include "uri-references.h"
#include "uri.h"
#include "sp-paint-server.h"
#include "streq.h"
#include "strneq.h"
#include "style.h"
#include "svg/css-ostringstream.h"
#include "xml/simple-document.h"
#include "macros.h"
#include "preferences.h"
#include "sp-filter-reference.h"
using Inkscape::CSSOStringStream;
#define BMAX 8192
#define SP_CSS_FONT_SIZE_DEFAULT 12.0;
struct SPStyleEnum;
/*#########################
## FORWARD DECLARATIONS
#########################*/
static CRSelEng *sp_repr_sel_eng();
//SPPropMap SPStyle::_propmap;
// C++11 allows one constructor to call another... might be useful. The original C code
// had separate calls to create SPStyle, one with only SPDocument and the other with only
// SPObject as parameters.
// Unimplemented SVG 1.1: alignment-baseline, clip, clip-path, color-profile, cursor,
// dominant-baseline, flood-color, flood-opacity, font-size-adjust,
// glyph-orientation-horizontal, glyph-orientation-vertical, kerning, lighting-color,
// pointer-events, stop-color, stop-opacity, unicode-bidi
// For enums: property( name, enumeration, default value , inherits = true );
// For scale24: property( name, default value = 0, inherits = true );
// 'font', 'font-size', and 'font-family' must come first as other properties depend on them
// for calculated values (through 'em' and 'ex'). ('ex' is currently not read.)
// The following properties can depend on 'em' and 'ex':
// baseline-shift, kerning, letter-spacing, stroke-dash-offset, stroke-width, word-spacing,
// Non-SVG 1.1: text-indent, line-spacing
// Hidden in SPIFontStyle: (to be refactored)
// font-family
// font-specification
// Font related properties and 'font' shorthand
font_size(),
font(), // SPIFont
// Text related properties
// General visual properties
paint_order(), // SPIPaintOrder
// Color properties
color_interpolation( "color-interpolation", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_SRGB),
color_interpolation_filters("color-interpolation-filters", enum_color_interpolation, SP_CSS_COLOR_INTERPOLATION_LINEARRGB),
// Solid color properties
// Fill properties
// Stroke properites
stroke_dasharray(), // SPIDashArray
// Filter properties
filter(),
enable_background("enable-background", enum_enable_background, SP_CSS_BACKGROUND_ACCUMULATE, false),
// Rendering hint properties
{
// std::cout << "SPStyle::SPStyle( SPDocument ): Entrance: (" << _count << ")" << std::endl;
// std::cout << " Document: " << (document_in?"present":"null") << std::endl;
// std::cout << " Object: "
// << (object_in?(object_in->getId()?object_in->getId():"id null"):"object null") << std::endl;
// static bool first = true;
// if( first ) {
// std::cout << "Size of SPStyle: " << sizeof(SPStyle) << std::endl;
// std::cout << " SPIBase: " << sizeof(SPIBase) << std::endl;
// std::cout << " SPIFloat: " << sizeof(SPIFloat) << std::endl;
// std::cout << " SPIScale24: " << sizeof(SPIScale24) << std::endl;
// std::cout << " SPILength: " << sizeof(SPILength) << std::endl;
// std::cout << " SPILengthOrNormal: " << sizeof(SPILengthOrNormal) << std::endl;
// std::cout << " SPIColor: " << sizeof(SPIColor) << std::endl;
// std::cout << " SPIPaint: " << sizeof(SPIPaint) << std::endl;
// std::cout << " SPITextDecorationLine" << sizeof(SPITextDecorationLine) << std::endl;
// std::cout << " Glib::ustring:" << sizeof(Glib::ustring) << std::endl;
// std::cout << " SPColor: " << sizeof(SPColor) << std::endl;
// first = false;
// }
++_count; // Poor man's memory leak detector
_refcount = 1;
cloned = false;
if( object ) {
} else {
}
// 'font' shorthand requires access to included properties.
font.setStylePointer( this );
// Properties that depend on 'font-size' for calculating lengths.
baseline_shift.setStylePointer( this );
text_indent.setStylePointer( this );
line_height.setStylePointer( this );
letter_spacing.setStylePointer( this );
word_spacing.setStylePointer( this );
stroke_width.setStylePointer( this );
stroke_dashoffset.setStylePointer( this );
// Properties that depend on 'color'
text_decoration_color.setStylePointer( this );
fill.setStylePointer( this );
stroke.setStylePointer( this );
// color.setStylePointer( this ); // Doen't need reference to self
// 'text_decoration' shorthand requires access to included properties.
text_decoration.setStylePointer( this );
// SPIPaint, SPIFilter needs access to 'this' (SPStyle)
// for setting up signals... 'fill', 'stroke' already done
filter.setStylePointer( this );
// Used to iterate over markers
// This might be too resource hungary... but for now it possible to loop over properties
// 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
// 'font-size'/'font' must be before properties that need to know em, ex size (SPILength,
// SPILenghtOrNormal)
// MAP -------------------------------------------
// if( _propmap.size() == 0 ) {
// // 'color' must be before 'fill', 'stroke', 'text-decoration-color', ...
// _propmap.insert( std::make_pair( color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color ) ) );
// // 'font-size' must be before properties that need to know em, ex size (SPILength, SPILenghtOrNormal)
// _propmap.insert( std::make_pair( font_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_style ) ) );
// _propmap.insert( std::make_pair( font_variant.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_variant ) ) );
// _propmap.insert( std::make_pair( font_weight.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_weight ) ) );
// _propmap.insert( std::make_pair( font_stretch.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_stretch ) ) );
// _propmap.insert( std::make_pair( font_size.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_size ) ) );
// _propmap.insert( std::make_pair( line_height.name, reinterpret_cast<SPIBasePtr>(&SPStyle::line_height ) ) );
// _propmap.insert( std::make_pair( font_family.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_family ) ) );
// _propmap.insert( std::make_pair( font.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font ) ) );
// _propmap.insert( std::make_pair( font_specification.name, reinterpret_cast<SPIBasePtr>(&SPStyle::font_specification ) ) );
// _propmap.insert( std::make_pair( text_indent.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_indent ) ) );
// _propmap.insert( std::make_pair( text_align.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_align ) ) );
// _propmap.insert( std::make_pair( text_decoration.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration ) ) );
// _propmap.insert( std::make_pair( text_decoration_line.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_line ) ) );
// _propmap.insert( std::make_pair( text_decoration_style.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_style ) ) );
// _propmap.insert( std::make_pair( text_decoration_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_decoration_color ) ) );
// _propmap.insert( std::make_pair( letter_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::letter_spacing ) ) );
// _propmap.insert( std::make_pair( word_spacing.name, reinterpret_cast<SPIBasePtr>(&SPStyle::word_spacing ) ) );
// _propmap.insert( std::make_pair( text_transform.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_transform ) ) );
// _propmap.insert( std::make_pair( direction.name, reinterpret_cast<SPIBasePtr>(&SPStyle::direction ) ) );
// _propmap.insert( std::make_pair( block_progression.name, reinterpret_cast<SPIBasePtr>(&SPStyle::block_progression ) ) );
// _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::writing_mode ) ) );
// _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast<SPIBasePtr>(&SPStyle::baseline_shift ) ) );
// _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_anchor ) ) );
// _propmap.insert( std::make_pair( white_space.name, reinterpret_cast<SPIBasePtr>(&SPStyle::white_space ) ) );
// _propmap.insert( std::make_pair( clip_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::clip_rule ) ) );
// _propmap.insert( std::make_pair( display.name, reinterpret_cast<SPIBasePtr>(&SPStyle::display ) ) );
// _propmap.insert( std::make_pair( overflow.name, reinterpret_cast<SPIBasePtr>(&SPStyle::overflow ) ) );
// _propmap.insert( std::make_pair( visibility.name, reinterpret_cast<SPIBasePtr>(&SPStyle::visibility ) ) );
// _propmap.insert( std::make_pair( opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::opacity ) ) );
// _propmap.insert( std::make_pair( isolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::isolation ) ) );
// _propmap.insert( std::make_pair( mix_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::mix_blend_mode ) ) );
// _propmap.insert( std::make_pair( color_interpolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation ) ) );
// _propmap.insert( std::make_pair( color_interpolation_filters.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation_filters ) ) );
// _propmap.insert( std::make_pair( solid_color.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_color ) ) );
// _propmap.insert( std::make_pair( solid_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::solid_opacity ) ) );
// _propmap.insert( std::make_pair( fill.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill ) ) );
// _propmap.insert( std::make_pair( fill_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_opacity ) ) );
// _propmap.insert( std::make_pair( fill_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::fill_rule ) ) );
// _propmap.insert( std::make_pair( stroke.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke ) ) );
// _propmap.insert( std::make_pair( stroke_width.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_width ) ) );
// _propmap.insert( std::make_pair( stroke_linecap.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linecap ) ) );
// _propmap.insert( std::make_pair( stroke_linejoin.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_linejoin ) ) );
// _propmap.insert( std::make_pair( stroke_miterlimit.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_miterlimit ) ) );
// _propmap.insert( std::make_pair( stroke_dasharray.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dasharray ) ) );
// _propmap.insert( std::make_pair( stroke_dashoffset.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_dashoffset ) ) );
// _propmap.insert( std::make_pair( stroke_opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::stroke_opacity ) ) );
// _propmap.insert( std::make_pair( marker.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker ) ) );
// _propmap.insert( std::make_pair( marker_start.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_start ) ) );
// _propmap.insert( std::make_pair( marker_mid.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_mid ) ) );
// _propmap.insert( std::make_pair( marker_end.name, reinterpret_cast<SPIBasePtr>(&SPStyle::marker_end ) ) );
// _propmap.insert( std::make_pair( paint_order.name, reinterpret_cast<SPIBasePtr>(&SPStyle::paint_order ) ) );
// _propmap.insert( std::make_pair( filter.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter ) ) );
// _propmap.insert( std::make_pair( filter_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_blend_mode ) ) );
// _propmap.insert( std::make_pair( filter_gaussianBlur_deviation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::filter_gaussianBlur_deviation ) ) );
// _propmap.insert( std::make_pair( color_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_rendering ) ) );
// _propmap.insert( std::make_pair( image_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::image_rendering ) ) );
// _propmap.insert( std::make_pair( shape_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::shape_rendering ) ) );
// _propmap.insert( std::make_pair( text_rendering.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_rendering ) ) );
// _propmap.insert( std::make_pair( enable_background.name, reinterpret_cast<SPIBasePtr>(&SPStyle::enable_background ) ) );
// }
}
// std::cout << "SPStyle::~SPStyle" << std::endl;
--_count; // Poor man's memory leak detector.
// Remove connections
// The following shoud be moved into SPIPaint and SPIFilter
}
}
}
_properties.clear();
// std::cout << "SPStyle::~SPstyle(): Exit\n" << std::endl;
}
// Used in SPStyle::clear()
void clear_property( SPIBase* p ) {
p->clear();
}
// Matches void sp_style_clear();
void
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).clear();
// }
// Release connection to object, created in sp_style_new_from_object()
// href->detach() called in fill->clear()...
}
}
}
if (document) {
fill.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), this));
stroke.value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), this));
}
cloned = false;
}
// Matches void sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
void
// std::cout << "SPstyle::read( SPObject, Inkscape::XML::Node ): Entrance: "
// << (object?(object->getId()?object->getId():"id null"):"object null") << " "
// << (repr?(repr->name()?repr->name():"no name"):"repr null")
// << std::endl;
// // Uncomment to verify that we don't need to call clear.
// std::cout << " Creating temp style for testing" << std::endl;
// SPStyle *temp = new SPStyle();
// if( !(*temp == *this ) ) std::cout << "SPStyle::read: Need to clear" << std::endl;
// delete temp;
clear(); // FIXME, If this isn't here, gradient editing stops working. Why?
cloned = true;
}
/* 1. Style attribute */
// std::cout << " MERGING STYLE ATTRIBUTE" << std::endl;
_mergeString( val );
}
/* 2 Style sheet */
// std::cout << " MERGING OBJECT STYLESHEET" << std::endl;
if (object) {
} else {
// std::cerr << "SPStyle::read: No object! Can not read style sheet" << std::endl;
}
/* 3 Presentation attributes */
// std::cout << " MERGING PRESENTATION ATTRIBUTES" << std::endl;
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).readAttribute( repr );
// }
/* 4 Cascade from parent */
// std::cout << " CASCADING FROM PARENT" << std::endl;
if( object ) {
}
} else {
// When does this happen?
// std::cout << "SPStyle::read(): reading via repr->parent()" << std::endl;
delete parent;
}
}
}
// Matches void sp_style_read_from_object(SPStyle *style, SPObject *object);
void
// std::cout << "SPStyle::readFromObject: "<< (object->getId()?object->getId():"null")<< std::endl;
}
// Matches sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
void
// std::cout << "SPStyle::readIfUnset: Entrance: " << (val?val:"null") << std::endl;
// To Do: If it is not too slow, use std::map instead of std::vector inorder to remove switch()
// (looking up SP_PROP_xxxx already uses a hash).
switch (id) {
break;
case SP_PROP_FONT_FAMILY:
break;
case SP_PROP_FONT_SIZE:
break;
case SP_PROP_FONT_SIZE_ADJUST:
}
break;
case SP_PROP_FONT_STYLE:
break;
case SP_PROP_FONT_VARIANT:
break;
case SP_PROP_FONT_WEIGHT:
break;
case SP_PROP_FONT_STRETCH:
break;
case SP_PROP_FONT:
break;
/* Text */
case SP_PROP_TEXT_INDENT:
break;
case SP_PROP_TEXT_ALIGN:
break;
case SP_PROP_TEXT_DECORATION:
break;
break;
break;
break;
case SP_PROP_LINE_HEIGHT:
break;
case SP_PROP_LETTER_SPACING:
break;
case SP_PROP_WORD_SPACING:
break;
case SP_PROP_TEXT_TRANSFORM:
break;
/* Text (css3) */
case SP_PROP_DIRECTION:
break;
break;
case SP_PROP_WRITING_MODE:
break;
case SP_PROP_TEXT_ANCHOR:
break;
case SP_PROP_WHITE_SPACE:
break;
case SP_PROP_BASELINE_SHIFT:
break;
case SP_PROP_TEXT_RENDERING:
break;
break;
break;
break;
break;
case SP_PROP_KERNING:
break;
/* Misc */
case SP_PROP_CLIP:
break;
case SP_PROP_COLOR:
break;
case SP_PROP_CURSOR:
break;
case SP_PROP_DISPLAY:
break;
case SP_PROP_OVERFLOW:
break;
case SP_PROP_VISIBILITY:
break;
case SP_PROP_ISOLATION:
break;
case SP_PROP_MIX_BLEND_MODE:
break;
/* SVG */
case SP_PROP_CLIP_PATH:
/** \todo
* This is a workaround. Inkscape only supports 'clip-path' as SVG attribute, not as
* style property. By having both CSS and SVG attribute set, editing of clip-path
* will fail, since CSS always overwrites SVG attributes.
* Fixes Bug #324849
*/
g_warning("attribute 'clip-path' given as CSS");
//XML Tree being directly used here.
break;
case SP_PROP_CLIP_RULE:
break;
case SP_PROP_MASK:
/** \todo
* See comment for SP_PROP_CLIP_PATH
*/
g_warning("attribute 'mask' given as CSS");
//XML Tree being directly used here.
break;
case SP_PROP_OPACITY:
break;
break;
/* Filter */
case SP_PROP_FILTER:
break;
case SP_PROP_FLOOD_COLOR:
break;
case SP_PROP_FLOOD_OPACITY:
break;
case SP_PROP_LIGHTING_COLOR:
break;
/* Gradient */
case SP_PROP_STOP_COLOR:
break;
case SP_PROP_STOP_OPACITY:
break;
/* Interactivity */
case SP_PROP_POINTER_EVENTS:
break;
/* Paint */
// We read it but issue warning
g_warning("Inkscape currently only supports color-interpolation = sRGB");
}
break;
break;
case SP_PROP_COLOR_PROFILE:
break;
case SP_PROP_COLOR_RENDERING:
break;
case SP_PROP_SOLID_COLOR:
break;
case SP_PROP_SOLID_OPACITY:
break;
case SP_PROP_FILL:
break;
case SP_PROP_FILL_OPACITY:
break;
case SP_PROP_FILL_RULE:
break;
case SP_PROP_IMAGE_RENDERING:
break;
case SP_PROP_MARKER:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
break;
case SP_PROP_MARKER_START:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
break;
case SP_PROP_MARKER_MID:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
break;
case SP_PROP_MARKER_END:
/* TODO: Call sp_uri_reference_resolve(SPDocument *document, guchar const *uri) */
break;
case SP_PROP_SHAPE_RENDERING:
break;
case SP_PROP_STROKE:
break;
case SP_PROP_STROKE_WIDTH:
break;
case SP_PROP_STROKE_DASHARRAY:
break;
break;
case SP_PROP_STROKE_LINECAP:
break;
case SP_PROP_STROKE_LINEJOIN:
break;
break;
case SP_PROP_STROKE_OPACITY:
break;
case SP_PROP_PAINT_ORDER:
break;
default:
break;
}
}
// std::cout << "SPStyle::write" << std::endl;
} else {
}
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// if( base != NULL ) {
// style_string += (this->*(i->second)).write( flags, &(base->*(i->second)) );
// } else {
// style_string += (this->*(i->second)).write( flags, NULL );
// }
// }
// Remove trailing ';'
if( style_string.size() > 0 ) {
}
return style_string;
}
// Corresponds to sp_style_merge_from_parent()
void
// std::cout << "SPStyle::cascade" << std::endl;
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).cascade( &(parent->*(i->second)) );
// }
}
// Corresponds to sp_style_merge_from_dying_parent()
void
// std::cout << "SPStyle::merge" << std::endl;
}
// for(SPPropMap::iterator i = _propmap.begin(); i != _propmap.end(); ++i ) {
// (this->*(i->second)).cascade( &(parent->*(i->second)) );
// }
}
// Mostly for unit testing
bool
// Uncomment for testing
// for(std::vector<SPIBase*>::size_type i = 0; i != _properties.size(); ++i) {
// if( *_properties[i] != *rhs._properties[i])
// std::cout << _properties[i]->name << ": "
// << _properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL) << " "
// << rhs._properties[i]->write(SP_STYLE_FLAG_ALWAYS,NULL)
// << (*_properties[i] == *rhs._properties[i]) << std::endl;
// }
}
return true;
}
void
// std::cout << "SPStyle::_mergeString: " << (p?p:"null") << std::endl;
CRDeclaration *const decl_list
if (decl_list) {
}
}
void
// std::cout << "SPStyle::_mergeDeclList" << std::endl;
// In reverse order, as later declarations to take precedence over earlier ones.
// (Properties are only set if not previously set. See:
// Ref: http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order point 4.)
}
_mergeDecl( decl_list );
}
void
// std::cout << "SPStyle::_mergeDecl" << std::endl;
if (prop_idx != SP_ATTR_INVALID) {
/** \todo
* effic: Test whether the property is already set before trying to
* convert to string. Alternatively, set from CRTerm directly rather
* than converting to string.
*/
}
}
void
// std::cout << "SPStyle::_mergeProps" << std::endl;
// In reverse order, as later declarations to take precedence over earlier ones.
if (props) {
_mergeDecl( decl );
}
}
void
// std::cout << "SPStyle::_mergeObjectStylesheet: " << (object->getId()?object->getId():"null") << std::endl;
if (!sel_eng) {
sel_eng = sp_repr_sel_eng();
}
//XML Tree being directly used here while it shouldn't be.
&props);
/// \todo Check what errors can occur, and handle them properly.
if (props) {
}
}
// Internal
/**
* Release callback.
*/
static void
{
(void)object; // TODO
}
// Internal
/**
* Emit style modified signal on style's object if the filter changed.
*/
static void
{
(void)flags; // TODO
{
}
}
}
// Internal
/**
* Gets called when the filter is (re)attached to the style
*/
void
{
if (old_ref) {
}
if ( SP_IS_FILTER(ref))
{
}
}
/**
* Emit style modified signal on style's object if server is style's fill
* or stroke paint server.
*/
static void
{
(void)flags; // TODO
{
/** \todo
* fixme: I do not know, whether it is optimal - we are
* forcing reread of everything (Lauris)
*/
/** \todo
* fixme: We have to use object_modified flag, because parent
* flag is only available downstreams.
*/
}
{
/// \todo fixme:
}
} else if (server) {
}
}
/**
* Gets called when the paintserver is (re)attached to the style
*/
void
{
if (old_ref) {
}
if (SP_IS_PAINT_SERVER(ref)) {
}
}
/**
* Gets called when the paintserver is (re)attached to the style
*/
void
{
if (old_ref) {
}
if (SP_IS_PAINT_SERVER(ref)) {
}
}
// Called in: desktop-style.cpp, gradient-chemistry.cpp, sp-object.cpp, sp-stop.cpp, style.cpp
// widgets/stroke-style.cpp, widgets/text-toolbar.cpp, ui/dialog/glyphs.cpp, ui/dialog/swatches.cpp,
// ui/widget/object-composite-settings.cpp, ui/widget/selected-style.cpp, ui/widget/style-swatch.cpp
/**
* Returns a new SPStyle object with default settings.
*/
SPStyle *
{
return style;
}
// Called in: sp-object.cpp
/**
* Creates a new SPStyle object, and attaches it to the specified SPObject.
*/
SPStyle *
{
return style;
}
// Called in display/drawing-item.cpp, display/nr-filter-primitive.cpp, libnrtype/Layout-TNG-Input.cpp
/**
* Increase refcount of style.
*/
SPStyle *
{
return style;
}
// Called in style.cpp, desktop-style.cpp, sp-object.cpp, sp-stop.cpp, text-editing.cpp
// display/drawing-group.cpp, ...
/**
* Decrease refcount of style with possible destruction.
*/
SPStyle *
{
delete style;
return NULL;
}
return style;
}
// Called in: sp-clippath.cpp, sp-item.cpp (suspicious), sp-object.cpp, sp-style-elem.cpp
/**
* Read style properties from object's repr.
*
* 1. Reset existing object style
* 2. Load current effective object style
* 3. Load i attributes from immediate parent (which has to be up-to-date)
*/
void
{
// std::cout << "sp_style_read_from_object: " << (object->getId()?object->getId():"null") << std::endl;
}
// Called in: libnrtype/font-lister.cpp, widgets/dash-selector.cpp, widgets/text-toolbar.cpp,
// Why is this called when draging a gradient handle?
/**
* Read style properties from preferences.
* @param style The style to write to
* @param path Preferences directory from which the style should be read
*/
void
{
// not optimal: we reconstruct the node based on the prefs, then pass it to
// sp_style_read for actual processing.
for (std::vector<Inkscape::Preferences::Entry>::iterator i = attrs.begin(); i != attrs.end(); ++i) {
}
delete tempdoc;
}
static CRSelEng *
{
/** \todo
* Check whether we need to register any pseudo-class handlers.
* libcroco has its own default handlers for first-child and lang.
*
* We probably want handlers for link and arguably visited (though
* inkscape can't visit links at the time of writing). hover etc.
* more useful in inkview than the editor inkscape.
*
* http://www.w3.org/TR/SVG11/styling.html#StylingWithCSS says that
* the following should be honoured, at least by inkview:
* :hover, :active, :focus, :visited, :link.
*/
return ret;
}
// Called in text-editting.cpp, ui/tools/frehand-base.cpp, ui/widget/style-swatch.cpp
/**
* Parses a style="..." string and merges it with an existing SPStyle.
*/
void
{
// std::cout << "sp_style_merge_from_style_string: " << (p?p:"null") <<std::endl;
/*
* Reference: http://www.w3.org/TR/SVG11/styling.html#StyleAttribute:
* ``When CSS styling is used, CSS inline style is specified by including
* semicolon-separated property declarations of the form "name : value"
* within the style attribute''.
*
* That's fairly ambiguous. Is a `value' allowed to contain semicolons?
* Why does it say "including", what else is allowed in the style
* attribute value?
*/
style->_mergeString( p );
}
/** Indexed by SP_CSS_FONT_SIZE_blah. These seem a bit small */
// Called in sp-object.cpp, sp-tref.cpp, sp-use.cpp
/**
* Sets computed values in \a style, which may involve inheriting from (or in some other way
* calculating from) corresponding computed values of \a parent.
*
* References: http://www.w3.org/TR/SVG11/propidx.html shows what properties inherit by default.
* http://www.w3.org/TR/SVG11/styling.html#Inheritance gives general rules as to what it means to
* inherit a value. http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value is more precise
* about what the computed value is (not obvious for lengths).
*
* \pre \a parent's computed values are already up-to-date.
*/
void
{
// std::cout << "sp_style_merge_from_parent" << std::endl;
if (!parent)
return;
return;
}
// Called in: sp-use.cpp, sp-tref.cpp, sp-item.cpp
/**
* Combine \a style and \a parent style specifications into a single style specification that
* preserves (as much as possible) the effect of the existing \a style being a child of \a parent.
*
* Called when the parent repr is to be removed (e.g. the parent is a \<use\> element that is being
* trying to retain the same visual appearance once the parent is removed. Interesting cases are
* when there is unusual interaction with the parent's value (opacity, display) or when the value
* can be specified as relative to the parent computed value (font-size, font-weight etc.).
*
* Doesn't update computed values of \a style. For correctness, you should subsequently call
* sp_style_merge_from_parent against the new parent (presumably \a parent's parent) even if \a
* style was previously up-to-date wrt \a parent.
*
* \pre \a parent's computed values are already up-to-date.
* (\a style's computed values needn't be up-to-date.)
*/
void
{
// std::cout << "sp_style_merge_from_dying_parent" << std::endl;
}
// The following functions should be incorporated into SPIPaint. FIXME
// Called in: style.cpp, style-internal.cpp
void
sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI *uri, SPDocument *document)
{
// std::cout << "sp_style_set_ipaint_to_uri: Entrance: " << uri << " " << (void*)document << std::endl;
// 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
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));
}
}
try {
} catch (Inkscape::BadURIException &e) {
}
}
}
// Called in: style.cpp, style-internal.cpp
void
{
try {
} catch (...) {
}
}
// Called in: desktop-style.cpp
void
{
}
// Called in: widgets/font-selector.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
gchar const *
{
// specify px by default, see inkscape bug 1221626, mozilla bug 234789
switch (unit) {
case SP_CSS_UNIT_NONE: return "px";
case SP_CSS_UNIT_PX: return "px";
case SP_CSS_UNIT_PT: return "pt";
case SP_CSS_UNIT_PC: return "pc";
case SP_CSS_UNIT_MM: return "mm";
case SP_CSS_UNIT_CM: return "cm";
case SP_CSS_UNIT_IN: return "in";
case SP_CSS_UNIT_EM: return "em";
case SP_CSS_UNIT_EX: return "ex";
case SP_CSS_UNIT_PERCENT: return "%";
default: return "px";
}
return "px";
}
// Called in: style-internal.cpp, widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in pixels into another CSS unit size
*/
double
{
switch (unit) {
default:
break;
}
return unit_size;
}
// Called in: widgets/text-toolbar.cpp, ui/dialog/text-edit.cpp
/*
* Convert a size in a CSS unit size to pixels
*/
double
{
if (unit == SP_CSS_UNIT_PX) {
return size;
}
//g_message("sp_style_css_size_units_to_px %f %d = %f px", size, unit, out);
}
// Called in style.cpp, text-editing.cpp
/**
* Dumps the style to a CSS string, with either SP_STYLE_FLAG_IFSET or
* SP_STYLE_FLAG_ALWAYS flags. Used with Always for copying an object's
* complete cascaded style to style_clipboard. When you need a CSS string
* for an object in the document tree, you normally call
* sp_style_write_difference instead to take into account the object's parent.
*
* \pre style != NULL.
* \pre flags in {IFSET, ALWAYS}.
* \post ret != NULL.
*/
gchar *
{
/** \todo
* Merge with write_difference, much duplicate code!
*/
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
}
// Called in style.cpp, path-chemistry, NOT in text-editting.cpp (because of bug)
/**
* Dumps style to CSS string, see sp_style_write_string()
*
* \pre from != NULL.
* \pre to != NULL.
* \post ret != NULL.
*/
gchar *
{
}
// FIXME: Everything below this line belongs in a different file - css-chemistry?
void
{
if (linked) {
} else {
}
if (recursive) {
} else {
}
}
// Called in sp-object.cpp
/**
* Clear all style property attributes in object.
*/
void
{
if (!o) {
return;
}
if (!style) {
return;
}
if (!repr) {
return;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
/**
* \pre style != NULL.
* \pre flags in {IFSET, ALWAYS}.
*/
{
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
return css;
}
// Called in: selection-chemistry.cpp, widgets/stroke-marker-selector.cpp, widgets/stroke-style.cpp,
/**
* \pre object != NULL
* \pre flags in {IFSET, ALWAYS}.
*/
{
(flags == SP_STYLE_FLAG_ALWAYS) ),
NULL);
}
return result;
}
// Called in: selection-chemistry.cpp, ui/dialog/inkscape-preferences.cpp
/**
* Unset any text-related properties
*/
{
return css;
}
// Called in style.cpp
static bool
is_url(char const *p)
{
if (p == NULL)
return false;
/** \todo
* FIXME: I'm not sure if this applies to SVG as well, but CSS2 says any URIs
* in property values must start with 'url('.
*/
}
// Called in: ui/dialog/inkscape-preferences.cpp, ui/tools/tweek-tool.cpp
/**
* Unset any properties that contain URI values.
*
* Used for storing style that will be reused across documents when carrying
* the referenced defs is impractical.
*/
{
// All properties that may hold <uri> or <paint> according to SVG 1.1
if (is_url(sp_repr_css_property(css, "clip-path", NULL))) sp_repr_css_set_property(css, "clip-path", NULL);
if (is_url(sp_repr_css_property(css, "color-profile", NULL))) sp_repr_css_set_property(css, "color-profile", NULL);
if (is_url(sp_repr_css_property(css, "cursor", NULL))) sp_repr_css_set_property(css, "cursor", NULL);
if (is_url(sp_repr_css_property(css, "filter", NULL))) sp_repr_css_set_property(css, "filter", NULL);
if (is_url(sp_repr_css_property(css, "marker", NULL))) sp_repr_css_set_property(css, "marker", NULL);
if (is_url(sp_repr_css_property(css, "marker-start", NULL))) sp_repr_css_set_property(css, "marker-start", NULL);
if (is_url(sp_repr_css_property(css, "marker-mid", NULL))) sp_repr_css_set_property(css, "marker-mid", NULL);
if (is_url(sp_repr_css_property(css, "marker-end", NULL))) sp_repr_css_set_property(css, "marker-end", NULL);
if (is_url(sp_repr_css_property(css, "stroke", NULL))) sp_repr_css_set_property(css, "stroke", NULL);
return css;
}
// Called in style.cpp
/**
* Scale a single-value property.
*/
static void
double ex, bool only_with_units = false)
{
if (w) {
if (w == units) {// nothing converted, non-numeric value
return;
}
// only_with_units, but no units found, so do nothing.
return;
}
}
}
// Called in style.cpp for stroke-dasharray
/**
* Scale a list-of-values property.
*/
static void
{
if (string) {
bool first = true;
gchar *w = *i;
if (w == NULL)
break;
if (w == units) {// nothing converted, non-numeric value ("none" or "inherit"); do nothing
g_strfreev(a);
return;
}
if (!first) {
os << ",";
}
first = false;
}
g_strfreev(a);
}
}
// Called in: text-editing.cpp,
/**
* Scale any properties that may hold <length> by ex.
*/
{
return css;
}
/**
* See: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
*/
void
{
bool quote = false;
// Can't wait for C++11!
} else if (*it == '\'') {
// Single quotes require escaping and quotes.
out += '\\';
quote = true;
} else {
// Quote everything else including spaces.
// (CSS Fonts Level 3 recommends quoting with spaces.)
quote = true;
}
// (Actually it's a bit more complicated but as it never hurts to quote...)
quote = true;
}
}
if( quote ) {
out += '\'';
}
}
/**
* Quote font names in font-family lists, changing string in place.
* We use unquoted names internally but some need to be quoted in CSS.
*/
void
{
}
}
// Called in style-internal.cpp, xml/repr-css.cpp
/**
* Remove paired single and double quotes from a string, changing string in place.
*/
void
{
}
}
// Called in style-internal.cpp, text-toolbar.cpp
/**
* Remove paired single and double quotes from font names in font-family lists,
* changing string in place.
* We use unquoted family names internally but CSS sometimes uses quoted names.
*/
void
{
css_unquote( tokens[i] );
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :