17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*   Copyright (C) 2001-2013, International Business Machines
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*   Corporation and others.  All Rights Reserved.
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.bidi;
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Utility;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.Bidi;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Regression test for the basic "inverse" Bidi mode.
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ported from C by Lina Kemmel, Matitiahu Allouche
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class TestInverse extends BidiTest {
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int countRoundtrips = 0;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int countNonRoundtrips = 0;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final String[] testCases = {
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "\u006c\u0061\u0028\u0074\u0069\u006e\u0020\u05d0\u05d1\u0029\u05d2\u05d3",
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "\u006c\u0061\u0074\u0020\u05d0\u05d1\u05d2\u0020\u0031\u0032\u0033",
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "\u006c\u0061\u0074\u0020\u05d0\u0028\u05d1\u05d2\u0020\u0031\u0029\u0032\u0033",
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "\u0031\u0032\u0033\u0020\u05d0\u05d1\u05d2\u0020\u0034\u0035\u0036",
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "\u0061\u0062\u0020\u0061\u0062\u0020\u0661\u0662"
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void testInverse() {
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Bidi bidi;
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("\nEntering TestInverse\n");
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi = new Bidi();
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        log("inverse Bidi: testInverse(L) with " + testCases.length +
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            " test cases ---\n");
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for(i = 0; i < testCases.length; ++i) {
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("Testing case " + i);
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _testInverseBidi(bidi, testCases[i], Bidi.DIRECTION_LEFT_TO_RIGHT);
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        log("inverse Bidi: testInverse(R) with " + testCases.length +
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            " test cases ---\n");
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < testCases.length; ++i) {
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("Testing case " + i);
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _testInverseBidi(bidi, testCases[i], Bidi.DIRECTION_RIGHT_TO_LEFT);
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _testManyInverseBidi(bidi, Bidi.DIRECTION_LEFT_TO_RIGHT);
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _testManyInverseBidi(bidi, Bidi.DIRECTION_RIGHT_TO_LEFT);
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("inverse Bidi: rountrips: " + countRoundtrips +
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert              "   non-roundtrips: " + countNonRoundtrips);
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _testWriteReverse();
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _testManyAddedPoints();
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _testMisc();
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        logln("\nExiting TestInverse\n");
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char[][] repeatSegments = {
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x61, 0x62 },     /* L */
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x5d0, 0x5d1 },   /* R */
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x627, 0x628 },   /* AL */
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x31, 0x32 },     /* EN */
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x661, 0x662 },   /* AN */
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        { 0x20, 0x20 }      /* WS (N) */
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int COUNT_REPEAT_SEGMENTS = 6;
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _testManyInverseBidi(Bidi bidi, int direction) {
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char[] text = { 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i, j, k;
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        log("inverse Bidi: testManyInverseBiDi(" +
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            (direction == Bidi.DIRECTION_LEFT_TO_RIGHT ? 'L' : 'R') +
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ") - test permutations of text snippets ---\n");
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < COUNT_REPEAT_SEGMENTS; ++i) {
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            text[0] = repeatSegments[i][0];
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            text[1] = repeatSegments[i][1];
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (j = 0; j < COUNT_REPEAT_SEGMENTS; ++j) {
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                text[3] = repeatSegments[j][0];
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                text[4] = repeatSegments[j][1];
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (k = 0; k < COUNT_REPEAT_SEGMENTS; ++k) {
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    text[6] = repeatSegments[k][0];
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    text[7] = repeatSegments[k][1];
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    log("inverse Bidi: testManyInverseBiDi()[" +
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i + " " + j + " " + k + "]\n");
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    _testInverseBidi(bidi, new String(text), direction);
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _testInverseBidi(Bidi bidi, String src, int direction) {
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String visualLTR, logicalDest, visualDest;
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (direction == Bidi.DIRECTION_LEFT_TO_RIGHT) {
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("inverse Bidi: testInverse(L)\n");
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* convert visual to logical */
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setInverse(true);
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!bidi.isInverse()) {
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err("Error while doing setInverse(true)\n");
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setPara(src, Bidi.LTR, null);
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!Arrays.equals(src.toCharArray(), bidi.getText())) {
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err("Wrong value returned by getText\n");
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!src.equals(bidi.getTextAsString())) {
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err("Wrong value returned by getTextAsString\n");
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logicalDest = bidi.writeReordered(Bidi.DO_MIRRORING |
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                  Bidi.INSERT_LRM_FOR_NUMERIC);
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("  v ");
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                printUnicode(src.toCharArray(), bidi.getLevels());
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("\n");
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* convert back to visual LTR */
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setInverse(false);
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (bidi.isInverse()) {
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err("Error while doing setInverse(false)\n");
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setPara(logicalDest, Bidi.LTR, null);
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                visualDest = bidi.writeReordered(Bidi.DO_MIRRORING |
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                 Bidi.REMOVE_BIDI_CONTROLS);
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("inverse Bidi: testInverse(R)\n");
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* reverse visual from RTL to LTR */
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                visualLTR = Bidi.writeReverse(src, 0);
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("  vr");
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                printUnicode(src.toCharArray(), null);
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("\n");
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* convert visual RTL to logical */
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setInverse(true);
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setPara(visualLTR, Bidi.LTR, null);
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logicalDest = bidi.writeReordered(Bidi.DO_MIRRORING |
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                  Bidi.INSERT_LRM_FOR_NUMERIC);
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("  vl");
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                printUnicode(visualLTR.toCharArray(), bidi.getLevels());
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("\n");
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* convert back to visual RTL */
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setInverse(false);
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                bidi.setPara(logicalDest, Bidi.LTR, null);
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                visualDest = bidi.writeReordered(Bidi.DO_MIRRORING |
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             Bidi.REMOVE_BIDI_CONTROLS | Bidi.OUTPUT_REVERSE);
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("  l ");
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            printUnicode(logicalDest.toCharArray(), bidi.getLevels());
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("\n");
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("  v ");
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            printUnicode(visualDest.toCharArray(), null);
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("\n");
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception e) {
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("\ninverse Bidi: *** failed");
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("   error message: " + e.getMessage());
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            e.printStackTrace();
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            visualDest = null;
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* check and print results */
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (src.equals(visualDest)) {
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ++countRoundtrips;
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log(" + roundtripped\n");
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ++countNonRoundtrips;
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log(" * did not roundtrip\n");
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _testWriteReverse() {
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* U+064e and U+0650 are combining marks (Mn) */
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        final String
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            forward = "\u200f\u0627\u064e\u0650\u0020\u0028\u0031\u0029",
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            reverseKeepCombining =
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                "\u0029\u0031\u0028\u0020\u0627\u064e\u0650\u200f",
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            reverseRemoveControlsKeepCombiningDoMirror =
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                "\u0028\u0031\u0029\u0020\u0627\u064e\u0650";
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String reverse;
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* test Bidi.writeReverse() with "interesting" options */
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            reverse = Bidi.writeReverse(forward, Bidi.KEEP_BASE_COMBINING);
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception e) {
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Failure in Bidi.writeReverse(KEEP_BASE_COMBINING)");
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            reverse = null;
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        assertEquals("\nFailure in " + getClass().toString() +
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     " in Bidi.writeReverse", reverseKeepCombining,
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     reverse, forward, null, "KEEP_BASE_COMBINING", null);
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            reverse = Bidi.writeReverse(forward, Bidi.REMOVE_BIDI_CONTROLS |
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        Bidi.DO_MIRRORING | Bidi.KEEP_BASE_COMBINING);
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception e) {
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Failure in Bidi.writeReverse(KEEP_BASE_COMBINING)");
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        assertEquals("\nFailure in " + getClass().toString() +
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     " in Bidi.writeReverse",
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     reverseRemoveControlsKeepCombiningDoMirror,
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     reverse, forward, null,
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     "REMOVE_BIDI_CONTROLS|DO_MIRRORING|KEEP_BASE_COMBINING",
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     null);
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void printUnicode(char[] chars, byte[] levels) {
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        log("{ ");
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < chars.length; ++i) {
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("0x" + Utility.hex(chars[i]));
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (levels != null) {
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                log("." + levels[i]);
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            log("   ");
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        log(" }");
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _testManyAddedPoints() {
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Bidi bidi = new Bidi();
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char[] text = new char[90];
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < text.length; i+=3) {
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            text[i] = 'a';
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            text[i+1] = '\u05d0';
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            text[i+2] = '3';
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT);
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi.setReorderingOptions(Bidi.OPTION_INSERT_MARKS);
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi.setPara(text, Bidi.LTR, null);
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String out = bidi.writeReordered(0);
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char[] expected = new char[120];
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < expected.length; i+=4) {
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expected[i] = 'a';
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expected[i+1] = '\u05d0';
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expected[i+2] = '\u200e';
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expected[i+3] = '3';
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        assertEquals("\nInvalid output with many added points",
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     new String(expected), out);
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _testMisc() {
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Bidi bidi = new Bidi();
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi.setInverse(true);
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        bidi.setPara("   ", Bidi.RTL, null);
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String out = bidi.writeReordered(Bidi.OUTPUT_REVERSE | Bidi.INSERT_LRM_FOR_NUMERIC);
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        assertEquals("\nInvalid output with RLM at both sides",
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     "\u200f   \u200f", out);
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static void main(String[] args) {
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestInverse().run(args);
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        catch (Exception e) {
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            System.out.println(e);
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
276