Index: poppler-0.20.5/CMakeLists.txt =================================================================== --- poppler-0.20.5.orig/CMakeLists.txt 2012-10-10 19:32:57.000000000 +0200 +++ poppler-0.20.5/CMakeLists.txt 2012-10-21 02:25:36.000000000 +0200 @@ -30,6 +30,8 @@ option(ENABLE_LIBOPENJPEG "Use libopenjpeg for JPX streams." ON) option(ENABLE_LCMS "Use liblcms for color management." ON) option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF) +option(ENABLE_ICU "Build with ICU." ON) +option(ENABLE_FRIBIDI "Build with FRIBIDI." ON) option(ENABLE_ZLIB "Build with zlib (not totally safe)." OFF) option(USE_FIXEDPOINT "Use fixed point arithmetic in the Splash backend" OFF) option(USE_FLOAT "Use single precision arithmetic in the Splash backend" OFF) @@ -124,6 +126,21 @@ set(ENABLE_CPP ${ICONV_FOUND}) set(HAVE_ICONV ${ICONV_FOUND}) endif(ENABLE_CPP) + +# well i don't know what to do here. +# fribidi should be enabled if icu can't be. +# the modules are there. +if(ENABLE_ICU) + macro_optional_find_package(ICU) + set(ENABLE_ICU ${ICU_FOUND}) + set(HAVE_ICU ${ICU_FOUND}) +endif(ENABLE_ICU) +if(ENABLE_FRIBIDI) + macro_optional_find_package(FRIBIDI) + set(ENABLE_FRIBIDI ${FRIBIDI_FOUND}) + set(HAVE_FRIBIDI ${FRIBIDI_FOUND}) +endif(ENABLE_FRIBIDI) + if(ENABLE_ZLIB) find_package(ZLIB) if(ZLIB_FOUND) Index: poppler-0.20.5/Makefile.am =================================================================== --- poppler-0.20.5.orig/Makefile.am 2012-08-15 16:31:38.000000000 +0300 +++ poppler-0.20.5/Makefile.am 2012-10-21 02:25:36.000000000 +0200 @@ -86,6 +86,8 @@ cmake/modules/PopplerDefaults.cmake \ cmake/modules/PopplerMacros.cmake \ cmake/modules/FindLIBOPENJPEG.cmake \ + cmake/modules/FindICU.cmake \ + cmake/modules/FindFriBiDi.cmake \ config.h.cmake \ poppler-cairo.pc.cmake \ poppler/poppler-config.h.cmake \ Index: poppler-0.20.5/configure.ac =================================================================== --- poppler-0.20.5.orig/configure.ac 2012-10-10 19:32:48.000000000 +0200 +++ poppler-0.20.5/configure.ac 2012-10-21 02:25:36.000000000 +0200 @@ -265,6 +265,44 @@ AC_DEFINE(HAVE_FSEEK64) fi +dnl Test for icu +AC_ARG_ENABLE(icu, + AC_HELP_STRING([--enable-icu], + [Build with icu based BIDI support. Enabled by default.]), + enable_icu=$enableval, + enable_icu="yes") +if test x$enable_icu = xyes; then + PKG_CHECK_MODULES(ICU, icu-uc, + [icu_pkgconfig=yes], [icu_pkgconfig=no]) + if test "x$icu_pkgconfig" = "xyes"; then + AC_DEFINE(HAVE_ICU, 1, [Have ICU include files]) + else + ICU_LIBS= + ICU_CFLAGS= + AC_PATH_PROG(ICU_CONFIG, icu-config, no) + if test "x$ICU_CONFIG" != "xno" ; then + ICU_CFLAGS= + ICU_LIBS=`$ICU_CONFIG --ldflags-libsonly` + AC_DEFINE(HAVE_ICU, 1, [Have ICU include files]) + fi + fi +fi + +dnl Test for fribidi +if test "x$ICU_LIBS" = "x"; then +AC_ARG_ENABLE(fribidi, + AC_HELP_STRING([--enable-fribidi], + [Build with fribidi based BIDI support. Enabled by default.]), + enable_fribidi=$enableval, + enable_fribidi="yes") +if test x$enable_fribidi = xyes; then + PKG_CHECK_MODULES([FRIBIDI], [fribidi], + [AC_DEFINE(HAVE_FRIBIDI, 1, [whether FriBidi is available])], [:]) + AC_SUBST(FRIBIDI_CFLAGS) + AC_SUBST(FRIBIDI_LIBS) +fi +fi + dnl Test for zlib AC_ARG_ENABLE([zlib], [AS_HELP_STRING([--enable-zlib],[Build with zlib])], @@ -816,6 +854,8 @@ echo " use libjpeg: $enable_libjpeg" echo " use libpng: $enable_libpng" echo " use libtiff: $enable_libtiff" +echo " use icu: $enable_icu" +echo " use fribidi: $enable_fribidi" echo " use zlib: $enable_zlib" echo " use libcurl: $enable_libcurl" echo " use libopenjpeg: $enable_libopenjpeg" Index: poppler-0.20.5/cmake/modules/FindFriBiDi.cmake =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ poppler-0.20.5/cmake/modules/FindFriBiDi.cmake 2012-10-21 02:25:36.000000000 +0200 @@ -0,0 +1,93 @@ +# - Find the native FriBiDI includes and library +# +# +# This module defines +# FRIBIDI_INCLUDE_DIR, where to find fribidi.h, etc. +# FRIBIDI_LIBRARIES, the libraries to link against to use FriBiDi. +# PNG_DEFINITIONS - You should ADD_DEFINITONS(${PNG_DEFINITIONS}) before compiling code that includes png library files. +# FRIBIDI_FOUND, If false, do not try to use PNG. +# also defined, but not for general use are +# FRIBIDI_LIBRARY, where to find the FriBiDi library. +# +# If this module finds an old version of fribidi, then this module will run +# add_definitions(-DOLD_FRIBIDI) so that Wesnoth will compile. + +include(CheckSymbolExists) + +SET(FRIBIDI_FOUND "NO") + +# Set variable in temp var, otherwise FIND_PATH might fail +# unset isn't present in the required version of cmake. +FIND_PATH(xFRIBIDI_INCLUDE_DIR fribidi.h + /usr/local/include/fribidi + /usr/include/fribidi + ) +set(FRIBIDI_INCLUDE_DIR ${xFRIBIDI_INCLUDE_DIR}) + +SET(FRIBIDI_NAMES ${FRIBIDI_NAMES} fribidi libfribidi) +FIND_LIBRARY(FRIBIDI_LIBRARY + NAMES ${FRIBIDI_NAMES} + PATHS /usr/lib /usr/local/lib + ) + +IF (FRIBIDI_LIBRARY AND FRIBIDI_INCLUDE_DIR) + SET(CMAKE_REQUIRED_INCLUDES ${FRIBIDI_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${FRIBIDI_LIBRARY}) + CHECK_SYMBOL_EXISTS(fribidi_utf8_to_unicode fribidi.h FOUND_fribidi_utf8_to_unicode) + CHECK_SYMBOL_EXISTS(fribidi_charset_to_unicode fribidi.h FOUND_fribidi_charset_to_unicode) + CHECK_SYMBOL_EXISTS(FRIBIDI_CHAR_SET_UTF8 fribidi.h FOUND_FRIBIDI_CHAR_SET_UTF8) + + # FriBiDi provides both fribidi_utf8_to_unicode and fribidi_charset_to_unicode. + # The difference is that + # 1. fribidi >= 0.10.5 has FRIBIDI_CHAR_SET_UTF8. + # 2. fribidi <= 0.10.4 has FRIBIDI_CHARSET_UTF8. + # Wesnoth has two methods to use FriBiDi. + # 1. Use fribidi_charset_to_unicode and FRIBIDI_CHAR_SET_UTF8. + # 2. Define OLD_FRIBIDI and use fribidi_utf8_to_unicode. + # To compile Wesnoth with fribidi <= 0.10.4, we must define OLD_FRIBIDI. + + # Newer versions of fribidi (not tested the initial version which has the + # issue, but at least 0.19.2 has the issue) no longer have the symbol + # FRIBIDI_CHAR_SET_UTF8. But the symbol is build with some macros confusing + # cmake. To test for that case let the compiler give its verdict. + if(FOUND_fribidi_charset_to_unicode AND NOT FOUND_FRIBIDI_CHAR_SET_UTF8) + file(WRITE "${CMAKE_BINARY_DIR}/fribidi_test.c" + "#include \nint main(){FriBidiCharSet s = FRIBIDI_CHAR_SET_UTF8;}" + ) + try_compile(FOUND_FRIBIDI_CHAR_SET_UTF8 + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/fribidi_test.c" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FRIBIDI_INCLUDE_DIR}" + ) + + file(REMOVE "${CMAKE_BINARY_DIR}/fribidi_test.c") + + endif(FOUND_fribidi_charset_to_unicode AND NOT FOUND_FRIBIDI_CHAR_SET_UTF8) + + if(FOUND_fribidi_charset_to_unicode AND FOUND_FRIBIDI_CHAR_SET_UTF8) + # fribidi >= 0.10.5 + SET(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) + SET(FRIBIDI_FOUND "YES") + elseif(FOUND_fribidi_utf8_to_unicode) + # fribidi <= 0.10.4 + SET(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) + SET(FRIBIDI_FOUND "YES") + add_definitions(-DOLD_FRIBIDI) + MESSAGE(STATUS "Legacy FriBiDi: ${FRIBIDI_LIBRARY}") + else() + SET(FRIBIDI_LIBRARIES "NOTFOUND") + SET(FRIBIDI_INCLUDE_DIR "NOTFOUND") + SET(FRIBIDI_FOUND "NO") + endif() +ENDIF (FRIBIDI_LIBRARY AND FRIBIDI_INCLUDE_DIR) + +IF (FRIBIDI_FOUND) + + IF (NOT FRIBIDI_FIND_QUIETLY) + MESSAGE(STATUS "Using FriBiDi: ${FRIBIDI_LIBRARY}") + ENDIF (NOT FRIBIDI_FIND_QUIETLY) +ELSE (FRIBIDI_FOUND) + IF (FRIBIDI_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find FriBiDi library") + ENDIF (FRIBIDI_FIND_REQUIRED) +ENDIF (FRIBIDI_FOUND) Index: poppler-0.20.5/cmake/modules/FindICU.cmake =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ poppler-0.20.5/cmake/modules/FindICU.cmake 2012-10-21 02:25:36.000000000 +0200 @@ -0,0 +1,52 @@ +# Imperfect module to find the ICU library with cmake + +find_program(ICU_CONFIG icu-config) + +if(NOT ICU_CONFIG) + set(ICU_FOUND FALSE) +else(NOT ICU_CONFIG) + + execute_process(COMMAND ${ICU_CONFIG} --exists + RESULT_VARIABLE ICU_EXISTS_RESULT) + if(NOT ${ICU_EXISTS_RESULT} EQUAL 0) + set(ICU_FOUND FALSE) + else(NOT ${ICU_EXISTS_RESULT} EQUAL 0) + + execute_process(COMMAND ${ICU_CONFIG} --cppflags-searchpath + COMMAND sed s/^-I//g + OUTPUT_VARIABLE ICU_INCLUDE_DIRS) + + execute_process(COMMAND ${ICU_CONFIG} --ldflags-libsonly + COMMAND tr -d \n + COMMAND sed "s/[\t ]*-l/ /g" + COMMAND sed "s/^[\t ]*//" + COMMAND sed "s/[\t ]*$//" + OUTPUT_VARIABLE ICU_LIBRARY_NAMES) + + separate_arguments(ICU_LIBRARY_NAMES) + +# execute_process(COMMAND ${ICU_CONFIG} --ldflags-searchpath +# COMMAND sed s/^-L// +# OUTPUT_VARIABLE ICU_LIB_DIR) + + foreach(CURRENT_LIB_NAME ${ICU_LIBRARY_NAMES}) + set(CURRENT_LIBRARY ${CURRENT_LIB_NAME}-NOTFOUND) + find_library(CURRENT_LIBRARY ${CURRENT_LIB_NAME}) + list(APPEND ICU_LIBRARIES ${CURRENT_LIBRARY}) + endforeach(CURRENT_LIB_NAME ${ICU_LIBRARY_NAMES}) + + set(ICU_FOUND TRUE) + + endif(NOT ${ICU_EXISTS_RESULT} EQUAL 0) +endif(NOT ICU_CONFIG) + +if(ICU_FOUND) + if(NOT ICU_FIND_QUIETLY) + MESSAGE(STATUS "Found ICU") + endif(NOT ICU_FIND_QUIETLY) +else(ICU_FOUND) + if(ICU_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find ICU") + endif(ICU_FIND_REQUIRED) +endif(ICU_FOUND) + Index: poppler-0.20.5/poppler/TextOutputDev.h =================================================================== --- poppler-0.20.5.orig/poppler/TextOutputDev.h 2012-08-31 00:16:11.000000000 +0300 +++ poppler-0.20.5/poppler/TextOutputDev.h 2012-10-21 02:25:36.000000000 +0200 @@ -33,6 +33,9 @@ #endif #include "poppler-config.h" +#if HAVE_ICU +#include +#endif #include #include "goo/gtypes.h" #include "GfxFont.h" @@ -479,6 +482,21 @@ // TextPage //------------------------------------------------------------------------ +enum ReorderingMode { + ReorderingNotNeeded, +#if HAVE_ICU + // all numbers ltr + ReorderingNumbersAsL=UBIDI_REORDER_INVERSE_NUMBERS_AS_L, + // windows + ReorderingNumbersSpecial=UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL, + // unicode (default) + ReorderingLikeDirect=UBIDI_REORDER_INVERSE_LIKE_DIRECT, + ReorderingDefault=ReorderingNumbersSpecial +#else + ReorderingDefault +#endif +}; + class TextPage { public: @@ -540,7 +558,8 @@ // Get the text which is inside the specified rectangle. GooString *getText(double xMin, double yMin, - double xMax, double yMax); + double xMax, double yMax, + ReorderingMode reordering_mode=ReorderingDefault); void visitSelection(TextSelectionVisitor *visitor, PDFRectangle *selection, @@ -569,7 +588,7 @@ // Dump contents of page to a file. void dump(void *outputStream, TextOutputFunc outputFunc, - GBool physLayout); + GBool physLayout, ReorderingMode reordering_mode=ReorderingDefault); // Get the head of the linked list of TextFlows. TextFlow *getFlows() { return flows; } @@ -589,7 +608,8 @@ void clear(); void assignColumns(TextLineFrag *frags, int nFrags, GBool rot); - int dumpFragment(Unicode *text, int len, UnicodeMap *uMap, GooString *s); + int dumpFragment(Unicode *text, int len, UnicodeMap *uMap, GooString *s, + ReorderingMode reordering_mode); GBool rawOrder; // keep text in content stream order Index: poppler-0.20.5/poppler/Makefile.am =================================================================== --- poppler-0.20.5.orig/poppler/Makefile.am 2012-09-10 20:28:34.000000000 +0300 +++ poppler-0.20.5/poppler/Makefile.am 2012-10-21 02:25:36.000000000 +0200 @@ -138,10 +138,18 @@ cms_libs = $(LCMS_LIBS) endif +icu_includes = $(ICU_CFLAGS) +icu_libs = $(ICU_LIBS) + +fribidi_includes = $(FRIBIDI_CFLAGS) +fribidi_libs = $(FRIBIDI_LIBS) + INCLUDES = \ -I$(top_srcdir) \ -I$(top_srcdir)/goo \ $(cms_includes) \ + $(icu_includes) \ + $(fribidi_includes) \ $(splash_includes) \ $(cairo_includes) \ $(arthur_includes) \ @@ -165,6 +173,8 @@ $(top_builddir)/goo/libgoo.la \ $(top_builddir)/fofi/libfofi.la \ $(cms_libs) \ + $(icu_libs) \ + $(fribidi_libs) \ $(splash_libs) \ $(libtiff_libs) \ $(libjpeg_libs) \ Index: poppler-0.20.5/poppler/TextOutputDev.cc =================================================================== --- poppler-0.20.5.orig/poppler/TextOutputDev.cc 2012-10-19 17:29:33.000000000 +0200 +++ poppler-0.20.5/poppler/TextOutputDev.cc 2012-10-21 02:25:36.000000000 +0200 @@ -48,6 +48,13 @@ #include #include #include +#if HAVE_ICU +#include +#include +#endif +#if HAVE_FRIBIDI +#include +#endif #ifdef _WIN32 #include // for O_BINARY #include // for setmode @@ -3758,7 +3765,7 @@ } GooString *TextPage::getText(double xMin, double yMin, - double xMax, double yMax) { + double xMax, double yMax, ReorderingMode reordering_mode) { GooString *s; UnicodeMap *uMap; TextBlock *blk; @@ -3983,7 +3990,7 @@ } // get the fragment text - col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); + col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s, reordering_mode); } if (multiLine) { @@ -4042,7 +4049,7 @@ virtual void visitWord (TextWord *word, int begin, int end, PDFRectangle *selection) { }; - GooString *getText(void); + GooString *getText(ReorderingMode reordering_mode=ReorderingDefault); private: TextLineFrag *frags; @@ -4079,7 +4086,7 @@ } -GooString *TextSelectionDumper::getText (void) +GooString *TextSelectionDumper::getText (ReorderingMode reordering_mode) { GooString *s; TextLineFrag *frag; @@ -4160,7 +4167,7 @@ actual_line = 0; } - page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, ((GooString*) strings->get (actual_line))); + page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, ((GooString*) strings->get (actual_line)), reordering_mode); last_length = frag->len; if (!frag->line->blk->tableEnd) { @@ -4169,7 +4176,7 @@ } // not a table else { - page->dumpFragment (frag->line->text + frag->start, frag->len, uMap, s); + page->dumpFragment (frag->line->text + frag->start, frag->len, uMap, s, reordering_mode); if (i < nFrags - 1) { s->append (eol, eolLen); } @@ -4831,7 +4838,7 @@ } void TextPage::dump(void *outputStream, TextOutputFunc outputFunc, - GBool physLayout) { + GBool physLayout, ReorderingMode reordering_mode) { UnicodeMap *uMap; TextFlow *flow; TextBlock *blk; @@ -4875,7 +4882,7 @@ for (word = rawWords; word; word = word->next) { s = new GooString(); - dumpFragment(word->text, word->len, uMap, s); + dumpFragment(word->text, word->len, uMap, s, reordering_mode); (*outputFunc)(outputStream, s->getCString(), s->getLength()); delete s; if (word->next && @@ -4949,7 +4956,7 @@ // print the line s = new GooString(); - col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s); + col += dumpFragment(frag->line->text + frag->start, frag->len, uMap, s, reordering_mode); (*outputFunc)(outputStream, s->getCString(), s->getLength()); delete s; @@ -4988,7 +4995,7 @@ --n; } s = new GooString(); - dumpFragment(line->text, n, uMap, s); + dumpFragment(line->text, n, uMap, s, reordering_mode); (*outputFunc)(outputStream, s->getCString(), s->getLength()); delete s; // output a newline when a hyphen is not suppressed @@ -5106,19 +5113,108 @@ } int TextPage::dumpFragment(Unicode *text, int len, UnicodeMap *uMap, - GooString *s) { + GooString *s, ReorderingMode reordering_mode) { char lre[8], rle[8], popdf[8], buf[8]; int lreLen, rleLen, popdfLen, n; int nCols, i, j, k; +#if HAVE_ICU + UBiDi *bidi = NULL; + UErrorCode err = U_ZERO_ERROR; + UBiDiLevel level = UBIDI_DEFAULT_LTR; + UChar *output = NULL, *input = NULL; + int32_t ulen; + UConverter *conv32 = NULL; +#elif HAVE_FRIBIDI + FriBidiCharType base_dir = FRIBIDI_TYPE_ON; + FriBidiChar *visual_str = NULL; +#endif nCols = 0; - if (uMap->isUnicode()) { + if (reordering_mode != ReorderingNotNeeded && uMap->isUnicode()) { lreLen = uMap->mapUnicode(0x202a, lre, sizeof(lre)); rleLen = uMap->mapUnicode(0x202b, rle, sizeof(rle)); popdfLen = uMap->mapUnicode(0x202c, popdf, sizeof(popdf)); +#if HAVE_ICU + conv32 = ucnv_open("UTF-32_PlatformEndian", &err); + ulen = ucnv_toUChars( + conv32, NULL, 0, (const char *) text, len * sizeof(Unicode), &err); + input = new UChar[ulen]; + output = new UChar[ulen]; + bidi = ubidi_open(); + + if (input && output && bidi && conv32) { + if (primaryLR) { + level = UBIDI_DEFAULT_LTR; + s->append(lre, lreLen); + } + else { + level = UBIDI_DEFAULT_RTL; + s->append(rle, rleLen); + } + err = U_ZERO_ERROR; + ulen = ucnv_toUChars( + conv32, input, ulen, (const char *) text, len * sizeof(Unicode), &err); + ubidi_setReorderingMode( bidi, (UBiDiReorderingMode) reordering_mode ); + ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS); + ubidi_setPara( bidi, input, len, level, NULL, &err ); + ubidi_writeReordered( bidi, output, len, UBIDI_DO_MIRRORING, &err ); + ucnv_fromUChars(conv32, (char *) text, len * sizeof(Unicode), + output, ulen, &err); + UCharCharacterIterator iter(output, ulen); + for (iter.first(); iter.current() != CharacterIterator::DONE; iter.next()) { + n = uMap->mapUnicode(iter.current(), buf, sizeof(buf)); + s->append(buf, n); + ++nCols; + } + s->append(popdf, popdfLen); + if (input != NULL) + delete input; + if (output != NULL) + delete output; + ubidi_close(bidi); + ucnv_close(conv32); + } + else { +#elif HAVE_FRIBIDI + visual_str = new FriBidiChar[len]; + + if (visual_str) { + if (primaryLR) { + base_dir = FRIBIDI_TYPE_LTR; + s->append(lre, lreLen); + } + else { + base_dir = FRIBIDI_TYPE_RTL; + s->append(rle, rleLen); + } + fribidi_log2vis ( + /* input */ + (FriBidiChar *) text, + (FriBidiStrIndex) len, + /* input and output */ + &base_dir, + /* output */ + visual_str, + NULL, + NULL, + NULL + ); + for (i = 0; i < len; ++i) { + n = uMap->mapUnicode(Unicode(visual_str[i]), buf, sizeof(buf)); + if (!FRIBIDI_IS_EXPLICIT(Unicode(visual_str[i]))) + ++nCols; + s->append(buf, n); + } + s->append(popdf, popdfLen); + if (visual_str != NULL) + delete visual_str; + } + else { +#endif + if (primaryLR) { i = 0; @@ -5182,7 +5278,9 @@ s->append(popdf, popdfLen); } - +#if (HAVE_ICU || HAVE_FRIBIDI) + } +#endif } else { for (i = 0; i < len; ++i) { n = uMap->mapUnicode(text[i], buf, sizeof(buf)); @@ -5190,7 +5288,6 @@ nCols += n; } } - return nCols; }