DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2378
Version: 1.3.0





Link: http://www.fltk.org/str.php?L2378
Version: 1.3.0
Index: src/Fl_PostScript.cxx
===================================================================
--- src/Fl_PostScript.cxx       (revision 7695)
+++ src/Fl_PostScript.cxx       (working copy)
@@ -349,23 +349,87 @@
 "end\n"
 "IDD image GR} bind def\n"
 
-// procedure to modify a font to use ISOLatin1 encoding (iso-8859-1)
-// and to keep its name unchanged
-"/ToLatin1 { dup findfont dup length dict "
-"begin {def} forall /Encoding ISOLatin1Encoding def currentdict end definefont 
pop } def\n"
-// modify all fonts to use ISOLatin1 encoding
-"/Helvetica ToLatin1 "
-"/Helvetica-Bold ToLatin1 "
-"/Helvetica-Oblique ToLatin1 "
-"/Helvetica-BoldOblique ToLatin1 \n"
-"/Courier ToLatin1 "
-"/Courier-Bold ToLatin1 "
-"/Courier-Oblique ToLatin1 "
-"/Courier-BoldOblique ToLatin1 \n"
-"/Times ToLatin1 "
-"/Times-Bold ToLatin1 "
-"/Times-Italic ToLatin1 "
-"/Times-BoldItalic ToLatin1 \n"
+// Create a custom PostScript font derived from PostScript standard text fonts
+// The encoding of this custom font is as follows:
+// 0000-00FF  coincides with Unicode, that is to ASCII + Latin-1
+// 0100-017F  coincides with Unicode, that is to Latin Extended-A
+// 0180-01A6  encodes miscellaneous characters present in PostScript standard 
text fonts
+
+// use ISOLatin1Encoding for all text fonts
+"/ToISO { dup findfont dup length dict copy begin /Encoding ISOLatin1Encoding 
def currentdict end definefont pop } def\n"
+"/Helvetica ToISO /Helvetica-Bold ToISO /Helvetica-Oblique ToISO 
/Helvetica-BoldOblique ToISO \n"
+"/Courier ToISO /Courier-Bold ToISO /Courier-Oblique ToISO 
/Courier-BoldOblique ToISO \n"
+"/Times-Roman ToISO /Times-Bold ToISO /Times-Italic ToISO /Times-BoldItalic 
ToISO \n"
+
+// define LatinExtA, the encoding of Latin-extended-A + some additional 
characters
+// see http://www.adobe.com/devnet/opentype/archives/glyphlist.txt for their 
names
+"/LatinExtA \n"
+"[ "
+" /Amacron /amacron /Abreve /abreve /Aogonek /aogonek\n" // begin of Latin 
Extended-A code page
+" /Cacute  /cacute  /Ccircumflex  /ccircumflex  /Cdotaccent  /cdotaccent  
/Ccaron  /ccaron \n"
+" /Dcaron  /dcaron   /Dcroat  /dcroat\n"
+" /Emacron  /emacron  /Ebreve  /ebreve  /Edotaccent  /edotaccent  /Eogonek  
/eogonek  /Ecaron  /ecaron\n"
+" /Gcircumflex  /gcircumflex  /Gbreve  /gbreve  /Gdotaccent  /gdotaccent  
/Gcommaaccent  /gcommaaccent \n"
+" /Hcircumflex /hcircumflex  /Hbar  /hbar  \n"
+" /Itilde  /itilde  /Imacron  /imacron  /Ibreve  /ibreve  /Iogonek  /iogonek 
/Idotaccent  /dotlessi  \n"
+" /IJ  /ij  /Jcircumflex  /jcircumflex\n"
+" /Kcommaaccent  /kcommaaccent  /kgreenlandic  \n"
+" /Lacute  /lacute  /Lcommaaccent  /lcommaaccent   /Lcaron  /lcaron  
/Ldotaccent /ldotaccent   /Lslash  /lslash \n"
+" /Nacute  /nacute  /Ncommaaccent  /ncommaaccent  /Ncaron  /ncaron  
/napostrophe  /Eng  /eng  \n"
+" /Omacron  /omacron /Obreve  /obreve  /Ohungarumlaut  /ohungarumlaut  /OE  
/oe \n"
+" /Racute  /racute  /Rcommaaccent  /rcommaaccent  /Rcaron  /rcaron \n"
+" /Sacute /sacute  /Scircumflex  /scircumflex  /Scedilla /scedilla /Scaron  
/scaron \n"
+" /Tcommaaccent  /tcommaaccent  /Tcaron  /tcaron  /Tbar  /tbar \n"
+" /Utilde  /utilde /Umacron /umacron  /Ubreve  /ubreve  /Uring  /uring  
/Uhungarumlaut  /uhungarumlaut  /Uogonek /uogonek \n"
+" /Wcircumflex  /wcircumflex  /Ycircumflex  /ycircumflex  /Ydieresis \n"
+" /Zacute /zacute /Zdotaccent /zdotaccent /Zcaron /zcaron \n"
+" /longs \n" // end of Latin Extended-A code page
+" /florin  /circumflex  /caron  /breve  /dotaccent  /ring \n" // remaining 
characters from PostScript standard text fonts
+" /ogonek  /tilde  /hungarumlaut  /endash /emdash \n"
+" /quoteleft  /quoteright  /quotesinglbase  /quotedblleft  /quotedblright \n"
+" /quotedblbase  /dagger  /daggerdbl  /bullet  /ellipsis \n"
+" /perthousand  /guilsinglleft  /guilsinglright  /fraction  /Euro \n"
+" /trademark /partialdiff  /Delta /summation  /radical \n"
+" /infinity /notequal /lessequal /greaterequal /lozenge \n"
+" /fi /fl /apple \n"
+" ] def \n"
+// deal with alternative PostScript names of some characters
+" /mycharstrings /Helvetica findfont /CharStrings get def\n"
+" /PSname2 { dup mycharstrings exch known {LatinExtA 3 -1 roll 3 -1 roll 
put}{pop pop} ifelse } def \n"
+" 16#20 /Gdot PSname2 16#21 /gdot PSname2 16#30 /Idot PSname2 16#3F /Ldot 
PSname2 16#40 /ldot PSname2 16#7F /slong PSname2 \n"
+
+// proc that gives LatinExtA encoding to a font
+"/ToLatinExtA { findfont dup length dict copy begin /Encoding LatinExtA def 
currentdict end definefont pop } def\n"
+// create Ext-versions of standard fonts that use LatinExtA encoding \n"
+"/HelveticaExt /Helvetica ToLatinExtA \n"
+"/Helvetica-BoldExt /Helvetica-Bold ToLatinExtA /Helvetica-ObliqueExt 
/Helvetica-Oblique ToLatinExtA  \n"
+"/Helvetica-BoldObliqueExt /Helvetica-BoldOblique ToLatinExtA  \n"
+"/CourierExt /Courier ToLatinExtA /Courier-BoldExt /Courier-Bold ToLatinExtA  
\n"
+"/Courier-ObliqueExt /Courier-Oblique ToLatinExtA /Courier-BoldObliqueExt 
/Courier-BoldOblique ToLatinExtA \n"
+"/Times-RomanExt /Times-Roman ToLatinExtA /Times-BoldExt /Times-Bold 
ToLatinExtA  \n"
+"/Times-ItalicExt /Times-Italic ToLatinExtA /Times-BoldItalicExt 
/Times-BoldItalic ToLatinExtA \n"
+
+// proc to create a Type 0 font with 2-byte encoding 
+// that merges a text font with ISO encoding + same font with LatinExtA 
encoding
+"/To2byte { 6 dict begin /FontType 0 def \n"
+"/FDepVector 3 1 roll findfont exch findfont 2 array astore def \n"
+"/FontMatrix [1  0  0  1  0  0] def /FMapType 6 def /Encoding [ 0 1 0 ] def\n"
+// 100: Hexa count of ISO array; A7: hexa count of LatinExtA array
+"/SubsVector < 01 0100 00A7 > def\n" 
+"currentdict end definefont pop } def\n"
+// create Type 0 versions of standard fonts
+"/Helvetica2B /HelveticaExt /Helvetica To2byte \n"
+"/Helvetica-Bold2B /Helvetica-BoldExt /Helvetica-Bold To2byte \n"
+"/Helvetica-Oblique2B /Helvetica-ObliqueExt /Helvetica-Oblique To2byte \n"
+"/Helvetica-BoldOblique2B /Helvetica-BoldObliqueExt /Helvetica-BoldOblique 
To2byte \n"
+"/Courier2B /CourierExt /Courier To2byte \n"
+"/Courier-Bold2B /Courier-BoldExt /Courier-Bold To2byte \n"
+"/Courier-Oblique2B /Courier-ObliqueExt /Courier-Oblique To2byte \n"
+"/Courier-BoldOblique2B /Courier-BoldObliqueExt /Courier-BoldOblique To2byte 
\n"
+"/Times-Roman2B /Times-RomanExt /Times-Roman To2byte \n"
+"/Times-Bold2B /Times-BoldExt /Times-Bold To2byte \n"
+"/Times-Italic2B /Times-ItalicExt /Times-Italic To2byte \n"
+"/Times-BoldItalic2B /Times-BoldItalicExt /Times-BoldItalic To2byte \n"
 ;
 
 static const char * prolog_2_pixmap =  // prolog relevant only if lang_level 
