cairo-renderer.cpp revision 38a54b600f5dae18f0432b96d0fbda699c31b974
/** \file
* Rendering with Cairo.
*/
/*
* Author:
* Miklos Erdelyi <erdelyim@gmail.com>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
* 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 "libnrtype/Layout-TNG.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
//#define TEST(_args) _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)
: _omitText(false)
{}
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. */
static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affine tr, SPStyle* style, CairoRenderContext *ctx)
{
bool render = true;
} else {
render = false; // stroke width zero and marker is thus scaled down to zero, skip
}
}
if (render) {
if (marker_item) {
}
}
}
{
return;
}
return;
}
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if (marker->orient_auto) {
} else {
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(pathv.begin()->front().pointAt(0));
}
}
}
// MID marker
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
// START position
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
if (marker->orient_auto) {
} else {
}
}
// MID position
{
/* 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 */
if (marker->orient_auto) {
} else {
}
++curve_it1;
++curve_it2;
}
}
// END position
if (marker->orient_auto) {
} else {
}
}
}
}
// END marker
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
/* Get reference to last curve in the path.
* For moveto-only path, this returns the "closing line segment". */
if (index > 0) {
index--;
}
if (marker->orient_auto) {
} else {
}
}
}
}
{
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);
}
}
{
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 converts the item to a raster image and includes the image into the cairo renderer.
It is only used for filters and then only when rendering filters as bitmaps is requested.
*/
{
// The code was adapted from sp_selection_create_bitmap_copy in selection-chemistry.cpp
// Calculate resolution
double res;
/** @TODO reimplement the resolution stuff (WHY?)
*/
if(res == 0) {
}
// Get the bounding box of the selection in document coordinates.
// no bbox, e.g. empty group
if (!bbox) {
return;
}
Geom::Rect bboxrect(Geom::Rect(Geom::Point(bbox->min()[Geom::X], bbox->min()[Geom::Y]), Geom::Point(bbox->max()[Geom::X], bbox->max()[Geom::Y])));
// assign the object dimension clipped on the document, no need to draw on area not on canvas
// no bbox, e.g. empty group
if (!bbox) {
return;
}
// The width and height of the bitmap in pixels
unsigned width = (unsigned) floor ((bbox->max()[Geom::X] - bbox->min()[Geom::X]) * (res / PX_PER_IN));
unsigned height =(unsigned) floor ((bbox->max()[Geom::Y] - bbox->min()[Geom::Y]) * (res / PX_PER_IN));
// Scale to exactly fit integer bitmap inside bounding box
// Location of bounding box in document coordinates.
// For default 90 dpi, snap bitmap to pixel grid
// Remove the negations when the inversion is gone.
}
// Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
// Matix to put bitmap in correct place on document
// ctx matrix already includes item transformation. We must substract.
// Do the export
if (pb) {
unsigned int w = gdk_pixbuf_get_width(pb);
unsigned int h = gdk_pixbuf_get_height(pb);
pb = 0;
}
}
{
// Check item's visibility
return;
}
}
if (SP_IS_ROOT(item)) {
TRACE(("root\n"));
} else if (SP_IS_SYMBOL(item)) {
TRACE(("symbol\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_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.
}
// TODO change this to accept a const SPItem:
{
// skip text if _omitText is true
return;
}
// Draw item on a temporary surface so a mask, clip path, or opacity can be applied to it.
if (state->need_layer) {
}
if (state->need_layer)
}
bool
CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool pageBoundingBox, SPItem *base)
{
// PLEASE note when making changes to the boundingbox and transform calculation, corresponding changes should be made to PDFLaTeXRenderer::setupDocument !!!
if (!base) {
}
NRRect d;
if (pageBoundingBox) {
} else {
}
if (ctx->_vector_based_target) {
// convert from px to pt
}
if (ret && !pageBoundingBox)
{
if (ctx->_vector_based_target)
}
return ret;
}
#include "macros.h" // SP_PRINT_*
// Apply an SVG clip path
void
{
return;
//SP_PRINT_DRECT("clipd", cp->display->bbox);
ctx->setTransform(&t);
}
TRACE(("BEGIN clip\n"));
if (SP_IS_ITEM(child)) {
// combine transform of the item in clippath and the item using clippath:
// render this item in clippath
// TODO fix this call to accept const items
}
}
TRACE(("END clip\n"));
// do clipping only if this was the first call to applyClipPath
}
// Apply an SVG mask
void
{
return;
//SP_PRINT_DRECT("maskd", &mask->display->bbox);
// TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ?
ctx->setTransform(&t);
}
// Clip mask contents... but...
// The mask's bounding box is the "geometric bounding box" which doesn't allow for
// filters which extend outside the bounding box. So don't clip.
// 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)) {
// TODO fix const correctness:
}
}
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:fileencoding=utf-8:textwidth=99 :