/*	
  BeOS Front-end du PDF file reader xpdf.
  Copyright (C) 1996 Derek B. Noonburg
  Copyright (C) 2000 Michael Pfeiffer

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include <interface/Bitmap.h>

#include "gmem.h"
#include "GString.h"
#include "Object.h"
#include "Stream.h"
#include "GfxState.h"
#include "GfxFont.h"
#include "FontFile.h"
#include "FontEncoding.h"
#include "Error.h"
#include "Params.h"
#include "TextOutputDev.h"

#include "XOutputFontInfo.h"
#include "BeFontEncoding.h"
#include "BeOutputFont.h"

#if JAPANESE_SUPPORT
#include "CID2UTF8.h"
#endif

//------------------------------------------------------------------------
// Parameters
//------------------------------------------------------------------------

#if HAVE_T1LIB_H
GString *t1libControl = NULL;
#endif

GString *t1Courier = NULL;
GString *t1CourierBold = NULL;
GString *t1CourierBoldOblique = NULL;
GString *t1CourierOblique = NULL;
GString *t1Helvetica = NULL;
GString *t1HelveticaBold = NULL;
GString *t1HelveticaBoldOblique = NULL;
GString *t1HelveticaOblique = NULL;
GString *t1Symbol = NULL;
GString *t1TimesBold = NULL;
GString *t1TimesBoldItalic = NULL;
GString *t1TimesItalic = NULL;
GString *t1TimesRoman = NULL;
GString *t1ZapfDingbats = NULL;

#if JAPANESE_SUPPORT
GString *japan12Font = NULL;
#endif

//------------------------------------------------------------------------
// Font map
//------------------------------------------------------------------------

struct FontMapEntry {
	char *pdfFont;
	char *beFontFamily;
	char *beFontStyle;
	GString **_t1Font;
	BeFontEncoding *encoding;
};

/////////////////////////////////////////////////////////////////////////
// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
static FontMapEntry fontMap[] = {
	{ "Helvetica", 				"Swis721 BT", 		"Roman",		NULL,	&beStandardEncoding },
	{ "Helvetica-Oblique", 		"Swis721 BT", 		"Italic",		NULL,	&beStandardEncoding },
	{ "Helvetica-Bold", 		"Swis721 BT", 		"Bold",			NULL,	&beStandardEncoding },
	{ "Helvetica-BoldOblique",	"Swis721 BT", 		"Bold Italic",	NULL,	&beStandardEncoding },
	{ "Times-Roman", 			"Dutch801 Rm BT", 	"Roman",		NULL,	&beStandardEncoding },
	{ "Times-Italic", 			"Dutch801 Rm BT", 	"Italic",		NULL,	&beStandardEncoding },
	{ "Times-Bold", 			"Dutch801 Rm BT", 	"Bold",			NULL,	&beStandardEncoding },
	{ "Times-BoldItalic", 		"Dutch801 Rm BT", 	"Bold Italic",	NULL,	&beStandardEncoding },
	{ "Courier", 				"Courier10 BT", 	"Roman",		NULL,	&beStandardEncoding },
	{ "Courier-Oblique", 		"Courier10 BT", 	"Italic",		NULL,	&beStandardEncoding },
	{ "Courier-Bold", 			"Courier10 BT", 	"Bold",			NULL,	&beStandardEncoding },
	{ "Courier-BoldOblique", 	"Courier10 BT", 	"Bold Italic",	NULL,	&beStandardEncoding },
/*
	{ "Arial", 					"Swis721 BT", 		"Roman",		NULL,	&beStandardEncoding },
	{ "Arial,Oblique", 			"Swis721 BT", 		"Italic",		NULL,	&beStandardEncoding },
	{ "Arial,Bold", 			"Swis721 BT", 		"Bold",			NULL,	&beStandardEncoding },
	{ "Arial,BoldOblique",		"Swis721 BT", 		"Bold Italic",	NULL,	&beStandardEncoding },
	{ "TimesNewRoman", 			"Dutch801 Rm BT", 	"Roman",		NULL,	&beStandardEncoding },
	{ "TimesNewRoman,Italic", 	"Dutch801 Rm BT", 	"Italic",		NULL,	&beStandardEncoding },
	{ "TimesNewRoman,Bold", 	"Dutch801 Rm BT", 	"Bold",			NULL,	&beStandardEncoding },
	{ "TimesNewRoman,BoldItalic", 	"Dutch801 Rm BT", 	"Bold Italic",	NULL,	&beStandardEncoding },
	{ "CourierNew", 				"Courier10 BT", 	"Roman",		NULL,	&beStandardEncoding },
	{ "CourierNew,Oblique", 		"Courier10 BT", 	"Italic",		NULL,	&beStandardEncoding },
	{ "CourierNew,Bold", 			"Courier10 BT", 	"Bold",			NULL,	&beStandardEncoding },
	{ "CourierNew,BoldOblique", 	"Courier10 BT", 	"Bold Italic",	NULL,	&beStandardEncoding },
*/
	{ "Palatino-Roman", 		"Baskerville", 		"Roman",		NULL,	&beStandardEncoding },
	{ "Palatino-Bold", 			"Baskerville", 		"Bold",			NULL,	&beStandardEncoding },
	{ "Palatino-Italic", 		"Baskerville", 		"Italic",		NULL,	&beStandardEncoding },
	{ "Palatino-BoldItalic", 	"Baskerville", 		"Bold Italic",	NULL,	&beStandardEncoding },
	{ "Symbol", 				"SymbolProp BT", 	"Regular",		NULL,	&beSymbolEncoding },
	{ "ZapfDingbats", 			"Dingbats", 		"Regular",		NULL,	&beStandardEncoding },
	{NULL}
};

static FontMapEntry *userFontMap = NULL;

//------------------------------------------------------------------------
// Font substitutions
//------------------------------------------------------------------------

struct FontSubst {
	char *pdfFont, *fontFamily, *fontStyle;
	GString **_t1Font;
	BeFontEncoding *encoding;
	double mWidth;
};

