Chapter 6: Text and Fonts

Contents

6.1 Overview of Canvas.DrawText method

Text is placed on a canvas via the DrawText method which takes three arguments: a Unicode string containing text to be printed, a parameter object (or parameter string), and a font object. This method returns the number of characters successfully printed. This number may be less than the length of the original string if the whole text did not fit in the space allocated for it.

6.1.1 Bounding Box Parameters

Besides the text and font arguments, the DrawText method takes quite a few numeric and Boolean parameters passed in via a parameter object or parameter string. The only two required parameters are X and Y that specify the coordinates of the upper-left corner of a bounding box inside which the text string will be displayed, as follows:

The vertical distance between the baseline (bottom of capital letters) of the first line of text and the top of the bounding box equals the current font size which is 10 by default (at first). Font size can be specified via the Size parameter. Once font size is explicitly specified, it becomes the default size for this font.

By default, the bounding box extends indefinitely to the right and downwards. If the Width parameter is specified, the bounding box becomes closed on the right, and the DrawText method will perform word wrapping, if necessary. If Width is specified, it is also possible to set Alignment to right (1) or center (2). By default, Alignment is set to left (0). Text justification (alignment on both the left and right sides) is also possible, but only via HTML (see Section 6.4 below).

If both the Width and Height parameter are specified, the bounding box becomes closed from all sides, and only the portion of the text string that fits in the box will be displayed. DrawText will then return the number of characters that were successfully displayed. If even a single line of text cannot fit in the height provided, no text will be displayed at all, and DrawText will return 0.

Example:

Page.Canvas.DrawText "Hello World!", "x=10, y=20; width=400; height=200; size=15; alignment=center", Doc.Fonts("Courier")

6.1.2 Rendering Parameter

The Rendering parameter (0 by default) determines whether showing text causes character outlines to be stroked, filled, used as a clipping boundary, or some combination of the three, as follows:

6.1.3 Other Parameters

Other DrawText parameters include:

Color: a standard color constant (such as red or blue) or a hex RGB value. This parameter is set to black (&H000000) by default.

Angle: specifies the angle (in degrees) by which the text should be rotated counter-clockwise around the upper-left corner of the bounding box. This parameter is set to 0 by default.

Spacing: This parameter controls the distance between individual lines of text. By default, this parameter is 1. Set it to a number greater than 1 to widen the distance between lines, and to a number between 0 and 1 to narrow it down.

Tab: This parameter controls how wide an indent should be when a tab character is encounterd. The indent is measured in space characters. This parameter is 10 by default which means the default tab indent is as wide as 10 space characters.

HTML: If set to True, this parameter informs the DrawText method that the text string is to be treated as HTML. Support for HTML tags is described in detail in Section 6.4 of this chapter. False by default.

ColorSpace, c1, c2, ..., cN: These parameters were introduced in version 2.7 to enable colors from color spaces other than RGB or CMYK to be specified. See Section 16.4 - Using Color Spaces with PdfTable and Other Objects for more info.

The Boolean parameter ReverseHebrewArabic will be described in Section 6.3 of this chapter.

6.1.4 Code Sample: Spanning Multiple Pages

The following code sample displays a user-specified text string on a page, and if it does not fit, more pages are added to the document as necessary:

Set Pdf = Server.CreateObject("Persits.Pdf")
Set Doc = Pdf.CreateDocument
Set page = Doc.Pages.Add( 216, 216 )

Text = Request("largetext")

Set Font = Doc.Fonts("Times-Roman")

Set param = pdf.CreateParam("x=10;y=206;height=196;width=196; size=30;")

Do While Len(Text) > 0
   CharsPrinted = Page.Canvas.DrawText(Text, param, Font)

   if CharsPrinted = Len(Text) Then Exit Do

   Set Page = Page.NextPage
   Text = Right( Text, Len(Text) - CharsPrinted)
Loop

Filename = Doc.Save( Server.MapPath("text.pdf"), False )
IPdfManager objPDF = new PdfManager();
IPdfDocument objDoc = objPDF.CreateDocument(Missing.Value);
IPdfPage objPage = objDoc.Pages.Add(216, 216, Missing.Value);

IPdfFont objFont = objDoc.Fonts["Times-Roman", Missing.Value];
String strText = txtLargeText.Text;
IPdfParam objParam = objPDF.CreateParam("x=10;y=206;height=196;width=196; size=30;");

while( strText.Length > 0 )
{
   int nCharsPrinted = objPage.Canvas.DrawText(strText, objParam, objFont);

   if( nCharsPrinted == strText.Length )
      break;

   objPage = objPage.NextPage;
   strText = strText.Substring( nCharsPrinted );
}

String strFilename = objDoc.Save( Server.MapPath("mask.pdf"), false );

The property Page.NextPage returns the page following this one. If this is the last page, a new page is created.

Click the links below to run this code sample:

6.2 Font Management

The third argument to the DrawText method is an instance of PdfFont, an object that encapsulates a particular font to be used for text rendering. PdfFont objects are obtained via the PdfFonts collection returned by PdfDocument's Fonts property.

A font object can be obtained from the PdfFonts collection in two ways: via the default parameterized Item property, or via the LoadFromFile method. The Item property expects two arguments: a font name, and optionally character set. This property only allows you to retrieve fonts that are currently installed on the machine and appear in the Fonts control panel, and also the 14 built-in PDF fonts (described below).

LoadFromFile, on the other hand, enables you to load TrueType or OpenType fonts from .ttf or .otf files. Such font do not have to be installed on the machine.

6.2.1 The 14 Standard Fonts

All PDF viewer applications are guaranteed to recognize the following 14 fonts, known as the standard fonts:

  • Times-Roman
  • Times-Bold
  • Times-Italic
  • Times-BoldItalic
  • Helvetica
  • Helvetica-Bold
  • Helvetica-Oblique
  • Helvetica-BoldOblique
  • Courier
  • Courier-Bold
  • Courier-Oblique
  • Courier-BoldOblique
  • Symbol
  • ZapfDingbats

To obtain such a font, pass the font name (including a dash character, if applicable) to the PdfFonts.Item property, and omit the 2nd optional argument, for example:

Set Font = Doc.Fonts.Item("Times-Bold")

or simply

Set Font = Doc.Fonts("Times-Bold")

The word Item can be omitted because it is PdfFonts' default property. In C#, the syntax is

IPdfFont objFont = objDoc.Fonts["Times-Bold", Missing.Value]

The advantage of using a standard font as opposed to an arbitrary TrueType font is that the size of your PDF document is reduced because standard fonts do not have to be embedded in the document. However, the standard fonts are limited to only a few simple fonts, and have no support for foreign alphabets. To compensate for these limitations, AspPDF supports the use of arbitrary TrueType or OpenType fonts.

See Appendix B - Special Font Tables for the Symbol and ZapfDingbats glyphs and their respective numeric codes.

6.2.2 Using TrueType Fonts

If anything other than a standard font name is passed to PdfFonts.Item or if the second CharSet argument is set to anything other than 0, the PdfFonts object will look for the specified font supporting the specified character set among the fonts currently installed on the machine. If a font matching these criteria is found, a corresponding PdfFont object is returned. Otherwise, an error exception is thrown.

AspPDF can also open a .ttf or .otf file containing a TrueType or OpenType font directly via the method PdfFonts.LoadFromFile which expects a full path to the font file, as follows:

Set Font = Doc.Fonts.LoadFromFile("c:\windows\fonts\arial.ttf")

As of Version 2.9.0.1, the LoadFromFile method supports TTC files as well, which are TrueType collections containing multiple TrueType fonts. By default, LoadFromFile loads the very first font in the collection. To load an arbitrary font, the 1-based font index must be appended to the TTC path, separated by a comma. The following line of code loads font #2 from the TrueType font collection gulim.ttc:

Set Font = Doc.Fonts.LoadFromFile("c:\windows\fonts\gulim.ttc,2")

A TrueType or OpenType font must contain a Unicode encoding table for AspPDF to be able to use it. An attempt to use a font that does not have such a table will result in an error exception. Most Windows fonts do have it.

AspPDF always embeds a TrueType font in the PDF document it creates. It does so in an optimized manner: only the glyphs (character shapes) that are used by the document are embedded, not the entire font.

6.2.3 Copyright Issues

Just like software, fonts are considered intellectual property and are subject to copyright protection and licensing. If you are using a non-standard font in your PDF document, you must carefully examine this font's embedding licensing rights to avoid potential legal problems.

All TrueType fonts contain embedding flags that indicate embedding licensing rights for the font. The PdfFont object exposes this value via the Embedding property. The possible values are:

  • 0: Installable embedding allowed.
  • 2: Restricted license embedding. No embedding allowed.
  • 6: Print & Preview embedding allowed. Font may be embedded in a document but installed temporarily on remote system. Documents can only be opened read-only.
  • 10: Editable embedding only, fonts may be embedded but must only be installed temporarily on remote system.

The value of 2 prohibits embedding, so we recommend using the following check when using an external font:

Set Font = Doc.Fonts.LoadFromFile("c:\winnt\fonts\somefont.ttf")
If Font.Embedding = 2 Then
   Response.Write "Embedding of this font is prohibited."
   Set Font = Nothing
End If
Note that AspPDF ignores the embedding flags, so it is the application developer's responsibility to perform the licensing rights check shown above. If in doubt, contact the font's vendor.

6.3 Hebrew and Arabic Character Handling

AspPDF's font-related functionality includes support for the Hebrew and Arabic right-to-left alphabets. It also includes the functionality to handle Arabic ligatures.

6.3.1 Right-to-Left Writing

The ReverseHebrewArabic parameter of the DrawText method, if set to True, reverses the sequence of Hebrew and Arabic characters in a text string, while leaving other alphabets' characters and punctuation marks in their regular order. Setting this parameter to True is usually combined with setting the Alignment parameter to right (1) as Hebrew and Arabic texts are usually aligned to the right.

6.3.2 Arabic Ligatures

When Arabic characters are encountered, AspPDF automatically converts individual character codes into "ligatures" (contextual joinings of letters), for example:

6.4 HTML Support

In order to facilitate text formatting, text strings passed to the Canvas.DrawText method may contain certain HTML tags. You must let DrawText know that the string is to be treated as HTML by setting an additional parameter, HTML, to true, e.g.

Canvas.DrawText "For more info, click <A HREF=""http://www.zzz.com""><U>here</U></A>", "x=10; y=20; html=true", Font

6.4.1 Supported Tags and Syntax

The following HTML tags are currently supported:

<A HREF="...">
<B>
<BR>
<CENTER>
<DIV ALIGN="..." STYLE="...">
<FONT SIZE="..." FACE="..." COLOR="...">
<FONT STYLE="...">
<I>
<P>
<SUB>
<SUP>
<U>
<S>

All other tags are ignored. Each attribute value inside a tag must be enclosed in double-quotes, otherwise the attribute will be ignored altogether. All attributes are optional. Tags and attributes are case-insensitive. The CR (13), LF (10) and Tab (9) characters are treated as spaces. Multiple consecutive space characters are treated as a single space.

The SIZE attribute of a <FONT> tag must be an integer between 1 and 7 which corresponds to absolute font size of 7.5, 10, 12, 13.5, 18, 24 and 36, respectively (in default user units). To specify an arbitrary font size, use the STYLE attribute described below. By default, font size is set to 10 (or the value of the Size parameter passed to the DrawText method.)

The FACE attribute of a <FONT> tag specifies a font name to be used to draw text that follows the tag. By default, the font object passed to the DrawText method as an argument is used. You must always specify a font family, such as "Courier New", instead of a specific font name such as "Courier New Bold". To draw text in bold, italic, or both, you must use the tags <B> and <I>, or style attributes font-weight and font-style (described below).

For example, the following text string will be displayed using four different fonts, Arial, Arial Bold, Arial Bold Italic, and Arial Italic:

"<FONT FACE=""Arial"">Happy <B>Birthday <i>To</b> You</i></FONT>"
Output:
Happy Birthday To You

Note that to be able to use the <B> and <I> tags, the respective font styles must be installed on your system, or an error exception will be thrown. AspPDF will not attempt to replace a missing font with a similar one.

The COLOR attribute of a <FONT> tag specifies font color. A color can be specified either by name or a Hex value prefixed by #, e.g.

<FONT COLOR="violet">
<FONT COLOR="#EE82EE">

