summaryrefslogtreecommitdiffstats
path: root/src/display/nr-arena-shape.h
blob: 782ae127a0acd019ae562205ea68ef9e72b41ba9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#ifndef __NR_ARENA_SHAPE_H__
#define __NR_ARENA_SHAPE_H__

/*
 * RGBA display list system for inkscape
 *
 * Author:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *
 * Copyright (C) 2001-2002 Lauris Kaplinski
 * Copyright (C) 2001 Ximian, Inc.
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#define NR_TYPE_ARENA_SHAPE (nr_arena_shape_get_type ())
#define NR_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_SHAPE, NRArenaShape))
#define NR_IS_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_SHAPE))

#include "display/curve.h"
#include "display/canvas-bpath.h"
#include "forward.h"
#include "sp-paint-server.h"
#include "nr-arena-item.h"

#include "../color.h"

#include "../livarot/Shape.h"

NRType nr_arena_shape_get_type (void);

struct NRArenaShape : public NRArenaItem {
	class Paint {
	public:
		enum Type {
			NONE,
			COLOR,
			SERVER
		};

		Paint() : _type(NONE), _server(NULL) {
			sp_color_set_rgb_rgba32(&_color, 0);
		}
		Paint(Paint const &p) { _assign(p); }
		~Paint() { clear(); }

		Type type() const { return _type; }
		SPPaintServer *server() const { return _server; }
		SPColor const &color() const { return _color; }

		Paint &operator=(Paint const &p) {
			set(p);
			return *this;
		}

		void set(Paint const &p) {
			clear();
			_assign(p);
		}
		void set(SPColor const &color) {
			clear();
			_type = COLOR;
			sp_color_copy(&_color, &color);
		}
		void set(SPPaintServer *server) {
			clear();
			if (server) {
				_type = SERVER;
				_server = server;
				sp_object_ref(_server, NULL);
			}
		}
		void clear() {
			if ( _type == SERVER ) {
				sp_object_unref(_server, NULL);
				_server = NULL;
			}
			_type = NONE;
		}

	private:
		Type _type;
		SPColor _color;
		SPPaintServer *_server;

		void _assign(Paint const &p) {
			_type = p._type;
			_server = p._server;
			sp_color_copy(&_color, &p._color);
			if (_server) {
				sp_object_ref(_server, NULL);
			}
		}
	};

	enum FillRule {
		EVEN_ODD,
		NONZERO
	};

	enum CapType {
		ROUND_CAP,
		SQUARE_CAP,
		BUTT_CAP
	};

	enum JoinType {
		ROUND_JOIN,
		BEVEL_JOIN,
		MITRE_JOIN
	};

	/* Shape data */
	SPCurve *curve;
	SPStyle *style;
	NRRect paintbox;
	/* State data */
	NR::Matrix ctm;
	
	SPPainter *fill_painter;
	SPPainter *stroke_painter;
	// the 2 cached polygons, for rasterizations uses
	Shape *fill_shp;
	Shape *stroke_shp;
	// the stroke width of stroke_shp, to detect when it changes (on normal/outline switching) and rebuild
	float cached_width; 
	// delayed_shp=true means the *_shp polygons are not computed yet
	// they'll be computed on demand in *_render(), *_pick() or *_clip()
	// the goal is to not uncross polygons that are outside the viewing region
	bool    delayed_shp;
	// approximate bounding box, for the case when the polygons have been delayed
	NRRectL approx_bbox;
	// cache for transformations: cached_fill and cached_stroke are
	// polygons computed for the cached_fctm and cache_sctm respectively
	// when the transformation changes interactively (tracked by the
	// SP_OBJECT_USER_MODIFIED_FLAG_B), we check if it's an isometry wrt
	// the cached ctm. if it's an isometry, just apply it to the cached
	// polygon to get the *_shp polygon.  Otherwise, recompute so this
	// works fine for translation and rotation, but not scaling and
	// skewing
	NR::Matrix cached_fctm;
	NR::Matrix cached_sctm;
    NRRectL    cached_farea;
    NRRectL    cached_sarea;
    bool       cached_fpartialy;
    bool       cached_spartialy;
	
	Shape    *cached_fill;
	Shape    *cached_stroke;
	/* Markers */
	NRArenaItem *markers;

	static NRArenaShape *create(NRArena *arena) {
		NRArenaShape *obj=reinterpret_cast<NRArenaShape *>(nr_object_new(NR_TYPE_ARENA_SHAPE));
		obj->init(arena);
		return obj;
	}

	void setFill(SPPaintServer *server);
	void setFill(SPColor const &color);
	void setFillOpacity(double opacity);
	void setFillRule(FillRule rule);

	void setStroke(SPPaintServer *server);
	void setStroke(SPColor const &color);
	void setStrokeOpacity(double opacity);
	void setStrokeWidth(double width);
	void setLineCap(CapType cap);
	void setLineJoin(JoinType join);
	void setMitreLimit(double limit);

        void setPaintBox(NR::Rect const &pbox);

	void _invalidateCachedFill() {
		if (cached_fill) {
			delete cached_fill;
			cached_fill = NULL;
		}
	}
	void _invalidateCachedStroke() {
		if (cached_stroke) {
			delete cached_stroke;
			cached_stroke = NULL;
		}
	}

	struct Style {
		Style() : opacity(0.0) {}
		Paint paint;
		double opacity;
	};
	struct FillStyle : public Style {
		FillStyle() : rule(EVEN_ODD) {}
		FillRule rule;
	} _fill;
	struct StrokeStyle : public Style {
		StrokeStyle()
		: cap(ROUND_CAP), join(ROUND_JOIN),
		  width(0.0), mitre_limit(0.0)
		{}

		CapType cap;
		JoinType join;
		double width;
		double mitre_limit;
	} _stroke;
};

struct NRArenaShapeClass {
	NRArenaItemClass parent_class;
};

void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve, bool justTrans);
void nr_arena_shape_set_style (NRArenaShape *shape, SPStyle *style);
void nr_arena_shape_set_paintbox (NRArenaShape *shape, const NRRect *pbox);

#endif