summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Harris <bjh21@bjh21.me.uk>2007-02-08 21:50:00 +0000
committerBen Harris <bjh21@bjh21.me.uk>2007-02-08 21:50:00 +0000
commita0a77360d18d8207cbd67bb00297553fe90bc43a (patch)
tree2ba73cfd34a0ccc385e1b82536f76e0a291fda1f
parent032b461a08eebc91d19f12c3e4d78032a5a173db (diff)
downloadhalibut-a0a77360d18d8207cbd67bb00297553fe90bc43a.zip
halibut-a0a77360d18d8207cbd67bb00297553fe90bc43a.tar.gz
halibut-a0a77360d18d8207cbd67bb00297553fe90bc43a.tar.bz2
halibut-a0a77360d18d8207cbd67bb00297553fe90bc43a.tar.xz
Support for embedding TrueType fonts in PDF output. The code isn't the most
beautiful I've ever written, and xpdf turns out not to support the encoding mechanism I've chosen, but it works in GhostScript so I'm not too unhappy for now. [originally from svn r7259]
-rw-r--r--bk_pdf.c156
-rw-r--r--in_sfnt.c46
-rw-r--r--paper.h10
3 files changed, 150 insertions, 62 deletions
diff --git a/bk_pdf.c b/bk_pdf.c
index 74944f0..d75244d 100644
--- a/bk_pdf.c
+++ b/bk_pdf.c
@@ -14,9 +14,6 @@ paragraph *pdf_config_filename(char *filename)
return cmdline_cfg_simple("pdf-filename", filename, NULL);
}
-typedef struct object_Tag object;
-typedef struct objlist_Tag objlist;
-
struct object_Tag {
objlist *list;
object *next;
@@ -31,10 +28,6 @@ struct objlist_Tag {
object *head, *tail;
};
-static object *new_object(objlist *list);
-static void objtext(object *o, char const *text);
-static void objstream(object *o, char const *text);
-static void objstream_len(object *o, char const *text, size_t len);
static void pdf_string(void (*add)(object *, char const *),
object *, char const *);
static void pdf_string_len(void (*add)(object *, char const *),
@@ -137,8 +130,11 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
objtext(resources, "<<\n/ProcSet [/PDF/Text]\n/Font <<\n");
for (fe = doc->fonts->head; fe; fe = fe->next) {
char fname[40];
+ char buf[80];
int i, prev;
- object *font;
+ object *font, *fontdesc;
+ int flags;
+ font_info const *fi = fe->font->info;
sprintf(fname, "f%d", font_index++);
fe->name = dupstr(fname);
@@ -151,26 +147,13 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
objref(resources, font);
objtext(resources, "\n");
- objtext(font, "<<\n/Type /Font\n/Subtype /Type1\n/Name /");
- objtext(font, fe->name);
- objtext(font, "\n/BaseFont /");
- objtext(font, fe->font->info->name);
- objtext(font, "\n/Encoding <<\n/Type /Encoding\n/Differences [");
-
- for (i = 0; i < 256; i++) {
- char buf[20];
- if (fe->vector[i] == NOGLYPH)
- continue;
- if (i != prev + 1) {
- sprintf(buf, "\n%d", i);
- objtext(font, buf);
- }
- objtext(font, i % 8 ? "/" : "\n/");
- objtext(font, glyph_extern(fe->vector[i]));
- prev = i;
- }
- objtext(font, "\n]\n>>\n");
+ /*
+ * Construct those parts of the font descriptor that don't dependd
+ * on the file format.
+ */
+ if (!is_std_font(fe->font->info->name)) {
+ fontdesc = new_object(&olist);
#define FF_FIXEDPITCH 0x00000001
#define FF_SERIF 0x00000002
@@ -182,36 +165,6 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
#define FF_SMALLCAP 0x00020000
#define FF_FORCEBOLD 0x00040000
- if (!is_std_font(fe->font->info->name)){
- object *widths = new_object(&olist);
- object *fontdesc = new_object(&olist);
- int firstchar = -1, lastchar = -1;
- char buf[80];
- font_info const *fi = fe->font->info;
- int flags;
- for (i = 0; i < 256; i++)
- if (fe->vector[i] != NOGLYPH) {
- if (firstchar < 0) firstchar = i;
- lastchar = i;
- }
- sprintf(buf, "/FirstChar %d\n/LastChar %d\n/Widths ",
- firstchar, lastchar);
- objtext(font, buf);
- objref(font, widths);
- objtext(font, "\n");
- objtext(widths, "[\n");
- for (i = firstchar; i <= lastchar; i++) {
- double width;
- if (fe->vector[i] == NOGLYPH)
- width = 0.0;
- else
- width = find_width(fe->font, fe->vector[i]);
- sprintf(buf, "%g\n", 1000.0 * width / FUNITS_PER_PT);
- objtext(widths, buf);
- }
- objtext(widths, "]\n");
- objtext(font, "/FontDescriptor ");
- objref(font, fontdesc);
objtext(fontdesc, "<<\n/Type /FontDescriptor\n/Name /");
objtext(fontdesc, fi->name);
flags = 0;
@@ -236,6 +189,76 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
objtext(fontdesc, buf);
sprintf(buf, "/StemV %g\n", fi->stemv);
objtext(fontdesc, buf);
+ }
+
+ objtext(font, "<<\n/Type /Font\n/BaseFont /");
+ objtext(font, fe->font->info->name);
+ if (fe->font->info->filetype == TRUETYPE) {
+ object *cidfont = new_object(&olist);
+ object *cmap = new_object(&olist);
+ objtext(font, "/Subtype/Type0\n/Encoding ");
+ sfnt_cmap(fe, cmap);
+ objref(font, cmap);
+ objtext(font, "\n/DescendantFonts[");
+ objref(font, cidfont);
+ objtext(font, "]\n");
+ objtext(cidfont, "<<\n/Type/Font\n/Subtype/CIDFontType2\n"
+ "/BaseFont/");
+ objtext(cidfont, fe->font->info->name);
+ objtext(cidfont, "\n/CIDSystemInfo<</Registry(Adobe)"
+ "/Ordering(Identity)/Supplement 0>>\n");
+ objtext(cidfont, "/FontDescriptor ");
+ objref(cidfont, fontdesc);
+ objtext(cidfont, ">>\n");
+ } else {
+ objtext(font, "/Subtype /Type1\n");
+ objtext(font, "\n/Encoding <<\n/Type /Encoding\n/Differences [");
+
+ for (i = 0; i < 256; i++) {
+ char buf[20];
+ if (fe->vector[i] == NOGLYPH)
+ continue;
+ if (i != prev + 1) {
+ sprintf(buf, "\n%d", i);
+ objtext(font, buf);
+ }
+ objtext(font, i % 8 ? "/" : "\n/");
+ objtext(font, glyph_extern(fe->vector[i]));
+ prev = i;
+ }
+
+ objtext(font, "\n]\n>>\n");
+ if (!is_std_font(fe->font->info->name)){
+ object *widths = new_object(&olist);
+ int firstchar = -1, lastchar = -1;
+ for (i = 0; i < 256; i++)
+ if (fe->vector[i] != NOGLYPH) {
+ if (firstchar < 0) firstchar = i;
+ lastchar = i;
+ }
+ sprintf(buf, "/FirstChar %d\n/LastChar %d\n/Widths ",
+ firstchar, lastchar);
+ objtext(font, buf);
+ objref(font, widths);
+ objtext(font, "\n");
+ objtext(widths, "[\n");
+ for (i = firstchar; i <= lastchar; i++) {
+ double width;
+ if (fe->vector[i] == NOGLYPH)
+ width = 0.0;
+ else
+ width = find_width(fe->font, fe->vector[i]);
+ sprintf(buf, "%g\n", 1000.0 * width / FUNITS_PER_PT);
+ objtext(widths, buf);
+ }
+ objtext(widths, "]\n");
+ objtext(font, "/FontDescriptor ");
+ objref(font, fontdesc);
+ }
+
+ }
+
+ if (!is_std_font(fe->font->info->name)) {
if (fi->fontfile && fi->filetype == TYPE1) {
object *fontfile = new_object(&olist);
size_t len;
@@ -254,6 +277,17 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
objtext(fontfile, "/Length3 0\n");
objtext(fontdesc, "/FontFile ");
objref(fontdesc, fontfile);
+ } else if (fi->fontfile && fi->filetype == TRUETYPE) {
+ object *fontfile = new_object(&olist);
+ size_t len;
+ char *ffbuf;
+
+ sfnt_data((font_info *)fi, &ffbuf, &len);
+ objstream_len(fontfile, ffbuf, len);
+ sprintf(buf, "<<\n/Length1 %lu\n", (unsigned long)len);
+ objtext(fontfile, buf);
+ objtext(fontdesc, "/FontFile2 ");
+ objref(fontdesc, fontfile);
}
objtext(fontdesc, "\n>>\n");
}
@@ -581,7 +615,7 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords,
sfree(filename);
}
-static object *new_object(objlist *list)
+object *new_object(objlist *list)
{
object *obj = snew(object);
@@ -607,17 +641,17 @@ static object *new_object(objlist *list)
return obj;
}
-static void objtext(object *o, char const *text)
+void objtext(object *o, char const *text)
{
rdaddsc(&o->main, text);
}
-static void objstream_len(object *o, char const *text, size_t len)
+void objstream_len(object *o, char const *text, size_t len)
{
rdaddsn(&o->stream, text, len);
}
-static void objstream(object *o, char const *text)
+void objstream(object *o, char const *text)
{
rdaddsc(&o->stream, text);
}
diff --git a/in_sfnt.c b/in_sfnt.c
index fe16941..9e21bf2 100644
--- a/in_sfnt.c
+++ b/in_sfnt.c
@@ -802,3 +802,49 @@ void sfnt_writeps(font_info const *fi, FILE *ofp) {
sfree(breaks);
fprintf(ofp, "end /%s exch definefont\n", fi->name);
}
+
+void sfnt_cmap(font_encoding *fe, object *cmap) {
+ unsigned i;
+
+ objtext(cmap, "<</Type/CMap\n/CMapName/");
+ objtext(cmap, fe->name);
+ objtext(cmap, "\n/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)"
+ "/Supplement 0>>\n");
+ objstream(cmap, "%!PS-Adobe-3.0 Resource-CMap\n"
+ "%%DocumentNeededResources: procset CIDInit\n"
+ "%%IncludeResource: procset CIDInit\n"
+ "%%BeginResource: CMap ");
+ objstream(cmap, fe->name);
+ objstream(cmap, "\n%%Title (");
+ objstream(cmap, fe->name);
+ objstream(cmap, " Adobe Identity 0)\n%%Version: 1\n%%EndComments\n");
+ objstream(cmap, "/CIDInit/ProcSet findresource begin\n");
+ objstream(cmap, "12 dict begin begincmap\n");
+ objstream(cmap, "/CIDSystemInfo 3 dict dup begin\n"
+ "/Registry(Adobe)def/Ordering(Identity)def/Supplement 0 def "
+ "end def\n");
+ objstream(cmap, "/CMapName/");
+ objstream(cmap, fe->name);
+ objstream(cmap, " def/CMapType 0 def/WMode 0 def\n");
+ objstream(cmap, "1 begincodespacerange<00><FF>endcodespacerange\n");
+ for (i = 0; i < 256; i++) {
+ char buf[20];
+ if (fe->vector[i] == NOGLYPH)
+ continue;
+ objstream(cmap, "1 begincidchar");
+ sprintf(buf, "<%02X>", i);
+ objstream(cmap, buf);
+ sprintf(buf, "%hu", sfnt_glyphtoindex(fe->font->info->fontfile,
+ fe->vector[i]));
+ objstream(cmap, buf);
+ objstream(cmap, " endcidchar\n");
+ }
+ objstream(cmap, "endcmap CMapName currentdict /CMap defineresource pop "
+ "end end\n%%EndResource\n%%EOF\n");
+}
+
+void sfnt_data(font_info *fi, char **bufp, size_t *lenp) {
+ sfnt *sf = fi->fontfile;
+ *bufp = sf->data;
+ *lenp = sf->len;
+}
diff --git a/paper.h b/paper.h
index b68fd5f..3f20fc2 100644
--- a/paper.h
+++ b/paper.h
@@ -393,8 +393,14 @@ const int *ps_std_font_widths(char const *fontname);
const kern_pair *ps_std_font_kerns(char const *fontname);
/*
- * Function from bk_pdf.c borrowed by bk_ps.c
+ * Functions exported from bk_pdf.c
*/
+typedef struct object_Tag object;
+typedef struct objlist_Tag objlist;
+object *new_object(objlist *list);
+void objtext(object *o, char const *text);
+void objstream(object *o, char const *text);
+void objstream_len(object *o, char const *text, size_t len);
char *pdf_outline_convert(wchar_t *s, int *len);
/*
@@ -413,5 +419,7 @@ void pf_writeps(font_info const *fi, FILE *ofp);
* Backend functions exported by in_sfnt.c
*/
void sfnt_writeps(font_info const *fi, FILE *ofp);
+void sfnt_cmap(font_encoding *fe, object *);
+void sfnt_data(font_info *fi, char **bufp, size_t *lenp);
#endif