I think I've found a pretty serious bug where DrawSetClipPath shows data corruption. The code example below is doing the following:
* Create a DrawingWand.
* Defining a clip path which is either just a rectangle in the top left quadrant of the image, or the same but with extra clip regions across the DrawingWand.
* Setting that clip path.
* Drawing a rectangle into the centre of the DrawingWand.
* Saving that drawing wand to a file.
That codes is called multiple times.
It starts out producing the images as expected:
But after several runs, each of which shouldn't affect each other, the images start looking like:
i.e. the data from the previous images is leaking through to the current image.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wand/MagickWand.h>
void ThrowWandException(MagickWand *wand) {
char *description;
ExceptionType severity;
description = MagickGetException(wand, &severity);
(void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description);
description=(char *) MagickRelinquishMemory(description);
exit(-1);
}
PixelWand *makePixelWand(char *string) {
PixelWand *pixel_wand;
pixel_wand = NewPixelWand();
if (PixelSetColor (pixel_wand, string) == MagickFalse) {
printf("Failed to set color");
exit(-1);
}
return pixel_wand;
}
void drawClipTest(int extraClipping, int writeFile, char *filename) {
MagickBooleanType status;
DrawingWand *drawing_wand;
PixelWand *fill_color_wand, *stroke_color_wand;
char *clip_mask;
char *clip_mask_duplicate;
int x;
char *backgroundColor = "rgb(225, 225, 225)";
char *strokeColor = "rgb(0, 0, 0)";
char *fillColor = "DodgerBlue2";
PixelWand *destroyed_wand;
// $draw = new \ImagickDraw();
drawing_wand = NewDrawingWand();
// $draw->setStrokeColor($strokeColor);
stroke_color_wand = makePixelWand(strokeColor);
DrawSetStrokeColor(drawing_wand, stroke_color_wand);
//destroyed_wand = DestroyPixelWand (stroke_color_wand);
//clearWand(stroke_color_wand);
// $draw->setFillColor($fillColor);
fill_color_wand = makePixelWand(fillColor);
DrawSetFillColor(drawing_wand, fill_color_wand);
//destroyed_wand = DestroyPixelWand (fill_color_wand);
//clearWand(fill_color_wand);
// $draw->setStrokeOpacity(1);
DrawSetStrokeOpacity(drawing_wand, 1);
// $draw->setStrokeWidth(2);
DrawSetStrokeWidth(drawing_wand, 2);
// $draw->pushClipPath($clipPathName);
DrawPushClipPath(drawing_wand, "testClipPath");
// $draw->rectangle(0, 0, 250, 250);
DrawRectangle(drawing_wand, 0, 0, 250, 250);
if (extraClipping) {
for (x=0 ; x<1000 ; x++) {
int posX = (x * 23 * 53 ) % 500;
int posY = (x * 7) % 500;
DrawRectangle(drawing_wand, posX, posY, posX + 10, posY + 10);
}
}
// $draw->popClipPath();
DrawPopClipPath(drawing_wand);
//DrawSetClipRule(internd->drawing_wand, fill_rule);
status = DrawSetClipPath(drawing_wand, "testClipPath");
if (status == MagickFalse) {
printf("Failed to DrawSetClipPath ");
exit(-1);
}
// $draw->rectangle(200, 200, 300, 300);
//This is the only thing that should be drawn into the final image
DrawRectangle(drawing_wand, 100, 100, 400, 400);
MagickWand *magick_wand;
magick_wand = NewMagickWand();
PixelWand *background_color_wand = makePixelWand(backgroundColor);
status = MagickNewImage(magick_wand, 500, 500, background_color_wand);
if (writeFile) {
MagickSetImageFormat(magick_wand, "png");
MagickDrawImage(magick_wand, drawing_wand);
status = MagickWriteImages(magick_wand, filename, MagickTrue);
if (status == MagickFalse) {
ThrowWandException(magick_wand);
}
}
magick_wand = DestroyMagickWand(magick_wand);
return;
}
int main(int argc,char **argv) {
int x;
char filename[1024];
MagickWandGenesis();
for (x=0 ; x<10 ; x++) {
sprintf(filename, "clipFirst_%d.png", x);
drawClipTest(1, 1, filename);
sprintf(filename, "clipSecond_%d.png", x);
drawClipTest(0, 1, filename);
}
MagickWandTerminus();
return (0);
}