📄 type1.c
字号:
{ int i; for (i = 0; i < numstems; i++) { Destroy(stems[i].lbhint); Destroy(stems[i].lbrevhint); Destroy(stems[i].rthint); Destroy(stems[i].rtrevhint); } return(0); } /*******************************************************************//* Compute the dislocation that a stemhint should cause for points *//* inside the stem. *//*******************************************************************/static int ComputeStem(stemno)int stemno;{ int verticalondevice, idealwidth; DOUBLE stemstart, stemwidth; struct segment *p; int i; DOUBLE stembottom, stemtop, flatposition; DOUBLE Xpixels, Ypixels; DOUBLE unitpixels, onepixel; int suppressovershoot, enforceovershoot; DOUBLE stemshift, flatpospixels, overshoot; DOUBLE widthdiff; /* Number of character space units to adjust width */ DOUBLE lbhintvalue, rthintvalue; DOUBLE cxx, cyx, cxy, cyy; /* Transformation matrix */ int rotated; /* TRUE if character is on the side, FALSE if upright */ /************************************************/ /* DETERMINE ORIENTATION OF CHARACTER ON DEVICE */ /************************************************/ QuerySpace(CharSpace, &cxx, &cyx, &cxy, &cyy); /* Transformation matrix */ if (FABS(cxx) < 0.00001 || FABS(cyy) < 0.00001) rotated = TRUE; /* Char is on side (90 or 270 degrees), possibly oblique. */ else if (FABS(cyx) < 0.00001 || FABS(cxy) < 0.00001) rotated = FALSE; /* Char is upright (0 or 180 degrees), possibly oblique. */ else { stems[stemno].lbhint = NULL; /* Char is at non-axial angle, ignore hints. */ stems[stemno].lbrevhint = NULL; stems[stemno].rthint = NULL; stems[stemno].rtrevhint = NULL; return(0); } /* Determine orientation of stem */ if (stems[stemno].vertical) { verticalondevice = !rotated; stemstart = stems[stemno].x; stemwidth = stems[stemno].dx; } else { verticalondevice = rotated; stemstart = stems[stemno].y; stemwidth = stems[stemno].dy; } /* Determine how many pixels (non-negative) correspond to 1 character space unit (unitpixels), and how many character space units (non-negative) correspond to one pixel (onepixel). */ if (stems[stemno].vertical) p = ILoc(CharSpace, 1, 0); else p = ILoc(CharSpace, 0, 1); QueryLoc(p, IDENTITY, &Xpixels, &Ypixels); Destroy(p); if (verticalondevice) unitpixels = FABS(Xpixels); else unitpixels = FABS(Ypixels); onepixel = 1.0 / unitpixels; /**********************/ /* ADJUST STEM WIDTHS */ /**********************/ widthdiff = 0.0; /* Find standard stem with smallest width difference from this stem */ if (stems[stemno].vertical) { /* vertical stem */ if (blues->StdVW != 0) /* there is an entry for StdVW */ widthdiff = blues->StdVW - stemwidth; for (i = 0; i < blues->numStemSnapV; ++i) { /* now look at StemSnapV */ if (FABS(blues->StemSnapV[i] - stemwidth) < FABS(widthdiff)) /* this standard width is the best match so far for this stem */ widthdiff = blues->StemSnapV[i] - stemwidth; } } else { /* horizontal stem */ if (blues->StdHW != 0) /* there is an entry for StdHW */ widthdiff = blues->StdHW - stemwidth; for (i = 0; i < blues->numStemSnapH; ++i) { /* now look at StemSnapH */ if (FABS(blues->StemSnapH[i] - stemwidth) < FABS(widthdiff)) /* this standard width is the best match so far for this stem */ widthdiff = blues->StemSnapH[i] - stemwidth; } } /* Only expand or contract stems if they differ by less than 1 pixel from the closest standard width, otherwise make the width difference = 0. */ if (FABS(widthdiff) > onepixel) widthdiff = 0.0; /* Expand or contract stem to the nearest integral number of pixels. */ idealwidth = ROUND((stemwidth + widthdiff) * unitpixels); /* Ensure that all stems are at least one pixel wide. */ if (idealwidth == 0) idealwidth = 1; /* Apply ForceBold to vertical stems. */ if (blues->ForceBold && stems[stemno].vertical && ((T1_Type1OperatorFlags & T1_IGNORE_FORCEBOLD)==0)) /* Force this vertical stem to be at least DEFAULTBOLDSTEMWIDTH wide. */ if (idealwidth < DEFAULTBOLDSTEMWIDTH) idealwidth = DEFAULTBOLDSTEMWIDTH; /* Now compute the number of character space units necessary */ widthdiff = idealwidth * onepixel - stemwidth; /*********************************************************************/ /* ALIGNMENT ZONES AND OVERSHOOT SUPPRESSION - HORIZONTAL STEMS ONLY */ /*********************************************************************/ stemshift = 0.0; if (!stems[stemno].vertical) { /* Get bottom and top boundaries of the stem. */ stembottom = stemstart; stemtop = stemstart + stemwidth; /* Find out if this stem intersects an alignment zone (the BlueFuzz */ /* entry in the Private dictionary specifies the number of character */ /* units to extend (in both directions) the effect of an alignment */ /* zone on a horizontal stem. The default value of BlueFuzz is 1. */ for (i = 0; i < numalignmentzones; ++i) { if (alignmentzones[i].topzone) { if (stemtop >= alignmentzones[i].bottomy && stemtop <= alignmentzones[i].topy + blues->BlueFuzz) { break; /* We found a top-zone */ } } else { if (stembottom <= alignmentzones[i].topy && stembottom >= alignmentzones[i].bottomy - blues->BlueFuzz) { break; /* We found a bottom-zone */ } } } if (i < numalignmentzones) { /* We found an intersecting zone (number i). */ suppressovershoot = FALSE; enforceovershoot = FALSE; /* When 1 character space unit is rendered smaller than BlueScale device units (pixels), we must SUPPRESS overshoots. Otherwise, if the top (or bottom) of this stem is more than BlueShift character space units away from the flat position, we must ENFORCE overshoot. */ 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(0); } /* 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)); } return(0); } #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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -