/**
* @file
* SVG stylesheets implementation - Classes used by SPStyle class.
*/
/* Authors:
* C++ conversion:
* Tavmjong Bah <tavmjong@free.fr>
* Legacy C implementation:
* Lauris Kaplinski <lauris@kaplinski.com>
* Peter Moulder <pmoulder@mail.csse.monash.edu.au>
* bulia byak <buliabyak@users.sf.net>
* Abhishek Sharma
* 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 "style-internal.h"
#include "style-enums.h"
#include "style.h"
#include "svg/svg-color.h"
#include "svg/svg-icc-color.h"
#include "streq.h"
#include "strneq.h"
#include "extract-uri.h"
#include "preferences.h"
#include "svg/css-ostringstream.h"
// TODO REMOVE OR MAKE MEMBER FUNCTIONS
void sp_style_set_ipaint_to_uri(SPStyle *style, SPIPaint *paint, const Inkscape::URI *uri, SPDocument *document);
using Inkscape::CSSOStringStream;
// SPIBase --------------------------------------------------------------
// SPIFloat -------------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
} else {
set = true;
inherit = false;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
} else {
}
}
}
void
} else {
}
}
void
if( inherits ) {
}
}
} else {
}
}
bool
} else {
return false;
}
}
// SPIScale24 -----------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
} else {
set = true;
inherit = false;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
} else {
}
}
}
void
} else {
}
}
void
if( inherits ) {
}
} else {
// Needed only for 'opacity' which does not inherit. See comment at bottom of file.
} else {
}
}
} else {
}
}
bool
} else {
return false;
}
}
// SPILength ------------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
} else {
gchar *e;
/** \todo fixme: Move this to standard place (Lauris) */
return;
}
if (!*e) {
/* Userspace */
} else if (!strcmp(e, "px")) {
/* Userspace */
} else if (!strcmp(e, "pt")) {
/* Userspace / DEVICESCALE */
} else if (!strcmp(e, "pc")) {
} else if (!strcmp(e, "mm")) {
} else if (!strcmp(e, "cm")) {
} else if (!strcmp(e, "in")) {
} else if (!strcmp(e, "em")) {
/* EM square */
if( style ) {
} else {
}
} else if (!strcmp(e, "ex")) {
/* ex square */
if( style ) {
} else {
}
} else if (!strcmp(e, "%")) {
/* Percentage */
// See: http://www.w3.org/TR/CSS2/visudet.html#propdef-line-height
if( style ) {
} else {
}
}
} else {
/* Invalid */
return;
}
set = true;
inherit = false;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
} else {
switch (this->unit) {
case SP_CSS_UNIT_NONE:
break;
case SP_CSS_UNIT_PX:
break;
case SP_CSS_UNIT_PT:
break;
case SP_CSS_UNIT_PC:
break;
case SP_CSS_UNIT_MM:
break;
case SP_CSS_UNIT_CM:
break;
case SP_CSS_UNIT_IN:
break;
case SP_CSS_UNIT_EM:
break;
case SP_CSS_UNIT_EX:
break;
case SP_CSS_UNIT_PERCENT:
break;
default:
/* Invalid */
break;
}
}
}
}
void
} else {
// Recalculate based on new font-size, font-family inherited from parent
if (unit == SP_CSS_UNIT_EM) {
} else if (unit == SP_CSS_UNIT_EX) {
// FIXME: Get x height from libnrtype or pango.
// Special case
}
}
} else {
}
}
void
if( inherits ) {
// Fix up so values are correct
switch (p->unit) {
case SP_CSS_UNIT_EM:
case SP_CSS_UNIT_EX:
/** \todo
* FIXME: Have separate ex ratio parameter.
* Get x height from libnrtype or pango.
*/
}
break;
default:
break;
}
}
}
} else {
}
}
bool
// If length depends on external parameter, lengths cannot be equal.
if (unit == SP_CSS_UNIT_EM) return false;
if (unit == SP_CSS_UNIT_EX) return false;
if (unit == SP_CSS_UNIT_PERCENT) return false;
if (r->unit == SP_CSS_UNIT_EM) return false;
if (r->unit == SP_CSS_UNIT_EX) return false;
if (r->unit == SP_CSS_UNIT_PERCENT) return false;
} else {
return false;
}
}
// SPILengthOrNormal ----------------------------------------------------
void
if( !str ) return;
set = true;
inherit = false;
normal = true;
} else {
normal = false;
}
};
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->normal) {
return (name + ":normal;");
} else {
}
}
}
void
}
} else {
}
}
void
if( inherits ) {
}
}
}
}
bool
} else {
return false;
}
}
// SPIEnum --------------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
} else {
set = true;
inherit = false;
/* Save copying for values not needing it */
break;
}
}
// The following is defined in CSS 2.1
if( value == SP_CSS_FONT_WEIGHT_NORMAL ) {
} else if (value == SP_CSS_FONT_WEIGHT_BOLD ) {
}
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
}
}
}
}
}
void
} else {
if( value == SP_CSS_FONT_STRETCH_NARROWER ) {
} else if (value == SP_CSS_FONT_STRETCH_WIDER ) {
}
}
// strictly, 'bolder' and 'lighter' should go to the next weight
// expressible in the current font family, but that's difficult to
// find out, so jumping by 3 seems an appropriate approximation
if( value == SP_CSS_FONT_WEIGHT_LIGHTER ) {
} else if (value == SP_CSS_FONT_WEIGHT_BOLDER ) {
}
}
}
} else {
}
}
// FIXME Handle font_stretch and font_weight (relative values) New derived class?
void
if( inherits ) {
} else {
// The following is to special case 'font-stretch' and 'font-weight'
}
unsigned const min_computed_val = 0;
if( value < smaller_val ) {
// Child has absolute value, leave as is.
// Works for all enum properties
// Values cancel, unset
set = false;
// Leave as is, what does applying "wider" twice do?
} else {
// Child is smaller or larger, adjust parent value accordingly
inherit = false;
}
}
}
}
}
}
bool
} else {
return false;
}
}
// SPIEnumBits ----------------------------------------------------------
// Used for 'font-variant-xxx'
void
if( !str ) return;
set = true;
inherit = true;
} else {
set = true;
inherit = false;
/* Save copying for values not needing it */
}
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
}
if (this->value == 0 ) {
return (name + ":normal");
}
unsigned j = 1;
if (j & this->value ) {
return_string += " ";
}
j *= 2;
}
return return_string;
}
}
// SPILigatures -----------------------------------------------------
// Used for 'font-variant-ligatures'
void
if( !str ) return;
set = true;
inherit = true;
// Defaults for TrueType
inherit = false;
set = true;
inherit = false;
set = true;
} else {
// We need to parse in order
set = true;
inherit = false;
// Turn on
} else {
// Turn off
}
}
}
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
}
if (value == SP_CSS_FONT_VARIANT_LIGATURES_NONE ) {
return (name + ":none;");
}
if (value == SP_CSS_FONT_VARIANT_LIGATURES_NORMAL ) {
return (name + ":normal;");
}
if ( !(value & SP_CSS_FONT_VARIANT_LIGATURES_COMMON) )
return_string += "no-common-ligatures ";
return_string += "discretionary-ligatures ";
return_string += "historical-ligatures ";
if ( !(value & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL) )
return_string += "no-contextual ";
return_string += ";";
return return_string;
}
}
// SPINumeric -----------------------------------------------------
// Used for 'font-variant-numeric'
void
if( !str ) return;
set = true;
inherit = true;
// Defaults for TrueType
inherit = false;
set = true;
} else {
// We need to parse in order
set = true;
inherit = false;
// Must switch off incompatible value
break;
break;
break;
break;
break;
break;
// Do nothing
break;
default:
break;
}
}
}
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
}
if (value == SP_CSS_FONT_VARIANT_NUMERIC_NORMAL ) {
return (name + ":normal;");
}
return_string += "lining-nums ";
return_string += "oldstyle-nums ";
return_string += "proportional-nums ";
return_string += "tabular-nums ";
return_string += "diagonal-fractions ";
return_string += "stacked-fractions ";
if ( value & SP_CSS_FONT_VARIANT_NUMERIC_ORDINAL )
return_string += "ordinal ";
return_string += "slashed-zero ";
return_string += ";";
return return_string;
}
}
// SPIString ------------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
} else {
set = true;
inherit = false;
// Family names may be quoted in CSS, internally we use unquoted names.
css_unquote( str_temp );
}
}
}
// This routine is actually rarely used. Writing is done usually
// in sp_repr_css_write_string...
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
} else {
if( this->value ) {
} else {
}
}
}
}
}
void
}
void
}
} else {
}
}
void
if( inherits ) {
}
}
}
}
bool
} else {
return false;
}
}
// SPIColor -------------------------------------------------------------
// Used for 'color', 'text-decoration-color', 'flood-color', 'lighting-color', and 'stop-color'.
// (The last three have yet to be implemented.)
// CSS3: 'currentcolor' is allowed value and is equal to inherit for the 'color' property.
// FIXME: We should preserve named colors, hsl colors, etc.
if( !str ) return;
set = false;
inherit = false;
currentcolor = false;
set = true;
inherit = true;
set = true;
currentcolor = true;
inherit = true; // CSS3
} else {
}
} else {
if (rgb0 != 0xff) {
set = true;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->currentcolor) {
// currentcolor goes first to handle special case for 'color' property
css << "currentColor";
} else if (this->inherit) {
css << "inherit";
} else {
css << " ";
}
i != iEnd; ++i) {
css << ", " << *i;
}
css << ')';
}
}
}
}
}
void
} else {
// Add CSS4 Color: Lighter, Darker
}
} else {
}
}
void
if( inherits ) {
currentcolor = p->currentcolor;
}
}
}
}
bool
if ( (this->currentcolor != r->currentcolor ) ||
return false;
}
} else {
return false;
}
}
// SPIPaint -------------------------------------------------------------
// Paint is used for 'fill' and 'stroke'. SPIPaint perhaps should be derived from SPIColor.
// 'style' is set in SPStyle::SPStyle or in the legacy SPIPaint::read( gchar, style, document )
// It is needed for computed value when value is 'currentColor'. It is also needed to
// find the object for creating an href (this is done through document but should be done
// directly so document not needed.. FIXME).
clear();
}
}
/**
* Set SPIPaint object from string.
*
* \pre paint == \&style.fill || paint == \&style.stroke.
*/
void
// std::cout << "SPIPaint::read: Entrance: " << " |" << (str?str:"null") << "|" << std::endl;
// if( style ) {
// std::cout << " document: " << (void*)style->document << std::endl;
// std::cout << " object: " << (style->object?"present":"null") << std::endl;
// if( style->object )
// std::cout << " : " << (style->object->getId()?style->object->getId():"no ID")
// << " document: " << (style->object->document?"yes":"no") << std::endl;
// }
if(!str ) return;
reset( false ); // Do not init
// Is this necessary?
while (g_ascii_isspace(*str)) {
++str;
}
set = true;
inherit = true;
} else {
// Read any URL first. The other values can be stand-alone or backup to the URL.
// FIXME: THE FOLLOWING CODE SHOULD BE PUT IN A PRIVATE FUNCTION FOR REUSE
} else if (!style ) {
} else {
set = true;
// Create href if not done already
// std::cout << " Creating value.href" << std::endl;
style->fill_ps_changed_connection = value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_fill_paint_server_ref_changed), style));
} else {
style->stroke_ps_changed_connection = value.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_stroke_paint_server_ref_changed), style));
}
}
// std::cout << "uri: " << (uri?uri:"null") << std::endl;
// TODO check what this does in light of move away from union
}
}
while ( g_ascii_isspace(*str) ) {
++str;
}
set = true;
if (style) {
} else {
// Normally an SPIPaint is part of an SPStyle and the value of 'color' is
// available. SPIPaint can be used 'stand-alone' (e.g. to parse color values) in
// which case a value of 'currentColor' is meaningless, thus we shouldn't reach
// here.
setColor( 0 );
}
set = true;
set = true;
set = true;
noneSet = true;
} else {
if (rgb0 != 0xff) {
set = true;
while (g_ascii_isspace(*str)) {
++str;
}
delete tmp;
tmp = 0;
}
}
}
}
}
}
// Stand-alone read (Legacy read()), used multiple places, e.g. sp-stop.cpp
// This function should not be necessary. FIXME
void
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
css << "inherit";
} else {
// url must go first as other values can serve as fallbacks
}
if ( this->noneSet ) {
css << " ";
}
css << "none";
}
if ( this->paintOrigin == SP_CSS_PAINT_ORIGIN_CURRENT_COLOR ) {
css << " ";
}
css << "currentColor";
}
if ( this->paintOrigin == SP_CSS_PAINT_ORIGIN_CONTEXT_FILL ) {
css << " ";
}
css << "context-fill";
}
if ( this->paintOrigin == SP_CSS_PAINT_ORIGIN_CONTEXT_STROKE ) {
css << " ";
}
css << "context-stroke";
}
css << " ";
}
}
css << " ";
}
i != iEnd; ++i) {
css << ", " << *i;
}
css << ')';
}
}
}
}
}
void
// std::cout << "SPIPaint::clear(): " << name << std::endl;
reset( true ); // Reset and Init
}
void
// std::cout << "SPIPaint::reset(): " << name << " " << init << std::endl;
colorSet = false;
noneSet = false;
}
}
if( init ) {
// 'black' is default for 'fill'
}
// currentcolor = true;
}
}
}
void
// std::cout << "SPIPaint::cascade" << std::endl;
reset( false ); // Do not init
if( p->isPaintserver() ) {
// Why can we use p->document ?
sp_style_set_ipaint_to_uri( style, this, p->value.href->getURI(), p->value.href->getOwnerDocument());
} else {
}
} else if( p->isColor() ) {
} else if( p->isNoneSet() ) {
noneSet = true;
} else if( p->paintOrigin == SP_CSS_PAINT_ORIGIN_CURRENT_COLOR ) {
} else if( isNone() ) {
//
} else {
}
} else {
if( paintOrigin == SP_CSS_PAINT_ORIGIN_CURRENT_COLOR ) {
// Update in case color value changed.
}
}
} else {
}
}
void
// if( inherits ) { Paint always inherits
}
}
}
bool
(this->isPaintserver() != r->isPaintserver() ) ||
(this->paintOrigin != r->paintOrigin ) ) {
return false;
}
if ( this->isPaintserver() ) {
return false;
}
}
if ( this->isColor() ) {
return false;
}
}
} else {
return false;
}
}
// SPIPaintOrder --------------------------------------------------------
void
if( !str ) return;
set = false;
inherit = false;
set = true;
inherit = true;
} else {
set = true;
layer_set[0] = true;
} else {
// This certainly can be done more efficiently
unsigned int i = 0;
for( ; i < PAINT_ORDER_LAYERS; ++i ) {
if( c[i] ) {
layer_set[i] = false;
if( !strcmp( c[i], "fill")) {
layer[i] = SP_CSS_PAINT_ORDER_FILL;
layer_set[i] = true;
used[0] = true;
} else if( !strcmp( c[i], "stroke")) {
layer_set[i] = true;
used[1] = true;
} else if( !strcmp( c[i], "markers")) {
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 ) {
layer[i] = SP_CSS_PAINT_ORDER_FILL;
layer_set[i] = false;
++i;
}
layer_set[i] = false;
++i;
}
layer_set[i] = false;
}
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
css << "inherit";
} else {
for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
if( this->layer_set[i] == true ) {
switch (this->layer[i]) {
css << "normal";
assert( i == 0 );
break;
case SP_CSS_PAINT_ORDER_FILL:
if (i!=0) css << " ";
css << "fill";
break;
if (i!=0) css << " ";
css << "stroke";
break;
if (i!=0) css << " ";
css << "markers";
break;
}
} else {
break;
}
}
}
}
}
void
for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
}
}
} else {
}
}
void
// if( inherits ) { PaintOrder always inherits
}
}
}
bool
if( layer[0] == SP_CSS_PAINT_ORDER_NORMAL &&
for (unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
}
} else {
return false;
}
}
// SPIFilter ------------------------------------------------------------
if( href ) {
clear();
delete href;
}
}
void
if( !str ) return;
clear();
set = true;
inherit = true;
set = true;
return;
} else if (!style) {
return;
}
set = true;
// Create href if not already done.
if (!href) {
}
// Do we have href now?
if ( href ) {
} else {
return;
}
}
// We have href
try {
} catch (Inkscape::BadURIException &e) {
}
} else {
}
}
{
// TODO: fix base
//SPILength const *const my_base = dynamic_cast<const SPILength*>(base);
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
return retval;
}
}
}
void
if( href ) {
}
}
}
void
if( inherit ) { // Only inherits if 'inherit' true/
// This is rather unlikely so ignore for now. FIXME
(void)p;
} else {
// Do nothing
}
} else {
}
}
void
// The "correct" thing to do is to combine the filter primitives.
// The next best thing is to keep any filter on this object. If there
// is no filter on this object, then use any filter on the parent.
if( href ) {
// If we alread have an href, use it (unlikely but heck...)
}
} else {
// If we don't have an href, create it
//href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
}
}
if( href ) {
// If we now have an href, try to attach parent filter
try {
} catch (Inkscape::BadURIException &e) {
}
}
}
}
}
// FIXME
bool
(void)r;
return true;
} else {
return false;
}
}
// SPIDashArray ---------------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
return;
}
return;
}
bool LineSolid = true;
while (e != str) {
/* TODO: Should allow <length> rather than just a unitless (px) number. */
if (number > 0.00000001)
LineSolid = false;
if (e != str) {
str = e;
}
}
if (LineSolid) {
}
return;
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
return (name + ":inherit;");
return (name + ":none;");
} else {
if (i) {
os << ", ";
}
}
os << ";";
}
}
}
void
} else {
}
}
void
if( inherits ) {
}
}
} else {
}
}
bool
} else {
return false;
}
}
// SPIFontSize ----------------------------------------------------------
/** Indexed by SP_CSS_FONT_SIZE_blah. These seem a bit small */
void
if( !str ) return;
set = true;
inherit = true;
// xx-small, x-small, etc.
for (unsigned i = 0; enum_font_size[i].key; i++) {
set = true;
inherit = false;
return;
}
}
/* Invalid */
return;
} else {
set = true;
/* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file.
If a bad SVG file is encountered and this is zero odd things
might happen because the inverse is used in some scaling actions.
*/
if( unit == SP_CSS_UNIT_PERCENT ) {
} else {
}
}
return;
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
css << "inherit";
} else if (this->type == SP_FONT_SIZE_LITERAL) {
for (unsigned i = 0; enum_font_size[i].key; i++) {
}
}
} else if (this->type == SP_FONT_SIZE_LENGTH) {
}
} else if (this->type == SP_FONT_SIZE_PERCENTAGE) {
}
}
}
void
// Calculate computed based on parent as needed
} else if( type == SP_FONT_SIZE_LITERAL ) {
if( literal < SP_CSS_FONT_SIZE_SMALLER ) {
} else if( literal == SP_CSS_FONT_SIZE_SMALLER ) {
} else if( literal == SP_CSS_FONT_SIZE_LARGER ) {
} else {
}
} else if( type == SP_FONT_SIZE_PERCENTAGE ) {
// Percentage for font size is relative to parent computed (rather than viewport)
} else if( type == SP_FONT_SIZE_LENGTH ) {
switch ( unit ) {
case SP_CSS_UNIT_EM:
/* Relative to parent font size */
break;
case SP_CSS_UNIT_EX:
/* Relative to parent font size */
break;
default:
/* No change */
break;
}
}
/* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file.
If a bad SVG file is encountered and this is zero odd things
might happen because the inverse is used in some scaling actions.
*/
} else {
}
}
double
switch (type) {
case SP_FONT_SIZE_LITERAL: {
switch (literal) {
case SP_CSS_FONT_SIZE_SMALLER:
return 5.0 / 6.0;
case SP_CSS_FONT_SIZE_LARGER:
return 6.0 / 5.0;
default:
}
}
case SP_FONT_SIZE_PERCENTAGE:
return value;
case SP_FONT_SIZE_LENGTH: {
switch (unit ) {
case SP_CSS_UNIT_EM:
return value;
case SP_CSS_UNIT_EX:
return value * 0.5;
default:
}
}
}
}
void
// Parent has definined font-size
// Computed value same as parent
} else if ( type == SP_FONT_SIZE_LENGTH &&
unit != SP_CSS_UNIT_EM &&
unit != SP_CSS_UNIT_EX ) {
// Absolute size, computed value already set
} else if ( type == SP_FONT_SIZE_LITERAL &&
// Absolute size, computed value already set
//g_assert( literal < G_N_ELEMENTS(font_size_table) );
} else {
// Relative size
double const child_frac( relative_fraction() );
set = true;
inherit = false;
if ( ( p->type == SP_FONT_SIZE_LITERAL &&
p->literal < SP_CSS_FONT_SIZE_SMALLER ) ||
( p->type == SP_FONT_SIZE_LENGTH &&
p->unit != SP_CSS_UNIT_EM &&
p->unit != SP_CSS_UNIT_EX ) ) {
// Parent absolut size
} else {
// Parent relative size
double const parent_frac( p->relative_fraction() );
if( type == SP_FONT_SIZE_LENGTH ) {
value *= parent_frac;
} else {
}
}
} // Relative size
/* Set a minimum font size to something much smaller than should ever (ever!) be encountered in a real file.
If a bad SVG file is encountered and this is zero odd things
might happen because the inverse is used in some scaling actions.
*/
} // Parent set and not inherit
} else {
}
}
// What about different SVG units?
bool
if( type == SP_FONT_SIZE_LENGTH ) {
} else if (type == SP_FONT_SIZE_LITERAL ) {
} else {
}
} else {
return false;
}
}
// SPIFont ----------------------------------------------------------
void
if( !str ) return;
if( !style ) {
return;
}
set = true;
inherit = true;
} else {
// Break string into white space separated tokens
// CSS is case insensitive but we're comparing against lowercase strings
if (lparam == "/" ) {
// line_height follows... note: font-size already read
} else {
// Try to parse each property in turn
if( test_style.set ) {
continue;
}
// font-variant (Note: only CSS2.1 value small-caps is valid in shortcut.)
if( test_variant.set ) {
continue;
}
// font-weight
if( test_weight.set ) {
continue;
}
// font-stretch (added in CSS 3 Fonts)
if( test_stretch.set ) {
continue;
}
// font-size
continue;
}
// No valid property value found.
break;
}
} // params
// The rest must be font-family...
// Everything in shorthand is set per CSS rules, this works since
// properties are read backwards from end to start.
// style->font_size_adjust.set = true;
// style->font_kerning.set = true;
// style->font_language_override.set = true;;
}
}
{
// At the moment, do nothing. We could add a preference to write out
// 'font' shorthand rather than longhand properties.
// SPIFontSize const *const my_base = dynamic_cast<const SPIFontSize*>(base);
// if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
// ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
// ((flags & SP_STYLE_FLAG_IFDIFF) && this->set
// && (!my_base->set || this != my_base )))
// {
// CSSOStringStream css;
// }
}
// void
// SPIFont::cascade( const SPIBase* const parent ) {
// }
// void
// SPIFont::merge( const SPIBase* const parent ) {
// }
// Does nothing...
bool
} else {
return false;
}
}
// SPIBaselineShift -----------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
// baseline or sub or super
for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
set = true;
inherit = false;
return;
}
}
/* Invalid */
return;
} else {
if( unit == SP_CSS_UNIT_PERCENT ) {
} else {
}
return;
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if (this->inherit) {
css << "inherit";
} else if (this->type == SP_BASELINE_SHIFT_LITERAL) {
for (unsigned i = 0; enum_baseline_shift[i].key; i++) {
}
}
} else if (this->type == SP_BASELINE_SHIFT_LENGTH) {
} else {
}
} else if (this->type == SP_BASELINE_SHIFT_PERCENTAGE) {
}
}
}
void
} else if (type == SP_BASELINE_SHIFT_LITERAL) {
if( literal == SP_CSS_BASELINE_SHIFT_BASELINE ) {
computed = 0; // No change
} else if (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.
} else if (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.
} else {
/* Illegal value */
}
} else if (type == SP_BASELINE_SHIFT_PERCENTAGE) {
// Percentage for baseline shift is relative to computed "line-height"
// which is just font-size (see SVG1.1 'font').
} else if (type == SP_BASELINE_SHIFT_LENGTH) {
switch (unit) {
case SP_CSS_UNIT_EM:
break;
case SP_CSS_UNIT_EX:
break;
default:
/* No change */
break;
}
}
// baseline-shifts are relative to parent baseline
} else {
}
}
// This was not defined in the legacy C code, it needs some serious thinking (but is low priority).
// FIX ME
void
}
} else {
}
}
// This is not used but we have it for completeness, it has not been tested.
bool
if( type == SP_BASELINE_SHIFT_LENGTH ) {
} else if ( type == SP_BASELINE_SHIFT_LITERAL ) {
} else {
}
} else {
return false;
}
}
bool
if( type == SP_BASELINE_SHIFT_LITERAL ) {
if( literal == SP_CSS_BASELINE_SHIFT_BASELINE ) return true;
} else {
if( value == 0.0 ) return true;
}
return false;
}
// SPITextDecorationLine ------------------------------------------------
void
if( !str ) return;
set = true;
inherit = true;
set = true;
inherit = false;
underline = false;
overline = false;
line_through = false;
blink = false;
} else {
bool found_one = false;
bool hit_one = false;
// CSS 2 keywords
bool found_underline = false;
bool found_overline = false;
bool found_line_through = false;
bool found_blink = false;
// This method ignores inlineid keys and extra delimiters, so " ,,, blink hello" will set
// blink and ignore hello
while (1) {
// CSS 2 keywords
while(1){ // not really a loop, used to avoid a goto
hit_one = true; // most likely we will
hit_one = false; // whatever this thing is, we do not recognize it
break;
}
if(*str == '\0')break;
}
str++;
}
if (found_one) {
set = true;
inherit = false;
blink = found_blink;
}
else {
set = false;
inherit = false;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if( inherit ) {
os << "inherit";
} else {
os << "none";
}
os << ";";
}
}
void
line_through = p->line_through;
}
} else {
}
}
void
if( inherits ) { // Always inherits... but special rules?
line_through = p->line_through;
}
}
}
}
bool
return
(line_through == r->line_through ) &&
} else {
return false;
}
}
// SPITextDecorationStyle -----------------------------------------------
void
if( !str ) return;
set = false;
inherit = false;
solid = true; // Default
isdouble = false;
dotted = false;
dashed = false;
wavy = false;
set = true;
inherit = true;
solid = false;
} else {
// note, these are CSS 3 keywords
bool found_solid = false;
bool found_double = false;
bool found_dotted = false;
bool found_dashed = false;
bool found_wavy = false;
bool found_one = false;
// this method ignores inlineid keys and extra delimiters, so " ,,, style hello" will set style and ignore hello
// if more than one style is present, the first is used
while (1) {
else if ((slen == 6) && strneq(hstr, "double", slen)){ found_double = true; found_one = true; break; }
else if ((slen == 6) && strneq(hstr, "dotted", slen)){ found_dotted = true; found_one = true; break; }
else if ((slen == 6) && strneq(hstr, "dashed", slen)){ found_dashed = true; found_one = true; break; }
}
str++;
}
if(found_one){
set = true;
solid = found_solid;
wavy = found_wavy;
}
else {
set = false;
inherit = false;
}
}
}
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if( inherit ) {
os << "inherit";
} else if (this->solid ) {
os << "solid";
} else if (this->isdouble ) {
os << "double";
} else if (this->dotted ) {
os << "dotted";
} else if (this->dashed ) {
os << "dashed";
} else if (this->wavy ) {
os << "wavy";
} else {
}
os << ";";
}
}
void
}
} else {
}
}
void
if( inherits ) { // Always inherits... but special rules?
}
}
}
}
bool
return
} else {
return false;
}
}
// TextDecorationColor is handled by SPIPaint (should be SPIColor), default value is "currentColor"
// FIXME
// SPITextDecoration ----------------------------------------------------
void
if( !str ) return;
bool is_css3 = false;
}
if( test_style.set ) {
is_css3 = true;
}
// the color routine must be fed one token at a time - if multiple colors are found the LAST
// one is used ???? then why break on set?
// This could certainly be designed better
test_color.set = false;
while (1) {
gchar *frag = g_strndup(hstr,slen+1); // only send one piece at a time, since keywords may be intermixed
}
if( test_color.set ) {
is_css3 = true;
break;
}
test_color.set = false;
if( *str == '\0' )break;
}
str++;
}
// If we read a style or color then we have CSS3 which require any non-set values to be
// set to their default values.
if( is_css3 ) {
}
// If we set text_decoration_line, then update style_td (for CSS2 text-decoration)
}
}
// Returns CSS2 'text-decoration' (using settings in SPTextDecorationLine)
// This is required until all SVG renderers support CSS3 'text-decoration'
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
{
if( inherit ) {
os << "inherit";
} else {
os << "none";
}
os << ";";
}
}
void
}
} else {
}
}
void
}
} else {
}
}
// Use CSS2 value
bool
} else {
return false;
}
}
/* ---------------------------- NOTES ----------------------------- */
/*
* opacity's effect is cumulative; we set the new value to the combined effect. The
* default value for opacity is 1.0, not inherit. (Note that stroke-opacity and
* fill-opacity are quite different from opacity, and don't need any special handling.)
*
* Cases:
* - parent & child were each previously unset, in which case the effective
* opacity value is 1.0, and style should remain unset.
* - parent was previously unset (so computed opacity value of 1.0)
* and child was set to inherit. The merged child should
* get a value of 1.0, and shouldn't inherit (lest the new parent
* has a different opacity value). Given that opacity's default
* value is 1.0 (rather than inherit), we might as well have the
* merged child's opacity be unset.
* - parent was previously unset (so opacity 1.0), and child was set to a number.
* The merged child should retain its existing settings (though it doesn't matter
* if we make it unset if that number was 1.0).
* - parent was inherit and child was unset. Merged child should be set to inherit.
* - parent was inherit and child was inherit. (We can't in general reproduce this
* effect (short of introducing a new group), but setting opacity to inherit is rare.)
* If the inherited value was strictly between 0.0 and 1.0 (exclusive) then the merged
* child's value should be set to the product of the two, i.e. the square of the
* inherited value, and should not be marked as inherit. (This decision assumes that it
* is more important to retain the effective opacity than to retain the inheriting
* effect, and assumes that the inheriting effect either isn't important enough to create
* a group or isn't common enough to bother maintaining the code to create a group.) If
* the inherited value was 0.0 or 1.0, then marking the merged child as inherit comes
* closer to maintaining the effect.
* - parent was inherit and child was set to a numerical value. If the child's value
* was 1.0, then the merged child should have the same settings as the parent.
* If the child's value was 0, then the merged child should also be set to 0.
* case above: have the merged child set to the product of the two opacities and not
* marked as inherit, for the same reasons as for that case.
* - parent was set to a value, and child was unset. The merged child should have
* parent's settings.
* - parent was set to a value, and child was inherit. The merged child should
* be set to the product, i.e. the square of the parent's value.
* - parent & child are each set to a value. The merged child should be set to the
* product.
*/
/*
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 :