--- poppler-0.20.5.orig/poppler/TextOutputDev.h +++ poppler-0.20.5/poppler/TextOutputDev.h @@ -491,10 +491,11 @@ enum ReorderingMode { ReorderingNumbersSpecial=UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL, // unicode (default) ReorderingLikeDirect=UBIDI_REORDER_INVERSE_LIKE_DIRECT, - ReorderingDefault=ReorderingNumbersSpecial + ReorderingDefault=ReorderingNumbersSpecial, #else - ReorderingDefault + ReorderingDefault, #endif + ReorderingSentinel }; class TextPage { @@ -554,7 +555,8 @@ public: GBool caseSensitive, GBool backward, GBool wholeWord, double *xMin, double *yMin, - double *xMax, double *yMax); + double *xMax, double *yMax, + ReorderingMode reordering_mode=ReorderingDefault); // Get the text which is inside the specified rectangle. GooString *getText(double xMin, double yMin, --- poppler-0.20.5.orig/poppler/TextOutputDev.cc +++ poppler-0.20.5/poppler/TextOutputDev.cc @@ -3552,7 +3552,8 @@ GBool TextPage::findText(Unicode *s, int GBool caseSensitive, GBool backward, GBool wholeWord, double *xMin, double *yMin, - double *xMax, double *yMax) { + double *xMax, double *yMax, + ReorderingMode reordering_mode) { TextBlock *blk; TextLine *line; Unicode *s2, *txt; @@ -3563,7 +3564,88 @@ GBool TextPage::findText(Unicode *s, int double xMin1, yMin1, xMax1, yMax1; GBool found; - //~ needs to handle right-to-left text +#if HAVE_ICU + static struct { + ReorderingMode inverse_mode; + UBiDiReorderingMode direct_mode; + } reordering_inverse_to_direct[] = + { + // all numbers ltr + {ReorderingNumbersAsL, UBIDI_REORDER_GROUP_NUMBERS_WITH_R}, + // windows + {ReorderingNumbersSpecial, UBIDI_REORDER_NUMBERS_SPECIAL}, + // unicode (default) + {ReorderingLikeDirect, UBIDI_REORDER_DEFAULT}, + {ReorderingSentinel, UBIDI_REORDER_NUMBERS_SPECIAL} + }; + UBiDi *bidi = NULL; + UErrorCode err; + UChar *output = NULL, *input = NULL; + int32_t ulen; + UConverter *conv32 = NULL; + UBiDiReorderingMode ubidi_reordering_mode; +#elif HAVE_FRIBIDI + FriBidiCharType base_dir = FRIBIDI_TYPE_ON; + FriBidiChar *visual_str = NULL; +#endif + +#if HAVE_ICU + err = U_ZERO_ERROR; + conv32 = ucnv_open("UTF-32_PlatformEndian", &err); + ulen = ucnv_toUChars( + conv32, NULL, 0, (const char *) s, len * sizeof(Unicode), &err); + input = new UChar[ulen]; + output = new UChar[ulen]; + bidi = ubidi_open(); + + if (input && output && bidi && conv32) { + for (i = 0, ubidi_reordering_mode = UBIDI_REORDER_NUMBERS_SPECIAL; + reordering_inverse_to_direct[i].inverse_mode != ReorderingSentinel; + ++i) { + if (reordering_mode == reordering_inverse_to_direct[i].inverse_mode) { + ubidi_reordering_mode = reordering_inverse_to_direct[i].direct_mode; + break; + } + } + UBiDiLevel level = (primaryLR) ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL; + err = U_ZERO_ERROR; + ulen = ucnv_toUChars( + conv32, input, ulen, (const char *) s, len * sizeof(Unicode), &err); + ubidi_setReorderingMode( bidi, ubidi_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 *) s, len * sizeof(Unicode), output, ulen, &err); + } + if (input != NULL) + delete input; + if (output != NULL) + delete output; + ubidi_close(bidi); + ucnv_close(conv32); +#elif HAVE_FRIBIDI + visual_str = new FriBidiChar[len]; + + if (visual_str) { + base_dir = (primaryLR) ? FRIBIDI_TYPE_LTR : FRIBIDI_TYPE_RTL; + fribidi_log2vis ( + /* input */ + (FriBidiChar *) s, + (FriBidiStrIndex) len, + /* input and output */ + &base_dir, + /* output */ + visual_str, + NULL, + NULL, + NULL + ); + for (i = 0; i < len; ++i) + s[i] = visual_str[i]; + delete visual_str; + } +#endif if (rawOrder) { return gFalse;