// index: {symbolic:12, fixed:8, serif:4, sans-serif:0} + bold*2 + italic
static FontSubst fontSubst[16] = {
	{ "Helvetica", 				"Swis721 BT", 		"Roman",		NULL,	&beStandardEncoding, 1},
	{ "Helvetica-Oblique", 		"Swis721 BT", 		"Italic",		NULL,	&beStandardEncoding, 1},
	{ "Helvetica-Bold", 		"Swis721 BT", 		"Bold",			NULL,	&beStandardEncoding, 1 },
	{ "Helvetica-BoldOblique",	"Swis721 BT", 		"Bold Italic",	NULL,	&beStandardEncoding, 1 },
	{ "Times-Roman", 			"Dutch801 Rm BT", 	"Roman",		NULL,	&beStandardEncoding, 1 },
	{ "Times-Italic", 			"Dutch801 Rm BT", 	"Italic",		NULL,	&beStandardEncoding, 1 },
	{ "Times-Bold", 			"Dutch801 Rm BT", 	"Bold",			NULL,	&beStandardEncoding, 1 },
	{ "Times-BoldItalic", 		"Dutch801 Rm BT", 	"Bold Italic",	NULL,	&beStandardEncoding, 1 },
	{ "Courier", 				"Courier10 BT", 	"Roman",		NULL,	&beStandardEncoding, 1 },
	{ "Courier-Oblique", 		"Courier10 BT", 	"Italic",		NULL,	&beStandardEncoding, 1 },
	{ "Courier-Bold", 			"Courier10 BT", 	"Bold",			NULL,	&beStandardEncoding, 1 },
	{ "Courier-BoldOblique", 	"Courier10 BT", 	"Bold Italic",	NULL,	&beStandardEncoding, 1 },
/*	{ "Palatino-Roman", 		"Baskerville", 		"Roman",		NULL,	&beStandardEncoding },
	{ "Palatino-Bold", 			"Baskerville", 		"Bold",			NULL,	&beStandardEncoding },
	{ "Palatino-Italic", 		"Baskerville", 		"Italic",		NULL,	&beStandardEncoding },
	{ "Palatino-BoldItalic", 	"Baskerville", 		"Bold Italic",	NULL,	&beStandardEncoding },
*/
	{ "Symbol", 				"SymbolProp BT", 	"Regular",		NULL,	&beSymbolEncoding, 1 },
	{ "Symbol", 				"SymbolProp BT", 	"Regular",		NULL,	&beSymbolEncoding, 1 },
	{ "Symbol", 				"SymbolProp BT", 	"Regular",		NULL,	&beSymbolEncoding, 1 },
	{ "Symbol", 				"SymbolProp BT", 	"Regular",		NULL,	&beSymbolEncoding, 1 }
//	{ "ZapfDingbats", 			"Dingbats", 		"Regular",		NULL,	&beStandardEncoding }
/*	{"-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",			 &t1Helvetica,						0.833},
	{"-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1",			 &t1HelveticaOblique,		 0.833},
	{"-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",				 &t1HelveticaBold,				0.889},
	{"-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1",				 &t1HelveticaBoldOblique, 0.889},
	{"-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",					 &t1TimesRoman,					 0.788},
	{"-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1",					 &t1TimesItalic,					0.722},
	{"-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",						 &t1TimesBold,						0.833},
	{"-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1",						 &t1TimesBoldItalic,			0.778},
	{"-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1",				 &t1Courier,							0.600},
	{"-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1",				 &t1CourierOblique,			 0.600},
	{"-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1",					 &t1CourierBold,					0.600},
	{"-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1",					 &t1CourierBoldOblique,	 0.600},
	{"-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", &t1Symbol,							 0.576},
	{"-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", &t1Symbol,							 0.576},
	{"-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", &t1Symbol,							 0.576},
	{"-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", &t1Symbol,							 0.576}
*/
};

//------------------------------------------------------------------------
// 16-bit fonts
//------------------------------------------------------------------------

#if JAPANESE_SUPPORT
/*
static char *japan12DefFont =
		"-*-fixed-medium-r-normal-*-%s-*-*-*-*-*-jisx0208.1983-0";
*/
static const char 
	*DEFAULT_FONT_FAMILY = "Dutch801 Rm BT",
	*DEFAULT_FONT_STYLE = "Roman",
	*DEFAULT_JAPANESE_FONT_FAMILY = "Haru",
	*DEFAULT_JAPANESE_FONT_STYLE = "Regular",
	*DEFAULT_JAPANESE_BOLD_FONT_FAMILY = "Haru",
	*DEFAULT_JAPANESE_BOLD_FONT_STYLE = "Bold";

//~ from xpdf currently not used:
// CID 0 .. 96
static Gushort japan12Map[96] = {
	0x2120, 0x2120, 0x212a, 0x2149, 0x2174, 0x2170, 0x2173, 0x2175, // 00 .. 07
	0x2147, 0x214a, 0x214b, 0x2176, 0x215c, 0x2124, 0x213e, 0x2123, // 08 .. 0f
	0x213f, 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, // 10 .. 17
	0x2337, 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, // 18 .. 1f
	0x2129, 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, // 20 .. 27
	0x2347, 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, // 28 .. 2f
	0x234f, 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, // 30 .. 37
	0x2357, 0x2358, 0x2359, 0x235a, 0x214e, 0x216f, 0x214f, 0x2130, // 38 .. 3f
	0x2132, 0x2146, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, // 40 .. 47
	0x2367, 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, // 48 .. 4f
	0x236f, 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, // 50 .. 57
	0x2377, 0x2378, 0x2379, 0x237a, 0x2150, 0x2143, 0x2151, 0x2141	// 58 .. 5f
};

// CID 325 .. 421
static Gushort japan12KanaMap1[97] = {
	0x2131, 0x2121, 0x2123, 0x2156, 0x2157, 0x2122, 0x2126, 0x2572,
	0x2521, 0x2523, 0x2525, 0x2527, 0x2529, 0x2563, 0x2565, 0x2567,
	0x2543, 0x213c, 0x2522, 0x2524, 0x2526, 0x2528, 0x252a, 0x252b,
	0x252d, 0x252f, 0x2531, 0x2533, 0x2535, 0x2537, 0x2539, 0x253b,
	0x253d, 0x253f, 0x2541, 0x2544, 0x2546, 0x2548, 0x254a, 0x254b,
	0x254c, 0x254d, 0x254e, 0x254f, 0x2552, 0x2555, 0x2558, 0x255b,
	0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2564, 0x2566, 0x2568,
	0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256f, 0x2573, 0x212b,
	0x212c, 0x212e, 0x2570, 0x2571, 0x256e, 0x2575, 0x2576, 0x2574,
	0x252c, 0x252e, 0x2530, 0x2532, 0x2534, 0x2536, 0x2538, 0x253a,
	0x253c, 0x253e, 0x2540, 0x2542, 0x2545, 0x2547, 0x2549, 0x2550,
	0x2551, 0x2553, 0x2554, 0x2556, 0x2557, 0x2559, 0x255a, 0x255c,
	0x255d
};

// CID 501 .. 598
static Gushort japan12KanaMap2[98] = {
	0x212d, 0x212f, 0x216d, 0x214c, 0x214d, 0x2152, 0x2153, 0x2154,
	0x2155, 0x2158, 0x2159, 0x215a, 0x215b, 0x213d, 0x2121, 0x2472,
	0x2421, 0x2423, 0x2425, 0x2427, 0x2429, 0x2463, 0x2465, 0x2467,
	0x2443, 0x2422, 0x2424, 0x2426, 0x2428, 0x242a, 0x242b, 0x242d,
	0x242f, 0x2431, 0x2433, 0x2435, 0x2437, 0x2439, 0x243b, 0x243d,
	0x243f, 0x2441, 0x2444, 0x2446, 0x2448, 0x244a, 0x244b, 0x244c,
	0x244d, 0x244e, 0x244f, 0x2452, 0x2455, 0x2458, 0x245b, 0x245e,
	0x245f, 0x2460, 0x2461, 0x2462, 0x2464, 0x2466, 0x2468, 0x2469,
	0x246a, 0x246b, 0x246c, 0x246d, 0x246f, 0x2473, 0x2470, 0x2471,
	0x246e, 0x242c, 0x242e, 0x2430, 0x2432, 0x2434, 0x2436, 0x2438,
	0x243a, 0x243c, 0x243e, 0x2440, 0x2442, 0x2445, 0x2447, 0x2449,
	0x2450, 0x2451, 0x2453, 0x2454, 0x2456, 0x2457, 0x2459, 0x245a,
	0x245c, 0x245d
};

static char *japan12Roman[10] = {
	"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"
};

static char *japan12Abbrev1[6] = {
	"mm", "cm", "km", "mg", "kg", "cc"
};

#endif

//------------------------------------------------------------------------
// Constructed characters
//------------------------------------------------------------------------

#define lastRegularChar 0x0ff
#define firstSubstChar	0x100
#define lastSubstChar	 0x104
#define firstConstrChar 0x105
#define lastConstrChar	0x106
#define firstMultiChar	0x107
#define lastMultiChar	 0x110

// substituted chars
static Guchar substChars[] = {
	0x27,								// 100: quotesingle --> quoteright
	0x2d,								// 101: emdash --> hyphen
	0xad,								// 102: hyphen --> endash
	0x2f,								// 103: fraction --> slash
	0xb0,								// 104: ring --> degree
};

// constructed chars
// 105: bullet
// 106: trademark

// built-up chars
static char *multiChars[] = {
	"fi",								// 107: fi
	"fl",								// 108: fl
	"ff",								// 109: ff
	"ffi",						// 10a: ffi
	"ffl",						// 10b: ffl
	"OE",								// 10c: OE
	"oe",								// 10d: oe
	"...",						// 10e: ellipsis
	"``",								// 10f: quotedblleft
	"''"								// 110: quotedblright
};

// ignored chars
// 111: Lslash
//		: Scaron
//		: Zcaron
//		: Ydieresis
//		: breve
//		: caron
//		: circumflex
//		: dagger
//		: daggerdbl
//		: dotaccent
//		: dotlessi
//		: florin
//		: grave
//		: guilsinglleft
//		: guilsinglright
//		: hungarumlaut
//		: lslash
//		: ogonek
//		: perthousand
//		: quotedblbase
//		: quotesinglbase
//		: scaron
//		: tilde
//		: zcaron

//------------------------------------------------------------------------
// BeOutputFont
//------------------------------------------------------------------------

BeOutputFont::BeOutputFont(GfxFont *gfxFont, double m11, double m12,
						 double m21, double m22, /*Display *display,*/
						 BeOutputFontCache *cache) {
	int code;
	char *charName;

	id = gfxFont->getID();
	/*this->display = display;*/
	tm11 = m11;
	tm12 = m12;
	tm21 = m21;
	tm22 = m22;

	// check for hex char names
	hex = gFalse;
	if (!gfxFont->is16Bit()) {
		for (code = 0; code < 256; ++code) {
			if ((charName = gfxFont->getCharName(code))) {
		if ((charName[0] == 'B' || charName[0] == 'C' ||
				 charName[0] == 'G') &&
				strlen(charName) == 3 &&
				((charName[1] >= 'a' && charName[1] <= 'f') ||
				 (charName[1] >= 'A' && charName[1] <= 'F') ||
				 (charName[2] >= 'a' && charName[2] <= 'f') ||
				 (charName[2] >= 'A' && charName[2] <= 'F'))) {
			hex = gTrue;
			break;
		}
			}
		}
	}
}

BeOutputFont::~BeOutputFont() {
}
/*
void BeOutputFont::update(rgb_color stroke, rgb_color fill) {
	mFill = fill; mStroke = stroke;
}
*/
#if HAVE_T1LIB_H
//------------------------------------------------------------------------
// BeOutputT1Font
//------------------------------------------------------------------------

BeOutputT1Font::BeOutputT1Font(GfxFont *gfxFont, GString *pdfBaseFont,
								 double m11, double m12, double m21, double m22,
								 double size, double ntm11, double ntm12,
								 double ntm21, double ntm22,
								 /*Display *display,*/ BeOutputFontCache *cache):
	BeOutputFont(gfxFont, m11, m12, m21, m22, /*display,*/ cache)
{
	Ref embRef;
	T1_TMATRIX xform;

	t1ID = -1;
	t1libAA = cache->getT1libAA();
	t1libAAHigh = cache->getT1libAAHigh();
	
	// keep size info (for drawChar())
	this->size = (float)size;

	// we can only handle 8-bit, Type 1/1C, with embedded font file
	// or user-specified base fonts
	//~ also look for external font files
	if (!(pdfBaseFont ||
		(!gfxFont->is16Bit() &&
		 (gfxFont->getType() == fontType1 ||
			gfxFont->getType() == fontType1C) &&
		 gfxFont->getEmbeddedFontID(&embRef)))) {
		return;
	}

	// load the font
	if ((t1ID = cache->getT1Font(gfxFont, pdfBaseFont)) < 0)
		return;

	// transform the font
	xform.cxx = ntm11;
	xform.cxy = -ntm12;
	xform.cyx = ntm21;
	xform.cyy = -ntm22;
	T1_TransformFont(t1ID, &xform);
}

