% MagickCore Image Annotation Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 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"
#include "MagickCore/constitute.h"
#include "MagickCore/draw.h"
#include "MagickCore/draw-private.h"
+#include "MagickCore/enhance.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/gem.h"
#include "MagickCore/xwindow.h"
#include "MagickCore/xwindow-private.h"
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(__MINGW64__)
# undef interface
#endif
-#if defined(MAGICKCORE_HAVE_FT2BUILD_H)
-# include <ft2build.h>
-#endif
+#include <ft2build.h>
#if defined(FT_FREETYPE_H)
# include FT_FREETYPE_H
#else
*/
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
/*
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++)
{
(number_lines-1.0)*height)/2.0;
break;
}
- case StaticGravity:
case CenterGravity:
{
offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+
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+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;
draw_info->pointsize);
flags=FT_LOAD_NO_BITMAP;
if (draw_info->text_antialias == MagickFalse)
- flags|=FT_LOAD_TARGET_MONO;
+ flags|=FT_LOAD_TARGET_MONO;
else
{
#if defined(FT_LOAD_TARGET_LIGHT)
{
if (image->storage_class != DirectClass)
(void) SetImageStorageClass(image,DirectClass,exception);
- if (image->matte == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait)
(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))
{
/*
FT_Vector
kerning;
- status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
+ ft_status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
ft_kerning_default,&kerning);
- if (status == 0)
+ if (ft_status == 0)
origin.x+=(FT_Pos) (direction*kerning.x);
}
}
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++)
active,
sync;
- MagickRealType
+ double
fill_opacity;
PixelInfo
continue;
}
if (bitmap->bitmap.pixel_mode != ft_pixel_mode_mono)
- fill_opacity=(MagickRealType) (p[n])/(bitmap->bitmap.num_grays-1);
+ fill_opacity=(double) (p[n])/(bitmap->bitmap.num_grays-1);
else
fill_opacity=((p[(x >> 3)+y*bitmap->bitmap.pitch] &
(1 << (~x & 0x07)))) == 0 ? 0.0 : 1.0;
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)
FT_Done_Glyph(glyph.image);
}
metrics->width-=metrics->bounds.x1/64.0;
+ metrics->width+=annotate_info->stroke_width;
metrics->bounds.x1/=64.0;
metrics->bounds.y1/=64.0;
metrics->bounds.x2/=64.0;
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,
TypeMetric *metrics,ExceptionInfo *exception)
{
(void) ThrowMagickException(exception,GetMagickModule(),
- MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (Freetype)",
+ MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","'%s' (Freetype)",
draw_info->font != (char *) NULL ? draw_info->font : "none");
return(RenderPostscript(image,draw_info,offset,metrics,exception));
}
register ssize_t
i;
+ size_t
+ length;
+
ssize_t
y;
(fabs(draw_info->affine.ry) < MagickEpsilon) ? MagickTrue : MagickFalse;
extent.x=0.0;
extent.y=0.0;
- for (i=0; i <= (ssize_t) (strlen(draw_info->text)+2); i++)
+ length=strlen(draw_info->text);
+ for (i=0; i <= (ssize_t) (length+2); i++)
{
point.x=fabs(draw_info->affine.sx*i*draw_info->pointsize+
draw_info->affine.ry*2.0*draw_info->pointsize);
(void) RelinquishUniqueFileResource(filename);
if (annotate_image == (Image *) NULL)
return(MagickFalse);
+ (void) NegateImage(annotate_image,MagickFalse,exception);
resolution.x=DefaultResolution;
resolution.y=DefaultResolution;
if (draw_info->density != (char *) NULL)
/*
Render fill color.
*/
- if (image->matte == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
- if (annotate_image->matte == MagickFalse)
+ if (annotate_image->alpha_trait != BlendPixelTrait)
(void) SetImageAlphaChannel(annotate_image,OpaqueAlphaChannel,
exception);
fill_color=draw_info->fill;
for (x=0; x < (ssize_t) annotate_image->columns; x++)
{
(void) GetFillColor(draw_info,x,y,&fill_color,exception);
- SetPixelAlpha(annotate_image,ClampToQuantum((((MagickRealType)
- GetPixelIntensity(annotate_image,q)*fill_color.alpha)/
- QuantumRange)),q);
+ SetPixelAlpha(annotate_image,ClampToQuantum((((double) QuantumScale*
+ GetPixelIntensity(annotate_image,q)*fill_color.alpha))),q);
SetPixelRed(annotate_image,fill_color.red,q);
SetPixelGreen(annotate_image,fill_color.green,q);
SetPixelBlue(annotate_image,fill_color.blue,q);
% o exception: return any errors or warnings in this structure.
%
*/
-#if defined(MAGICKCORE_X11_DELEGATE)
static MagickBooleanType RenderX11(Image *image,const DrawInfo *draw_info,
const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
{
MagickBooleanType
status;
- static DrawInfo
- cache_info;
-
- static Display
- *display = (Display *) NULL;
-
- static XAnnotateInfo
- annotate_info;
-
- static XFontStruct
- *font_info;
-
- static XPixelInfo
- pixel;
-
- static XResourceInfo
- resource_info;
-
- static XrmDatabase
- resource_database;
-
- static XStandardColormap
- *map_info;
-
- static XVisualInfo
- *visual_info;
-
- size_t
- height,
- width;
-
if (annotate_semaphore == (SemaphoreInfo *) NULL)
- AcquireSemaphoreInfo(&annotate_semaphore);
+ ActivateSemaphoreInfo(&annotate_semaphore);
LockSemaphoreInfo(annotate_semaphore);
- if (display == (Display *) NULL)
- {
- const char
- *client_name;
-
- ImageInfo
- *image_info;
-
- /*
- Open X server connection.
- */
- display=XOpenDisplay(draw_info->server_name);
- if (display == (Display *) NULL)
- {
- ThrowXWindowException(XServerError,"UnableToOpenXServer",
- draw_info->server_name);
- return(MagickFalse);
- }
- /*
- Get user defaults from X resource database.
- */
- (void) XSetErrorHandler(XError);
- image_info=AcquireImageInfo();
- 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);
- resource_info.background_color=AcquireString("#ffffffffffff");
- resource_info.foreground_color=AcquireString("#000000000000");
- map_info=XAllocStandardColormap();
- if (map_info == (XStandardColormap *) NULL)
- {
- ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
- return(MagickFalse);
- }
- /*
- Initialize visual info.
- */
- visual_info=XBestVisualInfo(display,map_info,&resource_info);
- if (visual_info == (XVisualInfo *) NULL)
- {
- ThrowXWindowException(XServerError,"UnableToGetVisual",
- image->filename);
- return(MagickFalse);
- }
- map_info->colormap=(Colormap) NULL;
- pixel.pixels=(unsigned long *) NULL;
- /*
- Initialize Standard Colormap info.
- */
- XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
- map_info);
- XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
- &pixel);
- pixel.annotate_context=XDefaultGC(display,visual_info->screen);
- /*
- Initialize font info.
- */
- font_info=XBestFont(display,&resource_info,MagickFalse);
- if (font_info == (XFontStruct *) NULL)
- {
- ThrowXWindowException(XServerError,"UnableToLoadFont",
- draw_info->font);
- return(MagickFalse);
- }
- if ((map_info == (XStandardColormap *) NULL) ||
- (visual_info == (XVisualInfo *) NULL) ||
- (font_info == (XFontStruct *) NULL))
- {
- XFreeResources(display,visual_info,map_info,&pixel,font_info,
- &resource_info,(XWindowInfo *) NULL);
- ThrowXWindowException(XServerError,"UnableToLoadFont",
- image->filename);
- return(MagickFalse);
- }
- cache_info=(*draw_info);
- }
+ status=XRenderImage(image,draw_info,offset,metrics,exception);
UnlockSemaphoreInfo(annotate_semaphore);
- /*
- Initialize annotate info.
- */
- XGetAnnotateInfo(&annotate_info);
- annotate_info.stencil=ForegroundStencil;
- if (cache_info.font != draw_info->font)
- {
- /*
- Type name has changed.
- */
- (void) XFreeFont(display,font_info);
- (void) CloneString(&resource_info.font,draw_info->font);
- font_info=XBestFont(display,&resource_info,MagickFalse);
- if (font_info == (XFontStruct *) NULL)
- {
- ThrowXWindowException(XServerError,"UnableToLoadFont",
- draw_info->font);
- return(MagickFalse);
- }
- }
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
- "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
- draw_info->font : "none",draw_info->pointsize);
- cache_info=(*draw_info);
- annotate_info.font_info=font_info;
- annotate_info.text=(char *) draw_info->text;
- annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,
- (int) strlen(draw_info->text));
- annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
- metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
- metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
- metrics->ascent=(double) font_info->ascent+4;
- metrics->descent=(double) (-font_info->descent);
- metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
- metrics->height=font_info->ascent+font_info->descent;
- metrics->max_advance=(double) font_info->max_bounds.width;
- metrics->bounds.x1=0.0;
- metrics->bounds.y1=metrics->descent;
- metrics->bounds.x2=metrics->ascent+metrics->descent;
- metrics->bounds.y2=metrics->ascent+metrics->descent;
- metrics->underline_position=(-2.0);
- metrics->underline_thickness=1.0;
- if (draw_info->render == MagickFalse)
- return(MagickTrue);
- if (draw_info->fill.alpha == TransparentAlpha)
- return(MagickTrue);
- /*
- Render fill color.
- */
- width=annotate_info.width;
- height=annotate_info.height;
- if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
- (fabs(draw_info->affine.ry) >= MagickEpsilon))
- {
- if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
- (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
- annotate_info.degrees=(double) (180.0/MagickPI)*
- atan2(draw_info->affine.rx,draw_info->affine.sx);
- }
- (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
- "%.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);
- status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
- if (status == 0)
- {
- ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
- return(MagickFalse);
- }
- return(MagickTrue);
-}
-#else
-static MagickBooleanType RenderX11(Image *image,const DrawInfo *draw_info,
- const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
-{
- (void) draw_info;
- (void) offset;
- (void) metrics;
- (void) ThrowMagickException(exception,GetMagickModule(),
- MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
- image->filename);
- return(MagickFalse);
+ return(status);
}
-#endif