1 /*
2 * Base class for gradients and patterns
3 *
4 * Author:
5 * Lauris Kaplinski <lauris@kaplinski.com>
6 * Jon A. Cruz <jon@joncruz.org>
7 *
8 * Copyright (C) 1999-2002 Lauris Kaplinski
9 * Copyright (C) 2000-2001 Ximian, Inc.
10 * Copyright (C) 2000-2001 Ximian, Inc.
11 * Copyright (C) 2010 Authors
12 *
13 * Released under GNU GPL, read the file 'COPYING' for more information
14 */
16 #include <string.h>
17 #include "libnr/nr-pixblock-pattern.h"
18 #include "sp-paint-server.h"
20 #include "sp-gradient.h"
21 #include "xml/node.h"
23 static void sp_paint_server_class_init(SPPaintServerClass *psc);
25 static void sp_paint_server_release(SPObject *object);
27 static void sp_painter_stale_fill(SPPainter *painter, NRPixBlock *pb);
29 static SPObjectClass *parent_class;
30 static GSList *stale_painters = NULL;
32 GType SPPaintServer::getType(void)
33 {
34 static GType type = 0;
35 if (!type) {
36 GTypeInfo info = {
37 sizeof(SPPaintServerClass),
38 NULL, /* base_init */
39 NULL, /* base_finalize */
40 (GClassInitFunc) sp_paint_server_class_init,
41 NULL, /* class_finalize */
42 NULL, /* class_data */
43 sizeof(SPPaintServer),
44 16, /* n_preallocs */
45 (GInstanceInitFunc) SPPaintServer::init,
46 NULL, /* value_table */
47 };
48 type = g_type_register_static(SP_TYPE_OBJECT, "SPPaintServer", &info, (GTypeFlags) 0);
49 }
50 return type;
51 }
53 static void sp_paint_server_class_init(SPPaintServerClass *psc)
54 {
55 SPObjectClass *sp_object_class = (SPObjectClass *) psc;
56 sp_object_class->release = sp_paint_server_release;
57 parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT);
58 }
60 void SPPaintServer::init(SPPaintServer *ps)
61 {
62 ps->painters = NULL;
63 ps->swatch = false;
64 }
66 static void sp_paint_server_release(SPObject *object)
67 {
68 SPPaintServer *ps = SP_PAINT_SERVER(object);
70 while (ps->painters) {
71 SPPainter *painter = ps->painters;
72 ps->painters = painter->next;
73 stale_painters = g_slist_prepend(stale_painters, painter);
74 painter->next = NULL;
75 painter->server = NULL;
76 painter->fill = sp_painter_stale_fill;
77 }
79 if (((SPObjectClass *) parent_class)->release) {
80 ((SPObjectClass *) parent_class)->release(object);
81 }
82 }
84 SPPainter *sp_paint_server_painter_new(SPPaintServer *ps,
85 Geom::Matrix const &full_transform,
86 Geom::Matrix const &parent_transform,
87 const NRRect *bbox)
88 {
89 g_return_val_if_fail(ps != NULL, NULL);
90 g_return_val_if_fail(SP_IS_PAINT_SERVER(ps), NULL);
91 g_return_val_if_fail(bbox != NULL, NULL);
93 SPPainter *painter = NULL;
94 SPPaintServerClass *psc = (SPPaintServerClass *) G_OBJECT_GET_CLASS(ps);
95 if ( psc->painter_new ) {
96 painter = (*psc->painter_new)(ps, full_transform, parent_transform, bbox);
97 }
99 if (painter) {
100 painter->next = ps->painters;
101 painter->server = ps;
102 painter->type = (SPPainterType) G_OBJECT_TYPE(ps);
103 ps->painters = painter;
104 }
106 return painter;
107 }
109 static void sp_paint_server_painter_free(SPPaintServer *ps, SPPainter *painter)
110 {
111 g_return_if_fail(ps != NULL);
112 g_return_if_fail(SP_IS_PAINT_SERVER(ps));
113 g_return_if_fail(painter != NULL);
115 SPPaintServerClass *psc = (SPPaintServerClass *) G_OBJECT_GET_CLASS(ps);
117 SPPainter *r = NULL;
118 for (SPPainter *p = ps->painters; p != NULL; p = p->next) {
119 if (p == painter) {
120 if (r) {
121 r->next = p->next;
122 } else {
123 ps->painters = p->next;
124 }
125 p->next = NULL;
126 if (psc->painter_free) {
127 (*psc->painter_free) (ps, painter);
128 }
129 return;
130 }
131 r = p;
132 }
134 g_assert_not_reached();
135 }
137 SPPainter *sp_painter_free(SPPainter *painter)
138 {
139 g_return_val_if_fail(painter != NULL, NULL);
141 if (painter->server) {
142 sp_paint_server_painter_free(painter->server, painter);
143 } else {
144 SPPaintServerClass *psc = (SPPaintServerClass *) g_type_class_ref(painter->type);
145 if (psc->painter_free)
146 (*psc->painter_free)(NULL, painter);
147 stale_painters = g_slist_remove(stale_painters, painter);
148 }
150 return NULL;
151 }
153 static void sp_painter_stale_fill(SPPainter */*painter*/, NRPixBlock *pb)
154 {
155 nr_pixblock_render_gray_noise(pb, NULL);
156 }
158 bool SPPaintServer::isSwatch() const
159 {
160 return swatch;
161 }
163 bool SPPaintServer::isSolid() const
164 {
165 bool solid = false;
166 if (swatch && SP_IS_GRADIENT(this)) {
167 SPGradient *grad = SP_GRADIENT(this);
168 if ( grad->hasStops() && (grad->getStopCount() == 0) ) {
169 solid = true;
170 }
171 }
172 return solid;
173 }
178 /*
179 Local Variables:
180 mode:c++
181 c-file-style:"stroustrup"
182 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
183 indent-tabs-mode:nil
184 fill-column:99
185 End:
186 */
187 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :