annotate.c revision ed2315769b26818ed9d0c1291dc0457f0d8da0a4
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%           AAA   N   N  N   N   OOO   TTTTT   AAA   TTTTT  EEEEE             %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          A   A  NN  N  NN  N  O   O    T    A   A    T    E                 %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          AAAAA  N N N  N N N  O   O    T    AAAAA    T    EEE               %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          A   A  N  NN  N  NN  O   O    T    A   A    T    E                 %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%          A   A  N   N  N   N   OOO     T    A   A    T    EEEEE             %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                   MagickCore Image Annotation Methods                       %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                John Cristy                                  %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207e41fe84a841d7b9d7b36b245b65e9dcb3314943cristy%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Digital Applications (www.digapp.com) contributed the stroked text algorithm.
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% It was written by Leonard Rosenthol.
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/annotate.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/attribute.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache-view.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/client.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite-private.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw-private.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resource_.h"
684c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/semaphore.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/statistic.h"
704c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
714c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/token-private.h"
724c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/transform.h"
734c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/type.h"
744c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
754c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/xwindow-private.h"
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FREETYPE_DELEGATE)
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(__MINGW32__)
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  undef interface
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_HAVE_FT2BUILD_H)
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include <ft2build.h>
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(FT_FREETYPE_H)
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include FT_FREETYPE_H
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include <freetype/freetype.h>
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(FT_GLYPH_H)
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include FT_GLYPH_H
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include <freetype/ftglyph.h>
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(FT_OUTLINE_H)
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include FT_OUTLINE_H
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include <freetype/ftoutln.h>
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(FT_BBOX_H)
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include FT_BBOX_H
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  include <freetype/ftbbox.h>
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif /* defined(FT_BBOX_H) */
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
106d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  Annotate semaphores.
107d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy*/
108d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristystatic SemaphoreInfo
109d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  *annotate_semaphore = (SemaphoreInfo *) NULL;
110d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy
111d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy/*
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RenderType(Image *,const DrawInfo *,const PointInfo *,TypeMetric *),
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RenderPostscript(Image *,const DrawInfo *,const PointInfo *,TypeMetric *),
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RenderFreetype(Image *,const DrawInfo *,const char *,const PointInfo *,
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    TypeMetric *),
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RenderX11(Image *,const DrawInfo *,const PointInfo *,TypeMetric *);
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
126d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy+   A n n o t a t e C o m p o n e n t G e n e s i s                           %
127d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
128d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
129d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
130d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
132d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%  AnnotateComponentGenesis() instantiates the annotate component.
133d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
134d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%  The format of the AnnotateComponentGenesis method is:
135d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
136d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%      MagickBooleanType AnnotateComponentGenesis(void)
137d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
138d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy*/
139d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristyMagickExport MagickBooleanType AnnotateComponentGenesis(void)
140d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy{
141d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  AcquireSemaphoreInfo(&annotate_semaphore);
142d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  return(MagickTrue);
143d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy}
144d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy
145d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy/*
146d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
148d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
149d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
150d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy+   A n n o t a t e C o m p o n e n t T e r m i n u s                         %
151d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
152d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
153d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
154d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
156d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%  AnnotateComponentTerminus() destroys the annotate component.
157d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
158d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%  The format of the AnnotateComponentTerminus method is:
159d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
160d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%      AnnotateComponentTerminus(void)
161d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%
162d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy*/
163d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristyMagickExport void AnnotateComponentTerminus(void)
164d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy{
165d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  if (annotate_semaphore == (SemaphoreInfo *) NULL)
166d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy    AcquireSemaphoreInfo(&annotate_semaphore);
167d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  DestroySemaphoreInfo(&annotate_semaphore);
168d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy}
169d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy
170d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy/*
171d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
173d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
174d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy%                                                                             %
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   A n n o t a t e I m a g e                                                 %
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  AnnotateImage() annotates an image with text.  Optionally you can include
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  any of the following bits of information about the image by embedding
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the appropriate special characters:
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %b   file size in bytes.
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %c   comment.
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %d   directory in which the image resides.
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %e   extension of the image file.
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %f   original filename of the image.
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %h   height of image.
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %i   filename of the image.
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %k   number of unique colors.
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %l   image label.
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %m   image file format.
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %n   number of images in a image sequence.
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %o   output image filename.
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %p   page number of the image.
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %q   image depth (8 or 16).
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %q   image depth (8 or 16).
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %s   image scene number.
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %t   image filename without any extension.
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %u   a unique temporary filename.
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %w   image width.
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %x   x resolution of the image.
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    %y   y resolution of the image.
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the AnnotateImage method is:
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType AnnotateImage(Image *image,DrawInfo *draw_info)
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType AnnotateImage(Image *image,
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const DrawInfo *draw_info)
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    primitive[MaxTextExtent],
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **textlist;
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate,
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GeometryInfo
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry_info;
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PointInfo
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  RectangleInfo
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry;
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
241bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    length;
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  TypeMetric
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    metrics;
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
250bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
2515846039e7fade723e168819490eb771446e4b81fcristy    height,
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    number_lines;
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info != (DrawInfo *) NULL);
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info->signature == MagickSignature);
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->text == (char *) NULL)
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*draw_info->text == '\0')
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  textlist=StringToList(draw_info->text);
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (textlist == (char **) NULL)
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  length=strlen(textlist[0]);
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=1; textlist[i] != (char *) NULL; i++)
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (strlen(textlist[i]) > length)
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      length=strlen(textlist[i]);
271bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  number_lines=(size_t) i;
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate=CloneDrawInfo((ImageInfo *) NULL,draw_info);
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometry(image,&geometry);
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  SetGeometryInfo(&geometry_info);
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (annotate_info->geometry != (char *) NULL)
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ParsePageGeometry(image,annotate_info->geometry,&geometry,
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        &image->exception);
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ParseGeometry(annotate_info->geometry,&geometry_info);
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=MagickTrue;
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; textlist[i] != (char *) NULL; i++)
2863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Position text relative to image.
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info->affine.tx=geometry_info.xi-image->page.x;
2913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info->affine.ty=geometry_info.psi-image->page.y;
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CloneString(&annotate->text,textlist[i]);
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) GetTypeMetrics(image,annotate,&metrics);
294bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    height=(ssize_t) (metrics.ascent-metrics.descent+
2955846039e7fade723e168819490eb771446e4b81fcristy      draw_info->interline_spacing+0.5);
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    switch (annotate->gravity)
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case UndefinedGravity:
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      default:
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=annotate_info->affine.tx+i*annotate_info->affine.ry*height;
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=annotate_info->affine.ty+i*annotate_info->affine.sy*height;
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case NorthWestGravity:
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+i*
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*height+annotate_info->affine.ry*
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (metrics.ascent+metrics.descent);
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+i*
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*height+annotate_info->affine.sy*
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.ascent;
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case NorthGravity:
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width/2.0+i*annotate_info->affine.ry*height-
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)/2.0+
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(metrics.ascent+metrics.descent);
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+i*
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*height+annotate_info->affine.sy*
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.ascent-annotate_info->affine.rx*(metrics.width-
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.bounds.x1)/2.0;
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case NorthEastGravity:
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? 1.0 : -1.0)*annotate_info->affine.tx+
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width+i*annotate_info->affine.ry*height-
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)+
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(metrics.ascent+metrics.descent)-1.0;
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+i*
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*height+annotate_info->affine.sy*
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.ascent-annotate_info->affine.rx*(metrics.width-
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.bounds.x1);
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case WestGravity:
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+i*
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*height+annotate_info->affine.ry*
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (metrics.ascent+metrics.descent-(number_lines-1.0)*height)/2.0;
3443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+
3453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height/2.0+i*annotate_info->affine.sy*height+
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(metrics.ascent+metrics.descent-
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1.0)*height)/2.0;
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case StaticGravity:
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case CenterGravity:
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+
3543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width/2.0+i*annotate_info->affine.ry*height-
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)/2.0+
3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(metrics.ascent+metrics.descent-
3573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1)*height)/2.0;
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+
3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height/2.0+i*annotate_info->affine.sy*height-
3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1)/2.0+
3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(metrics.ascent+metrics.descent-
3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1.0)*height)/2.0;
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case EastGravity:
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? 1.0 : -1.0)*annotate_info->affine.tx+
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width+i*annotate_info->affine.ry*height-
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)+
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(metrics.ascent+metrics.descent-
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1.0)*height)/2.0-1.0;
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? -1.0 : 1.0)*annotate_info->affine.ty+
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height/2.0+i*annotate_info->affine.sy*height-
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1)+
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(metrics.ascent+metrics.descent-
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1.0)*height)/2.0;
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case SouthWestGravity:
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+i*
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*height-annotate_info->affine.ry*
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (number_lines-1.0)*height;
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? 1.0 : -1.0)*annotate_info->affine.ty+
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height+i*annotate_info->affine.sy*height-
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(number_lines-1.0)*height+metrics.descent;
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case SouthGravity:
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? -1.0 : 1.0)*annotate_info->affine.tx+
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width/2.0+i*annotate_info->affine.ry*height-
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)/2.0-
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(number_lines-1.0)*height/2.0;
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? 1.0 : -1.0)*annotate_info->affine.ty+
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height+i*annotate_info->affine.sy*height-
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1)/2.0-
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(number_lines-1.0)*height+metrics.descent;
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case SouthEastGravity:
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=(geometry.width == 0 ? 1.0 : -1.0)*annotate_info->affine.tx+
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.width+i*annotate_info->affine.ry*height-
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)-
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ry*(number_lines-1.0)*height-1.0;
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=(geometry.height == 0 ? 1.0 : -1.0)*annotate_info->affine.ty+
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          geometry.height+i*annotate_info->affine.sy*height-
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1)-
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sy*(number_lines-1.0)*height+metrics.descent;
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    switch (annotate->align)
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case LeftAlign:
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=annotate_info->affine.tx+i*annotate_info->affine.ry*height;
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=annotate_info->affine.ty+i*annotate_info->affine.sy*height;
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case CenterAlign:
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=annotate_info->affine.tx+i*annotate_info->affine.ry*height-
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1)/2.0;
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=annotate_info->affine.ty+i*annotate_info->affine.sy*height-
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1)/2.0;
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      case RightAlign:
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.x=annotate_info->affine.tx+i*annotate_info->affine.ry*height-
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.sx*(metrics.width+metrics.bounds.x1);
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        offset.y=annotate_info->affine.ty+i*annotate_info->affine.sy*height-
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.rx*(metrics.width+metrics.bounds.x1);
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      default:
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        break;
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4414c08aed51c5899665ade97263692328eea4af106cristy    if (draw_info->undercolor.alpha != TransparentAlpha)
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        DrawInfo
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          *undercolor_info;
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        /*
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Text box.
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        */
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        undercolor_info=CloneDrawInfo((ImageInfo *) NULL,(DrawInfo *) NULL);
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        undercolor_info->fill=draw_info->undercolor;
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        undercolor_info->affine=draw_info->affine;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        undercolor_info->affine.tx=offset.x-draw_info->affine.ry*metrics.ascent;
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        undercolor_info->affine.ty=offset.y-draw_info->affine.sy*metrics.ascent;
454b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        (void) FormatLocaleString(primitive,MaxTextExtent,
455a8549b176173db7680652304c372c64bb1a51737cristy          "rectangle 0,0 %g,%.20g",metrics.origin.x,(double) height);
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloneString(&undercolor_info->primitive,primitive);
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) DrawImage(image,undercolor_info);
4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) DestroyDrawInfo(undercolor_info);
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info->affine.tx=offset.x;
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info->affine.ty=offset.y;
462b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleString(primitive,MaxTextExtent,"stroke-width %g "
463a8549b176173db7680652304c372c64bb1a51737cristy      "line 0,0 %g,0",metrics.underline_thickness,metrics.width);
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (annotate->decorate == OverlineDecoration)
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        annotate_info->affine.ty-=(draw_info->affine.sy*(metrics.ascent+
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.descent-metrics.underline_position));
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloneString(&annotate_info->primitive,primitive);
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) DrawImage(image,annotate_info);
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (annotate->decorate == UnderlineDecoration)
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ty-=(draw_info->affine.sy*
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            metrics.underline_position);
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) CloneString(&annotate_info->primitive,primitive);
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) DrawImage(image,annotate_info);
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /*
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      Annotate image with text.
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    */
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=RenderType(image,annotate,&offset,&metrics);
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (annotate->decorate == LineThroughDecoration)
4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        annotate_info->affine.ty-=(draw_info->affine.sy*(height+
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          metrics.underline_position+metrics.descent)/2.0);
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) CloneString(&annotate_info->primitive,primitive);
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) DrawImage(image,annotate_info);
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyDrawInfo(annotate_info);
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate=DestroyDrawInfo(annotate);
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; textlist[i] != (char *) NULL; i++)
4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    textlist[i]=DestroyString(textlist[i]);
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  textlist=(char **) RelinquishMagickMemory(textlist);
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  F o r m a t M a g i c k C a p t i o n                                      %
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  FormatMagickCaption() formats a caption so that it fits within the image
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  width.  It returns the number of lines in the formatted caption.
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the FormatMagickCaption method is:
5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
520bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      ssize_t FormatMagickCaption(Image *image,DrawInfo *draw_info,
5216b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy%        const MagickBooleanType split,TypeMetric *metrics,char **caption)
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5296b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy%    o split: when no convenient line breaks-- insert newline.
5306b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy%
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: Return the font metrics in this structure.
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
5336b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy%    o caption: the caption.
5346b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy%
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
536bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyMagickExport ssize_t FormatMagickCaption(Image *image,DrawInfo *draw_info,
5376b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy  const MagickBooleanType split,TypeMetric *metrics,char **caption)
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p,
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q,
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *s;
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
547bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
550bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  q=draw_info->text;
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  s=(char *) NULL;
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=(*caption); GetUTFCode(p) != 0; p+=GetUTFOctets(p))
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (IsUTFSpace(GetUTFCode(p)) != MagickFalse)
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      s=p;
559bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (i=0; i < (ssize_t) GetUTFOctets(p); i++)
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *q++=(*(p+i));
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q='\0';
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=GetTypeMetrics(image,draw_info,metrics);
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (status == MagickFalse)
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
565bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    width=(size_t) floor(metrics->width+0.5);
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetUTFCode(p) != '\n')
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (width <= image->columns)
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        continue;
5693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (s == (char *) NULL)
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        s=p;
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while ((IsUTFSpace(GetUTFCode(s)) == MagickFalse) &&
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy               (GetUTFCode(s) != 0))
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          s+=GetUTFOctets(s);
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetUTFCode(s) != 0)
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *s='\n';
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        p=s;
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
5826b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy      if (split != MagickFalse)
5836b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy        {
5846b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          char
5856b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy            *target;
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5876b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          ssize_t
5886b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy            n;
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5906b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          /*
5916b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy            No convenient line breaks-- insert newline.
5926b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          */
5936b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          target=AcquireString(*caption);
5946b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          n=p-(*caption);
5956b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          CopyMagickString(target,*caption,n+1);
5966b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          ConcatenateMagickString(target,"\n",strlen(*caption)+1);
5976b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          ConcatenateMagickString(target,p,strlen(*caption)+2);
5986b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          (void) DestroyString(*caption);
5996b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          *caption=target;
6006b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy          p=(*caption)+n;
6016b1d05e71aed91c7f85ff155dfad281e24d16fe5cristy        }
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    s=(char *) NULL;
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=draw_info->text;
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  i=0;
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=(*caption); GetUTFCode(p) != 0; p+=GetUTFOctets(p))
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (GetUTFCode(p) == '\n')
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      i++;
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(i);
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t M u l t i l i n e T y p e M e t r i c s                             %
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetMultilineTypeMetrics() returns the following information for the
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  specified font and text:
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    character width
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    character height
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    ascender
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    descender
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    text width
6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    text height
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    maximum horizontal advance
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: x1
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: y1
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: x2
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: y2
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    origin: x
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    origin: y
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    underline position
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    underline thickness
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  This method is like GetTypeMetrics() but it returns the maximum text width
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  and height for multiple lines of text.
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetMultilineTypeMetrics method is:
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType GetMultilineTypeMetrics(Image *image,
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const DrawInfo *draw_info,TypeMetric *metrics)
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: Return the font metrics in this structure.
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType GetMultilineTypeMetrics(Image *image,
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const DrawInfo *draw_info,TypeMetric *metrics)
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    **textlist;
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
671bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  TypeMetric
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    extent;
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info != (DrawInfo *) NULL);
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info->text != (char *) NULL);
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info->signature == MagickSignature);
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*draw_info->text == '\0')
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->text=DestroyString(annotate_info->text);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Convert newlines to multiple lines of text.
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  textlist=StringToList(draw_info->text);
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (textlist == (char **) NULL)
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->render=MagickFalse;
695024843f38984cd26602f0b3b28a0768dfa056bb5cristy  annotate_info->direction=UndefinedDirection;
6963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(metrics,0,sizeof(*metrics));
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(&extent,0,sizeof(extent));
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Find the widest of the text lines.
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->text=textlist[0];
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=GetTypeMetrics(image,annotate_info,&extent);
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *metrics=extent;
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=1; textlist[i] != (char *) NULL; i++)
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info->text=textlist[i];
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=GetTypeMetrics(image,annotate_info,&extent);
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (extent.width > metrics->width)
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      *metrics=extent;
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
711bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  metrics->height=(double) (i*(size_t) (metrics->ascent-
712d2a9514ba7cb2921febc297cd1c3e3e0c0f8c768cristy    metrics->descent+0.5)+(i-1)*draw_info->interline_spacing);
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->text=(char *) NULL;
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyDrawInfo(annotate_info);
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (i=0; textlist[i] != (char *) NULL; i++)
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    textlist[i]=DestroyString(textlist[i]);
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  textlist=(char **) RelinquishMagickMemory(textlist);
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   G e t T y p e M e t r i c s                                               %
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  GetTypeMetrics() returns the following information for the specified font
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  and text:
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    character width
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    character height
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    ascender
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    descender
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    text width
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    text height
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    maximum horizontal advance
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: x1
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: y1
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: x2
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    bounds: y2
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    origin: x
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    origin: y
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    underline position
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    underline thickness
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the GetTypeMetrics method is:
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType GetTypeMetrics(Image *image,const DrawInfo *draw_info,
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        TypeMetric *metrics)
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: Return the font metrics in this structure.
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType GetTypeMetrics(Image *image,
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const DrawInfo *draw_info,TypeMetric *metrics)
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PointInfo
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset;
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image->signature == MagickSignature);
7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info != (DrawInfo *) NULL);
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info->text != (char *) NULL);
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(draw_info->signature == MagickSignature);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->render=MagickFalse;
789024843f38984cd26602f0b3b28a0768dfa056bb5cristy  annotate_info->direction=UndefinedDirection;
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ResetMagickMemory(metrics,0,sizeof(*metrics));
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset.x=0.0;
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset.y=0.0;
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=RenderType(image,annotate_info,&offset,metrics);
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),"Metrics: text: %s; "
796e7f5109f30fc7242d04a26174a9138483dda5b6acristy      "width: %g; height: %g; ascent: %g; descent: %g; max advance: %g; "
797a8549b176173db7680652304c372c64bb1a51737cristy      "bounds: %g,%g  %g,%g; origin: %g,%g; pixels per em: %g,%g; "
798e7f5109f30fc7242d04a26174a9138483dda5b6acristy      "underline position: %g; underline thickness: %g",annotate_info->text,
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      metrics->width,metrics->height,metrics->ascent,metrics->descent,
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      metrics->max_advance,metrics->bounds.x1,metrics->bounds.y1,
8014c08aed51c5899665ade97263692328eea4af106cristy      metrics->bounds.x2,metrics->bounds.y2,metrics->origin.x,metrics->origin.y,
8024c08aed51c5899665ade97263692328eea4af106cristy      metrics->pixels_per_em.x,metrics->pixels_per_em.y,
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      metrics->underline_position,metrics->underline_thickness);
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyDrawInfo(annotate_info);
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+   R e n d e r T y p e                                                       %
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RenderType() renders text on the image.  It also returns the bounding box of
8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  the text relative to the image.
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RenderType method is:
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType RenderType(Image *image,DrawInfo *draw_info,
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const PointInfo *offset,TypeMetric *metrics)
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o offset: (x,y) location of text relative to image.
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: bounding box of text.
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderType(Image *image,const DrawInfo *draw_info,
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const PointInfo *offset,TypeMetric *metrics)
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const TypeInfo
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *type_info;
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  type_info=(const TypeInfo *) NULL;
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->font != (char *) NULL)
8523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (*draw_info->font == '@')
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=RenderFreetype(image,draw_info,draw_info->encoding,offset,
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            metrics);
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(status);
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (*draw_info->font == '-')
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        return(RenderX11(image,draw_info,offset,metrics));
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (IsPathAccessible(draw_info->font) != MagickFalse)
8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=RenderFreetype(image,draw_info,draw_info->encoding,offset,
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            metrics);
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(status);
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      type_info=GetTypeInfo(draw_info->font,&image->exception);
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (type_info == (const TypeInfo *) NULL)
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          TypeWarning,"UnableToReadFont","`%s'",draw_info->font);
8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((type_info == (const TypeInfo *) NULL) &&
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (draw_info->family != (const char *) NULL))
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      type_info=GetTypeInfoByFamily(draw_info->family,draw_info->style,
8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        draw_info->stretch,draw_info->weight,&image->exception);
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (type_info == (const TypeInfo *) NULL)
8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) ThrowMagickException(&image->exception,GetMagickModule(),
8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          TypeWarning,"UnableToReadFont","`%s'",draw_info->family);
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (type_info == (const TypeInfo *) NULL)
882d984f27fbbb96073787c88f4c9409d7f836cedc5cristy    type_info=GetTypeInfoByFamily("Arial",draw_info->style,
883d984f27fbbb96073787c88f4c9409d7f836cedc5cristy      draw_info->stretch,draw_info->weight,&image->exception);
884d984f27fbbb96073787c88f4c9409d7f836cedc5cristy  if (type_info == (const TypeInfo *) NULL)
885cbb34a4def108d6db032ca9631a433afd3ea5a5dcristy    type_info=GetTypeInfoByFamily("Helvetica",draw_info->style,
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->stretch,draw_info->weight,&image->exception);
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (type_info == (const TypeInfo *) NULL)
888704acaaebbfeec018847456e79de0ce301db126ecristy    type_info=GetTypeInfoByFamily("Century Schoolbook",draw_info->style,
889704acaaebbfeec018847456e79de0ce301db126ecristy      draw_info->stretch,draw_info->weight,&image->exception);
890704acaaebbfeec018847456e79de0ce301db126ecristy  if (type_info == (const TypeInfo *) NULL)
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    type_info=GetTypeInfoByFamily((const char *) NULL,draw_info->style,
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->stretch,draw_info->weight,&image->exception);
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (type_info == (const TypeInfo *) NULL)
894704acaaebbfeec018847456e79de0ce301db126ecristy    type_info=GetTypeInfo("*",&image->exception);
895704acaaebbfeec018847456e79de0ce301db126ecristy  if (type_info == (const TypeInfo *) NULL)
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=RenderFreetype(image,draw_info,draw_info->encoding,offset,metrics);
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(status);
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->face=type_info->face;
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (type_info->metrics != (char *) NULL)
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CloneString(&annotate_info->metrics,type_info->metrics);
9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (type_info->glyphs != (char *) NULL)
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CloneString(&annotate_info->font,type_info->glyphs);
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=RenderFreetype(image,annotate_info,type_info->encoding,offset,metrics);
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyDrawInfo(annotate_info);
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(status);
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+   R e n d e r F r e e t y p e                                               %
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RenderFreetype() renders text on the image with a Truetype font.  It also
9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  returns the bounding box of the text relative to the image.
9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RenderFreetype method is:
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType RenderFreetype(Image *image,DrawInfo *draw_info,
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const char *encoding,const PointInfo *offset,TypeMetric *metrics)
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o encoding: the font encoding.
9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o offset: (x,y) location of text relative to image.
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: bounding box of text.
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FREETYPE_DELEGATE)
9452857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int TraceCubicBezier(FT_Vector *p,FT_Vector *q,FT_Vector *to,
9473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo *draw_info)
9483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  AffineMatrix
9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine;
9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    path[MaxTextExtent];
9543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine=draw_info->affine;
956b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(path,MaxTextExtent,
957a8549b176173db7680652304c372c64bb1a51737cristy    "C%g,%g %g,%g %g,%g",affine.tx+p->x/64.0,affine.ty-
9588cd5b3193212b4aebce08c4e7afbb66b09778029cristy    p->y/64.0,affine.tx+q->x/64.0,affine.ty-q->y/64.0,affine.tx+to->x/64.0,
9598cd5b3193212b4aebce08c4e7afbb66b09778029cristy    affine.ty-to->y/64.0);
9603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateString(&draw_info->primitive,path);
9613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(0);
9623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int TraceLineTo(FT_Vector *to,DrawInfo *draw_info)
9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  AffineMatrix
9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine;
9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    path[MaxTextExtent];
9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine=draw_info->affine;
973b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(path,MaxTextExtent,"L%g,%g",affine.tx+
9748cd5b3193212b4aebce08c4e7afbb66b09778029cristy    to->x/64.0,affine.ty-to->y/64.0);
9753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateString(&draw_info->primitive,path);
9763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(0);
9773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int TraceMoveTo(FT_Vector *to,DrawInfo *draw_info)
9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  AffineMatrix
9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine;
9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    path[MaxTextExtent];
9863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine=draw_info->affine;
988b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(path,MaxTextExtent,"M%g,%g",affine.tx+
9898cd5b3193212b4aebce08c4e7afbb66b09778029cristy    to->x/64.0,affine.ty-to->y/64.0);
9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateString(&draw_info->primitive,path);
9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(0);
9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic int TraceQuadraticBezier(FT_Vector *control,FT_Vector *to,
9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo *draw_info)
9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  AffineMatrix
9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine;
9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    path[MaxTextExtent];
10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine=draw_info->affine;
1004b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(path,MaxTextExtent,"Q%g,%g %g,%g",
10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine.tx+control->x/64.0,affine.ty-control->y/64.0,affine.tx+to->x/64.0,
10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine.ty-to->y/64.0);
10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ConcatenateString(&draw_info->primitive,path);
10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(0);
10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char *encoding,const PointInfo *offset,TypeMetric *metrics)
10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(FT_OPEN_PATHNAME)
10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define FT_OPEN_PATHNAME  ft_open_pathname
10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef struct _GlyphInfo
10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    FT_UInt
10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      id;
10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    FT_Vector
10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      origin;
10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    FT_Glyph
10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image;
10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } GlyphInfo;
10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char
10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *value;
10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1033c9b129570a277337cf0e887229741497e2ead5cfcristy  double
1034c9b129570a277337cf0e887229741497e2ead5cfcristy    direction;
1035c9b129570a277337cf0e887229741497e2ead5cfcristy
10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  DrawInfo
10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_BBox
10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bounds;
10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_BitmapGlyph
10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    bitmap;
10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Encoding
10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    encoding_type;
10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Error
10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Face
10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    face;
10533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Int32
10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags;
10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Library
10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    library;
10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Matrix
10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    affine;
10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Open_Args
10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    args;
10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FT_Vector
10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    origin;
10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GlyphInfo
10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    glyph,
10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    last_glyph;
10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PointInfo
10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    point,
10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resolution;
10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10809d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
10819d314ff2c17a77996c05413c2013880387e50f0ecristy    code,
10829d314ff2c17a77996c05413c2013880387e50f0ecristy    y;
10839d314ff2c17a77996c05413c2013880387e50f0ecristy
10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static FT_Outline_Funcs
10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    OutlineMethods =
10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (FT_Outline_MoveTo_Func) TraceMoveTo,
10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (FT_Outline_LineTo_Func) TraceLineTo,
10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (FT_Outline_ConicTo_Func) TraceQuadraticBezier,
10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (FT_Outline_CubicTo_Func) TraceCubicBezier,
10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      0, 0
10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    };
10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
10942857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  unsigned char
10952857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    *utf8;
10962857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize Truetype library.
10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=FT_Init_FreeType(&library);
11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status != 0)
11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ThrowBinaryException(TypeError,"UnableToInitializeFreetypeLibrary",
11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->filename);
11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  args.flags=FT_OPEN_PATHNAME;
11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->font == (char *) NULL)
11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    args.pathname=ConstantString("helvetica");
11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (*draw_info->font != '@')
11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      args.pathname=ConstantString(draw_info->font);
11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    else
11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      args.pathname=ConstantString(draw_info->font+1);
11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  face=(FT_Face) NULL;
1113eaedf06777741da32408da72c1e512975c600c48cristy  status=FT_Open_Face(library,&args,(long) draw_info->face,&face);
11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  args.pathname=DestroyString(args.pathname);
11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status != 0)
11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) FT_Done_FreeType(library);
11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ThrowMagickException(&image->exception,GetMagickModule(),
11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        TypeError,"UnableToReadFont","`%s'",draw_info->font);
11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(RenderPostscript(image,draw_info,offset,metrics));
11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((draw_info->metrics != (char *) NULL) &&
11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (IsPathAccessible(draw_info->metrics) != MagickFalse))
11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) FT_Attach_File(face,draw_info->metrics);
11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  encoding_type=ft_encoding_unicode;
11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=FT_Select_Charmap(face,encoding_type);
11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((status != 0) && (face->num_charmaps != 0))
11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status=FT_Set_Charmap(face,face->charmaps[0]);
11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (encoding != (const char *) NULL)
11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"AdobeCustom") == 0)
11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_adobe_custom;
11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"AdobeExpert") == 0)
11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_adobe_expert;
11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"AdobeStandard") == 0)
11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_adobe_standard;
11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"AppleRoman") == 0)
11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_apple_roman;
11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"BIG5") == 0)
11403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_big5;
11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"GB2312") == 0)
11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_gb2312;
11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Johab") == 0)
11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_johab;
11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(ft_encoding_latin_1)
11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Latin-1") == 0)
11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_latin_1;
11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
11493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Latin-2") == 0)
11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_latin_2;
11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"None") == 0)
11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_none;
11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"SJIScode") == 0)
11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_sjis;
11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Symbol") == 0)
11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_symbol;
11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Unicode") == 0)
11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_unicode;
11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(encoding,"Wansung") == 0)
11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        encoding_type=ft_encoding_wansung;
11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=FT_Select_Charmap(face,encoding_type);
11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (status != 0)
11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ThrowBinaryException(TypeError,"UnrecognizedFontEncoding",encoding);
11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Set text size.
11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resolution.x=DefaultResolution;
11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resolution.y=DefaultResolution;
11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->density != (char *) NULL)
11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GeometryInfo
11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        geometry_info;
11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickStatusType
11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        flags;
11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      flags=ParseGeometry(draw_info->density,&geometry_info);
11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resolution.x=geometry_info.rho;
11803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resolution.y=geometry_info.sigma;
11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((flags & SigmaValue) == 0)
11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        resolution.y=resolution.x;
11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=FT_Set_Char_Size(face,(FT_F26Dot6) (64.0*draw_info->pointsize),
11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (FT_F26Dot6) (64.0*draw_info->pointsize),(FT_UInt) resolution.x,
11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (FT_UInt) resolution.y);
11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.x=face->size->metrics.x_ppem;
11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.y=face->size->metrics.y_ppem;
11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->ascent=(double) face->size->metrics.ascender/64.0;
11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->descent=(double) face->size->metrics.descender/64.0;
11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->width=0;
11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->origin.x=0;
11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->origin.y=0;
11943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->height=(double) face->size->metrics.height/64.0;
11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->max_advance=0.0;
11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (face->size->metrics.max_advance > MagickEpsilon)
11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    metrics->max_advance=(double) face->size->metrics.max_advance/64.0;
11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x1=0.0;
11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y1=metrics->descent;
12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x2=metrics->ascent+metrics->descent;
12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y2=metrics->ascent+metrics->descent;
12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_position=face->underline_position/64.0;
12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_thickness=face->underline_thickness/64.0;
12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (*draw_info->text == '\0')
12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) FT_Done_Face(face);
12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) FT_Done_FreeType(library);
12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickTrue);
12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Compute bounding box.
12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),"Font %s; "
1215e7f5109f30fc7242d04a26174a9138483dda5b6acristy      "font-encoding %s; text-encoding %s; pointsize %g",
12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->font != (char *) NULL ? draw_info->font : "none",
12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      encoding != (char *) NULL ? encoding : "none",
12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->encoding != (char *) NULL ? draw_info->encoding : "none",
12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->pointsize);
12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  flags=FT_LOAD_NO_BITMAP;
12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  value=GetImageProperty(image,"type:hinting");
122233204240c3ef57786ee59c2692ffe8ffdce97bf9cristy  if ((value != (const char *) NULL) && (LocaleCompare(value,"off") == 0))
12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    flags|=FT_LOAD_NO_HINTING;
12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  glyph.id=0;
12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  glyph.image=NULL;
12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  last_glyph.id=0;
12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  last_glyph.image=NULL;
12283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  origin.x=0;
12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  origin.y=0;
12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine.xx=65536L;
12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine.yx=0L;
12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine.xy=0L;
12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  affine.yy=65536L;
12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->render != MagickFalse)
12353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      affine.xx=(FT_Fixed) (65536L*draw_info->affine.sx+0.5);
12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      affine.yx=(FT_Fixed) (-65536L*draw_info->affine.rx+0.5);
12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      affine.xy=(FT_Fixed) (-65536L*draw_info->affine.ry+0.5);
12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      affine.yy=(FT_Fixed) (65536L*draw_info->affine.sy+0.5);
12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloneString(&annotate_info->primitive,"path '");
12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->render != MagickFalse)
12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->storage_class != DirectClass)
12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageStorageClass(image,DirectClass);
12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->matte == MagickFalse)
12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1250c9b129570a277337cf0e887229741497e2ead5cfcristy  direction=1.0;
1251cf5467b5dddb5084ec79a5921b48ce9bb2a897cecristy  if (draw_info->direction == RightToLeftDirection)
1252c9b129570a277337cf0e887229741497e2ead5cfcristy    direction=(-1.0);
12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  point.x=0.0;
12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  point.y=0.0;
12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (p=draw_info->text; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
1256bd51246ae63047fa139606f6c6862ff989ab1fbdcristy    if (GetUTFCode(p) < 0)
1257bd51246ae63047fa139606f6c6862ff989ab1fbdcristy      break;
12582857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  utf8=(unsigned char *) NULL;
1259d913ea1f524066a6a8bf3d046755a5c0f7eb471fcristy  if (GetUTFCode(p) == 0)
12602857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    p=draw_info->text;
12612857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  else
1262bd51246ae63047fa139606f6c6862ff989ab1fbdcristy    {
12632857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      utf8=ConvertLatin1ToUTF8((unsigned char *) draw_info->text);
12642857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      if (utf8 != (unsigned char *) NULL)
1265c9b129570a277337cf0e887229741497e2ead5cfcristy        p=(char *) utf8;
12662857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    }
12672857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  for (code=0; GetUTFCode(p) != 0; p+=GetUTFOctets(p))
12682857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  {
12692857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    /*
12702857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      Render UTF-8 sequence.
12712857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    */
12722857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    glyph.id=FT_Get_Char_Index(face,GetUTFCode(p));
12732857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (glyph.id == 0)
12742857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      glyph.id=FT_Get_Char_Index(face,'?');
12752857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((glyph.id != 0) && (last_glyph.id != 0))
12762857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      {
12772857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        if (draw_info->kerning != 0.0)
1278c9b129570a277337cf0e887229741497e2ead5cfcristy          origin.x+=64.0*direction*draw_info->kerning;
12792857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        else
12802857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          if (FT_HAS_KERNING(face))
12812857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            {
12822857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              FT_Vector
12832857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                kerning;
12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
12852857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              status=FT_Get_Kerning(face,last_glyph.id,glyph.id,
12862857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                ft_kerning_default,&kerning);
12872857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              if (status == 0)
1288c9b129570a277337cf0e887229741497e2ead5cfcristy                origin.x+=direction*kerning.x;
12892857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            }
12902857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        }
12912857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    glyph.origin=origin;
12922857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    status=FT_Load_Glyph(face,glyph.id,flags);
12932857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (status != 0)
12942857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      continue;
12952857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    status=FT_Get_Glyph(face->glyph,&glyph.image);
12962857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (status != 0)
12972857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      continue;
12982857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->outline,
12992857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      &bounds);
13002857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (status != 0)
13012857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      continue;
13022857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((p == draw_info->text) || (bounds.xMin < metrics->bounds.x1))
13032857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      metrics->bounds.x1=bounds.xMin;
13042857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((p == draw_info->text) || (bounds.yMin < metrics->bounds.y1))
13052857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      metrics->bounds.y1=bounds.yMin;
13062857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((p == draw_info->text) || (bounds.xMax > metrics->bounds.x2))
13072857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      metrics->bounds.x2=bounds.xMax;
13082857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((p == draw_info->text) || (bounds.yMax > metrics->bounds.y2))
13092857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      metrics->bounds.y2=bounds.yMax;
13102857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (draw_info->render != MagickFalse)
13114c08aed51c5899665ade97263692328eea4af106cristy      if ((draw_info->stroke.alpha != TransparentAlpha) ||
13122857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          (draw_info->stroke_pattern != (Image *) NULL))
13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1314bd51246ae63047fa139606f6c6862ff989ab1fbdcristy          /*
13152857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            Trace the glyph.
1316bd51246ae63047fa139606f6c6862ff989ab1fbdcristy          */
13172857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          annotate_info->affine.tx=glyph.origin.x/64.0;
13182857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          annotate_info->affine.ty=glyph.origin.y/64.0;
13192857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          (void) FT_Outline_Decompose(&((FT_OutlineGlyph) glyph.image)->
13202857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            outline,&OutlineMethods,annotate_info);
1321bd51246ae63047fa139606f6c6862ff989ab1fbdcristy        }
13222857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    FT_Vector_Transform(&glyph.origin,&affine);
13232857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    (void) FT_Glyph_Transform(glyph.image,&affine,&glyph.origin);
13242857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
13252857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      (FT_Vector *) NULL,MagickTrue);
13262857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (status != 0)
13272857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      continue;
13282857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    bitmap=(FT_BitmapGlyph) glyph.image;
13292857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    point.x=offset->x+bitmap->left;
13302857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    point.y=offset->y-bitmap->top;
13312857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (draw_info->render != MagickFalse)
13322857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      {
13332857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        CacheView
13342857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          *image_view;
1335bd51246ae63047fa139606f6c6862ff989ab1fbdcristy
13362857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        ExceptionInfo
13372857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          *exception;
13382857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
13392857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        MagickBooleanType
13402857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          status;
1341bd51246ae63047fa139606f6c6862ff989ab1fbdcristy
13422857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        /*
13432857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          Rasterize the glyph.
13442857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        */
13452857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        status=MagickTrue;
13462857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        exception=(&image->exception);
13472857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        image_view=AcquireCacheView(image);
1348bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (y=0; y < (ssize_t) bitmap->bitmap.rows; y++)
13492857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        {
1350bd51246ae63047fa139606f6c6862ff989ab1fbdcristy          MagickBooleanType
13512857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            active,
13522857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            sync;
1353bd51246ae63047fa139606f6c6862ff989ab1fbdcristy
13542857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          MagickRealType
13552857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            fill_opacity;
13562857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
13572857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          PixelPacket
13582857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            fill_color;
13592857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
13604c08aed51c5899665ade97263692328eea4af106cristy          register Quantum
13612857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            *restrict q;
13622857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
13638815806717c3b3e2b4f8700b4cc18b751bd3c23fcristy          register ssize_t
13648815806717c3b3e2b4f8700b4cc18b751bd3c23fcristy            x;
13658815806717c3b3e2b4f8700b4cc18b751bd3c23fcristy
13662857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          register unsigned char
13672857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            *p;
13682857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy
136973ce31bc9ca5fc03ff0cef499e58ab2973add52ccristy          ssize_t
137073ce31bc9ca5fc03ff0cef499e58ab2973add52ccristy            x_offset,
137173ce31bc9ca5fc03ff0cef499e58ab2973add52ccristy            y_offset;
137273ce31bc9ca5fc03ff0cef499e58ab2973add52ccristy
13732857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          if (status == MagickFalse)
13742857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            continue;
1375bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          x_offset=(ssize_t) ceil(point.x-0.5);
1376bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          y_offset=(ssize_t) ceil(point.y+y-0.5);
1377bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows))
13782857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            continue;
13794c08aed51c5899665ade97263692328eea4af106cristy          q=(Quantum *) NULL;
1380bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns))
13812857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            active=MagickFalse;
13822857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          else
13832857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            {
13842857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              q=GetCacheViewAuthenticPixels(image_view,x_offset,y_offset,
13852857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                bitmap->bitmap.width,1,exception);
13864c08aed51c5899665ade97263692328eea4af106cristy              active=q != (Quantum *) NULL ? MagickTrue : MagickFalse;
13872857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            }
13882857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          p=bitmap->bitmap.buffer+y*bitmap->bitmap.width;
1389bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy          for (x=0; x < (ssize_t) bitmap->bitmap.width; x++)
1390bd51246ae63047fa139606f6c6862ff989ab1fbdcristy          {
13912857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            x_offset++;
13922857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            if ((*p == 0) || (x_offset < 0) ||
1393bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy                (x_offset >= (ssize_t) image->columns))
13943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              {
13952857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                p++;
1396ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
13972857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                continue;
13983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              }
13992857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            fill_opacity=(MagickRealType) (*p)/(bitmap->bitmap.num_grays-1);
14002857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            if (draw_info->text_antialias == MagickFalse)
14012857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              fill_opacity=fill_opacity >= 0.5 ? 1.0 : 0.0;
14022857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            if (active == MagickFalse)
14032857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              q=GetCacheViewAuthenticPixels(image_view,x_offset,y_offset,1,1,
14042857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                exception);
14054c08aed51c5899665ade97263692328eea4af106cristy            if (q == (const Quantum *) NULL)
14062857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              {
14072857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                p++;
1408ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy                q+=GetPixelChannels(image);
14092857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                continue;
14102857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              }
14112857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            (void) GetFillColor(draw_info,x_offset,y_offset,&fill_color);
14124c08aed51c5899665ade97263692328eea4af106cristy            fill_opacity=fill_opacity*fill_color.alpha;
14134c08aed51c5899665ade97263692328eea4af106cristy            CompositePixelOver(image,&fill_color,fill_opacity,q,
14144c08aed51c5899665ade97263692328eea4af106cristy              GetPixelAlpha(image,q),q);
14152857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            if (active == MagickFalse)
14162857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              {
14172857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                sync=SyncCacheViewAuthenticPixels(image_view,exception);
14182857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                if (sync == MagickFalse)
14192857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy                  status=MagickFalse;
14202857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy              }
14212857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            p++;
1422ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy            q+=GetPixelChannels(image);
14233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
14242857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          sync=SyncCacheViewAuthenticPixels(image_view,exception);
14252857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy          if (sync == MagickFalse)
14262857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy            status=MagickFalse;
14273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
14282857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        image_view=DestroyCacheView(image_view);
14292857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      }
14302857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((bitmap->left+bitmap->bitmap.width) > metrics->width)
14312857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      metrics->width=bitmap->left+bitmap->bitmap.width;
14322857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if ((draw_info->interword_spacing != 0.0) &&
14332857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        (IsUTFSpace(GetUTFCode(p)) != MagickFalse) &&
14342857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy        (IsUTFSpace(code) == MagickFalse))
1435c9b129570a277337cf0e887229741497e2ead5cfcristy      origin.x+=64.0*direction*draw_info->interword_spacing;
14362857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    else
1437c9b129570a277337cf0e887229741497e2ead5cfcristy      origin.x+=direction*face->glyph->advance.x;
14382857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    metrics->origin.x=origin.x;
14392857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    metrics->origin.y=origin.y;
14402857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    if (last_glyph.id != 0)
14412857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy      FT_Done_Glyph(last_glyph.image);
14422857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    last_glyph=glyph;
14432857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    code=GetUTFCode(p);
14442857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  }
14452857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy  if (utf8 != (unsigned char *) NULL)
14462857ffcd46fc4d091060c7e8aa9804f4b4d6efaacristy    utf8=(unsigned char *) RelinquishMagickMemory(utf8);
14473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (last_glyph.id != 0)
14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    FT_Done_Glyph(last_glyph.image);
14494c08aed51c5899665ade97263692328eea4af106cristy  if ((draw_info->stroke.alpha != TransparentAlpha) ||
14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (draw_info->stroke_pattern != (Image *) NULL))
14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
14523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (draw_info->render != MagickFalse)
14533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
14543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          /*
14553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            Draw text stroke.
14563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          */
14573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->linejoin=RoundJoin;
14583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.tx=offset->x;
14593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          annotate_info->affine.ty=offset->y;
14603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) ConcatenateString(&annotate_info->primitive,"'");
14613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) DrawImage(image,annotate_info);
14623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Determine font metrics.
14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
14673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  glyph.id=FT_Get_Char_Index(face,'_');
14683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  glyph.origin=origin;
14693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=FT_Load_Glyph(face,glyph.id,flags);
14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == 0)
14713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
14723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      status=FT_Get_Glyph(face->glyph,&glyph.image);
14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (status == 0)
14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
14753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          status=FT_Outline_Get_BBox(&((FT_OutlineGlyph) glyph.image)->
14763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            outline,&bounds);
14773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if (status == 0)
14783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
14793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              FT_Vector_Transform(&glyph.origin,&affine);
14803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              (void) FT_Glyph_Transform(glyph.image,&affine,&glyph.origin);
14813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              status=FT_Glyph_To_Bitmap(&glyph.image,ft_render_mode_normal,
14823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                (FT_Vector *) NULL,MagickTrue);
14833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              bitmap=(FT_BitmapGlyph) glyph.image;
14843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              if (bitmap->left > metrics->width)
14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                metrics->width=bitmap->left;
14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
14873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
14883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (glyph.id != 0)
14893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        FT_Done_Glyph(glyph.image);
14903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
14913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->width-=metrics->bounds.x1/64.0;
14923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x1/=64.0;
14933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y1/=64.0;
14943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x2/=64.0;
14953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y2/=64.0;
14963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->origin.x/=64.0;
14973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->origin.y/=64.0;
14983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
14993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Relinquish resources.
15003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
15013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyDrawInfo(annotate_info);
15023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) FT_Done_Face(face);
15033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) FT_Done_FreeType(library);
15043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
15053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
15073ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info,
15083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const char *magick_unused(encoding),const PointInfo *offset,
15093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  TypeMetric *metrics)
15103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ThrowMagickException(&image->exception,GetMagickModule(),
15123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (Freetype)",
1513ee08182aae410ed78e712a845bee7e51eedf73f3cristy    draw_info->font != (char *) NULL ? draw_info->font : "none");
15143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(RenderPostscript(image,draw_info,offset,metrics));
15153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
15173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
15193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+   R e n d e r P o s t s c r i p t                                           %
15243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
15273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RenderPostscript() renders text on the image with a Postscript font.  It
15303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  also returns the bounding box of the text relative to the image.
15313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RenderPostscript method is:
15333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType RenderPostscript(Image *image,DrawInfo *draw_info,
15353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const PointInfo *offset,TypeMetric *metrics)
15363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
15383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
15403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
15423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o offset: (x,y) location of text relative to image.
15443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: bounding box of text.
15463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
15473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
15483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15493ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline size_t MagickMin(const size_t x,const size_t y)
15503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (x < y)
15523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(x);
15533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(y);
15543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15563ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic char *EscapeParenthesis(const char *text)
15573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
15593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *buffer;
15603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  register char
15623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
15633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1564bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
15653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
15663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  size_t
15683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    escapes;
15693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  escapes=0;
15713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  buffer=AcquireString(text);
15723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  p=buffer;
1573bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i < (ssize_t) MagickMin(strlen(text),MaxTextExtent-escapes-1); i++)
15743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
15753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if ((text[i] == '(') || (text[i] == ')'))
15763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
15773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *p++='\\';
15783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        escapes++;
15793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
15803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p++=text[i];
15813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
15823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  *p='\0';
15833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(buffer);
15843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
15853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15863ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderPostscript(Image *image,
15873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics)
15883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
15893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  char
15903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    filename[MaxTextExtent],
15913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    geometry[MaxTextExtent],
15923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *text;
15933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  FILE
15953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *file;
15963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
15973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
15983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_image;
15993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
16013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *annotate_info;
16023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
16043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unique_file;
16053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
16073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    identity;
16083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PointInfo
16103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    extent,
16113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    point,
16123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resolution;
16133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1614bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
16153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    i;
16163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
16179d314ff2c17a77996c05413c2013880387e50f0ecristy  ssize_t
16189d314ff2c17a77996c05413c2013880387e50f0ecristy    y;
16199d314ff2c17a77996c05413c2013880387e50f0ecristy
16203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
16213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Render label with a Postscript font.
16223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
16233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
16243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
1625e7f5109f30fc7242d04a26174a9138483dda5b6acristy      "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
16263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->font : "none",draw_info->pointsize);
16273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  file=(FILE *) NULL;
16283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unique_file=AcquireUniqueFileResource(filename);
16293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unique_file != -1)
16303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    file=fdopen(unique_file,"wb");
16313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((unique_file == -1) || (file == (FILE *) NULL))
16323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
16333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowFileException(&image->exception,FileOpenError,"UnableToOpenFile",
16343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        filename);
16353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
16363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1637b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"%%!PS-Adobe-3.0\n");
1638b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"/ReencodeType\n");
1639b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"{\n");
1640b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"  findfont dup length\n");
1641b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,
16423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  dict begin { 1 index /FID ne {def} {pop pop} ifelse } forall\n");
1643b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,
16443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    "  /Encoding ISOLatin1Encoding def currentdict end definefont pop\n");
1645b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"} bind def\n");
16463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
16473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Sample to compute bounding box.
16483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
16493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  identity=(draw_info->affine.sx == draw_info->affine.sy) &&
16503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (draw_info->affine.rx == 0.0) && (draw_info->affine.ry == 0.0) ?
16513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MagickTrue : MagickFalse;
16523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  extent.x=0.0;
16533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  extent.y=0.0;
1654bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (i=0; i <= (ssize_t) (strlen(draw_info->text)+2); i++)
16553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
16563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    point.x=fabs(draw_info->affine.sx*i*draw_info->pointsize+
16573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->affine.ry*2.0*draw_info->pointsize);
16583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    point.y=fabs(draw_info->affine.rx*i*draw_info->pointsize+
16593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->affine.sy*2.0*draw_info->pointsize);
16603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (point.x > extent.x)
16613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      extent.x=point.x;
16623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (point.y > extent.y)
16633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      extent.y=point.y;
16643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1665b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"%g %g moveto\n",identity  != MagickFalse ? 0.0 :
16663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    extent.x/2.0,extent.y/2.0);
1667b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"%g %g scale\n",draw_info->pointsize,
16683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    draw_info->pointsize);
16693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((draw_info->font == (char *) NULL) || (*draw_info->font == '\0') ||
16703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (strchr(draw_info->font,'/') != (char *) NULL))
1671b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    (void) FormatLocaleFile(file,
16723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      "/Times-Roman-ISO dup /Times-Roman ReencodeType findfont setfont\n");
16733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
16741e604812fad85bb96f757a2393015ae3d061c39acristy    (void) FormatLocaleFile(file,
16751e604812fad85bb96f757a2393015ae3d061c39acristy      "/%s-ISO dup /%s ReencodeType findfont setfont\n",draw_info->font,
16761e604812fad85bb96f757a2393015ae3d061c39acristy      draw_info->font);
1677b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"[%g %g %g %g 0 0] concat\n",
16788cd5b3193212b4aebce08c4e7afbb66b09778029cristy    draw_info->affine.sx,-draw_info->affine.rx,-draw_info->affine.ry,
16798cd5b3193212b4aebce08c4e7afbb66b09778029cristy    draw_info->affine.sy);
16803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  text=EscapeParenthesis(draw_info->text);
16813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (identity == MagickFalse)
16821e604812fad85bb96f757a2393015ae3d061c39acristy    (void) FormatLocaleFile(file,"(%s) stringwidth pop -0.5 mul -0.5 rmoveto\n",
16831e604812fad85bb96f757a2393015ae3d061c39acristy      text);
1684b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"(%s) show\n",text);
16853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  text=DestroyString(text);
1686b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleFile(file,"showpage\n");
16873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) fclose(file);
1688b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0!",
1689e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    floor(extent.x+0.5),floor(extent.y+0.5));
16903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=AcquireImageInfo();
1691b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(annotate_info->filename,MaxTextExtent,"ps:%s",
16923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    filename);
16933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloneString(&annotate_info->page,geometry);
16943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->density != (char *) NULL)
16953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) CloneString(&annotate_info->density,draw_info->density);
16963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info->antialias=draw_info->text_antialias;
16973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_image=ReadImage(annotate_info,&image->exception);
16983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  CatchException(&image->exception);
16993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info=DestroyImageInfo(annotate_info);
17003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(filename);
17013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (annotate_image == (Image *) NULL)
17023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
17033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resolution.x=DefaultResolution;
17043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  resolution.y=DefaultResolution;
17053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->density != (char *) NULL)
17063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
17073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      GeometryInfo
17083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        geometry_info;
17093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickStatusType
17113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        flags;
17123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      flags=ParseGeometry(draw_info->density,&geometry_info);
17143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resolution.x=geometry_info.rho;
17153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resolution.y=geometry_info.sigma;
17163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((flags & SigmaValue) == 0)
17173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        resolution.y=resolution.x;
17183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
17193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (identity == MagickFalse)
17203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) TransformImage(&annotate_image,"0x0",(char *) NULL);
17213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
17223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
17233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      RectangleInfo
17243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        crop_info;
17253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      crop_info=GetImageBoundingBox(annotate_image,&annotate_image->exception);
1727bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      crop_info.height=(size_t) ((resolution.y/DefaultResolution)*
17283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ExpandAffine(&draw_info->affine)*draw_info->pointsize+0.5);
1729bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      crop_info.y=(ssize_t) ceil((resolution.y/DefaultResolution)*extent.y/8.0-
173006609eef311d5af857f65f20ed3af6860c1994becristy        0.5);
1731b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      (void) FormatLocaleString(geometry,MaxTextExtent,
17326d8abbae64da926477182d86d5007bc2c5a8b979cristy        "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
1733e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy        crop_info.height,(double) crop_info.x,(double) crop_info.y);
17343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) TransformImage(&annotate_image,geometry,(char *) NULL);
17353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
17363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.x=(resolution.y/DefaultResolution)*
17373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ExpandAffine(&draw_info->affine)*draw_info->pointsize;
17383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.y=metrics->pixels_per_em.x;
17393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->ascent=metrics->pixels_per_em.x;
17403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->descent=metrics->pixels_per_em.y/-5.0;
17413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->width=(double) annotate_image->columns/
17423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ExpandAffine(&draw_info->affine);
17433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->height=1.152*metrics->pixels_per_em.x;
17443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->max_advance=metrics->pixels_per_em.x;
17453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x1=0.0;
17463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y1=metrics->descent;
17473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x2=metrics->ascent+metrics->descent;
17483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y2=metrics->ascent+metrics->descent;
17493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_position=(-2.0);
17503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_thickness=1.0;
17513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->render == MagickFalse)
17523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
17533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      annotate_image=DestroyImage(annotate_image);
17543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickTrue);
17553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
17564c08aed51c5899665ade97263692328eea4af106cristy  if (draw_info->fill.alpha != TransparentAlpha)
17573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
17583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ExceptionInfo
17593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *exception;
17603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      MagickBooleanType
17623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        sync;
17633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      PixelPacket
17653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        fill_color;
17663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      CacheView
17683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *annotate_view;
17693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
17713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Render fill color.
17723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
17733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (image->matte == MagickFalse)
17743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
17753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (annotate_image->matte == MagickFalse)
17763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) SetImageAlphaChannel(annotate_image,OpaqueAlphaChannel);
17773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      fill_color=draw_info->fill;
17783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      exception=(&image->exception);
17793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      annotate_view=AcquireCacheView(annotate_image);
1780bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy      for (y=0; y < (ssize_t) annotate_image->rows; y++)
17813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
1782bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        register ssize_t
17833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          x;
17843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17854c08aed51c5899665ade97263692328eea4af106cristy        register Quantum
1786c47d1f8ecfe7d04f0f003cca0fe175658bbf0fb2cristy          *restrict q;
17873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
17883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        q=GetCacheViewAuthenticPixels(annotate_view,0,y,annotate_image->columns,
17893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          1,exception);
17904c08aed51c5899665ade97263692328eea4af106cristy        if (q == (const Quantum *) NULL)
17913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
1792bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for (x=0; x < (ssize_t) annotate_image->columns; x++)
17933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
17943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (void) GetFillColor(draw_info,x,y,&fill_color);
17954c08aed51c5899665ade97263692328eea4af106cristy          SetPixelAlpha(annotate_image,ClampToQuantum((((MagickRealType)
17964c08aed51c5899665ade97263692328eea4af106cristy            GetPixelIntensity(annotate_image,q)*fill_color.alpha)/
17974c08aed51c5899665ade97263692328eea4af106cristy            QuantumRange)),q);
17984c08aed51c5899665ade97263692328eea4af106cristy          SetPixelRed(annotate_image,fill_color.red,q);
17994c08aed51c5899665ade97263692328eea4af106cristy          SetPixelGreen(annotate_image,fill_color.green,q);
18004c08aed51c5899665ade97263692328eea4af106cristy          SetPixelBlue(annotate_image,fill_color.blue,q);
1801ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy          q+=GetPixelChannels(annotate_image);
18023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
18033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        sync=SyncCacheViewAuthenticPixels(annotate_view,exception);
18043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if (sync == MagickFalse)
18053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          break;
18063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
18073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      annotate_view=DestroyCacheView(annotate_view);
18083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CompositeImage(image,OverCompositeOp,annotate_image,
1809bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        (ssize_t) ceil(offset->x-0.5),(ssize_t) ceil(offset->y-(metrics->ascent+
181006609eef311d5af857f65f20ed3af6860c1994becristy        metrics->descent)-0.5));
18113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
18123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_image=DestroyImage(annotate_image);
18133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
18143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
18153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
18173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+   R e n d e r X 1 1                                                         %
18223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
18253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RenderX11() renders text on the image with an X11 font.  It also returns the
18283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  bounding box of the text relative to the image.
18293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RenderX11 method is:
18313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType RenderX11(Image *image,DrawInfo *draw_info,
18333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%        const PointInfo *offset,TypeMetric *metrics)
18343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
18363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image: the image.
18383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o draw_info: the draw info.
18403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o offset: (x,y) location of text relative to image.
18423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o metrics: bounding box of text.
18443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
18453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
18463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_X11_DELEGATE)
18473ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderX11(Image *image,const DrawInfo *draw_info,
18483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const PointInfo *offset,TypeMetric *metrics)
18493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
18503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
18513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
18523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static DrawInfo
18543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    cache_info;
18553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static Display
18573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *display = (Display *) NULL;
18583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XAnnotateInfo
18603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    annotate_info;
18613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XFontStruct
18633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *font_info;
18643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XPixelInfo
18663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    pixel;
18673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XResourceInfo
18693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resource_info;
18703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XrmDatabase
18723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    resource_database;
18733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XStandardColormap
18753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *map_info;
18763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static XVisualInfo
18783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *visual_info;
18793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1880bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  size_t
18813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    height,
18823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    width;
18833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1884d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  if (annotate_semaphore == (SemaphoreInfo *) NULL)
1885d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy    AcquireSemaphoreInfo(&annotate_semaphore);
1886d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  LockSemaphoreInfo(annotate_semaphore);
18873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (display == (Display *) NULL)
18883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1889104cea817534e8601291610f22e496c10f8f9ddbcristy      const char
1890104cea817534e8601291610f22e496c10f8f9ddbcristy        *client_name;
1891104cea817534e8601291610f22e496c10f8f9ddbcristy
18923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ImageInfo
18933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        *image_info;
18943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
18953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
18963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Open X server connection.
18973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
18983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      display=XOpenDisplay(draw_info->server_name);
18993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (display == (Display *) NULL)
19003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(XServerError,"UnableToOpenXServer",
19023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            draw_info->server_name);
19033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
19063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Get user defaults from X resource database.
19073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
19083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) XSetErrorHandler(XError);
19093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info=AcquireImageInfo();
1910104cea817534e8601291610f22e496c10f8f9ddbcristy      client_name=GetClientName();
1911309c861abe279e5ad97173157f7c05fb9f4d5f8bcristy      resource_database=XGetResourceDatabase(display,client_name);
1912104cea817534e8601291610f22e496c10f8f9ddbcristy      XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
19133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resource_info.close_server=MagickFalse;
19143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resource_info.colormap=PrivateColormap;
19153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resource_info.font=AcquireString(draw_info->font);
19163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resource_info.background_color=AcquireString("#ffffffffffff");
19173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      resource_info.foreground_color=AcquireString("#000000000000");
19183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      map_info=XAllocStandardColormap();
19193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (map_info == (XStandardColormap *) NULL)
19203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
19223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->filename);
19233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
19263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Initialize visual info.
19273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
19283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      visual_info=XBestVisualInfo(display,map_info,&resource_info);
19293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (visual_info == (XVisualInfo *) NULL)
19303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(XServerError,"UnableToGetVisual",
19323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->filename);
19333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      map_info->colormap=(Colormap) NULL;
1936f2faecf9facdbbb14fcba373365f9f691a9658e0cristy      pixel.pixels=(unsigned long *) NULL;
19373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
19383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Initialize Standard Colormap info.
19393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
19403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
19413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        map_info);
19424c08aed51c5899665ade97263692328eea4af106cristy      XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
19434c08aed51c5899665ade97263692328eea4af106cristy        &pixel);
19443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      pixel.annotate_context=XDefaultGC(display,visual_info->screen);
19453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
19463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Initialize font info.
19473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
19483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      font_info=XBestFont(display,&resource_info,MagickFalse);
19493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (font_info == (XFontStruct *) NULL)
19503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(XServerError,"UnableToLoadFont",
19523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            draw_info->font);
19533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((map_info == (XStandardColormap *) NULL) ||
19563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (visual_info == (XVisualInfo *) NULL) ||
19573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          (font_info == (XFontStruct *) NULL))
19583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          XFreeResources(display,visual_info,map_info,&pixel,font_info,
19603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            &resource_info,(XWindowInfo *) NULL);
19613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(XServerError,"UnableToLoadFont",
19623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            image->filename);
19633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      cache_info=(*draw_info);
19663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1967d7ecaca521e2840f1308b758f7b3a3a9fd2dce38cristy  UnlockSemaphoreInfo(annotate_semaphore);
19683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
19693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Initialize annotate info.
19703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
19713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  XGetAnnotateInfo(&annotate_info);
19723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info.stencil=ForegroundStencil;
19733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (cache_info.font != draw_info->font)
19743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
19753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /*
19763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Type name has changed.
19773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      */
19783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) XFreeFont(display,font_info);
19793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CloneString(&resource_info.font,draw_info->font);
19803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      font_info=XBestFont(display,&resource_info,MagickFalse);
19813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (font_info == (XFontStruct *) NULL)
19823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
19833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ThrowXWindowException(XServerError,"UnableToLoadFont",
19843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            draw_info->font);
19853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          return(MagickFalse);
19863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
19873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
19883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
19893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
1990e7f5109f30fc7242d04a26174a9138483dda5b6acristy      "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
19913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      draw_info->font : "none",draw_info->pointsize);
19923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  cache_info=(*draw_info);
19933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info.font_info=font_info;
19943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info.text=(char *) draw_info->text;
19953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,
19963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (int) strlen(draw_info->text));
19973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
19983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
19993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
20003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->ascent=(double) font_info->ascent+4;
20013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->descent=(double) (-font_info->descent);
20023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
20033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->height=font_info->ascent+font_info->descent;
20043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->max_advance=(double) font_info->max_bounds.width;
20053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x1=0.0;
20063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y1=metrics->descent;
20073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.x2=metrics->ascent+metrics->descent;
20083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->bounds.y2=metrics->ascent+metrics->descent;
20093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_position=(-2.0);
20103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  metrics->underline_thickness=1.0;
20113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (draw_info->render == MagickFalse)
20123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
20134c08aed51c5899665ade97263692328eea4af106cristy  if (draw_info->fill.alpha == TransparentAlpha)
20143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
20153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
20163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Render fill color.
20173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
20183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  width=annotate_info.width;
20193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  height=annotate_info.height;
20203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ((draw_info->affine.rx != 0.0) || (draw_info->affine.ry != 0.0))
20213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
20223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (((draw_info->affine.sx-draw_info->affine.sy) == 0.0) &&
20233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          ((draw_info->affine.rx+draw_info->affine.ry) == 0.0))
20243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        annotate_info.degrees=(180.0/MagickPI)*
20253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          atan2(draw_info->affine.rx,draw_info->affine.sx);
20263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2027b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
20286d8abbae64da926477182d86d5007bc2c5a8b979cristy    "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
2029e8c25f9b4c9fb72cad6db08eeda58c7c5784014ecristy    ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
203006609eef311d5af857f65f20ed3af6860c1994becristy    draw_info->interline_spacing-0.5));
20313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
20323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
20333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
20343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=XAnnotateImage(display,&pixel,&annotate_info,image);
20353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == 0)
20363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
20373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
20383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        image->filename);
20393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
20403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
20413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
20423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
20433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
20443ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType RenderX11(Image *image,const DrawInfo *draw_info,
20453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const PointInfo *offset,TypeMetric *metrics)
20463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
20473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) draw_info;
20483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) offset;
20493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) metrics;
20503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ThrowMagickException(&image->exception,GetMagickModule(),
20513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
20523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->filename);
20533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
20543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
20553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2056