Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/TextOutputDev.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/unsupported/qpdf/xpdf/TextOutputDev.cc | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc index aa9366a..d3b0137 100644 --- a/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc +++ b/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc @@ -1,11 +1,11 @@ //======================================================================== // // TextOutputDev.cc // -// Copyright 1997 Derek B. Noonburg +// Copyright 1997-2002 Glyph & Cog, LLC // //======================================================================== #ifdef __GNUC__ #pragma implementation #endif @@ -45,12 +45,18 @@ TextString::TextString(GfxState *state, fouble fontSize) { } else { // this means that the PDF file draws text without a current font, // which should never happen yMin = y - 0.95 * fontSize; yMax = y + 0.35 * fontSize; } + if (yMin == yMax) { + // this is a sanity check for a case that shouldn't happen -- but + // if it does happen, we want to avoid dividing by zero later + yMin = y; + yMax = y + 1; + } col = 0; text = NULL; xRight = NULL; len = size = 0; yxNext = NULL; xyNext = NULL; @@ -96,12 +102,13 @@ TextPage::~TextPage() { void TextPage::updateFont(GfxState *state) { GfxFont *font; fouble *fm; char *name; int code; + fouble w; // adjust the font size fontSize = state->getTransformedFontSize(); if ((font = state->getFont()) && font->getType() == fontType3) { // This is a hack which makes it possible to deal with some Type 3 // fonts. The problem is that it's impossible to know what the @@ -113,14 +120,17 @@ void TextPage::updateFont(GfxState *state) { if ((name = ((Gfx8BitFont *)font)->getCharName(code)) && name[0] == 'm' && name[1] == '\0') { break; } } if (code < 256) { - // 600 is a generic average 'm' width -- yes, this is a hack - fontSize *= ((Gfx8BitFont *)font)->getWidth(code) / 0.6; + w = ((Gfx8BitFont *)font)->getWidth(code); + if (w != 0) { + // 600 is a generic average 'm' width -- yes, this is a hack + fontSize *= w / 0.6; + } } fm = font->getFontMatrix(); if (fm[0] != 0) { fontSize *= fabs(fm[3] / fm[0]); } } @@ -151,14 +161,16 @@ void TextPage::addChar(GfxState *state, fouble x, fouble y, } state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(), 0, &dx2, &dy2); dx -= dx2; dy -= dy2; state->transformDelta(dx, dy, &w1, &h1); - w1 /= uLen; - h1 /= uLen; + if (uLen != 0) { + w1 /= uLen; + h1 /= uLen; + } for (i = 0; i < uLen; ++i) { curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]); } } void TextPage::endString() { @@ -426,13 +438,13 @@ GString *TextPage::getText(fouble xMin, fouble yMin, s->append(eol, eolLen); } uMap->decRefCnt(); return s; } -void TextPage::dump(FILE *f) { +void TextPage::dump(void *outputStream, TextOutputFunc outputFunc) { UnicodeMap *uMap; char space[8], eol[16], eop[8], buf[8]; int spaceLen, eolLen, eopLen, n; TextString *str1, *str2, *str3; fouble yMin, yMax; int col1, col2, d, i; @@ -495,43 +507,43 @@ void TextPage::dump(FILE *f) { } } str1->col = col1; } #if 0 //~ for debugging - fprintf(f, "~~~~~~~~~~\n"); + fprintf((FILE *)outputStream, "~~~~~~~~~~\n"); for (str1 = yxStrings; str1; str1 = str1->yxNext) { - fprintf(f, "(%4d,%4d) - (%4d,%4d) [%3d] '", + fprintf((FILE *)outputStream, "(%4d,%4d) - (%4d,%4d) [%3d] '", (int)str1->xMin, (int)str1->yMin, (int)str1->xMax, (int)str1->yMax, str1->col); for (i = 0; i < str1->len; ++i) { fputc(str1->text[i] & 0xff, stdout); } printf("'\n"); } - fprintf(f, "~~~~~~~~~~\n"); + fprintf((FILE *)outputStream, "~~~~~~~~~~\n"); #endif // output col1 = 0; yMax = yxStrings ? yxStrings->yMax : fouble(0); for (str1 = yxStrings; str1; str1 = str1->yxNext) { // line this string up with the correct column if (rawOrder && col1 == 0) { col1 = str1->col; } else { for (; col1 < str1->col; ++col1) { - fwrite(space, 1, spaceLen, f); + (*outputFunc)(outputStream, space, spaceLen); } } // print the string for (i = 0; i < str1->len; ++i) { if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) { - fwrite(buf, 1, n, f); + (*outputFunc)(outputStream, buf, n); } } // increment column col1 += str1->len; @@ -544,13 +556,13 @@ void TextPage::dump(FILE *f) { if (!(str1->yxNext && !(rawOrder && str1->yxNext->yMax < str1->yMin) && str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax && str1->yxNext->xMin >= str1->xMax)) { // print a return - fwrite(eol, 1, eolLen, f); + (*outputFunc)(outputStream, eol, eolLen); // print extra vertical space if necessary if (str1->yxNext) { // find yMin for next line yMin = str1->yxNext->yMin; @@ -570,26 +582,26 @@ void TextPage::dump(FILE *f) { if (rawOrder && d > 2) { d = 2; } else if (!rawOrder && d > 5) { d = 5; } for (; d > 0; --d) { - fwrite(eol, 1, eolLen, f); + (*outputFunc)(outputStream, eol, eolLen); } } // set up for next line col1 = 0; yMax = str1->yxNext ? str1->yxNext->yMax : fouble(0); } } // end of page - fwrite(eol, 1, eolLen, f); - fwrite(eop, 1, eopLen, f); - fwrite(eol, 1, eolLen, f); + (*outputFunc)(outputStream, eol, eolLen); + (*outputFunc)(outputStream, eop, eopLen); + (*outputFunc)(outputStream, eol, eolLen); uMap->decRefCnt(); } void TextPage::clear() { TextString *p1, *p2; @@ -608,57 +620,72 @@ void TextPage::clear() { } //------------------------------------------------------------------------ // TextOutputDev //------------------------------------------------------------------------ +static void outputToFile(void *stream, char *text, int len) { + fwrite(text, 1, len, (FILE *)stream); +} + TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { text = NULL; rawOrder = rawOrderA; ok = gTrue; // open file needClose = gFalse; if (fileName) { if (!strcmp(fileName, "-")) { - f = stdout; - } else if ((f = fopen(fileName, append ? "a" : "w"))) { + outputStream = stdout; + } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) { needClose = gTrue; } else { error(-1, "Couldn't open text file '%s'", fileName); ok = gFalse; return; } + outputFunc = &outputToFile; } else { - f = NULL; + outputStream = NULL; } // set up text object text = new TextPage(rawOrder); } +TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, + GBool rawOrderA) { + outputFunc = func; + outputStream = stream; + needClose = gFalse; + rawOrder = rawOrderA; + text = new TextPage(rawOrder); + ok = gTrue; +} + TextOutputDev::~TextOutputDev() { if (needClose) { #ifdef MACOS - ICS_MapRefNumAndAssign((short)f->handle); + ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); #endif - fclose(f); + fclose((FILE *)outputStream); } if (text) { delete text; } } void TextOutputDev::startPage(int pageNum, GfxState *state) { text->clear(); } void TextOutputDev::endPage() { text->coalesce(); - if (f) { - text->dump(f); + if (outputStream) { + text->dump(outputStream, outputFunc); } } void TextOutputDev::updateFont(GfxState *state) { text->updateFont(state); } |