1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominik Seichter                                *
3  *   domseichter@web.de                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Library General Public License as       *
7  *   published by the Free Software Foundation; either version 2 of the    *
8  *   License, or (at your option) any later version.                       *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Library General Public     *
16  *   License along with this program; if not, write to the                 *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  *                                                                         *
20  *   In addition, as a special exception, the copyright holders give       *
21  *   permission to link the code of portions of this program with the      *
22  *   OpenSSL library under certain conditions as described in each         *
23  *   individual source file, and distribute linked combinations            *
24  *   including the two.                                                    *
25  *   You must obey the GNU General Public License in all respects          *
26  *   for all of the code used other than OpenSSL.  If you modify           *
27  *   file(s) with this exception, you may extend this exception to your    *
28  *   version of the file(s), but you are not obligated to do so.  If you   *
29  *   do not wish to do so, delete this exception statement from your       *
30  *   version.  If you delete this exception statement from all source      *
31  *   files in the program, then also delete it here.                       *
32  ***************************************************************************/
33 
34 #ifndef _PDF_FONT_METRICS_H_
35 #define _PDF_FONT_METRICS_H_
36 
37 #include "podofo/base/PdfDefines.h"
38 #include "podofo/base/Pdf3rdPtyForwardDecl.h"
39 #include "podofo/base/PdfString.h"
40 #include "podofo/base/PdfEncoding.h"
41 
42 namespace PoDoFo {
43 
44 class PdfArray;
45 class PdfObject;
46 class PdfVariant;
47 
48 /**
49  * This abstract class provides access
50  * to fontmetrics informations.
51  */
52 class PODOFO_DOC_API PdfFontMetrics {
53  public:
54     PdfFontMetrics( EPdfFontType eFontType, const char* pszFilename, const char* pszSubsetPrefix );
55 
56 
57     virtual ~PdfFontMetrics();
58 
59     /** Create a width array for this font which is a required part
60      *  of every font dictionary.
61      *  \param var the final width array is written to this PdfVariant
62      *  \param nFirst first character to be in the array
63      *  \param nLast last character code to be in the array
64      *  \param pEncoding encoding for correct character widths. If not passed default (latin1) encoding is used
65      */
66     virtual void GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast, const PdfEncoding* pEncoding = NULL ) const = 0;
67 
68     /** Get the width of a single glyph id
69      *
70      *  \param nGlyphId id of the glyph
71      *  \returns the width of a single glyph id
72      */
73     virtual double GetGlyphWidth( int nGlyphId ) const = 0;
74 
75     /** Get the width of a single named glyph
76      *
77      *  \param pszGlyphname name of the glyph
78      *  \returns the width of a single named glyph
79      */
80     virtual double GetGlyphWidth( const char* pszGlyphname ) const = 0;
81 
82     /** Create the bounding box array as required by the PDF reference
83      *  so that it can be written directly to a PDF file.
84      *
85      *  \param array write the bounding box to this array.
86      */
87     virtual void GetBoundingBox( PdfArray & array ) const = 0;
88 
89     /** Retrieve the width of a given text string in PDF units when
90      *  drawn with the current font
91      *  \param rsString a PdfString from which the width shall be calculated
92      *  \returns the width in PDF units
93      *
94      *  This is an overloaded method for your convinience!
95      */
96     inline double StringWidth( const PdfString & rsString ) const;
97 
98     /** Retrieve the width of a given text string in PDF units when
99      *  drawn with the current font
100      *  \param pszText a text string of which the width should be calculated
101      *  \param nLength if != 0 only the width of the nLength first characters is calculated
102      *  \returns the width in PDF units
103      */
104     double StringWidth( const char* pszText, pdf_long nLength = 0 ) const;
105 
106     /** Retrieve the width of a given text string in PDF units when
107      *  drawn with the current font
108      *  \param pszText a text string of which the width should be calculated
109      *  \param nLength if != 0 only the width of the nLength first characters is calculated
110      *  \returns the width in PDF units
111      */
112     double StringWidth( const pdf_utf16be* pszText, unsigned int nLength = 0 ) const;
113 
114 #ifndef _WCHAR_T_DEFINED
115 #if defined(_MSC_VER)  &&  _MSC_VER <= 1200    // not for MS Visual Studio 6
116 #else
117     /** Retrieve the width of a given text string in PDF units when
118      *  drawn with the current font
119      *  \param pszText a text string of which the width should be calculated
120      *  \param nLength if != 0 only the width of the nLength first characters is calculated
121      *  \returns the width in PDF units
122      */
123     double StringWidth( const wchar_t* pszText, unsigned int nLength = 0 ) const;
124 #endif
125 #endif
126 
127     /** Retrieve the width of a given text string in 1/1000th mm when
128      *  drawn with the current font
129      *  \param pszText a text string of which the width should be calculated
130      *  \param nLength if != 0 only the width of the nLength first characters is calculated
131      *  \returns the width in 1/1000th mm
132      */
133     inline unsigned long StringWidthMM( const char* pszText, unsigned int nLength = 0 ) const;
134 
135     /** Retrieve the width of a given text string in 1/1000th mm when
136      *  drawn with the current font
137      *  \param pszText a text string of which the width should be calculated
138      *  \param nLength if != 0 only the width of the nLength first characters is calculated
139      *  \returns the width in 1/1000th mm
140      */
141     inline unsigned long StringWidthMM( const pdf_utf16be* pszText, unsigned int nLength = 0 ) const;
142 
143 #ifndef _WCHAR_T_DEFINED
144 #if defined(_MSC_VER)  &&  _MSC_VER <= 1200    // not for MS Visual Studio 6
145 #else
146     /** Retrieve the width of a given text string in 1/1000th mm when
147      *  drawn with the current font
148      *  \param pszText a text string of which the width should be calculated
149      *  \param nLength if != 0 only the width of the nLength first characters is calculated
150      *  \returns the width in 1/1000th mm
151      */
152     inline unsigned long StringWidthMM( const wchar_t* pszText, unsigned int nLength = 0 ) const;
153 #endif
154 #endif
155 
156     /** Retrieve the width of the given character in PDF units in the current font
157      *  \param c character
158      *  \returns the width in PDF units
159      */
160     virtual double CharWidth( unsigned char c ) const = 0;
161 
162     // Peter Petrov 20 March 2009
163     /** Retrieve the width of the given character in PDF units in the current font
164      *  \param c character
165      *  \returns the width in PDF units
166      */
167     virtual double UnicodeCharWidth( unsigned short c ) const = 0;
168 
169     /** Retrieve the width of the given character in 1/1000th mm in the current font
170      *  \param c character
171      *  \returns the width in 1/1000th mm
172      */
173     inline unsigned long CharWidthMM( unsigned char c ) const;
174 
175     /** Retrieve the line spacing for this font
176      *  \returns the linespacing in PDF units
177      */
178     virtual double GetLineSpacing() const = 0;
179 
180     /** Retrieve the line spacing for this font
181      *  \returns the linespacing in 1/1000th mm
182      */
183     inline unsigned long GetLineSpacingMM() const;
184 
185     /** Get the width of the underline for the current
186      *  font size in PDF units
187      *  \returns the thickness of the underline in PDF units
188      */
189     virtual double GetUnderlineThickness() const = 0;
190 
191     /** Get the width of the underline for the current
192      *  font size in 1/1000th mm
193      *  \returns the thickness of the underline in 1/1000th mm
194      */
195     inline unsigned long GetUnderlineThicknessMM() const;
196 
197     /** Return the position of the underline for the current font
198      *  size in PDF units
199      *  \returns the underline position in PDF units
200      */
201     virtual double GetUnderlinePosition() const = 0;
202 
203     /** Return the position of the underline for the current font
204      *  size in 1/1000th mm
205      *  \returns the underline position in 1/1000th mm
206      */
207     inline long GetUnderlinePositionMM() const;
208 
209     /** Return the position of the strikeout for the current font
210      *  size in PDF units
211      *  \returns the underline position in PDF units
212      */
213     virtual double GetStrikeOutPosition() const = 0;
214 
215     /** Return the position of the strikeout for the current font
216      *  size in 1/1000th mm
217      *  \returns the underline position in 1/1000th mm
218      */
219     inline unsigned long GetStrikeOutPositionMM() const;
220 
221     /** Get the width of the strikeout for the current
222      *  font size in PDF units
223      *  \returns the thickness of the strikeout in PDF units
224      */
225     virtual double GetStrikeoutThickness() const = 0;
226 
227     /** Get the width of the strikeout for the current
228      *  font size in 1/1000th mm
229      *  \returns the thickness of the strikeout in 1/1000th mm
230      */
231     inline unsigned long GetStrikeoutThicknessMM() const;
232 
233     /** Get a pointer to the path of the font file.
234      *  \returns a zero terminated string containing the filename of the font file
235      */
236     inline const char* GetFilename() const;
237 
238     /** Get a pointer to the actual font data - if it was loaded from memory.
239      *  \returns a binary buffer of data containing the font data
240      */
241     virtual const char* GetFontData() const = 0;
242 
243     /** Get the length of the actual font data - if it was loaded from memory.
244      *  \returns a the length of the font data
245      */
246     virtual pdf_long GetFontDataLen() const = 0;
247 
248     /** Get a string with the postscript name of the font.
249      *  \returns the postscript name of the font or NULL string if no postscript name is available.
250      */
251     virtual const char* GetFontname() const = 0;
252 
253     /**
254      * \returns NULL or a 6 uppercase letter and "+" sign prefix
255      *          used for font subsets
256      */
257     inline const char* GetSubsetFontnamePrefix() const;
258 
259     /** Get the weight of this font.
260      *  Used to build the font dictionay
261      *  \returns the weight of this font (500 is normal).
262      */
263     virtual  unsigned int GetWeight() const = 0;
264 
265     /** Get the ascent of this font in PDF
266      *  units for the current font size.
267      *
268      *  \returns the ascender for this font
269      *
270      *  \see GetPdfAscent
271      */
272     virtual double GetAscent() const = 0;
273 
274     /** Get the ascent of this font
275      *  Used to build the font dictionay
276      *  \returns the ascender for this font
277      *
278      *  \see GetAscent
279      */
280     virtual double GetPdfAscent() const = 0;
281 
282     /** Get the descent of this font in PDF
283      *  units for the current font size.
284      *  This value is usually negative!
285      *
286      *  \returns the descender for this font
287      *
288      *  \see GetPdfDescent
289      */
290     virtual double GetDescent() const = 0;
291 
292     /** Get the descent of this font
293      *  Used to build the font dictionay
294      *  \returns the descender for this font
295      *
296      *  \see GetDescent
297      */
298     virtual double GetPdfDescent() const = 0;
299 
300     /** Get the italic angle of this font.
301      *  Used to build the font dictionay
302      *  \returns the italic angle of this font.
303      */
304     virtual int GetItalicAngle() const = 0;
305 
306     /** Set the font size of this metrics object for width and height
307      *  calculations.
308      *  This is typically called from PdfFont for you.
309      *
310      *  \param fSize font size in points
311      */
312     inline void SetFontSize( float fSize );
313 
314     /** Retrieve the current font size of this metrics object
315      *  \returns the current font size
316      */
317     inline float GetFontSize() const;
318 
319     /** Set the horizontal scaling of the font for compressing (< 100) and expanding (>100)
320      *  This is typically called from PdfFont for you.
321      *
322      *  \param fScale scaling in percent
323      */
324     inline void SetFontScale( float fScale );
325 
326     /** Retrieve the current horizontal scaling of this metrics object
327      *  \returns the current font scaling
328      */
329     inline float GetFontScale() const;
330 
331     /** Set the character spacing of this metrics object
332      *  \param fCharSpace character spacing in percent
333      */
334     inline void SetFontCharSpace( float fCharSpace );
335 
336     /** Retrieve the current character spacing of this metrics object
337      *  \returns the current font character spacing
338      */
339     inline float GetFontCharSpace() const;
340 
341     /** Set the word spacing of this metrics object
342      *  \param fWordSpace word spacing in PDF units
343      */
344     inline void SetWordSpace( float fWordSpace );
345 
346     /** Retrieve the current word spacing of this metrics object
347      *  \returns the current font word spacing in PDF units
348      */
349     inline float GetWordSpace() const;
350 
351     /**
352      *  \returns the fonttype of the loaded font
353      */
354     inline EPdfFontType GetFontType() const;
355 
356     /** Get the glyph id for a unicode character
357      *  in the current font.
358      *
359      *  \param lUnicode the unicode character value
360      *  \returns the glyhph id for the character or 0 if the glyph was not found.
361      */
362     virtual long GetGlyphId( long lUnicode ) const = 0;
363 
364     /** Symbol fonts do need special treatment in a few cases.
365      *  Use this method to check if the current font is a symbol
366      *  font. Symbold fonts are detected by checking
367      *  if they use FT_ENCODING_MS_SYMBOL as internal encoding.
368      *
369      * \returns true if this is a symbol font
370      */
371     virtual bool IsSymbol() const = 0;
372 
373     /** Try to detect the internal fonttype from
374      *  the file extension of a fontfile.
375      *
376      *  \param pszFilename must be the filename of a font file
377      *
378      *  \return font type
379      */
380     static EPdfFontType FontTypeFromFilename( const char* pszFilename );
381 
382  protected:
383     /**
384      *  Set the fonttype.
385      *  \param eFontType fonttype
386      */
387     inline void SetFontType(EPdfFontType eFontType);
388 
389  protected:
390     std::string   m_sFilename;
391     float         m_fFontSize;
392     float         m_fFontScale;
393     float         m_fFontCharSpace;
394     float         m_fWordSpace;
395 
396     std::vector<double> m_vecWidth;
397 
398     EPdfFontType  m_eFontType;
399     std::string   m_sFontSubsetPrefix;
400 };
401 
402 // -----------------------------------------------------
403 //
404 // -----------------------------------------------------
CharWidthMM(unsigned char c)405 unsigned long PdfFontMetrics::CharWidthMM( unsigned char c ) const
406 {
407     return static_cast<unsigned long>(this->CharWidth( c ) / PODOFO_CONVERSION_CONSTANT);
408 }
409 
410 // -----------------------------------------------------
411 //
412 // -----------------------------------------------------
StringWidth(const PdfString & rsString)413 double PdfFontMetrics::StringWidth( const PdfString & rsString ) const
414 {
415     return (rsString.IsUnicode() ?  this->StringWidth( rsString.GetUnicode() ) : this->StringWidth( rsString.GetString() ));
416 }
417 
418 // -----------------------------------------------------
419 //
420 // -----------------------------------------------------
StringWidthMM(const char * pszText,unsigned int nLength)421 unsigned long PdfFontMetrics::StringWidthMM( const char* pszText, unsigned int nLength ) const
422 {
423     return static_cast<unsigned long>(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT);
424 }
425 
426 // -----------------------------------------------------
427 //
428 // -----------------------------------------------------
StringWidthMM(const pdf_utf16be * pszText,unsigned int nLength)429 unsigned long PdfFontMetrics::StringWidthMM( const pdf_utf16be* pszText, unsigned int nLength ) const
430 {
431     return static_cast<unsigned long>(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT);
432 }
433 
434 // -----------------------------------------------------
435 //
436 // -----------------------------------------------------
437 #ifndef _WCHAR_T_DEFINED
438 #if defined(_MSC_VER)  &&  _MSC_VER <= 1200    // not for MS Visual Studio 6
439 #else
StringWidthMM(const wchar_t * pszText,unsigned int nLength)440 unsigned long PdfFontMetrics::StringWidthMM( const wchar_t* pszText, unsigned int nLength ) const
441 {
442     return static_cast<unsigned long>(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT);
443 }
444 #endif
445 #endif
446 
447 // -----------------------------------------------------
448 //
449 // -----------------------------------------------------
GetLineSpacingMM()450 unsigned long PdfFontMetrics::GetLineSpacingMM() const
451 {
452     return static_cast<unsigned long>(this->GetLineSpacing() / PODOFO_CONVERSION_CONSTANT);
453 }
454 
455 // -----------------------------------------------------
456 //
457 // -----------------------------------------------------
GetUnderlinePositionMM()458 long PdfFontMetrics::GetUnderlinePositionMM() const
459 {
460     return static_cast<long>(this->GetUnderlinePosition() /  PODOFO_CONVERSION_CONSTANT);
461 }
462 
463 // -----------------------------------------------------
464 //
465 // -----------------------------------------------------
GetStrikeOutPositionMM()466 unsigned long PdfFontMetrics::GetStrikeOutPositionMM() const
467 {
468     return static_cast<long>(this->GetStrikeOutPosition() /  PODOFO_CONVERSION_CONSTANT);
469 }
470 
471 // -----------------------------------------------------
472 //
473 // -----------------------------------------------------
GetUnderlineThicknessMM()474 unsigned long PdfFontMetrics::GetUnderlineThicknessMM() const
475 {
476     return static_cast<unsigned long>(this->GetUnderlineThickness() / PODOFO_CONVERSION_CONSTANT);
477 }
478 
479 // -----------------------------------------------------
480 //
481 // -----------------------------------------------------
GetStrikeoutThicknessMM()482 unsigned long PdfFontMetrics::GetStrikeoutThicknessMM() const
483 {
484     return static_cast<unsigned long>(this->GetStrikeoutThickness() / PODOFO_CONVERSION_CONSTANT);
485 }
486 
487 // -----------------------------------------------------
488 //
489 // -----------------------------------------------------
GetFilename()490 const char* PdfFontMetrics::GetFilename() const
491 {
492     return m_sFilename.c_str();
493 }
494 
495 // -----------------------------------------------------
496 //
497 // -----------------------------------------------------
GetFontType()498 EPdfFontType PdfFontMetrics::GetFontType() const
499 {
500     return m_eFontType;
501 }
502 
503 // -----------------------------------------------------
504 //
505 // -----------------------------------------------------
SetFontType(EPdfFontType eFontType)506 void PdfFontMetrics::SetFontType(EPdfFontType eFontType)
507 {
508     m_eFontType = eFontType;
509 }
510 
511 // -----------------------------------------------------
512 //
513 // -----------------------------------------------------
GetFontSize()514 float PdfFontMetrics::GetFontSize() const
515 {
516     return m_fFontSize;
517 }
518 
519 // -----------------------------------------------------
520 //
521 // -----------------------------------------------------
SetFontSize(float fSize)522 void PdfFontMetrics::SetFontSize( float fSize )
523 {
524     m_fFontSize = fSize;
525 }
526 
527 // -----------------------------------------------------
528 //
529 // -----------------------------------------------------
GetFontScale()530 float PdfFontMetrics::GetFontScale() const
531 {
532     return m_fFontScale;
533 }
534 
535 // -----------------------------------------------------
536 //
537 // -----------------------------------------------------
GetFontCharSpace()538 float PdfFontMetrics::GetFontCharSpace() const
539 {
540     return m_fFontCharSpace;
541 }
542 
543 // -----------------------------------------------------
544 //
545 // -----------------------------------------------------
GetWordSpace()546 inline float PdfFontMetrics::GetWordSpace() const
547 {
548     return m_fWordSpace;
549 }
550 
551 // -----------------------------------------------------
552 //
553 // -----------------------------------------------------
GetSubsetFontnamePrefix()554 const char* PdfFontMetrics::GetSubsetFontnamePrefix() const
555 {
556     return m_sFontSubsetPrefix.c_str();
557 }
558 
559 // -----------------------------------------------------
560 //
561 // -----------------------------------------------------
SetFontScale(float fScale)562 void PdfFontMetrics::SetFontScale( float fScale )
563 {
564     m_fFontScale = fScale;
565 }
566 
567 // -----------------------------------------------------
568 //
569 // -----------------------------------------------------
SetFontCharSpace(float fCharSpace)570 void PdfFontMetrics::SetFontCharSpace( float fCharSpace )
571 {
572     m_fFontCharSpace = fCharSpace;
573 }
574 
575 // -----------------------------------------------------
576 //
577 // -----------------------------------------------------
SetWordSpace(float fWordSpace)578 inline void PdfFontMetrics::SetWordSpace( float fWordSpace )
579 {
580     m_fWordSpace = fWordSpace;
581 }
582 
583 
584 };
585 
586 #endif // _PDF_FONT_METRICS_H_
587 
588