Coverage Report

Created: 2026-03-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/ttf.c
Line
Count
Source
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 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/license/                                         %
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
*/
95
static MagickBooleanType IsPFA(const unsigned char *magick,const size_t length)
96
0
{
97
0
  if (length < 14)
98
0
    return(MagickFalse);
99
0
  if (LocaleNCompare((char *) magick,"%!PS-AdobeFont",14) == 0)
100
0
    return(MagickTrue);
101
0
  return(MagickFalse);
102
0
}
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
*/
130
static MagickBooleanType IsTTF(const unsigned char *magick,const size_t length)
131
0
{
132
0
  if (length < 5)
133
0
    return(MagickFalse);
134
0
  if (((int) magick[0] == 0x00) && ((int) magick[1] == 0x01) &&
135
0
      ((int) magick[2] == 0x00) && ((int) magick[3] == 0x00) &&
136
0
      ((int) magick[4] == 0x00))
137
0
    return(MagickTrue);
138
0
  return(MagickFalse);
139
0
}
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
*/
168
static Image *ReadTTFImage(const ImageInfo *image_info,ExceptionInfo *exception)
169
7.18k
{
170
7.18k
  char
171
7.18k
    buffer[MagickPathExtent],
172
7.18k
    *text;
173
174
7.18k
  const char
175
7.18k
    Text[] =
176
7.18k
      "abcdefghijklmnopqrstuvwxyz\n"
177
7.18k
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
178
7.18k
      "0123456789.:,;(*!?}^)#${%^&-+@\n";
179
180
7.18k
  const TypeInfo
181
7.18k
    *type_info;
182
183
7.18k
  DrawInfo
184
7.18k
    *draw_info;
185
186
7.18k
  Image
187
7.18k
    *image;
188
189
7.18k
  MagickBooleanType
190
7.18k
    status;
191
192
7.18k
  PixelInfo
193
7.18k
    background_color;
194
195
7.18k
  ssize_t
196
7.18k
    i,
197
7.18k
    x;
198
199
7.18k
  Quantum
200
7.18k
    *q;
201
202
7.18k
  ssize_t
203
7.18k
    y;
204
205
  /*
206
    Open image file.
207
  */
208
7.18k
  assert(image_info != (const ImageInfo *) NULL);
209
7.18k
  assert(image_info->signature == MagickCoreSignature);
210
7.18k
  assert(exception != (ExceptionInfo *) NULL);
211
7.18k
  assert(exception->signature == MagickCoreSignature);
212
7.18k
  if (IsEventLogging() != MagickFalse)
213
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
214
0
      image_info->filename);
215
7.18k
  image=AcquireImage(image_info,exception);
216
7.18k
  image->columns=800;
217
7.18k
  image->rows=480;
218
7.18k
  type_info=GetTypeInfo(image_info->filename,exception);
219
7.18k
  if ((type_info != (const TypeInfo *) NULL) &&
220
0
      (type_info->glyphs != (char *) NULL))
221
0
    (void) CopyMagickString(image->filename,type_info->glyphs,MagickPathExtent);
222
7.18k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
223
7.18k
  if (status == MagickFalse)
224
473
    {
225
473
      image=DestroyImageList(image);
226
473
      return((Image *) NULL);
227
473
    }
228
6.71k
  status=SetImageExtent(image,image->columns,image->rows,exception);
229
6.71k
  if (status == MagickFalse)
230
0
    return(DestroyImageList(image));
231
  /*
232
    Color canvas with background color
233
  */
234
6.71k
  background_color=image_info->background_color;
235
3.22M
  for (y=0; y < (ssize_t) image->rows; y++)
236
3.22M
  {
237
3.22M
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
238
3.22M
    if (q == (Quantum *) NULL)
239
0
      break;
240
2.58G
    for (x=0; x < (ssize_t) image->columns; x++)
241
2.57G
    {
242
2.57G
      SetPixelViaPixelInfo(image,&background_color,q);
243
2.57G
      q+=(ptrdiff_t) GetPixelChannels(image);
244
2.57G
    }
245
3.22M
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
246
0
      break;
247
3.22M
  }
248
6.71k
  (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent);