== 2 for pixmaps/masked color images
@@ -875,21 +939,21 @@
 };
 
 static const char *_fontNames[] = {
-"Helvetica",
-"Helvetica-Bold",
-"Helvetica-Oblique",
-"Helvetica-BoldOblique",
-"Courier",
-"Courier-Bold",
-"Courier-Oblique",
-"Courier-BoldOblique",
-"Times",
-"Times-Bold",
-"Times-Italic",
-"Times-BoldItalic",
+"Helvetica2B", 
+"Helvetica-Bold2B",
+"Helvetica-Oblique2B",
+"Helvetica-BoldOblique2B",
+"Courier2B",
+"Courier-Bold2B",
+"Courier-Oblique2B",
+"Courier-BoldOblique2B",
+"Times-Roman2B",
+"Times-Bold2B",
+"Times-Italic2B",
+"Times-BoldItalic2B",
 "Symbol",
-"Courier",
-"Courier-Bold",
+"Courier2B",
+"Courier-Bold2B",
 "ZapfDingbats"
 };
 
@@ -929,28 +993,136 @@
   fprintf(output, "GR\n");
 }
 
-// outputs in PostScript a UTF8 string replacing non-Latin1 characters by ?
-// and using the same width in points as on display
+
+// computes the mask for the RGB image img of all pixels with color bg
+static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg)
+{
+  uchar red, green, blue, r, g, b;
+  uchar bit, byte, *q;
+  Fl::get_color(bg, red, green, blue);
+  int W = (w+7)/8; // width of mask
+  uchar* mask = new uchar[W * h];
+  q = mask;
+  while (h-- > 0) { // for each row
+    bit = 0x80; // byte with last bit set
+    byte = 0; // next mask byte to compute
+    for (int j = 0; j < w; j++) { // for each column
+      r = *++img; // the pixel color components
+      g = *++img;
+      b = *++img;
+      // if pixel has bg color, put it in mask
+      if (r == red && g == green && b == blue) byte |= bit;
+      bit = bit>>1; // shift bit one step to the right
+      if (bit == 0) { // single set bit has fallen out
+       *q++ = byte; // enter byte in mask
+       byte = 0; // reset next mask byte to zero
+       bit = 0x80; // and this byte
+       }
+      }
+    if (bit != 0x80) *q++ = byte; // enter last columns' byte in mask
+    }
+  return mask;
+}
+
+// write to PostScript a bitmap image of a UTF8 string
+static void transformed_draw_extra(const char* str, int n, double x, double y, 
int w, FILE *output) {
+  const float scale = 3; // scale for bitmask computation
+  Fl_Fontsize old_size = fl_size();
+  fl_font(fl_font(), (Fl_Fontsize)(scale * old_size) );
+  w =  (int)(w *scale + 0.5);
+  int h = fl_height();
+  // create an offscreen image of the string
+  Fl_Color text_color = fl_color();
+  Fl_Color bg_color = fl_contrast(FL_WHITE, text_color);
+  Fl_Offscreen off = fl_create_offscreen(w+2, (int)(h+3*scale) );
+  fl_begin_offscreen(off);
+  fl_color(bg_color);
+  // color offscreen background with a shade contrasting with the text color
+  fl_rectf(0, 0, w+2, (int)(h+3*scale) );
+  fl_color(text_color);
+  fl_draw(str, n, 1, (int)(h * 0.8) ); // draw string in offscreen
+  // read (most of) the offscreen image
+  uchar *img = fl_read_image(NULL, 1, 1, w, h, 0);
+  fl_end_offscreen();
+  fl_font(fl_font(), old_size);
+  fl_delete_offscreen(off);
+  // compute the mask of what is the background
+  uchar *mask = calc_mask(img, w, h, bg_color);
+  delete img;
+  // write the string image to PostScript as a scaled bitmask
+  fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w/scale, 
h/scale, w, h);
+  uchar *di;
+  int wmask = (w+7)/8;
+  for (int j = h - 1; j >= 0; j--){
+    di = mask + j * wmask;
+    for (int i = 0; i < wmask; i++){
+      //if (!(i%80)) fprintf(output, "\n"); // don't have lines longer than 
255 chars
+      fprintf(output, "%2.2x", *di );
+      di++;
+    }
+    fprintf(output,"\n");
+  }
+  fprintf(output,">\n");
+  delete mask;
+}
+
+static int is_in_table(unsigned utf) {
+  unsigned i;
+  static unsigned extra_table_roman[] = { // unicodes/*names*/ of other 
characters from PostScript standard fonts
+    0x192/*florin*/, 0x2C6/*circumflex*/, 0x2C7/*caron*/, 
+    0x2D8/*breve*/, 0x2D9/*dotaccent*/, 0x2DA/*ring*/, 0x2DB/*ogonek*/, 
0x2DC/*tilde*/, 0x2DD/*hungarumlaut*/,
+    0x2013/*endash*/, 0x2014/*emdash*/, 0x2018/*quoteleft*/, 
0x2019/*quoteright*/, 
+    0x201A/*quotesinglbase*/, 0x201C/*quotedblleft*/, 0x201D/*quotedblright*/, 
0x201E/*quotedblbase*/, 
+    0x2020/*dagger*/, 0x2021/*daggerdbl*/, 0x2022/*bullet*/,
+    0x2026/*ellipsis*/, 0x2030/*perthousand*/, 0x2039/*guilsinglleft*/, 
0x203A/*guilsinglright*/, 
+    0x2044/*fraction*/, 0x20AC/*Euro*/, 0x2122/*trademark*/, 
+    0x2202/*partialdiff*/, 0x2206/*Delta*/, 0x2211/*summation*/, 
0x221A/*radical*/,
+    0x221E/*infinity*/, 0x2260/*notequal*/, 0x2264/*lessequal*/, 
+    0x2265/*greaterequal*/, 
+    0x25CA/*lozenge*/, 0xFB01/*fi*/, 0xFB02/*fl*/,
+    0xF8FF/*apple*/
+  };
+  for ( i = 0; i < sizeof(extra_table_roman)/sizeof(int); i++) {
+    if (extra_table_roman[i] == utf) return i + 0x180;
+  }
+  return 0;
+}
+
+// outputs in PostScript a UTF8 string using the same width in points as on 
display
 void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, 
double x, double y) {
-  int len;
+  int len, code;
   if (!n || !str || !*str) return;
+  // compute display width of string
+  int width = (int)fl_width(str, n);
+  if (width == 0) return;
+  fprintf(output, "%d <", width);
+  // transforms UTF8 encoding to our custom PostScript encoding as follows:
+  // extract each unicode character
+  // if unicode <= 0x17F, unicode and PostScript codes are identical
+  // if unicode is one of the values listed in extra_table_roman above
+  //    its PostScript code is 0x180 + the character's rank in 
extra_table_roman
+  // if unicode is something else, draw all string as bitmap image
+
   const char *last = str + n;
-  // compute display width of string
-  fprintf(output,"%g (", fl_width(str, n));
-  while (str < last) {
+  const char *str2 = str;
+  while (str2 < last) {
     // Extract each unicode character of string.
-    // Until 0xFF, UTF codes coincide with iso-Latin1 (iso-8859-1)
-    unsigned utf = fl_utf8decode(str, last, &len);
-    str += len;
-    if (utf > 0xFF) {
-      utf = '?'; // replace non Latin-1 unicodes by ?
+    unsigned utf = fl_utf8decode(str2, last, &len);
+    str2 += len;
+    if (utf <= 0x17F) { // until Latin Extended-A
+      ;
       }
-    else if (utf == '(' || utf == ')' || utf == '\\') {
-      putc('\\' , output); // these chars need be escaped
-     }
-    putc(utf, output); // output the latin character
+    else if ( (code = is_in_table(utf)) != 0) { // other handled characters
+      utf = code;
+      }
+    else { // unhandled character: draw all string as bitmap image
+      fprintf(output, "> pop pop\n"); // close and ignore the opened hex string
+      transformed_draw_extra(str, n, x, y, width, output);
+      return;
+    }
+    fprintf(output, "%4.4X", utf);
   }
-  fprintf(output, ") %g %g show_pos_width\n", x, y);
+  fprintf(output, "> %g %g show_pos_width\n", x, y);
 }
 
 struct matrix {double a, b, c, d, x, y;};
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs

Reply via email to