By default, the color is set to black (#000000) or whatever value specified by the Color parameter passed to DrawText.

The STYLE attribute of the <FONT> and <DIV> tags allows you to specify various font attributes in a single tag using the Cascading Style Sheet (CSS) syntax. The following CSS attributes are currently supported:

color
font-family
font-size (in pt, in, cm or mm)
font-style (normal or italic)
font-weight (normal or bold)
text-decoration (none or underline)

For example:

<FONT STYLE="font-family: Arial; font-size: 12pt; font-weight: bold; color: red">

Text alignment to the left, center, right, and both sides is to be specified via a <DIV> tag with the ALIGN attribute set to "left", "center", "right", and "justify", respectively.

In addition to the HTML tags mentioned above, the DrawText method recognizes the following special symbols:

&amp; (&)
&cent; (¢)
&copy; (©)
&deg; (°)
&euro; (€)
&ge; (≥)
&gt; (>)
&le; (≤)
&lt; (<)
&nbsp; (non-breakable space)
&ne; (≠)
&pound; (£)
&quot; (")
&reg; (®)
&trade; (™)
&yen; (¥)
&#NNN; (an arbitrary character with Unicode code NNN)

6.4.2 Spanning Multiple Pages

If a text string does not fit in a single page, the DrawText method must be called on the next page and passed a remainder of the string, and this has to be repeated as many times as necessary. The size of the remainder is determined by the return value of DrawText (see the code sample in Section 6.1.4.)

For the most part, this method applies to HTML strings as well, except that by cutting off a portion of the string that has already been drawn on a previous page we may inadvertently cut off HTML tags that are still in effect. As a result, text on subsequent pages may not be displayed correctly.

To circumvent this problem, the PdfCanvas object provides a read-only HtmlTag property which is populated by a call to DrawText if the HTML parameter is set to true and the specified text string does not fit in the page. The property contains an HTML tag representing a set of font attributes currently in effect. This tag should simply be prepended to the remainder of the text string for the next call to DrawText.

The following code sample demonstrates this technique:

...
' Load string from file
Text = Pdf.LoadTextFromFile(Server.MapPath("html.txt") )

Set param = pdf.CreateParam("x=10; y=290; width=280; height=280; html=true")

Do While Len(Text) > 0
   CharsPrinted = Page.Canvas.DrawText(Text, param, Font )

   ' Save HTML tag generated by DrawText to reflect current font state
   HtmlTag = Page.Canvas.HtmlTag

   ' We printed the entire string. Exit loop.
   if CharsPrinted = Len(Text) Then Exit Do

   ' Otherwise print remaining text on next page
   Set Page = Page.NextPage

   Text = HtmlTag & Right( Text, Len(Text) - CharsPrinted)
Loop
...
...
String strText = objPDF.LoadTextFromFile( Server.MapPath("html.txt") );

IPdfParam objParam = objPDF.CreateParam("x=10; y=290; width=280; height=280; html=true");
while( strText.Length > 0 )
{
   // DrawText returns the number of characters that fit in the box allocated.
   int nCharsPrinted = objPage.Canvas.DrawText( strText, objParam, objFont );

   // HTML tag generated by DrawText to reflect current font state
   String strHtmlTag = objPage.Canvas.HtmlTag;

   // The entire string printed? Exit loop.
   if( nCharsPrinted == strText.Length )
      break;

   // Otherwise print remaining text on next page
   objPage = objPage.NextPage;

   strText = strHtmlTag + strText.Substring( nCharsPrinted );
}
...

Click the links below to run this code sample:

6.4.3 Issues and Limitations

  • DrawText requires that attribute values in a tag be enclosed in double quotes, although most other HTML implementations do not require that.
  • An <A> tag cannot span multiple pages.
  • An <A> tag can only be used on a PdfCanvas object associated with a page. It cannot be used on a PdfCanvas object associated with a graphics or table cell. This limitation is due to the fact that HTML anchors (links) in PDF are implemented via annotations, and an annotation can only be associated with a page.
  • When the HTML parameter is set to True, the ReverseHebrewArabic and Angle parameters are ignored.

Starting with Version 1.6, AspPDF provides a much more extensive HTML support via the ImportFromUrl method. For more information, see Chapter 15 - HTML to PDF Conversion.