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 @@ | |||
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__ |
10 | #pragma implementation | 10 | #pragma implementation |
11 | #endif | 11 | #endif |
@@ -45,12 +45,18 @@ TextString::TextString(GfxState *state, fouble fontSize) { | |||
45 | } else { | 45 | } else { |
46 | // this means that the PDF file draws text without a current font, | 46 | // this means that the PDF file draws text without a current font, |
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; |
55 | yxNext = NULL; | 61 | yxNext = NULL; |
56 | xyNext = NULL; | 62 | xyNext = NULL; |
@@ -96,12 +102,13 @@ TextPage::~TextPage() { | |||
96 | 102 | ||
97 | void TextPage::updateFont(GfxState *state) { | 103 | 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) { |
106 | // This is a hack which makes it possible to deal with some Type 3 | 113 | // This is a hack which makes it possible to deal with some Type 3 |
107 | // fonts. The problem is that it's impossible to know what the | 114 | // fonts. The problem is that it's impossible to know what the |
@@ -113,14 +120,17 @@ void TextPage::updateFont(GfxState *state) { | |||
113 | if ((name = ((Gfx8BitFont *)font)->getCharName(code)) && | 120 | if ((name = ((Gfx8BitFont *)font)->getCharName(code)) && |
114 | name[0] == 'm' && name[1] == '\0') { | 121 | name[0] == 'm' && name[1] == '\0') { |
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]); |
125 | } | 135 | } |
126 | } | 136 | } |
@@ -151,14 +161,16 @@ void TextPage::addChar(GfxState *state, fouble x, fouble y, | |||
151 | } | 161 | } |
152 | state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(), | 162 | state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(), |
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 | } |
163 | 175 | ||
164 | void TextPage::endString() { | 176 | void TextPage::endString() { |
@@ -426,13 +438,13 @@ GString *TextPage::getText(fouble xMin, fouble yMin, | |||
426 | s->append(eol, eolLen); | 438 | s->append(eol, eolLen); |
427 | } | 439 | } |
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; |
437 | fouble yMin, yMax; | 449 | fouble yMin, yMax; |
438 | int col1, col2, d, i; | 450 | int col1, col2, d, i; |
@@ -495,43 +507,43 @@ void TextPage::dump(FILE *f) { | |||
495 | } | 507 | } |
496 | } | 508 | } |
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; |
516 | yMax = yxStrings ? yxStrings->yMax : fouble(0); | 528 | yMax = yxStrings ? yxStrings->yMax : fouble(0); |
517 | for (str1 = yxStrings; str1; str1 = str1->yxNext) { | 529 | for (str1 = yxStrings; str1; str1 = str1->yxNext) { |
518 | 530 | ||
519 | // line this string up with the correct column | 531 | // line this string up with the correct column |
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 |
536 | col1 += str1->len; | 548 | col1 += str1->len; |
537 | 549 | ||
@@ -544,13 +556,13 @@ void TextPage::dump(FILE *f) { | |||
544 | if (!(str1->yxNext && | 556 | if (!(str1->yxNext && |
545 | !(rawOrder && str1->yxNext->yMax < str1->yMin) && | 557 | !(rawOrder && str1->yxNext->yMax < str1->yMin) && |
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 | ||
555 | // find yMin for next line | 567 | // find yMin for next line |
556 | yMin = str1->yxNext->yMin; | 568 | yMin = str1->yxNext->yMin; |
@@ -570,26 +582,26 @@ void TextPage::dump(FILE *f) { | |||
570 | if (rawOrder && d > 2) { | 582 | if (rawOrder && d > 2) { |
571 | d = 2; | 583 | d = 2; |
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 |
581 | col1 = 0; | 593 | col1 = 0; |
582 | yMax = str1->yxNext ? str1->yxNext->yMax : fouble(0); | 594 | yMax = str1->yxNext ? str1->yxNext->yMax : fouble(0); |
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 | ||
594 | void TextPage::clear() { | 606 | void TextPage::clear() { |
595 | TextString *p1, *p2; | 607 | TextString *p1, *p2; |
@@ -608,57 +620,72 @@ void TextPage::clear() { | |||
608 | } | 620 | } |
609 | 621 | ||
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; |
618 | 634 | ||
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 | } |
649 | } | 676 | } |
650 | 677 | ||
651 | void TextOutputDev::startPage(int pageNum, GfxState *state) { | 678 | void TextOutputDev::startPage(int pageNum, GfxState *state) { |
652 | text->clear(); | 679 | text->clear(); |
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) { |
663 | text->updateFont(state); | 690 | text->updateFont(state); |
664 | } | 691 | } |