From: knutux Date: Wed, 19 Apr 2006 05:14:26 +0000 (+0000) Subject: Rendering optimisation, which gives best results for zoomed in drawings with complex... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=b64d0121f71311f8f4439bd85e773e8a22f12185;p=inkscape.git Rendering optimisation, which gives best results for zoomed in drawings with complex (multi-node) paths. Optimisation focus - eliminating cubicTo and LineTo nodes outside of visible area, so no unneeded calculations is needed and less memory is consumed (this avoids crashes which were occurring previously if zooming into a complex drawing) --- diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index 1d77de158..2d192ac1b 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -278,10 +278,12 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf) FALSE, FALSE); #ifdef STRICT_RGBA + pb.visible_area = buf->visible_rect; nr_arena_item_invoke_render (arena->root, &area, &pb, 0); nr_blit_pixblock_pixblock (&cb, &pb); nr_pixblock_release (&pb); #else + cb.visible_area = buf->visible_rect; nr_arena_item_invoke_render (arena->root, &area, &cb, 0); #endif diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index 78ba90c2b..083e7a7f4 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -440,6 +440,7 @@ nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, u if (style->fill.type != SP_PAINT_TYPE_NONE || item->arena->rendermode == RENDERMODE_OUTLINE) { NRPixBlock m; nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + m.visible_area = pb->visible_area; /* Render children fill mask */ for (child = group->children; child != NULL; child = child->next) { @@ -479,6 +480,7 @@ nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, u NRPixBlock m; guint32 rgba; nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + m.visible_area = pb->visible_area; /* Render children stroke mask */ for (child = group->children; child != NULL; child = child->next) { ret = nr_arena_glyphs_stroke_mask(NR_ARENA_GLYPHS(child), area, &m); diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index 7f473ae4d..44068cf9d 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -340,6 +340,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, item->px, 4 * (carea.x1 - carea.x0), TRUE, TRUE); + cpb.visible_area = pb->visible_area; dpb = &cpb; // Set nocache flag for downstream rendering flags |= NR_ARENA_ITEM_RENDER_NO_CACHE; @@ -401,6 +402,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, /* Setup and render item buffer */ nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + ipb.visible_area = pb->visible_area; state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ @@ -414,6 +416,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, if (item->clip || item->mask) { /* Setup mask pixblock */ nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + mpb.visible_area = pb->visible_area; /* Do clip if needed */ if (item->clip) { state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb); @@ -432,6 +435,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, NRPixBlock tpb; /* Set up yet another temporary pixblock */ nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + tpb.visible_area = pb->visible_area; state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, &tpb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ @@ -542,6 +546,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, /* Setup and render item buffer */ nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + ipb.visible_area = pb->visible_area; state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ @@ -555,6 +560,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, if (item->clip || item->mask) { /* Setup mask pixblock */ nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + mpb.visible_area = pb->visible_area; /* Do clip if needed */ if (item->clip) { state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb); @@ -573,6 +579,7 @@ unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, NRPixBlock tpb; /* Set up yet another temporary pixblock */ nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N, carea.x0, carea.y0, carea.x1, carea.y1, TRUE); + tpb.visible_area = pb->visible_area; state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, &tpb, flags); if (state & NR_ARENA_ITEM_STATE_INVALID) { /* Clean up and return error */ diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 743a70f9c..4f8acca48 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -97,6 +97,8 @@ nr_arena_shape_init(NRArenaShape *shape) shape->stroke_painter = NULL; shape->cached_fill = NULL; shape->cached_stroke = NULL; + shape->cached_fpartialy = false; + shape->cached_spartialy = false; shape->fill_shp = NULL; shape->stroke_shp = NULL; @@ -184,8 +186,8 @@ nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArena nr_arena_item_request_render(child); } -void nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc); -void nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, bool force_shape = false); +void nr_arena_shape_update_stroke(NRArenaShape *shape, NRGC* gc, NRRectL *area); +void nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape = false); void nr_arena_shape_add_bboxes(NRArenaShape* shape,NRRect &bbox); static guint @@ -301,8 +303,8 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g if ( shape->delayed_shp ) { item->bbox=shape->approx_bbox; } else { - nr_arena_shape_update_stroke(shape,gc); - nr_arena_shape_update_fill(shape,gc); + nr_arena_shape_update_stroke(shape, gc, area); + nr_arena_shape_update_fill(shape, gc, area); bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0; nr_arena_shape_add_bboxes(shape,bbox); @@ -377,19 +379,28 @@ int matrix_is_isometry(NR::Matrix p) { return 0; } +static bool is_inner_area(NRRectL const &outer, NRRectL const &inner) { + return (outer.x0 <= inner.x0 && outer.y0 <= inner.y0 && outer.x1 >= inner.x1 && outer.y1 >= inner.y1); +} + /** 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, bool force_shape) +nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape) { - shape->delayed_shp = false; if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) && ((shape->curve->end > 2) || (shape->curve->bpath[1].code == NR_CURVETO)) ) { if (TRUE || !shape->fill_shp) { NR::Matrix cached_to_new; int isometry = 0; if ( shape->cached_fill ) { - cached_to_new = shape->cached_fctm.inverse()*gc->transform; - isometry = matrix_is_isometry(cached_to_new); + if (shape->cached_fctm == gc->transform) { + isometry = 2; // identity + } else { + cached_to_new = shape->cached_fctm.inverse() * gc->transform; + isometry = matrix_is_isometry(cached_to_new); + } + if (0 != isometry && !is_inner_area(shape->cached_farea, *area)) + isometry = 0; } if ( isometry == 0 ) { if ( shape->cached_fill == NULL ) shape->cached_fill=new Shape; @@ -402,7 +413,13 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, bool force_shape) thePath->LoadArtBPath(shape->curve->bpath,tempMat,true); } - thePath->Convert(1.0); + if (is_inner_area(*area, NR_ARENA_ITEM(shape)->bbox)) { + thePath->Convert(1.0); + shape->cached_fpartialy = false; + } else { + thePath->Convert(area, 1.0); + shape->cached_fpartialy = true; + } thePath->Fill(theShape, 0); @@ -414,6 +431,7 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, bool force_shape) shape->cached_fill->ConvertToShape(theShape, fill_nonZero); } shape->cached_fctm=gc->transform; + shape->cached_farea = *area; delete theShape; delete thePath; if ( shape->fill_shp == NULL ) @@ -421,6 +439,11 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, bool force_shape) shape->fill_shp->Copy(shape->cached_fill); + } else if ( 2 == isometry ) { + if ( shape->fill_shp == NULL ) { + shape->fill_shp = new Shape; + shape->fill_shp->Copy(shape->cached_fill); + } } else { if ( shape->fill_shp == NULL ) @@ -443,17 +466,16 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, bool force_shape) shape->fill_shp->needPointsSorting(); shape->fill_shp->needEdgesSorting(); } + shape->delayed_shp |= shape->cached_fpartialy; } } } void -nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc) +nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area) { SPStyle* style = shape->style; - shape->delayed_shp = false; - float const scale = NR_MATRIX_DF_EXPANSION(&gc->transform); if (NR_ARENA_ITEM(shape)->arena->rendermode == RENDERMODE_OUTLINE || @@ -468,8 +490,14 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc) int isometry = 0; if ( shape->cached_stroke ) { - cached_to_new = shape->cached_sctm.inverse() * gc->transform; - isometry = matrix_is_isometry(cached_to_new); + if (shape->cached_sctm == gc->transform) { + isometry = 2; // identity + } else { + cached_to_new = shape->cached_sctm.inverse() * gc->transform; + isometry = matrix_is_isometry(cached_to_new); + } + if (0 != isometry && !is_inner_area(shape->cached_sarea, *area)) + isometry = 0; } if ( isometry == 0 ) { @@ -482,10 +510,20 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc) thePath->LoadArtBPath(shape->curve->bpath, tempMat, true); } - if (NR_ARENA_ITEM(shape)->arena->rendermode != RENDERMODE_OUTLINE) - thePath->Convert(1.0); - else - thePath->Convert(4.0); // slightly rougher & faster + // add some padding to the rendering area, so clipped path does not go into a render area + NRRectL padded_area = *area; + padded_area.x0 -= (NR::ICoord)width; + padded_area.x1 += (NR::ICoord)width; + padded_area.y0 -= (NR::ICoord)width; + padded_area.y1 += (NR::ICoord)width; + if (is_inner_area(padded_area, NR_ARENA_ITEM(shape)->bbox)) { + thePath->Convert((NR_ARENA_ITEM(shape)->arena->rendermode != RENDERMODE_OUTLINE) ? 1.0 : 4.0); + shape->cached_spartialy = false; + } + else { + thePath->Convert(&padded_area, (NR_ARENA_ITEM(shape)->arena->rendermode != RENDERMODE_OUTLINE) ? 1.0 : 4.0); + shape->cached_spartialy = true; + } if (style->stroke_dash.n_dash && NR_ARENA_ITEM(shape)->arena->rendermode != RENDERMODE_OUTLINE) { double dlen = 0.0; @@ -555,14 +593,19 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc) } shape->cached_sctm=gc->transform; + shape->cached_sarea = *area; delete thePath; delete theShape; if ( shape->stroke_shp == NULL ) shape->stroke_shp=new Shape; shape->stroke_shp->Copy(shape->cached_stroke); + } else if ( 2 == isometry ) { + if ( shape->stroke_shp == NULL ) { + shape->stroke_shp=new Shape; + shape->stroke_shp->Copy(shape->cached_stroke); + } } else { - if ( shape->stroke_shp == NULL ) shape->stroke_shp=new Shape; shape->stroke_shp->Reset(shape->cached_stroke->numberOfPoints(), shape->cached_stroke->numberOfEdges()); @@ -581,6 +624,7 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc) shape->stroke_shp->needPointsSorting(); shape->stroke_shp->needEdgesSorting(); } + shape->delayed_shp |= shape->cached_spartialy; } } @@ -655,8 +699,9 @@ nr_arena_shape_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned if ( nr_rect_l_test_intersect(area, &item->bbox) ) { NRGC tempGC(NULL); tempGC.transform=shape->ctm; - nr_arena_shape_update_stroke(shape,&tempGC); - nr_arena_shape_update_fill(shape,&tempGC); + shape->delayed_shp = false; + nr_arena_shape_update_stroke(shape,&tempGC,&pb->visible_area); + nr_arena_shape_update_fill(shape,&tempGC,&pb->visible_area); /* NRRect bbox; bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0; nr_arena_shape_add_bboxes(shape,bbox); @@ -665,6 +710,8 @@ nr_arena_shape_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned item->bbox.x1 = (gint32)(bbox.x1 + 1.0F); item->bbox.y1 = (gint32)(bbox.y1 + 1.0F); shape->approx_bbox=item->bbox;*/ + } else { + return item->state; } } @@ -674,6 +721,7 @@ nr_arena_shape_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned guint32 rgba; nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + m.visible_area = pb->visible_area; nr_pixblock_render_shape_mask_or(m,shape->fill_shp); m.empty = FALSE; @@ -704,6 +752,7 @@ nr_arena_shape_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned guint32 rgba; nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + m.visible_area = pb->visible_area; nr_pixblock_render_shape_mask_or(m, shape->stroke_shp); m.empty = FALSE; @@ -750,7 +799,10 @@ nr_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb) if ( nr_rect_l_test_intersect(area, &item->bbox) ) { NRGC tempGC(NULL); tempGC.transform=shape->ctm; - nr_arena_shape_update_fill(shape, &tempGC, true); + shape->delayed_shp = false; + nr_arena_shape_update_fill(shape, &tempGC, &pb->visible_area, true); + } else { + return item->state; } } @@ -759,6 +811,7 @@ nr_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb) /* fixme: We can OR in one step (Lauris) */ nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + m.visible_area = pb->visible_area; nr_pixblock_render_shape_mask_or(m,shape->fill_shp); for (int y = area->y0; y < area->y1; y++) { @@ -786,7 +839,7 @@ nr_arena_shape_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int / if (!shape->curve) return NULL; if (!shape->style) return NULL; if ( shape->delayed_shp ) { - NRRectL area; + NRRectL area, updateArea; area.x0=(int)floor(p[NR::X]); area.x1=(int)ceil(p[NR::X]); area.y0=(int)floor(p[NR::Y]); @@ -800,8 +853,13 @@ nr_arena_shape_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int / if ( nr_rect_l_test_intersect(&area, &item->bbox) ) { NRGC tempGC(NULL); tempGC.transform=shape->ctm; - nr_arena_shape_update_stroke(shape,&tempGC); - nr_arena_shape_update_fill(shape,&tempGC); + updateArea = item->bbox; + if (shape->cached_stroke) + nr_rect_l_intersect (&updateArea, &updateArea, &shape->cached_sarea); + + shape->delayed_shp = false; + nr_arena_shape_update_stroke(shape, &tempGC, &updateArea); + nr_arena_shape_update_fill(shape, &tempGC, &updateArea); /* NRRect bbox; bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0; nr_arena_shape_add_bboxes(shape,bbox); diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h index 9f8eec99a..cd72013f6 100644 --- a/src/display/nr-arena-shape.h +++ b/src/display/nr-arena-shape.h @@ -138,6 +138,10 @@ struct NRArenaShape : public NRArenaItem { // skewing NR::Matrix cached_fctm; NR::Matrix cached_sctm; + NRRectL cached_farea; + NRRectL cached_sarea; + bool cached_fpartialy; + bool cached_spartialy; Shape *cached_fill; Shape *cached_stroke; diff --git a/src/display/nr-arena.cpp b/src/display/nr-arena.cpp index f54bfbb90..a6e33d2dc 100644 --- a/src/display/nr-arena.cpp +++ b/src/display/nr-arena.cpp @@ -109,6 +109,8 @@ nr_arena_render_paintserver_fill (NRPixBlock *pb, NRRectL *area, SPPainter *pain NRPixBlock cb, cb_opa; nr_pixblock_setup_fast (&cb, NR_PIXBLOCK_MODE_R8G8B8A8N, area->x0, area->y0, area->x1, area->y1, TRUE); nr_pixblock_setup_fast (&cb_opa, NR_PIXBLOCK_MODE_R8G8B8A8N, area->x0, area->y0, area->x1, area->y1, TRUE); + cb.visible_area = pb->visible_area; + cb_opa.visible_area = pb->visible_area; /* Need separate gradient buffer (lauris)*/ // do the filling diff --git a/src/display/nr-gradient-gpl.cpp b/src/display/nr-gradient-gpl.cpp index 54a33cfdb..536217649 100644 --- a/src/display/nr-gradient-gpl.cpp +++ b/src/display/nr-gradient-gpl.cpp @@ -271,6 +271,7 @@ nr_lgradient_render_generic (NRLGradientRenderer *lgr, NRPixBlock *pb) (unsigned char *) lgr->vector, 4 * NR_GRADIENT_VECTOR_LENGTH, 0, 0); + spb.visible_area = pb->visible_area; bpp = (pb->mode == NR_PIXBLOCK_MODE_A8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; for (y = 0; y < height; y++) { diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index b1ed7d3d2..5e19539f3 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1565,6 +1565,10 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1) buf.rect.y0 = y0; buf.rect.x1 = x1; buf.rect.y1 = y1; + buf.visible_rect.x0 = draw_x1; + buf.visible_rect.y0 = draw_y1; + buf.visible_rect.x1 = draw_x2; + buf.visible_rect.y1 = draw_y2; GdkColor *color = &widget->style->bg[GTK_STATE_NORMAL]; buf.bg_color = (((color->red & 0xff00) << 8) | (color->green & 0xff00) diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 86522870a..34ed87ac9 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -52,6 +52,7 @@ struct SPCanvasBuf{ guchar *buf; int buf_rowstride; NRRectL rect; + NRRectL visible_rect; /// Background color, given as 0xrrggbb guint32 bg_color; // If empty, ignore contents of buffer and use a solid area of bg_color diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index 6715f890f..463d32336 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -142,7 +142,12 @@ sp_ctrlline_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int f thePath->MoveTo(NR::Point(cl->s.x, cl->s.y) * affine); thePath->LineTo(NR::Point(cl->e.x, cl->e.y) * affine); - thePath->Convert(1.0); + NRRectL area; + area.x0=item->x1; + area.x1=item->x2; + area.y0=item->y1; + area.y1=item->y2; + thePath->Convert(&area, 1.0); if ( cl->shp == NULL ) cl->shp=new Shape; thePath->Stroke(cl->shp,false,0.5,join_straight,butt_straight,20.0,false); cl->shp->CalcBBox(); diff --git a/src/libnr/nr-pixblock.cpp b/src/libnr/nr-pixblock.cpp index 9b1ff2752..59e64b558 100644 --- a/src/libnr/nr-pixblock.cpp +++ b/src/libnr/nr-pixblock.cpp @@ -64,10 +64,10 @@ nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, i pb->mode = mode; pb->empty = 1; - pb->area.x0 = x0; - pb->area.y0 = y0; - pb->area.x1 = x1; - pb->area.y1 = y1; + pb->visible_area.x0 = pb->area.x0 = x0; + pb->visible_area.y0 = pb->area.y0 = y0; + pb->visible_area.x1 = pb->area.x1 = x1; + pb->visible_area.y1 = pb->area.y1 = y1; pb->rs = bpp * w; } @@ -103,10 +103,10 @@ nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1 pb->mode = mode; pb->empty = 1; - pb->area.x0 = x0; - pb->area.y0 = y0; - pb->area.x1 = x1; - pb->area.y1 = y1; + pb->visible_area.x0 = pb->area.x0 = x0; + pb->visible_area.y0 = pb->area.y0 = y0; + pb->visible_area.x1 = pb->area.x1 = x1; + pb->visible_area.y1 = pb->area.y1 = y1; pb->rs = bpp * w; } @@ -130,10 +130,10 @@ nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, pb->size = NR_PIXBLOCK_SIZE_STATIC; pb->mode = mode; pb->empty = empty; - pb->area.x0 = x0; - pb->area.y0 = y0; - pb->area.x1 = x1; - pb->area.y1 = y1; + pb->visible_area.x0 = pb->area.x0 = x0; + pb->visible_area.y0 = pb->area.y0 = y0; + pb->visible_area.x1 = pb->area.x1 = x1; + pb->visible_area.y1 = pb->area.y1 = y1; pb->data.px = px; pb->rs = rs; diff --git a/src/libnr/nr-pixblock.h b/src/libnr/nr-pixblock.h index 2a13dd921..c9ccb4fc6 100644 --- a/src/libnr/nr-pixblock.h +++ b/src/libnr/nr-pixblock.h @@ -41,6 +41,7 @@ struct NRPixBlock { bool empty : 1; ///< Empty flag unsigned int rs; ///< Size of line in bytes NRRectL area; + NRRectL visible_area; union { unsigned char *px; ///< Pointer to buffer unsigned char p[sizeof (unsigned char *)]; ///< Tiny buffer diff --git a/src/livarot/Path.cpp b/src/livarot/Path.cpp index 32c100310..8ad806349 100644 --- a/src/livarot/Path.cpp +++ b/src/livarot/Path.cpp @@ -428,6 +428,18 @@ int Path::AddPoint(NR::Point const &iPt, bool mvto) } +int Path::ReplacePoint(NR::Point const &iPt) +{ + if (pts.empty()) { + return -1; + } + + int const n = pts.size() - 1; + pts[n] = path_lineto(polyline_lineto, iPt); + return n; +} + + int Path::AddPoint(NR::Point const &iPt, int ip, double it, bool mvto) { if (back == false) { diff --git a/src/livarot/Path.h b/src/livarot/Path.h index 5b1df6294..291d8f157 100644 --- a/src/livarot/Path.h +++ b/src/livarot/Path.h @@ -13,6 +13,7 @@ #include "LivarotDefs.h" #include "livarot/livarot-forward.h" #include "libnr/nr-point.h" +#include /* * the Path class: a structure to hold path description and their polyline approximation (not kept in sync) @@ -108,6 +109,7 @@ public: // transforms a description in a polyline (for stroking and filling) // treshhold is the max length^2 (sort of) void Convert (double treshhold); + void Convert(NRRectL *area, double treshhold); void ConvertEvenLines (double treshhold); // decomposes line segments too, for later recomposition // same function for use when you want to later recompose the curves from the polyline void ConvertWithBackData (double treshhold); @@ -119,6 +121,7 @@ public: int AddPoint ( NR::Point const &iPt, int ip, double it, bool mvto = false); int AddForcedPoint ( NR::Point const &iPt); // add point int AddForcedPoint ( NR::Point const &iPt, int ip, double it); + int ReplacePoint(NR::Point const &iPt); // replace point // transform in a polygon (in a graph, in fact; a subsequent call to ConvertToShape is needed) // - fills the polyline; justAdd=true doesn't reset the Shape dest, but simply adds the polyline into it diff --git a/src/livarot/PathConversion.cpp b/src/livarot/PathConversion.cpp index e6f7acb0c..d81785d20 100644 --- a/src/livarot/PathConversion.cpp +++ b/src/livarot/PathConversion.cpp @@ -400,6 +400,271 @@ void Path::Convert(double treshhold) } } +#define POINT_RELATION_TO_AREA(pt, area) ((pt)[0] < (area)->x0 ? 1 : ((pt)[0] > (area)->x1 ? 2 : ((pt)[1] < (area)->y0 ? 3 : ((pt)[1] > (area)->y1 ? 4 : 0)))) + +void Path::Convert(NRRectL *area, double treshhold) +{ + if ( descr_flags & descr_adding_bezier ) { + CancelBezier(); + } + + if ( descr_flags & descr_doing_subpath ) { + CloseSubpath(); + } + + SetBackData(false); + ResetPoints(); + if ( descr_cmd.empty() ) { + return; + } + + NR::Point curX; + int curP = 1; + int lastMoveTo = 0; + short last_point_relation = 0; + short curent_point_relation = 0; + bool start_elimination = false; + bool replace = false; + + // le moveto + { + int const firstTyp = descr_cmd[0]->getType(); + if ( firstTyp == descr_moveto ) { + curX = dynamic_cast(descr_cmd[0])->p; + } else { + curP = 0; + curX[0] = curX[1] = 0; + } + + last_point_relation = POINT_RELATION_TO_AREA(curX, area); + lastMoveTo = AddPoint(curX, true); + } + descr_cmd[0]->associated = lastMoveTo; + + // et le reste, 1 par 1 + while ( curP < int(descr_cmd.size()) ) { + + int const nType = descr_cmd[curP]->getType(); + NR::Point nextX; + + switch (nType) { + case descr_forced: { + descr_cmd[curP]->associated = AddForcedPoint(curX); + last_point_relation = 0; + curP++; + break; + } + + case descr_moveto: { + PathDescrMoveTo *nData = dynamic_cast(descr_cmd[curP]); + nextX = nData->p; + lastMoveTo = AddPoint(nextX, true); + descr_cmd[curP]->associated = lastMoveTo; + last_point_relation = 0; + + // et on avance + curP++; + break; + } + + case descr_close: { + nextX = pts[lastMoveTo].p; + descr_cmd[curP]->associated = AddPoint(nextX, false); + if ( descr_cmd[curP]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[curP]->associated = 0; + } else { + descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated; + } + } + last_point_relation = 0; + curP++; + break; + } + + case descr_lineto: { + PathDescrLineTo *nData = dynamic_cast(descr_cmd[curP]); + nextX = nData->p; + curent_point_relation = POINT_RELATION_TO_AREA(nextX, area); + replace = false; + if (curent_point_relation > 0 && curent_point_relation == last_point_relation) { + if (!start_elimination) { + start_elimination = true; + } else { + replace = true; + descr_cmd[curP]->associated = ReplacePoint(nextX); + } + } else { + start_elimination = false; + } + + if (!replace) { + descr_cmd[curP]->associated = AddPoint(nextX, false); + } + + if ( descr_cmd[curP]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[curP]->associated = 0; + } else { + descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated; + } + } + last_point_relation = curent_point_relation; + // et on avance + curP++; + break; + } + + case descr_cubicto: { + PathDescrCubicTo *nData = dynamic_cast(descr_cmd[curP]); + nextX = nData->p; + + curent_point_relation = POINT_RELATION_TO_AREA(nextX, area); + replace = false; + if (curent_point_relation > 0 && curent_point_relation == last_point_relation && + curent_point_relation == POINT_RELATION_TO_AREA(curX + (nData->start), area) && + curent_point_relation == POINT_RELATION_TO_AREA(nextX + (nData->end), area)) + { + if (!start_elimination) { + start_elimination = true; + } else { + replace = true; + descr_cmd[curP]->associated = ReplacePoint(nextX); + } + } else { + start_elimination = false; + } + + if (!replace) { + RecCubicTo(curX, nData->start, nextX, nData->end, treshhold, 8); + descr_cmd[curP]->associated = AddPoint(nextX,false); + } + + if ( descr_cmd[curP]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[curP]->associated = 0; + } else { + descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated; + } + } + last_point_relation = curent_point_relation; + // et on avance + curP++; + break; + } + + case descr_arcto: { + PathDescrArcTo *nData = dynamic_cast(descr_cmd[curP]); + nextX = nData->p; + DoArc(curX, nextX, nData->rx, nData->ry, nData->angle, nData->large, nData->clockwise, treshhold); + descr_cmd[curP]->associated = AddPoint(nextX, false); + if ( descr_cmd[curP]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[curP]->associated = 0; + } else { + descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated; + } + } + last_point_relation = 0; + // et on avance + curP++; + break; + } + + case descr_bezierto: { + PathDescrBezierTo *nBData = dynamic_cast(descr_cmd[curP]); + int nbInterm = nBData->nb; + nextX = nBData->p; + int curBD = curP; + + curP++; + int ip = curP; + PathDescrIntermBezierTo *nData = dynamic_cast(descr_cmd[ip]); + + if ( nbInterm == 1 ) { + NR::Point const midX = nData->p; + RecBezierTo(midX, curX, nextX, treshhold, 8); + } else if ( nbInterm > 1 ) { + NR::Point bx = curX; + NR::Point cx = curX; + NR::Point dx = curX; + + dx = nData->p; + ip++; + nData = dynamic_cast(descr_cmd[ip]); + + cx = 2 * bx - dx; + + for (int k = 0; k < nbInterm - 1; k++) { + bx = cx; + cx = dx; + + dx = nData->p; + ip++; + nData = dynamic_cast(descr_cmd[ip]); + + NR::Point stx = (bx + cx) / 2; + if ( k > 0 ) { + descr_cmd[ip - 2]->associated = AddPoint(stx, false); + if ( descr_cmd[ip - 2]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[ip - 2]->associated = 0; + } else { + descr_cmd[ip - 2]->associated = descr_cmd[ip - 3]->associated; + } + } + } + + { + NR::Point const mx = (cx + dx) / 2; + RecBezierTo(cx, stx, mx, treshhold, 8); + } + } + + { + bx = cx; + cx = dx; + + dx = nextX; + dx = 2 * dx - cx; + + NR::Point stx = (bx + cx) / 2; + + descr_cmd[ip - 1]->associated = AddPoint(stx, false); + if ( descr_cmd[ip - 1]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[ip - 1]->associated = 0; + } else { + descr_cmd[ip - 1]->associated = descr_cmd[ip - 2]->associated; + } + } + + { + NR::Point mx = (cx + dx) / 2; + RecBezierTo(cx, stx, mx, treshhold, 8); + } + } + } + + descr_cmd[curBD]->associated = AddPoint(nextX, false); + if ( descr_cmd[curBD]->associated < 0 ) { + if ( curP == 0 ) { + descr_cmd[curBD]->associated = 0; + } else { + descr_cmd[curBD]->associated = descr_cmd[curBD - 1]->associated; + } + } + + last_point_relation = 0; + // et on avance + curP += nbInterm; + break; + } + } + + curX = nextX; + } +} void Path::ConvertEvenLines(double treshhold) diff --git a/src/livarot/Shape.cpp b/src/livarot/Shape.cpp index eead99225..178e8660e 100644 --- a/src/livarot/Shape.cpp +++ b/src/livarot/Shape.cpp @@ -22,16 +22,19 @@ Shape::Shape() : iData(NULL), sTree(NULL), sEvts(NULL), + qrsData(NULL), _need_points_sorting(false), _need_edges_sorting(false), _has_points_data(false), + _point_data_initialised(false), _has_edges_data(false), _has_sweep_src_data(false), _has_sweep_dest_data(false), _has_raster_data(false), _has_quick_raster_data(false), _has_back_data(false), - _has_voronoi_data(false) + _has_voronoi_data(false), + _bbox_up_to_date(false) { leftX = topY = rightX = bottomY = 0; maxPt = 0; @@ -43,6 +46,7 @@ Shape::~Shape (void) { maxPt = 0; maxAr = 0; + free(qrsData); } void Shape::Affiche(void) @@ -58,64 +62,65 @@ void Shape::Affiche(void) */ } +/** + * Allocates space for point cache or clears the cache + \param nVal Allocate a cache (true) or clear it (false) + */ void Shape::MakePointData (bool nVal) { if (nVal) { if (_has_points_data == false) - { - _has_points_data = true; - pData.resize(maxPt); - } - } - else - { - if (_has_points_data) - { - _has_points_data = false; - pData.clear(); - } - } + { + _has_points_data = true; + _point_data_initialised = false; + _bbox_up_to_date = false; + pData.resize(maxPt); + } + } + /* no need to clean point data - keep it cached*/ } + void Shape::MakeEdgeData (bool nVal) { if (nVal) { if (_has_edges_data == false) - { - _has_edges_data = true; - eData.resize(maxAr); - } + { + _has_edges_data = true; + eData.resize(maxAr); + } } else { if (_has_edges_data) - { - _has_edges_data = false; - eData.clear(); - } + { + _has_edges_data = false; + eData.clear(); + } } } + void Shape::MakeRasterData (bool nVal) { if (nVal) { if (_has_raster_data == false) - { - _has_raster_data = true; - swrData.resize(maxAr); - } + { + _has_raster_data = true; + swrData.resize(maxAr); + } } else { if (_has_raster_data) - { - _has_raster_data = false; - swrData.clear(); - } + { + _has_raster_data = false; + swrData.clear(); + } } } void @@ -124,18 +129,17 @@ Shape::MakeQuickRasterData (bool nVal) if (nVal) { if (_has_quick_raster_data == false) - { - _has_quick_raster_data = true; - qrsData.resize(maxAr); - } + { + _has_quick_raster_data = true; + qrsData = (quick_raster_data*)realloc(qrsData, maxAr * sizeof(quick_raster_data)); + } } else { if (_has_quick_raster_data) - { - _has_quick_raster_data = false; - qrsData.clear(); - } + { + _has_quick_raster_data = false; + } } } void @@ -144,18 +148,18 @@ Shape::MakeSweepSrcData (bool nVal) if (nVal) { if (_has_sweep_src_data == false) - { - _has_sweep_src_data = true; - swsData.resize(maxAr); - } + { + _has_sweep_src_data = true; + swsData.resize(maxAr); + } } else { if (_has_sweep_src_data) - { - _has_sweep_src_data = false; - swsData.clear(); - } + { + _has_sweep_src_data = false; + swsData.clear(); + } } } void @@ -164,18 +168,18 @@ Shape::MakeSweepDestData (bool nVal) if (nVal) { if (_has_sweep_dest_data == false) - { - _has_sweep_dest_data = true; - swdData.resize(maxAr); - } + { + _has_sweep_dest_data = true; + swdData.resize(maxAr); + } } else { if (_has_sweep_dest_data) - { - _has_sweep_dest_data = false; - swdData.clear(); - } + { + _has_sweep_dest_data = false; + swdData.clear(); + } } } void @@ -184,18 +188,18 @@ Shape::MakeBackData (bool nVal) if (nVal) { if (_has_back_data == false) - { - _has_back_data = true; - ebData.resize(maxAr); - } + { + _has_back_data = true; + ebData.resize(maxAr); + } } else { if (_has_back_data) - { - _has_back_data = false; - ebData.clear(); - } + { + _has_back_data = false; + ebData.clear(); + } } } void @@ -204,20 +208,20 @@ Shape::MakeVoronoiData (bool nVal) if (nVal) { if (_has_voronoi_data == false) - { - _has_voronoi_data = true; - vorpData.resize(maxPt); - voreData.resize(maxAr); - } + { + _has_voronoi_data = true; + vorpData.resize(maxPt); + voreData.resize(maxAr); + } } else { if (_has_voronoi_data) - { - _has_voronoi_data = false; - vorpData.clear(); - voreData.clear(); - } + { + _has_voronoi_data = false; + vorpData.clear(); + voreData.clear(); + } } } @@ -252,6 +256,7 @@ Shape::Copy (Shape * who) _need_points_sorting = who->_need_points_sorting; _need_edges_sorting = who->_need_edges_sorting; _has_points_data = false; + _point_data_initialised = false; _has_edges_data = false; _has_sweep_src_data = false; _has_sweep_dest_data = false; @@ -259,42 +264,48 @@ Shape::Copy (Shape * who) _has_quick_raster_data = false; _has_back_data = false; _has_voronoi_data = false; + _bbox_up_to_date = false; _pts = who->_pts; _aretes = who->_aretes; } +/** + * Clear points and edges and prepare internal data using new size. + */ void -Shape::Reset (int n, int m) +Shape::Reset (int pointCount, int edgeCount) { _pts.clear(); _aretes.clear(); type = shape_polygon; - if (n > maxPt) + if (pointCount > maxPt) { - maxPt = n; + maxPt = pointCount; if (_has_points_data) - pData.resize(maxPt); + pData.resize(maxPt); if (_has_voronoi_data) - vorpData.resize(maxPt); + vorpData.resize(maxPt); } - if (m > maxAr) + if (edgeCount > maxAr) { - maxAr = m; + maxAr = edgeCount; if (_has_edges_data) - eData.resize(maxAr); + eData.resize(maxAr); if (_has_sweep_dest_data) - swdData.resize(maxAr); + swdData.resize(maxAr); if (_has_sweep_src_data) - swsData.resize(maxAr); + swsData.resize(maxAr); if (_has_back_data) - ebData.resize(maxAr); + ebData.resize(maxAr); if (_has_voronoi_data) - voreData.resize(maxAr); + voreData.resize(maxAr); } _need_points_sorting = false; _need_edges_sorting = false; + _point_data_initialised = false; + _bbox_up_to_date = false; } int @@ -304,9 +315,9 @@ Shape::AddPoint (const NR::Point x) { maxPt = 2 * numberOfPoints() + 1; if (_has_points_data) - pData.resize(maxPt); + pData.resize(maxPt); if (_has_voronoi_data) - vorpData.resize(maxPt); + vorpData.resize(maxPt); } dg_point p; @@ -324,6 +335,8 @@ Shape::AddPoint (const NR::Point x) pData[n].nextLinkedPoint = -1; pData[n].askForWindingS = NULL; pData[n].askForWindingB = -1; + pData[n].rx[0] = Round(p.x[0]); + pData[n].rx[1] = Round(p.x[1]); } if (_has_voronoi_data) { @@ -346,23 +359,23 @@ Shape::SubPoint (int p) while (cb >= 0 && cb < numberOfEdges()) { if (getEdge(cb).st == p) - { - int ncb = getEdge(cb).nextS; - _aretes[cb].nextS = _aretes[cb].prevS = -1; - _aretes[cb].st = -1; - cb = ncb; - } + { + int ncb = getEdge(cb).nextS; + _aretes[cb].nextS = _aretes[cb].prevS = -1; + _aretes[cb].st = -1; + cb = ncb; + } else if (getEdge(cb).en == p) - { - int ncb = getEdge(cb).nextE; - _aretes[cb].nextE = _aretes[cb].prevE = -1; - _aretes[cb].en = -1; - cb = ncb; - } + { + int ncb = getEdge(cb).nextE; + _aretes[cb].nextE = _aretes[cb].prevE = -1; + _aretes[cb].en = -1; + cb = ncb; + } else - { - break; - } + { + break; + } } _pts[p].incidentEdge[FIRST] = _pts[p].incidentEdge[LAST] = -1; if (p < numberOfPoints() - 1) @@ -379,60 +392,60 @@ Shape::SwapPoints (int a, int b) { int cb = getPoint(a).incidentEdge[FIRST]; if (getEdge(cb).st == a) - { - _aretes[cb].st = numberOfPoints(); - } + { + _aretes[cb].st = numberOfPoints(); + } else if (getEdge(cb).en == a) - { - _aretes[cb].en = numberOfPoints(); - } + { + _aretes[cb].en = numberOfPoints(); + } cb = getPoint(a).incidentEdge[LAST]; if (getEdge(cb).st == a) - { - _aretes[cb].st = numberOfPoints(); - } + { + _aretes[cb].st = numberOfPoints(); + } else if (getEdge(cb).en == a) - { - _aretes[cb].en = numberOfPoints(); - } + { + _aretes[cb].en = numberOfPoints(); + } cb = getPoint(b).incidentEdge[FIRST]; if (getEdge(cb).st == b) - { - _aretes[cb].st = a; - } + { + _aretes[cb].st = a; + } else if (getEdge(cb).en == b) - { - _aretes[cb].en = a; - } + { + _aretes[cb].en = a; + } cb = getPoint(b).incidentEdge[LAST]; if (getEdge(cb).st == b) - { - _aretes[cb].st = a; - } + { + _aretes[cb].st = a; + } else if (getEdge(cb).en == b) - { - _aretes[cb].en = a; - } + { + _aretes[cb].en = a; + } cb = getPoint(a).incidentEdge[FIRST]; if (getEdge(cb).st == numberOfPoints()) - { - _aretes[cb].st = b; - } + { + _aretes[cb].st = b; + } else if (getEdge(cb).en == numberOfPoints()) - { - _aretes[cb].en = b; - } + { + _aretes[cb].en = b; + } cb = getPoint(a).incidentEdge[LAST]; if (getEdge(cb).st == numberOfPoints()) - { - _aretes[cb].st = b; - } + { + _aretes[cb].st = b; + } else if (getEdge(cb).en == numberOfPoints()) - { - _aretes[cb].en = b; - } + { + _aretes[cb].en = b; + } } else @@ -440,46 +453,46 @@ Shape::SwapPoints (int a, int b) int cb; cb = getPoint(a).incidentEdge[FIRST]; while (cb >= 0) - { - int ncb = NextAt (a, cb); - if (getEdge(cb).st == a) - { - _aretes[cb].st = numberOfPoints(); - } - else if (getEdge(cb).en == a) - { - _aretes[cb].en = numberOfPoints(); - } - cb = ncb; - } + { + int ncb = NextAt (a, cb); + if (getEdge(cb).st == a) + { + _aretes[cb].st = numberOfPoints(); + } + else if (getEdge(cb).en == a) + { + _aretes[cb].en = numberOfPoints(); + } + cb = ncb; + } cb = getPoint(b).incidentEdge[FIRST]; while (cb >= 0) - { - int ncb = NextAt (b, cb); - if (getEdge(cb).st == b) - { - _aretes[cb].st = a; - } - else if (getEdge(cb).en == b) - { - _aretes[cb].en = a; - } - cb = ncb; - } + { + int ncb = NextAt (b, cb); + if (getEdge(cb).st == b) + { + _aretes[cb].st = a; + } + else if (getEdge(cb).en == b) + { + _aretes[cb].en = a; + } + cb = ncb; + } cb = getPoint(a).incidentEdge[FIRST]; while (cb >= 0) - { - int ncb = NextAt (numberOfPoints(), cb); - if (getEdge(cb).st == numberOfPoints()) - { - _aretes[cb].st = b; - } - else if (getEdge(cb).en == numberOfPoints()) - { - _aretes[cb].en = b; - } - cb = ncb; - } + { + int ncb = NextAt (numberOfPoints(), cb); + if (getEdge(cb).st == numberOfPoints()) + { + _aretes[cb].st = b; + } + else if (getEdge(cb).en == numberOfPoints()) + { + _aretes[cb].en = b; + } + cb = ncb; + } } { dg_point swap = getPoint(a); @@ -533,8 +546,8 @@ Shape::SortPoints (int s, int e) if (e == s + 1) { if (getPoint(s).x[1] > getPoint(e).x[1] - || (getPoint(s).x[1] == getPoint(e).x[1] && getPoint(s).x[0] > getPoint(e).x[0])) - SwapPoints (s, e); + || (getPoint(s).x[1] == getPoint(e).x[1] && getPoint(s).x[0] > getPoint(e).x[0])) + SwapPoints (s, e); return; } @@ -547,160 +560,160 @@ Shape::SortPoints (int s, int e) while (le < ppos || ri > plast) { if (le < ppos) - { - do - { - int test = 0; - if (getPoint(le).x[1] > pvaly) - { - test = 1; - } - else if (getPoint(le).x[1] == pvaly) - { - if (getPoint(le).x[0] > pvalx) - { - test = 1; - } - else if (getPoint(le).x[0] == pvalx) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (le < ppos - 1) - { - SwapPoints (le, ppos - 1, ppos); - ppos--; - continue; // sans changer le - } - else if (le == ppos - 1) - { - ppos--; - break; - } - else - { - // oupsie - break; - } - } - if (test > 0) - { - break; - } - le++; - } - while (le < ppos); - } + { + do + { + int test = 0; + if (getPoint(le).x[1] > pvaly) + { + test = 1; + } + else if (getPoint(le).x[1] == pvaly) + { + if (getPoint(le).x[0] > pvalx) + { + test = 1; + } + else if (getPoint(le).x[0] == pvalx) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (le < ppos - 1) + { + SwapPoints (le, ppos - 1, ppos); + ppos--; + continue; // sans changer le + } + else if (le == ppos - 1) + { + ppos--; + break; + } + else + { + // oupsie + break; + } + } + if (test > 0) + { + break; + } + le++; + } + while (le < ppos); + } if (ri > plast) - { - do - { - int test = 0; - if (getPoint(ri).x[1] > pvaly) - { - test = 1; - } - else if (getPoint(ri).x[1] == pvaly) - { - if (getPoint(ri).x[0] > pvalx) - { - test = 1; - } - else if (getPoint(ri).x[0] == pvalx) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (ri > plast + 1) - { - SwapPoints (ri, plast + 1, plast); - plast++; - continue; // sans changer ri - } - else if (ri == plast + 1) - { - plast++; - break; - } - else - { - // oupsie - break; - } - } - if (test < 0) - { - break; - } - ri--; - } - while (ri > plast); - } + { + do + { + int test = 0; + if (getPoint(ri).x[1] > pvaly) + { + test = 1; + } + else if (getPoint(ri).x[1] == pvaly) + { + if (getPoint(ri).x[0] > pvalx) + { + test = 1; + } + else if (getPoint(ri).x[0] == pvalx) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (ri > plast + 1) + { + SwapPoints (ri, plast + 1, plast); + plast++; + continue; // sans changer ri + } + else if (ri == plast + 1) + { + plast++; + break; + } + else + { + // oupsie + break; + } + } + if (test < 0) + { + break; + } + ri--; + } + while (ri > plast); + } if (le < ppos) - { - if (ri > plast) - { - SwapPoints (le, ri); - le++; - ri--; - } - else - { - if (le < ppos - 1) - { - SwapPoints (ppos - 1, plast, le); - ppos--; - plast--; - } - else if (le == ppos - 1) - { - SwapPoints (plast, le); - ppos--; - plast--; - } - } - } + { + if (ri > plast) + { + SwapPoints (le, ri); + le++; + ri--; + } + else + { + if (le < ppos - 1) + { + SwapPoints (ppos - 1, plast, le); + ppos--; + plast--; + } + else if (le == ppos - 1) + { + SwapPoints (plast, le); + ppos--; + plast--; + } + } + } else - { - if (ri > plast + 1) - { - SwapPoints (plast + 1, ppos, ri); - ppos++; - plast++; - } - else if (ri == plast + 1) - { - SwapPoints (ppos, ri); - ppos++; - plast++; - } - else - { - break; - } - } + { + if (ri > plast + 1) + { + SwapPoints (plast + 1, ppos, ri); + ppos++; + plast++; + } + else if (ri == plast + 1) + { + SwapPoints (ppos, ri); + ppos++; + plast++; + } + else + { + break; + } + } } SortPoints (s, ppos - 1); SortPoints (plast + 1, e); @@ -714,9 +727,9 @@ Shape::SortPointsByOldInd (int s, int e) if (e == s + 1) { if (getPoint(s).x[1] > getPoint(e).x[1] || (getPoint(s).x[1] == getPoint(e).x[1] && getPoint(s).x[0] > getPoint(e).x[0]) - || (getPoint(s).x[1] == getPoint(e).x[1] && getPoint(s).x[0] == getPoint(e).x[0] - && pData[s].oldInd > pData[e].oldInd)) - SwapPoints (s, e); + || (getPoint(s).x[1] == getPoint(e).x[1] && getPoint(s).x[0] == getPoint(e).x[0] + && pData[s].oldInd > pData[e].oldInd)) + SwapPoints (s, e); return; } @@ -730,182 +743,182 @@ Shape::SortPointsByOldInd (int s, int e) while (le < ppos || ri > plast) { if (le < ppos) - { - do - { - int test = 0; - if (getPoint(le).x[1] > pvaly) - { - test = 1; - } - else if (getPoint(le).x[1] == pvaly) - { - if (getPoint(le).x[0] > pvalx) - { - test = 1; - } - else if (getPoint(le).x[0] == pvalx) - { - if (pData[le].oldInd > pvali) - { - test = 1; - } - else if (pData[le].oldInd == pvali) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (le < ppos - 1) - { - SwapPoints (le, ppos - 1, ppos); - ppos--; - continue; // sans changer le - } - else if (le == ppos - 1) - { - ppos--; - break; - } - else - { - // oupsie - break; - } - } - if (test > 0) - { - break; - } - le++; - } - while (le < ppos); - } + { + do + { + int test = 0; + if (getPoint(le).x[1] > pvaly) + { + test = 1; + } + else if (getPoint(le).x[1] == pvaly) + { + if (getPoint(le).x[0] > pvalx) + { + test = 1; + } + else if (getPoint(le).x[0] == pvalx) + { + if (pData[le].oldInd > pvali) + { + test = 1; + } + else if (pData[le].oldInd == pvali) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (le < ppos - 1) + { + SwapPoints (le, ppos - 1, ppos); + ppos--; + continue; // sans changer le + } + else if (le == ppos - 1) + { + ppos--; + break; + } + else + { + // oupsie + break; + } + } + if (test > 0) + { + break; + } + le++; + } + while (le < ppos); + } if (ri > plast) - { - do - { - int test = 0; - if (getPoint(ri).x[1] > pvaly) - { - test = 1; - } - else if (getPoint(ri).x[1] == pvaly) - { - if (getPoint(ri).x[0] > pvalx) - { - test = 1; - } - else if (getPoint(ri).x[0] == pvalx) - { - if (pData[ri].oldInd > pvali) - { - test = 1; - } - else if (pData[ri].oldInd == pvali) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (ri > plast + 1) - { - SwapPoints (ri, plast + 1, plast); - plast++; - continue; // sans changer ri - } - else if (ri == plast + 1) - { - plast++; - break; - } - else - { - // oupsie - break; - } - } - if (test < 0) - { - break; - } - ri--; - } - while (ri > plast); - } + { + do + { + int test = 0; + if (getPoint(ri).x[1] > pvaly) + { + test = 1; + } + else if (getPoint(ri).x[1] == pvaly) + { + if (getPoint(ri).x[0] > pvalx) + { + test = 1; + } + else if (getPoint(ri).x[0] == pvalx) + { + if (pData[ri].oldInd > pvali) + { + test = 1; + } + else if (pData[ri].oldInd == pvali) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (ri > plast + 1) + { + SwapPoints (ri, plast + 1, plast); + plast++; + continue; // sans changer ri + } + else if (ri == plast + 1) + { + plast++; + break; + } + else + { + // oupsie + break; + } + } + if (test < 0) + { + break; + } + ri--; + } + while (ri > plast); + } if (le < ppos) - { - if (ri > plast) - { - SwapPoints (le, ri); - le++; - ri--; - } - else - { - if (le < ppos - 1) - { - SwapPoints (ppos - 1, plast, le); - ppos--; - plast--; - } - else if (le == ppos - 1) - { - SwapPoints (plast, le); - ppos--; - plast--; - } - } - } + { + if (ri > plast) + { + SwapPoints (le, ri); + le++; + ri--; + } + else + { + if (le < ppos - 1) + { + SwapPoints (ppos - 1, plast, le); + ppos--; + plast--; + } + else if (le == ppos - 1) + { + SwapPoints (plast, le); + ppos--; + plast--; + } + } + } else - { - if (ri > plast + 1) - { - SwapPoints (plast + 1, ppos, ri); - ppos++; - plast++; - } - else if (ri == plast + 1) - { - SwapPoints (ppos, ri); - ppos++; - plast++; - } - else - { - break; - } - } + { + if (ri > plast + 1) + { + SwapPoints (plast + 1, ppos, ri); + ppos++; + plast++; + } + else if (ri == plast + 1) + { + SwapPoints (ppos, ri); + ppos++; + plast++; + } + else + { + break; + } + } } SortPointsByOldInd (s, ppos - 1); SortPointsByOldInd (plast + 1, e); @@ -919,8 +932,8 @@ Shape::SortPointsRounded (int s, int e) if (e == s + 1) { if (pData[s].rx[1] > pData[e].rx[1] - || (pData[s].rx[1] == pData[e].rx[1] && pData[s].rx[0] > pData[e].rx[0])) - SwapPoints (s, e); + || (pData[s].rx[1] == pData[e].rx[1] && pData[s].rx[0] > pData[e].rx[0])) + SwapPoints (s, e); return; } @@ -933,160 +946,160 @@ Shape::SortPointsRounded (int s, int e) while (le < ppos || ri > plast) { if (le < ppos) - { - do - { - int test = 0; - if (pData[le].rx[1] > pvaly) - { - test = 1; - } - else if (pData[le].rx[1] == pvaly) - { - if (pData[le].rx[0] > pvalx) - { - test = 1; - } - else if (pData[le].rx[0] == pvalx) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (le < ppos - 1) - { - SwapPoints (le, ppos - 1, ppos); - ppos--; - continue; // sans changer le - } - else if (le == ppos - 1) - { - ppos--; - break; - } - else - { - // oupsie - break; - } - } - if (test > 0) - { - break; - } - le++; - } - while (le < ppos); - } + { + do + { + int test = 0; + if (pData[le].rx[1] > pvaly) + { + test = 1; + } + else if (pData[le].rx[1] == pvaly) + { + if (pData[le].rx[0] > pvalx) + { + test = 1; + } + else if (pData[le].rx[0] == pvalx) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (le < ppos - 1) + { + SwapPoints (le, ppos - 1, ppos); + ppos--; + continue; // sans changer le + } + else if (le == ppos - 1) + { + ppos--; + break; + } + else + { + // oupsie + break; + } + } + if (test > 0) + { + break; + } + le++; + } + while (le < ppos); + } if (ri > plast) - { - do - { - int test = 0; - if (pData[ri].rx[1] > pvaly) - { - test = 1; - } - else if (pData[ri].rx[1] == pvaly) - { - if (pData[ri].rx[0] > pvalx) - { - test = 1; - } - else if (pData[ri].rx[0] == pvalx) - { - test = 0; - } - else - { - test = -1; - } - } - else - { - test = -1; - } - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (ri > plast + 1) - { - SwapPoints (ri, plast + 1, plast); - plast++; - continue; // sans changer ri - } - else if (ri == plast + 1) - { - plast++; - break; - } - else - { - // oupsie - break; - } - } - if (test < 0) - { - break; - } - ri--; - } - while (ri > plast); - } + { + do + { + int test = 0; + if (pData[ri].rx[1] > pvaly) + { + test = 1; + } + else if (pData[ri].rx[1] == pvaly) + { + if (pData[ri].rx[0] > pvalx) + { + test = 1; + } + else if (pData[ri].rx[0] == pvalx) + { + test = 0; + } + else + { + test = -1; + } + } + else + { + test = -1; + } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (ri > plast + 1) + { + SwapPoints (ri, plast + 1, plast); + plast++; + continue; // sans changer ri + } + else if (ri == plast + 1) + { + plast++; + break; + } + else + { + // oupsie + break; + } + } + if (test < 0) + { + break; + } + ri--; + } + while (ri > plast); + } if (le < ppos) - { - if (ri > plast) - { - SwapPoints (le, ri); - le++; - ri--; - } - else - { - if (le < ppos - 1) - { - SwapPoints (ppos - 1, plast, le); - ppos--; - plast--; - } - else if (le == ppos - 1) - { - SwapPoints (plast, le); - ppos--; - plast--; - } - } - } + { + if (ri > plast) + { + SwapPoints (le, ri); + le++; + ri--; + } + else + { + if (le < ppos - 1) + { + SwapPoints (ppos - 1, plast, le); + ppos--; + plast--; + } + else if (le == ppos - 1) + { + SwapPoints (plast, le); + ppos--; + plast--; + } + } + } else - { - if (ri > plast + 1) - { - SwapPoints (plast + 1, ppos, ri); - ppos++; - plast++; - } - else if (ri == plast + 1) - { - SwapPoints (ppos, ri); - ppos++; - plast++; - } - else - { - break; - } - } + { + if (ri > plast + 1) + { + SwapPoints (plast + 1, ppos, ri); + ppos++; + plast++; + } + else if (ri == plast + 1) + { + SwapPoints (ppos, ri); + ppos++; + plast++; + } + else + { + break; + } + } } SortPointsRounded (s, ppos - 1); SortPointsRounded (plast + 1, e); @@ -1107,17 +1120,17 @@ Shape::AddEdge (int st, int en) { maxAr = 2 * numberOfEdges() + 1; if (_has_edges_data) - eData.resize(maxAr); + eData.resize(maxAr); if (_has_sweep_src_data) - swsData.resize(maxAr); + swsData.resize(maxAr); if (_has_sweep_dest_data) - swdData.resize(maxAr); + swdData.resize(maxAr); if (_has_raster_data) - swrData.resize(maxAr); + swrData.resize(maxAr); if (_has_back_data) - ebData.resize(maxAr); + ebData.resize(maxAr); if (_has_voronoi_data) - voreData.resize(maxAr); + voreData.resize(maxAr); } dg_arete a; @@ -1170,11 +1183,11 @@ Shape::AddEdge (int st, int en, int leF, int riF) int cb = getPoint(st).incidentEdge[FIRST]; while (cb >= 0) { - if (getEdge(cb).st == st && getEdge(cb).en == en) - return -1; // doublon - if (getEdge(cb).st == en && getEdge(cb).en == st) - return -1; // doublon - cb = NextAt (st, cb); + if (getEdge(cb).st == st && getEdge(cb).en == en) + return -1; // doublon + if (getEdge(cb).st == en && getEdge(cb).en == st) + return -1; // doublon + cb = NextAt (st, cb); } } type = shape_graph; @@ -1182,17 +1195,17 @@ Shape::AddEdge (int st, int en, int leF, int riF) { maxAr = 2 * numberOfEdges() + 1; if (_has_edges_data) - eData.resize(maxAr); + eData.resize(maxAr); if (_has_sweep_src_data) - swsData.resize(maxAr); + swsData.resize(maxAr); if (_has_sweep_dest_data) - swdData.resize(maxAr); + swdData.resize(maxAr); if (_has_raster_data) - swrData.resize(maxAr); + swrData.resize(maxAr); if (_has_back_data) - ebData.resize(maxAr); + ebData.resize(maxAr); if (_has_voronoi_data) - voreData.resize(maxAr); + voreData.resize(maxAr); } dg_arete a; @@ -1256,106 +1269,106 @@ Shape::SwapEdges (int a, int b) if (getEdge(a).prevS >= 0 && getEdge(a).prevS != b) { if (getEdge(getEdge(a).prevS).st == getEdge(a).st) - { - _aretes[getEdge(a).prevS].nextS = b; - } + { + _aretes[getEdge(a).prevS].nextS = b; + } else if (getEdge(getEdge(a).prevS).en == getEdge(a).st) - { - _aretes[getEdge(a).prevS].nextE = b; - } + { + _aretes[getEdge(a).prevS].nextE = b; + } } if (getEdge(a).nextS >= 0 && getEdge(a).nextS != b) { if (getEdge(getEdge(a).nextS).st == getEdge(a).st) - { - _aretes[getEdge(a).nextS].prevS = b; - } + { + _aretes[getEdge(a).nextS].prevS = b; + } else if (getEdge(getEdge(a).nextS).en == getEdge(a).st) - { - _aretes[getEdge(a).nextS].prevE = b; - } + { + _aretes[getEdge(a).nextS].prevE = b; + } } if (getEdge(a).prevE >= 0 && getEdge(a).prevE != b) { if (getEdge(getEdge(a).prevE).st == getEdge(a).en) - { - _aretes[getEdge(a).prevE].nextS = b; - } + { + _aretes[getEdge(a).prevE].nextS = b; + } else if (getEdge(getEdge(a).prevE).en == getEdge(a).en) - { - _aretes[getEdge(a).prevE].nextE = b; - } + { + _aretes[getEdge(a).prevE].nextE = b; + } } if (getEdge(a).nextE >= 0 && getEdge(a).nextE != b) { if (getEdge(getEdge(a).nextE).st == getEdge(a).en) - { - _aretes[getEdge(a).nextE].prevS = b; - } + { + _aretes[getEdge(a).nextE].prevS = b; + } else if (getEdge(getEdge(a).nextE).en == getEdge(a).en) - { - _aretes[getEdge(a).nextE].prevE = b; - } + { + _aretes[getEdge(a).nextE].prevE = b; + } } if (getEdge(a).st >= 0) { if (getPoint(getEdge(a).st).incidentEdge[FIRST] == a) - _pts[getEdge(a).st].incidentEdge[FIRST] = numberOfEdges(); + _pts[getEdge(a).st].incidentEdge[FIRST] = numberOfEdges(); if (getPoint(getEdge(a).st).incidentEdge[LAST] == a) - _pts[getEdge(a).st].incidentEdge[LAST] = numberOfEdges(); + _pts[getEdge(a).st].incidentEdge[LAST] = numberOfEdges(); } if (getEdge(a).en >= 0) { if (getPoint(getEdge(a).en).incidentEdge[FIRST] == a) - _pts[getEdge(a).en].incidentEdge[FIRST] = numberOfEdges(); + _pts[getEdge(a).en].incidentEdge[FIRST] = numberOfEdges(); if (getPoint(getEdge(a).en).incidentEdge[LAST] == a) - _pts[getEdge(a).en].incidentEdge[LAST] = numberOfEdges(); + _pts[getEdge(a).en].incidentEdge[LAST] = numberOfEdges(); } if (getEdge(b).prevS >= 0 && getEdge(b).prevS != a) { if (getEdge(getEdge(b).prevS).st == getEdge(b).st) - { - _aretes[getEdge(b).prevS].nextS = a; - } + { + _aretes[getEdge(b).prevS].nextS = a; + } else if (getEdge(getEdge(b).prevS).en == getEdge(b).st) - { - _aretes[getEdge(b).prevS].nextE = a; - } + { + _aretes[getEdge(b).prevS].nextE = a; + } } if (getEdge(b).nextS >= 0 && getEdge(b).nextS != a) { if (getEdge(getEdge(b).nextS).st == getEdge(b).st) - { - _aretes[getEdge(b).nextS].prevS = a; - } + { + _aretes[getEdge(b).nextS].prevS = a; + } else if (getEdge(getEdge(b).nextS).en == getEdge(b).st) - { - _aretes[getEdge(b).nextS].prevE = a; - } + { + _aretes[getEdge(b).nextS].prevE = a; + } } if (getEdge(b).prevE >= 0 && getEdge(b).prevE != a) { if (getEdge(getEdge(b).prevE).st == getEdge(b).en) - { - _aretes[getEdge(b).prevE].nextS = a; - } + { + _aretes[getEdge(b).prevE].nextS = a; + } else if (getEdge(getEdge(b).prevE).en == getEdge(b).en) - { - _aretes[getEdge(b).prevE].nextE = a; - } + { + _aretes[getEdge(b).prevE].nextE = a; + } } if (getEdge(b).nextE >= 0 && getEdge(b).nextE != a) { if (getEdge(getEdge(b).nextE).st == getEdge(b).en) - { - _aretes[getEdge(b).nextE].prevS = a; - } + { + _aretes[getEdge(b).nextE].prevS = a; + } else if (getEdge(getEdge(b).nextE).en == getEdge(b).en) - { - _aretes[getEdge(b).nextE].prevE = a; - } + { + _aretes[getEdge(b).nextE].prevE = a; + } } @@ -1363,28 +1376,28 @@ Shape::SwapEdges (int a, int b) int p = getEdge(b).st; if (p >= 0) { if (getPoint(p).incidentEdge[i] == b) { - _pts[p].incidentEdge[i] = a; + _pts[p].incidentEdge[i] = a; } } p = getEdge(b).en; if (p >= 0) { if (getPoint(p).incidentEdge[i] == b) { - _pts[p].incidentEdge[i] = a; + _pts[p].incidentEdge[i] = a; } } p = getEdge(a).st; if (p >= 0) { if (getPoint(p).incidentEdge[i] == numberOfEdges()) { - _pts[p].incidentEdge[i] = b; + _pts[p].incidentEdge[i] = b; } } p = getEdge(a).en; if (p >= 0) { if (getPoint(p).incidentEdge[i] == numberOfEdges()) { - _pts[p].incidentEdge[i] = b; + _pts[p].incidentEdge[i] = b; } } @@ -1469,71 +1482,71 @@ Shape::SortEdges (void) { int const d = getPoint(p).totalDegree(); if (d > 1) - { - int cb; - cb = getPoint(p).incidentEdge[FIRST]; - int nb = 0; - while (cb >= 0) - { - int n = nb++; - list[n].no = cb; - if (getEdge(cb).st == p) - { - list[n].x = getEdge(cb).dx; - list[n].starting = true; - } - else - { - list[n].x = -getEdge(cb).dx; - list[n].starting = false; - } - cb = NextAt (p, cb); - } - SortEdgesList (list, 0, nb - 1); - _pts[p].incidentEdge[FIRST] = list[0].no; - _pts[p].incidentEdge[LAST] = list[nb - 1].no; - for (int i = 0; i < nb; i++) - { - if (list[i].starting) - { - if (i > 0) - { - _aretes[list[i].no].prevS = list[i - 1].no; - } - else - { - _aretes[list[i].no].prevS = -1; - } - if (i < nb - 1) - { - _aretes[list[i].no].nextS = list[i + 1].no; - } - else - { - _aretes[list[i].no].nextS = -1; - } - } - else - { - if (i > 0) - { - _aretes[list[i].no].prevE = list[i - 1].no; - } - else - { - _aretes[list[i].no].prevE = -1; - } - if (i < nb - 1) - { - _aretes[list[i].no].nextE = list[i + 1].no; - } - else - { - _aretes[list[i].no].nextE = -1; - } - } - } - } + { + int cb; + cb = getPoint(p).incidentEdge[FIRST]; + int nb = 0; + while (cb >= 0) + { + int n = nb++; + list[n].no = cb; + if (getEdge(cb).st == p) + { + list[n].x = getEdge(cb).dx; + list[n].starting = true; + } + else + { + list[n].x = -getEdge(cb).dx; + list[n].starting = false; + } + cb = NextAt (p, cb); + } + SortEdgesList (list, 0, nb - 1); + _pts[p].incidentEdge[FIRST] = list[0].no; + _pts[p].incidentEdge[LAST] = list[nb - 1].no; + for (int i = 0; i < nb; i++) + { + if (list[i].starting) + { + if (i > 0) + { + _aretes[list[i].no].prevS = list[i - 1].no; + } + else + { + _aretes[list[i].no].prevS = -1; + } + if (i < nb - 1) + { + _aretes[list[i].no].nextS = list[i + 1].no; + } + else + { + _aretes[list[i].no].nextS = -1; + } + } + else + { + if (i > 0) + { + _aretes[list[i].no].prevE = list[i - 1].no; + } + else + { + _aretes[list[i].no].prevE = -1; + } + if (i < nb - 1) + { + _aretes[list[i].no].nextE = list[i + 1].no; + } + else + { + _aretes[list[i].no].nextE = -1; + } + } + } + } } g_free(list); } @@ -1566,92 +1579,92 @@ Shape::CmpToVert (NR::Point ax, NR::Point bx,bool as,bool bs) if (tstAX < 0) { if (tstAY < 0) - { - quadA = 7; - } + { + quadA = 7; + } else if (tstAY == 0) - { - quadA = 6; - } + { + quadA = 6; + } else if (tstAY > 0) - { - quadA = 5; - } + { + quadA = 5; + } } else if (tstAX == 0) { if (tstAY < 0) - { - quadA = 0; - } + { + quadA = 0; + } else if (tstAY == 0) - { - quadA = -1; - } + { + quadA = -1; + } else if (tstAY > 0) - { - quadA = 4; - } + { + quadA = 4; + } } else if (tstAX > 0) { if (tstAY < 0) - { - quadA = 1; - } + { + quadA = 1; + } else if (tstAY == 0) - { - quadA = 2; - } + { + quadA = 2; + } else if (tstAY > 0) - { - quadA = 3; - } + { + quadA = 3; + } } if (tstBX < 0) { if (tstBY < 0) - { - quadB = 7; - } + { + quadB = 7; + } else if (tstBY == 0) - { - quadB = 6; - } + { + quadB = 6; + } else if (tstBY > 0) - { - quadB = 5; - } + { + quadB = 5; + } } else if (tstBX == 0) { if (tstBY < 0) - { - quadB = 0; - } + { + quadB = 0; + } else if (tstBY == 0) - { - quadB = -1; - } + { + quadB = -1; + } else if (tstBY > 0) - { - quadB = 4; - } + { + quadB = 4; + } } else if (tstBX > 0) { if (tstBY < 0) - { - quadB = 1; - } + { + quadB = 1; + } else if (tstBY == 0) - { - quadB = 2; - } + { + quadB = 2; + } else if (tstBY > 0) - { - quadB = 3; - } + { + quadB = 3; + } } if (quadA < quadB) return 1; @@ -1696,134 +1709,134 @@ Shape::SortEdgesList (edge_list * list, int s, int e) while (le < ppos || ri > plast) { if (le < ppos) - { - do - { + { + do + { int test = CmpToVert (pvalx, list[le].x,pvals,list[le].starting); - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (le < ppos - 1) - { - edge_list swap = list[le]; - list[le] = list[ppos - 1]; - list[ppos - 1] = list[ppos]; - list[ppos] = swap; - ppos--; - continue; // sans changer le - } - else if (le == ppos - 1) - { - ppos--; - break; - } - else - { - // oupsie - break; - } - } - if (test > 0) - { - break; - } - le++; - } - while (le < ppos); - } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (le < ppos - 1) + { + edge_list swap = list[le]; + list[le] = list[ppos - 1]; + list[ppos - 1] = list[ppos]; + list[ppos] = swap; + ppos--; + continue; // sans changer le + } + else if (le == ppos - 1) + { + ppos--; + break; + } + else + { + // oupsie + break; + } + } + if (test > 0) + { + break; + } + le++; + } + while (le < ppos); + } if (ri > plast) - { - do - { + { + do + { int test = CmpToVert (pvalx, list[ri].x,pvals,list[ri].starting); - if (test == 0) - { - // on colle les valeurs egales au pivot ensemble - if (ri > plast + 1) - { - edge_list swap = list[ri]; - list[ri] = list[plast + 1]; - list[plast + 1] = list[plast]; - list[plast] = swap; - plast++; - continue; // sans changer ri - } - else if (ri == plast + 1) - { - plast++; - break; - } - else - { - // oupsie - break; - } - } - if (test < 0) - { - break; - } - ri--; - } - while (ri > plast); - } + if (test == 0) + { + // on colle les valeurs egales au pivot ensemble + if (ri > plast + 1) + { + edge_list swap = list[ri]; + list[ri] = list[plast + 1]; + list[plast + 1] = list[plast]; + list[plast] = swap; + plast++; + continue; // sans changer ri + } + else if (ri == plast + 1) + { + plast++; + break; + } + else + { + // oupsie + break; + } + } + if (test < 0) + { + break; + } + ri--; + } + while (ri > plast); + } if (le < ppos) - { - if (ri > plast) - { - edge_list swap = list[le]; - list[le] = list[ri]; - list[ri] = swap; - le++; - ri--; - } - else if (le < ppos - 1) - { - edge_list swap = list[ppos - 1]; - list[ppos - 1] = list[plast]; - list[plast] = list[le]; - list[le] = swap; - ppos--; - plast--; - } - else if (le == ppos - 1) - { - edge_list swap = list[plast]; - list[plast] = list[le]; - list[le] = swap; - ppos--; - plast--; - } - else - { - break; - } - } + { + if (ri > plast) + { + edge_list swap = list[le]; + list[le] = list[ri]; + list[ri] = swap; + le++; + ri--; + } + else if (le < ppos - 1) + { + edge_list swap = list[ppos - 1]; + list[ppos - 1] = list[plast]; + list[plast] = list[le]; + list[le] = swap; + ppos--; + plast--; + } + else if (le == ppos - 1) + { + edge_list swap = list[plast]; + list[plast] = list[le]; + list[le] = swap; + ppos--; + plast--; + } + else + { + break; + } + } else - { - if (ri > plast + 1) - { - edge_list swap = list[plast + 1]; - list[plast + 1] = list[ppos]; - list[ppos] = list[ri]; - list[ri] = swap; - ppos++; - plast++; - } - else if (ri == plast + 1) - { - edge_list swap = list[ppos]; - list[ppos] = list[ri]; - list[ri] = swap; - ppos++; - plast++; - } - else - { - break; - } - } + { + if (ri > plast + 1) + { + edge_list swap = list[plast + 1]; + list[plast + 1] = list[ppos]; + list[ppos] = list[ri]; + list[ri] = swap; + ppos++; + plast++; + } + else if (ri == plast + 1) + { + edge_list swap = list[ppos]; + list[ppos] = list[ri]; + list[ri] = swap; + ppos++; + plast++; + } + else + { + break; + } + } } SortEdgesList (list, s, ppos - 1); SortEdgesList (list, plast + 1, e); @@ -1848,13 +1861,13 @@ Shape::ConnectStart (int p, int b) if (getPoint(p).incidentEdge[LAST] >= 0) { if (getEdge(getPoint(p).incidentEdge[LAST]).st == p) - { - _aretes[getPoint(p).incidentEdge[LAST]].nextS = b; - } + { + _aretes[getPoint(p).incidentEdge[LAST]].nextS = b; + } else if (getEdge(getPoint(p).incidentEdge[LAST]).en == p) - { - _aretes[getPoint(p).incidentEdge[LAST]].nextE = b; - } + { + _aretes[getPoint(p).incidentEdge[LAST]].nextE = b; + } } _pts[p].incidentEdge[LAST] = b; if (getPoint(p).incidentEdge[FIRST] < 0) @@ -1873,13 +1886,13 @@ Shape::ConnectEnd (int p, int b) if (getPoint(p).incidentEdge[LAST] >= 0) { if (getEdge(getPoint(p).incidentEdge[LAST]).st == p) - { - _aretes[getPoint(p).incidentEdge[LAST]].nextS = b; - } + { + _aretes[getPoint(p).incidentEdge[LAST]].nextS = b; + } else if (getEdge(getPoint(p).incidentEdge[LAST]).en == p) - { - _aretes[getPoint(p).incidentEdge[LAST]].nextE = b; - } + { + _aretes[getPoint(p).incidentEdge[LAST]].nextE = b; + } } _pts[p].incidentEdge[LAST] = b; if (getPoint(p).incidentEdge[FIRST] < 0) @@ -1895,24 +1908,24 @@ Shape::DisconnectStart (int b) if (getEdge(b).prevS >= 0) { if (getEdge(getEdge(b).prevS).st == getEdge(b).st) - { - _aretes[getEdge(b).prevS].nextS = getEdge(b).nextS; - } + { + _aretes[getEdge(b).prevS].nextS = getEdge(b).nextS; + } else if (getEdge(getEdge(b).prevS).en == getEdge(b).st) - { - _aretes[getEdge(b).prevS].nextE = getEdge(b).nextS; - } + { + _aretes[getEdge(b).prevS].nextE = getEdge(b).nextS; + } } if (getEdge(b).nextS >= 0) { if (getEdge(getEdge(b).nextS).st == getEdge(b).st) - { - _aretes[getEdge(b).nextS].prevS = getEdge(b).prevS; - } + { + _aretes[getEdge(b).nextS].prevS = getEdge(b).prevS; + } else if (getEdge(getEdge(b).nextS).en == getEdge(b).st) - { - _aretes[getEdge(b).nextS].prevE = getEdge(b).prevS; - } + { + _aretes[getEdge(b).nextS].prevE = getEdge(b).prevS; + } } if (getPoint(getEdge(b).st).incidentEdge[FIRST] == b) _pts[getEdge(b).st].incidentEdge[FIRST] = getEdge(b).nextS; @@ -1930,24 +1943,24 @@ Shape::DisconnectEnd (int b) if (getEdge(b).prevE >= 0) { if (getEdge(getEdge(b).prevE).st == getEdge(b).en) - { - _aretes[getEdge(b).prevE].nextS = getEdge(b).nextE; - } + { + _aretes[getEdge(b).prevE].nextS = getEdge(b).nextE; + } else if (getEdge(getEdge(b).prevE).en == getEdge(b).en) - { - _aretes[getEdge(b).prevE].nextE = getEdge(b).nextE; - } + { + _aretes[getEdge(b).prevE].nextE = getEdge(b).nextE; + } } if (getEdge(b).nextE >= 0) { if (getEdge(getEdge(b).nextE).st == getEdge(b).en) - { - _aretes[getEdge(b).nextE].prevS = getEdge(b).prevE; - } + { + _aretes[getEdge(b).nextE].prevS = getEdge(b).prevE; + } else if (getEdge(getEdge(b).nextE).en == getEdge(b).en) - { - _aretes[getEdge(b).nextE].prevE = getEdge(b).prevE; - } + { + _aretes[getEdge(b).nextE].prevE = getEdge(b).prevE; + } } if (getPoint(getEdge(b).en).incidentEdge[FIRST] == b) _pts[getEdge(b).en].incidentEdge[FIRST] = getEdge(b).nextE; @@ -2005,9 +2018,12 @@ Shape::Inverse (int b) void Shape::CalcBBox (bool strict_degree) { + if (_bbox_up_to_date) + return; if (hasPoints() == false) { leftX = rightX = topY = bottomY = 0; + _bbox_up_to_date = true; return; } leftX = rightX = getPoint(0).x[0]; @@ -2028,6 +2044,8 @@ Shape::CalcBBox (bool strict_degree) } } } + + _bbox_up_to_date = true; } // winding of a point with respect to the Shape @@ -2091,15 +2109,19 @@ Shape::PtWinding (const NR::Point px) const void Shape::initialisePointData() { + if (_point_data_initialised) + return; int const N = numberOfPoints(); for (int i = 0; i < N; i++) { - pData[i].pending = 0; - pData[i].edgeOnLeft = -1; - pData[i].nextLinkedPoint = -1; - pData[i].rx[0] = Round(getPoint(i).x[0]); - pData[i].rx[1] = Round(getPoint(i).x[1]); + pData[i].pending = 0; + pData[i].edgeOnLeft = -1; + pData[i].nextLinkedPoint = -1; + pData[i].rx[0] = Round(getPoint(i).x[0]); + pData[i].rx[1] = Round(getPoint(i).x[1]); } + + _point_data_initialised = true; } void Shape::initialiseEdgeData() @@ -2107,27 +2129,27 @@ void Shape::initialiseEdgeData() int const N = numberOfEdges(); for (int i = 0; i < N; i++) { - eData[i].rdx = pData[getEdge(i).en].rx - pData[getEdge(i).st].rx; - eData[i].length = dot(eData[i].rdx, eData[i].rdx); - eData[i].ilength = 1 / eData[i].length; - eData[i].sqlength = sqrt(eData[i].length); - eData[i].isqlength = 1 / eData[i].sqlength; - eData[i].siEd = eData[i].rdx[1] * eData[i].isqlength; - eData[i].coEd = eData[i].rdx[0] * eData[i].isqlength; - - if (eData[i].siEd < 0) { - eData[i].siEd = -eData[i].siEd; - eData[i].coEd = -eData[i].coEd; - } - - swsData[i].misc = NULL; - swsData[i].firstLinkedPoint = -1; - swsData[i].stPt = swsData[i].enPt = -1; - swsData[i].leftRnd = swsData[i].rightRnd = -1; - swsData[i].nextSh = NULL; - swsData[i].nextBo = -1; - swsData[i].curPoint = -1; - swsData[i].doneTo = -1; + eData[i].rdx = pData[getEdge(i).en].rx - pData[getEdge(i).st].rx; + eData[i].length = dot(eData[i].rdx, eData[i].rdx); + eData[i].ilength = 1 / eData[i].length; + eData[i].sqlength = sqrt(eData[i].length); + eData[i].isqlength = 1 / eData[i].sqlength; + eData[i].siEd = eData[i].rdx[1] * eData[i].isqlength; + eData[i].coEd = eData[i].rdx[0] * eData[i].isqlength; + + if (eData[i].siEd < 0) { + eData[i].siEd = -eData[i].siEd; + eData[i].coEd = -eData[i].coEd; + } + + swsData[i].misc = NULL; + swsData[i].firstLinkedPoint = -1; + swsData[i].stPt = swsData[i].enPt = -1; + swsData[i].leftRnd = swsData[i].rightRnd = -1; + swsData[i].nextSh = NULL; + swsData[i].nextBo = -1; + swsData[i].curPoint = -1; + swsData[i].doneTo = -1; } } @@ -2152,9 +2174,9 @@ void Shape::clearIncidenceData() bool directedEulerian(Shape const *s) { for (int i = 0; i < s->numberOfPoints(); i++) { - if (s->getPoint(i).dI != s->getPoint(i).dO) { - return false; - } + if (s->getPoint(i).dI != s->getPoint(i).dO) { + return false; + } } return true; @@ -2171,7 +2193,7 @@ bool directedEulerian(Shape const *s) double distance(Shape const *s, NR::Point const &p) { if ( s->hasPoints() == false) { - return 0.0; + return 0.0; } /* Find the minimum distance from p to one of the points on s. @@ -2182,35 +2204,35 @@ double distance(Shape const *s, NR::Point const &p) double bdot = NR::dot(p - s->getPoint(0).x, p - s->getPoint(0).x); for (int i = 0; i < s->numberOfPoints(); i++) { - NR::Point const offset( p - s->getPoint(i).x ); - double ndot = NR::dot(offset, offset); - if ( ndot < bdot ) { - bdot = ndot; - } + NR::Point const offset( p - s->getPoint(i).x ); + double ndot = NR::dot(offset, offset); + if ( ndot < bdot ) { + bdot = ndot; + } } for (int i = 0; i < s->numberOfEdges(); i++) { - if ( s->getEdge(i).st >= 0 && s->getEdge(i).en >= 0 ) { - /* The edge has start and end points */ - NR::Point const st(s->getPoint(s->getEdge(i).st).x); // edge start - NR::Point const en(s->getPoint(s->getEdge(i).en).x); // edge end - - NR::Point const d(p - st); // vector between p and edge start - NR::Point const e(en - st); // vector of the edge - double const el = NR::dot(e, e); // edge length - - /* Update bdot if appropriate */ - if ( el > 0.001 ) { - double const npr = NR::dot(d, e); - if ( npr > 0 && npr < el ) { - double const nl = fabs( NR::cross(d, e) ); - double ndot = nl * nl / el; - if ( ndot < bdot ) { - bdot = ndot; - } - } - } - } + if ( s->getEdge(i).st >= 0 && s->getEdge(i).en >= 0 ) { + /* The edge has start and end points */ + NR::Point const st(s->getPoint(s->getEdge(i).st).x); // edge start + NR::Point const en(s->getPoint(s->getEdge(i).en).x); // edge end + + NR::Point const d(p - st); // vector between p and edge start + NR::Point const e(en - st); // vector of the edge + double const el = NR::dot(e, e); // edge length + + /* Update bdot if appropriate */ + if ( el > 0.001 ) { + double const npr = NR::dot(d, e); + if ( npr > 0 && npr < el ) { + double const nl = fabs( NR::cross(d, e) ); + double ndot = nl * nl / el; + if ( ndot < bdot ) { + bdot = ndot; + } + } + } + } } return sqrt(bdot); @@ -2233,7 +2255,7 @@ double distance(Shape const *s, NR::Point const &p) bool distanceLessThanOrEqual(Shape const *s, NR::Point const &p, double const max_l2) { if ( s->hasPoints() == false ) { - return false; + return false; } /* TODO: Consider using bbox to return early, perhaps conditional on nbPt or nbAr. */ @@ -2248,31 +2270,31 @@ bool distanceLessThanOrEqual(Shape const *s, NR::Point const &p, double const ma double const max_l1 = max_l2 * M_SQRT2; for (int i = 0; i < s->numberOfPoints(); i++) { - NR::Point const offset( p - s->getPoint(i).x ); - double const l1 = NR::L1(offset); - if ( (l1 <= max_l2) || ((l1 <= max_l1) && (NR::L2(offset) <= max_l2)) ) { - return true; - } + NR::Point const offset( p - s->getPoint(i).x ); + double const l1 = NR::L1(offset); + if ( (l1 <= max_l2) || ((l1 <= max_l1) && (NR::L2(offset) <= max_l2)) ) { + return true; + } } for (int i = 0; i < s->numberOfEdges(); i++) { - if ( s->getEdge(i).st >= 0 && s->getEdge(i).en >= 0 ) { - NR::Point const st(s->getPoint(s->getEdge(i).st).x); - NR::Point const en(s->getPoint(s->getEdge(i).en).x); - NR::Point const d(p - st); - NR::Point const e(en - st); - double const el = NR::L2(e); - if ( el > 0.001 ) { - NR::Point const e_unit(e / el); - double const npr = NR::dot(d, e_unit); - if ( npr > 0 && npr < el ) { - double const nl = fabs(NR::cross(d, e_unit)); - if ( nl <= max_l2 ) { - return true; - } - } - } - } + if ( s->getEdge(i).st >= 0 && s->getEdge(i).en >= 0 ) { + NR::Point const st(s->getPoint(s->getEdge(i).st).x); + NR::Point const en(s->getPoint(s->getEdge(i).en).x); + NR::Point const d(p - st); + NR::Point const e(en - st); + double const el = NR::L2(e); + if ( el > 0.001 ) { + NR::Point const e_unit(e / el); + double const npr = NR::dot(d, e_unit); + if ( npr > 0 && npr < el ) { + double const nl = fabs(NR::cross(d, e_unit)); + if ( nl <= max_l2 ) { + return true; + } + } + } + } } return false; diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h index d0be5e44e..37039f241 100644 --- a/src/livarot/Shape.h +++ b/src/livarot/Shape.h @@ -315,7 +315,7 @@ public: int nbQRas; int firstQRas; int lastQRas; - std::vector qrsData; + quick_raster_data *qrsData; std::vector chgts; int nbInc; @@ -523,6 +523,7 @@ private: bool _need_edges_sorting; ///< edges have been added: maybe they are not ordered clockwise ///< nota: if you remove an edge, the clockwise order still holds bool _has_points_data; ///< the pData array is allocated + bool _point_data_initialised;///< the pData array is up to date bool _has_edges_data; ///< the eData array is allocated bool _has_sweep_src_data; ///< the swsData array is allocated bool _has_sweep_dest_data; ///< the swdData array is allocated @@ -530,6 +531,7 @@ private: bool _has_quick_raster_data;///< the swrData array is allocated bool _has_back_data; //< the ebData array is allocated bool _has_voronoi_data; + bool _bbox_up_to_date; ///< the leftX/rightX/topY/bottomY are up to date std::vector _pts; std::vector _aretes; diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index d9bb665f0..a76c0f745 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -541,8 +541,11 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter) if (numberOfPoints() > maxPt) { maxPt = numberOfPoints(); - if (_has_points_data) + if (_has_points_data) { pData.resize(maxPt); + _point_data_initialised = false; + _bbox_up_to_date = false; + } } _aretes = a->_aretes; diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp index 3e5a3bcaf..ea401f7f0 100644 --- a/src/livarot/ShapeSweep.cpp +++ b/src/livarot/ShapeSweep.cpp @@ -75,8 +75,11 @@ Shape::Reoriente (Shape * a) if (numberOfPoints() > maxPt) { maxPt = numberOfPoints(); - if (_has_points_data) - pData.resize(maxPt); + if (_has_points_data) { + pData.resize(maxPt); + _point_data_initialised = false; + _bbox_up_to_date = false; + } } _aretes = a->_aretes;