BeOutputT1Font::~BeOutputT1Font() {
	if (t1ID >= 0) {
		T1_DeleteFont(t1ID);
	}
}

GBool BeOutputT1Font::isOk() {
	return t1ID >= 0;
}
/*
void BeOutputT1Font::update(rgb_color stroke, rgb_color fill) {
}
*/
void BeOutputT1Font::drawChar(GfxState *state, BBitmap *bitmap, BView *view,
								/*Pixmap pixmap,*/ /*GC gc,*/
								 double x, double y, int c) {
	// double scale = view->IsPrinting() ? 10 : 1;
	drawing_mode dm = view->DrawingMode();

	if (t1libAA || t1libAAHigh) {
	GLYPH *g = T1_AASetChar( t1ID, c, size /* * scale */, NULL);
	if ((g != NULL) && (g->bits != NULL)) {
			// T1_DumpGlyph( g);
		if (g->bpp != 8) {
			fprintf(stderr, "BeOutputT1Font::drawChar bpp = %d\n", (int)g->bpp);
			return;
		}
	
		int32 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
		int32 height = g->metrics.ascent - g->metrics.descent;
		rgb_color color = view->HighColor(); // stroke color

		BBitmap *bitmap = new BBitmap (BRect (0, 0, width-1, height-1), B_RGB32);

		int32 bpr = bitmap->BytesPerRow ();
		unsigned char *pixLine = (unsigned char*) bitmap->Bits();
		unsigned char *bits = (unsigned char *)g->bits;

		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				color.alpha = bits[x + y * width];
				unsigned char *p = &pixLine[x * 4 + bpr * y];
				p[0] = color.blue;				
				p[1] = color.green;				
				p[2] = color.red;				
				p[3] = color.alpha;
			}
		}
		
		view->SetDrawingMode(B_OP_ALPHA);
		view->DrawBitmap (bitmap, BRect (x + g->metrics.leftSideBearing, y - g->metrics.ascent + 1, x + g->metrics.rightSideBearing - 1, y - g->metrics.descent));
//		view->DrawBitmap (bitmap, BRect (x, y - g->metrics.ascent	/ scale + 1, x + width / scale - 1, y - g->metrics.descent / scale));
		delete bitmap;
	}
	} else {
	GLYPH *g = T1_SetChar( t1ID, c, size /* * scale */, NULL);
	if ((g != NULL) && (g->bits != NULL)) {
			// T1_DumpGlyph( g);
		if (g->bpp != 1) {
			fprintf(stderr, "BeOutputT1Font::drawChar bpp = %d\n", (int)g->bpp);
			return;
		}
	
		int32 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
		int32 height = g->metrics.ascent - g->metrics.descent;
		rgb_color color = view->HighColor(); // stroke color
		drawing_mode dm = view->DrawingMode();

		BBitmap *bitmap = new BBitmap (BRect (0, 0, width-1, height-1), B_RGB32);

		int32 bpr = bitmap->BytesPerRow ();
		int32 bpr2 = (width + 7) / 8;
		unsigned char *pixLine = (unsigned char*) bitmap->Bits();
		unsigned char *bits = (unsigned char *)g->bits;

		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				unsigned char *p = &pixLine[x * 4 + bpr * y];
				if (bits[x / 8 + y * bpr2] & (1 << (x % 8))) {
					p[0] = color.blue;				
					p[1] = color.green;				
					p[2] = color.red;				
					p[3] = 255;
				} else {
					p[3] = 0;
				}
			}
		}
		view->SetDrawingMode(B_OP_ALPHA);
		view->DrawBitmap (bitmap, BRect (x + g->metrics.leftSideBearing, y - g->metrics.ascent + 1, x + g->metrics.rightSideBearing - 1, y - g->metrics.descent));
//		view->DrawBitmap (bitmap, BRect (x, y - g->metrics.ascent	/ scale + 1, x + width / scale - 1, y - g->metrics.descent / scale));
		delete bitmap;
	}
	}

	view->SetDrawingMode(dm);
}
#endif // HAVE_T1LIB_H

//------------------------------------------------------------------------
// BeOutputServerFont
//------------------------------------------------------------------------

