📄 ptotdll.c
字号:
}static int ParseEncoding(T *t, char *instr) { /* Parse first line of QE directive. */ int e = ReadInt(&instr); int n = ReadInt(&instr); int i; if (e<0) return PSTOTEXT_FILTER_BADENCODINGNUMBER; if (n>/*256*/1024) return PSTOTEXT_FILTER_TOOMANYGLYPHINDEXES; /* Grow "t->encoding" if necessary. */ if (t->encodingSize<=e) { int oldSize = t->encodingSize; t->encodingSize = 2*e; t->encoding = (EncodingTable *)realloc( (char *)t->encoding, t->encodingSize * sizeof(Encoding) ); for(i=oldSize;i<t->encodingSize;i++)(*t->encoding)[i] = NULL; } /* If this is the first encoding numbered "e", allocate array. */ if ((*t->encoding)[e] == NULL) (*t->encoding)[e] = (EncodingVector *)malloc(sizeof(EncodingVector)); t-> state = state_encoding; t->encoding_e = e; t->encoding_n = n; t->encoding_i = 0; return 0;}static int ParseEncodingMore(T *t, char *instr) { /* Parse subsequent line of QE directive. */ Encoding enc = (*t->encoding)[t->encoding_e]; int i, tooSparse; for (i = t->encoding_i; i<t->encoding_i+16 ; i++) (*enc)[i] = (i<t->encoding_n) ? ReadInt(&instr) : NonstandardGlyph; t->encoding_i += 16; if (t->encoding_i < 256) /* skip */ ; else { /* End of directive. */ t->state = state_normal; /* Some applications build the encoding vector incrementally. If this one doesn't have at least the lower-case letters, we augment it with ISOLatin1. */ tooSparse = 0; for (i = 'a'; i<='z'; i++) tooSparse = (*enc)[i] == NonstandardGlyph; if (tooSparse) for (i = 0; i<256; i++) if ((*enc)[i] == NonstandardGlyph) (*enc)[i] = i; } return 0;}#define GuessAscend 0.9#define GuessDescend -0.3static void ReadPair(double /*out*/ *x, /*out*/ double *y, char **instr) { *x = ReadLong(instr) / 100.0; *y = ReadLong(instr) / 100.0;}static int ParseFont(T *t, char *instr) { /* Parse QF directive. */ int n = ReadInt(&instr), i; Metrics mt; Font f; double xmax, bly, topry; if (n<0) return PSTOTEXT_FILTER_BADFONTNUMBER; /* Grow "t->font" if necessary. */ if (t->fontSize<=n) { int oldSize = t->fontSize; t->fontSize = 2*n; t->font = (FontTable *)realloc( (char *)t->font, t->fontSize * sizeof(Font) ); for(i=oldSize;i<t->fontSize;i++)(*t->font)[i] = NULL; } /* If this is the first font numbered "n", allocate "FontRec". */ if ((*t->font)[n] == NULL) (*t->font)[n] = (Font)malloc(sizeof(FontRec)); f = (*t->font)[n]; ReadPair(&f->x, &f->y, &instr); ReadPair(&f->xp, &f->yp, &instr); f->e = ReadInt(&instr); if ((*t->encoding)[f->e] == NULL) return PSTOTEXT_FILTER_BADENCODINGNUMBER; f->m = ReadInt(&instr); mt = (*t->metrics)[f->m]; if (mt == NULL) return PSTOTEXT_FILTER_BADMETRICNUMBER; /* Transform height of font bounding box to reporting coordinates: */ f->bx = f->xp * mt->bly / 1000.0; f->by = f->yp * mt->bly / 1000.0; f->tx = f->xp * mt->topry / 1000.0; f->ty = f->yp * mt->topry / 1000.0; /* In some fonts produced by dvips, the FontBBox is incorrectly defined as [0 0 1 1]. We check for this, and apply the same heuristic used for an undefined FontBBox in "ParseMetrics". */ if (f->by-f->ty < 1.1) { xmax = 0.0; for (i = 0; i<256; i++) if (mt->chr[i].x > xmax) xmax = mt->chr[i].x; bly = GuessDescend * xmax; topry = GuessAscend * xmax; f->bx = f->xp * bly / 1000.0; f->by = f->yp * bly / 1000.0; f->tx = f->xp * topry / 1000.0; f->ty = f->yp * topry / 1000.0; } return 0;}static int ParseMetrics(T *t, char *instr) { /* Parse first line of QM directive. */ int m = ReadInt(&instr), i; Metrics mt; if (m<0) return PSTOTEXT_FILTER_BADMETRICNUMBER; /* Grow "t->metrics" if necessary. */ if (t->metricsSize<=m) { int oldSize = t->metricsSize; t->metricsSize = 2*m; t->metrics = (MetricsTable *)realloc( (char *)t->metrics, t->metricsSize * sizeof(Metrics) ); for (i=oldSize;i<t->metricsSize;i++)(*t->metrics)[i] = NULL; } /* If this is the first metrics numbered "m", allocate "MetricsRec". */ if ((*t->metrics)[m] == NULL) (*t->metrics)[m] = (Metrics)malloc(sizeof(MetricsRec)); mt = (*t->metrics)[m]; ReadPair(&mt->blx, &mt->bly, &instr); ReadPair(&mt->toprx, &mt->topry, &instr); t->state = state_metrics; t->metrics_m = m; t->metrics_i = 0; return 0;}static int ParseMetricsMore(T *t, char *instr) { /* Parse subsequent line of QM directive. */ int i; Metrics mt = (*t->metrics)[t->metrics_m]; for (i = t->metrics_i; i<t->metrics_i+8; i++) ReadPair(&mt->chr[i].x, &mt->chr[i].y, &instr); t->metrics_i += 8; if (t->metrics_i < 256) /* skip */ ; else { /* End of directive. */ t->state = state_normal; /* If "FontBBox" was not specified, take a guess. */ if (mt->blx == 0.0 && mt->bly == 0.0 && mt->toprx == 0.0 && mt->topry == 0.0) { for (i = 0; i<256; i++) if (mt->chr[i].x > mt->toprx) mt->toprx = mt->chr[i].x; mt->bly = GuessDescend * mt->toprx; mt->topry = GuessAscend * mt->toprx; } } return 0;}static void Itransform(T *t, double *x1, double *y1, double x0, double y0) {/* Set (*x1, *y1) to (t->itransform) * (x0, y0). */ *x1 = t->itransform[0]*x0 + t->itransform[2]*y0 + t->itransform[4]; *y1 = t->itransform[1]*x0 + t->itransform[3]*y0 + t->itransform[5];}static void Output(T *t, const char **pre, const char **word, int *llx, int *lly, int *urx, int *ury) { /* Output the next word. */ double x0, y0, x1, y1, x2, y2, x3, y3; long blx, bly, toprx, topry, mid; Font f; f = (*t->font)[t->f]; /* Compute the corners of the parallelogram with width "(t->x0,t->y0)" to "(t->x1,t->y1)" and height "(f.bx,f.by)" to "(f.tx,f.ty)". Then compute the bottom left corner and the top right corner of the bounding box (rectangle with sides parallel to the coordinate system) of this rectangle. */ x0 = t->x0 + f->bx; y0 = t->y0 + f->by; x1 = t->x1 + f->bx; y1 = t->y1 + f->by; x2 = t->x0 + f->tx; y2 = t->y0 + f->ty; x3 = t->x1 + f->tx; y3 = t->y1 + f->ty; blx = (long)ceil(MIN(MIN(MIN(x0, x1), x2), x3)); bly = (long)ceil(MAX(MAX(MAX(y0, y1), y2), y3)); /* *** should this be floor? PMcJ 981002 */ toprx = (long)floor(MAX(MAX(MAX(x0, x1), x2), x3)); topry = (long)floor(MIN(MIN(MIN(y0, y1), y2), y3)); /* *** should this be ceil? PMcJ 981002 */ if (blx!=toprx && bly!=topry) { /* Output word separator if this isn't first word on page. */ if (t->nonEmptyPage) { mid = (topry+bly) / 2; if (blx<toprx && topry<bly && t->blx <= blx && t->topry <= mid && mid <= t->bly) *pre = " "; /* same line */ else *pre = "\n"; /* different line */ } else *pre = ""; /* Output elements "0" through "t->lbuf-1" of "t->buf". */ t->buf[t->lbuf] = '\0'; strncpy(t->word, t->buf, t->lbuf+1); *word = t->word; t->nonEmptyPage = TRUE; t->blx = blx; t->bly = bly; t->toprx = toprx; t->topry = topry; /* transform device units to default PostScript units */ Itransform( t, &x1, &y1, (double)blx, (double)bly); blx = (long)floor(x1); bly = (long)floor(y1); Itransform( t, &x1, &y1, (double)toprx, (double)topry); toprx = (long)ceil(x1); topry = (long)ceil(y1); if (blx < toprx) { *llx = blx; *urx = toprx; } else { *llx = toprx; *urx = blx; } if (bly < topry) { *lly = bly; *ury = topry; } else { *lly = topry; *ury = bly; } } /*if (blx!=toprx && bly!=topry) { */ t->lbuf = 0;}static BOOLEAN SameDirection(double x0, double y0, double x1, double y1) { return (y0 == 0.0 && y1 == 0.0 && x0*x1 > 0.0) || (x0 == 0.0 && x1 == 0.0 && y0*y1 > 0.0) || (x0 * y1 == x1 * y0);}static int ParseString(T *t, char *instr, const char **pre, const char **word, const char **post, int *llx, int *lly, int *urx, int *ury) { /* Parse QS directive. */#define spaceTol 0.3 /* fraction of average character width to signal word break */ char buf[1000]; int n, ch, i, j, in, l; Font f; Encoding enc; GlyphIndex glyph; double x0, y0, x1, y1, xsp, ysp, dx, dy, maxx, maxy;#define SetBuf() \ { \ strncpy(t->buf, buf, l); \ t->lbuf = l; \ t->f = n; \ t->x0 = x0; t->y0 = y0; t->x1 = x1; t->y1 = y1; \ } n = ReadInt(&instr); /* index in "t->font" */ f = (*t->font)[n]; if (f == NULL) return PSTOTEXT_FILTER_BADFONTNUMBER; enc = (*t->encoding)[f->e]; if (enc==NULL) return PSTOTEXT_FILTER_BADENCODINGNUMBER; ReadPair(&x0, &y0, &instr); /* initial currentpoint */ j = ReadInt(&instr); /* length of string */ ch = ReadChar(&instr); if (ch != ' ') return PSTOTEXT_FILTER_BADQS; l = 0; for (i = 0; i<=j-1; i++) { in = ReadChar(&instr); /* if (in=='\0') return PSTOTEXT_FILTER_BADQS; */ /* TeX uses '\0' */ glyph = (*enc)[in]; /* If "glyph==0", then "in" mapped to the glyph ".notdef". This is usually a mistake, but we check for several known cases: */ if (glyph == 0) { /* If any element of the current encoding is in the range used by Microsoft TrueType, assume this character is, too. */ int k; BOOLEAN tt = FALSE; for(k = 0; !tt && k < sizeof(*enc)/sizeof((*enc)[0]); k++) { if (FirstTT1 <= (*enc)[k] && (*enc)[k] <= LastTT2) tt = TRUE; } if (tt) glyph = FirstTT1 + (int)in; /* There are too many other exceptions to actually trap this: else if (in == '\r') ; // Adobe Illustrator does this... else if (in == '\t') ; // MacDraw Pro does this... else if (in == '\032') ; // MS Word on Mac does this... else return PSTOTEXT_FILTER_BADGLYPHINDEX; */ } if (glyph == 0) /* skip */; else if (glyph <= LastISOLatin1) { buf[l] = (char)glyph; /* *** if (glyph IN ISOLatin1Gaps) buf[l] = UnknownChar; */ l++; } else if (glyph <= LASTSpecialGlyphs) { const char *str = SpecialGlyphs[glyph-FIRSTSpecialGlyphs]; int lstr = strlen(str); strncpy(&buf[l], str, lstr); l += lstr; } else if (glyph <= LastDvips) { const char *str; int lstr; char tempstr[2]; if (t->dvipsIsCork) { if (glyph <= LASTCorkSpecialGlyphs) str = CorkSpecialGlyphs[glyph-FIRSTCorkSpecialGlyphs]; else if (glyph == FIRSTCorkSpecialGlyphs+0337) str = "SS"; else if (glyph == FIRSTCorkSpecialGlyphs+0377) str = "\337"; else { tempstr[0] = (char)(glyph-FIRSTCorkSpecialGlyphs); tempstr[1] = '\0'; str = &tempstr[0]; } } else if (glyph <= LASTDvipsGlyphs) /* Assume old text layout (OT1?). */ str = DvipsGlyphs[glyph-FIRSTDvipsGlyphs]; else { tempstr[0] = UnknownChar; tempstr[1] = '\0'; str = &tempstr[0]; } lstr = strlen(str); strncpy(&buf[l], str, lstr); l += lstr; } else if (glyph <= LastTT2) { if (FirstTT2 <= glyph) glyph -= FirstTT2-FirstTT1; if (glyph < FirstTT1+32) { buf[l] = UnknownChar; l++; } else if (glyph < FIRSTTTSpecialGlyphs || LASTTTSpecialGlyphs < glyph) { buf[l] = (char)(glyph - FirstTT1); l++; } else { const char *str = TTSpecialGlyphs[glyph-FIRSTTTSpecialGlyphs]; int lstr = strlen(str); strncpy(&buf[l], str, lstr); l += lstr; } } else if (glyph <= LastOldDvips) { const char *str = DvipsGlyphs[glyph-FirstOldDvips]; int lstr = strlen(str); strncpy(&buf[l], str, lstr); l += lstr; } else if (glyph == NonstandardGlyph) { /* not in StandardGlyphs */ buf[l] = UnknownChar; l++; } else return PSTOTEXT_FILTER_BADGLYPHINDEX; /* We no longer substitute minus for hyphen. */ /* if (buf[l-1] == '\255') buf[l-1] = '-'; */ } ReadPair(&x1, &y1, &instr); /* final currentpoint */ if (l != 0) { /* "l==0" e.g., when Adobe Illustrator outputs "\r" */ if (t->lbuf == 0) {SetBuf();} else { /* If the distance between this string and the previous one is less than "spaceTol" times the minimum of the average character widths in the two strings, and the two strings are in the same direction, then append this string to the previous one. Otherwise, output the previous string and then save the current one. Sometimes this string overlaps the previous string, e.g., when TeX is overprinting an accent over another character. So we make a special case for this (but only handle the left-to-right orientation). */ /* Set "(xsp,ysp)" to the reporting space coordinates of the minimum of the average width of the characters in this string and the previous one. */ xsp = MIN((t->x1-t->x0) / t->lbuf, (x1-x0) / l); ysp = MIN((t->y1-t->y0) / t->lbuf, (y1-y0) / l); dx = x0 - t->x1; dy = y0 - t->y1; maxx = spaceTol * xsp; maxy = spaceTol * ysp; if ((dx*dx + dy*dy < maxx*maxx + maxy*maxy) || ((t->y1 == y0 && t->x0 <= t->x1 && t->x0 <= x0 && x0 <= t->x1) && SameDirection(t->x1-t->x0, t->y1-t->y0, x1-x0, y1-y0))) { if (t->lbuf+l >= sizeof(t->buf)) { Output(t, pre, word, llx, lly, urx, ury); *post = ""; SetBuf(); } else { strncpy(&t->buf[t->lbuf], buf, l); t->lbuf += l; t->x1 = x1; t->y1 = y1; /* *** Merge font bounding boxes? */ } } else { Output(t, pre, word, llx, lly, urx, ury); *post = ""; SetBuf(); } } } return 0;}int DLLEXPORT pstotextFilter(void *instance, char *instr, const char **pre, const char **word, const char **post, int *llx, int *lly, int *urx, int *ury) { T *t = (T *)instance; int c; *word = NULL; switch (t->state) { case state_normal: do {c = ReadChar(&instr); if (c=='\0') return 0;} while (c!='Q'); c = ReadChar(&instr); switch (c) { case 'I': return ParseInverseTransform(t, instr); case 'M': return ParseMetrics(t, instr); case 'E': return ParseEncoding(t, instr); case 'F': return ParseFont(t, instr); case 'S': return ParseString( t, instr, pre, word, post, llx, lly, urx, ury); case 'C': case 'P': /* copypage, showpage */ /* If any QS directives have been encountered on this page, t->buf will be nonempty now. */ if (t->lbuf > 0) { Output(t, pre, word, llx, lly, urx, ury); *post = "\n\f\n"; } else { *pre = ""; *word = ""; *llx = 0; *lly = 0; *urx = 0; *ury = 0; *post = "\f\n"; } t->nonEmptyPage = FALSE; t->blx = t->bly = t->toprx = t->topry = 0; break; case 'Z': /* erasepage */ /* skip */ break; case '\0': return 0; /* default: skip */ } break; case state_metrics: return ParseMetricsMore(t, instr); case state_encoding: return ParseEncodingMore(t, instr); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -