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.
14
#define GRAD_RECTANGULAR 3
16
#define GRAD_ELLIPTICAL 5
18
typedef struct Gradient_s {
31
typedef struct Rectangle_s {
39
poly_rotate (ImpPoint *poly, int n, int cx, int cy, double fAngle)
44
for (i = 0; i < n; i++) {
47
poly->x = (cos(fAngle) * nX + sin(fAngle) * nY) + cx;
48
poly->y = - (sin(fAngle)* nX - cos(fAngle) * nY) + cy;
54
r_draw_gradient_simple (ImpRenderCtx *ctx, void *drw_data, Gradient *grad)
56
Rectangle rRect = { 0, 0, ctx->pix_w - 1, ctx->pix_h - 1 };
57
Rectangle aRect, aFullRect;
58
ImpPoint poly[4], tempoly[2];
60
double fW, fH, fDX, fDY, fAngle;
61
double fScanLine, fScanInc;
62
long redSteps, greenSteps, blueSteps;
64
int i, nSteps, nSteps2;
67
cx = rRect.Left + (rRect.Right - rRect.Left) / 2;
68
cy = rRect.Top + (rRect.Bottom - rRect.Top) / 2;
71
aRect.Top--; aRect.Left--; aRect.Bottom++; aRect.Right++;
72
fW = rRect.Right - rRect.Left;
73
fH = rRect.Bottom - rRect.Top;
74
fAngle = (((double) grad->angle) * 3.14 / 1800.0);
75
fDX = fW * fabs (cos (fAngle)) + fH * fabs (sin (fAngle));
76
fDY = fH * fabs (cos (fAngle)) + fW * fabs (sin (fAngle));
77
fDX = (fDX - fW) * 0.5 - 0.5;
78
fDY = (fDY - fH) * 0.5 - 0.5;
85
nBorder = grad->border * (aRect.Bottom - aRect.Top) / 100;
86
if (grad->type == GRAD_LINEAR) {
91
aRect.Bottom -= nBorder;
94
if (aRect.Top > (aRect.Bottom - 1))
95
aRect.Top = aRect.Bottom - 1;
97
poly[0].x = aFullRect.Left;
98
poly[0].y = aFullRect.Top;
99
poly[1].x = aFullRect.Right;
100
poly[1].y = aFullRect.Top;
101
poly[2].x = aRect.Right;
102
poly[2].y = aRect.Top;
103
poly[3].x = aRect.Left;
104
poly[3].y = aRect.Top;
105
poly_rotate (&poly[0], 4, cx, cy, fAngle);
107
redSteps = grad->end.red - grad->start.red;
108
greenSteps = grad->end.green - grad->start.green;
109
blueSteps = grad->end.blue - grad->start.blue;
110
nSteps = grad->steps;
113
mr = aRect.Bottom - aRect.Top;
119
if (abs(greenSteps) > mr) mr = abs(greenSteps);
120
if (abs(blueSteps) > mr) mr = abs(blueSteps);
121
if (mr < nSteps) nSteps = mr;
124
if (grad->type == GRAD_AXIAL) {
125
if (nSteps & 1) nSteps++;
126
nSteps2 = nSteps + 2;
132
nSteps2 = nSteps + 1;
136
fScanLine = aRect.Top;
137
fScanInc = (double)(aRect.Bottom - aRect.Top) / (double)nSteps;
139
for (i = 0; i < nSteps2; i++) {
141
ctx->drw->set_fg_color(drw_data, &gcol);
142
ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
144
aRect.Top = (long)(fScanLine += fScanInc);
146
tempoly[0].x = aFullRect.Left;
147
tempoly[0].y = aFullRect.Bottom;
148
tempoly[1].x = aFullRect.Right;
149
tempoly[1].y = aFullRect.Bottom;
151
tempoly[0].x = aRect.Left;
152
tempoly[0].y = aRect.Top;
153
tempoly[1].x = aRect.Right;
154
tempoly[1].y = aRect.Top;
156
poly_rotate (&tempoly[0], 2, cx, cy, fAngle);
159
poly[2] = tempoly[1];
160
poly[3] = tempoly[0];
162
if (grad->type == GRAD_LINEAR) {
163
gcol.red = grad->start.red + ((redSteps * i) / nSteps2);
164
gcol.green = grad->start.green + ((greenSteps * i) / nSteps2);
165
gcol.blue = grad->start.blue + ((blueSteps * i) / nSteps2);
168
gcol.red = grad->end.red;
169
gcol.green = grad->end.green;
170
gcol.blue = grad->end.blue;
172
if (i <= (nSteps / 2)) {
173
gcol.red = grad->end.red - ((redSteps * i) / nSteps2);
174
gcol.green = grad->end.green - ((greenSteps * i) / nSteps2);
175
gcol.blue = grad->end.blue - ((blueSteps * i) / nSteps2);
177
int i2 = i - nSteps / 2;
178
gcol.red = grad->start.red + ((redSteps * i2) / nSteps2);
179
gcol.green = grad->start.green + ((greenSteps * i2) / nSteps2);
180
gcol.blue = grad->start.blue + ((blueSteps * i2) / nSteps2);
188
r_draw_gradient_complex (ImpRenderCtx *ctx, void *drw_data, Gradient *grad)
190
Rectangle rRect = { 0, 0, ctx->pix_w - 1, ctx->pix_h - 1 };
191
Rectangle aRect = rRect;
194
double fAngle = (((double) grad->angle) * 3.14 / 1800.0);
195
long redSteps, greenSteps, blueSteps;
202
double sTop, sLeft, sRight, sBottom, sInc;
205
redSteps = grad->end.red - grad->start.red;
206
greenSteps = grad->end.green - grad->start.green;
207
blueSteps = grad->end.blue - grad->start.blue;
209
if (grad->type == GRAD_SQUARE || grad->type == GRAD_RECTANGULAR) {
210
double fW = aRect.Right - aRect.Left;
211
double fH = aRect.Bottom - aRect.Top;
212
double fDX = fW * fabs (cos (fAngle)) + fH * fabs (sin (fAngle));
213
double fDY = fH * fabs (cos (fAngle)) + fW * fabs (sin (fAngle));
214
fDX = (fDX - fW) * 0.5 - 0.5;
215
fDY = (fDY - fH) * 0.5 - 0.5;
222
sW = aRect.Right - aRect.Left;
223
sH = aRect.Bottom - aRect.Top;
225
if (grad->type == GRAD_SQUARE) {
226
if (sW > sH) sH = sW; else sW = sH;
227
} else if (grad->type == GRAD_RADIAL) {
228
sW = 0.5 + sqrt ((double)sW*(double)sW + (double)sH*(double)sH);
230
} else if (grad->type == GRAD_ELLIPTICAL) {
231
sW = 0.5 + (double)sW * 1.4142;
232
sH = 0.5 + (double)sH * 1.4142;
235
nZW = (aRect.Right - aRect.Left) * grad->offset_x / 100;
236
nZH = (aRect.Bottom - aRect.Top) * grad->offset_y / 100;
237
bX = grad->border * sW / 100;
238
bY = grad->border * sH / 100;
239
cx = aRect.Left + nZW;
240
cy = aRect.Top + nZH;
245
aRect.Left = cx - ((aRect.Right - aRect.Left) >> 1);
246
aRect.Top = cy - ((aRect.Bottom - aRect.Top) >> 1);
248
nSteps = grad->steps;
249
minRect = aRect.Right - aRect.Left;
250
if (aRect.Bottom - aRect.Top < minRect) minRect = aRect.Bottom - aRect.Top;
254
nSteps = minRect / 2;
256
nSteps = minRect / 4;
258
if (abs(greenSteps) > mr) mr = abs(greenSteps);
259
if (abs(blueSteps) > mr) mr = abs(blueSteps);
260
if (mr < nSteps) nSteps = mr;
265
sRight = aRect.Right;
266
sBottom = aRect.Bottom;
267
sInc = (double) minRect / (double) nSteps * 0.5;
270
poly[0].x = rRect.Left;
271
poly[0].y = rRect.Top;
272
poly[1].x = rRect.Right;
273
poly[1].y = rRect.Top;
274
poly[2].x = rRect.Right;
275
poly[2].y = rRect.Bottom;
276
poly[3].x = rRect.Left;
277
poly[3].y = rRect.Bottom;
278
ctx->drw->set_fg_color(drw_data, &gcol);
279
ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
281
for (i = 0; i < nSteps; i++) {
282
aRect.Left = (long) (sLeft += sInc);
283
aRect.Top = (long) (sTop += sInc);
284
aRect.Right = (long) (sRight -= sInc);
285
aRect.Bottom = (long) (sBottom -= sInc);
286
if (aRect.Bottom - aRect.Top < 2 || aRect.Right - aRect.Left < 2)
289
gcol.red = grad->start.red + (redSteps * (i+1) / nSteps);
290
gcol.green = grad->start.green + (greenSteps * (i+1) / nSteps);
291
gcol.blue = grad->start.blue + (blueSteps * (i+1) / nSteps);
292
ctx->drw->set_fg_color(drw_data, &gcol);
294
if (grad->type == GRAD_RADIAL || grad->type == GRAD_ELLIPTICAL) {
295
ctx->drw->draw_arc(drw_data, 1, aRect.Left, aRect.Top,
296
aRect.Right - aRect.Left, aRect.Bottom - aRect.Top,
299
poly[0].x = aRect.Left;
300
poly[0].y = aRect.Top;
301
poly[1].x = aRect.Right;
302
poly[1].y = aRect.Top;
303
poly[2].x = aRect.Right;
304
poly[2].y = aRect.Bottom;
305
poly[3].x = aRect.Left;
306
poly[3].y = aRect.Bottom;
307
poly_rotate (&poly[0], 4, cx, cy, fAngle);
308
ctx->drw->draw_polygon(drw_data, 1, &poly[0], 4);
314
r_draw_gradient (ImpRenderCtx *ctx, void *drw_data, iks *node)
321
stil = r_get_style (ctx, node, "draw:fill-gradient-name");
322
x = iks_find_with_attrib (iks_find (ctx->styles, "office:styles"),
323
"draw:gradient", "draw:name", stil);
325
memset (&grad, 0, sizeof (Gradient));
330
tmp = iks_find_attrib (x, "draw:start-color");
331
if (tmp) r_parse_color (tmp, &grad.start);
332
tmp = iks_find_attrib (x, "draw:start-intensity");
334
int val = atoi (tmp);
335
grad.start.red = grad.start.red * val / 100;
336
grad.start.green = grad.start.green * val / 100;
337
grad.start.blue = grad.start.blue * val / 100;
339
tmp = iks_find_attrib (x, "draw:end-color");
340
if (tmp) r_parse_color (tmp, &grad.end);
341
tmp = iks_find_attrib (x, "draw:end-intensity");
343
int val = atoi (tmp);
344
grad.end.red = grad.end.red * val / 100;
345
grad.end.green = grad.end.green * val / 100;
346
grad.end.blue = grad.end.blue * val / 100;
348
tmp = iks_find_attrib (x, "draw:angle");
349
if (tmp) grad.angle = atoi(tmp) % 3600;
350
tmp = iks_find_attrib (x, "draw:border");
351
if (tmp) grad.border = atoi(tmp);
352
tmp = r_get_style (ctx, node, "draw:gradient-step-count");
353
if (tmp) grad.steps = atoi (tmp);
354
tmp = iks_find_attrib (x, "draw:cx");
355
if (tmp) grad.offset_x = atoi (tmp);
356
tmp = iks_find_attrib (x, "draw:cy");
357
if (tmp) grad.offset_y = atoi (tmp);
358
tmp = iks_find_attrib (x, "draw:style");
359
if (iks_strcmp (tmp, "linear") == 0)
360
grad.type = GRAD_LINEAR;
361
else if (iks_strcmp (tmp, "axial") == 0)
362
grad.type = GRAD_AXIAL;
363
else if (iks_strcmp (tmp, "radial") == 0)
364
grad.type = GRAD_RADIAL;
365
else if (iks_strcmp (tmp, "rectangular") == 0)
366
grad.type = GRAD_RECTANGULAR;
367
else if (iks_strcmp (tmp, "ellipsoid") == 0)
368
grad.type = GRAD_ELLIPTICAL;
369
else if (iks_strcmp (tmp, "square") == 0)
370
grad.type = GRAD_SQUARE;
372
if (grad.type == -1) return;
375
// ctx->gc = gdk_gc_new (ctx->d);
376
// gdk_gc_copy (ctx->gc, gc);
378
if (grad.type == GRAD_LINEAR || grad.type == GRAD_AXIAL)
379
r_draw_gradient_simple (ctx, drw_data, &grad);
381
r_draw_gradient_complex (ctx, drw_data, &grad);
383
// gdk_gc_unref (ctx->gc);