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,9 +1,9 @@ | |||
1 | //======================================================================== | 1 | //======================================================================== |
2 | // | 2 | // |
3 | // TextOutputDev.cc | 3 | // TextOutputDev.cc |
4 | // | 4 | // |
5 | // Copyright 1997 Derek B. Noonburg | 5 | // Copyright 1997-2002 Glyph & Cog, LLC |
6 | // | 6 | // |
7 | //======================================================================== | 7 | //======================================================================== |
8 | 8 | ||
9 | #ifdef __GNUC__ | 9 | #ifdef __GNUC__ |
@@ -47,8 +47,14 @@ TextString::TextString(GfxState *state, fouble fontSize) { | |||
47 | // which should never happen | 47 | // which should never happen |
48 | yMin = y - 0.95 * fontSize; | 48 | yMin = y - 0.95 * fontSize; |
49 | yMax = y + 0.35 * fontSize; | 49 | yMax = y + 0.35 * fontSize; |
50 | } | 50 | } |
51 | if (yMin == yMax) { | ||
52 | // this is a sanity check for a case that shouldn't happen -- but | ||
53 | // if it does happen, we want to avoid dividing by zero later | ||
54 | yMin = y; | ||
55 | yMax = y + 1; | ||
56 | } | ||
51 | col = 0; | 57 | col = 0; |
52 | text = NULL; | 58 | text = NULL; |
53 | xRight = NULL; | 59 | xRight = NULL; |
54 | len = size = 0; | 60 | len = size = 0; |
@@ -98,8 +104,9 @@ void TextPage::updateFont(GfxState *state) { | |||
98 | GfxFont *font; | 104 | GfxFont *font; |
99 | fouble *fm; | 105 | fouble *fm; |
100 | char *name; | 106 | char *name; |
101 | int code; | 107 | int code; |
108 | fouble w; | ||
102 | 109 | ||
103 | // adjust the font size | 110 | // adjust the font size |
104 | fontSize = state->getTransformedFontSize(); | 111 | fontSize = state->getTransformedFontSize(); |
105 | if ((font = state->getFont()) && font->getType() == fontType3) { | 112 | if ((font = state->getFont()) && font->getType() == fontType3) { |
@@ -115,10 +122,13 @@ void TextPage::updateFont(GfxState *state) { | |||
115 | break; | 122 | break; |
116 | } | 123 | } |
117 | } | 124 | } |
118 | if (code < 256) { | 125 | if (code < 256) { |
119 | // 600 is a generic average 'm' width -- yes, this is a hack | 126 | w = ((Gfx8BitFont *)font)->getWidth(code); |
120 | fontSize *= ((Gfx8BitFont *)font)->getWidth(code) / 0.6; | 127 | if (w != 0) { |
128 | // 600 is a generic average 'm' width -- yes, this is a hack | ||
129 | fontSize *= w / 0.6; | ||
130 | } | ||
121 | } | 131 | } |
122 | fm = font->getFontMatrix(); | 132 | fm = font->getFontMatrix(); |
123 | if (fm[0] != 0) { | 133 | if (fm[0] != 0) { |
124 | fontSize *= fabs(fm[3] / fm[0]); | 134 | fontSize *= fabs(fm[3] / fm[0]); |
@@ -153,10 +163,12 @@ void TextPage::addChar(GfxState *state, fouble x, fouble y, | |||
153 | 0, &dx2, &dy2); | 163 | 0, &dx2, &dy2); |
154 | dx -= dx2; | 164 | dx -= dx2; |
155 | dy -= dy2; | 165 | dy -= dy2; |
156 | state->transformDelta(dx, dy, &w1, &h1); | 166 | state->transformDelta(dx, dy, &w1, &h1); |
157 | w1 /= uLen; | 167 | if (uLen != 0) { |
158 | h1 /= uLen; | 168 | w1 /= uLen; |
169 | h1 /= uLen; | ||
170 | } | ||
159 | for (i = 0; i < uLen; ++i) { | 171 | for (i = 0; i < uLen; ++i) { |
160 | curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]); | 172 | curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]); |
161 | } | 173 | } |
162 | } | 174 | } |
@@ -428,9 +440,9 @@ GString *TextPage::getText(fouble xMin, fouble yMin, | |||
428 | uMap->decRefCnt(); | 440 | uMap->decRefCnt(); |
429 | return s; | 441 | return s; |
430 | } | 442 | } |
431 | 443 | ||
432 | void TextPage::dump(FILE *f) { | 444 | void TextPage::dump(void *outputStream, TextOutputFunc outputFunc) { |
433 | UnicodeMap *uMap; | 445 | UnicodeMap *uMap; |
434 | char space[8], eol[16], eop[8], buf[8]; | 446 | char space[8], eol[16], eop[8], buf[8]; |
435 | int spaceLen, eolLen, eopLen, n; | 447 | int spaceLen, eolLen, eopLen, n; |
436 | TextString *str1, *str2, *str3; | 448 | TextString *str1, *str2, *str3; |
@@ -497,19 +509,19 @@ void TextPage::dump(FILE *f) { | |||
497 | str1->col = col1; | 509 | str1->col = col1; |
498 | } | 510 | } |
499 | 511 | ||
500 | #if 0 //~ for debugging | 512 | #if 0 //~ for debugging |
501 | fprintf(f, "~~~~~~~~~~\n"); | 513 | fprintf((FILE *)outputStream, "~~~~~~~~~~\n"); |
502 | for (str1 = yxStrings; str1; str1 = str1->yxNext) { | 514 | for (str1 = yxStrings; str1; str1 = str1->yxNext) { |
503 | fprintf(f, "(%4d,%4d) - (%4d,%4d) [%3d] '", | 515 | fprintf((FILE *)outputStream, "(%4d,%4d) - (%4d,%4d) [%3d] '", |
504 | (int)str1->xMin, (int)str1->yMin, | 516 | (int)str1->xMin, (int)str1->yMin, |
505 | (int)str1->xMax, (int)str1->yMax, str1->col); | 517 | (int)str1->xMax, (int)str1->yMax, str1->col); |
506 | for (i = 0; i < str1->len; ++i) { | 518 | for (i = 0; i < str1->len; ++i) { |
507 | fputc(str1->text[i] & 0xff, stdout); | 519 | fputc(str1->text[i] & 0xff, stdout); |
508 | } | 520 | } |
509 | printf("'\n"); | 521 | printf("'\n"); |
510 | } | 522 | } |
511 | fprintf(f, "~~~~~~~~~~\n"); | 523 | fprintf((FILE *)outputStream, "~~~~~~~~~~\n"); |
512 | #endif | 524 | #endif |
513 | 525 | ||
514 | // output | 526 | // output |
515 | col1 = 0; | 527 | col1 = 0; |
@@ -520,16 +532,16 @@ void TextPage::dump(FILE *f) { | |||
520 | if (rawOrder && col1 == 0) { | 532 | if (rawOrder && col1 == 0) { |
521 | col1 = str1->col; | 533 | col1 = str1->col; |
522 | } else { | 534 | } else { |
523 | for (; col1 < str1->col; ++col1) { | 535 | for (; col1 < str1->col; ++col1) { |
524 | fwrite(space, 1, spaceLen, f); | 536 | (*outputFunc)(outputStream, space, spaceLen); |
525 | } | 537 | } |
526 | } | 538 | } |
527 | 539 | ||
528 | // print the string | 540 | // print the string |
529 | for (i = 0; i < str1->len; ++i) { | 541 | for (i = 0; i < str1->len; ++i) { |
530 | if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) { | 542 | if ((n = uMap->mapUnicode(str1->text[i], buf, sizeof(buf))) > 0) { |
531 | fwrite(buf, 1, n, f); | 543 | (*outputFunc)(outputStream, buf, n); |
532 | } | 544 | } |
533 | } | 545 | } |
534 | 546 | ||
535 | // increment column | 547 | // increment column |
@@ -546,9 +558,9 @@ void TextPage::dump(FILE *f) { | |||
546 | str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax && | 558 | str1->yxNext->yMin < 0.2*str1->yMin + 0.8*str1->yMax && |
547 | str1->yxNext->xMin >= str1->xMax)) { | 559 | str1->yxNext->xMin >= str1->xMax)) { |
548 | 560 | ||
549 | // print a return | 561 | // print a return |
550 | fwrite(eol, 1, eolLen, f); | 562 | (*outputFunc)(outputStream, eol, eolLen); |
551 | 563 | ||
552 | // print extra vertical space if necessary | 564 | // print extra vertical space if necessary |
553 | if (str1->yxNext) { | 565 | if (str1->yxNext) { |
554 | 566 | ||
@@ -572,9 +584,9 @@ void TextPage::dump(FILE *f) { | |||
572 | } else if (!rawOrder && d > 5) { | 584 | } else if (!rawOrder && d > 5) { |
573 | d = 5; | 585 | d = 5; |
574 | } | 586 | } |
575 | for (; d > 0; --d) { | 587 | for (; d > 0; --d) { |
576 | fwrite(eol, 1, eolLen, f); | 588 | (*outputFunc)(outputStream, eol, eolLen); |
577 | } | 589 | } |
578 | } | 590 | } |
579 | 591 | ||
580 | // set up for next line | 592 | // set up for next line |
@@ -583,11 +595,11 @@ void TextPage::dump(FILE *f) { | |||
583 | } | 595 | } |
584 | } | 596 | } |
585 | 597 | ||
586 | // end of page | 598 | // end of page |
587 | fwrite(eol, 1, eolLen, f); | 599 | (*outputFunc)(outputStream, eol, eolLen); |
588 | fwrite(eop, 1, eopLen, f); | 600 | (*outputFunc)(outputStream, eop, eopLen); |
589 | fwrite(eol, 1, eolLen, f); | 601 | (*outputFunc)(outputStream, eol, eolLen); |
590 | 602 | ||
591 | uMap->decRefCnt(); | 603 | uMap->decRefCnt(); |
592 | } | 604 | } |
593 | 605 | ||
@@ -610,8 +622,12 @@ void TextPage::clear() { | |||
610 | //------------------------------------------------------------------------ | 622 | //------------------------------------------------------------------------ |
611 | // TextOutputDev | 623 | // TextOutputDev |
612 | //------------------------------------------------------------------------ | 624 | //------------------------------------------------------------------------ |
613 | 625 | ||
626 | static void outputToFile(void *stream, char *text, int len) { | ||
627 | fwrite(text, 1, len, (FILE *)stream); | ||
628 | } | ||
629 | |||
614 | TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { | 630 | TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { |
615 | text = NULL; | 631 | text = NULL; |
616 | rawOrder = rawOrderA; | 632 | rawOrder = rawOrderA; |
617 | ok = gTrue; | 633 | ok = gTrue; |
@@ -619,30 +635,41 @@ TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { | |||
619 | // open file | 635 | // open file |
620 | needClose = gFalse; | 636 | needClose = gFalse; |
621 | if (fileName) { | 637 | if (fileName) { |
622 | if (!strcmp(fileName, "-")) { | 638 | if (!strcmp(fileName, "-")) { |
623 | f = stdout; | 639 | outputStream = stdout; |
624 | } else if ((f = fopen(fileName, append ? "a" : "w"))) { | 640 | } else if ((outputStream = fopen(fileName, append ? "ab" : "wb"))) { |
625 | needClose = gTrue; | 641 | needClose = gTrue; |
626 | } else { | 642 | } else { |
627 | error(-1, "Couldn't open text file '%s'", fileName); | 643 | error(-1, "Couldn't open text file '%s'", fileName); |
628 | ok = gFalse; | 644 | ok = gFalse; |
629 | return; | 645 | return; |
630 | } | 646 | } |
647 | outputFunc = &outputToFile; | ||
631 | } else { | 648 | } else { |
632 | f = NULL; | 649 | outputStream = NULL; |
633 | } | 650 | } |
634 | 651 | ||
635 | // set up text object | 652 | // set up text object |
636 | text = new TextPage(rawOrder); | 653 | text = new TextPage(rawOrder); |
637 | } | 654 | } |
638 | 655 | ||
656 | TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream, | ||
657 | GBool rawOrderA) { | ||
658 | outputFunc = func; | ||
659 | outputStream = stream; | ||
660 | needClose = gFalse; | ||
661 | rawOrder = rawOrderA; | ||
662 | text = new TextPage(rawOrder); | ||
663 | ok = gTrue; | ||
664 | } | ||
665 | |||
639 | TextOutputDev::~TextOutputDev() { | 666 | TextOutputDev::~TextOutputDev() { |
640 | if (needClose) { | 667 | if (needClose) { |
641 | #ifdef MACOS | 668 | #ifdef MACOS |
642 | ICS_MapRefNumAndAssign((short)f->handle); | 669 | ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle); |
643 | #endif | 670 | #endif |
644 | fclose(f); | 671 | fclose((FILE *)outputStream); |
645 | } | 672 | } |
646 | if (text) { | 673 | if (text) { |
647 | delete text; | 674 | delete text; |
648 | } | 675 | } |
@@ -653,10 +680,10 @@ void TextOutputDev::startPage(int pageNum, GfxState *state) { | |||
653 | } | 680 | } |
654 | 681 | ||
655 | void TextOutputDev::endPage() { | 682 | void TextOutputDev::endPage() { |
656 | text->coalesce(); | 683 | text->coalesce(); |
657 | if (f) { | 684 | if (outputStream) { |
658 | text->dump(f); | 685 | text->dump(outputStream, outputFunc); |
659 | } | 686 | } |
660 | } | 687 | } |
661 | 688 | ||
662 | void TextOutputDev::updateFont(GfxState *state) { | 689 | void TextOutputDev::updateFont(GfxState *state) { |