/** * @file * Style information for rendering. *//* * Authors: * Krzysztof KosiƄski * * Copyright (C) 2010 Authors * Released under GNU GPL, read the file 'COPYING' for more information */ #include "display/nr-style.h" #include "style.h" #include "sp-paint-server.h" #include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!) #include "display/drawing-context.h" void NRStyle::Paint::clear() { if (server) { sp_object_unref(server, NULL); server = NULL; } type = PAINT_NONE; } void NRStyle::Paint::set(SPColor const &c) { clear(); type = PAINT_COLOR; color = c; } void NRStyle::Paint::set(SPPaintServer *ps) { clear(); if (ps) { type = PAINT_SERVER; server = ps; sp_object_ref(server, NULL); } } NRStyle::NRStyle() : fill() , stroke() , stroke_width(0.0) , miter_limit(0.0) , n_dash(0) , dash(NULL) , dash_offset(0.0) , fill_rule(CAIRO_FILL_RULE_EVEN_ODD) , line_cap(CAIRO_LINE_CAP_BUTT) , line_join(CAIRO_LINE_JOIN_MITER) , fill_pattern(NULL) , stroke_pattern(NULL) , text_decoration_line(TEXT_DECORATION_LINE_CLEAR) , text_decoration_style(TEXT_DECORATION_STYLE_CLEAR) , phase_length(0.0) , tspan_line_start(false) , tspan_line_end(false) , tspan_width(0) , ascender(0) , descender(0) , line_gap(0) , underline_thickness(0) , underline_position(0) , line_through_thickness(0) , line_through_position(0) , font_size(0) {} NRStyle::~NRStyle() { if (fill_pattern) cairo_pattern_destroy(fill_pattern); if (stroke_pattern) cairo_pattern_destroy(stroke_pattern); if (dash){ delete [] dash; } } void NRStyle::set(SPStyle *style) { if ( style->fill.isPaintserver() ) { fill.set(style->getFillPaintServer()); } else if ( style->fill.isColor() ) { fill.set(style->fill.value.color); } else if ( style->fill.isNone() ) { fill.clear(); } else { g_assert_not_reached(); } fill.opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value); switch (style->fill_rule.computed) { case SP_WIND_RULE_EVENODD: fill_rule = CAIRO_FILL_RULE_EVEN_ODD; break; case SP_WIND_RULE_NONZERO: fill_rule = CAIRO_FILL_RULE_WINDING; break; default: g_assert_not_reached(); } if ( style->stroke.isPaintserver() ) { stroke.set(style->getStrokePaintServer()); } else if ( style->stroke.isColor() ) { stroke.set(style->stroke.value.color); } else if ( style->stroke.isNone() ) { stroke.clear(); } else { g_assert_not_reached(); } stroke.opacity = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); stroke_width = style->stroke_width.computed; switch (style->stroke_linecap.computed) { case SP_STROKE_LINECAP_ROUND: line_cap = CAIRO_LINE_CAP_ROUND; break; case SP_STROKE_LINECAP_SQUARE: line_cap = CAIRO_LINE_CAP_SQUARE; break; case SP_STROKE_LINECAP_BUTT: line_cap = CAIRO_LINE_CAP_BUTT; break; default: g_assert_not_reached(); } switch (style->stroke_linejoin.computed) { case SP_STROKE_LINEJOIN_ROUND: line_join = CAIRO_LINE_JOIN_ROUND; break; case SP_STROKE_LINEJOIN_BEVEL: line_join = CAIRO_LINE_JOIN_BEVEL; break; case SP_STROKE_LINEJOIN_MITER: line_join = CAIRO_LINE_JOIN_MITER; break; default: g_assert_not_reached(); } miter_limit = style->stroke_miterlimit.value; if (dash){ delete [] dash; } n_dash = style->stroke_dash.n_dash; if (n_dash != 0) { dash_offset = style->stroke_dash.offset; dash = new double[n_dash]; for (unsigned int i = 0; i < n_dash; ++i) { dash[i] = style->stroke_dash.dash[i]; } } else { dash_offset = 0.0; dash = NULL; } 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; } if(style->text_decoration_line.overline ){ text_decoration_line |= TEXT_DECORATION_LINE_OVERLINE + TEXT_DECORATION_LINE_SET; } if(style->text_decoration_line.line_through){ text_decoration_line |= TEXT_DECORATION_LINE_LINETHROUGH + TEXT_DECORATION_LINE_SET; } if(style->text_decoration_line.blink ){ text_decoration_line |= TEXT_DECORATION_LINE_BLINK + TEXT_DECORATION_LINE_SET; } text_decoration_style = TEXT_DECORATION_STYLE_CLEAR; if(style->text_decoration_style.inherit ){ text_decoration_style |= TEXT_DECORATION_STYLE_INHERIT; } if(style->text_decoration_style.solid ){ text_decoration_style |= TEXT_DECORATION_STYLE_SOLID + TEXT_DECORATION_STYLE_SET; } if(style->text_decoration_style.isdouble ){ text_decoration_style |= TEXT_DECORATION_STYLE_ISDOUBLE + TEXT_DECORATION_STYLE_SET; } if(style->text_decoration_style.dotted ){ text_decoration_style |= TEXT_DECORATION_STYLE_DOTTED + TEXT_DECORATION_STYLE_SET; } if(style->text_decoration_style.dashed ){ text_decoration_style |= TEXT_DECORATION_STYLE_DASHED + TEXT_DECORATION_STYLE_SET; } if(style->text_decoration_style.wavy ){ text_decoration_style |= TEXT_DECORATION_STYLE_WAVY + TEXT_DECORATION_STYLE_SET; } if( style->text_decoration_color.set || style->text_decoration_color.inherit || style->text_decoration_color.currentcolor || style->text_decoration_color.colorSet){ text_decoration_color.set(style->text_decoration_color.value.color); text_decoration_useColor = true; } else { text_decoration_color.clear(); text_decoration_useColor = false; } if(text_decoration_line != TEXT_DECORATION_LINE_CLEAR){ phase_length = style->text_decoration_data.phase_length; tspan_line_start = style->text_decoration_data.tspan_line_start; tspan_line_end = style->text_decoration_data.tspan_line_end; tspan_width = style->text_decoration_data.tspan_width; ascender = style->text_decoration_data.ascender; descender = style->text_decoration_data.descender; line_gap = style->text_decoration_data.line_gap; underline_thickness = style->text_decoration_data.underline_thickness; underline_position = style->text_decoration_data.underline_position; line_through_thickness = style->text_decoration_data.line_through_thickness; line_through_position = style->text_decoration_data.line_through_position; font_size = style->font_size.computed; } text_direction = style->direction.computed; update(); } bool NRStyle::prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox) { // update fill pattern if (!fill_pattern) { switch (fill.type) { case PAINT_SERVER: { fill_pattern = sp_paint_server_create_pattern(fill.server, ct.raw(), paintbox, fill.opacity); } break; case PAINT_COLOR: { SPColor const &c = fill.color; fill_pattern = cairo_pattern_create_rgba( c.v.c[0], c.v.c[1], c.v.c[2], fill.opacity); } break; default: break; } } if (!fill_pattern) return false; return true; } void NRStyle::applyFill(Inkscape::DrawingContext &ct) { ct.setSource(fill_pattern); ct.setFillRule(fill_rule); } bool NRStyle::prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox) { if (!stroke_pattern) { switch (stroke.type) { case PAINT_SERVER: { stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct.raw(), paintbox, stroke.opacity); } break; case PAINT_COLOR: { SPColor const &c = stroke.color; stroke_pattern = cairo_pattern_create_rgba( c.v.c[0], c.v.c[1], c.v.c[2], stroke.opacity); } break; default: break; } } if (!stroke_pattern) return false; return true; } void NRStyle::applyStroke(Inkscape::DrawingContext &ct) { ct.setSource(stroke_pattern); ct.setLineWidth(stroke_width); ct.setLineCap(line_cap); ct.setLineJoin(line_join); ct.setMiterLimit(miter_limit); cairo_set_dash(ct.raw(), dash, n_dash, dash_offset); // fixme } void NRStyle::update() { // force pattern update if (fill_pattern) cairo_pattern_destroy(fill_pattern); if (stroke_pattern) cairo_pattern_destroy(stroke_pattern); fill_pattern = NULL; stroke_pattern = NULL; } /* 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 :