Here is a Qt 2.3.1 release patch allowing to print Unicode (UTF-8) characters present in Adobe Glyph List. It uses Level 2 glyphshow operator. Printing all Unicode probably would require CID Type 2 fonts but I think Qt currently embeds Type 42 or 3 fonts only. It has been tested with Ghostscript 6.01, XFree 4.1 on FreeBSD, Qt was compiled with Xft support - you should have your TTF directories in /usr/X11R6/lib/X11/XftConfig file. In addition this patch adds #define Q_PRINTER_USE_TYPE42 and you can enable embedding TTF fonts into postscript if you export QT_TTFTOPS=42 into your environment. Spacing between characters sometimes may be wrong because I don't found an equivalent of stringwidth when using postscript glyph names. Ghostscript may run out of limits with big TTF's like Cyberbit, set QT_TTFTOPS=3 in that case. KDE 2.1: set Charset=UTF-8 in ~/.kde/share/config/kdeglobals [Locale] section and set LANG or LC_* to UTF-8 locale and printing should work. p.s. If your patch can't handle unified diff, get GNU patch or diff format converter. --- src/kernel/qfont_x11.cpp.orig Sun Jul 8 20:51:39 2001 +++ src/kernel/qfont_x11.cpp Sun Jul 8 20:59:44 2001 @@ -366,6 +366,7 @@ { "KOI8-U", QFont::KOI8U }, { "CP 1251", QFont::CP1251 }, { "PT 154", QFont::PT154 }, + { "UTF-8", QFont::Unicode }, { 0, /* anything */ QFont::ISO_8859_1 } }; --- src/kernel/qpsprinter.cpp.orig Sun Jul 8 20:52:24 2001 +++ src/kernel/qpsprinter.cpp Sun Jul 8 21:23:07 2001 @@ -67,7 +67,7 @@ #ifndef QT_NO_PRINTER -#undef Q_PRINTER_USE_TYPE42 +#define Q_PRINTER_USE_TYPE42 #include "qpainter.h" #include "qapplication.h" @@ -753,6 +753,10 @@ "/T {", // PdcDrawText2 [string fm.width x] " PCol SC", // really need to kill these SCs " ty MT", +" false", // false means ascii string +" 2 index", // get string +" { 127 gt { pop true exit }if }forall", // true means non-ascii characters in string +" { UTF-8_show }{", // use UTF-8_show only if needed " 1 index", // string cwidth string " dup length exch", // string cwidth length string " stringwidth pop", // string cwidth length pwidth @@ -760,6 +764,7 @@ " exch sub exch div", // string extraperchar " exch 0 exch", // extraperchar 0 string " ashow", +" }ifelse", "} D", "", "/QI {", @@ -777,8 +782,6 @@ "} D", 0 }; - - // the next table is derived from a list provided by Adobe on its web // server: http://partners.adobe.com/asn/developer/typeforum/glyphlist.txt @@ -3091,21 +3094,45 @@ s << " dict dup begin\n"; // Emmit one key-value pair for each glyph. + QString glyphname; + int has_notdef = -1; for(int x=0; x < numGlyphs; x++) { + glyphname = glyphName(x); + if (glyphname == ".notdef") + has_notdef = x; if(target_type == 42) { s << "/"; - s << glyphName(x); + s << glyphname; s << " "; s << x; s << " def\n"; } else { /* type 3 */ s << "/"; - s << glyphName(x); + s << glyphname; s << "{"; charproc(x,s); s << "}_d\n"; /* "} bind def" */ } } + if (has_notdef == -1) { // add /.notdef symbol to prevent postscript interpreter errors + if(target_type == 42) { + s << "/.notdef 0 def\n"; + } else { /* type 3 */ + s << "/.notdef{750 0 125 0 620 620 _sc +125 0 _m +125 620 _l +620 620 _l +620 0 _l +125 0 _l +141 16 _m +600 16 _l +600 600 _l +141 600 _l +141 16 _l +_cl}_d +"; + } + } s << "end readonly def\n"; @@ -4929,8 +4956,8 @@ // to the most common text and assume the current locale. If that fails we use latin1. if ( cs == QFont::Unicode ) cs = QFont::charSetForLocale(); - if ( cs == QFont::Unicode ) - cs = QFont::ISO_8859_1; + // if ( cs == QFont::Unicode ) + // cs = QFont::ISO_8859_1; if ( cs == QFont::Set_Ja || cs == QFont::JIS_X_0208) { p = new QPSPrinterFontJapanese( f ); } else if ( cs == QFont::Set_Ko || cs == QFont::KSC_5601) { @@ -5141,8 +5168,8 @@ int cs = (int)f.charSet(); if ( cs == QFont::Unicode ) cs = QFont::charSetForLocale(); - if ( cs == QFont::Unicode ) - cs = QFont::ISO_8859_1; + // if ( cs == QFont::Unicode ) + // cs = QFont::ISO_8859_1; key.sprintf( "%s %d %d", ps.ascii(), f.pointSize(), cs ); QString * tmp; @@ -6037,8 +6064,77 @@ stream << "%%BeginProlog\n"; stream << prologLicense << *fixed_ps_header << "\n"; - stream << "%%EndProlog\n" - << "%%BeginSetup\n"; + stream << "%%EndProlog\n"; + stream << " + +% args: UTF-8_string required_string_width +/UTF-8_show { + exch dup length { + dup 0 get +% [0x0000 - 0x007f] [00000000.0bbbbbbb] -> 0bbbbbbb +% [0x0080 - 0x07ff] [00000bbb.bbbbbbbb] -> 110bbbbb, 10bbbbbb +% [0x0800 - 0xffff] [bbbbbbbb.bbbbbbbb] -> 1110bbbb, 10bbbbbb, 10bbbbbb +% values above 0xffff are absent from Adobe glyph list anyway + dup 127 gt { % > 0x007f + dup 2#11011111 le { % 2 bytes + 2#11111 and % strip leading 110 + dup 6 bitshift % 7-8 bits + 2 index 1 get 2#111111 and % get second byte without leading 10 + or % 1-8 bits + exch -2 bitshift 8 bitshift % 9-11 bits + or + % truncate string + exch dup length 2 sub 2 exch getinterval exch + true + } { + dup 2#11101111 le { % 3 bytes + 2#1111 and % strip leading 1110 + dup 6 bitshift % + 2 index 1 get 2#111111 and % get second byte without leading 10 + or % + exch -2 bitshift 8 bitshift % + or + 6 bitshift % make free space for the third byte bits + 1 index 2 get 2#111111 and % get third byte without leading 10 + or + % truncate string + exch dup length 3 sub 3 exch getinterval exch + true + } { + exch dup length 1 sub 1 exch getinterval exch + false + } ifelse + } ifelse + } { + exch dup length 1 sub 1 exch getinterval exch + true + } ifelse + + { + % UCS value in stack + dup UCS2PS exch known { + UCS2PS exch get glyphshow + } { + pop /.notdef glyphshow + } ifelse + 0.5 0 rmoveto % TODO calculate real number + } if + dup length 0 eq { + clear exit + } if + + } repeat + clear +} bind def + +"; + stream << "% (\n/UCS2PS <<\n"; + QString AGL_line; + for (int i=0; unicodetoglyph[i].u != 0xffff; i++) { + stream << AGL_line.sprintf("\t16#%.4X /%s\n", unicodetoglyph[i].u, unicodetoglyph[i].g); + } + stream << ">> def\n % )\n/FE" << QFont::Unicode << " ISOLatin1Encoding def\n"; + stream << "%%BeginSetup\n"; stream << "/pageinit {\n"; if ( !printer->fullPage() ) {