BeOutputServerFont::BeOutputServerFont(GfxFont *gfxFont, char *fontFamily, 
									 char *fontStyle,
										 BeFontEncoding *encoding,
										 double m11, double m12,
										 double m21, double m22,
										 double size,
										 double ntm11, double ntm12,
										 double ntm21, double ntm22,
										 /*Display *display,*/
										 BeOutputFontCache *cache):
	BeOutputFont(gfxFont, m11, m12, m21, m22, /*display,*/ cache)
{
	char fontName[200], fontSize[100];
	GBool rotated;
	int startSize, sz;
	int code, code2;
	char *charName;
	int n;
	this->encoding = encoding;
	
	beFont = NULL;

	// Construct forward and reverse map.
	// This tries to deal with font subset character names of the
	// form 'Bxx', 'Cxx', 'Gxx', with decimal or hex numbering.
	if (!gfxFont->is16Bit()) {
		for (code = 0; code < 256; ++code)
			revMap[code] = 0;
		if (encoding) {
			for (code = 0; code < 256; ++code) {
		if ((charName = gfxFont->getCharName(code))) {
			if ((code2 = encoding->getIndex(charName)) < 0) {
				n = strlen(charName);
				if (hex && n == 3 &&
				(charName[0] == 'B' || charName[0] == 'C' ||
				 charName[0] == 'G') &&
				isxdigit(charName[1]) && isxdigit(charName[2])) {
					sscanf(charName+1, "%x", &code2);
				} else if (!hex && n >= 2 && n <= 3 &&
							 isdigit(charName[0]) && isdigit(charName[1])) {
					code2 = atoi(charName);
					if (code2 >= 256)
				code2 = -1;
				} else if (!hex && n >= 3 && n <= 5 && isdigit(charName[1])) {
					code2 = atoi(charName+1);
					if (code2 >= 256)
				code2 = -1;
				}
				//~ this is a kludge -- is there a standard internal encoding
				//~ used by all/most Type 1 fonts?
				if (code2 == 262)				// hyphen
					code2 = 45;
				else if (code2 == 266)		// emdash
					code2 = 208;
			}
			if (code2 >= 0) {
				map[code] = (Gushort)code2;
				if (code2 < 256)
					revMap[code2] = (Guchar)code;
			} else {
				map[code] = 0;
			}
		} else {
			map[code] = 0;
		}
			}
		} else {
			code2 = 0; // to make gcc happy
			//~ this is a hack to get around the fact that X won't draw
			//~ chars 0..31; this works when the fonts have duplicate encodings
			//~ for those chars
			for (code = 0; code < 32; ++code) {
		if ((charName = gfxFont->getCharName(code)) &&
				(code2 = gfxFont->getCharCode(charName)) >= 0) {
			map[code] = (Gushort)code2;
			if (code2 < 256)
				revMap[code2] = (Guchar)code;
		}
			}
			for (code = 32; code < 256; ++code) {
		map[code] = (Gushort)code;
		revMap[code] = (Guchar)code;
			}
		}
	}

	// adjust transform for the X transform convention
	ntm12 = -ntm12;
	ntm22 = -ntm22;

	// try to get a rotated font?
	rotated = !(ntm11 > 0 && ntm22 > 0 &&
					fabs(ntm11 / ntm22 - 1) < 0.2 &&
					fabs(ntm12) < 0.01 &&
					fabs(ntm21) < 0.01);

	beFont = new BFont();
	beFont->SetFamilyAndStyle (fontFamily, fontStyle);
	beFont->SetSize (size);
	beFont->SetEncoding (B_UNICODE_UTF8);
#if MORE_DEBUG
	fprintf(stderr, "Font set to %s %s %f\n", fontFamily, fontStyle, size);
#endif
	// open X font -- if font is not found (which means the server can't
	// scale fonts), try progressively smaller and then larger sizes
	//~ This does a linear search -- it should get a list of fonts from
	//~ the server and pick the closest.
/*	startSize = (int)size;
	if (rotated)
		sprintf(fontSize, "[%s%0.2f %s%0.2f %s%0.2f %s%0.2f]",
				ntm11<0 ? "~" : "", fabs(ntm11 * size),
				ntm12<0 ? "~" : "", fabs(ntm12 * size),
				ntm21<0 ? "~" : "", fabs(ntm21 * size),
				ntm22<0 ? "~" : "", fabs(ntm22 * size));
	else
		sprintf(fontSize, "%d", startSize);
	sprintf(fontName, fontNameFmt, fontSize);
*/
	
		/*XLoadQueryFont(display, fontName);*/
/*	
	if (!xFont) {
		for (sz = startSize; sz >= startSize/2 && sz >= 1; --sz) {
			sprintf(fontSize, "%d", sz);
			sprintf(fontName, fontNameFmt, fontSize);
			if ((xFont = XLoadQueryFont(display, fontName)))
		break;
		}
		if (!xFont) {
			for (sz = startSize + 1; sz < startSize + 10; ++sz) {
		sprintf(fontSize, "%d", sz);
		sprintf(fontName, fontNameFmt, fontSize);
		if ((xFont = XLoadQueryFont(display, fontName)))
			break;
			}
			if (!xFont) {
		sprintf(fontSize, "%d", startSize);
		sprintf(fontName, fontNameFmt, fontSize);
		error(-1, "Failed to open font: '%s'", fontName);
		return;
			}
		}
	}
*/
}

BeOutputServerFont::~BeOutputServerFont() {
	if (beFont) delete beFont;
}

GBool BeOutputServerFont::isOk() {
	return beFont != NULL;
}

void BeOutputServerFont::drawChar(GfxState *state, BBitmap *bitmap, BView *mView,
									/*Pixmap pixmap,*/ /*GC gc,*/
								 double x, double y, int c) {
	int32 c1 = map[c];
	if (c1 < 0) return;
	
	double x1, y1;
	double rotation, x2, y2;
	
	// FIXME: Optimize this:
	state->transformDelta(1, 0, &x1, &y1);
	rotation = -atan2( y1, x1 );
	// Determine rotation
	state->textTransformDelta( 1, 0, &x1, &y1 );
	rotation = (rotation + atan2( y1, x1 )) * 180 / PI;
	// Set rotation
	beFont->SetRotation(rotation);
	mView->SetFont(beFont);

	//state->transform( x, y, &x1, &y1 );
	/*
	if (state->getRender() & 1) {
		mView->SetHighColor(mStroke);
		// mView->SetLowColor(mFill);
	}
	else {
		mView->SetHighColor(mFill);
		// mView->SetLowColor(mStroke);
	}
	*/
	mView->DrawString( encoding->getUtf8At(c1), BPoint( x, y ));
#ifdef MORE_DEBUG
	rgb_color color = mView->HighColor();
	fprintf(stderr, "%s", encoding->getUtf8At(c1));
	fprintf(stderr, "%d %d %d %d\n", color.red, color.green, color.blue, color.alpha);
#endif
	// mView->SetHighColor(mStroke);	
}

void BeOutputServerFont::drawChar16(GfxState *state, BBitmap *bitmap, BView *mView,
									/*Pixmap pixmap,*/ /*GC gc,*/
								 double x, double y, int c) {
	GfxFont *gfxFont = state->getFont();
	double x1, y1;
		Guint c1, u8;
	char pp[5];
	
	switch (gfxFont->getCharSet16()) {
	// convert Adobe-Japan1-2 to UTF-8
	case font16AdobeJapan12:
#if JAPANESE_SUPPORT
		if(c <= 8720){
			u8 = (Guint)japanUniJISUCS2HMap2[c];
			if(u8 == 0 ){
				if(c == 0){					//---- null
					c1 = u8;
					//---- CID-HalfWidth Character -> UTF-8(ASCII)
				}else	if((c >= 232) && (c <= 322)){ 
					c1 = (Guint)c - 199;
				}else{					//---- Converted "?", this is no much case 
					c1 = 0x3f;
					printf("Unsupported Adobe-Japan1-2 character: %d", c);
				}
			}else{	//---- Converted completed.
				c1 = u8;
			}
		}else{		//---- Max convert table over!
			c1 = 0x3f;
			printf("Unsupported Adobe-Japan1-2 character: %d", c);
	}
#endif // JAPANESE_SUPPORT
	break;

	// convert Adobe-GB1-2 to GB 2312-80
//	case font16AdobeGB12:
#if CHINESE_SUPPORT
#endif // CHINESE_SUPPORT
//		break;
	}

	if((c1 & 0xFFFFFF00) == 0 ){
		pp[0] = c1;
		pp[1] = NULL ;
		//pp[2] = NULL ;
		//pp[3] = NULL ;
		//pp[4] = NULL ;
	}else if((c1 & 0xFFFF0000) == 0 ){
		pp[0] = (c1 >> 8);
		pp[1] = (c1 & 0xFF) ;
		//pp[2] = NULL ;
		//pp[3] = NULL ;
		//pp[4] = NULL ;
	}else if((c1 & 0xFF000000) == 0 ){
		pp[0] = (c1 >> 16);
		pp[1] = ((c1 >> 8)& 0xFF);
		pp[2] = (c1 & 0xFF) ;
		pp[3] = NULL ;
		//pp[4] = NULL ;
	}else{
		pp[0] = (c1 >> 24);
		pp[1] = ((c1 >> 16)& 0xFF);
		pp[2] = ((c1 >> 8)& 0xFF);
		pp[3] = (c1 & 0xFF) ;
		pp[4] = NULL ;
	}	
#ifdef MORE_DEBUG
	printf("| UTF8==%d:0x%x --- ",c1,c1);
	printf(pp);
	printf("\n");
#endif

	// FIXME: Optimize this:
	state->transformDelta(1, 0, &x1, &y1);
	double rotation = -atan2( y1, x1 );
	// Determine rotation
	state->textTransformDelta( 1, 0, &x1, &y1 );
	rotation = (rotation + atan2( y1, x1 )) * 180 / PI;

	// Set rotation
	beFont->SetRotation(rotation);
	mView->SetFont(beFont);
	/*
	if (state->getRender() & 1) {
		mView->SetHighColor(mStroke);
	}else {
		mView->SetHighColor(mFill);
	}
	*/
	mView->DrawString(pp ,BPoint( x, y ));
	// mView->SetHighColor(mStroke);
}

//------------------------------------------------------------------------
// BeOutputFontCache
//------------------------------------------------------------------------

BeOutputFontCache::BeOutputFontCache(/*Display *display*/) {
	//this->display = display;
#if HAVE_T1LIB_H
	t1Init = gFalse;
	if (t1libControl) {
		useT1lib = t1libControl->cmp("none") != 0;
		t1libAA = t1libControl->cmp("plain") != 0;
		t1libAAHigh = t1libControl->cmp("high") == 0;
	} else {
		useT1lib = gTrue; // gFalse;
		t1libAA = gFalse; // gFalse;
		t1libAAHigh = gTrue; // gFalse;
	}
#endif
	clear();
}

BeOutputFontCache::~BeOutputFontCache() {
	delFonts();
}

void BeOutputFontCache::startDoc(/*int screenNum,*/ Guint depth
								/*, Colormap colormap*/) {
	delFonts();
	clear();

#ifdef HAVE_T1LIB_H
	if (useT1lib) {
		if (T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
					 T1_NO_AFM)) {
			if (t1libAA) {
		T1_AASetLevel(t1libAAHigh ? T1_AA_HIGH : T1_AA_LOW);
		if (depth <= 8)
			T1_AASetBitsPerPixel(8);
		else if (depth <= 16)
			T1_AASetBitsPerPixel(16);
		else
			T1_AASetBitsPerPixel(32);
			}
			/*
			T1_AASetGrayValues(0, 64, 128, 192, 255); 
	
			unsigned long grayValues[17];
			for (int i = 0; i <= 16; i++) {
				grayValues[i] = 63 + i * 192 / 16;
			}
			grayValues[0] = 0;
			T1_AAHSetGrayValues(grayValues);
			T1_AASetLevel(T1_AA_HIGH);
			*/
			t1Init = gTrue;
		} else {
			useT1lib = gFalse;
		}
	}
#endif // HAVE_T1LIB_H
}

void BeOutputFontCache::delFonts() {
	int i;

#if HAVE_T1LIB_H
	// delete Type 1 fonts
	for (i = 0; i < nT1Fonts; ++i)
		delete t1Fonts[i];
	for (i = 0; i < t1BaseFontsSize && t1BaseFonts[i].num >= 0; ++i) {
		T1_DeleteFont(t1BaseFonts[i].t1ID);
		gfree(t1BaseFonts[i].encStr);
		gfree(t1BaseFonts[i].enc);
	}
	gfree(t1BaseFonts);
	if (t1Init) {
		T1_CloseLib();
	}
#endif

	// delete server fonts
	for (i = 0; i < nServerFonts; ++i)
		delete serverFonts[i];
}

void BeOutputFontCache::clear() {
	int i;

#if HAVE_T1LIB_H
	// clear Type 1 font cache
	for (i = 0; i < t1FontCacheSize; ++i)
		t1Fonts[i] = NULL;
	nT1Fonts = 0;
	t1BaseFonts = NULL;
	t1BaseFontsSize = 0;
#endif

	// clear server font cache
	for (i = 0; i < serverFontCacheSize; ++i)
		serverFonts[i] = NULL;
	nServerFonts = 0;
}

BeOutputFont *BeOutputFontCache::getFont(GfxFont *gfxFont,
											 double m11, double m12,
											 double m21, double m22) {
#if HAVE_T1LIB_H
	BeOutputT1Font *t1Font;
#endif
	BeOutputServerFont *serverFont;
	FontMapEntry *fme = NULL;
	GString *t1FontName;
	char *beFontFamily, *beFontStyle;
	BeFontEncoding *beEncoding;
	double size;
	double ntm11, ntm12, ntm21, ntm22;
	double w1, w2, v;
	double *fm;
	int index;
	int code;
	int i, j;

#ifdef MORE_DEBUG
	switch (gfxFont->getType()) {
		case fontUnknownType:
			fprintf(stderr, "PDFViewer: Font unknown type");
			break;
		case fontType1:
			fprintf(stderr, "PDFViewer: Font Type 1");
			break;
		case fontType1C:
			fprintf(stderr, "PDFViewer: Font Type 1C");
			break;
		case fontType3:
			fprintf(stderr, "PDFViewer: Font Type 3");
			break;
		case fontTrueType:
			fprintf(stderr, "PDFViewer: Font True Type");
			break;
		case fontType0:
			fprintf(stderr, "PDFViewer: Font Type 0");
			break;
		default:
			fprintf(stderr, "PDFViewer: Font Type ???");
	}

	if (gfxFont->getName()) {
		fprintf(stderr, " '%s' ", gfxFont->getName()->getCString());
	} else {
		fprintf(stderr, " has no name, ");
	}
	Ref embId;
	if (gfxFont->getEmbeddedFontID(&embId)) {
		fprintf(stderr, " embedded");
	} else {
		fprintf(stderr, " external");
	}

	if (gfxFont->is16Bit()) {
		fprintf(stderr, " 16 Bit\n");
	} else {
		fprintf(stderr, " 8 Bit\n");
	}
#endif 

	// is it the most recently used Type 1 or server font?
#if HAVE_T1LIB_H
	if (useT1lib && nT1Fonts > 0 &&
			t1Fonts[0]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
		return t1Fonts[0];
	}
#endif
	if (nServerFonts > 0 && serverFonts[0]->matches(gfxFont->getID(),
													m11, m12, m21, m22))
		return serverFonts[0];

#if HAVE_T1LIB_H
	// is it in the Type 1 cache?
	if (useT1lib) {
		for (i = 1; i < nT1Fonts; ++i) {
			if (t1Fonts[i]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
		t1Font = t1Fonts[i];
		for (j = i; j > 0; --j)
			t1Fonts[j] = t1Fonts[j-1];
		t1Fonts[0] = t1Font;
		return t1Font;
			}
		}
	}
#endif

	// is it in the server cache?
	for (i = 1; i < nServerFonts; ++i) {
		if (serverFonts[i]->matches(gfxFont->getID(), m11, m12, m21, m22)) {
			serverFont = serverFonts[i];
			for (j = i; j > 0; --j)
		serverFonts[j] = serverFonts[j-1];
			serverFonts[0] = serverFont;
			return serverFont;
		}
	}

	// compute size and normalized transform matrix
	size = sqrt(m21*m21 + m22*m22);
	ntm11 = m11 / size;
	ntm12 = m12 / size;
	ntm21 = m21 / size;
	ntm22 = m22 / size;

	// search for a font map entry
	t1FontName = NULL;
	beFontFamily = beFontStyle = NULL;
	beEncoding = NULL;
	if (!gfxFont->is16Bit() && gfxFont->getName()) {
		if (userFontMap != NULL) {
			for (fme = userFontMap; fme->pdfFont; ++fme) {
				if (!gfxFont->getName()->cmp(fme->pdfFont)) {
			break;
				}
			}
		}
		if (!fme || !fme->pdfFont) {
			for (fme = fontMap; fme->pdfFont; ++fme) {
		if (!gfxFont->getName()->cmp(fme->pdfFont)) {
			break;
		}
			}
		}
//		if (fme && fme->t1Font) {
//			t1FontName = *fme->t1Font;
//		}
		if (fme && fme->beFontFamily && fme->encoding) {
			beFontFamily = fme->beFontFamily;
			beFontStyle = fme->beFontStyle;
			beEncoding = fme->encoding;
		}
	}

	// no font map entry found, so substitute a font
	if (!t1FontName && !beFontFamily) {
		if (gfxFont->is16Bit()) {
			beFontFamily = fontSubst[0].fontFamily;
			beFontStyle = fontSubst[0].fontStyle;
			beEncoding = fontSubst[0].encoding;
			t1FontName = NULL;
			switch (gfxFont->getCharSet16()) {
			case font16AdobeJapan12:
#if JAPANESE_SUPPORT
		// beFontFamily = japan12Font ? japan12Font->getCString() : japan12DefFont;
		beFontFamily = (char*)DEFAULT_JAPANESE_FONT_FAMILY;
		beFontStyle = (char*)DEFAULT_JAPANESE_FONT_STYLE;
#endif
		break;
			}
		} else {
			if (gfxFont->isFixedWidth()) {
		index = 8;
			} else if (gfxFont->isSerif()) {
		index = 4;
			} else {
		index = 0;
			}
			if (gfxFont->isBold())
		index += 2;
			if (gfxFont->isItalic())
		index += 1;
			beFontFamily = fontSubst[index].fontFamily;
			beFontStyle = fontSubst[index].fontStyle;
			// t1FontName = *fontSubst[index].t1Font;
			beEncoding = fontSubst[index].encoding;
			// un-normalize
			ntm11 = m11;
			ntm12 = m12;
			ntm21 = m21;
			ntm22 = m22;
			// get width of 'm' in real font and substituted font
			if ((code = gfxFont->getCharCode("m")) >= 0)
		w1 = gfxFont->getWidth(code);
			else
		w1 = 0;
			w2 = fontSubst[index].mWidth;
			if (gfxFont->getType() == fontType3) {
		// This is a hack which makes it possible to substitute for some
		// Type 3 fonts.	The problem is that it's impossible to know what
		// the base coordinate system used in the font is without actually
		// rendering the font.	This code tries to guess by looking at the
		// width of the character 'm' (which breaks if the font is a
		// subset that doesn't contain 'm').
		if (w1 > 0 && (w1 > 1.1 * w2 || w1 < 0.9 * w2)) {
			w1 /= w2;
			ntm11 = m11 * w1;
			ntm12 = m12 * w1;
			ntm21 = m21 * w1;
			ntm22 = m22 * w1;
		}
		fm = gfxFont->getFontMatrix();
		v = (fm[0] == 0) ? 1 : (fm[3] / fm[0]);
		ntm12 *= v;
		ntm22 *= v;
			} else if (!gfxFont->isSymbolic()) {
		// if real font is substantially narrower than substituted
		// font, reduce the font size accordingly
		if (w1 > 0.01 && w1 < 0.9 * w2) {
			w1 /= w2;
			if (w1 < 0.8)
				w1 = 0.8;
			ntm11 = m11 * w1;
			ntm12 = m12 * w1;
			ntm21 = m21 * w1;
			ntm22 = m22 * w1;
		}
			}
			// renormalize
			size = sqrt(ntm21*ntm21 + ntm22*ntm22);
			ntm11 /= size;
			ntm12 /= size;
			ntm21 /= size;
			ntm22 /= size;
		}
	}

#if HAVE_T1LIB_H
	// try to create a new Type 1 font
	if (useT1lib) {
		t1Font = new BeOutputT1Font(gfxFont, t1FontName,
									 m11, m12, m21, m22,
									 size, ntm11, ntm12, ntm21, ntm22,
									 /*display,*/ this);
		if (t1Font->isOk()) {

			// insert in cache
			if (nT1Fonts == t1FontCacheSize) {
		--nT1Fonts;
		delete t1Fonts[nT1Fonts];
			}
			for (j = nT1Fonts; j > 0; --j)
		t1Fonts[j] = t1Fonts[j-1];
			t1Fonts[0] = t1Font;
			++nT1Fonts;

			return t1Font;
		}
		delete t1Font;
	}
#endif

	// create a new server font
	serverFont = new BeOutputServerFont(gfxFont, beFontFamily, beFontStyle, beEncoding,
										 m11, m12, m21, m22,
										 size, ntm11, ntm12, ntm21, ntm22,
										 /*display,*/ this);
	if (serverFont->isOk()) {

		// insert in cache
		if (nServerFonts == serverFontCacheSize) {
			--nServerFonts;
			delete serverFonts[nServerFonts];
		}
		for (j = nServerFonts; j > 0; --j)
			serverFonts[j] = serverFonts[j-1];
		serverFonts[0] = serverFont;
		++nServerFonts;

		return serverFont;
	}
	delete serverFont;

	return NULL;
}

