File Coverage

blib/lib/PDF/Builder/FontManager.pm
Criterion Covered Total %
statement 70 343 20.4
branch 18 154 11.6
condition 16 48 33.3
subroutine 7 13 53.8
pod 6 6 100.0
total 117 564 20.7


line stmt bran cond sub pod time code
1             package PDF::Builder::FontManager;
2              
3 38     38   320 use strict;
  38         113  
  38         1278  
4 38     38   219 use warnings;
  38         98  
  38         1975  
5              
6             our $VERSION = '3.025'; # VERSION
7             our $LAST_UPDATE = '3.025'; # manually update whenever code is changed
8              
9 38     38   260 use Carp;
  38         85  
  38         2475  
10 38     38   301 use Scalar::Util qw(weaken);
  38         142  
  38         162113  
11              
12             # unless otherwise noted, routines beginning with _ are internal helper
13             # functions and should not be used by others
14             #
15             # TBD (future)
16             # spec use of synfont() against a base to get
17             # fake bold, italic, bold+italic
18             # small caps, perhaps petite caps
19             # condensed and expanded (or via hscale())
20             # support for UTF-8 subfonts for single byte encoding fonts
21              
22             =head1 NAME
23              
24             PDF::Builder::FontManager - Managing the font library for PDF::Builder
25              
26             =head1 SYNOPSIS
27              
28             These routines are called from the PDF::Builder class (see C
29             add_font()> methods).
30              
31             # core fonts come pre-loaded
32             # Add new a new font face and variants
33             my $rc = $pdf->add_font(
34             'face' => $unique_face_name, # font family, e.g., Times
35             'type' => 'core', # note that core fonts preloaded
36             'style' => 'serif', # also sans-serif, script (cursive),
37             # and symbol
38             'width' => 'proportional', # also constant
39             'settings' => { 'encode' => $encoding },
40             # note that these are actual core font names rather than file paths
41             'file' => { 'roman' => 'Times-Roman',
42             'italic' => 'Times-Italic',
43             'bold' => 'Times-Bold',
44             'bold-italic' => 'Times-BoldItalic' },
45             # for non-core these would be the actual file paths
46             # prefixed with font search paths
47             );
48             $rc = $pdf->add_font(
49             'face' => 'DejaVuSans', # Deja Vu sans serif family
50             'type' => 'ttf', # otf uses 'ttf'
51             'style' => 'sans-serif',
52             'width' => 'proportional',
53             'settings' => { 'encode' => 'utf8' },
54             # the defined font paths will be prepended to find the actual path
55             'file' => { 'roman' => 'DejaVuSans.ttf',
56             'italic' => 'DejaVuSans-Oblique.ttf',
57             'bold' => 'DejaVuSans-Bold.ttf',
58             'bold-italic' => 'DejaVuSans-BoldOblique.ttf' }
59             );
60              
61             Some of the global data, which can be reset via the C method:
62              
63             * default-face: initialized to Times-Roman (core), used if you start
64             formatting text without explicitly setting a face
65             * default-serif: initialized to Times-Roman (core), used if you want
66             a "generic" serif typeface
67             * default-sansserif: initialized to Helvetica (core), used if you want
68             a "generic" sans-serif typeface
69             * default-constant: initialized to Courier (core), used if you want
70             a "generic" constant-width typeface
71             * default-script: NOT initialized (no default), used if you want
72             a "generic" script (cursive) typeface
73             * default-symbol initialized to Symbol (core), used if you want
74             a "generic" symbol typeface
75             * font-paths: C:/Windows/Fonts for Windows systems for TTF, other types
76             are in non-standard paths, and for non-Windows, anything goes
77              
78             Usage of C is to specify the face and variants, and then each time,
79             specify I and I to be on or off. If the desired file is not yet
80             opened, it will be, and the C<$font> returned. If the font was already
81             created earlier, the saved C<$font> will be returned.
82              
83             my $font = $pdf->get_font(
84             'face' => 'Times',
85             'italic' => 0, # desire Roman (upright)
86             'bold' => 0, # desire medium weight
87             );
88             # if $font is undef, we have a problem...
89             $text->font($font, $font_size);
90             $text->... # use this font (medium weight Times-Roman core font)
91             $font = $pdf->get_font('italic' => 1);
92             $text->... # switched to italic
93             $font = $pdf->get_font('italic' => 0);
94             $text->... # back to Roman (upright) text
95              
96             =head1 METHODS
97              
98             =over
99              
100             =item PDF::Builder::FontManager->new(%opts)
101              
102             This is called from Builder.pm's C. Currently there are no options
103             selectable. It will set up the font manager system and preload it with the
104             core fonts. Various defaults will be set for the face (core Times-Roman),
105             serif face (core Times-Roman), sans-serif face (core Helvetica), constant
106             width (fixed pitch) face (core Courier), and a symbol font (core Symbol).
107             There is no default for a script (cursive) font unless you set one using
108             the C method.
109              
110             =cut
111              
112             sub new {
113 217     217 1 554 my ($class, $pdf) = @_;
114              
115 217         660 my $self = bless { 'pdf' => $pdf }, $class;
116 217         1152 weaken $self->{'pdf'};
117             #$pdf = $pdf->{'pdf'} if $pdf->isa('PDF::Builder');
118             #$class = ref($class) if ref($class);
119             #my $self = $class->SUPER::new($pdf);
120 217         501 $self->{' pdf'} = $pdf;
121              
122             # current font is default font until face explicitly changed.
123             # Times face should be element 0 of the font-list array.
124 217         930 $self->{' current-font'} = {'face' => 'Times', 'index' => 0,
125             'italic' => 0, 'bold' => 0};
126             # just the face to use. index assumes standard core initialization
127 217         701 $self->{' default-font'} = {'face' => 'Times', 'index' => 0};
128 217         634 $self->{' default-serif'} = {'face' => 'Times', 'index' => 0};
129 217         595 $self->{' default-sansserif'} = {'face' => 'Helvetica', 'index' => 1};
130 217         545 $self->{' default-constant'} = {'face' => 'Courier', 'index' => 2};
131 217         804 $self->{' default-symbol'} = {'face' => 'Symbol', 'index' => 3};
132             # no script font loaded by default
133 217         617 $self->{' default-script'} = {'face' => undef, 'index' => -1};
134 217         506 $self->{' font-paths'} = [];
135              
136 217         448 $self->{' font-list'} = [];
137              
138             # For Windows, can at least initialize to TTF place. Any additional fonts
139             # for Windows, and all non-Windows paths, will have to be added by the
140             # user. Note that an absolute (starts with /) or semi-absolute (starts
141             # with ./ or ../) font path/file will NOT have any search paths
142             # prepended!
143 217         372 push @{$self->{' font-paths'}}, $pdf->font_path();
  217         844  
144             # can add any additional paths, but better to do in Builder.pm
145              
146 217         838 $self->_initialize_core();
147              
148 217         700 return $self;
149             } # end of new()
150              
151             =item @list = $pdf->font_settings() # Get
152              
153             =item $pdf->font_settings(%info) # Set
154              
155             Get or set some information about fonts, particularly the fonts to be used for
156             "generic" purposes.
157              
158             "Get" returns a list (array) of the default font face name, the default generic
159             serif face, the default generic sans-serif face, the default generic constant
160             width face, the default generic symbol face, and the default generic script
161             (cursive) face. It is possible for an element to be undefined (e.g., the
162             generic script face is C).
163              
164             "Set" changes one or more default settings:
165              
166             'font' => face to use for the default font face (initialized to Times)
167             'serif' => face to use for the generic serif face (initialized to Times)
168             'sans-serif' => face to use for the generic sans serif face
169             (initialized to Helvetica)
170             'constant' => face to use for the generic constant width face
171             (initialized to Courier)
172             'script' => face to use for the generic script face (uninitialized)
173             'symbol' => face to use for the generic symbol face
174             (initialized to Symbol)
175              
176             =cut
177              
178             sub font_settings {
179 0     0 1 0 my ($self, %info) = @_;
180              
181 0 0       0 if (!keys %info) {
182             # Get default faces, nothing passed in
183             return (
184             $self->{' default-font'}->{'face'},
185             $self->{' default-serif'}->{'face'},
186             $self->{' default-sansserif'}->{'face'},
187             $self->{' default-constant'}->{'face'},
188             $self->{' default-script'}->{'face'},
189 0         0 $self->{' default-symbol'}->{'face'},
190             );
191             }
192              
193             # Set default info from %info passed in
194             # also check if face exists, and at same time pick up the index value
195 0         0 my $index;
196 0 0       0 if (defined $info{'font'}) {
197 0         0 $index = $self->_face2index($info{'font'});
198 0 0       0 if ($index >= 0) {
199 0         0 $self->{' default-font'}->{'face'} = $info{'font'};
200 0         0 $self->{' default-font'}->{'index'} = $index;
201             } else {
202 0         0 carp "font_settings can't find face $info{'font'}. ignored.";
203             }
204             }
205 0 0       0 if (defined $info{'serif'}) {
206 0         0 $index = $self->_face2index($info{'serif'});
207 0 0       0 if ($index >= 0) {
208 0         0 $self->{' default-serif'}->{'face'} = $info{'serif'};
209 0         0 $self->{' default-serif'}->{'index'} = $index;
210             } else {
211 0         0 carp "font_settings can't find face $info{'serif'}. ignored.";
212             }
213             }
214 0 0       0 if (defined $info{'sans-serif'}) {
215 0         0 $index = $self->_face2index($info{'sans-serif'});
216 0 0       0 if ($index >= 0) {
217 0         0 $self->{' default-sansserif'}->{'face'} = $info{'sans-serif'};
218 0         0 $self->{' default-sansserif'}->{'index'} = $index;
219             } else {
220 0         0 carp "font_settings can't find face $info{'sans-serif'}. ignored.";
221             }
222             }
223 0 0       0 if (defined $info{'constant'}) {
224 0         0 $index = $self->_face2index($info{'constant'});
225 0 0       0 if ($index >= 0) {
226 0         0 $self->{' default-constant'}->{'face'} = $info{'constant'};
227 0         0 $self->{' default-constant'}->{'index'} = $index;
228             } else {
229 0         0 carp "font_settings can't find face $info{'constant'}. ignored.";
230             }
231             }
232 0 0       0 if (defined $info{'script'}) {
233 0         0 $index = $self->_face2index($info{'script'});
234 0 0       0 if ($index >= 0) {
235 0         0 $self->{' default-script'}->{'face'} = $info{'script'};
236 0         0 $self->{' default-script'}->{'index'} = $index;
237             } else {
238 0         0 carp "font_settings can't find face $info{'script'}. ignored.";
239             }
240             }
241 0 0       0 if (defined $info{'symbol'}) {
242 0         0 $index = $self->_face2index($info{'symbol'});
243 0 0       0 if ($index >= 0) {
244 0         0 $self->{' default-symbol'}->{'face'} = $info{'symbol'};
245 0         0 $self->{' default-symbol'}->{'index'} = $index;
246             } else {
247 0         0 carp "font_settings can't find face $info{'symbol'}. ignored.";
248             }
249             }
250              
251 0         0 return;
252             }
253              
254             =item $rc = $pdf->add_font_path("a directory path", %opts)
255              
256             This method adds one search path to the list of paths to search. In the
257             C method, each defined search path will be prepended to the C
258             entry (except for core fonts) in turn, until the font file is found. However,
259             if the C entry starts with / or ./ or ../, it will be used alone.
260             A C entry starting with .../ is a special case, which is turned into ../
261             before the search path is prepended. This permits you to give a search path
262             that you expect to move up one or more directories.
263              
264             The font path search list always includes the current directory (.), and is
265             initialized in C as C<@font_path>. For the
266             Windows operating system, C usually contains a number of TTF
267             fonts that come standard with Windows, so it is added by default. Anything
268             else, including all Linux (and other non-Windows operating systems), will have
269             to be added depending on your particular system. Some common places are:
270              
271             Windows (B use / and not \\ in Windows paths!). Linux systems may or
272             may not handle spaces in directory names gracefully!
273              
274             /Windows/Fonts
275             /WinNT/Fonts
276             /Program Files/MikTex 2.9/fonts/type1/urw/bookman (URW Bookman for MikTex)
277             /Program Files (x86)/MikTex 2.9/fonts/type1/urw/bookman (older versions)
278             /Program Files/Adobe/Acrobat DC/Resource/CIDFont (Adobe Reader fonts)
279             GhostScript may have its own directories
280              
281             Note that directory names with spaces (e.g., C) may not play
282             nice with some Linux systems, so they are not included by default.
283              
284             Linux, etc.
285              
286             /usr/share/fonts (common base)
287             /usr/local/share/fonts (common base)
288             /usr/share/fonts/dejavu-sans-fonts (Deja Vu Sans TTF specifically)
289             /usr/share/fonts/truetype/ttf-dejavu
290             /usr/share/fonts/truetype/dejavu
291             /usr/lib/defoma/gs.d/devs/fonts (GhostScript?)
292             /usr/share/fonts/type1/gsfonts (GhostScript PS)
293             /usr/share/X11/fonts/urw-fonts (URW PS)
294              
295             Third-party application installations, such as Adobe's Acrobat Reader, may be
296             a source of installed fonts, too.
297              
298             A return code of 0 means the path was successfully added, while 1 means there
299             was a problem encountered (and a message was issued).
300              
301             No options are currently defined.
302              
303             =cut
304              
305             sub add_font_path {
306 0     0 1 0 my ($self, $newpath, %opts) = @_;
307              
308 0         0 my $rc = 0; # OK so far!
309              
310             # TBD: consider validating that this $newpath exists?
311             # will not be using until actually attempt to open the file!
312 0         0 push @{ $self->{' font-paths'} }, $newpath;
  0         0  
313              
314 0         0 return $rc;
315             } # end of add_font_path()
316              
317             =item $rc = add_font(%info)
318              
319             Add a new font entry (by face and variants) to the Font Manager's list of
320             known fonts.
321              
322             C<%info> items to be defined:
323              
324             =over
325              
326             =item face => 'face name'
327              
328             This should be a unique string to identify just one entry in the Font
329             Manager fonts table. I.e., you should not have two "Times" (one a core font
330             and the other a TTF font). Give them different names (face names are case
331             I, so 'Times' is different from 'times'). The C name is
332             used to retrieve the desired font.
333              
334             =item type => 'type string'
335              
336             This tells which Builder font routine to use to load the font. The allowed
337             entries are:
338              
339             =over
340              
341             =item B
342              
343             This is a core font, and is loaded via the C routine. Note that
344             the core fonts are automatically pre-loaded (including additional ones on
345             Windows systems), so you should not need to explicitly load any core fonts
346             (at least, the 14 basic ones). All PDF installation are supposed to include
347             these 14 basic core fonts, but the precise actual file type may vary among
348             installations, and substitutions may be made (so long as the metrics match).
349             Currently, core fonts are limited to single byte encodings.
350              
351             On Windows systems, there are an additional 14 core fonts which are normally
352             loaded. These are Georgia, Verdana, Trebuchet, Wingdings, and Webdings faces.
353             Use caution if making use of these additional core fonts, as non-Windows
354             systems may not include them without explicit manual installation of these
355             fonts. These fonts may be safe to use if you know that all your PDF readers
356             will be running on Windows systems.
357              
358             =item B
359              
360             This is a TrueType (.ttf) or OpenType (.otf) font, loaded with C.
361             Currently this is the only
362             type which can be used with multibyte (e.g., I) encodings, as well as
363             with single byte encodings such as I. It is also the only font type
364             that can be used with HarfBuzz::Shaper. Many systems include a number of TTF
365             fonts, but unlike core fonts, none are automatically loaded by the PDF::Builder
366             Font Manager, and must be explicitly loaded via C.
367              
368             =item B
369              
370             This is a PostScript (Type1) font, loaded with C, which used to be
371             quite commonly used, but is
372             fairly rarely used today, having mostly been supplanted by the more capable
373             TTF format. Some systems may include some Type1 fonts, but Windows,
374             for example, does not normally come with any. No Type1 fonts are automatically
375             loaded by the PDF::Builder Font Manager, and must be explicitly loaded via
376             C.
377              
378             It is assumed that the font metrics file (.afm or .pfm) has the same base file
379             name as the glyph file (.pfa or .pfb), is found in the same directory, I
380             either can work with either.
381             If you have need for a different directory, a different base name, or a
382             specific metrics file to go with a specific glyph file, let us know, so we can
383             add such functionality. Otherwise, you will need to directly use the C
384             method in order to specify such different paths.
385              
386             =item B
387              
388             This is an East Asian (Chinese-Japanese-Korean) type font, loaded with the
389             C method. Note that CJK fonts
390             have never been well supported by PDF::Builder, and depend on some fairly old
391             (obsolete) features and external files (.cmap and .data). We suggest that,
392             rather than going directly to CJK files, you first try directly using the
393             (usually) TTF files, in the TTF format. Few systems come with CJK fonts
394             installed. No CJK fonts are automatically loaded by the PDF::Builder Font
395             Manager, and must be explicitly loaded via C.
396              
397             =item B
398              
399             This is an Adobe Bitmap Distribution Format font, loaded with the C
400             method, a very old bitmapped format
401             dating back to the early days of the X11 system. Unlike the filled smooth
402             outlines used in most modern fonts, BDF's are a coarse grid of on/off pixels.
403             Please be kind to your readers and use this format sparingly, such as only for
404             chapter titles or headings! Few systems come with BDF fonts installed any more.
405             No BDF fonts are automatically loaded by the PDF::Builder Font Manager, and
406             must be explicitly loaded via C.
407              
408             =back
409              
410             =item settings => { 'encode' => string, ... }
411              
412             This is a collection of any other settings, flags, etc. accepted by this
413             particular font type. See the POD for C, C, etc. (per
414             I for the allowable entries. An important one will be the encoding,
415             which you will need to specify, if you use any characters beyond basic ASCII.
416              
417             Currently, all fonts may use any single byte encoding you
418             desire (the default is I). Only TTF type fonts (which includes OTF and
419             CJK fonts) may currently specify a multibyte encoding such as I. Needless
420             to say, the text data that you pass to text routines must conform to the given
421             encoding. You are I forced to use the same encoding for all defined fonts,
422             but if you wish to mix-and-match encodings, it is up to you to define your
423             text that uses the encoding specified for the particular font used!
424              
425             Note in particular when you use I that (if numeric) they are given
426             in the Unicode number. When out of the single byte range (x00-xFF), results are
427             unpredictable if you give an entity that does not fall within the encoding's
428             range! Also check results for Unicode points within the range x80-xFF if you
429             are using I encoding.
430              
431             =item style => 'styling'
432              
433             This specifies the styling of the font: B, B, B
434             (constant width, or fixed pitch), B