Artifact b93537bf6a1224abb368ed8dc19f2d9942ac9e4b13d0c2a8245f3fc293d7aef2:
- Executable file
r38/lisp/csl/cslbase/FXPostscriptFont.cpp
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 17616) [annotate] [blame] [check-ins using] [more...]
/******************************************************************************** * * * P o s t c r i p t F o n t O b j e c t * * * ********************************************************************************* * Copyright (C) 1997,2003 by Jeroen van der Zijp. All Rights Reserved. * ********************************************************************************* * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; * * version 2.1 of the License. * * * * This library 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * * Together with the FOX addendum that permits distribution of statically linked * * binaries. * ********************************************************************************* * $Id: FXPostscriptFont.cpp,v 1.65 2003/10/27 23:59:21 fox Exp $ * ********************************************************************************/ // This file was written by A C Norman based on FXFont.c, for which the // above copyright etc apply. /* Signature: 6af519ba 19-Jun-2007 */ #ifdef HAVE_CONFIG_H #include "config.h" #else #define HAVE_LIBFOX 1 #endif #ifdef HAVE_LIBFOX #include <fx.h> #include "FXPostscriptFont.h" #include <ctype.h> using namespace FX; namespace FX { /*******************************************************************************/ #ifdef WANTED_AND_ACTUAL // A bunch of field-names changed between 1.1.45 and 1.1.49 so here for // older releases I map onto the newer names. It may be that I should be a // lot more carefull wrt actualXxx and wantedXxx. // version 1.1.x is SO old now that I might properly disard this... #define actualName name #define actualSize size #define actualWeight weight #define actualSlant slant #define actualEncoding encoding #define actualSetwidth setwidth #endif // Object implementation FXIMPLEMENT(FXPostscriptFont,FXFont,NULL,0) // Deserialization FXPostscriptFont::FXPostscriptFont(){ font=(void*)-1L; } // Construct font from X11 font spec. Well for Postscript Fonts // I will not support decoding X11 long-names... FXPostscriptFont::FXPostscriptFont(FXApp* a,const FXString& nm):FXFont(a,nm){ FXTRACE((100,"FXPostscriptFont::FXPostscriptFont %p\n",this)); actualSize=0; actualWeight=0; actualSlant=0; actualEncoding=FONTENCODING_DEFAULT; #if (FOX_MINOR<=4) actualSetwidth=FONTSETWIDTH_DONTCARE; #else actualSetwidth=0; #endif font=NULL; } // Construct a font with given face name, size in points(pixels), weight, slant, character set encoding, setwidth, and hints FXPostscriptFont::FXPostscriptFont(FXApp* a, const FXString &face, FXuint sz, FXuint wt, FXuint sl, FXuint enc, FXuint setw, FXuint h):FXFont(a,face){ FXTRACE((100,"FXPostscriptFont::FXPostscriptFont %p\n",this)); actualSize=10*sz; actualWeight=wt; actualSlant=sl; actualEncoding=enc; actualSetwidth=setw; #if (FOX_MINOR<=4) hints=(h&~FONTHINT_X11); #else hints=(h&~FXFont::X11); #endif font=NULL; } // Construct font from font description FXPostscriptFont::FXPostscriptFont(FXApp* a, const FXFontDesc &fontdesc):FXFont(a, fontdesc){ FXTRACE((100,"FXPostscriptFont::FXPostscriptFont %p\n",this)); actualName=fontdesc.face; actualSize=fontdesc.size; actualWeight=fontdesc.weight; actualSlant=fontdesc.slant; actualEncoding=fontdesc.encoding; actualSetwidth=fontdesc.setwidth; hints=fontdesc.flags; font=NULL; } /*******************************************************************************/ // // When generating Postscript I need font metrics. These can be extracted // from "afm" files that Adobe supply. I have a program "get-adobe-metrics.c" // that can be run on a typical Linux system to extract the (minimal) metric // information that I need here and build a file "font-info.c". By including // that file here I collect info about all the standard Postscript Fonts. // I will not permit a user to use any other fonts than these! // // // There are 35 standard Postscript fonts that might be used with this // print package. They are: // AvantGarde-Book // AvantGarde-BookOblique // AvantGarde-Demi // AvantGarde-DemiOblique // Bookman-Demi // Bookman-DemiItalic // Bookman-Light // Bookman-LightItalic // * Courier-Bold // * Courier-BoldOblique // * Courier // * Courier-Oblique // * Helvetica-Bold // * Helvetica-BoldOblique // Helvetica-NarrowBold // Helvetica-NarrowBoldOblique // * Helvetica // * Helvetica-Oblique // Helvetica-Narrow // Helvetica-NarrowOblique // NewCenturySchlbk-Bold // NewCenturySchlbk-BoldItalic // NewCenturySchlbk-Italic // NewCenturySchlbk-Roman // Palatino-Bold // Palatino-BoldItalic // Palatino-Italic // Palatino-Roman // * Symbol // * Times-Bold // * Times-BoldItalic // * Times-Italic // * Times-Roman // ZapfChancery-MediumItalic // ZapfDingbats // [those marked * are the original 13] // // // Font metrics: I extract these from .afm files so that I can have // rapid access to the information that I need throughout this package. // The effect is that I fill a few kilobytes of memory with font tables. // To avoid going over the top I will not keep per-character bearing // information. The information in the font tables is based on having a // nominal character cell that is 1000 units high, which means that // integer metrics are quite accurate enough for everybody. #include "font-info.c" // Here is the sort of info found in "font-info.c". Each font // listed comes with its full Adobe name. // [It will shortly need (max)width, height, ascent, descent, // leading, (max)left-bearing (max)right-bearing] // The main data is then an array of 256 short integers. This contains // -1 if the character is not present, otherwise the character width. // Note once again that these numbers are all based on a nominal 1pt font // with units of 1/1000. Another way to think of this is that numbers are // in units of 1/72000in and will need to be multiplied by the point size // of a font before use. // // typedef struct font_info { // char *name; // short int isfixed, fontwidth, maxleftbearing, maxrightbearing; // short int capheight, xheight, ascent, descent; // short int charwidth[256]; // } font_info; // // static font_info font_widths[] = { // {"AvantGarde-Demi", 0, 1280, 233, 234, 740, 555, 740, -185, { // -1, -1, -1, -1, -1, -1, -1, -1, // ... // -1, 874, 760, 946, 771, 865, 771, 888, // 967, 888, 831, 873, 927, 970, 918, -1 }}, // {(char *)0, {}}}; // static font_info *find_metrics(const char *name) { font_info *p = font_widths; while (p->name != NULL && strcmp(name, p->name)!=0) p++; if (p->name != NULL) return p; return &font_widths[0]; // this should never occur! } // Create font. In this case I take that to mean the process of refining // the font name and fetching associated metrics. enum family { AvantGarde, Bookman, Courier, Helvetica, NewCenturySchlbk, Palatino, Symbol, Times, ZapfChancery, ZapfDingbats }; // return true of s has p as an initial sub-string, ignoring case static FXbool matches(const char *s, const char *p) { while (*p != 0) { if (*s==0 || tolower(*s)!=tolower(*p)) return FALSE; s++; p++; } return TRUE; } // return true if s has p as a substring, ignoring case static FXbool contains(const char *s, const char *p) { while (*s != 0) { if (matches(s, p)) return TRUE; s++; } return FALSE; } void FXPostscriptFont::create() { // I will start by massaging the given name etc to provide me with one of the // canonical Postscript names. Note that the tests on font families // are done in an order so that later test acn override tentative decisions // made by earlier ones. Eg the font with name "roman" will first be // identified as asking for Times (roman, bold etc), but if the word // "palatino" is see too then you get Palatino-Roman. If the name is // not recognised at all you will get Times family fam = Times; // a default family to use const char *n = actualName.text(); #if (FOX_MINOR<=4) if (contains(n, "bold")) actualWeight = FONTWEIGHT_BOLD; if (contains(n, "light")) actualWeight = FONTWEIGHT_LIGHT; if (contains(n, "italic")) actualSlant = FONTSLANT_ITALIC; if (contains(n, "oblique")) actualSlant = FONTSLANT_OBLIQUE; if (contains(n, "narrow")) actualSetwidth = FONTSETWIDTH_NARROW; #else if (contains(n, "bold")) actualWeight = FXFont::Bold; if (contains(n, "light")) actualWeight = FXFont::Light; if (contains(n, "italic")) actualSlant = FXFont::Italic; if (contains(n, "oblique")) actualSlant = FXFont::Oblique; if (contains(n, "narrow")) actualSetwidth = FXFont::Condensed; #endif if (contains(n, "times") || contains(n, "serif") || contains(n, "roman")) fam = Times; if (contains(n, "avant")) fam = AvantGarde; if (contains(n, "bookman")) fam = Bookman; if (contains(n, "courier") || contains(n, "fixed")) fam = Courier; if (contains(n, "helvet") || contains(n, "ariel") || contains(n, "sanserif") || contains(n, "swiss")) fam = Helvetica; if (contains(n, "newcent")) fam = NewCenturySchlbk; if (contains(n, "palatin")) fam = Palatino; if (contains(n, "symbol")) fam = Symbol; if (contains(n, "chancery") || contains(n, "zapf")) fam = ZapfChancery; if (contains(n, "dingbat")) fam = ZapfDingbats; // Now a few cases that override #if (FOX_MINOR<=4) if (actualSetwidth != FONTSETWIDTH_DONTCARE && actualSetwidth <= FONTSETWIDTH_COMPRESSED) fam = Helvetica; if (hints & (FONTPITCH_FIXED|FONTHINT_MODERN)) fam = Courier; else if ((hints & FONTPITCH_VARIABLE) && fam==Courier) fam = Helvetica; #define four(reg, bold, ital, boldital) \ (actualWeight<=FONTWEIGHT_NORMAL ? \ (actualSlant<=FONTSLANT_REGULAR ? reg : ital) : \ (actualSlant<=FONTSLANT_REGULAR ? bold : boldital)) #else if (actualSetwidth != 0 && actualSetwidth <= FXFont::Condensed) fam = Helvetica; if (hints & (FXFont::Fixed|FXFont::Modern)) fam = Courier; else if ((hints & FXFont::Variable) && fam==Courier) fam = Helvetica; #define four(reg, bold, ital, boldital) \ (actualWeight<=FXFont::Normal ? \ (actualSlant<=FXFont::Straight ? reg : ital) : \ (actualSlant<=FXFont::Straight ? bold : boldital)) #endif switch (fam) { case AvantGarde: actualName = four("AvantGarde-Book", "AvantGarde-Demi", "AvantGarde-BookOblique", "AvantGarde-DemiOblique"); break; case Bookman: actualName = four("Bookman-Light", "Bookman-Demi", "Bookman-LightItalic", "Bookman-DemiItalic"); break; case Courier: actualName = four("Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"); break; case Helvetica: #if (FOX_MINOR<=4) if (actualSetwidth == FONTSETWIDTH_NARROW) #else if (actualSetwidth == FXFont::Condensed) #endif actualName = four("Helvetica-Narrowi", "Helvetica-NarrowBold", "Helvetica-NarrowOblique", "Helvetica-NarrowBoldOblique"); else actualName = four("Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique"); break; case NewCenturySchlbk: actualName = four("NewCenturySchlbk", "NewCenturySchlbk-Bold", "NewCenturySchlbk-Italic", "NewCenturySchlbk-BoldItalic"); break; case Palatino: actualName = four("Palatino-Roman", "Palatino-Bold", "Palatino-Italic", "Palatino-BoldItalic"); break; case Symbol: actualName = "Symbol"; #if (FOX_MINOR<=4) actualWeight = FONTWEIGHT_NORMAL; actualSlant = FONTSLANT_REGULAR; #else actualWeight = FXFont::Normal; actualSlant = FXFont::Straight; #endif break; case Times: default: actualName = four("Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic"); break; case ZapfChancery: actualName = "ZapfChancery-MediumItalic"; #if (FOX_MINOR<=4) actualWeight = FONTWEIGHT_NORMAL; actualSlant = FONTSLANT_ITALIC; #else actualWeight = FXFont::Normal; actualSlant = FXFont::Italic; #endif break; case ZapfDingbats: actualName = "ZapfDingbats"; #if (FOX_MINOR<=4) actualWeight = FONTWEIGHT_NORMAL; actualSlant = FONTSLANT_REGULAR; #else actualWeight = FXFont::Normal; actualSlant = FXFont::Straight; #endif } metrics = find_metrics(actualName.text()); } // Does font have given character glyph? FXbool FXPostscriptFont::hasChar(FXint ch) const { return metrics->charwidth[ch & 0xff] != -1; } // Get first character glyph in font #if (FOX_MINOR<=4) FXint FXPostscriptFont::getMinChar() const #else FXwchar FXPostscriptFont::getMinChar() const #endif { int i; for (i=0; i<256; i++) if (metrics->charwidth[i] != -1) return i; return 256; } // Get last character glyph in font #if (FOX_MINOR<=4) FXint FXPostscriptFont::getMaxChar() const #else FXwchar FXPostscriptFont::getMaxChar() const #endif { int i; for (i=255; i>=0; i--) if (metrics->charwidth[i] != -1) return i; return 0; } // Get font leading [that is lead-ing as in Pb!] FXint FXPostscriptFont::getFontLeading() const { // I use 0.2 of the point-size as my leading. Point sizes are stored in // decipoints. I return a value in millipoints. return (200/10)*actualSize; } // Get font line spacing [height+leading] FXint FXPostscriptFont::getFontSpacing() const { return (1200/10)*actualSize; } // Left bearing FXint FXPostscriptFont::leftBearing(FXchar ch) const { return (metrics->maxleftbearing*actualSize)/10; } // Right bearing FXint FXPostscriptFont::rightBearing(FXchar ch) const { return (metrics->maxrightbearing*actualSize)/10; } // Is it a mono space font FXbool FXPostscriptFont::isFontMono() const { return metrics->isfixed; } // Get font width FXint FXPostscriptFont::getFontWidth() const { return (metrics->fontwidth*actualSize)/10; } // Get font height FXint FXPostscriptFont::getFontHeight() const { return (1000/10)*actualSize; } // Get font ascent FXint FXPostscriptFont::getFontAscent() const { return (metrics->ascent*actualSize)/10; } // Get font descent FXint FXPostscriptFont::getFontDescent() const { return (metrics->descent*actualSize)/10; } // Text width FXint FXPostscriptFont::getTextWidth(const FXchar *text, FXuint n) const { int w = 0; while (*text != 0 && (n--)!=0) // stop on null char as well as at length { w += metrics->charwidth[*text & 0xff]; text++; } return (w*actualSize)/10; } // Text width FXint FXPostscriptFont::getTextWidth(const FXString &text) const { return getTextWidth(text.text(), text.length()); } // Text height FXint FXPostscriptFont::getTextHeight(const FXchar *text, FXuint n) const { return (1000/10)*actualSize; // use font height } // Text height FXint FXPostscriptFont::getTextHeight(const FXString &text) const { return getTextHeight(text.text(), text.length()); } /******************************************************************************/ // Clean up FXPostscriptFont::~FXPostscriptFont() { FXTRACE((100,"FXPostscriptFont::~FXPostscriptFont %p\n",this)); destroy(); } } #endif // HAVE_LIBFOX // end of FXPostscriptFont.cpp