PFB files for printers that don't understand them


Subject: PFB files for printers that don't understand them
From: Mike Meyer (mwm@mired.org)
Date: Fri Jun 09 2000 - 14:41:37 CDT


Not all PS printers (my HP LJ5MP, for instance) can handle PFB files,
though they can handle the equivalent PFA files. The attached patch to
xap_UnixFont.(h|cpp) changes the openPFA and getPFAChar to
automatically detect PFB files and expand them to PFA files as they
are read. It should be applied in the src/af/xap/unix directory.

If you don't have a PS interpreter that chokes on PFB files, the best
test you can do is to try using PFB files and verify that things are
still working properly. If you do have such a device, try printing to
it, or saving to a file and running the resulting file through that
interpreter.

The downside is that performance seems to have gone to pot, almost
certainly because I use a ut_ByteBuf to buffer bytes for the thing,
and then remove one char in each call to getPFAChar, resulting in lots
(and lots) of data shuffling. I believe the correct solution is to fix
the API to xap_UnixFont so you can get more than one byte at a time,
thus removing all that data shuffling. The obvious solution is a
getPFAData that returns a ut_ByteBuf containing the entire data file,
which should be at most a couple of hundred K. Getting read of the
single-char calls to ps_Generate::writeBytes in the only place that
uses getPFAChar will probably help as well.

I wanted to solicit input from others before making such a change,
though.

        <mike

--- xap_UnixFont.cpp-old Fri Jun 9 12:46:50 2000
+++ xap_UnixFont.cpp Fri Jun 9 14:06:14 2000
@@ -87,7 +87,7 @@
 
         m_metricsData = NULL;
         
- m_PFAFile = NULL;
+ m_PFFile = NULL;
         
         m_fontKey = NULL;
 }
@@ -103,7 +103,7 @@
         
         m_metricsData = NULL;
 
- m_PFAFile = NULL;
+ m_PFFile = NULL;
 
         m_fontKey = NULL;
 
@@ -120,7 +120,7 @@
         FREEP(m_fontfile);
         FREEP(m_metricfile);
 
- DELETEP(m_PFAFile);
+ DELETEP(m_PFFile);
         
         FREEP(m_fontKey);
 
@@ -304,10 +304,11 @@
 UT_Bool XAP_UnixFont::openPFA(void)
 {
         ASSERT_MEMBERS;
+ int peeked;
         
- m_PFAFile = fopen(m_fontfile, "r");
+ m_PFFile = fopen(m_fontfile, "r");
 
- if (!m_PFAFile)
+ if (!m_PFFile)
         {
                 char message[1024];
                 g_snprintf(message, 1024,
@@ -316,14 +317,18 @@
                 return UT_FALSE;
         }
 
+ /* Check to see if it's a binary or ascii PF file */
+ peeked = fgetc(m_PFFile);
+ ungetc(peeked, m_PFFile);
+ m_PFB = peeked == PFB_MARKER;
         return UT_TRUE;
 }
 
 UT_Bool XAP_UnixFont::closePFA(void)
 {
- if (m_PFAFile)
+ if (m_PFFile)
         {
- fclose(m_PFAFile);
+ fclose(m_PFFile);
                 return UT_TRUE;
         }
         return UT_FALSE;
@@ -331,8 +336,87 @@
 
 char XAP_UnixFont::getPFAChar(void)
 {
- UT_ASSERT(m_PFAFile);
- return fgetc(m_PFAFile);
+ UT_ASSERT(m_PFFile);
+ return m_PFB ? _getPFBChar() : fgetc(m_PFFile);
+}
+
+char XAP_UnixFont::_getPFBChar(void)
+{
+ char c = 0, message[1024];
+ UT_Byte inbuf[BUFSIZ], hexbuf[2 * BUFSIZ], *inp, *hexp;
+ int type, in, got, length;
+ static char *hex = "0123456789abcdef";
+
+ if (m_buffer.getLength() > 0)
+ {
+ c = m_buffer.getPointer(0)[0];
+ m_buffer.del(0, 1);
+ return c ;
+ }
+
+ // Read a block into the buffer.
+ in = fgetc(m_PFFile);
+ type = fgetc(m_PFFile);
+
+ if (in != PFB_MARKER
+ || (type != PFB_ASCII && type != PFB_BINARY && type != PFB_DONE))
+ {
+ g_snprintf(message, 1024,
+ "AbiWord encountered errors parsing the font data file\n"
+ "[%s].\n"
+ "These errors were not fatal, but printing may be incorrect.",
+ m_fontfile);
+ messageBoxOK(message);
+ return EOF;
+ }
+
+ if (type == PFB_DONE)
+ {
+ // It may still be broken if there's data after this, but...
+ return EOF;
+ }
+
+ length = fgetc(m_PFFile) & 0xFF;
+ length |= (fgetc(m_PFFile) & 0XFF) << 8;
+ length |= (fgetc(m_PFFile) & 0XFF) << 16;
+ length |= (fgetc(m_PFFile) & 0XFF) << 24;
+ if (feof(m_PFFile))
+ {
+ return EOF;
+ }
+
+ while (length > 0)
+ {
+ in = (length > BUFSIZ ? BUFSIZ : length);
+ got = fread(inbuf, 1, in, m_PFFile);
+ if (in != got)
+ {
+ g_snprintf(message, 1024,
+ "AbiWord encountered errors parsing the font data file\n"
+ "[%s].\n"
+ "These errors were not fatal, but printing may be incorrect.",
+ m_fontfile);
+ messageBoxOK(message);
+ length = got;
+ }
+ if (type == PFB_ASCII)
+ m_buffer.append(inbuf, got);
+ else // type == PFB_BINARY
+ {
+ hexp = hexbuf;
+ for (inp = inbuf; inp - inbuf < got; inp += 1)
+ {
+ *hexp++ = hex[(*inp >> 4) & 0xf];
+ *hexp++ = hex[*inp & 0xf];
+ }
+ m_buffer.append(hexbuf, 2 * got);
+ }
+ length -= got ;
+ }
+
+ c = m_buffer.getPointer(0)[0];
+ m_buffer.del(0, 1);
+ return c;
 }
 
 const char * XAP_UnixFont::getFontKey(void)
--- xap_UnixFont.h-old Fri Jun 9 12:46:51 2000
+++ xap_UnixFont.h Fri Jun 9 12:29:44 2000
@@ -26,6 +26,7 @@
 
 #include "ut_types.h"
 #include "ut_vector.h"
+#include "ut_bytebuf.h"
 
 #include "gr_Graphics.h"
 
@@ -97,8 +98,18 @@
         char * m_fontfile;
         char * m_metricfile;
 
- FILE * m_PFAFile;
+ // The font file proper
+ FILE * m_PFFile;
+ UT_Bool m_PFB;
+ UT_ByteBuf m_buffer;
+ char _getPFBChar(void);
 };
+
+/* Values found in PFB files */
+#define PFB_MARKER 0x80
+#define PFB_ASCII 1
+#define PFB_BINARY 2
+#define PFB_DONE 3
 
 /*****************************************************************/
 



This archive was generated by hypermail 2b25 : Fri Jun 09 2000 - 14:42:21 CDT