249
6.71k
  (void) CopyMagickString(image->filename,image_info->filename,
250
6.71k
    MagickPathExtent);
251
  /*
252
    Prepare drawing commands
253
  */
254
6.71k
  y=20;
255
6.71k
  draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
256
6.71k
  draw_info->font=AcquireString("");
257
6.71k
  (void) ImageToFile(image,draw_info->font,exception);
258
6.71k
  ConcatenateString(&draw_info->primitive,"push graphic-context\n");
259
6.71k
  (void) FormatLocaleString(buffer,MagickPathExtent,
260
6.71k
    " viewbox 0 0 %.20g %.20g\n",(double) image->columns,(double) image->rows);
261
6.71k
  ConcatenateString(&draw_info->primitive,buffer);
262
6.71k
  ConcatenateString(&draw_info->primitive," font-size 18\n");
263
6.71k
  (void) FormatLocaleString(buffer,MagickPathExtent," text 10,%.20g '",
264
6.71k
    (double) y);
265
6.71k
  ConcatenateString(&draw_info->primitive,buffer);
266
6.71k
  text=EscapeString(Text,'"');
267
6.71k
  ConcatenateString(&draw_info->primitive,text);
268
6.71k
  text=DestroyString(text);
269
6.71k
  (void) FormatLocaleString(buffer,MagickPathExtent,"'\n");
270
6.71k
  ConcatenateString(&draw_info->primitive,buffer);
271
6.71k
  y+=20*(ssize_t) MultilineCensus((char *) Text)+20;
272
53.6k
  for (i=12; i <= 72; i+=6)
273
46.9k
  {
274
46.9k
    y+=i+12;
275
46.9k
    ConcatenateString(&draw_info->primitive," font-size 18\n");
276
46.9k
    (void) FormatLocaleString(buffer,MagickPathExtent,
277
46.9k
      " text 10,%.20g '%.20g'\n",(double) y,(double) i);
278
46.9k
    ConcatenateString(&draw_info->primitive,buffer);
279
46.9k
    (void) FormatLocaleString(buffer,MagickPathExtent," font-size %.20g\n",
280
46.9k
      (double) i);
281
46.9k
    ConcatenateString(&draw_info->primitive,buffer);
282
46.9k
    (void) FormatLocaleString(buffer,MagickPathExtent," text 50,%.20g "
283
46.9k
      "'That which does not destroy me, only makes me stronger.'\n",(double) y);
284
46.9k
    ConcatenateString(&draw_info->primitive,buffer);
285
46.9k
    if (i >= 24)
286
33.5k
      i+=6;
287
46.9k
  }
288
6.71k
  ConcatenateString(&draw_info->primitive,"pop graphic-context");
289
6.71k
  (void) DrawImage(image,draw_info,exception);
290
  /*
291
    Relinquish resources.
292
  */
293
6.71k
  (void) RelinquishUniqueFileResource(draw_info->font);
294
6.71k
  draw_info=DestroyDrawInfo(draw_info);
295
6.71k
  if (CloseBlob(image) == MagickFalse)
296
151
    status=MagickFalse;
297
6.71k
  if (status == MagickFalse)
298
151
    return(DestroyImageList(image));
299
6.56k
  return(GetFirstImageInList(image));
300
6.71k
}
301
#endif /* MAGICKCORE_FREETYPE_DELEGATE */
302

