PDFlib 是國際廣泛使用的伺服器端 PDF 生成庫,支援 C/C++、Java、Perl、PHP、Python、Tcl、RealBasic 等語言。本系列文章分享使用 PDFlib 輸出簡體中文的實戰經驗。第一篇介紹 PDFlib 內建的三款 Acrobat 標準簡體中文字體、支援的 14 種編碼格式、字體與編碼的最佳組合策略,並提供完整 C 語言範例程式碼。
STSong-LightAdobeSongStd-Light-AcroSTSongStd-Light-Acro這三款字體均為 Acrobat 內建標準字體,無需額外安裝即可在 PDF 中正確顯示,適合跨平台文件交換。
| 編碼名稱 | 字符集與文本格式 |
|---|---|
| UniGB-UCS2-H / -V | Unicode (UCS-2) 編碼,適用於 Adobe-GB1 字符集 |
| UniGB-UTF16-H / -V | Unicode (UTF-16BE) 編碼,含 GB18030-2000 所有字符映射 |
| GB-EUC-H / -V | Microsoft Code Page 936 (charset 134),GB 2312-80,EUC-CN 編碼 |
| GBpc-EUC-H / -V | Macintosh,GB 2312-80,EUC-CN,Script Manager code 2 |
| GBK-EUC-H / -V | Microsoft Code Page 936,GBK 字符集,GBK 編碼 |
| GBKp-EUC-H / -V | 同 GBK-EUC-H,但半形拉丁字符改為比例字體,0x24 映射為 $ 而非 ¥ |
| GBK2K-H / -V | GB 18030-2000 字符集,混合 1/2/4 位元組編碼 |
命名規則:-H 為橫向輸出,-V 為縱向輸出;Uni 開頭為 Unicode 類編碼,GB 開頭為 CP936 類編碼。
雖然理論上 3 種字體 × 14 種編碼 = 42 種組合,但 PDFlib 並非支援所有組合。最穩妥、相容性最好的組合是:
PDFlib 內建三種字體 + Unicode 類編碼 (UniGB-UCS2-H/V, UniGB-UTF16-H/V)
Unicode 編碼支援完整字符集,避免 CP936 編碼在某些字體組合下出現字符缺失或錯位問題。
int Font_CS;
Font_CS = PDF_load_font(p, "STSong-Light", 0, "UniGB-UTF16-H", "");
程式碼自動產生多頁 PDF,每頁展示一種字體搭配 14 種編碼的輸出效果。Unicode 編碼使用 Unicode 字串,CP936 編碼使用 CP936 字串,自動判斷橫向/縱向編碼調整行距。
/*******************************************************************/
/* This example demostrates the usage of PDFlib builtin fonts */
/* based on Chinese Simplifed Windows. */
/*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdflib.h"
int main(void) {
PDF *p = NULL;
int i = 0, j = 0, Left = 50, Top = 800;
int Font_E = 0, Font_CS = 0;
char TextUnicode[] = "\x80\x7B\x53\x4F\x2D\x4E\x87\x65";
char TextCp936[] = "\xBC\xF2\xCC\xE5\xD6\xD0\xCE\xC4";
char EncodingName[100];
static const char *ChineseFont[] = {"STSong-Light", "AdobeSongStd-Light-Acro", "STSongStd-Light-Acro", };
static const char *Encoding[] = {
"UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V",
"GB-EUC-H", "GB-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V",
"GBK-EUC-H", "GBK-EUC-V", "GBKp-EUC-H", "GBKp-EUC-V",
"GBK2K-H", "GBK2K-V",
};
const int fsize = sizeof ChineseFont / sizeof (char *);
const int esize = sizeof Encoding / sizeof (char *);
/* create a new PDFlib object */
if ((p = PDF_new()) == (PDF *) 0) {
printf("Couldn't create PDFlib object (out of memory)!\n");
return(2);
}
PDF_TRY(p) {
if (PDF_begin_document(p, "pdflib_cs1.pdf", 0, "") == -1) {
printf("Error: %s\n", PDF_get_errmsg(p));
return(2);
}
PDF_set_info(p, "Creator", "pdflib_cs1.c");
PDF_set_info(p, "Author", "bowriver2001@yahoo.ca");
PDF_set_info(p, "Title", "Output Chinese Simplify with PDFlib builtin font");
Font_E = PDF_load_font(p, "Helvetica-Bold", 0, "winansi", "");
for (i = 0; i < fsize; i++) {
/*Start a new page. */
Top = 800;
PDF_begin_page_ext(p, a4_width, a4_height, "");
PDF_setfont(p, Font_E, 24);
PDF_show_xy(p, ChineseFont[i] , Left + 50, Top);
Top -= 30;
for (j = 0; j < esize; j++) {
Font_CS = PDF_load_font(p, ChineseFont[i], 0, Encoding[j], "");
PDF_setfont(p, Font_E, 12);
strcpy(EncodingName, "");
strcat(EncodingName, Encoding[j]);
strcat(EncodingName, ":");
PDF_show_xy(p, EncodingName , Left, Top);
PDF_setfont(p, Font_CS, 12);
if (strstr(Encoding[j], "-H") != NULL) {
/* It's horizontal encoding. */
Top -= 15;
}
if (strstr(Encoding[j], "UniGB") != NULL) {
/* It's unicode encoding. */
PDF_show_xy2(p, TextUnicode, 8, Left, Top);
} else {
/* It's code page 936 encoding. */
PDF_show_xy2(p, TextCp936, 8, Left, Top);
}
if (strstr(Encoding[j], "-H") != NULL) {
/* It's horizontal encoding. */
Top -= 25;
} else {
/* It's vertical encoding. */
Top -= 65;
}
}
/* End of page. */
PDF_end_page_ext(p, "");
}
PDF_end_document(p, "");
}
PDF_CATCH(p) {
printf("PDFlib exception occurred in pdflib_cs1 sample:\n");
printf("[%d] %s: %s\n", PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
PDF_delete(p);
return(2);
}
PDF_delete(p);
return 0;
}
UniGB-UTF16-H 含 GB18030 全字符集,相容性最佳。