1 /* imposter (OO.org Impress viewer)
2 ** Copyright (C) 2003-2005 Gurer Ozen
3 ** This code is free software; you can redistribute it and/or
4 ** modify it under the terms of GNU General Public License.
15 #define GRAD_RECTANGULAR 3
17 #define GRAD_ELLIPTICAL 5
19 typedef struct Gradient_s {
32 typedef struct Rectangle_s {
40 poly_rotate (ImpPoint *poly, int n, int cx, int cy, double fAngle)
45 for (i = 0; i < n; i++) {
48 poly->x = (cos(fAngle) * nX + sin(fAngle) * nY) + cx;
49 poly->y = - (sin(fAngle)* nX - cos(fAngle) * nY) + cy;
55 r_draw_gradient_simple (ImpRenderCtx *ctx, void *drw_data, Gradient *grad)
57 Rectangle rRect = { 0, 0, ctx->pix_w - 1, ctx->pix_h - 1 };
58 Rectangle aRect, aFullRect;
59 ImpPoint poly[4], tempoly[2];
61 double fW, fH, fDX, fDY, fAngle;
62 double fScanLine, fScanInc;
63 long redSteps, greenSteps, blueSteps;
65 int i, nSteps, nSteps2;
68 cx = rRect.Left + (rRect.Right - rRect.Left) / 2;
69 cy = rRect.Top + (rRect.Bottom - rRect.Top) / 2;
72 aRect.Top--; aRect.Left--; aRect.Bottom++; aRect.Right++;
73 fW = rRect.Right - rRect.Left;
74 fH = rRect.Bottom - rRect.Top;
75 fAngle = (((double) grad->angle) * 3.14 / 1800.0);
76 fDX = fW * fabs (cos (fAngle)) + fH * fabs (sin (fAngle));
77 fDY = fH * fabs (cos (fAngle)) + fW * fabs (sin (fAngle));
78 fDX = (fDX - fW) * 0.5 - 0.5;
79 fDY = (fDY - fH) * 0.5 - 0.5;
86 nBorder = grad->border * (aRect.Bottom - aRect.Top) / 100;
87 if (grad->type == GRAD_LINEAR) {
92 aRect.Bottom -= nBorder;
95 if (aRect.Top > (aRect.Bottom - 1))
96 aRect.Top = aRect.Bottom - 1;
98 poly[0].x = aFullRect.Left;
99 poly[0].y = aFullRect.Top;
100 poly[1].x = aFullRect.Right;
101 poly[1].y = aFullRect.Top;
102 poly[2].x = aRect.Right;
103 poly[2].y = aRect.Top;
104 poly[3].x = aRect.Left;
105 poly[3].y = aRect.Top;
106 poly_rotate (&poly[0], 4, cx, cy, fAngle);
108 redSteps = grad->end.red - grad->start.red;
109 greenSteps = grad->end.green - grad->start.green;
110 blueSteps = grad->end.blue - grad->start.blue;
111 nSteps = grad->steps;
114 mr = aRect.Bottom - aRect.Top;
120 if (abs(greenSteps) > mr) mr = abs(greenSteps);
121 if (abs(blueSteps) > mr) mr = abs(blueSteps);
122 if (mr < nSteps) nSteps = mr;
125 if (grad->type == GRAD_AXIAL) {
126 if (nSteps & 1) nSteps++;
127 nSteps2 = nSteps + 2;
133 nSteps2 = nSteps + 1;
137 fScanLine = aRect.Top;
138 fScanInc = (double)(aRect.Bottom - aRect.Top) / (double)nSteps;
140 for (i = 0; i < nSteps2; i++) {
142 ctx->drw->set_fg_color(drw_data, &gcol);
143 ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
145 aRect.Top = (long)(fScanLine += fScanInc);
147 tempoly[0].x = aFullRect.Left;
148 tempoly[0].y = aFullRect.Bottom;
149 tempoly[1].x = aFullRect.Right;
150 tempoly[1].y = aFullRect.Bottom;
152 tempoly[0].x = aRect.Left;
153 tempoly[0].y = aRect.Top;
154 tempoly[1].x = aRect.Right;
155 tempoly[1].y = aRect.Top;
157 poly_rotate (&tempoly[0], 2, cx, cy, fAngle);
160 poly[2] = tempoly[1];
161 poly[3] = tempoly[0];
163 if (grad->type == GRAD_LINEAR) {
164 gcol.red = grad->start.red + ((redSteps * i) / nSteps2);
165 gcol.green = grad->start.green + ((greenSteps * i) / nSteps2);
166 gcol.blue = grad->start.blue + ((blueSteps * i) / nSteps2);
169 gcol.red = grad->end.red;
170 gcol.green = grad->end.green;
171 gcol.blue = grad->end.blue;
173 if (i <= (nSteps / 2)) {
174 gcol.red = grad->end.red - ((redSteps * i) / nSteps2);
175 gcol.green = grad->end.green - ((greenSteps * i) / nSteps2);
176 gcol.blue = grad->end.blue - ((blueSteps * i) / nSteps2);
178 int i2 = i - nSteps / 2;
179 gcol.red = grad->start.red + ((redSteps * i2) / nSteps2);
180 gcol.green = grad->start.green + ((greenSteps * i2) / nSteps2);
181 gcol.blue = grad->start.blue + ((blueSteps * i2) / nSteps2);
189 r_draw_gradient_complex (ImpRenderCtx *ctx, void *drw_data, Gradient *grad)
191 Rectangle rRect = { 0, 0, ctx->pix_w - 1, ctx->pix_h - 1 };
192 Rectangle aRect = rRect;
195 double fAngle = (((double) grad->angle) * 3.14 / 1800.0);
196 long redSteps, greenSteps, blueSteps;
203 double sTop, sLeft, sRight, sBottom, sInc;
206 redSteps = grad->end.red - grad->start.red;
207 greenSteps = grad->end.green - grad->start.green;
208 blueSteps = grad->end.blue - grad->start.blue;
210 if (grad->type == GRAD_SQUARE || grad->type == GRAD_RECTANGULAR) {
211 double fW = aRect.Right - aRect.Left;
212 double fH = aRect.Bottom - aRect.Top;
213 double fDX = fW * fabs (cos (fAngle)) + fH * fabs (sin (fAngle));
214 double fDY = fH * fabs (cos (fAngle)) + fW * fabs (sin (fAngle));
215 fDX = (fDX - fW) * 0.5 - 0.5;
216 fDY = (fDY - fH) * 0.5 - 0.5;
223 sW = aRect.Right - aRect.Left;
224 sH = aRect.Bottom - aRect.Top;
226 if (grad->type == GRAD_SQUARE) {
227 if (sW > sH) sH = sW; else sW = sH;
228 } else if (grad->type == GRAD_RADIAL) {
229 sW = 0.5 + sqrt ((double)sW*(double)sW + (double)sH*(double)sH);
231 } else if (grad->type == GRAD_ELLIPTICAL) {
232 sW = 0.5 + (double)sW * 1.4142;
233 sH = 0.5 + (double)sH * 1.4142;
236 nZW = (aRect.Right - aRect.Left) * grad->offset_x / 100;
237 nZH = (aRect.Bottom - aRect.Top) * grad->offset_y / 100;
238 bX = grad->border * sW / 100;
239 bY = grad->border * sH / 100;
240 cx = aRect.Left + nZW;
241 cy = aRect.Top + nZH;
246 aRect.Left = cx - ((aRect.Right - aRect.Left) >> 1);
247 aRect.Top = cy - ((aRect.Bottom - aRect.Top) >> 1);
249 nSteps = grad->steps;
250 minRect = aRect.Right - aRect.Left;
251 if (aRect.Bottom - aRect.Top < minRect) minRect = aRect.Bottom - aRect.Top;
255 nSteps = minRect / 2;
257 nSteps = minRect / 4;
259 if (abs(greenSteps) > mr) mr = abs(greenSteps);
260 if (abs(blueSteps) > mr) mr = abs(blueSteps);
261 if (mr < nSteps) nSteps = mr;
266 sRight = aRect.Right;
267 sBottom = aRect.Bottom;
268 sInc = (double) minRect / (double) nSteps * 0.5;
271 poly[0].x = rRect.Left;
272 poly[0].y = rRect.Top;
273 poly[1].x = rRect.Right;
274 poly[1].y = rRect.Top;
275 poly[2].x = rRect.Right;
276 poly[2].y = rRect.Bottom;
277 poly[3].x = rRect.Left;
278 poly[3].y = rRect.Bottom;
279 ctx->drw->set_fg_color(drw_data, &gcol);
280 ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
282 for (i = 0; i < nSteps; i++) {
283 aRect.Left = (long) (sLeft += sInc);
284 aRect.Top = (long) (sTop += sInc);
285 aRect.Right = (long) (sRight -= sInc);
286 aRect.Bottom = (long) (sBottom -= sInc);
287 if (aRect.Bottom - aRect.Top < 2 || aRect.Right - aRect.Left < 2)
290 gcol.red = grad->start.red + (redSteps * (i+1) / nSteps);
291 gcol.green = grad->start.green + (greenSteps * (i+1) / nSteps);
292 gcol.blue = grad->start.blue + (blueSteps * (i+1) / nSteps);
293 ctx->drw->set_fg_color(drw_data, &gcol);
295 if (grad->type == GRAD_RADIAL || grad->type == GRAD_ELLIPTICAL) {
296 ctx->drw->draw_arc(drw_data, 1, aRect.Left, aRect.Top,
297 aRect.Right - aRect.Left, aRect.Bottom - aRect.Top,
300 poly[0].x = aRect.Left;
301 poly[0].y = aRect.Top;
302 poly[1].x = aRect.Right;
303 poly[1].y = aRect.Top;
304 poly[2].x = aRect.Right;
305 poly[2].y = aRect.Bottom;
306 poly[3].x = aRect.Left;
307 poly[3].y = aRect.Bottom;
308 poly_rotate (&poly[0], 4, cx, cy, fAngle);
309 ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
315 r_draw_gradient (ImpRenderCtx *ctx, void *drw_data, iks *node)
322 stil = r_get_style (ctx, node, "draw:fill-gradient-name");
323 x = iks_find_with_attrib (iks_find (ctx->styles, "office:styles"),
324 "draw:gradient", "draw:name", stil);
326 memset (&grad, 0, sizeof (Gradient));
331 tmp = iks_find_attrib (x, "draw:start-color");
332 if (tmp) r_parse_color (tmp, &grad.start);
333 tmp = iks_find_attrib (x, "draw:start-intensity");
335 int val = atoi (tmp);
336 grad.start.red = grad.start.red * val / 100;
337 grad.start.green = grad.start.green * val / 100;
338 grad.start.blue = grad.start.blue * val / 100;
340 tmp = iks_find_attrib (x, "draw:end-color");
341 if (tmp) r_parse_color (tmp, &grad.end);
342 tmp = iks_find_attrib (x, "draw:end-intensity");
344 int val = atoi (tmp);
345 grad.end.red = grad.end.red * val / 100;
346 grad.end.green = grad.end.green * val / 100;
347 grad.end.blue = grad.end.blue * val / 100;
349 tmp = iks_find_attrib (x, "draw:angle");
350 if (tmp) grad.angle = atoi(tmp) % 3600;
351 tmp = iks_find_attrib (x, "draw:border");
352 if (tmp) grad.border = atoi(tmp);
353 tmp = r_get_style (ctx, node, "draw:gradient-step-count");
354 if (tmp) grad.steps = atoi (tmp);
355 tmp = iks_find_attrib (x, "draw:cx");
356 if (tmp) grad.offset_x = atoi (tmp);
357 tmp = iks_find_attrib (x, "draw:cy");
358 if (tmp) grad.offset_y = atoi (tmp);
359 tmp = iks_find_attrib (x, "draw:style");
360 if (iks_strcmp (tmp, "linear") == 0)
361 grad.type = GRAD_LINEAR;
362 else if (iks_strcmp (tmp, "axial") == 0)
363 grad.type = GRAD_AXIAL;
364 else if (iks_strcmp (tmp, "radial") == 0)
365 grad.type = GRAD_RADIAL;
366 else if (iks_strcmp (tmp, "rectangular") == 0)
367 grad.type = GRAD_RECTANGULAR;
368 else if (iks_strcmp (tmp, "ellipsoid") == 0)
369 grad.type = GRAD_ELLIPTICAL;
370 else if (iks_strcmp (tmp, "square") == 0)
371 grad.type = GRAD_SQUARE;
373 if (grad.type == -1) return;
376 // ctx->gc = gdk_gc_new (ctx->d);
377 // gdk_gc_copy (ctx->gc, gc);
379 if (grad.type == GRAD_LINEAR || grad.type == GRAD_AXIAL)
380 r_draw_gradient_simple (ctx, drw_data, &grad);
382 r_draw_gradient_complex (ctx, drw_data, &grad);
384 // gdk_gc_unref (ctx->gc);