Changeset 367 for trunk


Ignore:
Timestamp:
Apr 8, 2010, 10:16:54 AM (11 years ago)
Author:
dmik
Message:

Merged bramches/kmk (r294:365) to trunk.

Location:
trunk
Files:
14 deleted
11 edited
157 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/libdjvu/DjVuGlobal.h

    r280 r367  
    7070inline void * operator new(size_t, void * ptr) { return ptr; }
    7171# endif
    72 #elif defined(AUTOCONF) && defined(HAVE_STDINCLUDES)
     72#elif (defined(AUTOCONF) || defined(OS2)) && defined(HAVE_STDINCLUDES)
    7373# include <new>
    7474#else
  • trunk/libdjvu/config.h

    r280 r367  
    131131
    132132/* define if the compiler comes with standard includes */
     133#if defined(__WATCOM__)
    133134#undef HAVE_STDINCLUDES
     135#else
     136#define HAVE_STDINCLUDES 1
     137#endif
    134138
    135139/* Define to 1 if you have the <stdint.h> header file. */
  • trunk/poppler/fc-emulate-os2/fontconfig/fontconfig.cpp

    r272 r367  
    2222#define INCL_DOS
    2323#define INCL_WIN
     24#if defined(__EMX__)
     25#define OS2EMX_PLAIN_CHAR
     26#endif
    2427#include <os2.h>
    2528
     
    2932
    3033#include <stdio.h>
     34#include <string.h>
     35
     36#if defined( __WATCOMC__ )
    3137#include <dos.h>
    32 #include <string.h>
     38#else
     39#include <io.h>
     40#include <sys/stat.h>
     41#endif
    3342
    3443#include "fontconfig.h"
     
    247256
    248257    string key = familyName;
    249     if ( stricmp( styleName.c_str(), "regular" ) != 0 ) {
     258    if ( stricmp( styleName.c_str(), "regular" ) != 0 &&
     259         stricmp( styleName.c_str(), "book" ) != 0 ) {
    250260        key += ' ';
    251261        key += styleName;
     
    278288    char dir[ _MAX_DIR ];
    279289    char fname[ _MAX_FNAME ];
     290#if defined( __WATCOMC__ )
    280291    _splitpath( __argv[0], drive, dir, fname, NULL );
     292#else
     293    _execname( fullpath, sizeof(fullpath) );
     294    _splitpath( fullpath, drive, dir, fname, NULL );
     295#endif
    281296    strlwr( fname );
    282297    _makepath( fullpath, drive, dir, fname, ".fcf" );
     
    435450#define DEFAULT_SANSSERIF_FONT      "helvetica"
    436451#define DEFAULT_MONOSPACED_FONT     "courier"
     452#define DEFAULT_SYMBOL_FONT         "symbol set"
    437453
    438454static bool isSansserif( const char *family )
     
    445461}
    446462
    447 static string buildFontKey( FcPattern *p, bool useDefaultFonts )
     463static string buildFontKey( FcPattern *p )
    448464{
    449465    string key = p->family;
    450466
    451     if ( useDefaultFonts )
    452     {
     467    // From http://en.wikipedia.org/wiki/Portable_Document_Format:
     468    //
     469    // There are fourteen typefaces that have a special significance to PDF
     470    // documents:
     471    //
     472    //  * Times (v3) (in regular, italic, bold, and bold italic)
     473    //  * Courier (in regular, oblique, bold and bold oblique)
     474    //  * Helvetica (v3) (in regular, oblique, bold and bold oblique)
     475    //  * Symbol
     476    //  * Zapf Dingbats
     477    //
     478    // These fonts, sometimes referred to as the "base fourteen fonts" should
     479    // always be present (actually present or a close substitute) and so need
     480    // not be embedded in a PDF.[46]  PDF viewers must know about the metrics
     481    // of these fonts. Other fonts may be substituted if they are not embedded
     482    // in a PDF.
     483    //
     484    // The following code is based on this information and guarantees that we
     485    // always return a valid font for those (except Zapf Dingbats for which we
     486    // don't have a pre-installed OS/2 font).
     487
     488    bool ignoreStyle = false;
     489
     490    if ( fontmap->find( key ) == fontmap->end() ) {
     491        // not found: try substitutions
    453492        if ( p->spacing == FC_MONO ) {
    454493            key = DEFAULT_MONOSPACED_FONT;
    455         }
    456         else
    457         {
     494        } else {
    458495            if ( isSansserif( p->family ) ) {
    459496                key = DEFAULT_SANSSERIF_FONT;
     497            } else {
     498                if ( key == "symbol" ) {
     499                    ignoreStyle = true;
     500                    key = "opensymbol";
     501                    if ( fontmap->find( key ) == fontmap->end() )
     502                        key = DEFAULT_SYMBOL_FONT;
     503                } else if ( key == "zapfdingbats" || key == "zapf dingbats" ) {
     504                    ignoreStyle = true;
     505                    key = "dejavu sans";
     506                    // last resort, quite meaningless but we must provide something
     507                    if ( fontmap->find( key ) == fontmap->end() )
     508                        key = DEFAULT_SYMBOL_FONT;
     509                } else {
     510                    key = DEFAULT_SERIF_FONT;
     511                }
    460512            }
    461             else {
    462                 key = DEFAULT_SERIF_FONT;
    463             }
    464         }
    465     }
    466     else
    467     {
    468         // use 'Symbol Set' (SYMB.PFB) instead of 'Symbol'
    469         if ( strcmp( p->family, "symbol" ) == 0 ) {
    470             key = "symbol set";
    471         }
    472     }
    473 
    474     if ( p->weight > FC_WEIGHT_NORMAL ) {
    475         key += ' ';
    476         key += "bold";
    477     }
    478 
    479     if ( (p->slant == FC_SLANT_ITALIC) || (p->slant == FC_SLANT_OBLIQUE) ) {
    480         key += ' ';
    481         key += "italic";
     513        }
     514
     515    }
     516
     517    if ( !ignoreStyle ) {
     518        if ( p->weight > FC_WEIGHT_NORMAL ) {
     519            key += ' ';
     520            key += "bold";
     521        }
     522        if ( (p->slant == FC_SLANT_ITALIC) || (p->slant == FC_SLANT_OBLIQUE) ) {
     523            key += ' ';
     524            key += "italic";
     525        }
    482526    }
    483527
     
    497541    pat->filename = NULL;
    498542
    499     string key = buildFontKey( pat, false );
    500 
    501     if ( fontmap->find( key ) == fontmap->end() ) {
    502         key = buildFontKey( pat, true );
    503         pat->filename = newstrdup( (*fontmap)[ key ].c_str() );
    504     }
    505     else {
    506         pat->filename = newstrdup( (*fontmap)[ key ].c_str() );
    507     }
     543    string key = buildFontKey( pat );
     544    pat->filename = newstrdup( (*fontmap)[ key ].c_str() );
    508545
    509546//printf( "MATCHED STYLE: %s, FILENAME: %s\n", key.c_str(), pat->filename );
  • trunk/poppler/fc-emulate-os2/fontconfig/fontconfig.h

    r71 r367  
    2323#define _ERFONTCONFIG_H_
    2424
    25 typedef unsigned char   FcChar8;
    26 typedef unsigned short  FcChar16;
    27 typedef unsigned int    FcChar32;
    28 typedef int             FcBool;
     25typedef char    FcChar8;
     26typedef short   FcChar16;
     27typedef int     FcChar32;
     28typedef int     FcBool;
    2929
    3030
  • trunk/poppler/mypoppler/config.h

    r250 r367  
    1414#undef HAVE_CAIRO
    1515
    16 /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
    17    */
     16/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */
     17#if defined(__WATCOMC__)
    1818#undef HAVE_DIRENT_H
     19#else
     20#define HAVE_DIRENT_H 1
     21#endif
    1922
    2023#define HAVE_DIRECT_H 1
  • trunk/poppler/mypoppler/goo/gstrtod.cc

    r290 r367  
    2626#include <locale.h>
    2727#include <errno.h>
    28 #include <stdlib>
     28#include <stdlib.h>
    2929#include <string.h>
    3030
  • trunk/poppler/mypoppler/poppler/GfxFont.cc

    r277 r367  
    542542  char *charName;
    543543  GBool missing, hex;
     544  char alpha;
    544545  Unicode toUnicode[256];
    545546  CharCodeToUnicode *utu, *ctu2;
     
    827828
    828829  // pass 1: use the name-to-Unicode mapping table
    829   missing = hex = gFalse;
     830  missing = gFalse;
     831  hex = gTrue;
     832  alpha = -1;
    830833  for (code = 0; code < 256; ++code) {
    831834    if ((charName = enc[code])) {
     
    834837        // if it wasn't in the name-to-Unicode table, check for a
    835838        // name that looks like 'Axx' or 'xx', where 'A' is any letter
    836         // and 'xx' is two hex digits
    837         if ((strlen(charName) == 3 &&
    838              isalpha(charName[0]) &&
    839              isxdigit(charName[1]) && isxdigit(charName[2]) &&
    840              ((charName[1] >= 'a' && charName[1] <= 'f') ||
    841               (charName[1] >= 'A' && charName[1] <= 'F') ||
    842               (charName[2] >= 'a' && charName[2] <= 'f') ||
    843               (charName[2] >= 'A' && charName[2] <= 'F'))) ||
    844             (strlen(charName) == 2 &&
    845              isxdigit(charName[0]) && isxdigit(charName[1]) &&
    846              ((charName[0] >= 'a' && charName[0] <= 'f') ||
    847               (charName[0] >= 'A' && charName[0] <= 'F') ||
    848               (charName[1] >= 'a' && charName[1] <= 'f') ||
    849               (charName[1] >= 'A' && charName[1] <= 'F')))) {
    850           hex = gTrue;
     839        // and 'xx' is two hex digits. Be strict and assume that names are
     840    // consistent (i.e. either all are 'Axx' or 'xx')
     841    if (hex) {
     842      if (strlen(charName) == 3 &&
     843          isalpha(charName[0]) &&
     844          isxdigit(charName[1]) && isxdigit(charName[2]) &&
     845          ((charName[1] >= 'a' && charName[1] <= 'f') ||
     846           (charName[1] >= 'A' && charName[1] <= 'F') ||
     847           (charName[2] >= 'a' && charName[2] <= 'f') ||
     848           (charName[2] >= 'A' && charName[2] <= 'F'))) {
     849        if (alpha == -1)
     850          alpha = charName[0];
     851        else if (alpha != charName[0])
     852          hex = gFalse;
     853      } else
     854      if (strlen(charName) == 2 &&
     855          isxdigit(charName[0]) && isxdigit(charName[1]) &&
     856          ((charName[0] >= 'a' && charName[0] <= 'f') ||
     857           (charName[0] >= 'A' && charName[0] <= 'F') ||
     858           (charName[1] >= 'a' && charName[1] <= 'f') ||
     859           (charName[1] >= 'A' && charName[1] <= 'F'))) {
     860        if (alpha == -1)
     861          alpha = 0;
     862        else if (alpha != 0)
     863          hex = gFalse;
     864      } else {
     865          hex = gFalse;
     866      }
    851867        }
    852868        missing = gTrue;
  • trunk/poppler/mypoppler/poppler/NameToUnicodeTable.h

    r2 r367  
    10941094  {0x007d, "}"},
    10951095  {0x007e, "~"},
     1096  // Zapf Dingbats PS character name to Unicode mappings according to:
     1097  // http://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/zdingbat.txt
     1098  {0x2701, "a1"},
     1099  {0x2702, "a2"},
     1100  {0x2703, "a202"},
     1101  {0x2704, "a3"},
     1102  {0x260E, "a4"},
     1103  {0x2706, "a5"},
     1104  {0x2707, "a119"},
     1105  {0x2708, "a118"},
     1106  {0x2709, "a117"},
     1107  {0x261B, "a11"},
     1108  {0x261E, "a12"},
     1109  {0x270C, "a13"},
     1110  {0x270D, "a14"},
     1111  {0x270E, "a15"},
     1112  {0x270F, "a16"},
     1113  {0x2710, "a105"},
     1114  {0x2711, "a17"},
     1115  {0x2712, "a18"},
     1116  {0x2713, "a19"},
     1117  {0x2714, "a20"},
     1118  {0x2715, "a21"},
     1119  {0x2716, "a22"},
     1120  {0x2717, "a23"},
     1121  {0x2718, "a24"},
     1122  {0x2719, "a25"},
     1123  {0x271A, "a26"},
     1124  {0x271B, "a27"},
     1125  {0x271C, "a28"},
     1126  {0x271D, "a6"},
     1127  {0x271E, "a7"},
     1128  {0x271F, "a8"},
     1129  {0x2720, "a9"},
     1130  {0x2721, "a10"},
     1131  {0x2722, "a29"},
     1132  {0x2723, "a30"},
     1133  {0x2724, "a31"},
     1134  {0x2725, "a32"},
     1135  {0x2726, "a33"},
     1136  {0x2727, "a34"},
     1137  {0x2605, "a35"},
     1138  {0x2729, "a36"},
     1139  {0x272A, "a37"},
     1140  {0x272B, "a38"},
     1141  {0x272C, "a39"},
     1142  {0x272D, "a40"},
     1143  {0x272E, "a41"},
     1144  {0x272F, "a42"},
     1145  {0x2730, "a43"},
     1146  {0x2731, "a44"},
     1147  {0x2732, "a45"},
     1148  {0x2733, "a46"},
     1149  {0x2734, "a47"},
     1150  {0x2735, "a48"},
     1151  {0x2736, "a49"},
     1152  {0x2737, "a50"},
     1153  {0x2738, "a51"},
     1154  {0x2739, "a52"},
     1155  {0x273A, "a53"},
     1156  {0x273B, "a54"},
     1157  {0x273C, "a55"},
     1158  {0x273D, "a56"},
     1159  {0x273E, "a57"},
     1160  {0x273F, "a58"},
     1161  {0x2740, "a59"},
     1162  {0x2741, "a60"},
     1163  {0x2742, "a61"},
     1164  {0x2743, "a62"},
     1165  {0x2744, "a63"},
     1166  {0x2745, "a64"},
     1167  {0x2746, "a65"},
     1168  {0x2747, "a66"},
     1169  {0x2748, "a67"},
     1170  {0x2749, "a68"},
     1171  {0x274A, "a69"},
     1172  {0x274B, "a70"},
     1173  {0x25CF, "a71"},
     1174  {0x274D, "a72"},
     1175  {0x25A0, "a73"},
     1176  {0x274F, "a74"},
     1177  {0x2750, "a203"},
     1178  {0x2751, "a75"},
     1179  {0x2752, "a204"},
     1180  {0x25B2, "a76"},
     1181  {0x25BC, "a77"},
     1182  {0x25C6, "a78"},
     1183  {0x2756, "a79"},
     1184  {0x25D7, "a81"},
     1185  {0x2758, "a82"},
     1186  {0x2759, "a83"},
     1187  {0x275A, "a84"},
     1188  {0x275B, "a97"},
     1189  {0x275C, "a98"},
     1190  {0x275D, "a99"},
     1191  {0x275E, "a100"},
     1192  {0xF8D7, "a89"},
     1193  {0xF8D8, "a90"},
     1194  {0xF8D9, "a93"},
     1195  {0xF8DA, "a94"},
     1196  {0xF8DB, "a91"},
     1197  {0xF8DC, "a92"},
     1198  {0xF8DD, "a205"},
     1199  {0xF8DE, "a85"},
     1200  {0xF8DF, "a206"},
     1201  {0xF8E0, "a86"},
     1202  {0xF8E1, "a87"},
     1203  {0xF8E2, "a88"},
     1204  {0xF8E3, "a95"},
     1205  {0xF8E4, "a96"},
     1206  {0x2761, "a101"},
     1207  {0x2762, "a102"},
     1208  {0x2763, "a103"},
     1209  {0x2764, "a104"},
     1210  {0x2765, "a106"},
     1211  {0x2766, "a107"},
     1212  {0x2767, "a108"},
     1213  {0x2663, "a112"},
     1214  {0x2666, "a111"},
     1215  {0x2665, "a110"},
     1216  {0x2660, "a109"},
     1217  {0x2460, "a120"},
     1218  {0x2461, "a121"},
     1219  {0x2462, "a122"},
     1220  {0x2463, "a123"},
     1221  {0x2464, "a124"},
     1222  {0x2465, "a125"},
     1223  {0x2466, "a126"},
     1224  {0x2467, "a127"},
     1225  {0x2468, "a128"},
     1226  {0x2469, "a129"},
     1227  {0x2776, "a130"},
     1228  {0x2777, "a131"},
     1229  {0x2778, "a132"},
     1230  {0x2779, "a133"},
     1231  {0x277A, "a134"},
     1232  {0x277B, "a135"},
     1233  {0x277C, "a136"},
     1234  {0x277D, "a137"},
     1235  {0x277E, "a138"},
     1236  {0x277F, "a139"},
     1237  {0x2780, "a140"},
     1238  {0x2781, "a141"},
     1239  {0x2782, "a142"},
     1240  {0x2783, "a143"},
     1241  {0x2784, "a144"},
     1242  {0x2785, "a145"},
     1243  {0x2786, "a146"},
     1244  {0x2787, "a147"},
     1245  {0x2788, "a148"},
     1246  {0x2789, "a149"},
     1247  {0x278A, "a150"},
     1248  {0x278B, "a151"},
     1249  {0x278C, "a152"},
     1250  {0x278D, "a153"},
     1251  {0x278E, "a154"},
     1252  {0x278F, "a155"},
     1253  {0x2790, "a156"},
     1254  {0x2791, "a157"},
     1255  {0x2792, "a158"},
     1256  {0x2793, "a159"},
     1257  {0x2794, "a160"},
     1258  {0x2192, "a161"},
     1259  {0x2194, "a163"},
     1260  {0x2195, "a164"},
     1261  {0x2798, "a196"},
     1262  {0x2799, "a165"},
     1263  {0x279A, "a192"},
     1264  {0x279B, "a166"},
     1265  {0x279C, "a167"},
     1266  {0x279D, "a168"},
     1267  {0x279E, "a169"},
     1268  {0x279F, "a170"},
     1269  {0x27A0, "a171"},
     1270  {0x27A1, "a172"},
     1271  {0x27A2, "a173"},
     1272  {0x27A3, "a162"},
     1273  {0x27A4, "a174"},
     1274  {0x27A5, "a175"},
     1275  {0x27A6, "a176"},
     1276  {0x27A7, "a177"},
     1277  {0x27A8, "a178"},
     1278  {0x27A9, "a179"},
     1279  {0x27AA, "a193"},
     1280  {0x27AB, "a180"},
     1281  {0x27AC, "a199"},
     1282  {0x27AD, "a181"},
     1283  {0x27AE, "a200"},
     1284  {0x27AF, "a182"},
     1285  {0x27B1, "a201"},
     1286  {0x27B2, "a183"},
     1287  {0x27B3, "a184"},
     1288  {0x27B4, "a197"},
     1289  {0x27B5, "a185"},
     1290  {0x27B6, "a194"},
     1291  {0x27B7, "a198"},
     1292  {0x27B8, "a186"},
     1293  {0x27B9, "a195"},
     1294  {0x27BA, "a187"},
     1295  {0x27BB, "a188"},
     1296  {0x27BC, "a189"},
     1297  {0x27BD, "a190"},
     1298  {0x27BE, "a191"},
     1299  // end of Zapf Dingbats
    10961300  { 0, NULL }
    10971301};
  • trunk/poppler/mypoppler/poppler/TextOutputDev.cc

    r277 r367  
    16161616}
    16171617
     1618GBool TextBlock::isBeforeByRule1(TextBlock *blk1) {
     1619  GBool before = gFalse;
     1620  GBool overlap = gFalse;
     1621
     1622  switch (this->page->primaryRot) {
     1623  case 0:
     1624  case 2:
     1625    overlap = ((this->xMin <= blk1->xMin) &&
     1626               (blk1->xMin <= this->xMax)) ||
     1627      ((blk1->xMin <= this->xMin) &&
     1628       (this->xMin <= blk1->xMax));
     1629    break;
     1630  case 1:
     1631  case 3:
     1632    overlap = ((this->yMin <= blk1->yMin) &&
     1633               (blk1->yMin <= this->yMax)) ||
     1634      ((blk1->yMin <= this->yMin) &&
     1635       (this->yMin <= blk1->yMax));
     1636    break;
     1637  }
     1638  switch (this->page->primaryRot) {
     1639  case 0:
     1640    before = overlap && this->yMin < blk1->yMin;
     1641    break;
     1642  case 1:
     1643    before = overlap && this->xMax > blk1->xMax;
     1644    break;
     1645  case 2:
     1646    before = overlap && this->yMax > blk1->yMax;
     1647    break;
     1648  case 3:
     1649    before = overlap && this->xMin < blk1->xMin;
     1650    break;
     1651  }
     1652  return before;
     1653}
     1654
     1655GBool TextBlock::isBeforeByRule2(TextBlock *blk1) {
     1656  double cmp = 0;
     1657  int rotLR = rot;
     1658
     1659  if (!page->primaryLR) {
     1660    rotLR = (rotLR + 2) % 4;
     1661  }
     1662
     1663  switch (rotLR) {
     1664  case 0:
     1665    cmp = xMax - blk1->xMin;
     1666    break;
     1667  case 1:
     1668    cmp = yMin - blk1->yMax;
     1669    break;
     1670  case 2:
     1671    cmp = blk1->xMax - xMin;
     1672    break;
     1673  case 3:
     1674    cmp = blk1->yMin - yMax;
     1675    break;
     1676  }
     1677  return cmp <= 0;
     1678}
     1679
     1680// Sort into reading order by performing a topological sort using the rules
     1681// given in "High Performance Document Layout Analysis", T.M. Breuel, 2003.
     1682// See http://pubs.iupr.org/#2003-breuel-sdiut
     1683// Topological sort is done by depth first search, see
     1684// http://en.wikipedia.org/wiki/Topological_sorting
     1685int TextBlock::visitDepthFirst(TextBlock *blkList, int pos1,
     1686                               TextBlock **sorted, int sortPos,
     1687                               GBool* visited) {
     1688  int pos2;
     1689  TextBlock *blk1, *blk2, *blk3;
     1690  GBool before;
     1691
     1692  if (visited[pos1]) {
     1693    return sortPos;
     1694  }
     1695
     1696  blk1 = this;
     1697
     1698#if 0 // for debugging
     1699  printf("visited: %d %.2f..%.2f %.2f..%.2f\n",
     1700         sortPos, blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1701#endif
     1702  visited[pos1] = gTrue;
     1703  pos2 = -1;
     1704  for (blk2 = blkList; blk2; blk2 = blk2->next) {
     1705    pos2++;
     1706    if (visited[pos2]) {
     1707      // skip visited nodes
     1708      continue;
     1709    }
     1710    before = gFalse;
     1711    if (blk2->isBeforeByRule1(blk1)) {
     1712      // Rule (1) blk1 and blk2 overlap, and blk2 is above blk1.
     1713      before = gTrue;
     1714#if 0 // for debugging
     1715      printf("rule1: %.2f..%.2f %.2f..%.2f %.2f..%.2f %.2f..%.2f\n",
     1716             blk2->xMin, blk2->xMax, blk2->yMin, blk2->yMax,
     1717             blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1718#endif
     1719    } else if (blk2->isBeforeByRule2(blk1)) {
     1720      // Rule (2) blk2 left of blk1, and no intervening blk3
     1721      //          such that blk1 is before blk3 by rule 1,
     1722      //          and blk3 is before blk2 by rule 1.
     1723      before = gTrue;
     1724      for (blk3 = blkList; blk3; blk3 = blk3->next) {
     1725        if (blk3 == blk2 || blk3 == blk1) {
     1726          continue;
     1727        }
     1728        if (blk1->isBeforeByRule1(blk3) &&
     1729            blk3->isBeforeByRule1(blk2)) {
     1730          before = gFalse;
     1731          break;
     1732        }
     1733      }
     1734#if 0 // for debugging
     1735      if (before) {
     1736        printf("rule2: %.2f..%.2f %.2f..%.2f %.2f..%.2f %.2f..%.2f\n",
     1737               blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax,
     1738               blk2->xMin, blk2->xMax, blk2->yMin, blk2->yMax);
     1739      }
     1740#endif
     1741    }
     1742    if (before) {
     1743      // blk2 is before blk1, so it needs to be visited
     1744      // before we can add blk1 to the sorted list.
     1745      sortPos = blk2->visitDepthFirst(blkList, pos2, sorted, sortPos, visited);
     1746    }
     1747  }
     1748#if 0 // for debugging
     1749  printf("sorted: %d %.2f..%.2f %.2f..%.2f\n",
     1750         sortPos, blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1751#endif
     1752  sorted[sortPos++] = blk1;
     1753  return sortPos;
     1754}
     1755
    16181756//------------------------------------------------------------------------
    16191757// TextFlow
     
    21842322  TextWord *word0, *word1, *word2;
    21852323  TextLine *line;
    2186   TextBlock *blkList, *blkStack, *blk, *lastBlk, *blk0, *blk1;
    2187   TextBlock **blkArray;
     2324  TextBlock *blkList, *blk, *lastBlk, *blk0, *blk1;
    21882325  TextFlow *flow, *lastFlow;
    21892326  TextUnderline *underline;
     
    21952332  int count[4];
    21962333  int lrCount;
    2197   int firstBlkIdx, nBlocksLeft;
    21982334  int col1, col2;
    21992335  int i, j, n;
     
    26882824  }
    26892825
    2690 #if 0 // for debugging 
     2826#if 0 // for debugging
    26912827  printf("*** rotation ***\n");
    26922828  for (rot = 0; rot < 4; ++rot) {
     
    28422978  //----- reading order sort
    28432979
    2844   // sort blocks into yx order (in preparation for reading order sort)
    2845   qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpYXPrimaryRot);
    2846 
    28472980  // compute space on left and right sides of each block
    28482981  for (i = 0; i < nBlocks; ++i) {
     
    28572990
    28582991#if 0 // for debugging
    2859   printf("*** blocks, after yx sort ***\n");
     2992  printf("PAGE\n");
     2993#endif
     2994
     2995  int sortPos = 0;
     2996  GBool *visited = (GBool *)gmallocn(nBlocks, sizeof(GBool));
     2997  for (i = 0; i < nBlocks; i++) {
     2998    visited[i] = gFalse;
     2999  }
     3000  i = -1;
     3001  for (blk1 = blkList; blk1; blk1 = blk1->next) {
     3002    i++;
     3003    sortPos = blk1->visitDepthFirst(blkList, i, blocks, sortPos, visited);
     3004  }
     3005  if (visited) {
     3006    gfree(visited);
     3007  }
     3008
     3009#if 0 // for debugging
     3010  printf("*** blocks, after ro sort ***\n");
    28603011  for (i = 0; i < nBlocks; ++i) {
    28613012    blk = blocks[i];
     
    28773028  }
    28783029  printf("\n");
     3030  fflush(stdout);
    28793031#endif
    28803032
     
    28823034  //~ this needs to be adjusted for writing mode (vertical text)
    28833035  //~ this also needs to account for right-to-left column ordering
    2884   blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
    2885   memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *));
     3036  flow = NULL;
    28863037  while (flows) {
    28873038    flow = flows;
     
    28903041  }
    28913042  flows = lastFlow = NULL;
    2892   firstBlkIdx = 0;
    2893   nBlocksLeft = nBlocks;
    2894   while (nBlocksLeft > 0) {
    2895 
    2896     // find the upper-left-most block
    2897     for (; !blkArray[firstBlkIdx]; ++firstBlkIdx) ;
    2898     i = firstBlkIdx;
    2899     blk = blkArray[i];
    2900     for (j = firstBlkIdx + 1; j < nBlocks; ++j) {
    2901       blk1 = blkArray[j];
    2902       if (blk1) {
    2903         if (blk && blk->secondaryDelta(blk1) > 0) {
    2904           break;
    2905         }
    2906         if (blk1->primaryCmp(blk) < 0) {
    2907           i = j;
    2908           blk = blk1;
    2909         }
    2910       }
    2911     }
    2912     blkArray[i] = NULL;
    2913     --nBlocksLeft;
     3043  // assume blocks are already in reading order,
     3044  // and construct flows accordingly.
     3045  for (i = 0; i < nBlocks; i++) {
     3046    blk = blocks[i];
    29143047    blk->next = NULL;
    2915 
    2916     // create a new flow, starting with the upper-left-most block
     3048    if (flow) {
     3049      blk1 = blocks[i - 1];
     3050      blkSpace = maxBlockSpacing * blk1->lines->words->fontSize;
     3051      if (blk1->secondaryDelta(blk) <= blkSpace &&
     3052          blk->isBelow(blk1) &&
     3053          flow->blockFits(blk, blk1)) {
     3054        flow->addBlock(blk);
     3055        continue;
     3056      }
     3057    }
    29173058    flow = new TextFlow(this, blk);
    29183059    if (lastFlow) {
     
    29223063    }
    29233064    lastFlow = flow;
    2924     fontSize = blk->lines->words->fontSize;
    2925 
    2926     // push the upper-left-most block on the stack
    2927     blk->stackNext = NULL;
    2928     blkStack = blk;
    2929 
    2930     // find the other blocks in this flow
    2931     while (blkStack) {
    2932 
    2933       // find the upper-left-most block under (but within
    2934       // maxBlockSpacing of) the top block on the stack
    2935       blkSpace = maxBlockSpacing * blkStack->lines->words->fontSize;
    2936       blk = NULL;
    2937       i = -1;
    2938       for (j = firstBlkIdx; j < nBlocks; ++j) {
    2939         blk1 = blkArray[j];
    2940         if (blk1) {
    2941           if (blkStack->secondaryDelta(blk1) > blkSpace) {
    2942             break;
    2943           }
    2944           if (blk && blk->secondaryDelta(blk1) > 0) {
    2945             break;
    2946           }
    2947           if (blk1->isBelow(blkStack) &&
    2948               (!blk || blk1->primaryCmp(blk) < 0)) {
    2949             i = j;
    2950             blk = blk1;
    2951           }
    2952         }
    2953       }
    2954 
    2955       // if a suitable block was found, add it to the flow and push it
    2956       // onto the stack
    2957       if (blk && flow->blockFits(blk, blkStack)) {
    2958         blkArray[i] = NULL;
    2959         --nBlocksLeft;
    2960         blk->next = NULL;
    2961         flow->addBlock(blk);
    2962         fontSize = blk->lines->words->fontSize;
    2963         blk->stackNext = blkStack;
    2964         blkStack = blk;
    2965 
    2966       // otherwise (if there is no block under the top block or the
    2967       // block is not suitable), pop the stack
    2968       } else {
    2969         blkStack = blkStack->stackNext;
    2970       }
    2971     }
    2972   }
    2973   gfree(blkArray);
     3065  }
    29743066
    29753067#if 0 // for debugging
     
    35223614GooString *TextSelectionDumper::getText (void)
    35233615{
    3524   GBool oneRot = gTrue;
    35253616  GooString *s;
    35263617  TextLineFrag *frag;
    3527   int i, col;
     3618  int i;
    35283619  GBool multiLine;
    35293620  UnicodeMap *uMap;
     
    35423633
    35433634  if (nFrags > 0) {
    3544     for (i = 0; i < nFrags; ++i) {
    3545       frags[i].computeCoords(oneRot);
    3546     }
    3547     page->assignColumns(frags, nFrags, oneRot);
    3548 
    3549     // if all lines in the region have the same rotation, use it;
    3550     // otherwise, use the page's primary rotation
    3551     if (oneRot) {
    3552       qsort(frags, nFrags, sizeof(TextLineFrag),
    3553             &TextLineFrag::cmpYXLineRot);
    3554     } else {
    3555       qsort(frags, nFrags, sizeof(TextLineFrag),
    3556             &TextLineFrag::cmpYXPrimaryRot);
    3557     }
    3558 
    3559     col = 0;
    35603635    multiLine = gFalse;
    35613636    for (i = 0; i < nFrags; ++i) {
    35623637      frag = &frags[i];
    35633638
    3564       // insert a return
    3565       if (frag->col < col ||
    3566           (i > 0 && fabs(frag->base - frags[i-1].base) >
    3567                       maxIntraLineDelta * frags[i-1].line->words->fontSize)) {
    3568           s->append(eol, eolLen);
    3569         col = 0;
    3570         multiLine = gTrue;
    3571       }
    3572 
    3573       // column alignment
    3574       for (; col < frag->col; ++col) {
    3575         s->append(space, spaceLen);
    3576       }
    3577 
    3578       // get the fragment text
    3579       col += page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, s);
    3580     }
    3581 
    3582     if (multiLine) {
     3639      page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, s);
    35833640      s->append(eol, eolLen);
    35843641    }
     
    38603917                               PDFRectangle *selection,
    38613918                               SelectionStyle style) {
    3862   TextLine *p, *begin, *end;
    38633919  PDFRectangle child_selection;
    3864   double start_x, start_y, stop_x, stop_y;
    3865 
    3866   begin = NULL;
    3867   end = NULL;
    3868   start_x = selection->x1;
    3869   start_y = selection->y1;
    3870   stop_x = selection->x2;
    3871   stop_y = selection->y2;
    3872  
    3873   for (p = lines; p != NULL; p = p->next) {
    3874     if (selection->x1 < p->xMax && selection->y1 < p->yMax &&
    3875         selection->x2 < p->xMax && selection->y2 < p->yMax && begin == NULL) {
    3876       begin = p;
    3877       if (selection->x1 < selection->x2) {
    3878         start_x = selection->x1;
    3879         start_y = selection->y1;
    3880         stop_x = selection->x2;
    3881         stop_y = selection->y2;
     3920  double x[2], y[2], d, best_d[2];
     3921  TextLine *p, *best_line[2];
     3922  int i, count = 0, best_count[2], start, stop;
     3923  GBool all[2];
     3924
     3925  x[0] = selection->x1;
     3926  y[0] = selection->y1;
     3927  x[1] = selection->x2;
     3928  y[1] = selection->y2;
     3929
     3930  for (i = 0; i < 2; i++) {
     3931    // the first/last lines are often not nearest
     3932    // the corners, so we have to force them to be
     3933    // selected when the selection runs outside this
     3934    // block.
     3935    if (page->primaryLR) {
     3936      all[i] = x[i] >= this->xMax && y[i] >= this->yMax;
     3937      if (x[i] <= this->xMin && y[i] <= this->yMin) {
     3938        best_line[i] = this->lines;
     3939        best_count[i] = 1;
    38823940      } else {
    3883         start_x = selection->x2;
    3884         start_y = selection->y2;
    3885         stop_x = selection->x1;
    3886         stop_y = selection->y1;
    3887       }
    3888     } else if (selection->x1 < p->xMax && selection->y1 < p->yMax && begin == NULL) {
    3889       begin = p;
    3890       start_x = selection->x1;
    3891       start_y = selection->y1;
    3892       stop_x = selection->x2;
    3893       stop_y = selection->y2;
    3894     } else if (selection->x2 < p->xMax && selection->y2 < p->yMax && begin == NULL) {
    3895       begin = p;
    3896       start_x = selection->x2;
    3897       start_y = selection->y2;
    3898       stop_x = selection->x1;
    3899       stop_y = selection->y1;
    3900     }
    3901 
    3902     if (((selection->x1 > p->xMin && selection->y1 > p->yMin) ||
    3903          (selection->x2 > p->xMin && selection->y2 > p->yMin))
    3904         && (begin != NULL))
    3905       end = p->next;
    3906   }
    3907 
    3908   /* Skip empty selection. */
    3909   if (end == begin)
     3941        best_line[i] = NULL;
     3942        best_count[i] = 0;
     3943      }
     3944    } else {
     3945      all[i] = x[i] <= this->xMin && y[i] >= this->yMax;
     3946      if (x[i] >= this->xMax && y[i] <= this->yMin) {
     3947        best_line[i] = this->lines;
     3948        best_count[i] = 1;
     3949      } else {
     3950        best_line[i] = NULL;
     3951        best_count[i] = 0;
     3952      }
     3953    }
     3954    best_d[i] = 0;
     3955  }
     3956
     3957  // find the nearest line to the selection points
     3958  // using the manhattan distance.
     3959  for (p = this->lines; p; p = p->next) {
     3960    count++;
     3961    for (i = 0; i < 2; i++) {
     3962      d = fmax(p->xMin - x[i], 0.0) +
     3963        fmax(x[i] - p->xMax, 0.0) +
     3964        fmax(p->yMin - y[i], 0.0) +
     3965        fmax(y[i] - p->yMax, 0.0);
     3966      if (!best_line[i] || all[i] ||
     3967          d < best_d[i]) {
     3968        best_line[i] = p;
     3969        best_count[i] = count;
     3970        best_d[i] = d;
     3971      }
     3972    }
     3973  }
     3974  // assert: best is always set.
     3975  if (!best_line[0] || !best_line[1]) {
    39103976    return;
    3911 
    3912   visitor->visitBlock (this, begin, end, selection);
    3913 
    3914   for (p = begin; p != end; p = p->next) {
    3915     if (p == begin && style != selectionStyleLine) {
    3916       child_selection.x1 = start_x;
    3917       child_selection.y1 = start_y;
     3977  }
     3978
     3979  // Now decide which point was first.
     3980  if (best_count[0] < best_count[1] ||
     3981      (best_count[0] == best_count[1] &&
     3982       y[0] < y[1])) {
     3983    start = 0;
     3984    stop = 1;
     3985  } else {
     3986    start = 1;
     3987    stop = 0;
     3988  }
     3989
     3990  visitor->visitBlock(this, best_line[start], best_line[stop], selection);
     3991
     3992  for (p = best_line[start]; p; p = p->next) {
     3993    if (page->primaryLR) {
     3994      child_selection.x1 = p->xMin;
     3995      child_selection.x2 = p->xMax;
    39183996    } else {
    3919       child_selection.x1 = 0;
    3920       child_selection.y1 = 0;
    3921     }
    3922     if (p->next == end && style != selectionStyleLine) {
    3923       child_selection.x2 = stop_x;
    3924       child_selection.y2 = stop_y;
     3997      child_selection.x1 = p->xMax;
     3998      child_selection.x2 = p->xMin;
     3999    }
     4000    child_selection.y1 = p->yMin;
     4001    child_selection.y2 = p->yMax;
     4002    if (style == selectionStyleLine) {
     4003      if (p == best_line[start]) {
     4004        child_selection.x1 = 0;
     4005        child_selection.y1 = 0;
     4006      }
     4007      if (p == best_line[stop]) {
     4008        child_selection.x2 = page->pageWidth;
     4009        child_selection.y2 = page->pageHeight;
     4010      }
    39254011    } else {
    3926       child_selection.x2 = page->pageWidth;
    3927       child_selection.y2 = page->pageHeight;
    3928     }
    3929 
     4012      if (p == best_line[start]) {
     4013        child_selection.x1 = fmax(p->xMin, fmin(p->xMax, x[start]));
     4014        child_selection.y1 = fmax(p->yMin, fmin(p->yMax, y[start]));
     4015      }
     4016      if (p == best_line[stop]) {
     4017        child_selection.x2 = fmax(p->xMin, fmin(p->xMax, x[stop]));
     4018        child_selection.y2 = fmax(p->yMin, fmin(p->yMax, y[stop]));
     4019      }
     4020    }
    39304021    p->visitSelection(visitor, &child_selection, style);
     4022    if (p == best_line[stop]) {
     4023      return;
     4024    }
    39314025  }
    39324026}
     
    39364030                              SelectionStyle style)
    39374031{
    3938   int i, begin, end;
    39394032  PDFRectangle child_selection;
    3940   double start_x, start_y, stop_x, stop_y;
    3941   TextBlock *b;
    3942 
    3943   begin = nBlocks;
    3944   end = 0;
    3945   start_x = selection->x1;
    3946   start_y = selection->y1;
    3947   stop_x = selection->x2;
    3948   stop_y = selection->y2;
    3949 
    3950   for (i = 0; i < nBlocks; i++) {
    3951     b = blocks[i];
    3952 
    3953     if (selection->x1 < b->xMax && selection->y1 < b->yMax &&
    3954         selection->x2 < b->xMax && selection->y2 < b->yMax && i < begin) {
    3955       begin = i;
    3956       if (selection->y1 < selection->y2) {
    3957         start_x = selection->x1;
    3958         start_y = selection->y1;
    3959         stop_x = selection->x2;
    3960         stop_y = selection->y2;
     4033  double x[2], y[2], d, best_d[2];
     4034  double xMin, yMin, xMax, yMax;
     4035  TextFlow *flow, *best_flow[2];
     4036  TextBlock *blk, *best_block[2];
     4037  int i, count = 0, best_count[2], start, stop;
     4038
     4039  if (!flows)
     4040    return;
     4041
     4042  x[0] = selection->x1;
     4043  y[0] = selection->y1;
     4044  x[1] = selection->x2;
     4045  y[1] = selection->y2;
     4046
     4047  xMin = pageWidth;
     4048  yMin = pageHeight;
     4049  xMax = 0.0;
     4050  yMax = 0.0;
     4051
     4052  for (i = 0; i < 2; i++) {
     4053    best_block[i] = NULL;
     4054    best_flow[i] = NULL;
     4055    best_count[i] = 0;
     4056    best_d[i] = 0;
     4057  }
     4058
     4059  // find the nearest blocks to the selection points
     4060  // using the manhattan distance.
     4061  for (flow = flows; flow; flow = flow->next) {
     4062    for (blk = flow->blocks; blk; blk = blk->next) {
     4063      count++;
     4064      // the first/last blocks in reading order are
     4065      // often not the closest to the page corners;
     4066      // track the corners, force those blocks to
     4067      // be selected if the selection runs across
     4068      // multiple pages.
     4069      xMin = fmin(xMin, blk->xMin);
     4070      yMin = fmin(yMin, blk->yMin);
     4071      xMax = fmax(xMax, blk->xMax);
     4072      yMax = fmax(yMax, blk->yMax);
     4073      for (i = 0; i < 2; i++) {
     4074        d = fmax(blk->xMin - x[i], 0.0) +
     4075          fmax(x[i] - blk->xMax, 0.0) +
     4076          fmax(blk->yMin - y[i], 0.0) +
     4077          fmax(y[i] - blk->yMax, 0.0);
     4078        if (!best_block[i] ||
     4079            d < best_d[i] ||
     4080            (!blk->next && !flow->next &&
     4081             x[i] > xMax && y[i] > yMax)) {
     4082          best_block[i] = blk;
     4083          best_flow[i] = flow;
     4084          best_count[i] = count;
     4085          best_d[i] = d;
     4086        }
     4087      }
     4088    }
     4089  }
     4090  for (i = 0; i < 2; i++) {
     4091    if (primaryLR) {
     4092      if (x[i] < xMin && y[i] < yMin) {
     4093        best_block[i] = flows->blocks;
     4094        best_flow[i] = flows;
     4095        best_count[i] = 1;
     4096      }
     4097    } else {
     4098      if (x[i] > xMax && y[i] < yMin) {
     4099        best_block[i] = flows->blocks;
     4100        best_flow[i] = flows;
     4101        best_count[i] = 1;
     4102      }
     4103    }
     4104  }
     4105  // assert: best is always set.
     4106  if (!best_block[0] || !best_block[1]) {
     4107    return;
     4108  }
     4109
     4110  // Now decide which point was first.
     4111  if (best_count[0] < best_count[1] ||
     4112      (best_count[0] == best_count[1] && y[0] < y[1])) {
     4113    start = 0;
     4114    stop = 1;
     4115  } else {
     4116    start = 1;
     4117    stop = 0;
     4118  }
     4119
     4120  for (flow = best_flow[start]; flow; flow = flow->next) {
     4121    if (flow == best_flow[start]) {
     4122      blk = best_block[start];
     4123    } else {
     4124      blk = flow->blocks;
     4125    }
     4126    for (; blk; blk = blk->next) {
     4127      if (primaryLR) {
     4128        child_selection.x1 = blk->xMin;
     4129        child_selection.x2 = blk->xMax;
    39614130      } else {
    3962         start_x = selection->x2;
    3963         start_y = selection->y2;
    3964         stop_x = selection->x1;
    3965         stop_y = selection->y1;
    3966       }
    3967     } else if (selection->x1 < b->xMax && selection->y1 < b->yMax && i < begin) {
    3968       begin = i;
    3969       start_x = selection->x1;
    3970       start_y = selection->y1;
    3971       stop_x = selection->x2;
    3972       stop_y = selection->y2;
    3973     } else if (selection->x2 < b->xMax && selection->y2 < b->yMax && i < begin) {
    3974       begin = i;
    3975       start_x = selection->x2;
    3976       start_y = selection->y2;
    3977       stop_x = selection->x1;
    3978       stop_y = selection->y1;
    3979     }
    3980 
    3981     if ((selection->x1 > b->xMin && selection->y1 > b->yMin) ||
    3982         (selection->x2 > b->xMin && selection->y2 > b->yMin))
    3983       end = i + 1;
    3984   }
    3985 
    3986   for (i = begin; i < end; i++) {
    3987     if (blocks[i]->xMin < start_x && start_x < blocks[i]->xMax &&
    3988         blocks[i]->yMin < start_y && start_y < blocks[i]->yMax) {
    3989       child_selection.x1 = start_x;
    3990       child_selection.y1 = start_y;
    3991     } else {
    3992       child_selection.x1 = 0;
    3993       child_selection.y1 = 0;
    3994     }
    3995     if (blocks[i]->xMin < stop_x && stop_x < blocks[i]->xMax &&
    3996         blocks[i]->yMin < stop_y && stop_y < blocks[i]->yMax) {
    3997       child_selection.x2 = stop_x;
    3998       child_selection.y2 = stop_y;
    3999     } else {
    4000       child_selection.x2 = pageWidth;
    4001       child_selection.y2 = pageHeight;
    4002     }
    4003 
    4004     blocks[i]->visitSelection(visitor, &child_selection, style);
     4131        child_selection.x1 = blk->xMax;
     4132        child_selection.x2 = blk->xMin;
     4133      }
     4134      child_selection.y1 = blk->yMin;
     4135      child_selection.y2 = blk->yMax;
     4136      if (blk == best_block[start]) {
     4137        child_selection.x1 = fmax(blk->xMin, fmin(blk->xMax, x[start]));
     4138        child_selection.y1 = fmax(blk->yMin, fmin(blk->yMax, y[start]));
     4139      }
     4140      if (blk == best_block[stop]) {
     4141        child_selection.x2 = fmax(blk->xMin, fmin(blk->xMax, x[stop]));
     4142        child_selection.y2 = fmax(blk->yMin, fmin(blk->yMax, y[stop]));
     4143        blk->visitSelection(visitor, &child_selection, style);
     4144        return;
     4145      }
     4146      blk->visitSelection(visitor, &child_selection, style);
     4147    }
    40054148  }
    40064149}
     
    42874430          (*outputFunc)(outputStream, s->getCString(), s->getLength());
    42884431          delete s;
    4289           if (!line->hyphenated) {
    4290             if (line->next) {
    4291               (*outputFunc)(outputStream, space, spaceLen);
    4292             } else if (blk->next) {
    4293               //~ this is a bit of a kludge - we should really do a more
    4294               //~ intelligent determination of paragraphs
    4295               if (blk->next->lines->words->fontSize ==
    4296                   blk->lines->words->fontSize) {
    4297                 (*outputFunc)(outputStream, space, spaceLen);
    4298               } else {
    4299                 (*outputFunc)(outputStream, eol, eolLen);
    4300               }
    4301             }
     4432          // output a newline when a hyphen is not suppressed
     4433          if (n == line->len) {
     4434            (*outputFunc)(outputStream, eol, eolLen);
    43024435          }
    43034436        }
    43044437      }
    4305       (*outputFunc)(outputStream, eol, eolLen);
    43064438      (*outputFunc)(outputStream, eol, eolLen);
    43074439    }
  • trunk/poppler/mypoppler/poppler/TextOutputDev.h

    r277 r367  
    362362private:
    363363
     364  GBool isBeforeByRule1(TextBlock *blk1);
     365  GBool isBeforeByRepeatedRule1(TextBlock *blkList, TextBlock *blk1);
     366  GBool isBeforeByRule2(TextBlock *blk1);
     367
     368  int visitDepthFirst(TextBlock *blkList, int pos1,
     369                      TextBlock **sorted, int sortPos,
     370                      GBool* visited);
     371
    364372  TextPage *page;               // the parent page
    365373  int rot;                      // text rotation
Note: See TracChangeset for help on using the changeset viewer.