summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/xpdf/TextOutputDev.cc
Unidiff
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/TextOutputDev.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/TextOutputDev.cc73
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
97void TextPage::updateFont(GfxState *state) { 103void 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
164void TextPage::endString() { 176void 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
432void TextPage::dump(FILE *f) { 444void 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
594void TextPage::clear() { 606void 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
626static void outputToFile(void *stream, char *text, int len) {
627 fwrite(text, 1, len, (FILE *)stream);
628}
629
614TextOutputDev::TextOutputDev(char *fileName, GBool rawOrderA, GBool append) { 630TextOutputDev::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
656TextOutputDev::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
639TextOutputDev::~TextOutputDev() { 666TextOutputDev::~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
651void TextOutputDev::startPage(int pageNum, GfxState *state) { 678void TextOutputDev::startPage(int pageNum, GfxState *state) {
652 text->clear(); 679 text->clear();
653} 680}
654 681
655void TextOutputDev::endPage() { 682void 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
662void TextOutputDev::updateFont(GfxState *state) { 689void TextOutputDev::updateFont(GfxState *state) {
663 text->updateFont(state); 690 text->updateFont(state);
664} 691}