index b4a6c82e5b8b4d37e7f21cb28aeeea153cacf7fc..23bf70be5eb597e34a8cd58d67f61d4e71b5568e 100644 (file)
#include <libnr/nr-blit.h>
#include <libnr/nr-convert2geom.h>
#include <2geom/pathvector.h>
+#include <2geom/curves.h>
#include <livarot/Path.h>
#include <livarot/float-line.h>
#include <livarot/int-line.h>
#include "sp-filter.h"
#include "sp-filter-reference.h"
#include "display/nr-filter.h"
-
+#include <typeinfo>
#include <cairo.h>
//int showRuns=0;
@@ -251,8 +252,7 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
shape->ctm = gc->transform;
if (state & NR_ARENA_ITEM_STATE_BBOX) {
if (shape->curve) {
- // note: the original code before 2geom used to calculate the exact bounding box, for speed we take the approx bbox here
- boundingbox = bounds_fast_transformed(shape->curve->get_pathvector(), to_2geom(gc->transform));
+ boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), to_2geom(gc->transform));
item->bbox.x0 = (gint32)(boundingbox[0][0] - 1.0F);
item->bbox.y0 = (gint32)(boundingbox[1][0] - 1.0F);
item->bbox.x1 = (gint32)(boundingbox[0][1] + 1.9999F);
@@ -275,8 +275,7 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
if (shape->curve) {
- // note: the original code before 2geom used to calculate the exact bounding box, for speed we take the approx bbox here
- boundingbox = bounds_fast_transformed(shape->curve->get_pathvector(), to_2geom(gc->transform));
+ boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), to_2geom(gc->transform));
if (shape->_stroke.paint.type() != NRArenaShape::Paint::NONE || outline) {
float width, scale;
return (outer.x0 <= inner.x0 && outer.y0 <= inner.y0 && outer.x1 >= inner.x1 && outer.y1 >= inner.y1);
}
+/* returns true if the pathvector has a region that needs fill.
+ * is for optimizing purposes, so should be fast and can falsely return true.
+ * CANNOT falsely return false. */
+static bool has_inner_area(Geom::PathVector const & pv) {
+ // return false for the cases where there is surely no region to be filled
+ if (pv.empty())
+ return false;
+
+ if ( (pv.size() == 1) && (pv.front().size() <= 1) ) {
+ // vector has only one path with only one segment, see if that's a non-curve segment: that would mean no internal region
+ Geom::Curve const * c = & pv.front().front();
+ if ( dynamic_cast<Geom::LineSegment const*>(c) ||
+ dynamic_cast<Geom::HLineSegment const*>(c) ||
+ dynamic_cast<Geom::VLineSegment const*>(c) )
+ {
+ return false;
+ }
+ }
+
+ return true; //too costly to see if it has region to be filled, so return true.
+}
+
/** force_shape is used for clipping paths, when we need the shape for clipping even if it's not filled */
void
nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape)
{
if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) &&
- ((shape->curve->get_length() > 2) || (SP_CURVE_BPATH(shape->curve)[1].code == NR_CURVETO)) ) {
+// ((shape->curve->get_length() > 2) || (SP_CURVE_BPATH(shape->curve)[1].code == NR_CURVETO)) ) { // <-- this used to be the old code, i think it has to determine that the path has a sort of 'internal region' where fill would occur
+ has_inner_area(shape->curve->get_pathvector()) ) {
if (TRUE || !shape->fill_shp) {
NR::Matrix cached_to_new = NR::identity();
int isometry = 0;
@@ -443,8 +465,8 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool fo
Path* thePath=new Path;
Shape* theShape=new Shape;
{
- NR::Matrix tempMat(gc->transform);
- thePath->LoadArtBPath(SP_CURVE_BPATH(shape->curve),tempMat,true);
+ Geom::Matrix tempMat(to_2geom(gc->transform));
+ thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
}
if (is_inner_area(*area, NR_ARENA_ITEM(shape)->bbox)) {
Path* thePath = new Path;
Shape* theShape = new Shape;
{
- NR::Matrix tempMat(gc->transform);
- thePath->LoadArtBPath(SP_CURVE_BPATH(shape->curve), tempMat, true);
+ Geom::Matrix tempMat( to_2geom(gc->transform) );
+ thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
}
// add some padding to the rendering area, so clipped path does not go into a render area
@@ -1046,14 +1068,16 @@ nr_arena_shape_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int /
if (!shape->curve) return NULL;
if (!shape->style) return NULL;
- if (SP_SCALE24_TO_FLOAT(shape->style->opacity.value) == 0) // fully transparent, no pick
+
+ bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
+
+ if (SP_SCALE24_TO_FLOAT(shape->style->opacity.value) == 0 && !outline)
+ // fully transparent, no pick unless outline mode
return NULL;
GTimeVal tstart, tfinish;
g_get_current_time (&tstart);
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
double width;
if (outline) {
width = 0.5;
@@ -1064,19 +1088,17 @@ nr_arena_shape_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int /
width = 0;
}
- const_NRBPath bp;
- bp.path = SP_CURVE_BPATH(shape->curve);
double dist = NR_HUGE;
int wind = 0;
bool needfill = (shape->_fill.paint.type() != NRArenaShape::Paint::NONE
&& shape->_fill.opacity > 1e-3 && !outline);
if (item->arena->canvasarena) {
- NR::Rect viewbox = item->arena->canvasarena->item.canvas->getViewbox();
- viewbox.growBy (width);
- nr_path_matrix_point_bbox_wind_distance(&bp, shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
+ Geom::Rect viewbox = to_2geom(item->arena->canvasarena->item.canvas->getViewbox());
+ viewbox.expandBy (width);
+ pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), to_2geom(shape->ctm), to_2geom(p), NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
} else {
- nr_path_matrix_point_bbox_wind_distance(&bp, shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
+ pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), to_2geom(shape->ctm), to_2geom(p), NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
}
g_get_current_time (&tfinish);