marker.cpp revision 45271f563f2a5f606c949ddc1fbbc6f82a27a11f
/*
* SVG <marker> implementation
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Bryce Harrington <bryce@bryceharrington.org>
* Abhishek Sharma
* Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 1999-2003 Lauris Kaplinski
* 2004-2006 Bryce Harrington
* 2008 Johan Engelen
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <cstring>
#include <string>
#include "config.h"
#include "display/drawing-group.h"
#include "attributes.h"
#include "marker.h"
#include "document.h"
#include "document-private.h"
#include "preferences.h"
struct SPMarkerView {
unsigned int key;
};
static Inkscape::XML::Node *sp_marker_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static Inkscape::DrawingItem *sp_marker_private_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static Geom::OptRect sp_marker_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type);
static void sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destroyitems);
/**
* Initializes a SPMarkerClass object. Establishes the function pointers to the class'
* member routines in the class vtable, and sets pointers to parent classes.
*/
{
}
/**
* Initializes an SPMarker object. This notes the marker's viewBox is
* not set and initializes the marker's c2p identity matrix.
*/
static void
{
}
/**
* Virtual build callback for SPMarker.
*
* This is to be invoked immediately after creation of an SPMarker. This
* method fills an SPMarker object with its SVG attributes, and calls the
* parent class' build routine to attach the object to its document and
* repr. The result will be creation of the whole document tree.
*
* \see SPObject::build()
*/
{
}
}
/**
* Removes, releases and unrefs all children of object
*
* This is the inverse of sp_marker_build(). It must be invoked as soon
* as the marker is removed from the tree, even if it is still referenced
* by other objects. It hides and removes any views of the marker, then
* calls the parent classes' release function to deregister the object
* and release its SPRepr bindings. The result will be the destruction
* of the entire document tree.
*
* \see SPObject::release()
*/
{
// Destroy all DrawingItems etc.
// Parent class ::hide method
}
}
}
/**
* Sets an attribute, 'key', of a marker object to 'value'. Supported
* attributes that can be set with this routine include:
*
* SP_ATTR_MARKERUNITS
* SP_ATTR_REFX
* SP_ATTR_REFY
* SP_ATTR_MARKERWIDTH
* SP_ATTR_MARKERHEIGHT
* SP_ATTR_ORIENT
* SP_ATTR_VIEWBOX
* SP_ATTR_PRESERVEASPECTRATIO
*/
{
switch (key) {
case SP_ATTR_MARKERUNITS:
if (value) {
}
}
break;
case SP_ATTR_REFX:
break;
case SP_ATTR_REFY:
break;
case SP_ATTR_MARKERWIDTH:
break;
case SP_ATTR_MARKERHEIGHT:
break;
case SP_ATTR_ORIENT:
if (value) {
}
}
break;
case SP_ATTR_VIEWBOX:
if (value) {
char *eptr;
/* fixme: We have to take original item affine into account */
/* fixme: Think (Lauris) */
/* Set viewbox */
}
}
break;
/* Do setup before, so we can use break to escape */
if (value) {
int len;
gchar c[256];
const gchar *p, *e;
p = value;
while (*p && *p == 32) p += 1;
if (!*p) break;
e = p;
while (*e && *e != 32) e += 1;
len = e - p;
if (len > 8) break;
c[len] = 0;
/* Now the actual part */
if (!strcmp (c, "none")) {
} else if (!strcmp (c, "xMinYMin")) {
} else if (!strcmp (c, "xMidYMin")) {
} else if (!strcmp (c, "xMaxYMin")) {
} else if (!strcmp (c, "xMinYMid")) {
} else if (!strcmp (c, "xMidYMid")) {
} else if (!strcmp (c, "xMaxYMid")) {
} else if (!strcmp (c, "xMinYMax")) {
} else if (!strcmp (c, "xMidYMax")) {
} else if (!strcmp (c, "xMaxYMax")) {
} else {
break;
}
while (*e && *e == 32) e += 1;
if (*e) {
if (!strcmp (e, "meet")) {
} else if (!strcmp (e, "slice")) {
} else {
break;
}
}
}
break;
default:
break;
}
}
/**
* Updates <marker> when its attributes have changed. Takes care of setting up
* transformations and viewBoxes.
*/
{
// fixme: We have to set up clip here too
// Copy parent context
// Initialize tranformations
// Set up viewport
rctx.viewport = Geom::Rect::from_xywh(0, 0, marker->markerWidth.computed, marker->markerHeight.computed);
// Start with identity transform
// Viewbox is always present, either implicitly or explicitly
} else {
}
// Now set up viewbox transformation
// Determine actual viewbox in viewport coordinates
// double x = 0;
// double y = 0;
double width = 0;
double height = 0;
// x = 0.0;
// y = 0.0;
} else {
// Things are getting interesting
// Now place viewbox to requested position
/*switch (marker->aspect_align) {
case SP_ASPECT_XMIN_YMIN:
x = 0.0;
y = 0.0;
break;
case SP_ASPECT_XMID_YMIN:
x = 0.5 * (rctx.viewport.width() - width);
y = 0.0;
break;
case SP_ASPECT_XMAX_YMIN:
x = 1.0 * (rctx.viewport.width() - width);
y = 0.0;
break;
case SP_ASPECT_XMIN_YMID:
x = 0.0;
y = 0.5 * (rctx.viewport.height() - height);
break;
case SP_ASPECT_XMID_YMID:
x = 0.5 * (rctx.viewport.width() - width);
y = 0.5 * (rctx.viewport.height() - height);
break;
case SP_ASPECT_XMAX_YMID:
x = 1.0 * (rctx.viewport.width() - width);
y = 0.5 * (rctx.viewport.height() - height);
break;
case SP_ASPECT_XMIN_YMAX:
x = 0.0;
y = 1.0 * (rctx.viewport.height() - height);
break;
case SP_ASPECT_XMID_YMAX:
x = 0.5 * (rctx.viewport.width() - width);
y = 1.0 * (rctx.viewport.height() - height);
break;
case SP_ASPECT_XMAX_YMAX:
x = 1.0 * (rctx.viewport.width() - width);
y = 1.0 * (rctx.viewport.height() - height);
break;
default:
x = 0.0;
y = 0.0;
break;
}*/
}
// TODO fixme: all that work is done to figure out x and y, which are just ignored. Check why.
// viewbox transformation and reference translation
// If viewBox is set reinitialize child viewport
// Otherwise it already correct
}
// And invoke parent method
}
// As last step set additional transform of drawing group
if (v->items[i]) {
}
}
}
}
/**
* Writes the object's properties into its repr object.
*/
sp_marker_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
}
if (marker->markerUnits_set) {
} else {
}
} else {
}
} else {
}
} else {
}
} else {
}
} else {
}
if (marker->orient_set) {
if (marker->orient_auto) {
} else {
}
} else {
}
/* fixme: */
//XML Tree being used directly here while it shouldn't be....
//XML Tree being used directly here while it shouldn't be....
return repr;
}
/**
* This routine is disabled to break propagation.
*/
static Inkscape::DrawingItem *
sp_marker_private_show (SPItem */*item*/, Inkscape::Drawing &/*drawing*/, unsigned int /*key*/, unsigned int /*flags*/)
{
/* Break propagation */
return NULL;
}
/**
* This routine is disabled to break propagation.
*/
static void
{
/* Break propagation */
}
/**
* This routine is disabled to break propagation.
*/
{
/* Break propagation */
}
/**
* This routine is disabled to break propagation.
*/
static void
{
/* Break propagation */
}
/* fixme: Remove link if zero-sized (Lauris) */
/**
* Removes any SPMarkerViews that a marker has with a specific key.
* Set up the DrawingItem array's size in the specified SPMarker's SPMarkerView.
* This is called from sp_shape_update() for shapes that have markers. It
* removes the old view of the marker and establishes a new one, registering
* it with the marker's list of views for future updates.
*
* \param marker Marker to create views in.
* \param key Key to give each SPMarkerView.
* \param size Number of DrawingItems to put in the SPMarkerView.
*/
void
{
unsigned int i;
}
/* Free old view and allocate new */
/* Parent class ::hide method */
}
if (!view) {
view = new SPMarkerView();
for (i = 0; i < size; i++) {
}
}
}
/**
* Shows an instance of a marker. This is called during sp_shape_update_marker_view()
* show and transform a child item in the drawing for all views with the given key.
*/
{
// do not show marker if linewidth == 0 and markerUnits == strokeWidth
// otherwise Cairo will fail to render anything on the tile
// that contains the "degenerate" marker
return NULL;
}
return NULL;
}
/* Parent class ::show method */
/* fixme: Position (Lauris) */
}
}
if (marker->orient_auto) {
m = base;
} else {
/* fixme: Orient units (Lauris) */
}
}
}
}
}
return NULL;
}
/**
* This replaces SPItem implementation because we have our own views
* \param key SPMarkerView key to hide.
*/
void
{
SPMarkerView *v;
while (v != NULL) {
/* Parent class ::hide method */
return;
}
v = next;
}
}
/**
* Removes a given view. Also will destroy sub-items in the view if destroyitems
* is set to a non-zero value.
*/
static void
{
unsigned int i;
} else {
SPMarkerView *v;
}
if (destroyitems) {
/* We have to walk through the whole array because there may be hidden items */
}
}
delete view;
}
const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine /*transform*/, Geom::Affine move)
{
// Uncommenting this will make the marker fixed-size independent of stroke width.
// Commented out for consistency with standard markers which scale when you change
// stroke width:
//repr->setAttribute("markerUnits", "userSpaceOnUse");
dup_transform *= move;
}
return mark_id;
}
{
return marker;
}
return marker;
}
// Turn off garbage-collectable or it might be collected before we can use it
}
return marker_new;
}
/*
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 :