% July 1992 %
% %
% %
-% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
*/
#include "magick/studio.h"
#include "magick/annotate.h"
+#include "magick/attribute.h"
#include "magick/cache-view.h"
#include "magick/client.h"
#include "magick/color.h"
primitive[MaxTextExtent],
**textlist;
- double
- height;
-
DrawInfo
*annotate,
*annotate_info;
RectangleInfo
geometry;
- register long
+ register ssize_t
i;
size_t
TypeMetric
metrics;
- unsigned long
+ size_t
+ height,
number_lines;
assert(image != (Image *) NULL);
for (i=1; textlist[i] != (char *) NULL; i++)
if (strlen(textlist[i]) > length)
length=strlen(textlist[i]);
- number_lines=(unsigned long) i;
+ number_lines=(size_t) i;
annotate=CloneDrawInfo((ImageInfo *) NULL,draw_info);
annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
SetGeometry(image,&geometry);
annotate_info->affine.ty=geometry_info.psi-image->page.y;
(void) CloneString(&annotate->text,textlist[i]);
(void) GetTypeMetrics(image,annotate,&metrics);
- height=metrics.height;
- if (draw_info->interline_spacing != 0.0)
- height+=draw_info->interline_spacing;
+ height=(ssize_t) (metrics.ascent-metrics.descent+
+ draw_info->interline_spacing+0.5);
switch (annotate->gravity)
{
case UndefinedGravity:
undercolor_info->affine.tx=offset.x-draw_info->affine.ry*metrics.ascent;
undercolor_info->affine.ty=offset.y-draw_info->affine.sy*metrics.ascent;
(void) FormatMagickString(primitive,MaxTextExtent,
- "rectangle 0,0 %g,%g",metrics.origin.x,height);
+ "rectangle 0,0 %g,%.20g",metrics.origin.x,(double) height);
(void) CloneString(&undercolor_info->primitive,primitive);
(void) DrawImage(image,undercolor_info);
(void) DestroyDrawInfo(undercolor_info);
%
% The format of the FormatMagickCaption method is:
%
-% long FormatMagickCaption(Image *image,DrawInfo *draw_info,
-% TypeMetric *metrics,char **caption)
+% ssize_t FormatMagickCaption(Image *image,DrawInfo *draw_info,
+% const MagickBooleanType split,TypeMetric *metrics,char **caption)
%
% A description of each parameter follows.
%
% o image: The image.
%
-% o caption: the caption.
-%
% o draw_info: the draw info.
%
+% o split: when no convenient line breaks-- insert newline.
+%
% o metrics: Return the font metrics in this structure.
%
+% o caption: the caption.
+%
*/
-MagickExport long FormatMagickCaption(Image *image,DrawInfo *draw_info,
- TypeMetric *metrics,char **caption)
+MagickExport ssize_t FormatMagickCaption(Image *image,DrawInfo *draw_info,
+ const MagickBooleanType split,TypeMetric *metrics,char **caption)
{
MagickBooleanType
status;
*q,
*s;
- register long
+ register ssize_t
i;
- unsigned long
+ size_t
width;
q=draw_info->text;
{
if (IsUTFSpace(GetUTFCode(p)) != MagickFalse)
s=p;
- for (i=0; i < (long) GetUTFOctets(p); i++)
+ for (i=0; i < (ssize_t) GetUTFOctets(p); i++)
*q++=(*(p+i));
*q='\0';
status=GetTypeMetrics(image,draw_info,metrics);
if (status == MagickFalse)
break;
- width=(unsigned long) (metrics->width+0.5);
+ width=(size_t) floor(metrics->width+0.5);
if (GetUTFCode(p) != '\n')
if (width <= image->columns)
continue;
p=s;
}
else
- {
- char
- *target;
+ if (split != MagickFalse)
+ {
+ char
+ *target;
- long
- n;
+ ssize_t
+ n;
- /*
- No convenient line breaks-- insert newline.
- */
- target=AcquireString(*caption);
- n=p-(*caption);
- CopyMagickString(target,*caption,n+1);
- ConcatenateMagickString(target,"\n",strlen(*caption)+1);
- ConcatenateMagickString(target,p,strlen(*caption)+2);
- (void) DestroyString(*caption);
- *caption=target;
- p=(*caption)+n;
- }
+ /*
+ No convenient line breaks-- insert newline.
+ */
+ target=AcquireString(*caption);
+ n=p-(*caption);
+ CopyMagickString(target,*caption,n+1);
+ ConcatenateMagickString(target,"\n",strlen(*caption)+1);
+ ConcatenateMagickString(target,p,strlen(*caption)+2);
+ (void) DestroyString(*caption);
+ *caption=target;
+ p=(*caption)+n;
+ }
s=(char *) NULL;
q=draw_info->text;
}
MagickBooleanType
status;
- register long
+ register ssize_t
i;
TypeMetric
extent;
- unsigned long
- number_lines;
-
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
if (extent.width > metrics->width)
*metrics=extent;
}
- number_lines=(unsigned long) i;
- metrics->height=(double) number_lines*(long) (metrics->ascent-
- metrics->descent+0.5);
+ metrics->height=(double) (i*(size_t) (metrics->ascent-
+ metrics->descent+0.5)+(i-1)*draw_info->interline_spacing);
/*
Relinquish resources.
*/
TypeWarning,"UnableToReadFont","`%s'",draw_info->family);
}
if (type_info == (const TypeInfo *) NULL)
- type_info=GetTypeInfoByFamily("arial",draw_info->style,
+ type_info=GetTypeInfoByFamily("Arial",draw_info->style,
+ draw_info->stretch,draw_info->weight,&image->exception);
+ if (type_info == (const TypeInfo *) NULL)
+ type_info=GetTypeInfoByFamily("Helvetica",draw_info->style,
draw_info->stretch,draw_info->weight,&image->exception);
if (type_info == (const TypeInfo *) NULL)
- type_info=GetTypeInfoByFamily("helvetica",draw_info->style,
+ type_info=GetTypeInfoByFamily("Century Schoolbook",draw_info->style,
draw_info->stretch,draw_info->weight,&image->exception);
if (type_info == (const TypeInfo *) NULL)
type_info=GetTypeInfoByFamily((const char *) NULL,draw_info->style,
draw_info->stretch,draw_info->weight,&image->exception);
+ if (type_info == (const TypeInfo *) NULL)
+ type_info=GetTypeInfo("*",&image->exception);
if (type_info == (const TypeInfo *) NULL)
{
status=RenderFreetype(image,draw_info,draw_info->encoding,offset,metrics);
*/
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
+
static int TraceCubicBezier(FT_Vector *p,FT_Vector *q,FT_Vector *to,
DrawInfo *draw_info)
{
path[MaxTextExtent];
affine=draw_info->affine;
- (void) FormatMagickString(path,MaxTextExtent,"C%g,%g %g,%g %g,%g",
- affine.tx+p->x/64.0,affine.ty-p->y/64.0,affine.tx+q->x/64.0,
- affine.ty-q->y/64.0,affine.tx+to->x/64.0,affine.ty-to->y/64.0);
+ (void) FormatMagickString(path,MaxTextExtent,
+ "C%g,%g %g,%g %g,%g",affine.tx+p->x/64.0,affine.ty-
+ p->y/64.0,affine.tx+q->x/64.0,affine.ty-q->y/64.0,affine.tx+to->x/64.0,
+ affine.ty-to->y/64.0);
(void) ConcatenateString(&draw_info->primitive,path);
return(0);
}
path[MaxTextExtent];
affine=draw_info->affine;
- (void) FormatMagickString(path,MaxTextExtent,"L%g,%g",affine.tx+to->x/64.0,
- affine.ty-to->y/64.0);
+ (void) FormatMagickString(path,MaxTextExtent,"L%g,%g",affine.tx+
+ to->x/64.0,affine.ty-to->y/64.0);
(void) ConcatenateString(&draw_info->primitive,path);
return(0);
}
path[MaxTextExtent];
affine=draw_info->affine;
- (void) FormatMagickString(path,MaxTextExtent,"M%g,%g",affine.tx+to->x/64.0,
- affine.ty-to->y/64.0);
+ (void) FormatMagickString(path,MaxTextExtent,"M%g,%g",affine.tx+
+ to->x/64.0,affine.ty-to->y/64.0);
(void) ConcatenateString(&draw_info->primitive,path);
return(0);
}
const char
*value;
+ double
+ direction;
+
DrawInfo
*annotate_info;
glyph,
last_glyph;
- long
+ ssize_t
code,
y;
0, 0
};
+ unsigned char
+ *utf8;
+
/*
Initialize Truetype library.
*/
else
args.pathname=ConstantString(draw_info->font+1);
face=(FT_Face) NULL;
- status=FT_Open_Face(library,&args,draw_info->face,&face);
+ status=FT_Open_Face(library,&args,(long) draw_info->face,&face);
args.pathname=DestroyString(args.pathname);
if (status != 0)
{
draw_info->pointsize);
flags=FT_LOAD_NO_BITMAP;
value=GetImageProperty(image,"type:hinting");
- if (LocaleCompare(value,"off") == 0)
+ if ((value != (const char *) NULL) && (LocaleCompare(value,"off") == 0))
flags|=FT_LOAD_NO_HINTING;
glyph.id=0;
glyph.image=NULL;
if (image->matte == MagickFalse)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
}
+ direction=1.0;
+ if (draw_info->direction == RightToLeftDirection)
+ direction=(-1.0);
point.x=0.0;
point.y=0.0;
- code=0;
for (p=draw_info->text; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
+ if (GetUTFCode(p) < 0)
+ break;
+ utf8=(unsigned char *) NULL;
+ if (GetUTFCode(p) == 0)
+ p=draw_info->text;
+ else
+ {
+ utf8=ConvertLatin1ToUTF8((unsigned char *) draw_info->text);
+ if (utf8 != (unsigned char *) NULL)
+ p=(char *) utf8;
+ }
+ for (code=0; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
{
+ /*
+ Render UTF-8 sequence.
+ */
glyph.id=FT_Get_Char_Index(face,GetUTFCode(p));
if (glyph.id == 0)
glyph.id=FT_Get_Char_Index(face,'?');
if ((glyph.id != 0) && (last_glyph.id != 0))
{
if (draw_info->kerning != 0.0)
- origin.x+=64.0*draw_info->kerning;
+ origin.x+=64.0*direction*draw_info->kerning;
else
if (FT_HAS_KERNING(face))
{
status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
ft_kerning_default,&kerning);
if (status == 0)
- origin.x+=kerning.x;
+ origin.x+=direction*kerning.x;
}
}
glyph.origin=origin;
*/
annotate_info->affine.tx=glyph.origin.x/64.0;
annotate_info->affine.ty=glyph.origin.y/64.0;
- (void) FT_Outline_Decompose(&((FT_OutlineGlyph) glyph.image)->outline,
- &OutlineMethods,annotate_info);
+ (void) FT_Outline_Decompose(&((FT_OutlineGlyph) glyph.image)->
+ outline,&OutlineMethods,annotate_info);
}
FT_Vector_Transform(&glyph.origin,&affine);
(void) FT_Glyph_Transform(glyph.image,&affine,&glyph.origin);
status=MagickTrue;
exception=(&image->exception);
image_view=AcquireCacheView(image);
- for (y=0; y < (long) bitmap->bitmap.rows; y++)
+ for (y=0; y < (ssize_t) bitmap->bitmap.rows; y++)
{
- long
- x_offset,
- y_offset;
-
MagickBooleanType
active,
sync;
PixelPacket
fill_color;
- register long
+ register ssize_t
x;
register PixelPacket
- *__restrict q;
+ *restrict q;
register unsigned char
*p;
+ ssize_t
+ x_offset,
+ y_offset;
+
if (status == MagickFalse)
continue;
- x_offset=(long) (point.x+0.5);
- y_offset=(long) (point.y+y+0.5);
- if ((y_offset < 0) || (y_offset >= (long) image->rows))
+ x_offset=(ssize_t) ceil(point.x-0.5);
+ y_offset=(ssize_t) ceil(point.y+y-0.5);
+ if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
continue;
q=(PixelPacket *) NULL;
- if ((x_offset < 0) || (x_offset >= (long) image->columns))
+ if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
active=MagickFalse;
else
{
active=q != (PixelPacket *) NULL ? MagickTrue : MagickFalse;
}
p=bitmap->bitmap.buffer+y*bitmap->bitmap.width;
- for (x=0; x < (long) bitmap->bitmap.width; x++)
+ for (x=0; x < (ssize_t) bitmap->bitmap.width; x++)
{
x_offset++;
if ((*p == 0) || (x_offset < 0) ||
- (x_offset >= (long) image->columns))
+ (x_offset >= (ssize_t) image->columns))
{
p++;
q++;
if ((draw_info->interword_spacing != 0.0) &&
(IsUTFSpace(GetUTFCode(p)) != MagickFalse) &&
(IsUTFSpace(code) == MagickFalse))
- origin.x+=64.0*draw_info->interword_spacing;
+ origin.x+=64.0*direction*draw_info->interword_spacing;
else
- origin.x+=face->glyph->advance.x;
+ origin.x+=direction*face->glyph->advance.x;
metrics->origin.x=origin.x;
metrics->origin.y=origin.y;
if (last_glyph.id != 0)
last_glyph=glyph;
code=GetUTFCode(p);
}
+ if (utf8 != (unsigned char *) NULL)
+ utf8=(unsigned char *) RelinquishMagickMemory(utf8);
if (last_glyph.id != 0)
FT_Done_Glyph(last_glyph.image);
if ((draw_info->stroke.opacity != TransparentOpacity) ||
register char
*p;
- register long
+ register ssize_t
i;
size_t
escapes=0;
buffer=AcquireString(text);
p=buffer;
- for (i=0; i < (long) MagickMin(strlen(text),MaxTextExtent-escapes-1); i++)
+ for (i=0; i < (ssize_t) MagickMin(strlen(text),MaxTextExtent-escapes-1); i++)
{
if ((text[i] == '(') || (text[i] == ')'))
{
int
unique_file;
- long
+ ssize_t
y;
MagickBooleanType
point,
resolution;
- register long
+ register ssize_t
i;
/*
MagickTrue : MagickFalse;
extent.x=0.0;
extent.y=0.0;
- for (i=0; i <= (long) (strlen(draw_info->text)+2); i++)
+ for (i=0; i <= (ssize_t) (strlen(draw_info->text)+2); i++)
{
point.x=fabs(draw_info->affine.sx*i*draw_info->pointsize+
draw_info->affine.ry*2.0*draw_info->pointsize);
else
(void) fprintf(file,"/%s-ISO dup /%s ReencodeType findfont setfont\n",
draw_info->font,draw_info->font);
- (void) fprintf(file,"[%g %g %g %g 0 0] concat\n",draw_info->affine.sx,
- -draw_info->affine.rx,-draw_info->affine.ry,draw_info->affine.sy);
+ (void) fprintf(file,"[%g %g %g %g 0 0] concat\n",
+ draw_info->affine.sx,-draw_info->affine.rx,-draw_info->affine.ry,
+ draw_info->affine.sy);
text=EscapeParenthesis(draw_info->text);
if (identity == MagickFalse)
(void) fprintf(file,"(%s) stringwidth pop -0.5 mul -0.5 rmoveto\n",text);
text=DestroyString(text);
(void) fprintf(file,"showpage\n");
(void) fclose(file);
- (void) FormatMagickString(geometry,MaxTextExtent,"%ldx%ld+0+0!",(long)
- (extent.x+0.5),(long) (extent.y+0.5));
+ (void) FormatMagickString(geometry,MaxTextExtent,"%.20gx%.20g+0+0!",
+ floor(extent.x+0.5),floor(extent.y+0.5));
annotate_info=AcquireImageInfo();
(void) FormatMagickString(annotate_info->filename,MaxTextExtent,"ps:%s",
filename);
crop_info;
crop_info=GetImageBoundingBox(annotate_image,&annotate_image->exception);
- crop_info.height=(unsigned long) ((resolution.y/DefaultResolution)*
+ crop_info.height=(size_t) ((resolution.y/DefaultResolution)*
ExpandAffine(&draw_info->affine)*draw_info->pointsize+0.5);
- crop_info.y=(long) ((resolution.y/DefaultResolution)*extent.y/8.0+0.5);
- (void) FormatMagickString(geometry,MaxTextExtent,"%lux%lu%+ld%+ld",
- crop_info.width,crop_info.height,crop_info.x,crop_info.y);
+ crop_info.y=(ssize_t) ceil((resolution.y/DefaultResolution)*extent.y/8.0-
+ 0.5);
+ (void) FormatMagickString(geometry,MaxTextExtent,
+ "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
+ crop_info.height,(double) crop_info.x,(double) crop_info.y);
(void) TransformImage(&annotate_image,geometry,(char *) NULL);
}
metrics->pixels_per_em.x=(resolution.y/DefaultResolution)*
fill_color=draw_info->fill;
exception=(&image->exception);
annotate_view=AcquireCacheView(annotate_image);
- for (y=0; y < (long) annotate_image->rows; y++)
+ for (y=0; y < (ssize_t) annotate_image->rows; y++)
{
- register long
+ register ssize_t
x;
register PixelPacket
- *__restrict q;
+ *restrict q;
q=GetCacheViewAuthenticPixels(annotate_view,0,y,annotate_image->columns,
1,exception);
if (q == (PixelPacket *) NULL)
break;
- for (x=0; x < (long) annotate_image->columns; x++)
+ for (x=0; x < (ssize_t) annotate_image->columns; x++)
{
(void) GetFillColor(draw_info,x,y,&fill_color);
- q->opacity=RoundToQuantum(QuantumRange-(((QuantumRange-
+ q->opacity=ClampToQuantum(QuantumRange-(((QuantumRange-
(MagickRealType) PixelIntensityToQuantum(q))*(QuantumRange-
fill_color.opacity))/QuantumRange));
q->red=fill_color.red;
}
annotate_view=DestroyCacheView(annotate_view);
(void) CompositeImage(image,OverCompositeOp,annotate_image,
- (long) (offset->x+0.5),(long) (offset->y-(metrics->ascent+
- metrics->descent)+0.5));
+ (ssize_t) ceil(offset->x-0.5),(ssize_t) ceil(offset->y-(metrics->ascent+
+ metrics->descent)-0.5));
}
annotate_image=DestroyImage(annotate_image);
return(MagickTrue);
static XVisualInfo
*visual_info;
- unsigned long
+ size_t
height,
width;
if (display == (Display *) NULL)
{
+ const char
+ *client_name;
+
ImageInfo
*image_info;
*/
(void) XSetErrorHandler(XError);
image_info=AcquireImageInfo();
- resource_database=XGetResourceDatabase(display,GetClientName());
- XGetResourceInfo(image_info,resource_database,GetClientName(),
- &resource_info);
+ client_name=GetClientName();
+ resource_database=XGetResourceDatabase(display,client_name);
+ XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
resource_info.close_server=MagickFalse;
resource_info.colormap=PrivateColormap;
resource_info.font=AcquireString(draw_info->font);
atan2(draw_info->affine.rx,draw_info->affine.sx);
}
(void) FormatMagickString(annotate_info.geometry,MaxTextExtent,
- "%lux%lu+%ld+%ld",width,height,(long) (offset->x+0.5),
- (long) (offset->y-metrics->ascent-metrics->descent+0.5));
+ "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
+ ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
+ draw_info->interline_spacing-0.5));
pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);