diff options
Diffstat (limited to 'src/display/nr-style.cpp')
| -rw-r--r-- | src/display/nr-style.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp new file mode 100644 index 000000000..c15dd78a3 --- /dev/null +++ b/src/display/nr-style.cpp @@ -0,0 +1,218 @@ +/** + * @file + * @brief Style information for rendering + *//* + * Authors: + * Krzysztof KosiĆski <tweenk.pl@gmail.com> + * + * 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!) + +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) +{} + +NRStyle::~NRStyle() +{ + cairo_pattern_destroy(fill_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; + + 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; + } + + opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); + + update(); +} + +bool NRStyle::prepareFill(cairo_t *ct, NRRect *paintbox) +{ + // update fill pattern + if (!fill_pattern) { + switch (fill.type) { + case PAINT_SERVER: + fill_pattern = sp_paint_server_create_pattern(fill.server, ct, 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(cairo_t *ct) +{ + cairo_set_source(ct, fill_pattern); + cairo_set_fill_rule(ct, fill_rule); +} + +bool NRStyle::prepareStroke(cairo_t *ct, NRRect *paintbox) +{ + if (!stroke_pattern) { + switch (stroke.type) { + case PAINT_SERVER: + stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct, 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(cairo_t *ct) +{ + cairo_set_source(ct, stroke_pattern); + cairo_set_line_width(ct, stroke_width); + cairo_set_line_cap(ct, line_cap); + cairo_set_line_join(ct, line_join); + cairo_set_miter_limit(ct, miter_limit); + cairo_set_dash(ct, dash, n_dash, dash_offset); +} + +void NRStyle::update() +{ + // force pattern update + cairo_pattern_destroy(fill_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:encoding=utf-8:textwidth=99 : |
