blob: 150d40dd91108bd7c7219fb9b86612bfc4064613 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% TTTTT TTTTT FFFFF %
7% T T F %
8% T T FFF %
9% T T F %
10% T T F %
11% %
12% %
13% Return A Preview For A TrueType or Postscript Font %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/draw.h"
46#include "MagickCore/exception.h"
47#include "MagickCore/exception-private.h"
48#include "MagickCore/image.h"
49#include "MagickCore/image-private.h"
50#include "MagickCore/list.h"
51#include "MagickCore/magick.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/quantum-private.h"
54#include "MagickCore/static.h"
55#include "MagickCore/string_.h"
56#include "MagickCore/module.h"
57#include "MagickCore/type.h"
58#include "MagickWand/MagickWand.h"
cristy3ed852e2009-09-05 21:47:34 +000059#if defined(MAGICKCORE_FREETYPE_DELEGATE)
cristy03f187e2013-01-24 00:22:19 +000060#include <ft2build.h>
cristy3ed852e2009-09-05 21:47:34 +000061#if defined(FT_FREETYPE_H)
62# include FT_FREETYPE_H
63#else
64# include <freetype/freetype.h>
65#endif
66#endif
67
68/*
69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70% %
71% %
72% %
73% I s P F A %
74% %
75% %
76% %
77%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78%
79% IsPFA()() returns MagickTrue if the image format type, identified by the
80% magick string, is PFA.
81%
82% The format of the IsPFA method is:
83%
84% MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
85%
86% A description of each parameter follows:
87%
88% o magick: compare image format pattern against these bytes.
89%
90% o length: Specifies the length of the magick string.
91%
92%
93*/
94static MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
95{
96 if (length < 14)
97 return(MagickFalse);
cristy97841ba2010-09-02 15:48:08 +000098 if (LocaleNCompare((char *) magick,"%!PS-AdobeFont",14) == 0)
cristy3ed852e2009-09-05 21:47:34 +000099 return(MagickTrue);
100 return(MagickFalse);
101}
102
103/*
104%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105% %
106% %
107% %
108% I s T T F %
109% %
110% %
111% %
112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113%
114% IsTTF()() returns MagickTrue if the image format type, identified by the
115% magick string, is TTF.
116%
117% The format of the IsTTF method is:
118%
119% MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
120%
121% A description of each parameter follows:
122%
123% o magick: compare image format pattern against these bytes.
124%
125% o length: Specifies the length of the magick string.
126%
127%
128*/
129static MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
130{
131 if (length < 5)
132 return(MagickFalse);
133 if (((int) magick[0] == 0x00) && ((int) magick[1] == 0x01) &&
134 ((int) magick[2] == 0x00) && ((int) magick[3] == 0x00) &&
cristy94027a32010-05-31 18:37:32 +0000135 ((int) magick[4] == 0x00))
cristy3ed852e2009-09-05 21:47:34 +0000136 return(MagickTrue);
137 return(MagickFalse);
138}
139
140#if defined(MAGICKCORE_FREETYPE_DELEGATE)
141/*
142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143% %
144% %
145% %
146% R e a d T T F I m a g e %
147% %
148% %
149% %
150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151%
152% ReadTTFImage() reads a TrueType font file and returns it. It
153% allocates the memory necessary for the new Image structure and returns a
154% pointer to the new image.
155%
156% The format of the ReadTTFImage method is:
157%
158% Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
159%
160% A description of each parameter follows:
161%
162% o image_info: the image info.
163%
164% o exception: return any errors or warnings in this structure.
165%
166*/
167static Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
168{
169 char
cristy151b66d2015-04-15 10:50:31 +0000170 buffer[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +0000171 *text;
172
173 const char
174 *Text = (char *)
175 "abcdefghijklmnopqrstuvwxyz\n"
176 "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
cristy947cb4c2011-10-20 18:41:46 +0000177 "0123456789.:,;(*!?}^)#${%^&-+@\n";
cristy3ed852e2009-09-05 21:47:34 +0000178
179 const TypeInfo
180 *type_info;
181
182 DrawInfo
183 *draw_info;
184
185 Image
186 *image;
187
cristy3ed852e2009-09-05 21:47:34 +0000188 MagickBooleanType
189 status;
190
cristy101ab702011-10-13 13:06:32 +0000191 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000192 background_color;
193
cristybb503372010-05-27 20:51:26 +0000194 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000195 i,
196 x;
197
cristy4c08aed2011-07-01 19:47:50 +0000198 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000199 *q;
200
cristyc6da28e2011-04-28 01:41:35 +0000201 ssize_t
202 y;
203
cristy3ed852e2009-09-05 21:47:34 +0000204 /*
205 Open image file.
206 */
207 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000208 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000209 if (image_info->debug != MagickFalse)
210 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
211 image_info->filename);
212 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000213 assert(exception->signature == MagickCoreSignature);
cristy9950d572011-10-01 18:22:35 +0000214 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000215 image->columns=800;
216 image->rows=480;
217 type_info=GetTypeInfo(image_info->filename,exception);
218 if ((type_info != (const TypeInfo *) NULL) &&
219 (type_info->glyphs != (char *) NULL))
cristy151b66d2015-04-15 10:50:31 +0000220 (void) CopyMagickString(image->filename,type_info->glyphs,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000221 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
222 if (status == MagickFalse)
223 {
224 image=DestroyImageList(image);
225 return((Image *) NULL);
226 }
cristyacabb842014-12-14 23:36:33 +0000227 status=SetImageExtent(image,image->columns,image->rows,exception);
228 if (status == MagickFalse)
229 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000230 /*
231 Color canvas with background color
232 */
233 background_color=image_info->background_color;
cristybb503372010-05-27 20:51:26 +0000234 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000235 {
236 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000237 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000238 break;
cristybb503372010-05-27 20:51:26 +0000239 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000240 {
cristy11a06d32015-01-04 12:03:27 +0000241 SetPixelViaPixelInfo(image,&background_color,q);
cristyed231572011-07-14 02:18:59 +0000242 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000243 }
cristy3ed852e2009-09-05 21:47:34 +0000244 if (SyncAuthenticPixels(image,exception) == MagickFalse)
245 break;
246 }
cristy151b66d2015-04-15 10:50:31 +0000247 (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent);
248 (void) CopyMagickString(image->filename,image_info->filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000249 /*
250 Prepare drawing commands
251 */
252 y=20;
253 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
254 draw_info->font=AcquireString(image->filename);
255 ConcatenateString(&draw_info->primitive,"push graphic-context\n");
cristy151b66d2015-04-15 10:50:31 +0000256 (void) FormatLocaleString(buffer,MagickPathExtent," viewbox 0 0 %.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +0000257 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000258 ConcatenateString(&draw_info->primitive,buffer);
259 ConcatenateString(&draw_info->primitive," font-size 18\n");
cristy151b66d2015-04-15 10:50:31 +0000260 (void) FormatLocaleString(buffer,MagickPathExtent," text 10,%.20g '",(double) y);
cristy3ed852e2009-09-05 21:47:34 +0000261 ConcatenateString(&draw_info->primitive,buffer);
262 text=EscapeString(Text,'"');
263 ConcatenateString(&draw_info->primitive,text);
264 text=DestroyString(text);
cristy151b66d2015-04-15 10:50:31 +0000265 (void) FormatLocaleString(buffer,MagickPathExtent,"'\n");
cristy3ed852e2009-09-05 21:47:34 +0000266 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000267 y+=20*(ssize_t) MultilineCensus((char *) Text)+20;
268 for (i=12; i <= 72; i+=6)
cristy3ed852e2009-09-05 21:47:34 +0000269 {
cristy947cb4c2011-10-20 18:41:46 +0000270 y+=i+12;
271 ConcatenateString(&draw_info->primitive," font-size 18\n");
cristy151b66d2015-04-15 10:50:31 +0000272 (void) FormatLocaleString(buffer,MagickPathExtent," text 10,%.20g '%.20g'\n",
cristye8c25f92010-06-03 00:53:06 +0000273 (double) y,(double) i);
cristy3ed852e2009-09-05 21:47:34 +0000274 ConcatenateString(&draw_info->primitive,buffer);
cristy151b66d2015-04-15 10:50:31 +0000275 (void) FormatLocaleString(buffer,MagickPathExtent," font-size %.20g\n",
cristye8c25f92010-06-03 00:53:06 +0000276 (double) i);
cristy3ed852e2009-09-05 21:47:34 +0000277 ConcatenateString(&draw_info->primitive,buffer);
cristy151b66d2015-04-15 10:50:31 +0000278 (void) FormatLocaleString(buffer,MagickPathExtent," text 50,%.20g "
cristy947cb4c2011-10-20 18:41:46 +0000279 "'That which does not destroy me, only makes me stronger.'\n",(double) y);
cristy3ed852e2009-09-05 21:47:34 +0000280 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000281 if (i >= 24)
282 i+=6;
cristy3ed852e2009-09-05 21:47:34 +0000283 }
284 ConcatenateString(&draw_info->primitive,"pop graphic-context");
cristy018f07f2011-09-04 21:15:19 +0000285 (void) DrawImage(image,draw_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000286 /*
287 Relinquish resources.
288 */
289 draw_info=DestroyDrawInfo(draw_info);
290 (void) CloseBlob(image);
291 return(GetFirstImageInList(image));
292}
293#endif /* MAGICKCORE_FREETYPE_DELEGATE */
294
295/*
296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297% %
298% %
299% %
300% R e g i s t e r T T F I m a g e %
301% %
302% %
303% %
304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305%
306% RegisterTTFImage() adds attributes for the TTF image format to
307% the list of supported formats. The attributes include the image format
308% tag, a method to read and/or write the format, whether the format
309% supports the saving of more than one frame to the same file or blob,
310% whether the format supports native in-memory I/O, and a brief
311% description of the format.
312%
313% The format of the RegisterTTFImage method is:
314%
cristybb503372010-05-27 20:51:26 +0000315% size_t RegisterTTFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000316%
317*/
cristybb503372010-05-27 20:51:26 +0000318ModuleExport size_t RegisterTTFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000319{
320 char
cristy151b66d2015-04-15 10:50:31 +0000321 version[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000322
323 MagickInfo
324 *entry;
325
326 *version='\0';
327#if defined(FREETYPE_MAJOR) && defined(FREETYPE_MINOR) && defined(FREETYPE_PATCH)
cristy151b66d2015-04-15 10:50:31 +0000328 (void) FormatLocaleString(version,MagickPathExtent,"Freetype %d.%d.%d",
cristy3ed852e2009-09-05 21:47:34 +0000329 FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH);
330#endif
dirk06b627a2015-04-06 18:59:17 +0000331 entry=AcquireMagickInfo("TTF","DFONT","Multi-face font package");
cristy3ed852e2009-09-05 21:47:34 +0000332#if defined(MAGICKCORE_FREETYPE_DELEGATE)
333 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
334#endif
335 entry->magick=(IsImageFormatHandler *) IsTTF;
dirk08e9a112015-02-22 01:51:41 +0000336 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000337 if (*version != '\0')
338 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000339 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000340 entry=AcquireMagickInfo("TTF","PFA","Postscript Type 1 font (ASCII)");
cristy3ed852e2009-09-05 21:47:34 +0000341#if defined(MAGICKCORE_FREETYPE_DELEGATE)
342 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
343#endif
344 entry->magick=(IsImageFormatHandler *) IsPFA;
dirk08e9a112015-02-22 01:51:41 +0000345 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000346 if (*version != '\0')
347 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000348 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000349 entry=AcquireMagickInfo("TTF","PFB","Postscript Type 1 font (binary)");
cristy3ed852e2009-09-05 21:47:34 +0000350#if defined(MAGICKCORE_FREETYPE_DELEGATE)
351 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
352#endif
353 entry->magick=(IsImageFormatHandler *) IsPFA;
dirk08e9a112015-02-22 01:51:41 +0000354 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000355 if (*version != '\0')
356 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000357 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000358 entry=AcquireMagickInfo("TTF","OTF","Open Type font");
cristy3ed852e2009-09-05 21:47:34 +0000359#if defined(MAGICKCORE_FREETYPE_DELEGATE)
360 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
361#endif
362 entry->magick=(IsImageFormatHandler *) IsTTF;
dirk08e9a112015-02-22 01:51:41 +0000363 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000364 if (*version != '\0')
365 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000366 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000367 entry=AcquireMagickInfo("TTF","TTC","TrueType font collection");
cristy3ed852e2009-09-05 21:47:34 +0000368#if defined(MAGICKCORE_FREETYPE_DELEGATE)
369 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
370#endif
371 entry->magick=(IsImageFormatHandler *) IsTTF;
dirk08e9a112015-02-22 01:51:41 +0000372 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000373 if (*version != '\0')
374 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000375 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000376 entry=AcquireMagickInfo("TTF","TTF","TrueType font");
cristy3ed852e2009-09-05 21:47:34 +0000377#if defined(MAGICKCORE_FREETYPE_DELEGATE)
378 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
379#endif
380 entry->magick=(IsImageFormatHandler *) IsTTF;
dirk08e9a112015-02-22 01:51:41 +0000381 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000382 if (*version != '\0')
383 entry->version=ConstantString(version);
cristy3ed852e2009-09-05 21:47:34 +0000384 (void) RegisterMagickInfo(entry);
385 return(MagickImageCoderSignature);
386}
387
388/*
389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390% %
391% %
392% %
393% U n r e g i s t e r T T F I m a g e %
394% %
395% %
396% %
397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398%
399% UnregisterTTFImage() removes format registrations made by the
400% TTF module from the list of supported formats.
401%
402% The format of the UnregisterTTFImage method is:
403%
404% UnregisterTTFImage(void)
405%
406*/
407ModuleExport void UnregisterTTFImage(void)
408{
409 (void) UnregisterMagickInfo("TTF");
410 (void) UnregisterMagickInfo("TTC");
411 (void) UnregisterMagickInfo("OTF");
412 (void) UnregisterMagickInfo("PFA");
413 (void) UnregisterMagickInfo("PFB");
414 (void) UnregisterMagickInfo("PFA");
415 (void) UnregisterMagickInfo("DFONT");
416}