private TextLine makeTextLineOnRange(int startPos, int limitPos) { int[] charsLtoV = null; byte[] charLevels = null; if (fBidi != null) { Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos); charLevels = BidiUtils.getLevels(lineBidi); int[] charsVtoL = BidiUtils.createVisualToLogicalMap(charLevels); charsLtoV = BidiUtils.createInverseMap(charsVtoL); } TextLineComponent[] components = makeComponentsOnRange(startPos, limitPos); return new TextLine(fFrc, components, fBaselineOffsets, fChars, startPos, limitPos, charsLtoV, charLevels, fIsDirectionLTR); }
/** * Create a TextLine from the Font and character data over the * range. The range is relative to both the StyledParagraph and the * character array. */ public static TextLine createLineFromText(char[] chars, StyledParagraph styledParagraph, TextLabelFactory factory, boolean isDirectionLTR, float[] baselineOffsets) { factory.setLineContext(0, chars.length); Bidi lineBidi = factory.getLineBidi(); int[] charsLtoV = null; byte[] levels = null; if (lineBidi != null) { levels = BidiUtils.getLevels(lineBidi); int[] charsVtoL = BidiUtils.createVisualToLogicalMap(levels); charsLtoV = BidiUtils.createInverseMap(charsVtoL); } TextLineComponent[] components = getComponents(styledParagraph, chars, 0, chars.length, charsLtoV, levels, factory); return new TextLine(factory.getFontRenderContext(), components, baselineOffsets, chars, 0, chars.length, charsLtoV, levels, isDirectionLTR); }
/** * Create a TextLine from the text. chars is just the text in the iterator. */ public static TextLine standardCreateTextLine(FontRenderContext frc, AttributedCharacterIterator text, char[] chars, float[] baselineOffsets) { StyledParagraph styledParagraph = new StyledParagraph(text, chars); Bidi bidi = new Bidi(text); if (bidi.isLeftToRight()) { bidi = null; } int layoutFlags = 0; // no extra info yet, bidi determines run and line direction TextLabelFactory factory = new TextLabelFactory(frc, chars, bidi, layoutFlags); boolean isDirectionLTR = true; if (bidi != null) { isDirectionLTR = bidi.baseIsLeftToRight(); } return createLineFromText(chars, styledParagraph, factory, isDirectionLTR, baselineOffsets); }
/** * Return the level of each character into the levels array starting at start. * This is a convenience method for clients who prefer to use an explicit levels * array instead of iterating over the runs. * * @param levels the array to receive the character levels * @param start the starting offset into the the array * @throws IndexOutOfBoundsException if <code>start</code> is less than 0 or * <code>start + getLength()</code> is greater than <code>levels.length</code>. */ public static void getLevels(Bidi bidi, byte[] levels, int start) { int limit = start + bidi.getLength(); if (start < 0 || limit > levels.length) { throw new IndexOutOfBoundsException("levels.length = " + levels.length + " start: " + start + " limit: " + limit); } int runCount = bidi.getRunCount(); int p = start; for (int i = 0; i < runCount; ++i) { int rlimit = start + bidi.getRunLimit(i); byte rlevel = (byte)bidi.getRunLevel(i); while (p < rlimit) { levels[p++] = rlevel; } } }
/** * Return the level of each character into the levels array starting at start. * This is a convenience method for clients who prefer to use an explicit levels * array instead of iterating over the runs. * * @param levels the array to receive the character levels * @param start the starting offset into the array * @throws IndexOutOfBoundsException if {@code start} is less than 0 or * {@code start + getLength()} is greater than {@code levels.length}. */ public static void getLevels(Bidi bidi, byte[] levels, int start) { int limit = start + bidi.getLength(); if (start < 0 || limit > levels.length) { throw new IndexOutOfBoundsException("levels.length = " + levels.length + " start: " + start + " limit: " + limit); } int runCount = bidi.getRunCount(); int p = start; for (int i = 0; i < runCount; ++i) { int rlimit = start + bidi.getRunLimit(i); byte rlevel = (byte)bidi.getRunLevel(i); while (p < rlimit) { levels[p++] = rlevel; } } }
/** * This method determines if the direction of a substring is right-to-left. * If the string is empty that determination is based on the default system language * Locale.getDefault(). * The method can handle invalid substring definitions (start > end etc.), in which case the * method returns False. * * @return True if the text direction is right-to-left, false otherwise. */ public static boolean isRTL(CharSequence s, int start, int end) { if (s == null || s.length() == 0) { // empty string --> determine the direction from the default language return isRTL(Locale.getDefault()); } if (start == end) { // if no character is selected we need to expand the selection start = Math.max(0, --start); if (start == end) { end = Math.min(s.length(), ++end); } } try { Bidi bidi = new Bidi(s.subSequence(start, end).toString(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); return ! bidi.baseIsLeftToRight(); } catch (IndexOutOfBoundsException e) { return false; } }