poppler  0.25.3
About: Poppler is a PDF rendering library (based on the xpdf-3.0 code base). Development version.
  Fossies Dox: poppler-0.25.3.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HtmlOutputDev.cc
Go to the documentation of this file.
1 //========================================================================
2 //
3 // HtmlOutputDev.cc
4 //
5 // Copyright 1997-2002 Glyph & Cog, LLC
6 //
7 // Changed 1999-2000 by G.Ovtcharov
8 //
9 // Changed 2002 by Mikhail Kruk
10 //
11 //========================================================================
12 
13 //========================================================================
14 //
15 // Modified under the Poppler project - http://poppler.freedesktop.org
16 //
17 // All changes made under the Poppler project to this file are licensed
18 // under GPL version 2 or later
19 //
20 // Copyright (C) 2005-2013 Albert Astals Cid <aacid@kde.org>
21 // Copyright (C) 2008 Kjartan Maraas <kmaraas@gnome.org>
22 // Copyright (C) 2008 Boris Toloknov <tlknv@yandex.ru>
23 // Copyright (C) 2008 Haruyuki Kawabe <Haruyuki.Kawabe@unisys.co.jp>
24 // Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
25 // Copyright (C) 2009 Warren Toomey <wkt@tuhs.org>
26 // Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
27 // Copyright (C) 2009 Reece Dunn <msclrhd@gmail.com>
28 // Copyright (C) 2010, 2012, 2013 Adrian Johnson <ajohnson@redneon.com>
29 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
30 // Copyright (C) 2010 OSSD CDAC Mumbai by Leena Chourey (leenac@cdacmumbai.in) and Onkar Potdar (onkar@cdacmumbai.in)
31 // Copyright (C) 2011 Joshua Richardson <jric@chegg.com>
32 // Copyright (C) 2011 Stephen Reichling <sreichling@chegg.com>
33 // Copyright (C) 2011, 2012 Igor Slepchin <igor.slepchin@gmail.com>
34 // Copyright (C) 2012 Ihar Filipau <thephilips@gmail.com>
35 // Copyright (C) 2012 Gerald Schmidt <solahcin@gmail.com>
36 // Copyright (C) 2012 Pino Toscano <pino@kde.org>
37 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
38 // Copyright (C) 2013 Julien Nabet <serval2412@yahoo.fr>
39 // Copyright (C) 2013 Johannes Brandst├Ątter <jbrandstaetter@gmail.com>
40 // Copyright (C) 2014 Fabio D'Urso <fabiodurso@hotmail.it>
41 //
42 // To see a description of the changes please see the Changelog file that
43 // came with your tarball or type make ChangeLog if you are building from git
44 //
45 //========================================================================
46 
47 #ifdef __GNUC__
48 #pragma implementation
49 #endif
50 
51 #include "config.h"
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <stdarg.h>
55 #include <stddef.h>
56 #include <ctype.h>
57 #include <math.h>
58 #include <iostream>
59 #include "goo/GooString.h"
60 #include "goo/GooList.h"
61 #include "UnicodeMap.h"
62 #include "goo/gmem.h"
63 #include "Error.h"
64 #include "GfxState.h"
65 #include "Page.h"
66 #include "Annot.h"
67 #include "PNGWriter.h"
68 #include "GlobalParams.h"
69 #include "HtmlOutputDev.h"
70 #include "HtmlFonts.h"
71 #include "HtmlUtils.h"
72 #include "Outline.h"
73 #include "PDFDoc.h"
74 
75 #ifdef ENABLE_LIBPNG
76 #include <png.h>
77 #endif
78 
79 #define DEBUG __FILE__ << ": " << __LINE__ << ": DEBUG: "
80 
81 class HtmlImage
82 {
83 public:
84  HtmlImage(GooString *_fName, GfxState *state)
85  : fName(_fName) {
86  state->transform(0, 0, &xMin, &yMax);
87  state->transform(1, 1, &xMax, &yMin);
88  }
89  ~HtmlImage() { delete fName; }
90 
91  double xMin, xMax; // image x coordinates
92  double yMin, yMax; // image y coordinates
93  GooString *fName; // image file name
94 };
95 
96 // returns true if x is closer to y than x is to z
97 static inline bool IS_CLOSER(float x, float y, float z) { return fabs((x)-(y)) < fabs((x)-(z)); }
98 
99 extern GBool complexMode;
100 extern GBool singleHtml;
101 extern GBool ignore;
102 extern GBool printCommands;
103 extern GBool printHtml;
104 extern GBool noframes;
105 extern GBool stout;
106 extern GBool xml;
107 extern GBool showHidden;
108 extern GBool noMerge;
109 
110 extern double wordBreakThreshold;
111 
112 static GBool debug = gFalse;
113 static GooString *gstr_buff0 = NULL; // a workspace in which I format strings
114 
115 static GooString* basename(GooString* str){
116 
117  char *p=str->getCString();
118  int len=str->getLength();
119  for (int i=len-1;i>=0;i--)
120  if (*(p+i)==SLASH)
121  return new GooString((p+i+1),len-i-1);
122  return new GooString(str);
123 }
124 
125 #if 0
126 static GooString* Dirname(GooString* str){
127 
128  char *p=str->getCString();
129  int len=str->getLength();
130  for (int i=len-1;i>=0;i--)
131  if (*(p+i)==SLASH)
132  return new GooString(p,i+1);
133  return new GooString();
134 }
135 #endif
136 
137 static const char *print_matrix(const double *mat) {
138  delete gstr_buff0;
139 
140  gstr_buff0 = GooString::format("[{0:g} {1:g} {2:g} {3:g} {4:g} {5:g}]",
141  *mat, mat[1], mat[2], mat[3], mat[4], mat[5]);
142  return gstr_buff0->getCString();
143 }
144 
145 static const char *print_uni_str(const Unicode *u, const unsigned uLen) {
146  GooString *gstr_buff1 = NULL;
147 
148  delete gstr_buff0;
149 
150  if (!uLen) return "";
151  gstr_buff0 = GooString::format("{0:c}", (*u < 0x7F ? *u & 0xFF : '?'));
152  for (unsigned i = 1; i < uLen; i++) {
153  if (u[i] < 0x7F) {
154  gstr_buff1 = gstr_buff0->append(u[i] < 0x7F ? static_cast<char>(u[i]) & 0xFF : '?');
155  delete gstr_buff0;
156  gstr_buff0 = gstr_buff1;
157  }
158  }
159 
160  return gstr_buff0->getCString();
161 }
162 
163 //------------------------------------------------------------------------
164 // HtmlString
165 //------------------------------------------------------------------------
166 
167 HtmlString::HtmlString(GfxState *state, double fontSize, HtmlFontAccu* _fonts) : fonts(_fonts) {
168  GfxFont *font;
169  double x, y;
170 
171  state->transform(state->getCurX(), state->getCurY(), &x, &y);
172  if ((font = state->getFont())) {
173  double ascent = font->getAscent();
174  double descent = font->getDescent();
175  if( ascent > 1.05 ){
176  //printf( "ascent=%.15g is too high, descent=%.15g\n", ascent, descent );
177  ascent = 1.05;
178  }
179  if( descent < -0.4 ){
180  //printf( "descent %.15g is too low, ascent=%.15g\n", descent, ascent );
181  descent = -0.4;
182  }
183  yMin = y - ascent * fontSize;
184  yMax = y - descent * fontSize;
185  GfxRGB rgb;
186  state->getFillRGB(&rgb);
187  HtmlFont hfont=HtmlFont(font, static_cast<int>(fontSize-1), rgb);
188  if (isMatRotOrSkew(state->getTextMat())) {
189  double normalizedMatrix[4];
190  memcpy(normalizedMatrix, state->getTextMat(), sizeof(normalizedMatrix));
191  // browser rotates the opposite way
192  // so flip the sign of the angle -> sin() components change sign
193  if (debug)
194  std::cerr << DEBUG << "before transform: " << print_matrix(normalizedMatrix) << std::endl;
195  normalizedMatrix[1] *= -1;
196  normalizedMatrix[2] *= -1;
197  if (debug)
198  std::cerr << DEBUG << "after reflecting angle: " << print_matrix(normalizedMatrix) << std::endl;
199  normalizeRotMat(normalizedMatrix);
200  if (debug)
201  std::cerr << DEBUG << "after norm: " << print_matrix(normalizedMatrix) << std::endl;
202  hfont.setRotMat(normalizedMatrix);
203  }
204  fontpos = fonts->AddFont(hfont);
205  } else {
206  // this means that the PDF file draws text without a current font,
207  // which should never happen
208  yMin = y - 0.95 * fontSize;
209  yMax = y + 0.35 * fontSize;
210  fontpos=0;
211  }
212  if (yMin == yMax) {
213  // this is a sanity check for a case that shouldn't happen -- but
214  // if it does happen, we want to avoid dividing by zero later
215  yMin = y;
216  yMax = y + 1;
217  }
218  col = 0;
219  text = NULL;
220  xRight = NULL;
221  link = NULL;
222  len = size = 0;
223  yxNext = NULL;
224  xyNext = NULL;
225  htext=new GooString();
226  dir = textDirUnknown;
227 }
228 
229 
231  gfree(text);
232  delete htext;
233  gfree(xRight);
234 }
235 
236 void HtmlString::addChar(GfxState *state, double x, double y,
237  double dx, double dy, Unicode u) {
238  if (dir == textDirUnknown) {
239  //dir = UnicodeMap::getDirection(u);
240  dir = textDirLeftRight;
241  }
242 
243  if (len == size) {
244  size += 16;
245  text = (Unicode *)grealloc(text, size * sizeof(Unicode));
246  xRight = (double *)grealloc(xRight, size * sizeof(double));
247  }
248  text[len] = u;
249  if (len == 0) {
250  xMin = x;
251  }
252  xMax = xRight[len] = x + dx;
253 //printf("added char: %f %f xright = %f\n", x, dx, x+dx);
254  ++len;
255 }
256 
258 {
259  if( dir == textDirRightLeft && len > 1 )
260  {
261  //printf("will reverse!\n");
262  for (int i = 0; i < len / 2; i++)
263  {
264  Unicode ch = text[i];
265  text[i] = text[len - i - 1];
266  text[len - i - 1] = ch;
267  }
268  }
269 }
270 
271 //------------------------------------------------------------------------
272 // HtmlPage
273 //------------------------------------------------------------------------
274 
275 HtmlPage::HtmlPage(GBool rawOrder, char *imgExtVal) {
276  this->rawOrder = rawOrder;
277  curStr = NULL;
278  yxStrings = NULL;
279  xyStrings = NULL;
280  yxCur1 = yxCur2 = NULL;
281  fonts=new HtmlFontAccu();
282  links=new HtmlLinks();
283  imgList=new GooList();
284  pageWidth=0;
285  pageHeight=0;
286  fontsPageMarker = 0;
287  DocName=NULL;
288  firstPage = -1;
289  imgExt = new GooString(imgExtVal);
290 }
291 
293  clear();
294  delete DocName;
295  delete fonts;
296  delete links;
297  delete imgExt;
298  deleteGooList(imgList, HtmlImage);
299 }
300 
302  GfxFont *font;
303  double *fm;
304  char *name;
305  int code;
306  double w;
307 
308  // adjust the font size
309  fontSize = state->getTransformedFontSize();
310  if ((font = state->getFont()) && font->getType() == fontType3) {
311  // This is a hack which makes it possible to deal with some Type 3
312  // fonts. The problem is that it's impossible to know what the
313  // base coordinate system used in the font is without actually
314  // rendering the font. This code tries to guess by looking at the
315  // width of the character 'm' (which breaks if the font is a
316  // subset that doesn't contain 'm').
317  for (code = 0; code < 256; ++code) {
318  if ((name = ((Gfx8BitFont *)font)->getCharName(code)) &&
319  name[0] == 'm' && name[1] == '\0') {
320  break;
321  }
322  }
323  if (code < 256) {
324  w = ((Gfx8BitFont *)font)->getWidth(code);
325  if (w != 0) {
326  // 600 is a generic average 'm' width -- yes, this is a hack
327  fontSize *= w / 0.6;
328  }
329  }
330  fm = font->getFontMatrix();
331  if (fm[0] != 0) {
332  fontSize *= fabs(fm[3] / fm[0]);
333  }
334  }
335 }
336 
338  curStr = new HtmlString(state, fontSize, fonts);
339 }
340 
341 
343  HtmlString *tmp;
344 
345  int linkIndex = 0;
346  HtmlFont* h;
347  for(tmp=yxStrings;tmp;tmp=tmp->yxNext){
348  int pos=tmp->fontpos;
349  // printf("%d\n",pos);
350  h=fonts->Get(pos);
351 
352  if (tmp->htext) delete tmp->htext;
353  tmp->htext=HtmlFont::simple(h,tmp->text,tmp->len);
354 
355  if (links->inLink(tmp->xMin,tmp->yMin,tmp->xMax,tmp->yMax, linkIndex)){
356  tmp->link = links->getLink(linkIndex);
357  /*GooString *t=tmp->htext;
358  tmp->htext=links->getLink(k)->Link(tmp->htext);
359  delete t;*/
360  }
361  }
362 
363 }
364 
365 
366 void HtmlPage::addChar(GfxState *state, double x, double y,
367  double dx, double dy,
368  double ox, double oy, Unicode *u, int uLen) {
369  double x1, y1, w1, h1, dx2, dy2;
370  int n, i;
371  state->transform(x, y, &x1, &y1);
372  n = curStr->len;
373 
374  // check that new character is in the same direction as current string
375  // and is not too far away from it before adding
376  //if ((UnicodeMap::getDirection(u[0]) != curStr->dir) ||
377  // XXX
378  if (debug) {
379  double *text_mat = state->getTextMat();
380  // rotation is (cos q, sin q, -sin q, cos q, 0, 0)
381  // sin q is zero iff there is no rotation, or 180 deg. rotation;
382  // for 180 rotation, cos q will be negative
383  if (text_mat[0] < 0 || !is_within(text_mat[1], .1, 0)) {
384  std::cerr << DEBUG << "rotation matrix for \"" << print_uni_str(u, uLen) << '"' << std::endl;
385  std::cerr << "text " << print_matrix(state->getTextMat());
386  }
387  }
388  if (n > 0 && // don't start a new string, unless there is already a string
389  // TODO: the following line assumes that text is flowing left to
390  // right, which will not necessarily be the case, e.g. if rotated;
391  // It assesses whether or not two characters are close enough to
392  // be part of the same string
393  fabs(x1 - curStr->xRight[n-1]) > wordBreakThreshold * (curStr->yMax - curStr->yMin) &&
394  // rotation is (cos q, sin q, -sin q, cos q, 0, 0)
395  // sin q is zero iff there is no rotation, or 180 deg. rotation;
396  // for 180 rotation, cos q will be negative
397  !rot_matrices_equal(curStr->getFont().getRotMat(), state->getTextMat()))
398  {
399  endString();
400  beginString(state, NULL);
401  }
402  state->textTransformDelta(state->getCharSpace() * state->getHorizScaling(),
403  0, &dx2, &dy2);
404  dx -= dx2;
405  dy -= dy2;
406  state->transformDelta(dx, dy, &w1, &h1);
407  if (uLen != 0) {
408  w1 /= uLen;
409  h1 /= uLen;
410  }
411  for (i = 0; i < uLen; ++i) {
412  curStr->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]);
413  }
414 }
415 
417  HtmlString *p1, *p2;
418  double h, y1, y2;
419 
420  // throw away zero-length strings -- they don't have valid xMin/xMax
421  // values, and they're useless anyway
422  if (curStr->len == 0) {
423  delete curStr;
424  curStr = NULL;
425  return;
426  }
427 
428  curStr->endString();
429 
430 #if 0 //~tmp
431  if (curStr->yMax - curStr->yMin > 20) {
432  delete curStr;
433  curStr = NULL;
434  return;
435  }
436 #endif
437 
438  // insert string in y-major list
439  h = curStr->yMax - curStr->yMin;
440  y1 = curStr->yMin + 0.5 * h;
441  y2 = curStr->yMin + 0.8 * h;
442  if (rawOrder) {
443  p1 = yxCur1;
444  p2 = NULL;
445  } else if ((!yxCur1 ||
446  (y1 >= yxCur1->yMin &&
447  (y2 >= yxCur1->yMax || curStr->xMax >= yxCur1->xMin))) &&
448  (!yxCur2 ||
449  (y1 < yxCur2->yMin ||
450  (y2 < yxCur2->yMax && curStr->xMax < yxCur2->xMin)))) {
451  p1 = yxCur1;
452  p2 = yxCur2;
453  } else {
454  for (p1 = NULL, p2 = yxStrings; p2; p1 = p2, p2 = p2->yxNext) {
455  if (y1 < p2->yMin || (y2 < p2->yMax && curStr->xMax < p2->xMin))
456  break;
457  }
458  yxCur2 = p2;
459  }
460  yxCur1 = curStr;
461  if (p1)
462  p1->yxNext = curStr;
463  else
464  yxStrings = curStr;
465  curStr->yxNext = p2;
466  curStr = NULL;
467 }
468 
469 static const char *strrstr( const char *s, const char *ss )
470 {
471  const char *p = strstr( s, ss );
472  for( const char *pp = p; pp != NULL; pp = strstr( p+1, ss ) ){
473  p = pp;
474  }
475  return p;
476 }
477 
478 static void CloseTags( GooString *htext, GBool &finish_a, GBool &finish_italic, GBool &finish_bold )
479 {
480  const char *last_italic = finish_italic && ( finish_bold || finish_a ) ? strrstr( htext->getCString(), "<i>" ) : NULL;
481  const char *last_bold = finish_bold && ( finish_italic || finish_a ) ? strrstr( htext->getCString(), "<b>" ) : NULL;
482  const char *last_a = finish_a && ( finish_italic || finish_bold ) ? strrstr( htext->getCString(), "<a " ) : NULL;
483  if( finish_a && ( finish_italic || finish_bold ) && last_a > ( last_italic > last_bold ? last_italic : last_bold ) ){
484  htext->append("</a>", 4);
485  finish_a = false;
486  }
487  if( finish_italic && finish_bold && last_italic > last_bold ){
488  htext->append("</i>", 4);
489  finish_italic = false;
490  }
491  if( finish_bold )
492  htext->append("</b>", 4);
493  if( finish_italic )
494  htext->append("</i>", 4);
495  if( finish_a )
496  htext->append("</a>");
497 }
498 
499 // Strings are lines of text;
500 // This function aims to combine strings into lines and paragraphs if !noMerge
501 // It may also strip out duplicate strings (if they are on top of each other); sometimes they are to create a font effect
503  HtmlString *str1, *str2;
504  HtmlFont *hfont1, *hfont2;
505  double space, horSpace, vertSpace, vertOverlap;
506  GBool addSpace, addLineBreak;
507  int n, i;
508  double curX, curY;
509 
510 #if 0 //~ for debugging
511  for (str1 = yxStrings; str1; str1 = str1->yxNext) {
512  printf("x=%f..%f y=%f..%f size=%2d '",
513  str1->xMin, str1->xMax, str1->yMin, str1->yMax,
514  (int)(str1->yMax - str1->yMin));
515  for (i = 0; i < str1->len; ++i) {
516  fputc(str1->text[i] & 0xff, stdout);
517  }
518  printf("'\n");
519  }
520  printf("\n------------------------------------------------------------\n\n");
521 #endif
522  str1 = yxStrings;
523 
524  if( !str1 ) return;
525 
526  //----- discard duplicated text (fake boldface, drop shadows)
527  if( !complexMode )
528  { /* if not in complex mode get rid of duplicate strings */
529  HtmlString *str3;
530  GBool found;
531  while (str1)
532  {
533  double size = str1->yMax - str1->yMin;
534  double xLimit = str1->xMin + size * 0.2;
535  found = gFalse;
536  for (str2 = str1, str3 = str1->yxNext;
537  str3 && str3->xMin < xLimit;
538  str2 = str3, str3 = str2->yxNext)
539  {
540  if (str3->len == str1->len &&
541  !memcmp(str3->text, str1->text, str1->len * sizeof(Unicode)) &&
542  fabs(str3->yMin - str1->yMin) < size * 0.2 &&
543  fabs(str3->yMax - str1->yMax) < size * 0.2 &&
544  fabs(str3->xMax - str1->xMax) < size * 0.2)
545  {
546  found = gTrue;
547  //printf("found duplicate!\n");
548  break;
549  }
550  }
551  if (found)
552  {
553  str2->xyNext = str3->xyNext;
554  str2->yxNext = str3->yxNext;
555  delete str3;
556  }
557  else
558  {
559  str1 = str1->yxNext;
560  }
561  }
562  } /*- !complexMode */
563 
564  str1 = yxStrings;
565 
566  hfont1 = getFont(str1);
567  if( hfont1->isBold() )
568  str1->htext->insert(0,"<b>",3);
569  if( hfont1->isItalic() )
570  str1->htext->insert(0,"<i>",3);
571  if( str1->getLink() != NULL ) {
572  GooString *ls = str1->getLink()->getLinkStart();
573  str1->htext->insert(0, ls);
574  delete ls;
575  }
576  curX = str1->xMin; curY = str1->yMin;
577 
578  while (str1 && (str2 = str1->yxNext)) {
579  hfont2 = getFont(str2);
580  space = str1->yMax - str1->yMin; // the height of the font's bounding box
581  horSpace = str2->xMin - str1->xMax;
582  // if strings line up on left-hand side AND they are on subsequent lines, we need a line break
583  addLineBreak = !noMerge && (fabs(str1->xMin - str2->xMin) < 0.4) && IS_CLOSER(str2->yMax, str1->yMax + space, str1->yMax);
584  vertSpace = str2->yMin - str1->yMax;
585 
586 //printf("coalesce %d %d %f? ", str1->dir, str2->dir, d);
587 
588  if (str2->yMin >= str1->yMin && str2->yMin <= str1->yMax)
589  {
590  vertOverlap = str1->yMax - str2->yMin;
591  } else
592  if (str2->yMax >= str1->yMin && str2->yMax <= str1->yMax)
593  {
594  vertOverlap = str2->yMax - str1->yMin;
595  } else
596  {
597  vertOverlap = 0;
598  }
599 
600  // Combine strings if:
601  // They appear to be the same font (complex mode only) && going in the same direction AND at least one of the following:
602  // 1. They appear to be part of the same line of text
603  // 2. They appear to be subsequent lines of a paragraph
604  // We assume (1) or (2) above, respectively, based on:
605  // (1) strings overlap vertically AND
606  // horizontal space between end of str1 and start of str2 is consistent with a single space or less;
607  // when rawOrder, the strings have to overlap vertically by at least 50%
608  // (2) Strings flow down the page, but the space between them is not too great, and they are lined up on the left
609  if (
610  (
611  (
612  (
613  (rawOrder && vertOverlap > 0.5 * space)
614  ||
615  (!rawOrder && str2->yMin < str1->yMax)
616  ) &&
617  (horSpace > -0.5 * space && horSpace < space)
618  ) ||
619  (vertSpace >= 0 && vertSpace < 0.5 * space && addLineBreak)
620  ) &&
621  (!complexMode || (hfont1->isEqualIgnoreBold(*hfont2))) && // in complex mode fonts must be the same, in other modes fonts do not metter
622  str1->dir == str2->dir // text direction the same
623  )
624  {
625 // printf("yes\n");
626  n = str1->len + str2->len;
627  if ((addSpace = horSpace > wordBreakThreshold * space)) {
628  ++n;
629  }
630  if (addLineBreak) {
631  ++n;
632  }
633 
634  str1->size = (n + 15) & ~15;
635  str1->text = (Unicode *)grealloc(str1->text,
636  str1->size * sizeof(Unicode));
637  str1->xRight = (double *)grealloc(str1->xRight,
638  str1->size * sizeof(double));
639  if (addSpace) {
640  str1->text[str1->len] = 0x20;
641  str1->htext->append(xml?" ":"&#160;");
642  str1->xRight[str1->len] = str2->xMin;
643  ++str1->len;
644  }
645  if (addLineBreak) {
646  str1->text[str1->len] = '\n';
647  str1->htext->append("<br/>");
648  str1->xRight[str1->len] = str2->xMin;
649  ++str1->len;
650  str1->yMin = str2->yMin;
651  str1->yMax = str2->yMax;
652  str1->xMax = str2->xMax;
653  int fontLineSize = hfont1->getLineSize();
654  int curLineSize = (int)(vertSpace + space);
655  if( curLineSize != fontLineSize )
656  {
657  HtmlFont *newfnt = new HtmlFont(*hfont1);
658  newfnt->setLineSize(curLineSize);
659  str1->fontpos = fonts->AddFont(*newfnt);
660  delete newfnt;
661  hfont1 = getFont(str1);
662  // we have to reget hfont2 because it's location could have
663  // changed on resize
664  hfont2 = getFont(str2);
665  }
666  }
667  for (i = 0; i < str2->len; ++i) {
668  str1->text[str1->len] = str2->text[i];
669  str1->xRight[str1->len] = str2->xRight[i];
670  ++str1->len;
671  }
672 
673  /* fix <i>, <b> if str1 and str2 differ and handle switch of links */
674  HtmlLink *hlink1 = str1->getLink();
675  HtmlLink *hlink2 = str2->getLink();
676  bool switch_links = !hlink1 || !hlink2 || !hlink1->isEqualDest(*hlink2);
677  GBool finish_a = switch_links && hlink1 != NULL;
678  GBool finish_italic = hfont1->isItalic() && ( !hfont2->isItalic() || finish_a );
679  GBool finish_bold = hfont1->isBold() && ( !hfont2->isBold() || finish_a || finish_italic );
680  CloseTags( str1->htext, finish_a, finish_italic, finish_bold );
681  if( switch_links && hlink2 != NULL ) {
682  GooString *ls = hlink2->getLinkStart();
683  str1->htext->append(ls);
684  delete ls;
685  }
686  if( ( !hfont1->isItalic() || finish_italic ) && hfont2->isItalic() )
687  str1->htext->append("<i>", 3);
688  if( ( !hfont1->isBold() || finish_bold ) && hfont2->isBold() )
689  str1->htext->append("<b>", 3);
690 
691 
692  str1->htext->append(str2->htext);
693  // str1 now contains href for link of str2 (if it is defined)
694  str1->link = str2->link;
695  hfont1 = hfont2;
696  if (str2->xMax > str1->xMax) {
697  str1->xMax = str2->xMax;
698  }
699  if (str2->yMax > str1->yMax) {
700  str1->yMax = str2->yMax;
701  }
702  str1->yxNext = str2->yxNext;
703  delete str2;
704  } else { // keep strings separate
705 // printf("no\n");
706  GBool finish_a = str1->getLink() != NULL;
707  GBool finish_bold = hfont1->isBold();
708  GBool finish_italic = hfont1->isItalic();
709  CloseTags( str1->htext, finish_a, finish_italic, finish_bold );
710 
711  str1->xMin = curX; str1->yMin = curY;
712  str1 = str2;
713  curX = str1->xMin; curY = str1->yMin;
714  hfont1 = hfont2;
715  if( hfont1->isBold() )
716  str1->htext->insert(0,"<b>",3);
717  if( hfont1->isItalic() )
718  str1->htext->insert(0,"<i>",3);
719  if( str1->getLink() != NULL ) {
720  GooString *ls = str1->getLink()->getLinkStart();
721  str1->htext->insert(0, ls);
722  delete ls;
723  }
724  }
725  }
726  str1->xMin = curX; str1->yMin = curY;
727 
728  GBool finish_bold = hfont1->isBold();
729  GBool finish_italic = hfont1->isItalic();
730  GBool finish_a = str1->getLink() != NULL;
731  CloseTags( str1->htext, finish_a, finish_italic, finish_bold );
732 
733 #if 0 //~ for debugging
734  for (str1 = yxStrings; str1; str1 = str1->yxNext) {
735  printf("x=%3d..%3d y=%3d..%3d size=%2d ",
736  (int)str1->xMin, (int)str1->xMax, (int)str1->yMin, (int)str1->yMax,
737  (int)(str1->yMax - str1->yMin));
738  printf("'%s'\n", str1->htext->getCString());
739  }
740  printf("\n------------------------------------------------------------\n\n");
741 #endif
742 
743 }
744 
745 void HtmlPage::dumpAsXML(FILE* f,int page){
746  fprintf(f, "<page number=\"%d\" position=\"absolute\"", page);
747  fprintf(f," top=\"0\" left=\"0\" height=\"%d\" width=\"%d\">\n", pageHeight,pageWidth);
748 
749  for(int i=fontsPageMarker;i < fonts->size();i++) {
750  GooString *fontCSStyle = fonts->CSStyle(i);
751  fprintf(f,"\t%s\n",fontCSStyle->getCString());
752  delete fontCSStyle;
753  }
754 
755  int listlen=imgList->getLength();
756  for (int i = 0; i < listlen; i++) {
757  HtmlImage *img = (HtmlImage*)imgList->del(0);
758  fprintf(f,"<image top=\"%d\" left=\"%d\" ",xoutRound(img->yMin),xoutRound(img->xMin));
759  fprintf(f,"width=\"%d\" height=\"%d\" ",xoutRound(img->xMax-img->xMin),xoutRound(img->yMax-img->yMin));
760  fprintf(f,"src=\"%s\"/>\n",img->fName->getCString());
761  delete img;
762  }
763 
764  for(HtmlString *tmp=yxStrings;tmp;tmp=tmp->yxNext){
765  if (tmp->htext){
766  fprintf(f,"<text top=\"%d\" left=\"%d\" ",xoutRound(tmp->yMin),xoutRound(tmp->xMin));
767  fprintf(f,"width=\"%d\" height=\"%d\" ",xoutRound(tmp->xMax-tmp->xMin),xoutRound(tmp->yMax-tmp->yMin));
768  fprintf(f,"font=\"%d\">", tmp->fontpos);
769  fputs(tmp->htext->getCString(),f);
770  fputs("</text>\n",f);
771  }
772  }
773  fputs("</page>\n",f);
774 }
775 
776 static void printCSS(FILE *f)
777 {
778  // Image flip/flop CSS
779  // Source:
780  // http://stackoverflow.com/questions/1309055/cross-browser-way-to-flip-html-image-via-javascript-css
781  // tested in Chrome, Fx (Linux) and IE9 (W7)
782  static const char css[] =
783  "<style type=\"text/css\">" "\n"
784  "<!--" "\n"
785  ".xflip {" "\n"
786  " -moz-transform: scaleX(-1);" "\n"
787  " -webkit-transform: scaleX(-1);" "\n"
788  " -o-transform: scaleX(-1);" "\n"
789  " transform: scaleX(-1);" "\n"
790  " filter: fliph;" "\n"
791  "}" "\n"
792  ".yflip {" "\n"
793  " -moz-transform: scaleY(-1);" "\n"
794  " -webkit-transform: scaleY(-1);" "\n"
795  " -o-transform: scaleY(-1);" "\n"
796  " transform: scaleY(-1);" "\n"
797  " filter: flipv;" "\n"
798  "}" "\n"
799  ".xyflip {" "\n"
800  " -moz-transform: scaleX(-1) scaleY(-1);" "\n"
801  " -webkit-transform: scaleX(-1) scaleY(-1);" "\n"
802  " -o-transform: scaleX(-1) scaleY(-1);" "\n"
803  " transform: scaleX(-1) scaleY(-1);" "\n"
804  " filter: fliph + flipv;" "\n"
805  "}" "\n"
806  "-->" "\n"
807  "</style>" "\n";
808 
809  fwrite( css, sizeof(css)-1, 1, f );
810 }
811 
812 int HtmlPage::dumpComplexHeaders(FILE * const file, FILE *& pageFile, int page) {
813  GooString* tmp;
814 
815  if( !noframes )
816  {
817  GooString* pgNum=GooString::fromInt(page);
818  tmp = new GooString(DocName);
819  if (!singleHtml){
820  tmp->append('-')->append(pgNum)->append(".html");
821  pageFile = fopen(tmp->getCString(), "w");
822  } else {
823  tmp->append("-html")->append(".html");
824  pageFile = fopen(tmp->getCString(), "a");
825  }
826  delete pgNum;
827  if (!pageFile) {
828  error(errIO, -1, "Couldn't open html file '{0:t}'", tmp);
829  delete tmp;
830  return 1;
831  }
832 
833  if (!singleHtml)
834  fprintf(pageFile,"%s\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\n<head>\n<title>Page %d</title>\n\n", DOCTYPE, page);
835  else
836  fprintf(pageFile,"%s\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\n<head>\n<title>%s</title>\n\n", DOCTYPE, tmp->getCString());
837 
838  delete tmp;
839 
840  GooString *htmlEncoding = HtmlOutputDev::mapEncodingToHtml(globalParams->getTextEncodingName());
841  if (!singleHtml)
842  fprintf(pageFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"/>\n", htmlEncoding->getCString());
843  else
844  fprintf(pageFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"/>\n <br/>\n", htmlEncoding->getCString());
845  delete htmlEncoding;
846  }
847  else
848  {
849  pageFile = file;
850  fprintf(pageFile,"<!-- Page %d -->\n", page);
851  fprintf(pageFile,"<a name=\"%d\"></a>\n", page);
852  }
853 
854  return 0;
855 }
856 
857 void HtmlPage::dumpComplex(FILE *file, int page){
858  FILE* pageFile;
859  GooString* tmp;
860 
861  if( firstPage == -1 ) firstPage = page;
862 
863  if (dumpComplexHeaders(file, pageFile, page)) { error(errIO, -1, "Couldn't write headers."); return; }
864 
865  tmp=basename(DocName);
866 
867  fputs("<style type=\"text/css\">\n<!--\n",pageFile);
868  fputs("\tp {margin: 0; padding: 0;}",pageFile);
869  for(int i=fontsPageMarker;i!=fonts->size();i++) {
870  GooString *fontCSStyle;
871  if (!singleHtml)
872  fontCSStyle = fonts->CSStyle(i);
873  else
874  fontCSStyle = fonts->CSStyle(i,page);
875  fprintf(pageFile,"\t%s\n",fontCSStyle->getCString());
876  delete fontCSStyle;
877  }
878 
879  fputs("-->\n</style>\n",pageFile);
880 
881  if( !noframes )
882  {
883  fputs("</head>\n<body bgcolor=\"#A0A0A0\" vlink=\"blue\" link=\"blue\">\n",pageFile);
884  }
885 
886  fprintf(pageFile,"<div id=\"page%d-div\" style=\"position:relative;width:%dpx;height:%dpx;\">\n",
887  page, pageWidth, pageHeight);
888 
889  if( !ignore )
890  {
891  fprintf(pageFile,
892  "<img width=\"%d\" height=\"%d\" src=\"%s%03d.%s\" alt=\"background image\"/>\n",
893  pageWidth, pageHeight, tmp->getCString(),
894  (page-firstPage+1), imgExt->getCString());
895  }
896 
897  delete tmp;
898 
899  for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
900  if (tmp1->htext){
901  fprintf(pageFile,
902  "<p style=\"position:absolute;top:%dpx;left:%dpx;white-space:nowrap\" class=\"ft",
903  xoutRound(tmp1->yMin),
904  xoutRound(tmp1->xMin));
905  if (!singleHtml) {
906  fputc('0', pageFile);
907  } else {
908  fprintf(pageFile, "%d", page);
909  }
910  fprintf(pageFile,"%d\">", tmp1->fontpos);
911  fputs(tmp1->htext->getCString(), pageFile);
912  fputs("</p>\n", pageFile);
913  }
914  }
915 
916  fputs("</div>\n", pageFile);
917 
918  if( !noframes )
919  {
920  fputs("</body>\n</html>\n",pageFile);
921  fclose(pageFile);
922  }
923 }
924 
925 
926 void HtmlPage::dump(FILE *f, int pageNum)
927 {
928  if (complexMode || singleHtml)
929  {
930  if (xml) dumpAsXML(f, pageNum);
931  if (!xml) dumpComplex(f, pageNum);
932  }
933  else
934  {
935  fprintf(f,"<a name=%d></a>",pageNum);
936  // Loop over the list of image names on this page
937  int listlen=imgList->getLength();
938  for (int i = 0; i < listlen; i++) {
939  HtmlImage *img = (HtmlImage*)imgList->del(0);
940 
941  // see printCSS() for class names
942  const char *styles[4] = { "", " class=\"xflip\"", " class=\"yflip\"", " class=\"xyflip\"" };
943  int style_index=0;
944  if (img->xMin > img->xMax) style_index += 1; // xFlip
945  if (img->yMin > img->yMax) style_index += 2; // yFlip
946 
947  fprintf(f,"<img%s src=\"%s\"/><br/>\n",styles[style_index],img->fName->getCString());
948  delete img;
949  }
950 
951  GooString* str;
952  for(HtmlString *tmp=yxStrings;tmp;tmp=tmp->yxNext){
953  if (tmp->htext){
954  str=new GooString(tmp->htext);
955  fputs(str->getCString(),f);
956  delete str;
957  fputs("<br/>\n",f);
958  }
959  }
960  fputs("<hr/>\n",f);
961  }
962 }
963 
964 
965 
967  HtmlString *p1, *p2;
968 
969  if (curStr) {
970  delete curStr;
971  curStr = NULL;
972  }
973  for (p1 = yxStrings; p1; p1 = p2) {
974  p2 = p1->yxNext;
975  delete p1;
976  }
977  yxStrings = NULL;
978  xyStrings = NULL;
979  yxCur1 = yxCur2 = NULL;
980 
981  if( !noframes )
982  {
983  delete fonts;
984  fonts=new HtmlFontAccu();
985  fontsPageMarker = 0;
986  }
987  else
988  {
989  fontsPageMarker = fonts->size();
990  }
991 
992  delete links;
993  links=new HtmlLinks();
994 
995 
996 }
997 
998 void HtmlPage::setDocName(char *fname){
999  DocName=new GooString(fname);
1000 }
1001 
1002 void HtmlPage::addImage(GooString *fname, GfxState *state) {
1003  HtmlImage *img = new HtmlImage(fname, state);
1004  imgList->append(img);
1005 }
1006 
1007 //------------------------------------------------------------------------
1008 // HtmlMetaVar
1009 //------------------------------------------------------------------------
1010 
1011 HtmlMetaVar::HtmlMetaVar(const char *_name, const char *_content)
1012 {
1013  name = new GooString(_name);
1014  content = new GooString(_content);
1015 }
1016 
1018 {
1019  delete name;
1020  delete content;
1021 }
1022 
1024 {
1025  GooString *result = new GooString("<meta name=\"");
1026  result->append(name);
1027  result->append("\" content=\"");
1028  result->append(content);
1029  result->append("\"/>");
1030  return result;
1031 }
1032 
1033 //------------------------------------------------------------------------
1034 // HtmlOutputDev
1035 //------------------------------------------------------------------------
1036 
1037 static const char* HtmlEncodings[][2] = {
1038  {"Latin1", "ISO-8859-1"},
1039  {NULL, NULL}
1040 };
1041 
1042 GooString* HtmlOutputDev::mapEncodingToHtml(GooString* encoding)
1043 {
1044  GooString* enc = encoding;
1045  for(int i = 0; HtmlEncodings[i][0] != NULL; i++)
1046  {
1047  if( enc->cmp(HtmlEncodings[i][0]) == 0 )
1048  {
1049  delete enc;
1050  return new GooString(HtmlEncodings[i][1]);
1051  }
1052  }
1053  return enc;
1054 }
1055 
1056 void HtmlOutputDev::doFrame(int firstPage){
1057  GooString* fName=new GooString(Docname);
1058  GooString* htmlEncoding;
1059  fName->append(".html");
1060 
1061  if (!(fContentsFrame = fopen(fName->getCString(), "w"))){
1062  error(errIO, -1, "Couldn't open html file '{0:t}'", fName);
1063  delete fName;
1064  return;
1065  }
1066 
1067  delete fName;
1068 
1069  fName=basename(Docname);
1070  fputs(DOCTYPE, fContentsFrame);
1071  fputs("\n<html>",fContentsFrame);
1072  fputs("\n<head>",fContentsFrame);
1073  fprintf(fContentsFrame,"\n<title>%s</title>",docTitle->getCString());
1074  htmlEncoding = mapEncodingToHtml(globalParams->getTextEncodingName());
1075  fprintf(fContentsFrame, "\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"/>\n", htmlEncoding->getCString());
1076  dumpMetaVars(fContentsFrame);
1077  fprintf(fContentsFrame, "</head>\n");
1078  fputs("<frameset cols=\"100,*\">\n",fContentsFrame);
1079  fprintf(fContentsFrame,"<frame name=\"links\" src=\"%s_ind.html\"/>\n",fName->getCString());
1080  fputs("<frame name=\"contents\" src=",fContentsFrame);
1081  if (complexMode)
1082  fprintf(fContentsFrame,"\"%s-%d.html\"",fName->getCString(), firstPage);
1083  else
1084  fprintf(fContentsFrame,"\"%ss.html\"",fName->getCString());
1085 
1086  fputs("/>\n</frameset>\n</html>\n",fContentsFrame);
1087 
1088  delete fName;
1089  delete htmlEncoding;
1090  fclose(fContentsFrame);
1091 }
1092 
1093 HtmlOutputDev::HtmlOutputDev(Catalog *catalogA, char *fileName, char *title,
1094  char *author, char *keywords, char *subject, char *date,
1095  char *extension,
1096  GBool rawOrder, int firstPage, GBool outline)
1097 {
1098  catalog = catalogA;
1099  fContentsFrame = NULL;
1100  docTitle = new GooString(title);
1101  pages = NULL;
1102  dumpJPEG=gTrue;
1103  //write = gTrue;
1104  this->rawOrder = rawOrder;
1105  this->doOutline = outline;
1106  ok = gFalse;
1107  //this->firstPage = firstPage;
1108  //pageNum=firstPage;
1109  // open file
1110  needClose = gFalse;
1111  pages = new HtmlPage(rawOrder, extension);
1112 
1113  glMetaVars = new GooList();
1114  glMetaVars->append(new HtmlMetaVar("generator", "pdftohtml 0.36"));
1115  if( author ) glMetaVars->append(new HtmlMetaVar("author", author));
1116  if( keywords ) glMetaVars->append(new HtmlMetaVar("keywords", keywords));
1117  if( date ) glMetaVars->append(new HtmlMetaVar("date", date));
1118  if( subject ) glMetaVars->append(new HtmlMetaVar("subject", subject));
1119 
1120  maxPageWidth = 0;
1121  maxPageHeight = 0;
1122 
1123  pages->setDocName(fileName);
1124  Docname=new GooString (fileName);
1125 
1126  // for non-xml output (complex or simple) with frames generate the left frame
1127  if(!xml && !noframes)
1128  {
1129  if (!singleHtml)
1130  {
1131  GooString* left=new GooString(fileName);
1132  left->append("_ind.html");
1133 
1134  doFrame(firstPage);
1135 
1136  if (!(fContentsFrame = fopen(left->getCString(), "w")))
1137  {
1138  error(errIO, -1, "Couldn't open html file '{0:t}'", left);
1139  delete left;
1140  return;
1141  }
1142  delete left;
1143  fputs(DOCTYPE, fContentsFrame);
1144  fputs("<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\n<head>\n<title></title>\n</head>\n<body>\n", fContentsFrame);
1145 
1146  if (doOutline)
1147  {
1148  GooString *str = basename(Docname);
1149  fprintf(fContentsFrame, "<a href=\"%s%s\" target=\"contents\">Outline</a><br/>", str->getCString(), complexMode ? "-outline.html" : "s.html#outline");
1150  delete str;
1151  }
1152  }
1153  if (!complexMode)
1154  { /* not in complex mode */
1155 
1156  GooString* right=new GooString(fileName);
1157  right->append("s.html");
1158 
1159  if (!(page=fopen(right->getCString(),"w"))){
1160  error(errIO, -1, "Couldn't open html file '{0:t}'", right);
1161  delete right;
1162  return;
1163  }
1164  delete right;
1165  fputs(DOCTYPE, page);
1166  fputs("<html>\n<head>\n<title></title>\n",page);
1167  printCSS(page);
1168  fputs("</head>\n<body>\n",page);
1169  }
1170  }
1171 
1172  if (noframes) {
1173  if (stout) page=stdout;
1174  else {
1175  GooString* right=new GooString(fileName);
1176  if (!xml) right->append(".html");
1177  if (xml) right->append(".xml");
1178  if (!(page=fopen(right->getCString(),"w"))){
1179  error(errIO, -1, "Couldn't open html file '{0:t}'", right);
1180  delete right;
1181  return;
1182  }
1183  delete right;
1184  }
1185 
1186  GooString *htmlEncoding = mapEncodingToHtml(globalParams->getTextEncodingName());
1187  if (xml)
1188  {
1189  fprintf(page, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", htmlEncoding->getCString());
1190  fputs("<!DOCTYPE pdf2xml SYSTEM \"pdf2xml.dtd\">\n\n", page);
1191  fprintf(page,"<pdf2xml producer=\"%s\" version=\"%s\">\n", PACKAGE_NAME, PACKAGE_VERSION);
1192  }
1193  else
1194  {
1195  fprintf(page,"%s\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"\" xml:lang=\"\">\n<head>\n<title>%s</title>\n", DOCTYPE, docTitle->getCString());
1196 
1197  fprintf(page, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"/>\n", htmlEncoding->getCString());
1198 
1199  dumpMetaVars(page);
1200  printCSS(page);
1201  fprintf(page,"</head>\n");
1202  fprintf(page,"<body bgcolor=\"#A0A0A0\" vlink=\"blue\" link=\"blue\">\n");
1203  }
1204  delete htmlEncoding;
1205  }
1206  ok = gTrue;
1207 }
1208 
1210  HtmlFont::clear();
1211 
1212  delete Docname;
1213  delete docTitle;
1214 
1215  deleteGooList(glMetaVars, HtmlMetaVar);
1216 
1217  if (fContentsFrame){
1218  fputs("</body>\n</html>\n",fContentsFrame);
1219  fclose(fContentsFrame);
1220  }
1221  if (page != NULL) {
1222  if (xml) {
1223  fputs("</pdf2xml>\n",page);
1224  fclose(page);
1225  } else
1226  if ( !complexMode || xml || noframes )
1227  {
1228  fputs("</body>\n</html>\n",page);
1229  fclose(page);
1230  }
1231  }
1232  if (pages)
1233  delete pages;
1234 }
1235 
1236 void HtmlOutputDev::startPage(int pageNum, GfxState *state, XRef *xref) {
1237 #if 0
1238  if (mode&&!xml){
1239  if (write){
1240  write=gFalse;
1241  GooString* fname=Dirname(Docname);
1242  fname->append("image.log");
1243  if((tin=fopen(getFileNameFromPath(fname->getCString(),fname->getLength()),"w"))==NULL){
1244  printf("Error : can not open %s",fname);
1245  exit(1);
1246  }
1247  delete fname;
1248  // if(state->getRotation()!=0)
1249  // fprintf(tin,"ROTATE=%d rotate %d neg %d neg translate\n",state->getRotation(),state->getX1(),-state->getY1());
1250  // else
1251  fprintf(tin,"ROTATE=%d neg %d neg translate\n",state->getX1(),state->getY1());
1252  }
1253  }
1254 #endif
1255 
1256  this->pageNum = pageNum;
1257  GooString *str=basename(Docname);
1258  pages->clear();
1259  if(!noframes)
1260  {
1261  if (fContentsFrame)
1262  {
1263  if (complexMode)
1264  fprintf(fContentsFrame,"<a href=\"%s-%d.html\"",str->getCString(),pageNum);
1265  else
1266  fprintf(fContentsFrame,"<a href=\"%ss.html#%d\"",str->getCString(),pageNum);
1267  fprintf(fContentsFrame," target=\"contents\" >Page %d</a><br/>\n",pageNum);
1268  }
1269  }
1270 
1271  pages->pageWidth=static_cast<int>(state->getPageWidth());
1272  pages->pageHeight=static_cast<int>(state->getPageHeight());
1273 
1274  delete str;
1275 }
1276 
1277 
1279  Links *linksList = docPage->getLinks();
1280  for (int i = 0; i < linksList->getNumLinks(); ++i)
1281  {
1282  doProcessLink(linksList->getLink(i));
1283  }
1284  delete linksList;
1285 
1286  pages->conv();
1287  pages->coalesce();
1288  pages->dump(page, pageNum);
1289 
1290  // I don't yet know what to do in the case when there are pages of different
1291  // sizes and we want complex output: running ghostscript many times
1292  // seems very inefficient. So for now I'll just use last page's size
1293  maxPageWidth = pages->pageWidth;
1294  maxPageHeight = pages->pageHeight;
1295 
1296  //if(!noframes&&!xml) fputs("<br/>\n", fContentsFrame);
1297  if(!stout && !globalParams->getErrQuiet()) printf("Page-%d\n",(pageNum));
1298 }
1299 
1301  pages->updateFont(state);
1302 }
1303 
1305  pages->beginString(state, s);
1306 }
1307 
1309  pages->endString();
1310 }
1311 
1312 void HtmlOutputDev::drawChar(GfxState *state, double x, double y,
1313  double dx, double dy,
1314  double originX, double originY,
1315  CharCode code, int /*nBytes*/, Unicode *u, int uLen)
1316 {
1317  if ( !showHidden && (state->getRender() & 3) == 3) {
1318  return;
1319  }
1320  pages->addChar(state, x, y, dx, dy, originX, originY, u, uLen);
1321 }
1322 
1323 void HtmlOutputDev::drawJpegImage(GfxState *state, Stream *str)
1324 {
1325  FILE *f1;
1326  int c;
1327 
1328  // open the image file
1329  GooString *fName=createImageFileName("jpg");
1330  if (!(f1 = fopen(fName->getCString(), "wb"))) {
1331  error(errIO, -1, "Couldn't open image file '{0:t}'", fName);
1332  delete fName;
1333  return;
1334  }
1335 
1336  // initialize stream
1337  str = str->getNextStream();
1338  str->reset();
1339 
1340  // copy the stream
1341  while ((c = str->getChar()) != EOF)
1342  fputc(c, f1);
1343 
1344  fclose(f1);
1345 
1346  if (fName) {
1347  pages->addImage(fName, state);
1348  }
1349 }
1350 
1351 void HtmlOutputDev::drawPngImage(GfxState *state, Stream *str, int width, int height,
1352  GfxImageColorMap *colorMap, GBool isMask)
1353 {
1354 #ifdef ENABLE_LIBPNG
1355  FILE *f1;
1356 
1357  if (!colorMap && !isMask) {
1358  error(errInternal, -1, "Can't have color image without a color map");
1359  return;
1360  }
1361 
1362  // open the image file
1363  GooString *fName=createImageFileName("png");
1364  if (!(f1 = fopen(fName->getCString(), "wb"))) {
1365  error(errIO, -1, "Couldn't open image file '{0:t}'", fName);
1366  delete fName;
1367  return;
1368  }
1369 
1370  PNGWriter *writer = new PNGWriter( isMask ? PNGWriter::MONOCHROME : PNGWriter::RGB );
1371  // TODO can we calculate the resolution of the image?
1372  if (!writer->init(f1, width, height, 72, 72)) {
1373  error(errInternal, -1, "Can't init PNG for image '{0:t}'", fName);
1374  delete writer;
1375  fclose(f1);
1376  return;
1377  }
1378 
1379  if (!isMask) {
1380  Guchar *p;
1381  GfxRGB rgb;
1382  png_byte *row = (png_byte *) gmalloc(3 * width); // 3 bytes/pixel: RGB
1383  png_bytep *row_pointer= &row;
1384 
1385  // Initialize the image stream
1386  ImageStream *imgStr = new ImageStream(str, width,
1387  colorMap->getNumPixelComps(), colorMap->getBits());
1388  imgStr->reset();
1389 
1390  // For each line...
1391  for (int y = 0; y < height; y++) {
1392 
1393  // Convert into a PNG row
1394  p = imgStr->getLine();
1395  for (int x = 0; x < width; x++) {
1396  colorMap->getRGB(p, &rgb);
1397  // Write the RGB pixels into the row
1398  row[3*x]= colToByte(rgb.r);
1399  row[3*x+1]= colToByte(rgb.g);
1400  row[3*x+2]= colToByte(rgb.b);
1401  p += colorMap->getNumPixelComps();
1402  }
1403 
1404  if (!writer->writeRow(row_pointer)) {
1405  error(errIO, -1, "Failed to write into PNG '{0:t}'", fName);
1406  delete writer;
1407  delete imgStr;
1408  fclose(f1);
1409  return;
1410  }
1411  }
1412  gfree(row);
1413  imgStr->close();
1414  delete imgStr;
1415  }
1416  else { // isMask == true
1417  int size = (width + 7)/8;
1418 
1419  // PDF masks use 0 = draw current color, 1 = leave unchanged.
1420  // We invert this to provide the standard interpretation of alpha
1421  // (0 = transparent, 1 = opaque). If the colorMap already inverts
1422  // the mask we leave the data unchanged.
1423  int invert_bits = 0xff;
1424  if (colorMap) {
1425  GfxGray gray;
1426  Guchar zero = 0;
1427  colorMap->getGray(&zero, &gray);
1428  if (colToByte(gray) == 0)
1429  invert_bits = 0x00;
1430  }
1431 
1432  str->reset();
1433  Guchar *png_row = (Guchar *)gmalloc(size);
1434 
1435  for (int ri = 0; ri < height; ++ri)
1436  {
1437  for(int i = 0; i < size; i++)
1438  png_row[i] = str->getChar() ^ invert_bits;
1439 
1440  if (!writer->writeRow( &png_row ))
1441  {
1442  error(errIO, -1, "Failed to write into PNG '{0:t}'", fName);
1443  delete writer;
1444  fclose(f1);
1445  gfree(png_row);
1446  return;
1447  }
1448  }
1449  str->close();
1450  gfree(png_row);
1451  }
1452 
1453  str->close();
1454 
1455  writer->close();
1456  delete writer;
1457  fclose(f1);
1458 
1459  pages->addImage(fName, state);
1460 #else
1461  return;
1462 #endif
1463 }
1464 
1465 GooString *HtmlOutputDev::createImageFileName(const char *ext)
1466 {
1467  GooString *fName=new GooString(Docname);
1468  fName->append("-");
1469  GooString *pgNum= GooString::fromInt(pageNum);
1470  GooString *imgnum= GooString::fromInt(pages->getNumImages()+1);
1471 
1472  fName->append(pgNum)->append("_")->append(imgnum)->append(".")->append(ext);
1473  delete pgNum;
1474  delete imgnum;
1475 
1476  return fName;
1477 }
1478 
1480  int width, int height, GBool invert,
1481  GBool interpolate, GBool inlineImg) {
1482 
1483  if (ignore||(complexMode && !xml)) {
1484  OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
1485  return;
1486  }
1487 
1488  // dump JPEG file
1489  if (dumpJPEG && str->getKind() == strDCT) {
1490  drawJpegImage(state, str);
1491  }
1492  else {
1493 #ifdef ENABLE_LIBPNG
1494  drawPngImage(state, str, width, height, NULL, gTrue);
1495 #else
1496  OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
1497 #endif
1498  }
1499 }
1500 
1502  int width, int height, GfxImageColorMap *colorMap,
1503  GBool interpolate, int *maskColors, GBool inlineImg) {
1504 
1505  if (ignore||(complexMode && !xml)) {
1506  OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
1507  maskColors, inlineImg);
1508  return;
1509  }
1510 
1511  /*if( !globalParams->getErrQuiet() )
1512  printf("image stream of kind %d\n", str->getKind());*/
1513  // dump JPEG file
1514  if (dumpJPEG && str->getKind() == strDCT && (colorMap->getNumPixelComps() == 1 ||
1515  colorMap->getNumPixelComps() == 3) && !inlineImg) {
1516  drawJpegImage(state, str);
1517  }
1518  else {
1519 #ifdef ENABLE_LIBPNG
1520  drawPngImage(state, str, width, height, colorMap );
1521 #else
1522  OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
1523  maskColors, inlineImg);
1524 #endif
1525  }
1526 }
1527 
1528 
1529 
1530 void HtmlOutputDev::doProcessLink(AnnotLink* link){
1531  double _x1,_y1,_x2,_y2;
1532  int x1,y1,x2,y2;
1533 
1534  link->getRect(&_x1,&_y1,&_x2,&_y2);
1535  cvtUserToDev(_x1,_y1,&x1,&y1);
1536 
1537  cvtUserToDev(_x2,_y2,&x2,&y2);
1538 
1539 
1540  GooString* _dest=getLinkDest(link);
1541  HtmlLink t((double) x1,(double) y2,(double) x2,(double) y1,_dest);
1542  pages->AddLink(t);
1543  delete _dest;
1544 }
1545 
1546 GooString* HtmlOutputDev::getLinkDest(AnnotLink *link){
1547  char *p;
1548  if (!link->getAction())
1549  return new GooString();
1550  switch(link->getAction()->getKind())
1551  {
1552  case actionGoTo:
1553  {
1554  GooString* file=basename(Docname);
1555  int page=1;
1556  LinkGoTo *ha=(LinkGoTo *)link->getAction();
1557  LinkDest *dest=NULL;
1558  if (ha->getDest()!=NULL)
1559  dest=ha->getDest()->copy();
1560  else if (ha->getNamedDest()!=NULL)
1561  dest=catalog->findDest(ha->getNamedDest());
1562 
1563  if (dest){
1564  if (dest->isPageRef()){
1565  Ref pageref=dest->getPageRef();
1566  page=catalog->findPage(pageref.num,pageref.gen);
1567  }
1568  else {
1569  page=dest->getPageNum();
1570  }
1571 
1572  delete dest;
1573 
1574  GooString *str=GooString::fromInt(page);
1575  /* complex simple
1576  frames file-4.html files.html#4
1577  noframes file.html#4 file.html#4
1578  */
1579  if (noframes)
1580  {
1581  file->append(".html#");
1582  file->append(str);
1583  }
1584  else
1585  {
1586  if( complexMode )
1587  {
1588  file->append("-");
1589  file->append(str);
1590  file->append(".html");
1591  }
1592  else
1593  {
1594  file->append("s.html#");
1595  file->append(str);
1596  }
1597  }
1598 
1599  if (printCommands) printf(" link to page %d ",page);
1600  delete str;
1601  return file;
1602  }
1603  else
1604  {
1605  return new GooString();
1606  }
1607  }
1608  case actionGoToR:
1609  {
1610  LinkGoToR *ha=(LinkGoToR *) link->getAction();
1611  LinkDest *dest=NULL;
1612  int page=1;
1613  GooString *file=new GooString();
1614  if (ha->getFileName()){
1615  delete file;
1616  file=new GooString(ha->getFileName()->getCString());
1617  }
1618  if (ha->getDest()!=NULL) dest=ha->getDest()->copy();
1619  if (dest&&file){
1620  if (!(dest->isPageRef())) page=dest->getPageNum();
1621  delete dest;
1622 
1623  if (printCommands) printf(" link to page %d ",page);
1624  if (printHtml){
1625  p=file->getCString()+file->getLength()-4;
1626  if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")){
1627  file->del(file->getLength()-4,4);
1628  file->append(".html");
1629  }
1630  file->append('#');
1631  file->append(GooString::fromInt(page));
1632  }
1633  }
1634  if (printCommands && file) printf("filename %s\n",file->getCString());
1635  return file;
1636  }
1637  case actionURI:
1638  {
1639  LinkURI *ha=(LinkURI *) link->getAction();
1640  GooString* file=new GooString(ha->getURI()->getCString());
1641  // printf("uri : %s\n",file->getCString());
1642  return file;
1643  }
1644  case actionLaunch:
1645  {
1646  LinkLaunch *ha=(LinkLaunch *) link->getAction();
1647  GooString* file=new GooString(ha->getFileName()->getCString());
1648  if (printHtml) {
1649  p=file->getCString()+file->getLength()-4;
1650  if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF")){
1651  file->del(file->getLength()-4,4);
1652  file->append(".html");
1653  }
1654  if (printCommands) printf("filename %s",file->getCString());
1655 
1656  return file;
1657 
1658  }
1659  }
1660  default:
1661  return new GooString();
1662  }
1663 }
1664 
1665 void HtmlOutputDev::dumpMetaVars(FILE *file)
1666 {
1667  GooString *var;
1668 
1669  for(int i = 0; i < glMetaVars->getLength(); i++)
1670  {
1671  HtmlMetaVar *t = (HtmlMetaVar*)glMetaVars->get(i);
1672  var = t->toString();
1673  fprintf(file, "%s\n", var->getCString());
1674  delete var;
1675  }
1676 }
1677 
1679 {
1680 #ifdef DISABLE_OUTLINE
1681  return gFalse;
1682 #else
1683  FILE * output = NULL;
1684  GBool bClose = gFalse;
1685  Catalog *catalog = doc->getCatalog();
1686 
1687  if (!ok)
1688  return gFalse;
1689 
1690  Outline *outline = doc->getOutline();
1691  if (!outline)
1692  return gFalse;
1693 
1694  GooList *outlines = outline->getItems();
1695  if (!outlines)
1696  return gFalse;
1697 
1698  if (!complexMode || xml)
1699  {
1700  output = page;
1701  }
1702  else if (complexMode && !xml)
1703  {
1704  if (noframes)
1705  {
1706  output = page;
1707  fputs("<hr/>\n", output);
1708  }
1709  else
1710  {
1711  GooString *str = Docname->copy();
1712  str->append("-outline.html");
1713  output = fopen(str->getCString(), "w");
1714  delete str;
1715  if (output == NULL)
1716  return gFalse;
1717  bClose = gTrue;
1718 
1719  GooString *htmlEncoding =
1720  HtmlOutputDev::mapEncodingToHtml(globalParams->getTextEncodingName());
1721 
1722  fprintf(output, "<html xmlns=\"http://www.w3.org/1999/xhtml\" " \
1723  "lang=\"\" xml:lang=\"\">\n" \
1724  "<head>\n" \
1725  "<title>Document Outline</title>\n" \
1726  "<meta http-equiv=\"Content-Type\" content=\"text/html; " \
1727  "charset=%s\"/>\n" \
1728  "</head>\n<body>\n", htmlEncoding->getCString());
1729  delete htmlEncoding;
1730  }
1731  }
1732 
1733  if (!xml)
1734  {
1735  GBool done = newHtmlOutlineLevel(output, outlines, catalog);
1736  if (done && !complexMode)
1737  fputs("<hr/>\n", output);
1738 
1739  if (bClose)
1740  {
1741  fputs("</body>\n</html>\n", output);
1742  fclose(output);
1743  }
1744  }
1745  else
1746  newXmlOutlineLevel(output, outlines, catalog);
1747 
1748  return gTrue;
1749 #endif
1750 }
1751 
1752 GBool HtmlOutputDev::newHtmlOutlineLevel(FILE *output, GooList *outlines, Catalog* catalog, int level)
1753 {
1754 #ifdef DISABLE_OUTLINE
1755  return gFalse;
1756 #else
1757  GBool atLeastOne = gFalse;
1758 
1759  if (level == 1)
1760  {
1761  fputs("<a name=\"outline\"></a>", output);
1762  fputs("<h1>Document Outline</h1>\n", output);
1763  }
1764  fputs("<ul>\n",output);
1765 
1766  for (int i = 0; i < outlines->getLength(); i++)
1767  {
1768  OutlineItem *item = (OutlineItem*)outlines->get(i);
1769  GooString *titleStr = HtmlFont::HtmlFilter(item->getTitle(),
1770  item->getTitleLength());
1771 
1772  GooString *linkName = NULL;;
1773  int page = getOutlinePageNum(item);
1774  if (page > 0)
1775  {
1776  /* complex simple
1777  frames file-4.html files.html#4
1778  noframes file.html#4 file.html#4
1779  */
1780  linkName=basename(Docname);
1781  GooString *str=GooString::fromInt(page);
1782  if (noframes) {
1783  linkName->append(".html#");
1784  linkName->append(str);
1785  } else {
1786  if( complexMode ) {
1787  linkName->append("-");
1788  linkName->append(str);
1789  linkName->append(".html");
1790  } else {
1791  linkName->append("s.html#");
1792  linkName->append(str);
1793  }
1794  }
1795  delete str;
1796  }
1797 
1798  fputs("<li>",output);
1799  if (linkName)
1800  fprintf(output,"<a href=\"%s\">", linkName->getCString());
1801  fputs(titleStr->getCString(),output);
1802  if (linkName) {
1803  fputs("</a>",output);
1804  delete linkName;
1805  }
1806  delete titleStr;
1807  atLeastOne = gTrue;
1808 
1809  item->open();
1810  if (item->hasKids() && item->getKids())
1811  {
1812  fputs("\n",output);
1813  newHtmlOutlineLevel(output, item->getKids(), catalog, level+1);
1814  }
1815  item->close();
1816  fputs("</li>\n",output);
1817  }
1818  fputs("</ul>\n",output);
1819 
1820  return atLeastOne;
1821 #endif
1822 }
1823 
1824 void HtmlOutputDev::newXmlOutlineLevel(FILE *output, GooList *outlines, Catalog* catalog)
1825 {
1826 #ifndef DISABLE_OUTLINE
1827  fputs("<outline>\n", output);
1828 
1829  for (int i = 0; i < outlines->getLength(); i++)
1830  {
1831  OutlineItem *item = (OutlineItem*)outlines->get(i);
1832  GooString *titleStr = HtmlFont::HtmlFilter(item->getTitle(),
1833  item->getTitleLength());
1834  int page = getOutlinePageNum(item);
1835  if (page > 0)
1836  {
1837  fprintf(output, "<item page=\"%d\">%s</item>\n",
1838  page, titleStr->getCString());
1839  }
1840  else
1841  {
1842  fprintf(output, "<item>%s</item>\n", titleStr->getCString());
1843  }
1844  delete titleStr;
1845 
1846  item->open();
1847  if (item->hasKids() && item->getKids())
1848  {
1849  newXmlOutlineLevel(output, item->getKids(), catalog);
1850  }
1851  item->close();
1852  }
1853 
1854  fputs("</outline>\n", output);
1855 #endif
1856 }
1857 
1858 #ifndef DISABLE_OUTLINE
1859 int HtmlOutputDev::getOutlinePageNum(OutlineItem *item)
1860 {
1861  LinkAction *action = item->getAction();
1862  LinkGoTo *link = NULL;
1863  LinkDest *linkdest = NULL;
1864  int pagenum = -1;
1865 
1866  if (!action || action->getKind() != actionGoTo)
1867  return pagenum;
1868 
1869  link = dynamic_cast<LinkGoTo*>(action);
1870 
1871  if (!link || !link->isOk())
1872  return pagenum;
1873 
1874  if (link->getDest())
1875  linkdest = link->getDest()->copy();
1876  else if (link->getNamedDest())
1877  linkdest = catalog->findDest(link->getNamedDest());
1878 
1879  if (!linkdest)
1880  return pagenum;
1881 
1882  if (linkdest->isPageRef()) {
1883  Ref pageref = linkdest->getPageRef();
1884  pagenum = catalog->findPage(pageref.num, pageref.gen);
1885  } else {
1886  pagenum = linkdest->getPageNum();
1887  }
1888 
1889  delete linkdest;
1890  return pagenum;
1891 }
1892 #endif
Definition: Object.h:115
HtmlString(GfxState *state, double fontSize, HtmlFontAccu *fonts)
void conv()
GBool isBold() const
Definition: HtmlFonts.h:84
void transform(double x1, double y1, double *x2, double *y2)
Definition: GfxState.h:1473
HtmlImage(GooString *_fName, GfxState *state)
GBool hasKids()
Definition: Outline.h:72
virtual void reset()=0
HtmlMetaVar(const char *_name, const char *_content)
Definition: Error.h:47
Guchar * getLine()
Definition: Stream.cc:506
double getPageHeight()
Definition: GfxState.h:1407
static GooString * HtmlFilter(Unicode *u, int uLen)
Definition: HtmlFonts.cc:242
GooString * getURI()
Definition: Link.h:248
GfxColorComp b
Definition: GfxState.h:149
virtual void close()
Definition: Stream.cc:126
double getHorizScaling()
Definition: GfxState.h:1453
virtual int getChar()=0
GBool complexMode
Definition: pdftohtml.cc:72
void getRGB(Guchar *x, GfxRGB *rgb)
Definition: GfxState.cc:5865
void addChar(GfxState *state, double x, double y, double dx, double dy, double ox, double oy, Unicode *u, int uLen)
HtmlOutputDev(Catalog *catalogA, char *fileName, char *title, char *author, char *keywords, char *subject, char *date, char *extension, GBool rawOrder, int firstPage=1, GBool outline=0)
GfxFontType getType()
Definition: GfxFont.h:204
GooString * getTextEncodingName()
Definition: Object.h:69
void endString()
void transformDelta(double x1, double y1, double *x2, double *y2)
Definition: GfxState.h:1476
virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy)
Definition: OutputDev.cc:66
Definition: XRef.h:93
GfxColorComp GfxGray
Definition: GfxState.h:142
Definition: PDFDoc.h:76
GooString * toString()
double * getTextMat()
Definition: GfxState.h:1450
GBool dumpDocOutline(PDFDoc *doc)
void setRotMat(const double *const mat)
Definition: HtmlFonts.h:89
virtual LinkActionKind getKind()=0
GBool isMatRotOrSkew(const double *const mat)
Definition: HtmlUtils.h:38
GBool noframes
Definition: pdftohtml.cc:77
Definition: Link.h:234
int cmp(GooString *str) const
Definition: GooString.cc:826
double getCurY()
Definition: GfxState.h:1461
int getRender()
Definition: GfxState.h:1456
LinkDest * getDest()
Definition: Link.h:191
GBool xml
Definition: pdftohtml.cc:79
GBool singleHtml
Definition: pdftohtml.cc:73
Outline * getOutline()
Definition: PDFDoc.cc:1612
int AddFont(const HtmlFont &font)
Definition: HtmlFonts.cc:299
double getAscent()
Definition: GfxFont.h:234
GooString * del(int i, int n=1)
Definition: GooString.cc:791
void gfree(void *p)
Definition: gmem.cc:251
#define DEBUG
int findPage(int num, int gen)
Definition: Catalog.cc:433
int getLineSize() const
Definition: HtmlFonts.h:87
void * get(int i)
Definition: GooList.h:60
void updateFont(GfxState *state)
#define gTrue
Definition: gtypes.h:35
GooString * getNamedDest()
Definition: Link.h:161
#define xoutRound(x)
Definition: HtmlFonts.cc:66
GooString * insert(int i, char c)
Definition: GooString.cc:772
GooString * getFileName()
Definition: Link.h:190
friend class HtmlPage
GBool stout
Definition: pdftohtml.cc:78
Definition: Link.h:96
void normalizeRotMat(double *mat)
Definition: HtmlUtils.h:45
Ref getPageRef()
Definition: Link.h:112
unsigned char Guchar
Definition: gtypes.h:46
const double * getRotMat() const
Definition: HtmlFonts.h:91
virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, int *maskColors, GBool inlineImg)
Definition: Stream.h:62
void * grealloc(void *p, size_t size)
Definition: gmem.cc:172
GBool getErrQuiet()
double xMin
GooList * getItems()
Definition: Outline.h:46
GfxFont * getFont()
Definition: GfxState.h:1448
void dump(FILE *f, int pageNum)
int getPageNum()
Definition: Link.h:111
int getLength()
Definition: GooList.h:51
LinkDest * findDest(GooString *name)
Definition: Catalog.cc:444
void reset()
Definition: Stream.cc:483
virtual GBool isOk()
Definition: Link.h:156
unsigned int CharCode
Definition: CharTypes.h:22
int gen
Definition: Object.h:71
virtual Stream * getNextStream()
Definition: Stream.h:224
void setLineSize(int _lineSize)
Definition: HtmlFonts.h:88
void getGray(Guchar *x, GfxGray *gray)
Definition: GfxState.cc:5848
void append(void *p)
Definition: GooList.cc:52
virtual void startPage(int pageNum, GfxState *state, XRef *xref)
static void clear()
Definition: HtmlFonts.cc:191
double * getFontMatrix()
Definition: GfxFont.h:228
unsigned int Unicode
Definition: CharTypes.h:13
Definition: Link.h:146
GBool noMerge
Definition: pdftohtml.cc:85
GBool showHidden
Definition: pdftohtml.cc:84
double getY1()
Definition: GfxState.h:1403
double getTransformedFontSize()
Definition: GfxState.cc:6797
int getNumImages()
GooString * fName
double getCharSpace()
Definition: GfxState.h:1451
void endString()
char * getCString() const
Definition: GooString.h:116
static GooString * fromInt(int x)
Definition: GooString.cc:249
void coalesce()
PDFRectangle * getRect() const
Definition: Annot.h:601
GBool is_within(double a, double thresh, double b)
Definition: HtmlUtils.h:26
void textTransformDelta(double x1, double y1, double *x2, double *y2)
Definition: GfxState.h:1482
LinkAction * getAction()
Definition: Outline.h:70
HtmlPage(GBool rawOrder, char *imgExtVal)
LinkDest * copy()
Definition: Link.h:103
GooString * CSStyle(int i, int j=0)
Definition: HtmlFonts.cc:314
void open()
Definition: Outline.cc:177
Unicode * getTitle()
Definition: Outline.h:68
int getNumPixelComps()
Definition: GfxState.h:1164
int getLength()
Definition: GooString.h:113
#define SLASH
Definition: HtmlOutputDev.h:55
Catalog * getCatalog()
Definition: PDFDoc.h:116
void AddLink(const HtmlLink &x)
Links * getLinks()
Definition: Page.cc:489
void addImage(GooString *fname, GfxState *state)
void beginString(GfxState *state, GooString *s)
bool GBool
Definition: gtypes.h:34
virtual void updateFont(GfxState *state)
double xMax
const char * name
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg)
Definition: OutputDev.cc:98
double yMin
double wordBreakThreshold
Definition: pdftohtml.cc:82
void close()
Definition: Stream.cc:487
LinkDest * getDest()
Definition: Link.h:160
#define DOCTYPE
Definition: HtmlOutputDev.h:60
virtual void beginString(GfxState *state, GooString *s)
#define deleteGooList(list, T)
Definition: GooList.h:108
const HtmlFont & getFont() const
Definition: HtmlOutputDev.h:92
HtmlLink * getLink()
Definition: HtmlOutputDev.h:91
GlobalParams * globalParams
GfxColorComp r
Definition: GfxState.h:149
double getX1()
Definition: GfxState.h:1402
GooString * append(char c)
Definition: GooString.cc:286
void addChar(GfxState *state, double x, double y, double dx, double dy, Unicode u)
static GooString * simple(HtmlFont *font, Unicode *content, int uLen)
Definition: HtmlFonts.cc:276
GfxColorComp g
Definition: GfxState.h:149
void close()
Definition: Outline.cc:183
double getDescent()
Definition: GfxFont.h:235
virtual void endPage()
void * del(int i)
Definition: GooList.cc:84
double getPageWidth()
Definition: GfxState.h:1406
int getTitleLength()
Definition: Outline.h:69
GBool printHtml
Definition: pdftohtml.cc:71
virtual void endString(GfxState *state)
GBool isPageRef()
Definition: Link.h:110
int size() const
Definition: HtmlFonts.h:114
virtual StreamKind getKind()=0
int num
Definition: Object.h:70
double getCurX()
Definition: GfxState.h:1460
virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, Unicode *u, int uLen)
GBool ignore
Definition: pdftohtml.cc:74
void CDECL error(ErrorCategory category, Goffset pos, const char *msg,...)
Definition: Error.cc:62
void * gmalloc(size_t size)
Definition: gmem.cc:119
GooString * copy() const
Definition: GooString.h:71
double yMax
GBool rot_matrices_equal(const double *const mat0, const double *const mat1)
Definition: HtmlUtils.h:30
GBool isItalic() const
Definition: HtmlFonts.h:83
static GooString * format(const char *fmt,...) GOOSTRING_FORMAT
Definition: GooString.cc:257
void getFillRGB(GfxRGB *rgb)
Definition: GfxState.h:1415
GBool printCommands
Definition: pdftohtml.cc:69
HtmlFont * Get(int i)
Definition: HtmlFonts.h:110
GooList * getKids()
Definition: Outline.h:73
GBool isEqualIgnoreBold(const HtmlFont &x) const
Definition: HtmlFonts.cc:214
virtual ~HtmlOutputDev()
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg)
GooString * getFileName()
Definition: Link.h:221
virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, int *maskColors, GBool inlineImg)
Definition: OutputDev.cc:123
void clear()
Definition: Stream.h:98
#define gFalse
Definition: gtypes.h:36