📄 type1.c
字号:
/* $XConsortium: type1.c,v 1.5 91/10/10 11:20:06 rws Exp $ *//* Copyright International Business Machines, Corp. 1991 * All Rights Reserved * Copyright Lexmark International, Inc. 1991 * All Rights Reserved * Portions Copyright (c) 1990 Adobe Systems Incorporated. * All Rights Reserved * * License to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of IBM or Lexmark or Adobe * not be used in advertising or publicity pertaining to distribution of * the software without specific, written prior permission. * * IBM, LEXMARK, AND ADOBE PROVIDE THIS SOFTWARE "AS IS", WITHOUT ANY * WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE * ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE, INCLUDING * ANY DUTY TO SUPPORT OR MAINTAIN, BELONGS TO THE LICENSEE. SHOULD ANY * PORTION OF THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM, * LEXMARK, OR ADOBE) ASSUMES THE ENTIRE COST OF ALL SERVICING, REPAIR AND * CORRECTION. IN NO EVENT SHALL IBM, LEXMARK, OR ADOBE BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*********************************************************************//* *//* Type 1 module - Converting fonts in Adobe Type 1 Font Format *//* to scaled and hinted paths for rasterization. *//* Files: type1.c, type1.h, and blues.h. *//* *//* Authors: Sten F. Andler, IBM Almaden Research Center *//* (Type 1 interpreter, stem & flex hints) *//* *//* Patrick A. Casey, Lexmark International, Inc. *//* (Font level hints & stem hints) *//* *//*********************************************************************/ /******************//* Include Files: *//******************/#include "types.h"#include <stdio.h> /* a system-dependent include, usually */#include <math.h>#include "objects.h"#include "spaces.h"#include "paths.h"#include "fonts.h" /* understands about TEXTTYPEs */#include "pictures.h" /* understands about handles */ typedef struct xobject xobject;#include "util.h" /* PostScript objects */#include "fontfcn.h"#include "blues.h" /* Blues structure for font-level hints */ /**********************************//* Type1 Constants and Structures *//**********************************/#define MAXSTACK 24 /* Adobe Type1 limit */#define MAXCALLSTACK 10 /* Adobe Type1 limit */#define MAXPSFAKESTACK 32 /* Max depth of fake PostScript stack (local) */#define MAXSTRLEN 512 /* Max length of a Type 1 string (local) */#define MAXLABEL 256 /* Maximum number of new hints */#define MAXSTEMS 512 /* Maximum number of VSTEM and HSTEM hints */#define EPS 0.001 /* Small number for comparisons */ /************************************//* Adobe Type 1 CharString commands *//************************************/#define HSTEM 1#define VSTEM 3#define VMOVETO 4#define RLINETO 5#define HLINETO 6#define VLINETO 7#define RRCURVETO 8#define CLOSEPATH 9#define CALLSUBR 10#define RETURN 11#define ESCAPE 12#define HSBW 13#define ENDCHAR 14#define RMOVETO 21#define HMOVETO 22#define VHCURVETO 30#define HVCURVETO 31/* The following charstring code appears in some old Adobe font files in space and .notdef character and does not seems to do anything useful aside from taking two args from the stack. We allow this command and ignore it. The source code of ghostscript states that this command is obsolete *and* undocumented. This code may also appear in an Escape-sequence! */#define UNKNOWN_15 15/*******************************************//* Adobe Type 1 CharString Escape commands *//*******************************************/#define DOTSECTION 0#define VSTEM3 1#define HSTEM3 2#define SEAC 6#define SBW 7#define DIV 12#define CALLOTHERSUBR 16#define POP 17#define SETCURRENTPOINT 33 /* Note: We use routines from libm because in the original macro definitions, the evaluation order of tmpx is undefined by C-standard! */#define USE_MATHLIB_ROUTINES#ifdef USE_MATHLIB_ROUTINES#define FABS(x) (fabs (x))#define CEIL(x) ((LONG) ceil (x))#define FLOOR(x) ((LONG) floor (x))#else/*****************//* Useful macros *//*****************/static DOUBLE tmpx; /* Store macro argument in tmpx to avoid re-evaluation */static LONG tmpi; /* Store converted value in tmpi to avoid re-evaluation */#define FABS(x) (((tmpx = (x)) < 0.0) ? -tmpx : tmpx)#define CEIL(x) (((tmpi = (LONG) (tmpx = (x))) < tmpx) ? ++tmpi : tmpi)#define FLOOR(x) (((tmpi = (LONG) (tmpx = (x))) > tmpx) ? --tmpi : tmpi)#endif#define ROUND(x) FLOOR((x) + 0.5)#define ODD(x) (((int)(x)) & 01)#define CC IfTrace1(TRUE, "Char \"%s\": ", currentchar)/* To make some compiler happy we have to care about return types! */#define Errori {errflag = TRUE; return 0;} /* integer */#define Errord {errflag = TRUE; return 0.0;} /* double */#define Errorv {errflag = TRUE; return;} /* void */ #define Error0i(errmsg) { CC; IfTrace0(TRUE, errmsg); Errori;}#define Error0d(errmsg) { CC; IfTrace0(TRUE, errmsg); Errord;}#define Error0v(errmsg) { CC; IfTrace0(TRUE, errmsg); Errorv;} #define Error1i(errmsg,arg) { CC; IfTrace1(TRUE, errmsg, arg); Errori;}#define Error1d(errmsg,arg) { CC; IfTrace1(TRUE, errmsg, arg); Errord;}#define Error1v(errmsg,arg) { CC; IfTrace1(TRUE, errmsg, arg); Errorv;} /********************//* global variables *//********************/struct stem { /* representation of a STEM hint */ int vertical; /* TRUE if vertical, FALSE otherwise */ DOUBLE x, dx; /* interval of vertical stem */ DOUBLE y, dy; /* interval of horizontal stem */ struct segment *lbhint, *lbrevhint; /* left or bottom hint adjustment */ struct segment *rthint, *rtrevhint; /* right or top hint adjustment */}; extern struct XYspace *IDENTITY; static DOUBLE escapementX, escapementY;static DOUBLE sidebearingX, sidebearingY;static DOUBLE accentoffsetX, accentoffsetY; static struct segment *path;static int errflag; /*************************************************//* Global variables to hold Type1Char parameters *//*************************************************/static char *Environment;static char *currentchar;static struct XYspace *CharSpace;static psobj *CharStringP, *SubrsP, *OtherSubrsP;static int *ModeP; /************************//* Forward declarations *//************************/static DOUBLE Div();static DOUBLE PSFakePop();static int DoCommand();static int Escape();static int HStem();static int VStem();static int RLineTo();static int RRCurveTo();static int DoClosePath();static int CallSubr();static int Return();static int EndChar();static int RMoveTo();static int DotSection();static int Seac();static int Sbw();static int CallOtherSubr();static int SetCurrentPoint();/*****************************************//* statics for Flex procedures (FlxProc) *//*****************************************/static struct segment *FlxOldPath; /* save path before Flex feature */ /******************************************************//* statics for Font level hints (Blues) (see blues.h) *//******************************************************/static struct blues_struct *blues; /* the blues structure */static struct alignmentzone alignmentzones[MAXALIGNMENTZONES];int numalignmentzones; /* total number of alignment zones */ /****************************************************************//* Subroutines for the Font level hints (Alignment zones, etc.) *//****************************************************************//* Flags to control the rasterizer */#define T1_IGNORE_FORCEBOLD 0x0001#define T1_IGNORE_FAMILYALIGNMENT 0x0002#define T1_IGNORE_HINTING 0x0004#define T1_DEBUG_LINE 0x0100#define T1_DEBUG_REGION 0x0200#define T1_DEBUG_PATH 0x0400#define T1_DEBUG_FONT 0x0800#define T1_DEBUG_HINT 0x1000int T1_Type1OperatorFlags; /* for manipulation from t1lib */static void SetRasterFlags( void){ if (T1_Type1OperatorFlags & T1_IGNORE_HINTING) ProcessHints=0; else ProcessHints=1; if ( T1_Type1OperatorFlags & T1_DEBUG_LINE) LineDebug=1; else LineDebug=0; if ( T1_Type1OperatorFlags & T1_DEBUG_REGION) RegionDebug=1; else RegionDebug=0; if ( T1_Type1OperatorFlags & T1_DEBUG_PATH) PathDebug=1; else PathDebug=0; if ( T1_Type1OperatorFlags & T1_DEBUG_FONT) FontDebug=1; else FontDebug=0; if ( T1_Type1OperatorFlags & T1_DEBUG_HINT) HintDebug=1; else HintDebug=0; return; }/******************************************//* Fill in the alignment zone structures. *//******************************************/static int ComputeAlignmentZones(){ int i; DOUBLE dummy, bluezonepixels, familyzonepixels; struct segment *p; numalignmentzones = 0; /* initialize total # of zones */ /* Remarks by RMz (Author of t1lib): The handling of substitution of the BlueValues by the FamilyBlues and correspondingly for the OtherBlues and FamilyOtherBlues is not clearly documented. These are the problems: 1) Does the number of FamilyBlues entries need to be identical to that of BlueValues? 2) Obviously, the order of the alignment zones in the BlueValues and the FamilyBlues need not be same (see TimesBold.pfa) 3) Is it wise/recommended to make the substitution on a per alignment-zone level or global, i.e., if once then for all zones? 4) The principle found below, checking the delta-height of an alignment-zone and making a decision based on this is incorrect. The decision has to be done according to absolute pixel values at which a feature would be rendered with the BlueValues and the FamilyBlues respectively. To conclude, it seems better to disable the Family-feature until these things are well-known/defined. */ /* do the BlueValues zones */ for (i = 0; i < blues->numBlueValues; i +=2, ++numalignmentzones) { /* the 0th & 1st numbers in BlueValues are for a bottom zone */ /* the rest are topzones */ if (i == 0) /* bottom zone */ alignmentzones[numalignmentzones].topzone = FALSE; else /* top zone */ alignmentzones[numalignmentzones].topzone = TRUE; /* Check FamilyAlignment suppression */ if ( (T1_Type1OperatorFlags & T1_IGNORE_FAMILYALIGNMENT)==0) { if (i < blues->numFamilyBlues) { /* we must consider FamilyBlues */ p = ILoc(CharSpace,0,blues->BlueValues[i] - blues->BlueValues[i+1]); QueryLoc(p, IDENTITY, &dummy, &bluezonepixels); Destroy(p); p = ILoc(CharSpace,0,blues->FamilyBlues[i] - blues->FamilyBlues[i+1]); QueryLoc(p, IDENTITY, &dummy, &familyzonepixels); Destroy(p); /* is the difference in size of the zones less than 1 pixel? */ if (FABS(bluezonepixels - familyzonepixels) < 1.0) { /* use the Family zones */ alignmentzones[numalignmentzones].bottomy = blues->FamilyBlues[i]; alignmentzones[numalignmentzones].topy = blues->FamilyBlues[i+1]; continue; } } } /* use this font's Blue zones */ alignmentzones[numalignmentzones].bottomy = blues->BlueValues[i]; alignmentzones[numalignmentzones].topy = blues->BlueValues[i+1]; } /* do the OtherBlues zones */ for (i = 0; i < blues->numOtherBlues; i +=2, ++numalignmentzones) { /* all of the OtherBlues zones are bottom zones */ alignmentzones[numalignmentzones].topzone = FALSE; /* Check FamilyAlignment suppression */ if ( (T1_Type1OperatorFlags & T1_IGNORE_FAMILYALIGNMENT)==0) { if (i < blues->numFamilyOtherBlues) {/* consider FamilyOtherBlues */ p = ILoc(CharSpace,0,blues->OtherBlues[i] - blues->OtherBlues[i+1]); QueryLoc(p, IDENTITY, &dummy, &bluezonepixels); Destroy(p); p = ILoc(CharSpace,0,blues->FamilyOtherBlues[i] - blues->FamilyOtherBlues[i+1]); QueryLoc(p, IDENTITY, &dummy, &familyzonepixels); Destroy(p); /* is the difference in size of the zones less than 1 pixel? */ if (FABS(bluezonepixels - familyzonepixels) < 1.0) { /* use the Family zones */ alignmentzones[numalignmentzones].bottomy = blues->FamilyOtherBlues[i]; alignmentzones[numalignmentzones].topy = blues->FamilyOtherBlues[i+1]; continue; } } } /* use this font's Blue zones (as opposed to the Family Blues */ alignmentzones[numalignmentzones].bottomy = blues->OtherBlues[i]; alignmentzones[numalignmentzones].topy = blues->OtherBlues[i+1]; } return(0); } /**********************************************************************//* Subroutines and statics for handling of the VSTEM and HSTEM hints. *//**********************************************************************/int InDotSection; /* DotSection flag */struct stem stems[MAXSTEMS]; /* All STEM hints */int numstems; /* Number of STEM hints */int currstartstem; /* The current starting stem. */int oldvert, oldhor; /* Remember hint in effect */int oldhorhalf, oldverthalf; /* Remember which half of the stem */DOUBLE wsoffsetX, wsoffsetY; /* White space offset - for VSTEM3,HSTEM3 */int wsset; /* Flag for whether we've set wsoffsetX,Y */ static int InitStems() /* Initialize the STEM hint data structures */{ InDotSection = FALSE; currstartstem = numstems = 0; oldvert = oldhor = -1; return(0); } static int FinitStems() /* Terminate the STEM hint data structures */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -