Iterable<VisualFragment> getFragmentsInVisualOrder( final float startX, final int startVisualColumn, final int startOffset, int endOffset) { assert startOffset <= endOffset; final BidiRun[] runs; int startLogicalColumn = 0; if (startOffset == endOffset) { runs = new BidiRun[0]; } else { List<BidiRun> runList = new ArrayList<BidiRun>(); for (BidiRun run : myBidiRunsInLogicalOrder) { if (run.startOffset < startOffset) { startLogicalColumn = run.getLogicalColumn(startLogicalColumn, Math.min(startOffset, run.endOffset)); } if (run.endOffset <= startOffset) continue; if (run.startOffset >= endOffset) break; runList.add(run.subRun(startOffset, endOffset)); } runs = runList.toArray(new BidiRun[runList.size()]); reorderRunsVisually(runs); } final int finalStartLogicalColumn = startLogicalColumn; return new Iterable<VisualFragment>() { @Override public Iterator<VisualFragment> iterator() { return new VisualOrderIterator( startX, startVisualColumn, finalStartLogicalColumn, startOffset, runs); } }; }
boolean isRtlLocation(int offset, boolean leanForward) { if (offset == 0 && !leanForward) return false; for (BidiRun run : myBidiRunsInLogicalOrder) { if (offset < run.endOffset || offset == run.endOffset && !leanForward) return run.isRtl(); } return false; }
private static void addFragments( BidiRun run, char[] text, int start, int end, int fontStyle, FontPreferences fontPreferences, FontRenderContext fontRenderContext, @Nullable TabFragment tabFragment) { Font currentFont = null; int currentIndex = start; for (int i = start; i < end; i++) { char c = text[i]; if (c == '\t' && tabFragment != null) { assert run.level == 0; addTextFragmentIfNeeded( run, text, currentIndex, i, currentFont, fontRenderContext, run.isRtl()); run.fragments.add(tabFragment); currentFont = null; currentIndex = i + 1; } else { Font font = ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontStyle, fontPreferences) .getFont(); if (!font.equals(currentFont)) { addTextFragmentIfNeeded( run, text, currentIndex, i, currentFont, fontRenderContext, run.isRtl()); currentFont = font; currentIndex = i; } } } addTextFragmentIfNeeded( run, text, currentIndex, end, currentFont, fontRenderContext, run.isRtl()); }
@Override public VisualFragment next() { if (!hasNext()) { throw new NoSuchElementException(); } BidiRun run = myRuns[myRunIndex]; if (myRunIndex == 0 && myFragmentIndex == 0) { myFragment.startLogicalColumn += (run.isRtl() ? run.endOffset : run.startOffset) - myFragment.startOffset; } else { myFragment.startLogicalColumn = myFragment.getEndLogicalColumn(); if (myFragmentIndex == 0) { myFragment.startLogicalColumn += (run.isRtl() ? run.endOffset : run.startOffset) - myFragment.getEndOffset(); } myFragment.startVisualColumn = myFragment.getEndVisualColumn(); myFragment.startX = myFragment.getEndX(); } myFragment.isRtl = run.isRtl(); myFragment.delegate = run.fragments.get( run.isRtl() ? run.fragments.size() - 1 - myFragmentIndex : myFragmentIndex); myFragment.startOffset = run.isRtl() ? run.endOffset - myOffsetInsideRun : run.startOffset + myOffsetInsideRun; myOffsetInsideRun += myFragment.getLength(); myFragmentIndex++; if (myFragmentIndex >= run.fragments.size()) { myFragmentIndex = 0; myOffsetInsideRun = 0; myRunIndex++; } return myFragment; }