1 /*
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 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % 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 % https://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 */
42 #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/resource_.h"
55 #include "MagickCore/static.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/module.h"
58 #include "MagickCore/type.h"
59 #include "MagickCore/utility.h"
60 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
61 #include <ft2build.h>
62 #if defined(FT_FREETYPE_H)
63 # include FT_FREETYPE_H
64 #else
65 # include <freetype/freetype.h>
66 #endif
67 #endif
68
69 /*
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 % %
72 % %
73 % %
74 % I s P F A %
75 % %
76 % %
77 % %
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 %
80 % IsPFA()() returns MagickTrue if the image format type, identified by the
81 % magick string, is PFA.
82 %
83 % The format of the IsPFA method is:
84 %
85 % MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
86 %
87 % A description of each parameter follows:
88 %
89 % o magick: compare image format pattern against these bytes.
90 %
91 % o length: Specifies the length of the magick string.
92 %
93 %
94 */
IsPFA(const unsigned char * magick,const size_t length)95 static MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
96 {
97 if (length < 14)
98 return(MagickFalse);
99 if (LocaleNCompare((char *) magick,"%!PS-AdobeFont",14) == 0)
100 return(MagickTrue);
101 return(MagickFalse);
102 }
103
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 % %
107 % %
108 % %
109 % I s T T F %
110 % %
111 % %
112 % %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 % IsTTF()() returns MagickTrue if the image format type, identified by the
116 % magick string, is TTF.
117 %
118 % The format of the IsTTF method is:
119 %
120 % MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
121 %
122 % A description of each parameter follows:
123 %
124 % o magick: compare image format pattern against these bytes.
125 %
126 % o length: Specifies the length of the magick string.
127 %
128 %
129 */
IsTTF(const unsigned char * magick,const size_t length)130 static MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
131 {
132 if (length < 5)
133 return(MagickFalse);
134 if (((int) magick[0] == 0x00) && ((int) magick[1] == 0x01) &&
135 ((int) magick[2] == 0x00) && ((int) magick[3] == 0x00) &&
136 ((int) magick[4] == 0x00))
137 return(MagickTrue);
138 return(MagickFalse);
139 }
140
141 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
142 /*
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 % %
145 % %
146 % %
147 % R e a d T T F I m a g e %
148 % %
149 % %
150 % %
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 %
153 % ReadTTFImage() reads a TrueType font file and returns it. It
154 % allocates the memory necessary for the new Image structure and returns a
155 % pointer to the new image.
156 %
157 % The format of the ReadTTFImage method is:
158 %
159 % Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
160 %
161 % A description of each parameter follows:
162 %
163 % o image_info: the image info.
164 %
165 % o exception: return any errors or warnings in this structure.
166 %
167 */
ReadTTFImage(const ImageInfo * image_info,ExceptionInfo * exception)168 static Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
169 {
170 char
171 buffer[MagickPathExtent],
172 *text;
173
174 const char
175 Text[] =
176 "abcdefghijklmnopqrstuvwxyz\n"
177 "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
178 "0123456789.:,;(*!?}^)#${%^&-+@\n";
179
180 const TypeInfo
181 *type_info;
182
183 DrawInfo
184 *draw_info;
185
186 Image
187 *image;
188
189 MagickBooleanType
190 status;
191
192 PixelInfo
193 background_color;
194
195 ssize_t
196 i,
197 x;
198
199 Quantum
200 *q;
201
202 ssize_t
203 y;
204
205 /*
206 Open image file.
207 */
208 assert(image_info != (const ImageInfo *) NULL);
209 assert(image_info->signature == MagickCoreSignature);
210 if (image_info->debug != MagickFalse)
211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
212 image_info->filename);
213 assert(exception != (ExceptionInfo *) NULL);
214 assert(exception->signature == MagickCoreSignature);
215 image=AcquireImage(image_info,exception);
216 image->columns=800;
217 image->rows=480;
218 type_info=GetTypeInfo(image_info->filename,exception);
219 if ((type_info != (const TypeInfo *) NULL) &&
220 (type_info->glyphs != (char *) NULL))
221 (void) CopyMagickString(image->filename,type_info->glyphs,MagickPathExtent);
222 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
223 if (status == MagickFalse)
224 {
225 image=DestroyImageList(image);
226 return((Image *) NULL);
227 }
228 status=SetImageExtent(image,image->columns,image->rows,exception);
229 if (status == MagickFalse)
230 return(DestroyImageList(image));
231 /*
232 Color canvas with background color
233 */
234 background_color=image_info->background_color;
235 for (y=0; y < (ssize_t) image->rows; y++)
236 {
237 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
238 if (q == (Quantum *) NULL)
239 break;
240 for (x=0; x < (ssize_t) image->columns; x++)
241 {
242 SetPixelViaPixelInfo(image,&background_color,q);
243 q+=GetPixelChannels(image);
244 }
245 if (SyncAuthenticPixels(image,exception) == MagickFalse)
246 break;
247 }
248 (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent);
249 (void) CopyMagickString(image->filename,image_info->filename,
250 MagickPathExtent);
251 /*
252 Prepare drawing commands
253 */
254 y=20;
255 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
256 draw_info->font=AcquireString("");
257 (void) ImageToFile(image,draw_info->font,exception);
258 ConcatenateString(&draw_info->primitive,"push graphic-context\n");
259 (void) FormatLocaleString(buffer,MagickPathExtent,
260 " viewbox 0 0 %.20g %.20g\n",(double) image->columns,(double) image->rows);
261 ConcatenateString(&draw_info->primitive,buffer);
262 ConcatenateString(&draw_info->primitive," font-size 18\n");
263 (void) FormatLocaleString(buffer,MagickPathExtent," text 10,%.20g '",
264 (double) y);
265 ConcatenateString(&draw_info->primitive,buffer);
266 text=EscapeString(Text,'"');
267 ConcatenateString(&draw_info->primitive,text);
268 text=DestroyString(text);
269 (void) FormatLocaleString(buffer,MagickPathExtent,"'\n");
270 ConcatenateString(&draw_info->primitive,buffer);
271 y+=20*(ssize_t) MultilineCensus((char *) Text)+20;
272 for (i=12; i <= 72; i+=6)
273 {
274 y+=i+12;
275 ConcatenateString(&draw_info->primitive," font-size 18\n");
276 (void) FormatLocaleString(buffer,MagickPathExtent,
277 " text 10,%.20g '%.20g'\n",(double) y,(double) i);
278 ConcatenateString(&draw_info->primitive,buffer);
279 (void) FormatLocaleString(buffer,MagickPathExtent," font-size %.20g\n",
280 (double) i);
281 ConcatenateString(&draw_info->primitive,buffer);
282 (void) FormatLocaleString(buffer,MagickPathExtent," text 50,%.20g "
283 "'That which does not destroy me, only makes me stronger.'\n",(double) y);
284 ConcatenateString(&draw_info->primitive,buffer);
285 if (i >= 24)
286 i+=6;
287 }
288 ConcatenateString(&draw_info->primitive,"pop graphic-context");
289 (void) DrawImage(image,draw_info,exception);
290 /*
291 Relinquish resources.
292 */
293 (void) RelinquishUniqueFileResource(draw_info->font);
294 draw_info=DestroyDrawInfo(draw_info);
295 (void) CloseBlob(image);
296 return(GetFirstImageInList(image));
297 }
298 #endif /* MAGICKCORE_FREETYPE_DELEGATE */
299
300 /*
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % %
303 % %
304 % %
305 % R e g i s t e r T T F I m a g e %
306 % %
307 % %
308 % %
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310 %
311 % RegisterTTFImage() adds attributes for the TTF image format to
312 % the list of supported formats. The attributes include the image format
313 % tag, a method to read and/or write the format, whether the format
314 % supports the saving of more than one frame to the same file or blob,
315 % whether the format supports native in-memory I/O, and a brief
316 % description of the format.
317 %
318 % The format of the RegisterTTFImage method is:
319 %
320 % size_t RegisterTTFImage(void)
321 %
322 */
RegisterTTFImage(void)323 ModuleExport size_t RegisterTTFImage(void)
324 {
325 char
326 version[MagickPathExtent];
327
328 MagickInfo
329 *entry;
330
331 *version='\0';
332 #if defined(FREETYPE_MAJOR) && defined(FREETYPE_MINOR) && defined(FREETYPE_PATCH)
333 (void) FormatLocaleString(version,MagickPathExtent,"Freetype %d.%d.%d",
334 FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH);
335 #endif
336 entry=AcquireMagickInfo("TTF","DFONT","Multi-face font package");
337 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
338 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
339 #endif
340 entry->magick=(IsImageFormatHandler *) IsTTF;
341 entry->flags^=CoderAdjoinFlag;
342 if (*version != '\0')
343 entry->version=ConstantString(version);
344 (void) RegisterMagickInfo(entry);
345 entry=AcquireMagickInfo("TTF","PFA","Postscript Type 1 font (ASCII)");
346 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
347 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
348 #endif
349 entry->magick=(IsImageFormatHandler *) IsPFA;
350 entry->flags^=CoderAdjoinFlag;
351 if (*version != '\0')
352 entry->version=ConstantString(version);
353 (void) RegisterMagickInfo(entry);
354 entry=AcquireMagickInfo("TTF","PFB","Postscript Type 1 font (binary)");
355 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
356 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
357 #endif
358 entry->magick=(IsImageFormatHandler *) IsPFA;
359 entry->flags^=CoderAdjoinFlag;
360 if (*version != '\0')
361 entry->version=ConstantString(version);
362 (void) RegisterMagickInfo(entry);
363 entry=AcquireMagickInfo("TTF","OTF","Open Type font");
364 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
365 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
366 #endif
367 entry->magick=(IsImageFormatHandler *) IsTTF;
368 entry->flags^=CoderAdjoinFlag;
369 if (*version != '\0')
370 entry->version=ConstantString(version);
371 (void) RegisterMagickInfo(entry);
372 entry=AcquireMagickInfo("TTF","TTC","TrueType font collection");
373 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
374 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
375 #endif
376 entry->magick=(IsImageFormatHandler *) IsTTF;
377 entry->flags^=CoderAdjoinFlag;
378 if (*version != '\0')
379 entry->version=ConstantString(version);
380 (void) RegisterMagickInfo(entry);
381 entry=AcquireMagickInfo("TTF","TTF","TrueType font");
382 #if defined(MAGICKCORE_FREETYPE_DELEGATE)
383 entry->decoder=(DecodeImageHandler *) ReadTTFImage;
384 #endif
385 entry->magick=(IsImageFormatHandler *) IsTTF;
386 entry->flags^=CoderAdjoinFlag;
387 if (*version != '\0')
388 entry->version=ConstantString(version);
389 (void) RegisterMagickInfo(entry);
390 return(MagickImageCoderSignature);
391 }
392
393 /*
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 % %
396 % %
397 % %
398 % U n r e g i s t e r T T F I m a g e %
399 % %
400 % %
401 % %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 %
404 % UnregisterTTFImage() removes format registrations made by the
405 % TTF module from the list of supported formats.
406 %
407 % The format of the UnregisterTTFImage method is:
408 %
409 % UnregisterTTFImage(void)
410 %
411 */
UnregisterTTFImage(void)412 ModuleExport void UnregisterTTFImage(void)
413 {
414 (void) UnregisterMagickInfo("TTF");
415 (void) UnregisterMagickInfo("TTC");
416 (void) UnregisterMagickInfo("OTF");
417 (void) UnregisterMagickInfo("PFA");
418 (void) UnregisterMagickInfo("PFB");
419 (void) UnregisterMagickInfo("PFA");
420 (void) UnregisterMagickInfo("DFONT");
421 }
422