2
* Copyright © 2006 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
28
COMPIZ_PLUGIN_20081216 (imgsvg, SvgPluginVTable)
31
svgSet (CompAction *action,
32
CompAction::State state,
33
CompOption::Vector &options)
38
xid = CompOption::getIntOptionNamed (options, "window");
39
w = screen->findWindow (xid);
48
memset (p, 0, sizeof (p));
50
p[0].gravity = CompOption::getIntOptionNamed (options, "gravity0",
51
GRAVITY_NORTH | GRAVITY_WEST);
53
p[0].x = CompOption::getIntOptionNamed (options, "x0");
54
p[0].y = CompOption::getIntOptionNamed (options, "y0");
56
p[1].gravity = CompOption::getIntOptionNamed (options, "gravity1",
57
GRAVITY_SOUTH | GRAVITY_EAST);
59
p[1].x = CompOption::getIntOptionNamed (options, "x1");
60
p[1].y = CompOption::getIntOptionNamed (options, "y1");
62
data = CompOption::getStringOptionNamed (options, "data");
69
static const CompMetadata::OptionInfo svgOptionInfo[] = {
70
{ "set", "action", 0, svgSet, NULL }
73
SvgScreen::SvgScreen (CompScreen *screen) :
74
PrivateHandler<SvgScreen, CompScreen> (screen),
77
if (!imgsvgVTable->getMetadata ()->initOptions (svgOptionInfo,
84
ScreenInterface::setHandler (screen, true);
87
SvgScreen::~SvgScreen ()
92
SvgScreen::getOptions ()
98
SvgScreen::setOption (const char *name,
99
CompOption::Value &value)
103
o = CompOption::findOption (opt, name);
107
return CompOption::setOption (*o, value);
111
SvgScreen::fileToImage (CompString &path,
116
CompString fileName = path;
118
int len = fileName.length ();
120
if (len < 4 || fileName.substr (len - 4, 4) != ".svg")
123
status = readSvgToImage (fileName.c_str (), size, data);
127
stride = size.width () * 4;
131
status = screen->fileToImage (path, size, stride, data);
137
SvgScreen::handleCompizEvent (const char *plugin,
139
CompOption::Vector &options)
141
screen->handleCompizEvent (plugin, event, options);
143
if (strcmp (plugin, "zoom") == 0)
145
int output = CompOption::getIntOptionNamed (options, "output");
148
if (strcmp (event, "in") == 0)
150
zoom.setGeometry (CompOption::getIntOptionNamed (options, "x1"),
151
CompOption::getIntOptionNamed (options, "y1"),
152
CompOption::getIntOptionNamed (options, "x2"),
153
CompOption::getIntOptionNamed (options, "y2"));
155
else if (strcmp (event, "out") == 0)
157
zoom.setGeometry (0, 0, 0, 0);
164
SvgScreen::readSvgToImage (const char *file,
168
cairo_surface_t *surface;
169
std::ifstream svgFile;
170
GError *error = NULL;
171
RsvgHandle *svgHandle;
172
RsvgDimensionData svgDimension;
175
if (!svgFile.is_open ())
179
svgHandle = rsvg_handle_new_from_file (file, &error);
183
rsvg_handle_get_dimensions (svgHandle, &svgDimension);
185
size.setWidth (svgDimension.width);
186
size.setHeight (svgDimension.height);
188
data = malloc (svgDimension.width * svgDimension.height * 4);
191
rsvg_handle_free (svgHandle);
195
surface = cairo_image_surface_create_for_data ((unsigned char *) data,
199
svgDimension.width * 4);
204
cr = cairo_create (surface);
206
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
208
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
210
rsvg_handle_render_cairo (svgHandle, cr);
213
cairo_surface_destroy (surface);
216
rsvg_handle_free (svgHandle);
221
SvgWindow::SvgWindow (CompWindow *window) :
222
PrivateHandler<SvgWindow, CompWindow> (window),
223
sScreen (SvgScreen::get (screen)),
224
gScreen (GLScreen::get (screen)),
226
gWindow (GLWindow::get (window)),
231
GLWindowInterface::setHandler (gWindow, false);
234
SvgWindow::~SvgWindow ()
238
rsvg_handle_free (source->svg);
244
finiTexture (context->texture[0]);
250
SvgWindow::glDraw (const GLMatrix &transform,
251
GLFragment::Attrib &fragment,
252
const CompRegion ®ion,
255
bool status = gWindow->glDraw (transform, fragment, region, mask);
260
const CompRegion ® = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ?
261
infiniteRegion : region;
263
if (context && reg.numRects ())
265
GLTexture::MatrixList matrix (1);
269
CompRect rect = context->box.boundingRect ();
271
x1 = MIN (rect.x1 (), sScreen->zoom.x1 ());
272
y1 = MIN (rect.y1 (), sScreen->zoom.y1 ());
273
x2 = MAX (rect.x2 (), sScreen->zoom.x2 ());
274
y2 = MAX (rect.y2 (), sScreen->zoom.y2 ());
276
rect.setGeometry (x1, y1, x2 - x1, y2 - y1);
278
for (i = 0; i < context->texture[0].textures.size (); i++)
280
matrix[0] = context->texture[0].matrices[i];
282
gWindow->geometry ().reset ();
283
gWindow->glAddGeometry (matrix, context->box, reg);
285
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
286
mask |= PAINT_WINDOW_BLEND_MASK;
288
gWindow->glDrawTexture (context->texture[0].textures[i], fragment, mask);
290
if (rect.width () > 0 && rect.height () > 0)
292
float xScale, yScale;
297
rect.setGeometry (rect.x1 () - 1,
302
xScale = screen->width () /
303
(float) (sScreen->zoom.width ());
304
yScale = screen->height () /
305
(float) (sScreen->zoom.height ());
310
width = dx * xScale + 0.5f;
311
height = dy * yScale + 0.5f;
313
if (rect != context->rect ||
314
width != context->size.width () ||
315
height != context->size.height ())
317
float x1, y1, x2, y2;
319
context->rect = rect;
320
context->size.setWidth (width);
321
context->size.setHeight (height);
323
dx = context->box.boundingRect ().width ();
324
dy = context->box.boundingRect ().height ();
326
x1 = (rect.x1 () - context->box.boundingRect ().x ()) / dx;
327
y1 = (rect.y1 () - context->box.boundingRect ().y ()) / dy;
328
x2 = (rect.x2 () - context->box.boundingRect ().x ()) / dx;
329
y2 = (rect.y2 () - context->box.boundingRect ().y ()) / dy;
331
finiTexture (context->texture[1]);
333
if (initTexture (context->source, context->texture[1],
336
renderSvg (context->source, context->texture[1],
337
context->size, x1, y1, x2, y2);
343
for (j = 0; j < context->texture[1].textures.size (); j++)
345
GLTexture::Filter saveFilter;
348
matrix[0] = context->texture[1].matrices[j];
350
saveFilter = gScreen->filter (SCREEN_TRANS_FILTER);
351
gScreen->setFilter (SCREEN_TRANS_FILTER, GLTexture::Good);
353
gWindow->geometry ().reset ();
354
gWindow->glAddGeometry (matrix, r, reg);
356
gWindow->glDrawTexture (context->texture[1].textures[j],
359
gScreen->setFilter (SCREEN_TRANS_FILTER, saveFilter);
362
else if (context->texture[1].size.width ())
364
finiTexture (context->texture[1]);
365
initTexture (source, context->texture[1], CompSize ());
367
memset (&context->rect, 0, sizeof (BoxRec));
368
context->size.setWidth (0);
369
context->size.setHeight (0);
378
SvgWindow::moveNotify (int dx,
384
context->box.translate (dx, dy);
388
window->moveNotify (dx, dy, immediate);
392
SvgWindow::resizeNotify (int dx,
400
window->resizeNotify (dx, dy, dwidth, dheight);
404
SvgWindow::updateSvgMatrix ()
407
GLTexture::Matrix *m;
411
rect = context->box.boundingRect ();
412
texture = &context->texture[0];
414
if (texture->matrices.size () != texture->textures.size ())
415
texture->matrices.resize (texture->textures.size ());
417
for (i = 0; i < texture->textures.size (); i++)
419
m = &texture->matrices[i];
420
*m = texture->textures[i]->matrix ();
422
m->xx *= (float) texture->size.width () / rect.width ();
423
m->yy *= (float) texture->size.height () / rect.height ();
425
m->x0 -= (rect.x () * m->xx);
426
m->y0 -= (rect.y () * m->yy);
429
texture = &context->texture[1];
431
if (texture->matrices.size () != texture->textures.size ())
432
texture->matrices.resize (texture->textures.size ());
434
for (i = 0; i < texture->textures.size (); i++)
436
m = &texture->matrices[i];
437
*m = texture->textures[i]->matrix ();
439
m->xx *= (float) texture->size.width () / context->rect.width ();
440
m->yy *= (float) texture->size.height () / context->rect.height ();
442
m->x0 -= (context->rect.x () * m->xx);
443
m->y0 -= (context->rect.y () * m->yy);
448
SvgWindow::updateSvgContext ()
455
finiTexture (context->texture[0]);
456
finiTexture (context->texture[1]);
460
context = new SvgContext;
465
initTexture (source, context->texture[1], context->size);
467
context->source = source;
469
wSize.setWidth (window->geometry ().width ());
470
wSize.setHeight (window->geometry ().height ());
472
decor_apply_gravity (source->p1.gravity,
473
source->p1.x, source->p1.y,
474
wSize.width (), wSize.height (),
477
decor_apply_gravity (source->p2.gravity,
478
source->p2.x, source->p2.y,
479
wSize.width (), wSize.height (),
484
x2 = MIN (x2, wSize.width ());
485
y2 = MIN (y2, wSize.height ());
487
if (!initTexture (source, context->texture[0], wSize))
494
renderSvg (source, context->texture[0], wSize, 0.0f, 0.0f, 1.0f, 1.0f);
496
initTexture (source, context->texture[1], CompSize ());
498
context->box += CompRect (x1, y1, x2 - x1, y2 - y1);
499
context->box.translate (window->geometry ().x (), window->geometry ().y ());
506
SvgWindow::renderSvg (SvgSource *source,
517
cairo_save (texture.cr);
519
cairo_set_operator (texture.cr, CAIRO_OPERATOR_SOURCE);
520
cairo_set_source_rgba (texture.cr, 1.0, 1.0, 1.0, 0.0);
521
cairo_paint (texture.cr);
522
cairo_set_operator (texture.cr, CAIRO_OPERATOR_OVER);
524
cairo_scale (texture.cr, 1.0 / w, 1.0 / h);
526
cairo_scale (texture.cr,
527
(double) size.width () / source->dimension.width,
528
(double) size.height () / source->dimension.height);
530
cairo_translate (texture.cr,
531
-x1 * source->dimension.width,
532
-y1 * source->dimension.height);
534
rsvg_handle_render_cairo (source->svg, texture.cr);
536
cairo_restore (texture.cr);
540
SvgWindow::initTexture (SvgSource *source,
544
cairo_surface_t *surface;
545
Display *dpy = screen->dpy ();
548
texture.pixmap = None;
551
if (size.width () && size.height ())
553
XWindowAttributes attr;
554
XGetWindowAttributes (dpy, window->id (), &attr);
556
texture.pixmap = XCreatePixmap (dpy, screen->root (),
557
size.width (), size.height (),
561
GLTexture::bindPixmapToTexture (texture.pixmap,
562
size.width (), size.height (), attr.depth);
563
if (texture.textures.empty ())
565
compLogMessage ("svg", CompLogLevelInfo,
566
"Couldn't bind pixmap 0x%x to texture",
567
(int) texture.pixmap);
569
XFreePixmap (dpy, texture.pixmap);
574
surface = cairo_xlib_surface_create (dpy, texture.pixmap, attr.visual,
575
size.width (), size.height ());
576
texture.cr = cairo_create (surface);
577
cairo_surface_destroy (surface);
584
SvgWindow::finiTexture (SvgTexture &texture)
587
cairo_destroy (texture.cr);
590
XFreePixmap (screen->dpy (), texture.pixmap);
594
SvgWindow::setSvg (CompString &data,
597
RsvgHandle *svg = NULL;
598
GError *error = NULL;
603
svg = rsvg_handle_new_from_data ((guint8 *) data.c_str (),
604
data.length (), &error);
608
rsvg_handle_free (source->svg);
613
source = new SvgSource;
618
if (source && source->svg)
625
gWindow->glDrawSetEnabled (this, true);
626
rsvg_handle_get_dimensions (svg, &source->dimension);
633
rsvg_handle_free (svg);
643
finiTexture (context->texture[0]);
648
gWindow->glDrawSetEnabled (this, false);
653
SvgPluginVTable::init ()
655
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
658
getMetadata ()->addFromOptionInfo (svgOptionInfo, SVG_OPTION_NUM);
659
getMetadata ()->addFromFile (name ());
667
SvgPluginVTable::fini ()