% MagickCore Image Annotation Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 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 "MagickCore/annotate-private.h"
#include "MagickCore/attribute.h"
#include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
#include "MagickCore/client.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
*/
MagickPrivate MagickBooleanType AnnotateComponentGenesis(void)
{
- AcquireSemaphoreInfo(&annotate_semaphore);
+ if (annotate_semaphore == (SemaphoreInfo *) NULL)
+ annotate_semaphore=AcquireSemaphoreInfo();
return(MagickTrue);
}
\f
MagickPrivate void AnnotateComponentTerminus(void)
{
if (annotate_semaphore == (SemaphoreInfo *) NULL)
- AcquireSemaphoreInfo(&annotate_semaphore);
- DestroySemaphoreInfo(&annotate_semaphore);
+ ActivateSemaphoreInfo(&annotate_semaphore);
+ RelinquishSemaphoreInfo(&annotate_semaphore);
}
\f
/*
% any of the following bits of information about the image by embedding
% the appropriate special characters:
%
-% %b file size in bytes.
-% %c comment.
-% %d directory in which the image resides.
-% %e extension of the image file.
-% %f original filename of the image.
-% %h height of image.
-% %i filename of the image.
-% %k number of unique colors.
-% %l image label.
-% %m image file format.
-% %n number of images in a image sequence.
-% %o output image filename.
-% %p page number of the image.
-% %q image depth (8 or 16).
-% %q image depth (8 or 16).
-% %s image scene number.
-% %t image filename without any extension.
-% %u a unique temporary filename.
-% %w image width.
-% %x x resolution of the image.
-% %y y resolution of the image.
+% \n newline
+% \r carriage return
+% < less-than character.
+% > greater-than character.
+% & ampersand character.
+% %% a percent sign
+% %b file size of image read in
+% %c comment meta-data property
+% %d directory component of path
+% %e filename extension or suffix
+% %f filename (including suffix)
+% %g layer canvas page geometry (equivalent to "%Wx%H%X%Y")
+% %h current image height in pixels
+% %i image filename (note: becomes output filename for "info:")
+% %k CALCULATED: number of unique colors
+% %l label meta-data property
+% %m image file format (file magic)
+% %n number of images in current image sequence
+% %o output filename (used for delegates)
+% %p index of image in current image list
+% %q quantum depth (compile-time constant)
+% %r image class and colorspace
+% %s scene number (from input unless re-assigned)
+% %t filename without directory or extension (suffix)
+% %u unique temporary filename (used for delegates)
+% %w current width in pixels
+% %x x resolution (density)
+% %y y resolution (density)
+% %z image depth (as read in unless modified, image save depth)
+% %A image transparency channel enabled (true/false)
+% %C image compression type
+% %D image GIF dispose method
+% %G original image size (%wx%h; before any resizes)
+% %H page (canvas) height
+% %M Magick filename (original file exactly as given, including read mods)
+% %O page (canvas) offset ( = %X%Y )
+% %P page (canvas) size ( = %Wx%H )
+% %Q image compression quality ( 0 = default )
+% %S ?? scenes ??
+% %T image time delay (in centi-seconds)
+% %U image resolution units
+% %W page (canvas) width
+% %X page (canvas) x offset (including sign)
+% %Y page (canvas) y offset (including sign)
+% %Z unique filename (used for delegates)
+% %@ CALCULATED: trim bounding box (without actually trimming)
+% %# CALCULATED: 'signature' hash of image values
%
% The format of the AnnotateImage method is:
%
if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
if (IsGrayColorspace(image->colorspace) != MagickFalse)
- (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ (void) SetImageColorspace(image,sRGBColorspace,exception);
status=MagickTrue;
for (i=0; textlist[i] != (char *) NULL; i++)
{
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) FormatLocaleString(primitive,MaxTextExtent,
- "rectangle 0,0 %g,%.20g",metrics.origin.x,(double) height);
+ "rectangle -0.5,-0.5 %g,%.20g",metrics.origin.x,(double) height);
(void) CloneString(&undercolor_info->primitive,primitive);
(void) DrawImage(image,undercolor_info,exception);
(void) DestroyDrawInfo(undercolor_info);
status=GetTypeMetrics(image,draw_info,metrics,exception);
if (status == MagickFalse)
break;
- width=(size_t) floor(metrics->width+metrics->max_advance/2.0+0.5);
+ width=(size_t) floor(metrics->width+draw_info->stroke_width+0.5);
if ((width <= image->columns) || (strcmp(text,draw_info->text) == 0))
continue;
(void) strcpy(text,draw_info->text);
encoding_type;
FT_Error
- status;
+ ft_status;
FT_Face
face;
glyph,
last_glyph;
+ MagickBooleanType
+ status;
+
PointInfo
point,
resolution;
/*
Initialize Truetype library.
*/
- status=FT_Init_FreeType(&library);
- if (status != 0)
+ ft_status=FT_Init_FreeType(&library);
+ if (ft_status != 0)
ThrowBinaryException(TypeError,"UnableToInitializeFreetypeLibrary",
image->filename);
args.flags=FT_OPEN_PATHNAME;
else
args.pathname=ConstantString(draw_info->font+1);
face=(FT_Face) NULL;
- status=FT_Open_Face(library,&args,(long) draw_info->face,&face);
+ ft_status=FT_Open_Face(library,&args,(long) draw_info->face,&face);
args.pathname=DestroyString(args.pathname);
- if (status != 0)
+ if (ft_status != 0)
{
(void) FT_Done_FreeType(library);
(void) ThrowMagickException(exception,GetMagickModule(),TypeError,
(IsPathAccessible(draw_info->metrics) != MagickFalse))
(void) FT_Attach_File(face,draw_info->metrics);
encoding_type=ft_encoding_unicode;
- status=FT_Select_Charmap(face,encoding_type);
- if ((status != 0) && (face->num_charmaps != 0))
- status=FT_Set_Charmap(face,face->charmaps[0]);
+ ft_status=FT_Select_Charmap(face,encoding_type);
+ if ((ft_status != 0) && (face->num_charmaps != 0))
+ ft_status=FT_Set_Charmap(face,face->charmaps[0]);
if (encoding != (const char *) NULL)
{
if (LocaleCompare(encoding,"AdobeCustom") == 0)
encoding_type=ft_encoding_unicode;
if (LocaleCompare(encoding,"Wansung") == 0)
encoding_type=ft_encoding_wansung;
- status=FT_Select_Charmap(face,encoding_type);
- if (status != 0)
- ThrowBinaryException(TypeError,"UnrecognizedFontEncoding",encoding);
+ ft_status=FT_Select_Charmap(face,encoding_type);
+ if (ft_status != 0)
+ {
+ (void) FT_Done_Face(face);
+ (void) FT_Done_FreeType(library);
+ ThrowBinaryException(TypeError,"UnrecognizedFontEncoding",encoding);
+ }
}
/*
Set text size.
if ((flags & SigmaValue) == 0)
resolution.y=resolution.x;
}
- status=FT_Set_Char_Size(face,(FT_F26Dot6) (64.0*draw_info->pointsize),
+ ft_status=FT_Set_Char_Size(face,(FT_F26Dot6) (64.0*draw_info->pointsize),
(FT_F26Dot6) (64.0*draw_info->pointsize),(FT_UInt) resolution.x,
(FT_UInt) resolution.y);
metrics->pixels_per_em.x=face->size->metrics.x_ppem;
{
if (image->storage_class != DirectClass)
(void) SetImageStorageClass(image,DirectClass,exception);
- if (image->alpha_trait != BlendPixelTrait)
+ if (image->alpha_trait == UndefinedPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
}
direction=1.0;
if (utf8 != (unsigned char *) NULL)
p=(char *) utf8;
}
+ status=MagickTrue;
for (code=0; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
{
/*
glyph.id=FT_Get_Char_Index(face,'?');
if ((glyph.id != 0) && (last_glyph.id != 0))
{
- if (fabs(draw_info->kerning) >= MagickEpsilon)
- origin.x+=(FT_Pos) (64.0*direction*draw_info->kerning);
- else
- if (FT_HAS_KERNING(face))
- {
- FT_Vector
- kerning;
+ if (FT_HAS_KERNING(face))
+ {
+ FT_Vector
+ kerning;
- status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
- ft_kerning_default,&kerning);
- if (status == 0)
- origin.x+=(FT_Pos) (direction*kerning.x);
- }
- }
+ ft_status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
+ ft_kerning_default,&kerning);
+ if (ft_status == 0)
+ origin.x+=(FT_Pos) (direction*kerning.x);
+ }
+ origin.x+=(FT_Pos) (64.0*direction*draw_info->kerning);
+ }
glyph.origin=origin;
- status=FT_Load_Glyph(face,glyph.id,flags);
- if (status != 0)
+ ft_status=FT_Load_Glyph(face,glyph.id,flags);
+ if (ft_status != 0)
continue;
- status=FT_Get_Glyph(face->glyph,&glyph.image);
- if (status != 0)
+ ft_status=FT_Get_Glyph(face->glyph,&glyph.image);
+ if (ft_status != 0)
continue;
- status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->outline,
+ ft_status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->outline,
&bounds);
- if (status != 0)
+ if (ft_status != 0)
continue;
if ((p == draw_info->text) || (bounds.xMin < metrics->bounds.x1))
metrics->bounds.x1=(double) bounds.xMin;
metrics->bounds.x2=(double) bounds.xMax;
if ((p == draw_info->text) || (bounds.yMax > metrics->bounds.y2))
metrics->bounds.y2=(double) bounds.yMax;
- if (draw_info->render != MagickFalse)
- if ((draw_info->stroke.alpha != TransparentAlpha) ||
- (draw_info->stroke_pattern != (Image *) NULL))
- {
- /*
- Trace the glyph.
- */
- 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);
+ if ((draw_info->stroke.alpha != TransparentAlpha) ||
+ (draw_info->stroke_pattern != (Image *) NULL))
+ {
+ if ((status != MagickFalse) && (draw_info->render != MagickFalse))
+ {
+ /*
+ Trace the glyph.
+ */
+ 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);
+ }
}
FT_Vector_Transform(&glyph.origin,&affine);
(void) FT_Glyph_Transform(glyph.image,&affine,&glyph.origin);
- status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
+ ft_status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
(FT_Vector *) NULL,MagickTrue);
- if (status != 0)
+ if (ft_status != 0)
continue;
bitmap=(FT_BitmapGlyph) glyph.image;
point.x=offset->x+bitmap->left;
CacheView
*image_view;
- MagickBooleanType
- status;
-
register unsigned char
*p;
/*
Rasterize the glyph.
*/
- status=MagickTrue;
image_view=AcquireAuthenticCacheView(image,exception);
p=bitmap->bitmap.buffer;
for (y=0; y < (ssize_t) bitmap->bitmap.rows; y++)
q=GetCacheViewAuthenticPixels(image_view,x_offset,y_offset,1,1,
exception);
if (q == (Quantum *) NULL)
- {
- q+=GetPixelChannels(image);
- continue;
- }
+ continue;
GetPixelInfo(image,&fill_color);
(void) GetFillColor(draw_info,x_offset,y_offset,&fill_color,
exception);
if ((draw_info->stroke.alpha != TransparentAlpha) ||
(draw_info->stroke_pattern != (Image *) NULL))
{
- if (draw_info->render != MagickFalse)
+ if ((status != MagickFalse) && (draw_info->render != MagickFalse))
{
/*
Draw text stroke.
*/
glyph.id=FT_Get_Char_Index(face,'_');
glyph.origin=origin;
- status=FT_Load_Glyph(face,glyph.id,flags);
- if (status == 0)
+ ft_status=FT_Load_Glyph(face,glyph.id,flags);
+ if (ft_status == 0)
{
- status=FT_Get_Glyph(face->glyph,&glyph.image);
- if (status == 0)
+ ft_status=FT_Get_Glyph(face->glyph,&glyph.image);
+ if (ft_status == 0)
{
- status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->outline,
- &bounds);
- if (status == 0)
+ ft_status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->
+ outline,&bounds);
+ if (ft_status == 0)
{
FT_Vector_Transform(&glyph.origin,&affine);
(void) FT_Glyph_Transform(glyph.image,&affine,&glyph.origin);
- status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
+ ft_status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
(FT_Vector *) NULL,MagickTrue);
bitmap=(FT_BitmapGlyph) glyph.image;
if (bitmap->left > metrics->width)
annotate_info=DestroyDrawInfo(annotate_info);
(void) FT_Done_Face(face);
(void) FT_Done_FreeType(library);
- return(MagickTrue);
+ return(status);
}
#else
static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
/*
Render fill color.
*/
- if (image->alpha_trait != BlendPixelTrait)
+ if (image->alpha_trait == UndefinedPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
- if (annotate_image->alpha_trait != BlendPixelTrait)
+ if (annotate_image->alpha_trait == UndefinedPixelTrait)
(void) SetImageAlphaChannel(annotate_image,OpaqueAlphaChannel,
exception);
fill_color=draw_info->fill;
status;
if (annotate_semaphore == (SemaphoreInfo *) NULL)
- AcquireSemaphoreInfo(&annotate_semaphore);
+ ActivateSemaphoreInfo(&annotate_semaphore);
LockSemaphoreInfo(annotate_semaphore);
status=XRenderImage(image,draw_info,offset,metrics,exception);
UnlockSemaphoreInfo(annotate_semaphore);