blob: c672d16fba1e837761006d57798acbc3c47f2cd1 [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 %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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)
60#if defined(MAGICKCORE_HAVE_FT2BUILD_H)
61# include <ft2build.h>
62#endif
63#if defined(FT_FREETYPE_H)
64# include FT_FREETYPE_H
65#else
66# include <freetype/freetype.h>
67#endif
68#endif
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72% %
73% %
74% %
75% I s P F A %
76% %
77% %
78% %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81% IsPFA()() returns MagickTrue if the image format type, identified by the
82% magick string, is PFA.
83%
84% The format of the IsPFA method is:
85%
86% MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
87%
88% A description of each parameter follows:
89%
90% o magick: compare image format pattern against these bytes.
91%
92% o length: Specifies the length of the magick string.
93%
94%
95*/
96static MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
97{
98 if (length < 14)
99 return(MagickFalse);
cristy97841ba2010-09-02 15:48:08 +0000100 if (LocaleNCompare((char *) magick,"%!PS-AdobeFont",14) == 0)
cristy3ed852e2009-09-05 21:47:34 +0000101 return(MagickTrue);
102 return(MagickFalse);
103}
104
105/*
106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107% %
108% %
109% %
110% I s T T F %
111% %
112% %
113% %
114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115%
116% IsTTF()() returns MagickTrue if the image format type, identified by the
117% magick string, is TTF.
118%
119% The format of the IsTTF method is:
120%
121% MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
122%
123% A description of each parameter follows:
124%
125% o magick: compare image format pattern against these bytes.
126%
127% o length: Specifies the length of the magick string.
128%
129%
130*/
131static MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
132{
133 if (length < 5)
134 return(MagickFalse);
135 if (((int) magick[0] == 0x00) && ((int) magick[1] == 0x01) &&
136 ((int) magick[2] == 0x00) && ((int) magick[3] == 0x00) &&
cristy94027a32010-05-31 18:37:32 +0000137 ((int) magick[4] == 0x00))
cristy3ed852e2009-09-05 21:47:34 +0000138 return(MagickTrue);
139 return(MagickFalse);
140}
141
142#if defined(MAGICKCORE_FREETYPE_DELEGATE)
143/*
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145% %
146% %
147% %
148% R e a d T T F I m a g e %
149% %
150% %
151% %
152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153%
154% ReadTTFImage() reads a TrueType font file and returns it. It
155% allocates the memory necessary for the new Image structure and returns a
156% pointer to the new image.
157%
158% The format of the ReadTTFImage method is:
159%
160% Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
161%
162% A description of each parameter follows:
163%
164% o image_info: the image info.
165%
166% o exception: return any errors or warnings in this structure.
167%
168*/
169static Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
170{
171 char
172 buffer[MaxTextExtent],
173 *text;
174
175 const char
176 *Text = (char *)
177 "abcdefghijklmnopqrstuvwxyz\n"
178 "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
cristy947cb4c2011-10-20 18:41:46 +0000179 "0123456789.:,;(*!?}^)#${%^&-+@\n";
cristy3ed852e2009-09-05 21:47:34 +0000180
181 const TypeInfo
182 *type_info;
183
184 DrawInfo
185 *draw_info;
186
187 Image
188 *image;
189
cristy3ed852e2009-09-05 21:47:34 +0000190 MagickBooleanType
191 status;
192
cristy101ab702011-10-13 13:06:32 +0000193 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +0000194 background_color;
195
cristybb503372010-05-27 20:51:26 +0000196 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000197 i,
198 x;
199
cristy4c08aed2011-07-01 19:47:50 +0000200 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000201 *q;
202
cristyc6da28e2011-04-28 01:41:35 +0000203 ssize_t
204 y;
205
cristy3ed852e2009-09-05 21:47:34 +0000206 /*
207 Open image file.
208 */
209 assert(image_info != (const ImageInfo *) NULL);
210 assert(image_info->signature == MagickSignature);
211 if (image_info->debug != MagickFalse)
212 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
213 image_info->filename);
214 assert(exception != (ExceptionInfo *) NULL);
215 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000216 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000217 image->columns=800;
218 image->rows=480;
219 type_info=GetTypeInfo(image_info->filename,exception);
220 if ((type_info != (const TypeInfo *) NULL) &&
221 (type_info->glyphs != (char *) NULL))
222 (void) CopyMagickString(image->filename,type_info->glyphs,MaxTextExtent);
223 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
224 if (status == MagickFalse)
225 {
226 image=DestroyImageList(image);
227 return((Image *) NULL);
228 }
229 /*
230 Color canvas with background color
231 */
232 background_color=image_info->background_color;
cristybb503372010-05-27 20:51:26 +0000233 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000234 {
235 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000236 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000237 break;
cristybb503372010-05-27 20:51:26 +0000238 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000239 {
cristy803640d2011-11-17 02:11:32 +0000240 SetPixelInfoPixel(image,&background_color,q);
cristyed231572011-07-14 02:18:59 +0000241 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000242 }
cristy3ed852e2009-09-05 21:47:34 +0000243 if (SyncAuthenticPixels(image,exception) == MagickFalse)
244 break;
245 }
246 (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
247 (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
248 /*
249 Prepare drawing commands
250 */
251 y=20;
252 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
253 draw_info->font=AcquireString(image->filename);
254 ConcatenateString(&draw_info->primitive,"push graphic-context\n");
cristyb51dff52011-05-19 16:55:47 +0000255 (void) FormatLocaleString(buffer,MaxTextExtent," viewbox 0 0 %.20g %.20g\n",
cristye8c25f92010-06-03 00:53:06 +0000256 (double) image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000257 ConcatenateString(&draw_info->primitive,buffer);
258 ConcatenateString(&draw_info->primitive," font-size 18\n");
cristyb51dff52011-05-19 16:55:47 +0000259 (void) FormatLocaleString(buffer,MaxTextExtent," text 10,%.20g '",(double) y);
cristy3ed852e2009-09-05 21:47:34 +0000260 ConcatenateString(&draw_info->primitive,buffer);
261 text=EscapeString(Text,'"');
262 ConcatenateString(&draw_info->primitive,text);
263 text=DestroyString(text);
cristyb51dff52011-05-19 16:55:47 +0000264 (void) FormatLocaleString(buffer,MaxTextExtent,"'\n");
cristy3ed852e2009-09-05 21:47:34 +0000265 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000266 y+=20*(ssize_t) MultilineCensus((char *) Text)+20;
267 for (i=12; i <= 72; i+=6)
cristy3ed852e2009-09-05 21:47:34 +0000268 {
cristy947cb4c2011-10-20 18:41:46 +0000269 y+=i+12;
270 ConcatenateString(&draw_info->primitive," font-size 18\n");
271 (void) FormatLocaleString(buffer,MaxTextExtent," text 10,%.20g '%.20g'\n",
cristye8c25f92010-06-03 00:53:06 +0000272 (double) y,(double) i);
cristy3ed852e2009-09-05 21:47:34 +0000273 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000274 (void) FormatLocaleString(buffer,MaxTextExtent," font-size %.20g\n",
cristye8c25f92010-06-03 00:53:06 +0000275 (double) i);
cristy3ed852e2009-09-05 21:47:34 +0000276 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000277 (void) FormatLocaleString(buffer,MaxTextExtent," text 50,%.20g "
278 "'That which does not destroy me, only makes me stronger.'\n",(double) y);
cristy3ed852e2009-09-05 21:47:34 +0000279 ConcatenateString(&draw_info->primitive,buffer);
cristy947cb4c2011-10-20 18:41:46 +0000280 if (i >= 24)
281 i+=6;
cristy3ed852e2009-09-05 21:47:34 +0000282 }
283 ConcatenateString(&draw_info->primitive,"pop graphic-context");
cristy018f07f2011-09-04 21:15:19 +0000284 (void) DrawImage(image,draw_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000285 /*
286 Relinquish resources.
287 */
288 draw_info=DestroyDrawInfo(draw_info);
289 (void) CloseBlob(image);
290 return(GetFirstImageInList(image));
291}
292#endif /* MAGICKCORE_FREETYPE_DELEGATE */
293
294/*
295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296% %
297% %
298% %
299% R e g i s t e r T T F I m a g e %
300% %
301% %
302% %
303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304%
305% RegisterTTFImage() adds attributes for the TTF image format to
306% the list of supported formats. The attributes include the image format
307% tag, a method to read and/or write the format, whether the format
308% supports the saving of more than one frame to the same file or blob,
309% whether the format supports native in-memory I/O, and a brief
310% description of the format.
311%
312% The format of the RegisterTTFImage method is:
313%
cristybb503372010-05-27 20:51:26 +0000314% size_t RegisterTTFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000315%
316*/
cristybb503372010-05-27 20:51:26 +0000317ModuleExport size_t RegisterTTFImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000318{
319 char
320 version[MaxTextExtent];
321
322 MagickInfo
323 *entry;
324
325 *version='\0';
326#if defined(FREETYPE_MAJOR) && defined(FREETYPE_MINOR) && defined(FREETYPE_PATCH)
cristyb51dff52011-05-19 16:55:47 +0000327 (void) FormatLocaleString(version,MaxTextExtent,"Freetype %d.%d.%d",
cristy3ed852e2009-09-05 21:47:34 +0000328 FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH);
329#endif
330 entry=SetMagickInfo("DFONT");
331#if defined(MAGICKCORE_FREETYPE_DELEGATE)
332 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
333#endif
334 entry->magick=(IsImageFormatHandler *) IsTTF;
335 entry->adjoin=MagickFalse;
336 entry->description=ConstantString("Multi-face font package");
337 if (*version != '\0')
338 entry->version=ConstantString(version);
339 entry->module=ConstantString("TTF");
340 (void) RegisterMagickInfo(entry);
341 entry=SetMagickInfo("PFA");
342#if defined(MAGICKCORE_FREETYPE_DELEGATE)
343 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
344#endif
345 entry->magick=(IsImageFormatHandler *) IsPFA;
346 entry->adjoin=MagickFalse;
347 entry->description=ConstantString("Postscript Type 1 font (ASCII)");
348 if (*version != '\0')
349 entry->version=ConstantString(version);
350 entry->module=ConstantString("TTF");
351 (void) RegisterMagickInfo(entry);
352 entry=SetMagickInfo("PFB");
353#if defined(MAGICKCORE_FREETYPE_DELEGATE)
354 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
355#endif
356 entry->magick=(IsImageFormatHandler *) IsPFA;
357 entry->adjoin=MagickFalse;
358 entry->description=ConstantString("Postscript Type 1 font (binary)");
359 if (*version != '\0')
360 entry->version=ConstantString(version);
361 entry->module=ConstantString("TTF");
362 (void) RegisterMagickInfo(entry);
363 entry=SetMagickInfo("OTF");
364#if defined(MAGICKCORE_FREETYPE_DELEGATE)
365 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
366#endif
367 entry->magick=(IsImageFormatHandler *) IsTTF;
368 entry->adjoin=MagickFalse;
369 entry->description=ConstantString("Open Type font");
370 if (*version != '\0')
371 entry->version=ConstantString(version);
372 entry->module=ConstantString("TTF");
373 (void) RegisterMagickInfo(entry);
374 entry=SetMagickInfo("TTC");
375#if defined(MAGICKCORE_FREETYPE_DELEGATE)
376 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
377#endif
378 entry->magick=(IsImageFormatHandler *) IsTTF;
379 entry->adjoin=MagickFalse;
380 entry->description=ConstantString("TrueType font collection");
381 if (*version != '\0')
382 entry->version=ConstantString(version);
383 entry->module=ConstantString("TTF");
384 (void) RegisterMagickInfo(entry);
385 entry=SetMagickInfo("TTF");
386#if defined(MAGICKCORE_FREETYPE_DELEGATE)
387 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
388#endif
389 entry->magick=(IsImageFormatHandler *) IsTTF;
390 entry->adjoin=MagickFalse;
391 entry->description=ConstantString("TrueType font");
392 if (*version != '\0')
393 entry->version=ConstantString(version);
394 entry->module=ConstantString("TTF");
395 (void) RegisterMagickInfo(entry);
396 return(MagickImageCoderSignature);
397}
398
399/*
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401% %
402% %
403% %
404% U n r e g i s t e r T T F I m a g e %
405% %
406% %
407% %
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%
410% UnregisterTTFImage() removes format registrations made by the
411% TTF module from the list of supported formats.
412%
413% The format of the UnregisterTTFImage method is:
414%
415% UnregisterTTFImage(void)
416%
417*/
418ModuleExport void UnregisterTTFImage(void)
419{
420 (void) UnregisterMagickInfo("TTF");
421 (void) UnregisterMagickInfo("TTC");
422 (void) UnregisterMagickInfo("OTF");
423 (void) UnregisterMagickInfo("PFA");
424 (void) UnregisterMagickInfo("PFB");
425 (void) UnregisterMagickInfo("PFA");
426 (void) UnregisterMagickInfo("DFONT");
427}