style-internal.h revision ff98ca0d42186a71bdbd8484ee8acef605aa8b4a
#ifndef SEEN_SP_STYLE_INTERNAL_H
#define SEEN_SP_STYLE_INTERNAL_H
/** \file
* SPStyle internal: classes that are internal to SPStyle
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Jon A. Cruz <jon@joncruz.org>
* Tavmjong Bah <tavmjong@free.fr>
*
* Copyright (C) 2014 Tavmjong Bah
* Copyright (C) 2010 Jon A. Cruz
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "style-enums.h"
#include "color.h"
#include "svg/svg-icc-color.h"
#include "sp-marker-loc.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
#include "sp-paint-server-reference.h"
#include "uri.h"
#include <vector>
struct SPStyleEnum;
static const unsigned SP_STYLE_FLAG_IFSET (1 << 0);
enum SPStyleSrc {
};
/* General comments:
*
* This code is derived from the original C style code in style.cpp.
*
* Overview:
* Style can be obtained (in order of precidence) [CHECK]
* 1. "style" property in an element (style="fill:red").
* 2. Style sheet, internal or external (<style> rect {fill:red;}</style>).
* 3. Attributes in an element (fill="red").
* 4. Parent's style.
* A later property overrides an earlier property. This is implemented by
* reading in the properties backwards. If a property is already set, it
* prevents an earlier property from being read.
*
* In order for cascading to work, each element in the tree must be read in from top to bottom
* (parent before child). At each step, if a style property is not explicitly set, the property
* value is taken from the parent. Some properties have "computed" values that depend on:
* the parent's value (e.g. "font-size:larger"),
* another property value ("stroke-width":1em"), or
* an external value ("stroke-width:5%").
*
* To summarize:
*
* An explicitly set value (including 'inherit') has a 'true' "set" flag.
* The "value" is either explicitly set or inherited.
* The "computed" value (if present) is calculated from "value" and some other input.
*
* Functions:
* write(): Write a property and its value to a string.
* Flags:
* ALWAYS: Always write out property.
* IFSET: Write a property if 'set' flag is true, otherwise return empty string.
* IFDIFF: Write a property if computed values are different, otherwise return empty string,
* This is only used for text!!
*
* read(): Set a property value from a string.
* clear(): Set a property to its default value and set the 'set' flag to false.
* cascade(): Cascade the parent's property values to the child if the child's property
* is unset (and it allows inheriting) or the value is 'inherit'.
* Calculate computed values that depend on parent.
* This requires that the parent already be updated.
* merge(): Merge the property values of a child and a parent that is being deleted,
* attempting to preserve the style of the child.
* operator=: Assignment operator required due to use of templates (in original C code).
* operator==: True if computed values are equal. TO DO: DEFINE EXACTLY WHAT THIS MEANS
* operator!=: Inverse of operator==.
*
*
* Outside dependencies:
*
* The C structures that these classes are evolved from were designed to be embedded in to the
* style structure (i.e they are "internal" and thus have an "I" in the SPI prefix). However,
* they should be reasonably stand-alone and can provide some functionality outside of the style
* stucture (i.e. reading and writing style strings). Some properties do need access to other
* properties from the same object (e.g. SPILength sometimes needs to know font size) to
* calculate 'computed' values. Inheritence, of course, requires access to the parent object's
* style class.
*
* The only real outside dependancy is SPObject... which is needed in the cases of SPIPaint and
* SPIFilter for setting up the "href". (Currently, SPDocument is needed but this dependency
* should be removed as an "href" only needs the SPDocument for attaching an external document to
* the XML tree [see uri-references.cpp]. If SPDocument is really needed, it can be obtained from
* SPObject.)
*
*/
/// Virtual base class for all SPStyle interal classes
{
set(false),
inherit(false),
{}
{}
if ( !set ) {
}
}
}
}
}
// Explicit assignment operator required due to templates.
return *this;
}
// Check apples being compared to apples
}
}
// To do: make private
// To do: make private after g_asserts removed
};
/// Float type internal to SPStyle. (Only 'stroke-miterlimit')
{
SPIFloat()
: SPIBase( "anonymous_float" ),
value(0.0)
{}
{}
}
return *this;
}
}
// To do: make private
float value;
float value_default;
};
/*
* One might think that the best value for SP_SCALE24_MAX would be ((1<<24)-1), which allows the
* greatest possible precision for fitting [0, 1] fractions into 24 bits.
*
* However, in practice, that gives a problem with 0.5, which falls half way between two fractions
* of ((1<<24)-1). What's worse is that casting double(1<<23) / ((1<<24)-1) to float on x86
* produces wrong rounding behaviour, resulting in a fraction of ((1<<23)+2.0f) / (1<<24) rather
* than ((1<<23)+1.0f) / (1<<24) as one would expect, let alone ((1<<23)+0.0f) / (1<<24) as one
* would ideally like for this example.
*
* The value (1<<23) is thus best if one considers float conversions alone.
*
* The value 0xff0000 can exactly represent all 8-bit alpha channel values,
* and can exactly represent all multiples of 0.1. I haven't yet tested whether
* rounding bugs still get in the way of conversions to & from float, but my instinct is that
* it's fairly safe because 0xff fits three times inside float's significand.
*
* though that might need to be accompanied by greater use of double instead of float for
* colours and opacities, to be safe from rounding bugs.
*/
static const unsigned SP_SCALE24_MAX = 0xff0000;
#define SP_SCALE24_TO_FLOAT(v) ((double) (v) / SP_SCALE24_MAX)
/** Returns a scale24 for the product of two scale24 values. */
/// 24 bit data type internal to SPStyle.
// Used only for opacity, fill-opacity, stroke-opacity.
// Opacity does not inherit but stroke-opacity and fill-opacity do.
{
: SPIBase( "anonymous_scale24" ),
value(0)
{}
{}
{}
}
return *this;
}
}
// To do: make private
unsigned value : 24;
unsigned value_default : 24;
};
enum SPCSSUnit {
};
/// Length type internal to SPStyle.
// Needs access to 'font-size' and 'font-family' for computed values.
// Used for 'stroke-width' 'stroke-dash-offset' ('none' not handled), text-indent
{
: SPIBase( "anonymous_length" ),
value(0),
computed(0)
{}
{}
{}
}
return *this;
}
}
// To do: make private
unsigned unit : 4;
float value;
float computed;
float value_default;
};
/// Extended length type internal to SPStyle.
// Used for: line-height, letter-spacing, word-spacing
{
: SPILength( "anonymous_length" ),
normal(true)
{}
normal(true)
{}
{}
normal = true;
}
return *this;
}
}
// To do: make private
bool normal : 1;
};
/// Enum type internal to SPStyle.
// Used for many properties. 'font-stretch' and 'font-weight' must be special cased.
{
SPIEnum() :
SPIBase( "anonymous_enum" ),
value(0),
computed(0)
{}
SPIEnum( Glib::ustring const &name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) :
{}
// Following is needed for font-weight
SPIEnum( Glib::ustring const &name, SPStyleEnum const *enums, SPCSSFontWeight value, SPCSSFontWeight computed ) :
{}
{}
}
return *this;
}
}
// To do: make private
SPStyleEnum const *enums;
unsigned value : 8;
unsigned computed: 8;
unsigned value_default : 8;
};
/// String type internal to SPStyle.
// Used for 'marker', ..., 'font', 'font-family', 'inkscape-font-specification'
{
: SPIBase( "anonymous_string" ),
{}
// TODO probably want to avoid gchar* and c-style strings.
{}
}
return *this;
}
}
// To do: make private, convert value to Glib::ustring
};
/// Color type interal to SPStyle, FIXME Add string value to store SVG named color.
{
SPIColor()
: SPIBase( "anonymous_color" ),
currentcolor(false) {
}
currentcolor(false) {
}
{}
}
return *this;
}
}
void setColor( float r, float g, float b ) {
}
}
}
bool currentcolor : 1;
// FIXME: remove structure and derive SPIPaint from this class.
struct {
} value;
};
/// Paint type internal to SPStyle.
{
SPIPaint()
: SPIBase( "anonymous_paint" ),
currentcolor(false),
colorSet(false),
noneSet(false) {
clear();
}
currentcolor(false),
colorSet(false),
noneSet(false) {
clear(); // Sets defaults
}
return *this;
}
}
return (isPaintserver() == other.isPaintserver()) && (colorSet == other.colorSet) && (currentcolor == other.currentcolor);
}
bool isNoneSet() const {
return noneSet;
}
bool isNone() const {
} // TODO refine
bool isColor() const {
return colorSet && !isPaintserver();
}
bool isPaintserver() const {
}
void setColor( float r, float g, float b ) {
}
}
}
// To do: make private
bool currentcolor : 1;
bool colorSet : 1;
bool noneSet : 1;
struct {
} value;
};
// SVG 2
enum SPPaintOrderLayer {
};
// Normal maybe should be moved out as is done in other classes.
// This could be replaced by a generic enum class where multiple keywords are allowed and
// where order matters (in contrast to 'text-decoration-line' where order does not matter).
// Each layer represents a layer of paint which can be a fill, a stroke, or markers.
/// Paint order type internal to SPStyle
{
: SPIBase( "paint-order" ),
}
virtual ~SPIPaintOrder() {
}
for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
layer_set[i] = false;
}
}
for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i ) {
}
return *this;
}
}
// To do: make private
bool layer_set[PAINT_ORDER_LAYERS];
};
/// Filter type internal to SPStyle
{
: SPIBase( "stroke-dasharray" )
{} // Only one instance of SPIDashArray
{}
}
return *this;
}
}
// To do: make private, change double to SVGLength
};
/// Filter type internal to SPStyle
{
: SPIBase( "filter", false ),
{}
return *this;
}
}
// To do: make private
};
enum {
};
/// Fontsize type internal to SPStyle (also used by libnrtype/Layout-TNG-Input.cpp).
{
: SPIBase( "font-size" ) {
}
{}
}
return *this;
}
}
static float const font_size_default;
// To do: make private
unsigned type : 2;
unsigned unit : 4;
unsigned literal : 4;
float value;
float computed;
double relative_fraction() const;
static float const font_size_table[];
};
/// Font type internal to SPStyle ('font' shorthand)
{
SPIFont()
: SPIBase( "font" )
{}
{}
}
{} // Done in dependent properties
{}
return *this;
}
}
};
enum {
};
/// Baseline shift type internal to SPStyle. (This is actually just like SPIFontSize)
{
: SPIBase( "baseline-shift", false ) {
}
{}
}
return *this;
}
// This is not used but we have it for completeness, it has not been tested.
}
bool isZero() const;
// To do: make private
unsigned type : 2;
unsigned unit : 4;
unsigned literal: 2;
float value; // Can be negative
float computed;
};
// CSS 2. Changes in CSS 3, where description is for TextDecorationLine, NOT TextDecoration
// CSS3 2.2
/// Text decoration line type internal to SPStyle. THIS SHOULD BE A GENERIC CLASS
{
: SPIBase( "text-decoration-line" ) {
}
{}
}
return *this;
}
}
// To do: make private
bool underline : 1;
bool overline : 1;
bool line_through : 1;
};
// CSS3 2.2
/// Text decoration style type internal to SPStyle. THIS SHOULD JUST BE SPIEnum!
{
: SPIBase( "text-decoration-style" ) {
}
{}
}
return *this;
}
}
// To do: make private
bool solid : 1;
bool dotted : 1;
bool dashed : 1;
bool wavy : 1;
};
// This class reads in both CSS2 and CSS3 'text-decoration' property. It passes the line, style,
// and color parts to the appropriate CSS3 long-hand classes for reading and storing values. When
// writing out data, we write all four properties, with 'text-decoration' being written out with
// the right style. (See http://www.w3.org/TR/css-text-decor-3/#text-decoration-property )
/// Text decoration type internal to SPStyle.
{
: SPIBase( "text-decoration" ),
{}
{}
}
return *this;
}
// Use CSS2 value
}
};
// These are used to implement text_decoration. The values are not saved to or read from SVG file
struct SPITextDecorationData {
float phase_length; // length along text line,used for phase for dot/dash/wavy
bool tspan_line_start; // is first span on a line
bool tspan_line_end; // is last span on a line
float tspan_width; // from libnrtype, when it calculates spans
float ascender; // the rest from tspan's font
float descender;
float line_gap;
float underline_thickness;
float underline_position;
float line_through_thickness;
float line_through_position;
};
#endif // SEEN_SP_STYLE_INTERNAL_H
/*
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 :