#if HAVE_T1LIB_H
int BeOutputFontCache::getT1Font(GfxFont *gfxFont, GString *pdfBaseFont) {
	Ref id;
	char *fileName;
	char tmpFileName[60];
	FILE *f;
	char *fontBuf;
	int fontLen;
	Type1CFontConverter *cvt;
	Ref embRef;
	Object refObj, strObj;
	FontEncoding *enc;
	int encStrSize;
	char *encPtr;
	int t1ID;
	int c;
	int i, j;

	id = gfxFont->getID();

	// check available fonts
	t1ID = -1;
	for (i = 0; i < t1BaseFontsSize && t1BaseFonts[i].num >= 0; ++i) {
		if (t1BaseFonts[i].num == id.num && t1BaseFonts[i].gen == id.gen) {
			t1ID = t1BaseFonts[i].t1ID;
		}
	}

	// create a new base font
	if (t1ID < 0) {

		// resize t1BaseFonts if necessary
		if (i == t1BaseFontsSize) {
			t1BaseFonts = (BeOutputT1BaseFont *)
		grealloc(t1BaseFonts,
				 (t1BaseFontsSize + 16) * sizeof(BeOutputT1BaseFont));
			for (j = 0; j < 16; ++j) {
		t1BaseFonts[t1BaseFontsSize + j].num = -1;
			}
			t1BaseFontsSize += 16;
		}

		// create the font file
		tmpFileName[0] = '\0';
		if (!gfxFont->is16Bit() &&
		(gfxFont->getType() == fontType1 ||
		 gfxFont->getType() == fontType1C) &&
		gfxFont->getEmbeddedFontID(&embRef)) {
			tmpnam(tmpFileName);
			if (!(f = fopen(tmpFileName, "wb"))) {
		error(-1, "Couldn't open temporary Type 1 font file '%s'",
					tmpFileName);
		return -1;
			}
			if (gfxFont->getType() == fontType1C) {
		fontBuf = gfxFont->readEmbFontFile(&fontLen);
		cvt = new Type1CFontConverter(fontBuf, fontLen, f);
		cvt->convert();
		delete cvt;
		gfree(fontBuf);
			} else {
		gfxFont->getEmbeddedFontID(&embRef);
		refObj.initRef(embRef.num, embRef.gen);
		refObj.fetch(&strObj);
		refObj.free();
		strObj.streamReset();
		while ((c = strObj.streamGetChar()) != EOF)
			fputc(c, f);
			}
			fclose(f);
			strObj.free();
			fileName = tmpFileName;
		} else {
			fileName = pdfBaseFont->getCString();
		}

		// create the t1lib font
		if ((t1ID = T1_AddFont(fileName)) < 0) {
			error(-1, "Couldn't create t1lib font from '%s'", fileName);
			return -1;
		}
		T1_LoadFont(t1ID);
		t1BaseFonts[i].num = id.num;
		t1BaseFonts[i].gen = id.gen;
		t1BaseFonts[i].t1ID = t1ID;

		// remove the font file
		if (tmpFileName[0]) {
			unlink(tmpFileName);
		}

		// reencode it
		enc = gfxFont->getEncoding();
		encStrSize = 0;
		for (j = 0; j < 256 && j < enc->getSize(); ++j) {
			if (enc->getCharName(j)) {
		encStrSize += strlen(enc->getCharName(j)) + 1;
			}
		}
		t1BaseFonts[i].enc = (char **)gmalloc(257 * sizeof(char *));
		encPtr = (char *)gmalloc(encStrSize * sizeof(char));
		t1BaseFonts[i].encStr = encPtr;
		for (j = 0; j < 256 && j < enc->getSize(); ++j) {
			if (enc->getCharName(j)) {
		strcpy(encPtr, enc->getCharName(j));
		t1BaseFonts[i].enc[j] = encPtr;
		encPtr += strlen(encPtr) + 1;
			} else {
		t1BaseFonts[i].enc[j] = ".notdef";
			}
		}
		for (; j < 256; ++j) {
			t1BaseFonts[i].enc[j] = ".notdef";
		}
		t1BaseFonts[i].enc[256] = "custom";
		T1_ReencodeFont(t1BaseFonts[i].t1ID, t1BaseFonts[i].enc);
	}

	// copy it
	t1ID = T1_CopyFont(t1ID);

	return t1ID;
}
#endif
