00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
#include "magick/studio.h"
00049
#include "magick/annotate.h"
00050
#include "magick/attribute.h"
00051
#include "magick/blob.h"
00052
#include "magick/color.h"
00053
#include "magick/composite.h"
00054
#include "magick/composite_private.h"
00055
#include "magick/constitute.h"
00056
#include "magick/draw.h"
00057
#include "magick/draw_private.h"
00058
#include "magick/enhance.h"
00059
#include "magick/error.h"
00060
#include "magick/error_private.h"
00061
#include "magick/gem.h"
00062
#include "magick/geometry.h"
00063
#include "magick/log.h"
00064
#include "magick/monitor.h"
00065
#include "magick/option.h"
00066
#include "magick/paint.h"
00067
#include "magick/string_.h"
00068
#include "magick/token.h"
00069
#include "magick/transform.h"
00070
#include "magick/utility.h"
00071
00072
00073
00074
00075 #define BezierQuantum 200
00076
00077
00078
00079
00080 typedef struct _EdgeInfo
00081 {
00082
SegmentInfo
00083 bounds;
00084
00085
MagickRealType
00086 scanline;
00087
00088
PointInfo
00089 *
points;
00090
00091
unsigned long
00092 number_points;
00093
00094
long
00095 direction;
00096
00097
MagickBooleanType
00098 ghostline;
00099
00100
unsigned long
00101 highwater;
00102 }
EdgeInfo;
00103
00104
typedef struct _ElementInfo
00105 {
00106
MagickRealType
00107 cx,
00108
cy,
00109
major,
00110
minor,
00111
angle;
00112 }
ElementInfo;
00113
00114 typedef struct _PolygonInfo
00115 {
00116
EdgeInfo
00117 *
edges;
00118
00119
unsigned long
00120 number_edges;
00121 }
PolygonInfo;
00122
00123 typedef enum
00124 {
00125
MoveToCode,
00126
OpenCode,
00127
GhostlineCode,
00128
LineToCode,
00129
EndCode
00130 }
PathInfoCode;
00131
00132 typedef struct _PathInfo
00133 {
00134
PointInfo
00135 point;
00136
00137
PathInfoCode
00138 code;
00139 }
PathInfo;
00140
00141
00142
00143
00144
static PrimitiveInfo
00145 *
TraceStrokePolygon(
const DrawInfo *,
const PrimitiveInfo *);
00146
00147
static MagickBooleanType
00148
DrawStrokePolygon(
Image *,
const DrawInfo *,
const PrimitiveInfo *);
00149
00150
static unsigned long
00151
TracePath(
PrimitiveInfo *,
const char *);
00152
00153
static void
00154
#if defined(MagickFuture)
00155
DestroyGradientInfo(
GradientInfo *),
00156
#endif
00157
TraceArc(
PrimitiveInfo *,
const PointInfo,
const PointInfo,
const PointInfo),
00158
TraceArcPath(
PrimitiveInfo *,
const PointInfo,
const PointInfo,
const PointInfo,
00159
const double,
const MagickBooleanType,
const MagickBooleanType),
00160
TraceBezier(
PrimitiveInfo *,
const unsigned long),
00161
TraceCircle(
PrimitiveInfo *,
const PointInfo,
const PointInfo),
00162
TraceEllipse(
PrimitiveInfo *,
const PointInfo,
const PointInfo,
const PointInfo),
00163
TraceLine(
PrimitiveInfo *,
const PointInfo,
const PointInfo),
00164
TraceRectangle(
PrimitiveInfo *,
const PointInfo,
const PointInfo),
00165
TraceRoundRectangle(
PrimitiveInfo *,
const PointInfo,
const PointInfo,
00166
PointInfo),
00167
TraceSquareLinecap(
PrimitiveInfo *,
const unsigned long,
const double);
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 MagickExport void GetAffineMatrix(
AffineMatrix *affine_matrix)
00194 {
00195 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),
"...");
00196
assert(affine_matrix != (
AffineMatrix *) NULL);
00197 (
void)
ResetMagickMemory(affine_matrix,0,
sizeof(*affine_matrix));
00198 affine_matrix->sx=1.0;
00199 affine_matrix->sy=1.0;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 MagickExport DrawInfo *
CloneDrawInfo(
const ImageInfo *image_info,
00231
const DrawInfo *draw_info)
00232 {
00233
DrawInfo
00234 *clone_info;
00235
00236 clone_info=(
DrawInfo *)
AcquireMagickMemory(
sizeof(*clone_info));
00237
if (clone_info == (
DrawInfo *) NULL)
00238
ThrowMagickFatalException(
ResourceLimitFatalError,
00239
"UnableToAllocateDrawInfo",image_info->
filename);
00240
GetDrawInfo(image_info,clone_info);
00241
if (draw_info == (
DrawInfo *) NULL)
00242
return(clone_info);
00243
if (clone_info->primitive != (
char *) NULL)
00244 (
void)
CloneString(&clone_info->primitive,draw_info->
primitive);
00245
if (draw_info->
geometry != (
char *) NULL)
00246 (
void)
CloneString(&clone_info->geometry,draw_info->
geometry);
00247 clone_info->viewbox=draw_info->
viewbox;
00248 clone_info->affine=draw_info->
affine;
00249 clone_info->gravity=draw_info->
gravity;
00250 clone_info->fill=draw_info->
fill;
00251 clone_info->stroke=draw_info->
stroke;
00252 clone_info->stroke_width=draw_info->
stroke_width;
00253
if (draw_info->
fill_pattern != (
Image *) NULL)
00254 clone_info->fill_pattern=
CloneImage(draw_info->
fill_pattern,0,0,
MagickTrue,
00255 &draw_info->
fill_pattern->
exception);
00256
else
00257
if (draw_info->
tile != (
Image *) NULL)
00258 clone_info->fill_pattern=
CloneImage(draw_info->
tile,0,0,
MagickTrue,
00259 &draw_info->
tile->
exception);
00260 clone_info->tile=(
Image *) NULL;
00261
if (draw_info->
stroke_pattern != (
Image *) NULL)
00262 clone_info->stroke_pattern=
CloneImage(draw_info->
stroke_pattern,0,0,
00263
MagickTrue,&draw_info->
stroke_pattern->
exception);
00264 clone_info->stroke_antialias=draw_info->
stroke_antialias;
00265 clone_info->text_antialias=draw_info->
text_antialias;
00266 clone_info->fill_rule=draw_info->
fill_rule;
00267 clone_info->linecap=draw_info->
linecap;
00268 clone_info->linejoin=draw_info->
linejoin;
00269 clone_info->miterlimit=draw_info->
miterlimit;
00270 clone_info->dash_offset=draw_info->
dash_offset;
00271 clone_info->decorate=draw_info->
decorate;
00272 clone_info->compose=draw_info->
compose;
00273
if (draw_info->
text != (
char *) NULL)
00274 (
void)
CloneString(&clone_info->text,draw_info->
text);
00275
if (draw_info->
font != (
char *) NULL)
00276 (
void)
CloneString(&clone_info->font,draw_info->
font);
00277
if (draw_info->
metrics != (
char *) NULL)
00278 (
void)
CloneString(&clone_info->metrics,draw_info->
metrics);
00279
if (draw_info->
family != (
char *) NULL)
00280 (
void)
CloneString(&clone_info->family,draw_info->
family);
00281 clone_info->style=draw_info->
style;
00282 clone_info->stretch=draw_info->
stretch;
00283 clone_info->weight=draw_info->
weight;
00284
if (draw_info->
encoding != (
char *) NULL)
00285 (
void)
CloneString(&clone_info->encoding,draw_info->
encoding);
00286 clone_info->pointsize=draw_info->
pointsize;
00287
if (draw_info->
density != (
char *) NULL)
00288 (
void)
CloneString(&clone_info->density,draw_info->
density);
00289 clone_info->align=draw_info->
align;
00290 clone_info->undercolor=draw_info->
undercolor;
00291 clone_info->border_color=draw_info->
border_color;
00292
if (draw_info->
server_name != (
char *) NULL)
00293 (
void)
CloneString(&clone_info->server_name,draw_info->
server_name);
00294
if (draw_info->
dash_pattern != (
double *) NULL)
00295 {
00296
register long
00297 x;
00298
00299
for (x=0; draw_info->
dash_pattern[x] != 0.0; x++);
00300 clone_info->dash_pattern=(
double *)
00301
AcquireMagickMemory((size_t) (x+1)*
sizeof(*clone_info->dash_pattern));
00302
if (clone_info->dash_pattern == (
double *) NULL)
00303
ThrowMagickFatalException(
ResourceLimitFatalError,
00304
"UnableToAllocateDashPattern",image_info->
filename);
00305 (
void)
CopyMagickMemory(clone_info->dash_pattern,draw_info->
dash_pattern,
00306 (size_t) (x+1)*
sizeof(*clone_info->dash_pattern));
00307 }
00308
if (draw_info->
clip_path != (
char *) NULL)
00309 (
void)
CloneString(&clone_info->clip_path,draw_info->
clip_path);
00310 clone_info->bounds=draw_info->
bounds;
00311 clone_info->clip_units=draw_info->
clip_units;
00312 clone_info->render=draw_info->
render;
00313 clone_info->opacity=draw_info->
opacity;
00314 clone_info->element_reference=draw_info->
element_reference;
00315 clone_info->debug=
IsEventLogging();
00316
return(clone_info);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
#if defined(__cplusplus) || defined(c_plusplus)
00351
extern "C" {
00352
#endif
00353
00354 static int CompareEdges(
const void *x,
const void *y)
00355 {
00356
register const EdgeInfo
00357 *p,
00358 *q;
00359
00360
00361
00362
00363 p=(
EdgeInfo *) x;
00364 q=(
EdgeInfo *) y;
00365
if ((p->
points[0].
y-
MagickEpsilon) > q->
points[0].
y)
00366
return(1);
00367
if ((p->
points[0].
y+
MagickEpsilon) < q->
points[0].
y)
00368
return(-1);
00369
if ((p->
points[0].
x-
MagickEpsilon) > q->
points[0].
x)
00370
return(1);
00371
if ((p->
points[0].
x+
MagickEpsilon) < q->
points[0].
x)
00372
return(-1);
00373
if (((p->
points[1].
x-p->
points[0].
x)*(q->
points[1].
y-q->
points[0].
y)-
00374 (p->
points[1].
y-p->
points[0].
y)*(q->
points[1].
x-q->
points[0].
x)) > 0.0)
00375
return(1);
00376
return(-1);
00377 }
00378
00379
#if defined(__cplusplus) || defined(c_plusplus)
00380
}
00381
#endif
00382
00383 static void LogPolygonInfo(
const PolygonInfo *polygon_info)
00384 {
00385
register EdgeInfo
00386 *p;
00387
00388
register long
00389 i,
00390 j;
00391
00392 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" begin active-edge");
00393 p=polygon_info->
edges;
00394
for (i=0; i < (
long) polygon_info->
number_edges; i++)
00395 {
00396 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" edge %lu:",i);
00397 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" direction: %s",
00398 p->
direction !=
MagickFalse ?
"down" :
"up");
00399 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" ghostline: %s",
00400 p->
ghostline !=
MagickFalse ?
"transparent" :
"opaque");
00401 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
00402
" bounds: %g,%g - %g,%g",p->
bounds.
x1,p->
bounds.
y1,p->
bounds.
x2,
00403 p->
bounds.
y2);
00404
for (j=0; j < (
long) p->
number_points; j++)
00405 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" %g,%g",
00406 p->
points[j].
x,p->
points[j].
y);
00407 p++;
00408 }
00409 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" end active-edge");
00410 }
00411
00412 static void ReversePoints(
PointInfo *points,
const unsigned long number_points)
00413 {
00414
PointInfo
00415 point;
00416
00417
register long
00418 i;
00419
00420
for (i=0; i < (long) (number_points >> 1); i++)
00421 {
00422 point=points[i];
00423 points[i]=points[number_points-(i+1)];
00424 points[number_points-(i+1)]=point;
00425 }
00426 }
00427
00428 static PolygonInfo *
ConvertPathToPolygon(
const DrawInfo *draw_info,
00429
const PathInfo *path_info)
00430 {
00431
long
00432 direction,
00433 next_direction;
00434
00435
PointInfo
00436 point,
00437 *points;
00438
00439
PolygonInfo
00440 *polygon_info;
00441
00442
SegmentInfo
00443 bounds;
00444
00445
register long
00446 i,
00447 n;
00448
00449
MagickBooleanType
00450 ghostline;
00451
00452
unsigned long
00453 edge,
00454 number_edges,
00455 number_points;
00456
00457
00458
00459
00460 polygon_info=(
PolygonInfo *)
AcquireMagickMemory(
sizeof(*polygon_info));
00461
if (polygon_info == (
PolygonInfo *) NULL)
00462
return((
PolygonInfo *) NULL);
00463 number_edges=16;
00464 polygon_info->edges=(
EdgeInfo *)
00465
AcquireMagickMemory((size_t) number_edges*
sizeof(*polygon_info->edges));
00466
if (polygon_info->edges == (
EdgeInfo *) NULL)
00467
return((
PolygonInfo *) NULL);
00468 direction=0;
00469 edge=0;
00470 ghostline=
MagickFalse;
00471 n=0;
00472 number_points=0;
00473 points=(
PointInfo *) NULL;
00474 (
void)
ResetMagickMemory(&point,0,
sizeof(point));
00475 (
void)
ResetMagickMemory(&bounds,0,
sizeof(bounds));
00476
for (i=0; path_info[i].
code !=
EndCode; i++)
00477 {
00478
if ((path_info[i].
code ==
MoveToCode) || (path_info[i].
code ==
OpenCode) ||
00479 (path_info[i].
code ==
GhostlineCode))
00480 {
00481
00482
00483
00484
if ((points != (
PointInfo *) NULL) && (n >= 2))
00485 {
00486
if (edge == number_edges)
00487 {
00488 number_edges<<=1;
00489 polygon_info->edges=(
EdgeInfo *)
ResizeMagickMemory(
00490 polygon_info->edges,(size_t) number_edges*
00491
sizeof(*polygon_info->edges));
00492
if (polygon_info->edges == (
EdgeInfo *) NULL)
00493
return((
PolygonInfo *) NULL);
00494 }
00495 polygon_info->edges[edge].number_points=(
unsigned long) n;
00496 polygon_info->edges[edge].scanline=(-1.0);
00497 polygon_info->edges[edge].highwater=0;
00498 polygon_info->edges[edge].ghostline=ghostline;
00499 polygon_info->edges[edge].direction=(
long) (direction > 0);
00500
if (direction < 0)
00501
ReversePoints(points,(
unsigned long) n);
00502 polygon_info->edges[edge].points=points;
00503 polygon_info->edges[edge].bounds=bounds;
00504 polygon_info->edges[edge].bounds.y1=points[0].
y;
00505 polygon_info->edges[edge].bounds.y2=points[n-1].
y;
00506 points=(
PointInfo *) NULL;
00507 ghostline=
MagickFalse;
00508 edge++;
00509 }
00510
if (points == (
PointInfo *) NULL)
00511 {
00512 number_points=16;
00513 points=(
PointInfo *)
00514
AcquireMagickMemory((size_t) number_points*
sizeof(*points));
00515
if (points == (
PointInfo *) NULL)
00516
return((
PolygonInfo *) NULL);
00517 }
00518 ghostline=(
MagickBooleanType) (path_info[i].
code ==
GhostlineCode);
00519 point=path_info[i].
point;
00520 points[0]=point;
00521 bounds.x1=point.
x;
00522 bounds.x2=point.x;
00523 direction=0;
00524 n=1;
00525
continue;
00526 }
00527
00528
00529
00530 next_direction=((path_info[i].
point.
y > point.y) ||
00531 ((path_info[i].point.y == point.y) &&
00532 (path_info[i].point.x > point.x))) ? 1 : -1;
00533
if ((direction != 0) && (direction != next_direction))
00534 {
00535
00536
00537
00538 point=points[n-1];
00539
if (edge == number_edges)
00540 {
00541 number_edges<<=1;
00542 polygon_info->edges=(
EdgeInfo *)
ResizeMagickMemory(
00543 polygon_info->edges,(size_t) number_edges*
00544
sizeof(*polygon_info->edges));
00545
if (polygon_info->edges == (
EdgeInfo *) NULL)
00546
return((
PolygonInfo *) NULL);
00547 }
00548 polygon_info->edges[edge].number_points=(
unsigned long) n;
00549 polygon_info->edges[edge].scanline=(-1.0);
00550 polygon_info->edges[edge].highwater=0;
00551 polygon_info->edges[edge].ghostline=ghostline;
00552 polygon_info->edges[edge].direction=(
long) (direction > 0);
00553
if (direction < 0)
00554
ReversePoints(points,(
unsigned long) n);
00555 polygon_info->edges[edge].points=points;
00556 polygon_info->edges[edge].bounds=bounds;
00557 polygon_info->edges[edge].bounds.y1=points[0].y;
00558 polygon_info->edges[edge].bounds.y2=points[n-1].y;
00559 number_points=16;
00560 points=(
PointInfo *)
00561
AcquireMagickMemory((size_t) number_points*
sizeof(*points));
00562
if (points == (
PointInfo *) NULL)
00563
return((
PolygonInfo *) NULL);
00564 n=1;
00565 ghostline=
MagickFalse;
00566 points[0]=point;
00567 bounds.x1=point.x;
00568 bounds.x2=point.x;
00569 edge++;
00570 }
00571 direction=next_direction;
00572
if (points == (
PointInfo *) NULL)
00573
continue;
00574
if (n == (
long) number_points)
00575 {
00576 number_points<<=1;
00577 points=(
PointInfo *)
00578
ResizeMagickMemory(points,(size_t) number_points*
sizeof(*points));
00579
if (points == (
PointInfo *) NULL)
00580
return((
PolygonInfo *) NULL);
00581 }
00582 point=path_info[i].point;
00583 points[n]=point;
00584
if (point.x < bounds.x1)
00585 bounds.x1=point.
x;
00586
if (point.x > bounds.x2)
00587 bounds.x2=point.x;
00588 n++;
00589 }
00590
if (points != (
PointInfo *) NULL)
00591 {
00592
if (n < 2)
00593 points=(
PointInfo *)
RelinquishMagickMemory(points);
00594
else
00595 {
00596
if (edge == number_edges)
00597 {
00598 number_edges<<=1;
00599 polygon_info->edges=(
EdgeInfo *)
ResizeMagickMemory(
00600 polygon_info->edges,(size_t) number_edges*
00601
sizeof(*polygon_info->edges));
00602
if (polygon_info->edges == (
EdgeInfo *) NULL)
00603
return((
PolygonInfo *) NULL);
00604 }
00605 polygon_info->edges[edge].number_points=(
unsigned long) n;
00606 polygon_info->edges[edge].scanline=(-1.0);
00607 polygon_info->edges[edge].highwater=0;
00608 polygon_info->edges[edge].ghostline=ghostline;
00609 polygon_info->edges[edge].direction=(
long) (direction > 0);
00610
if (direction < 0)
00611
ReversePoints(points,(
unsigned long) n);
00612 polygon_info->edges[edge].points=points;
00613 polygon_info->edges[edge].bounds=bounds;
00614 polygon_info->edges[edge].bounds.y1=points[0].
y;
00615 polygon_info->edges[edge].bounds.y2=points[n-1].
y;
00616 ghostline=
MagickFalse;
00617 edge++;
00618 }
00619 }
00620 polygon_info->number_edges=edge;
00621 qsort(polygon_info->edges,(size_t) polygon_info->number_edges,
00622
sizeof(*polygon_info->edges),
CompareEdges);
00623
if (
IsEventLogging() !=
MagickFalse)
00624
LogPolygonInfo(polygon_info);
00625
return(polygon_info);
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 static void LogPathInfo(
const PathInfo *path_info)
00660 {
00661
register const PathInfo
00662 *p;
00663
00664 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" begin vector-path");
00665
for (p=path_info; p->
code !=
EndCode; p++)
00666 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
00667
" %g,%g %s",p->
point.
x,p->
point.
y,p->
code ==
GhostlineCode ?
00668
"moveto ghostline" : p->
code ==
OpenCode ?
"moveto open" :
00669 p->
code ==
MoveToCode ?
"moveto" : p->
code ==
LineToCode ?
"lineto" :
00670
"?");
00671 (
void)
LogMagickEvent(
DrawEvent,
GetMagickModule(),
" end vector-path");
00672 }
00673
00674 static PathInfo *
ConvertPrimitiveToPath(
const DrawInfo *draw_info,
00675
const PrimitiveInfo *primitive_info)
00676 {
00677
long
00678 coordinates,
00679 start;
00680
00681
PathInfo
00682 *path_info;
00683
00684
PathInfoCode
00685 code;
00686
00687
PointInfo
00688 p,
00689 q;
00690
00691
register long
00692 i,
00693 n;
00694
00695
00696
00697
00698
switch (primitive_info->
primitive)
00699 {
00700
case PointPrimitive:
00701
case ColorPrimitive:
00702
case MattePrimitive:
00703
case TextPrimitive:
00704
case ImagePrimitive:
00705
return((
PathInfo *) NULL);
00706
default:
00707
break;
00708 }
00709
for (i=0; primitive_info[i].
primitive !=
UndefinedPrimitive; i++);
00710 path_info=(
PathInfo *)
00711
AcquireMagickMemory((size_t) (2*i+3)*
sizeof(*path_info));
00712
if (path_info == (
PathInfo *) NULL)
00713
return((
PathInfo *) NULL);
00714 coordinates=0;
00715 n=0;
00716 q.
x=(-1);
00717 q.
y=(-1);
00718 start=0;
00719
for (i=0; primitive_info[i].
primitive !=
UndefinedPrimitive; i++)
00720 {
00721 code=
LineToCode;
00722
if (coordinates <= 0)
00723 {
00724 coordinates=(
long) primitive_info[i].
coordinates;
00725 p=primitive_info[i].
point;
00726 start=n;
00727 code=
MoveToCode;
00728 }
00729 coordinates--;
00730
00731
00732
00733
if ((i == 0) || (fabs(q.
x-primitive_info[i].
point.
x) >
MagickEpsilon) ||
00734 (fabs(q.
y-primitive_info[i].
point.
y) >
MagickEpsilon))
00735 {
00736 path_info[n].code=code;
00737 path_info[n].point=primitive_info[i].
point;
00738 q=primitive_info[i].
point;
00739 n++;
00740 }
00741
if (coordinates > 0)
00742
continue;
00743
if ((fabs(p.
x-primitive_info[i].
point.
x) <=
MagickEpsilon) &&
00744 (fabs(p.
y-primitive_info[i].
point.
y) <=
MagickEpsilon))
00745
continue;
00746
00747
00748
00749 path_info[start].code=
OpenCode;
00750 path_info[n].code=
GhostlineCode;
00751 path_info[n].point=primitive_info[i].
point;
00752 n++;
00753 path_info[n].code=
LineToCode;
00754 path_info[n].point=p;
00755 n++;
00756 }
00757 path_info[n].code=
EndCode;
00758 path_info[n].point.x=0.0;
00759 path_info[n].point.y=0.0;
00760
if (
IsEventLogging() !=
MagickFalse)
00761
LogPathInfo(path_info);
00762
return(path_info);
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 MagickExport DrawInfo *
DestroyDrawInfo(
DrawInfo *draw_info)
00790 {
00791
if (draw_info->
debug !=
MagickFalse)
00792 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),
"...");
00793
assert(draw_info != (
DrawInfo *) NULL);
00794
assert(draw_info->
signature ==
MagickSignature);
00795
if (draw_info->
primitive != (
char *) NULL)
00796 draw_info->
primitive=(
char *)
RelinquishMagickMemory(draw_info->
primitive);
00797
if (draw_info->
text != (
char *) NULL)
00798 draw_info->
text=(
char *)
RelinquishMagickMemory(draw_info->
text);
00799
if (draw_info->
geometry != (
char *) NULL)
00800 draw_info->
geometry=(
char *)
RelinquishMagickMemory(draw_info->
geometry);
00801
if (draw_info->
tile != (
Image *) NULL)
00802 draw_info->
tile=
DestroyImage(draw_info->
tile);
00803
if (draw_info->
fill_pattern != (
Image *) NULL)
00804 draw_info->
fill_pattern=
DestroyImage(draw_info->
fill_pattern);
00805
if (draw_info->
stroke_pattern != (
Image *) NULL)
00806 draw_info->
stroke_pattern=
DestroyImage(draw_info->
stroke_pattern);
00807
if (draw_info->
font != (
char *) NULL)
00808 draw_info->
font=(
char *)
RelinquishMagickMemory(draw_info->
font);
00809
if (draw_info->
metrics != (
char *) NULL)
00810 draw_info->
metrics=(
char *)
RelinquishMagickMemory(draw_info->
metrics);
00811
if (draw_info->
family != (
char *) NULL)
00812 draw_info->
family=(
char *)
RelinquishMagickMemory(draw_info->
family);
00813
if (draw_info->
encoding != (
char *) NULL)
00814 draw_info->
encoding=(
char *)
RelinquishMagickMemory(draw_info->
encoding);
00815
if (draw_info->
density != (
char *) NULL)
00816 draw_info->
density=(
char *)
RelinquishMagickMemory(draw_info->
density);
00817
if (draw_info->
server_name != (
char *) NULL)
00818 draw_info->
server_name=(
char *)
00819
RelinquishMagickMemory(draw_info->
server_name);
00820
if (draw_info->
dash_pattern != (
double *) NULL)
00821 draw_info->
dash_pattern=(
double *)
00822
RelinquishMagickMemory(draw_info->
dash_pattern);
00823
if (draw_info->
clip_path != (
char *) NULL)
00824 draw_info->
clip_path=(
char *)
RelinquishMagickMemory(draw_info->
clip_path);
00825 draw_info=(
DrawInfo *)
RelinquishMagickMemory(draw_info);
00826
return(draw_info);
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 static unsigned long DestroyEdge(
PolygonInfo *polygon_info,
00855
const unsigned long edge)
00856 {
00857
assert(edge < polygon_info->number_edges);
00858 polygon_info->
edges[edge].
points=(
PointInfo *)
00859
RelinquishMagickMemory(polygon_info->
edges[edge].
points);
00860 polygon_info->
number_edges--;
00861
if (edge < polygon_info->
number_edges)
00862 (
void)
CopyMagickMemory(polygon_info->
edges+edge,polygon_info->
edges+edge+1,
00863 (size_t) (polygon_info->
number_edges-edge)*
sizeof(*polygon_info->
edges));
00864
return(polygon_info->
number_edges);
00865 }
00866
00867
#if defined(MagickFuture)
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
static void DestroyGradientInfo(
GradientInfo *gradient_info)
00893 {
00894
register GradientInfo
00895 *p;
00896
00897
if (gradient_info->
debug !=
MagickFalse)
00898 (
void)
LogMagickEvent(TraceEvent,
GetMagickModule(),
"...");
00899
if (gradient_info == (
GradientInfo *) NULL)
00900
return;
00901
assert(gradient_info->
signature == MagickSignature);
00902
for (p=gradient_info; p->
previous != (
GradientInfo *) NULL; p=p->
previous);
00903
for (gradient_info=p; p != (
GradientInfo *) NULL; gradient_info=p)
00904 {
00905 p=p->next;
00906 gradient_info=(
GradientInfo *)
RelinquishMagickMemory(gradient_info);
00907 }
00908 }
00909
#endif
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 static void DestroyPolygonInfo(
PolygonInfo *polygon_info)
00935 {
00936
register long
00937 i;
00938
00939
for (i=0; i < (
long) polygon_info->
number_edges; i++)
00940 polygon_info->
edges[i].
points=(
PointInfo *)
00941
RelinquishMagickMemory(polygon_info->
edges[i].
points);
00942 polygon_info->
edges=(
EdgeInfo *)
RelinquishMagickMemory(polygon_info->
edges);
00943 polygon_info=(
PolygonInfo *)
RelinquishMagickMemory(polygon_info);
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 static SegmentInfo AffineEdge(
const Image *image,
const AffineMatrix *affine,
00976
const long y,
const SegmentInfo *edge)
00977 {
00978
MagickRealType
00979 intercept,
00980 z;
00981
00982
register long
00983 x;
00984
00985
SegmentInfo
00986 inverse_edge;
00987
00988
00989
00990
00991 inverse_edge.
x1=edge->
x1;
00992 inverse_edge.
x2=edge->
x2;
00993 z=affine->
ry*(y+0.5)+affine->
tx;
00994
if (affine->
sx >
MagickEpsilon)
00995 {
00996 intercept=(-z/affine->
sx);
00997 x=(
long) (intercept+
MagickEpsilon+0.5);
00998
if ((
MagickRealType) x > inverse_edge.
x1)
00999 inverse_edge.
x1=(
MagickRealType) x;
01000 intercept=(-z+(
MagickRealType) image->
columns)/affine->
sx;
01001 x=(
long) (intercept-
MagickEpsilon+0.5);
01002
if ((
MagickRealType) x < inverse_edge.
x2)
01003 inverse_edge.
x2=(
MagickRealType) x;
01004 }
01005
else
01006
if (affine->
sx < -
MagickEpsilon)
01007 {
01008 intercept=(-z+(
MagickRealType) image->
columns)/affine->
sx;
01009 x=(
long) (intercept+
MagickEpsilon+0.5);
01010
if ((
MagickRealType) x > inverse_edge.
x1)
01011 inverse_edge.
x1=(
MagickRealType) x;
01012 intercept=(-z/affine->
sx);
01013 x=(
long) (intercept-
MagickEpsilon+0.5);
01014
if ((
MagickRealType) x < inverse_edge.
x2)
01015 inverse_edge.
x2=(
MagickRealType) x;
01016 }
01017
else
01018
if ((z < 0.0) || (z >= (
MagickRealType) image->
columns))
01019 {
01020 inverse_edge.
x2=edge->
x1;
01021
return(inverse_edge);
01022 }
01023
01024
01025
01026 z=affine->
sy*(y+0.5)+affine->
ty;
01027
if (affine->
rx >
MagickEpsilon)
01028 {
01029 intercept=(-z /affine->
rx);
01030 x=(
long) (intercept+
MagickEpsilon+0.5);
01031
if ((
MagickRealType) x > inverse_edge.
x1)
01032 inverse_edge.
x1=(
MagickRealType) x;
01033 intercept=(-z+(
MagickRealType) image->
rows)/affine->
rx;
01034 x=(
long) (intercept-
MagickEpsilon+0.5);
01035
if ((
MagickRealType) x < inverse_edge.
x2)
01036 inverse_edge.
x2=(
MagickRealType) x;
01037 }
01038
else
01039
if (affine->
rx < -
MagickEpsilon)
01040 {
01041 intercept=(-z+(
MagickRealType) image->
rows)/affine->
rx;
01042 x=(
long) (intercept+
MagickEpsilon+0.5);
01043
if ((
MagickRealType) x > inverse_edge.
x1)
01044 inverse_edge.
x1=(
MagickRealType) x;
01045 intercept=(-z/affine->
rx);
01046 x=(
long) (intercept-
MagickEpsilon+0.5);
01047
if ((
MagickRealType) x < inverse_edge.
x2)
01048 inverse_edge.
x2=(
MagickRealType) x;
01049 }
01050
else
01051
if ((z < 0.0) || (z >= (
MagickRealType) image->
rows))
01052 {
01053 inverse_edge.
x2=edge->
x1;
01054
return(inverse_edge);
01055 }
01056
return(inverse_edge);
01057 }
01058
01059 static AffineMatrix InverseAffineMatrix(
const AffineMatrix *affine)
01060 {
01061
AffineMatrix
01062 inverse_affine;
01063
01064
MagickRealType
01065 determinant;
01066
01067 determinant=1.0/(affine->
sx*affine->
sy-affine->
rx*affine->
ry);
01068 inverse_affine.
sx=determinant*affine->
sy;
01069 inverse_affine.
rx=determinant*(-affine->
rx);
01070 inverse_affine.
ry=determinant*(-affine->
ry);
01071 inverse_affine.
sy=determinant*affine->
sx;
01072 inverse_affine.
tx=
01073 (-affine->
tx)*inverse_affine.
sx-affine->
ty*inverse_affine.
ry;
01074 inverse_affine.
ty=
01075 (-affine->
tx)*inverse_affine.
rx-affine->
ty*inverse_affine.
sy;
01076
return(inverse_affine);
01077 }
01078
01079 MagickExport MagickBooleanType DrawAffineImage(
Image *image,
01080
const Image *composite,
const AffineMatrix *affine)
01081 {
01082
AffineMatrix
01083 inverse_affine;
01084
01085
long
01086 start,
01087 stop,
01088 y;
01089
01090
PixelPacket
01091 pixel;
01092
01093
PointInfo
01094 extent[4],
01095 min,
01096 max,
01097 point;
01098
01099
register long
01100 i,
01101 x;
01102
01103
register PixelPacket
01104 *q;
01105
01106
SegmentInfo
01107 edge,
01108 inverse_edge;
01109
01110
01111
01112
01113
assert(image != (
Image *) NULL);
01114
assert(image->
signature ==
MagickSignature);
01115
if (image->
debug !=
MagickFalse)
01116 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image->
filename);
01117
assert(composite != (
const Image *) NULL);
01118
assert(composite->
signature ==
MagickSignature);
01119
assert(affine != (
AffineMatrix *) NULL);
01120 extent[0].
x=0;
01121 extent[0].
y=0;
01122 extent[1].
x=(
MagickRealType) composite->
columns;
01123 extent[1].
y=0;
01124 extent[2].
x=(
MagickRealType) composite->
columns;
01125 extent[2].
y=(
MagickRealType) composite->
rows;
01126 extent[3].
x=0;
01127 extent[3].
y=(
MagickRealType) composite->
rows;
01128
for (i=0; i < 4; i++)
01129 {
01130 x=(
long) extent[i].
x;
01131 y=(
long) extent[i].
y;
01132 extent[i].
x=(
MagickRealType) (x*affine->
sx+y*affine->
ry+affine->
tx);
01133 extent[i].
y=(
MagickRealType) (x*affine->
rx+y*affine->
sy+affine->
ty);
01134 }
01135 min=extent[0];
01136 max=extent[0];
01137
for (i=1; i < 4; i++)
01138 {
01139
if (min.
x > extent[i].x)
01140 min.
x=extent[i].x;
01141
if (min.
y > extent[i].y)
01142 min.
y=extent[i].y;
01143
if (max.
x < extent[i].x)
01144 max.
x=extent[i].x;
01145
if (max.
y < extent[i].y)
01146 max.
y=extent[i].y;
01147 }
01148
01149
01150
01151 image->
storage_class=
DirectClass;
01152 edge.
x1=min.
x;
01153 edge.
y1=min.
y;
01154 edge.
x2=max.
x;
01155 edge.
y2=max.
y;
01156 inverse_affine=
InverseAffineMatrix(affine);
01157
if (edge.
y1 < 0)
01158 edge.
y1=0.0;
01159
if (edge.
y2 >= (
MagickRealType) image->
rows)
01160 edge.
y2=(
MagickRealType) image->
rows-1;
01161
for (y=(
long) (edge.
y1+0.5); y <= (
long) (edge.
y2+0.5); y++)
01162 {
01163 inverse_edge=
AffineEdge(composite,&inverse_affine,y,&edge);
01164
if (inverse_edge.
x2 < inverse_edge.
x1)
01165
continue;
01166
if (inverse_edge.
x1 < 0)
01167 inverse_edge.
x1=0.0;
01168
if (inverse_edge.
x2 >= (
MagickRealType) image->
columns)
01169 inverse_edge.
x2=(
MagickRealType) image->
columns-1;
01170 start=(
long) (inverse_edge.
x1+0.5);
01171 stop=(
long) (inverse_edge.
x2+0.5);
01172 x=start;
01173 q=
GetImagePixels(image,x,y,(
unsigned long) (stop-x+1),1);
01174
if (q == (
PixelPacket *) NULL)
01175
break;
01176
for ( ; x <= stop; x++)
01177 {
01178 point.
x=(
MagickRealType) (x*inverse_affine.
sx+y*inverse_affine.
ry+
01179 inverse_affine.
tx);
01180 point.
y=(
MagickRealType) (x*inverse_affine.
rx+y*inverse_affine.
sy+
01181 inverse_affine.
ty);
01182 pixel=
AcquireOnePixel(composite,(
long) point.
x,(
long) point.
y,
01183 &image->
exception);
01184
MagickCompositeOver(&pixel,(
MagickRealType) pixel.
opacity,q,
01185 (
MagickRealType) q->
opacity,q);
01186 q++;
01187 }
01188
if (
SyncImagePixels(image) ==
MagickFalse)
01189
break;
01190 }
01191
return(
MagickTrue);
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 static void DrawBoundingRectangles(
Image *image,
const DrawInfo *draw_info,
01224
const PolygonInfo *polygon_info)
01225 {
01226
DrawInfo
01227 *clone_info;
01228
01229
long
01230 coordinates;
01231
01232
MagickRealType
01233 mid;
01234
01235
PointInfo
01236 end,
01237 resolution,
01238 start;
01239
01240
PrimitiveInfo
01241 primitive_info[6];
01242
01243
register long
01244 i;
01245
01246
SegmentInfo
01247 bounds;
01248
01249 clone_info=
CloneDrawInfo((
ImageInfo *) NULL,draw_info);
01250 (
void)
QueryColorDatabase(
"#000000ff",&clone_info->
fill,&image->
exception);
01251 resolution.
x=72.0;
01252 resolution.
y=