303
/*
304
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
%                                                                             %
306
%                                                                             %
307
%                                                                             %
308
%   R e g i s t e r T T F I m a g e                                           %
309
%                                                                             %
310
%                                                                             %
311
%                                                                             %
312
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313
%
314
%  RegisterTTFImage() adds attributes for the TTF image format to
315
%  the list of supported formats.  The attributes include the image format
316
%  tag, a method to read and/or write the format, whether the format
317
%  supports the saving of more than one frame to the same file or blob,
318
%  whether the format supports native in-memory I/O, and a brief
319
%  description of the format.
320
%
321
%  The format of the RegisterTTFImage method is:
322
%
323
%      size_t RegisterTTFImage(void)
324
%
325
*/
326
ModuleExport size_t RegisterTTFImage(void)
327
10
{
328
10
  char
329
10
    version[MagickPathExtent];
330
331
10
  MagickInfo
332
10
    *entry;
333
334
10
  *version='\0';
335
10
#if defined(FREETYPE_MAJOR) && defined(FREETYPE_MINOR) && defined(FREETYPE_PATCH)
336
10
  (void) FormatLocaleString(version,MagickPathExtent,"Freetype %d.%d.%d",
337
10
    FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH);
338
10
#endif
339
10
  entry=AcquireMagickInfo("TTF","DFONT","Multi-face font package");
340
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
341
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
342
10
#endif
343
10
  entry->magick=(IsImageFormatHandler *) IsTTF;
344
10
  entry->flags^=CoderAdjoinFlag;
345
10
  if (*version != '\0')
346
10
    entry->version=ConstantString(version);
347
10
  (void) RegisterMagickInfo(entry);
348
10
  entry=AcquireMagickInfo("TTF","PFA","Postscript Type 1 font (ASCII)");
349
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
350
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
351
10
#endif
352
10
  entry->magick=(IsImageFormatHandler *) IsPFA;
353
10
  entry->flags^=CoderAdjoinFlag;
354
10
  if (*version != '\0')
355
10
    entry->version=ConstantString(version);
356
10
  (void) RegisterMagickInfo(entry);
357
10
  entry=AcquireMagickInfo("TTF","PFB","Postscript Type 1 font (binary)");
358
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
359
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
360
10
#endif
361
10
  entry->magick=(IsImageFormatHandler *) IsPFA;
362
10
  entry->flags^=CoderAdjoinFlag;
363
10
  if (*version != '\0')
364
10
    entry->version=ConstantString(version);
365
10
  (void) RegisterMagickInfo(entry);
366
10
  entry=AcquireMagickInfo("TTF","OTF","Open Type font");
367
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
368
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
369
10
#endif
370
10
  entry->magick=(IsImageFormatHandler *) IsTTF;
371
10
  entry->flags^=CoderAdjoinFlag;
372
10
  if (*version != '\0')
373
10
    entry->version=ConstantString(version);
374
10
  (void) RegisterMagickInfo(entry);
375
10
  entry=AcquireMagickInfo("TTF","TTC","TrueType font collection");
376
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
377
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
378
10
#endif
379
10
  entry->magick=(IsImageFormatHandler *) IsTTF;
380
10
  entry->flags^=CoderAdjoinFlag;
381
10
  if (*version != '\0')
382
10
    entry->version=ConstantString(version);
383
10
  (void) RegisterMagickInfo(entry);
384
10
  entry=AcquireMagickInfo("TTF","TTF","TrueType font");
385
10
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
386
10
  entry->decoder=(DecodeImageHandler *) ReadTTFImage;
387
10
#endif
388
10
  entry->magick=(IsImageFormatHandler *) IsTTF;
389
10
  entry->flags^=CoderAdjoinFlag;
390
10
  if (*version != '\0')
391
10
    entry->version=ConstantString(version);
392
10
  (void) RegisterMagickInfo(entry);
393
10
  return(MagickImageCoderSignature);
394
10
}
395

396
/*
397
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398
%                                                                             %
399
%                                                                             %
400
%                                                                             %
401
%   U n r e g i s t e r T T F I m a g e                                       %
402
%                                                                             %
403
%                                                                             %
404
%                                                                             %
405
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406
%
407
%  UnregisterTTFImage() removes format registrations made by the
408
%  TTF module from the list of supported formats.
409
%
410
%  The format of the UnregisterTTFImage method is:
411
%
412
%      UnregisterTTFImage(void)
413
%
414
*/
415
ModuleExport void UnregisterTTFImage(void)
416
0
{
417
0
  (void) UnregisterMagickInfo("TTF");
418
0
  (void) UnregisterMagickInfo("TTC");
419
0
  (void) UnregisterMagickInfo("OTF");
420
0
  (void) UnregisterMagickInfo("PFA");
421
0
  (void) UnregisterMagickInfo("PFB");
422
0
  (void) UnregisterMagickInfo("PFA");
423
0
  (void) UnregisterMagickInfo("DFONT");
424
0
}