nr-style.cpp revision df6dea947cb4fcb132e1ee71c3a75628157fb326
/**
* @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()
{
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;
}
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 :