cairo-renderer.cpp revision c87a66337fedd13cf951d99e604362432220deb5
#define __SP_CAIRO_RENDERER_C__
/** \file
* Rendering with Cairo.
*/
/*
* Author:
* Miklos Erdelyi <erdelyim@gmail.com>
*
* Copyright (C) 2006 Miklos Erdelyi
*
* Licensed under GNU GPL
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_BACKEND
#endif
#ifndef PANGO_ENABLE_ENGINE
#define PANGO_ENABLE_ENGINE
#endif
#include <signal.h>
#include <errno.h>
#include <libnr/n-art-bpath.h>
#include <libnr/nr-matrix-ops.h>
#include <libnr/nr-matrix-fns.h>
#include <libnr/nr-matrix-translate-ops.h>
#include <libnr/nr-scale-matrix-ops.h>
#include "libnr/nr-matrix-rotate-ops.h"
#include "libnr/nr-matrix-translate-ops.h"
#include "libnr/nr-rotate-fns.h"
#include "libnr/nr-scale-ops.h"
#include "libnr/nr-scale-translate-ops.h"
#include "libnr/nr-translate-matrix-ops.h"
#include "libnr/nr-translate-scale-ops.h"
#include "libnr/nr-convert2geom.h"
#include "display/nr-arena.h"
#include "display/nr-arena-item.h"
#include "display/nr-arena-group.h"
#include "display/canvas-bpath.h"
#include "sp-item.h"
#include "sp-item-group.h"
#include "style.h"
#include "marker.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
#include "sp-root.h"
#include "sp-shape.h"
#include "sp-use.h"
#include "sp-text.h"
#include "sp-flowtext.h"
#include "sp-image.h"
#include "sp-symbol.h"
#include "sp-pattern.h"
#include "sp-mask.h"
#include "sp-clippath.h"
#include <unit-constants.h>
#include "helper/png-write.h"
#include "helper/pixbuf-ops.h"
#include "cairo-renderer.h"
#include "cairo-render-context.h"
#include <cairo.h>
// include support for only the compiled-in surface types
#ifdef CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
#endif
#ifdef CAIRO_HAS_PS_SURFACE
#include <cairo-ps.h>
#endif
//#define TRACE(_args) g_printf _args
// FIXME: expose these from sp-clippath/mask.cpp
struct SPClipPathView {
unsigned int key;
};
struct SPMaskView {
unsigned int key;
};
namespace Inkscape {
namespace Extension {
namespace Internal {
CairoRenderer::CairoRenderer(void)
{}
CairoRenderer::~CairoRenderer(void)
{
/* restore default signal handling for SIGPIPE */
#endif
return;
}
CairoRenderer::createContext(void)
{
// create initial render state
return new_context;
}
void
{
delete ctx;
}
/*
Here comes the rendering part which could be put into the 'render' methods of SPItems'
*/
/* The below functions are copy&pasted plus slightly modified from *_invoke_print functions. */
/* TODO FIXME: this does not render painting-marker-01-f.svg of SVG1.1 Test suite correctly. (orientation of one of the markers middle left ) */
{
/* fixme: Think (Lauris) */
/* TODO: make code prettier: lots of variables can be taken out of the loop! */
}
}
{
/* Put marker between curve_it1 and curve_it2.
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment */
}
++curve_it1;
++curve_it2;
}
}
}
}
}
}
{
while (l) {
if (SP_IS_ITEM(o)) {
}
l = g_slist_remove (l, o);
}
}
{
bool translated = false;
translated = true;
}
}
if (translated) {
}
}
{
}
{
}
{
int w, h, rs;
}
ctx->addClippingRect(image->x.computed, image->y.computed, image->width.computed, image->height.computed);
}
}
{
if (!SP_OBJECT_IS_CLONED (symbol))
return;
/* Cloned <symbol> is actually renderable */
// apply viewbox if set
if (0 /*symbol->viewBox_set*/) {
double view_width, view_height;
x = 0.0;
y = 0.0;
width = 1.0;
height = 1.0;
}
}
{
ctx->addClippingRect(root->x.computed, root->y.computed, root->width.computed, root->height.computed);
}
/**
this function convert the item to a raster image and include the raster into the cairo renderer
*/
{
g_warning("render as bitmap");
//the code now was copied from sp_selection_create_bitmap_copy
// Get the bounding box of the selection
//NR::Maybe<NR::Rect> _bbox = item->getBounds(from_2geom(sp_item_i2d_affine(item)));
// NRRect bbox = item->getBounds(from_2geom(sp_item_i2d_affine(item)));
// List of the items to show; all others will be hidden
// Remember parent and z-order of the topmost one
// Calculate resolution
double res;
/** @TODO reimplement the resolution stuff
*/
if(res == 0) {
}
// The width and height of the bitmap in pixels
// Find out if we have to run a filter
/** @TODO reimplement the filter stuff
//gchar const *filter = prefs_get_string_attribute ("options.createbitmap", "filter");
if (filter) {
// filter command is given;
// see if we have a parameter to pass to it
gchar const *param1 = prefs_get_string_attribute ("options.createbitmap", "filter_param1");
if (param1) {
if (param1[strlen(param1) - 1] == '%') {
// if the param string ends with %, interpret it as a percentage of the image's max dimension
gchar p1[256];
g_ascii_dtostr (p1, 256, ceil (g_ascii_strtod (param1, NULL) * MAX(width, height) / 100));
// the first param is always the image filename, the second is param1
run = g_strdup_printf ("%s \"%s\" %s", filter, filepath, p1);
} else {
// otherwise pass the param1 unchanged
run = g_strdup_printf ("%s \"%s\" %s", filter, filepath, param1);
}
} else {
// run without extra parameter
run = g_strdup_printf ("%s \"%s\"", filter, filepath);
}
}
*/
// Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
shift_y = -round (-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone
}
//t = t * ((NR::Matrix)ctx->getCurrentState()->transform).inverse();
// Do the export
// Run filter, if any
/*
if (run) {
g_print ("Running external filter: %s\n", run);
system (run);
}
*/
if (pb) {
unsigned int w = gdk_pixbuf_get_width(pb);
unsigned int h = gdk_pixbuf_get_height(pb);
matrix = t;
//matrix = ((NR::Matrix)ctx->getCurrentState()->transform).inverse();
//matrix.set_identity();
/*
// Create the repr for the image
Inkscape::XML::Node * repr = xml_doc->createElement("svg:image");
repr->setAttribute("xlink:href", filename);
repr->setAttribute("sodipodi:absref", filepath);
if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid
sp_repr_set_svg_double(repr, "width", width);
sp_repr_set_svg_double(repr, "height", height);
} else {
sp_repr_set_svg_double(repr, "width", (bbox.x1 - bbox.x0));
sp_repr_set_svg_double(repr, "height", (bbox.y1 - bbox.y0));
}
// Write transform
gchar *c=sp_svg_transform_write(t);
repr->setAttribute("transform", c);
g_free(c);
// add the new repr to the parent
parent->appendChild(repr);
// move to the saved position
repr->setPosition(pos > 0 ? pos + 1 : 1);
*/
}
}
{
// Check item's visibility
return;
}
}
if (SP_IS_ROOT(item)) {
TRACE(("root\n"));
} else if (SP_IS_GROUP(item)) {
TRACE(("group\n"));
} else if (SP_IS_SHAPE(item)) {
TRACE(("shape\n"));
TRACE(("use begin---\n"));
TRACE(("---use end\n"));
} else if (SP_IS_SYMBOL(item)) {
TRACE(("symbol\n"));
} else if (SP_IS_TEXT(item)) {
TRACE(("text\n"));
} else if (SP_IS_FLOWTEXT(item)) {
TRACE(("flowtext\n"));
} else if (SP_IS_IMAGE(item)) {
TRACE(("image\n"));
}
}
void
{
// If parent_has_userspace is true the parent state's transform
// This is so because we use the image's/(flow)text's transform for positioning
// instead of explicitly specifying it and letting the renderer do the
// transformation before rendering the item.
}
void
{
if (state->need_layer) {
}
if (state->need_layer)
}
bool
{
if (ctx->_vector_based_target) {
// width and height in pt
} else {
}
NRRect d;
bool pageBoundingBox = true;
if (pageBoundingBox) {
} else {
if (ctx->_vector_based_target) {
// convert from px to pt
}
}
}
#include "macros.h" // SP_PRINT_*
void
{
return;
//SP_PRINT_DRECT("clipd", cp->display->bbox);
ctx->setTransform(&t);
}
TRACE(("BEGIN clip\n"));
if (SP_IS_ITEM(child)) {
}
}
TRACE(("END clip\n"));
// do clipping only if this was the first call to applyClipPath
}
void
{
return;
//SP_PRINT_DRECT("maskd", &mask->display->bbox);
// TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ?
ctx->setTransform(&t);
}
// clip mask contents
ctx->addClippingRect(mask_bbox.x0, mask_bbox.y0, mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0);
TRACE(("BEGIN mask\n"));
if (SP_IS_ITEM(child)) {
}
}
TRACE(("END mask\n"));
}
void
calculatePreserveAspectRatio(unsigned int aspect_align, unsigned int aspect_clip, double vp_width, double vp_height,
{
if (aspect_align == SP_ASPECT_NONE)
return;
double new_width, new_height;
/* Now place viewbox to requested position */
switch (aspect_align) {
case SP_ASPECT_XMIN_YMIN:
break;
case SP_ASPECT_XMID_YMIN:
break;
case SP_ASPECT_XMAX_YMIN:
break;
case SP_ASPECT_XMIN_YMID:
break;
case SP_ASPECT_XMID_YMID:
break;
case SP_ASPECT_XMAX_YMID:
break;
case SP_ASPECT_XMIN_YMAX:
break;
case SP_ASPECT_XMID_YMAX:
break;
case SP_ASPECT_XMAX_YMAX:
break;
default:
break;
}
*height = new_height;
}
#include "clear-n_.h"
} /* namespace Internal */
} /* namespace Extension */
} /* namespace Inkscape */
/* End of GNU GPL code */
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :