📄 type1.c
字号:
if (unitpixels < blues->BlueScale) suppressovershoot = TRUE; else if (alignmentzones[i].topzone) if (stemtop >= alignmentzones[i].bottomy + blues->BlueShift) enforceovershoot = TRUE; else if (stembottom <= alignmentzones[i].topy - blues->BlueShift) enforceovershoot = TRUE; /*************************************************/ /* ALIGN THE FLAT POSITION OF THE ALIGNMENT ZONE */ /*************************************************/ /* Compute the position of the alignment zone's flat position in device space and the amount of shift needed to align it on a pixel boundary. Move all stems this amount. */ if (alignmentzones[i].topzone) flatposition = alignmentzones[i].bottomy; else flatposition = alignmentzones[i].topy; /* Find the flat position in pixels */ flatpospixels = flatposition * unitpixels; /* Find the stem shift necessary to align the flat position on a pixel boundary, and use this shift for all stems */ stemshift = (ROUND(flatpospixels) - flatpospixels) * onepixel; /************************************************/ /* HANDLE OVERSHOOT ENFORCEMENT AND SUPPRESSION */ /************************************************/ /* Compute overshoot amount (non-negative) */ if (alignmentzones[i].topzone) overshoot = stemtop - flatposition; else overshoot = flatposition - stembottom; if (overshoot > 0.0) { /* ENFORCE overshoot by shifting the entire stem (if necessary) so that it falls at least one pixel beyond the flat position. */ if (enforceovershoot) if (overshoot < onepixel) if (alignmentzones[i].topzone) stemshift += onepixel - overshoot; else stemshift -= onepixel - overshoot; /* SUPPRESS overshoot by aligning the stem to the alignment zone's flat position. */ if (suppressovershoot) if (alignmentzones[i].topzone) stemshift -= overshoot; else stemshift += overshoot; } /************************************************************/ /* COMPUTE HINT VALUES FOR EACH SIDE OF THE HORIZONTAL STEM */ /************************************************************/ /* If the stem was aligned by a topzone, we expand or contract the stem only at the bottom - since the stem top was aligned by the zone. If the stem was aligned by a bottomzone, we expand or contract the stem only at the top - since the stem bottom was aligned by the zone. */ if (alignmentzones[i].topzone) { lbhintvalue = stemshift - widthdiff; /* bottom */ rthintvalue = stemshift; /* top */ } else { lbhintvalue = stemshift; /* bottom */ rthintvalue = stemshift + widthdiff; /* top */ } stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, lbhintvalue)); stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue)); stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, 0.0, rthintvalue)); stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue)); return; } /* endif (i < numalignmentzones) */ /* We didn't find any alignment zones intersecting this stem, so proceed with normal stem alignment below. */ } /* endif (!stems[stemno].vertical) */ /* Align stem with pixel boundaries on device */ stemstart = stemstart - widthdiff / 2; stemshift = ROUND(stemstart * unitpixels) * onepixel - stemstart; /* Adjust the boundaries of the stem */ lbhintvalue = stemshift - widthdiff / 2; /* left or bottom */ rthintvalue = stemshift + widthdiff / 2; /* right or top */ if (stems[stemno].vertical) { stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, lbhintvalue, 0.0)); stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, -lbhintvalue, 0.0)); stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, rthintvalue, 0.0)); stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, -rthintvalue, 0.0)); } else { stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, lbhintvalue)); stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue)); stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, 0.0, rthintvalue)); stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue)); }} #define LEFT 1#define RIGHT 2#define BOTTOM 3#define TOP 4 /*********************************************************************//* Adjust a point using the given stem hint. Use the left/bottom *//* hint value or the right/top hint value depending on where the *//* point lies in the stem. *//*********************************************************************/static struct segment *Applyhint(p, stemnumber, half)struct segment *p;int stemnumber, half;{ if (half == LEFT || half == BOTTOM) return Join(p, stems[stemnumber].lbhint); /* left or bottom hint */ else return Join(p, stems[stemnumber].rthint); /* right or top hint */} /*********************************************************************//* Adjust a point using the given reverse hint. Use the left/bottom *//* hint value or the right/top hint value depending on where the *//* point lies in the stem. *//*********************************************************************/static struct segment *Applyrevhint(p, stemnumber, half)struct segment *p;int stemnumber, half;{ if (half == LEFT || half == BOTTOM) return Join(p, stems[stemnumber].lbrevhint); /* left or bottom hint */ else return Join(p, stems[stemnumber].rtrevhint); /* right or top hint */} /***********************************************************************//* Find the vertical and horizontal stems that the current point *//* (x, y) may be involved in. At most one horizontal and one vertical *//* stem can apply to a single point, since there are no overlaps *//* allowed. *//* The actual hintvalue is returned as a location. *//* Hints are ignored inside a DotSection. *//***********************************************************************/static struct segment *FindStems(x, y, dx, dy)double x, y, dx, dy;{ int i; int newvert, newhor; struct segment *p; int newhorhalf, newverthalf; if (InDotSection) return(NULL); newvert = newhor = -1; newhorhalf = newverthalf = -1; for (i = currstartstem; i < numstems; i++) { if (stems[i].vertical) { /* VSTEM hint */ if ((x >= stems[i].x - EPS) && (x <= stems[i].x+stems[i].dx + EPS)) { newvert = i; if (dy != 0.0) { if (dy < 0) newverthalf = LEFT; else newverthalf = RIGHT; } else { if (x < stems[i].x+stems[i].dx / 2) newverthalf = LEFT; else newverthalf = RIGHT; } } } else { /* HSTEM hint */ if ((y >= stems[i].y - EPS) && (y <= stems[i].y+stems[i].dy + EPS)) { newhor = i; if (dx != 0.0) { if (dx < 0) newhorhalf = TOP; else newhorhalf = BOTTOM; } else { if (y < stems[i].y+stems[i].dy / 2) newhorhalf = BOTTOM; else newhorhalf = TOP; } } } } p = NULL; if (newvert == -1 && oldvert == -1) ; /* Outside of any hints */ else if (newvert == oldvert && newverthalf == oldverthalf); /* No hint change */ else if (oldvert == -1) { /* New vertical hint in effect */ p = Applyhint(p, newvert, newverthalf); } else if (newvert == -1) { /* Old vertical hint no longer in effect */ p = Applyrevhint(p, oldvert, oldverthalf); } else { /* New vertical hint in effect, old hint no longer in effect */ p = Applyrevhint(p, oldvert, oldverthalf); p = Applyhint(p, newvert, newverthalf); } if (newhor == -1 && oldhor == -1) ; /* Outside of any hints */ else if (newhor == oldhor && newhorhalf == oldhorhalf) ; /* No hint change */ else if (oldhor == -1) { /* New horizontal hint in effect */ p = Applyhint(p, newhor, newhorhalf); } else if (newhor == -1) { /* Old horizontal hint no longer in effect */ p = Applyrevhint(p, oldhor, oldhorhalf); } else { /* New horizontal hint in effect, old hint no longer in effect */ p = Applyrevhint(p, oldhor, oldhorhalf); p = Applyhint(p, newhor, newhorhalf); } oldvert = newvert; oldverthalf = newverthalf; oldhor = newhor; oldhorhalf = newhorhalf; return p;} /******************************************************//* Subroutines and statics for the Type1Char routines *//******************************************************/ static int strindex; /* index into PostScript string being interpreted */static double currx, curry; /* accumulated x and y values for hints */ struct callstackentry { psobj *currstrP; /* current CharStringP */ int currindex; /* current strindex */ unsigned short currkey; /* current decryption key */ }; static double Stack[MAXSTACK];static int Top;static struct callstackentry CallStack[MAXCALLSTACK];static int CallTop;static double PSFakeStack[MAXPSFAKESTACK];static int PSFakeTop; static ClearStack(){ Top = -1;} static Push(Num) double Num;{ if (++Top < MAXSTACK) Stack[Top] = Num; else Error0("Push: Stack full\n");} static ClearCallStack(){ CallTop = -1;} static PushCall(CurrStrP, CurrIndex, CurrKey) psobj *CurrStrP; int CurrIndex; unsigned short CurrKey;{ if (++CallTop < MAXCALLSTACK) { CallStack[CallTop].currstrP = CurrStrP; /* save CharString pointer */ CallStack[CallTop].currindex = CurrIndex; /* save CharString index */ CallStack[CallTop].currkey = CurrKey; /* save decryption key */ } else Error0("PushCall: Stack full\n");} static PopCall(CurrStrPP, CurrIndexP, CurrKeyP) psobj **CurrStrPP; int *CurrIndexP; unsigned short *CurrKeyP;{ if (CallTop >= 0) { *CurrStrPP = CallStack[CallTop].currstrP; /* restore CharString pointer */ *CurrIndexP = CallStack[CallTop].currindex; /* restore CharString index */ *CurrKeyP = CallStack[CallTop--].currkey; /* restore decryption key */ } else Error0("PopCall: Stack empty\n");} static ClearPSFakeStack(){ PSFakeTop = -1;} /* PSFakePush: Pushes a number onto the fake PostScript stack */static PSFakePush(Num) double Num;{ if (++PSFakeTop < MAXPSFAKESTACK) PSFakeStack[PSFakeTop] = Num; else Error0("PSFakePush: Stack full\n");} /* PSFakePop: Removes a number from the top of the fake PostScript stack */static double PSFakePop (){ if (PSFakeTop >= 0) return(PSFakeStack[PSFakeTop--]); else Error0Ret("PSFakePop : Stack empty\n", 0.0); /*NOTREACHED*/} /***********************************************************************//* Center a stem on the pixel grid -- used by HStem3 and VStem3 *//***********************************************************************/static struct segment *CenterStem(edge1, edge2) double edge1; double edge2;{ int idealwidth, verticalondevice; double leftx, lefty, rightx, righty, center, width; double widthx, widthy; double shift, shiftx, shifty; double Xpixels, Ypixels; struct segment *p; p = Loc(CharSpace, edge1, 0.0); QueryLoc(p, IDENTITY, &leftx, &lefty); p = Join(p, Loc(CharSpace, edge2, 0.0)); QueryLoc(p, IDENTITY, &rightx, &righty); Destroy(p); widthx = FABS(rightx - leftx); widthy = FABS(righty - lefty); if (widthy <= EPS) { /* verticalondevice hint */ verticalondevice = TRUE; center = (rightx + leftx) / 2.0; width = widthx; } else if (widthx <= EPS) { /* horizontal hint */ verticalondevice = FALSE; center = (righty + lefty) / 2.0; width = widthy; } else { /* neither horizontal nor verticalondevice and not oblique */ return (NULL); } idealwidth = ROUND(width); if (idealwidth == 0) idealwidth = 1; if (ODD(idealwidth)) { /* is ideal width odd? */ /* center stem over pixel */ shift = FLOOR(center) + 0.5 - center; } else { /* align stem on pixel boundary */ shift = ROUND(center) - center; } if (verticalondevice) { shiftx = shift; shifty = 0.0; } else { shifty = shift; shiftx = 0.0; } p = Loc(IDENTITY, shiftx, shifty); QueryLoc(p, CharSpace, &Xpixels, &Ypixels); wsoffsetX = Xpixels; wsoffsetY = Ypixels; currx += wsoffsetX; curry += wsoffsetY; return (p);} /*----------------------------------------------------------------------- Decrypt - From Adobe Type 1 book page 63, with some modifications-----------------------------------------------------------------------*/#define KEY 4330 /* Initial key (seed) for CharStrings decryption */#define C1 52845 /* Multiplier for pseudo-random number generator */#define C2 22719 /* Constant for pseudo-random number generator */ static unsigned short r; /* Pseudo-random sequence of keys */ static unsigned char Decrypt(cipher)unsigned char cipher;{ unsigned char plain; plain = cipher ^ (r >> 8); r = (cipher + r) * C1 + C2; return plain;} /* Get the next byte from the codestring being interpreted */static int DoRead(CodeP) int *CodeP;{ if (strindex >= CharStringP->len) return(FALSE); /* end of string */ *CodeP = Decrypt((unsigned char) CharStringP->data.stringP[strindex++]); return(TRUE);} /* Strip blues->lenIV bytes from CharString and update encryption key *//* (the lenIV entry in the Private dictionary specifies the number of *//* random bytes at the beginning of each CharString; default is 4) */static void StartDecrypt(){ int Code; r = KEY; /* Initial key (seed) for CharStrings decryption */ for (strindex = 0; strindex < blues->lenIV;) if (!DoRead(&Code)) /* Read a byte and update decryption key */ Error0("StartDecrypt: Premature end of CharString\n");} static Decode(Code) int Code;{ int Code1, Code2, Code3, Code4; if (Code <= 31) /* Code is [0,31] */ DoCommand(Code); else if (Code <= 246) /* Code is [32,246] */ Push((double)(Code - 139)); else if (Code <= 250) { /* Code is [247,250] */ if (!DoRead(&Code2)) goto ended; Push((double)(((Code - 247) << 8) + Code2 + 108)); } else if (Code <= 254) { /* Code is [251,254] */ if (!DoRead(&Code2)) goto ended; Push((double)( -((Code - 251) << 8) - Code2 - 108)); } else { /* Code is 255 */ if (!DoRead(&Code1)) goto ended; if (!DoRead(&Code2)) goto ended; if (!DoRead(&Code3)) goto ended; if (!DoRead(&Code4)) goto ended; Push((double)((((((Code1<<8) + Code2)<<8) + Code3)<<8) + Code4)); } return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -