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); }
/** * Generate components for the paragraph. fChars, fBidi should have been * initialized already. */ private void generateComponents(int startingAt, int endingAt) { if (collectStats) { formattedChars += (endingAt-startingAt); } int layoutFlags = 0; // no extra info yet, bidi determines run and line direction TextLabelFactory factory = new TextLabelFactory(fFrc, fChars, fBidi, layoutFlags); int[] charsLtoV = null; if (fBidi != null) { fLevels = BidiUtils.getLevels(fBidi); int[] charsVtoL = BidiUtils.createVisualToLogicalMap(fLevels); charsLtoV = BidiUtils.createInverseMap(charsVtoL); fIsDirectionLTR = fBidi.baseIsLeftToRight(); } else { fLevels = null; fIsDirectionLTR = true; } try { fComponents = TextLine.getComponents( fParagraph, fChars, startingAt, endingAt, charsLtoV, fLevels, factory); } catch(IllegalArgumentException e) { System.out.println("startingAt="+startingAt+"; endingAt="+endingAt); System.out.println("fComponentLimit="+fComponentLimit); throw e; } fComponentStart = startingAt; fComponentLimit = endingAt; //debugFormatCount += (endingAt-startingAt); }
public int visualToLogical(int visualIndex) { if (fCharLogicalOrder == null) { return visualIndex; } if (fCharVisualOrder == null) { fCharVisualOrder = BidiUtils.createInverseMap(fCharLogicalOrder); } return fCharVisualOrder[visualIndex]; }
/** * Compute the components order from the given components array and * logical-to-visual character mapping. May return null if canonical. */ private static int[] computeComponentOrder(TextLineComponent[] components, int[] charsLtoV) { /* * Create a visual ordering for the glyph sets. The important thing * here is that the values have the proper rank with respect to * each other, not the exact values. For example, the first glyph * set that appears visually should have the lowest value. The last * should have the highest value. The values are then normalized * to map 1-1 with positions in glyphs. * */ int[] componentOrder = null; if (charsLtoV != null && components.length > 1) { componentOrder = new int[components.length]; int gStart = 0; for (int i = 0; i < components.length; i++) { componentOrder[i] = charsLtoV[gStart]; gStart += components[i].getNumCharacters(); } componentOrder = BidiUtils.createContiguousOrder(componentOrder); componentOrder = BidiUtils.createInverseMap(componentOrder); } return componentOrder; }
/** * Creates a row of views that will fit within the * layout span of the row. This is implemented to execute the * superclass functionality (which fills the row with child * views or view fragments) and follow that with bidi reordering * of the unidirectional view fragments. * * @param row the row to fill in with views. This is assumed * to be empty on entry. * @param pos The current position in the children of * this views element from which to start. * @return the position to start the next row */ protected int layoutRow(FlowView fv, int rowIndex, int p0) { int p1 = super.layoutRow(fv, rowIndex, p0); View row = fv.getView(rowIndex); Document doc = fv.getDocument(); Object i18nFlag = doc.getProperty(AbstractDocument.I18NProperty); if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) { int n = row.getViewCount(); if (n > 1) { AbstractDocument d = (AbstractDocument)fv.getDocument(); Element bidiRoot = d.getBidiRootElement(); byte[] levels = new byte[n]; View[] reorder = new View[n]; for( int i=0; i<n; i++ ) { View v = row.getView(i); int bidiIndex =bidiRoot.getElementIndex(v.getStartOffset()); Element bidiElem = bidiRoot.getElement( bidiIndex ); levels[i] = (byte)StyleConstants.getBidiLevel(bidiElem.getAttributes()); reorder[i] = v; } BidiUtils.reorderVisually( levels, reorder ); row.replace(0, n, reorder); } } return p1; }