📄 textmeasurer.java
字号:
int gaLimit = tlcStart + fComponents[tlcIndex].getNumCharacters(); if (gaLimit > startPos) { break; } else { tlcStart = gaLimit; } } // tlcStart is now the start of the tlc at tlcIndex int componentCount; { boolean split = false; int compStart = tlcStart; int lim=tlcIndex; for (boolean cont=true; cont; lim++) { int gaLimit = compStart + fComponents[lim].getNumCharacters(); if (cdWsStart > Math.max(compStart, startPos) && cdWsStart < Math.min(gaLimit, limitPos)) { split = true; } if (gaLimit >= limitPos) { cont=false; } else { compStart = gaLimit; } } componentCount = lim-tlcIndex; if (split) { componentCount++; } } TextLineComponent[] components = new TextLineComponent[componentCount]; int newCompIndex = 0; int linePos = startPos; int breakPt = cdWsStart; int subsetFlag; if (breakPt == startPos) { subsetFlag = fIsDirectionLTR? TextLineComponent.LEFT_TO_RIGHT : TextLineComponent.RIGHT_TO_LEFT; breakPt = limitPos; } else { subsetFlag = TextLineComponent.UNCHANGED; } while (linePos < limitPos) { int compLength = fComponents[tlcIndex].getNumCharacters(); int tlcLimit = tlcStart + compLength; int start = Math.max(linePos, tlcStart); int limit = Math.min(breakPt, tlcLimit); components[newCompIndex++] = fComponents[tlcIndex].getSubset( start-tlcStart, limit-tlcStart, subsetFlag); linePos += (limit-start); if (linePos == breakPt) { breakPt = limitPos; subsetFlag = fIsDirectionLTR? TextLineComponent.LEFT_TO_RIGHT : TextLineComponent.RIGHT_TO_LEFT; } if (linePos == tlcLimit) { tlcIndex++; tlcStart = tlcLimit; } } return components; } 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(components, fBaselineOffsets, fChars, startPos, limitPos, charsLtoV, charLevels, fIsDirectionLTR); } private void ensureComponents(int start, int limit) { if (start < fComponentStart || limit > fComponentLimit) { generateComponents(start, limit); } } private void makeLayoutWindow(int localStart) { int compStart = localStart; int compLimit = fChars.length; // If we've already gone past the layout window, format to end of paragraph if (layoutCount > 0 && !haveLayoutWindow) { float avgLineLength = Math.max(layoutCharCount / layoutCount, 1); compLimit = Math.min(localStart + (int)(avgLineLength*EST_LINES), fChars.length); } if (localStart > 0 || compLimit < fChars.length) { if (charIter == null) { charIter = new CharArrayIterator(fChars); } else { charIter.reset(fChars); } if (fLineBreak == null) { fLineBreak = BreakIterator.getLineInstance(); } fLineBreak.setText(charIter); if (localStart > 0) { if (!fLineBreak.isBoundary(localStart)) { compStart = fLineBreak.preceding(localStart); } } if (compLimit < fChars.length) { if (!fLineBreak.isBoundary(compLimit)) { compLimit = fLineBreak.following(compLimit); } } } ensureComponents(compStart, compLimit); haveLayoutWindow = true; } /** * Returns the index of the first character which will not fit on * on a line beginning at <code>start</code> and possible * measuring up to <code>maxAdvance</code> in graphical width. * * @param start the character index at which to start measuring. * <code>start</code> is an absolute index, not relative to the * start of the paragraph * @param maxAdvance the graphical width in which the line must fit * @return the index after the last character that will fit * on a line beginning at <code>start</code>, which is not longer * than <code>maxAdvance</code> in graphical width * @throws IllegalArgumentException if <code>start</code> is * less than the beginning of the paragraph. */ public int getLineBreakIndex(int start, float maxAdvance) { int localStart = start - fStart; if (!haveLayoutWindow || localStart < fComponentStart || localStart >= fComponentLimit) { makeLayoutWindow(localStart); } return calcLineBreak(localStart, maxAdvance) + fStart; } /** * Returns the graphical width of a line beginning at <code>start</code> * and including characters up to <code>limit</code>. * <code>start</code> and <code>limit</code> are absolute indices, * not relative to the start of the paragraph. * * @param start the character index at which to start measuring * @param limit the character index at which to stop measuring * @return the graphical width of a line beginning at <code>start</code> * and including characters up to <code>limit</code> * @throws IndexOutOfBoundsException if <code>limit</code> is less * than <code>start</code> * @throws IllegalArgumentException if <code>start</code> or * <code>limit</code> is not between the beginning of * the paragraph and the end of the paragraph. */ public float getAdvanceBetween(int start, int limit) { int localStart = start - fStart; int localLimit = limit - fStart; ensureComponents(localStart, localLimit); TextLine line = makeTextLineOnRange(localStart, localLimit); return line.getMetrics().advance; // could cache line in case getLayout is called with same start, limit } /** * Returns a <code>TextLayout</code> on the given character range. * * @param start the index of the first character * @param limit the index after the last character. Must be greater * than <code>start</code> * @return a <code>TextLayout</code> for the characters beginning at * <code>start</code> up to (but not including) <code>limit</code> * @throws IndexOutOfBoundsException if <code>limit</code> is less * than <code>start</code> * @throws IllegalArgumentException if <code>start</code> or * <code>limit</code> is not between the beginning of * the paragraph and the end of the paragraph. */ public TextLayout getLayout(int start, int limit) { int localStart = start - fStart; int localLimit = limit - fStart; ensureComponents(localStart, localLimit); TextLine textLine = makeTextLineOnRange(localStart, localLimit); if (localLimit < fChars.length) { layoutCharCount += limit-start; layoutCount++; } return new TextLayout(textLine, fBaseline, fBaselineOffsets, fJustifyRatio); } private int formattedChars = 0; private static boolean wantStats = false;/*"true".equals(System.getProperty("collectStats"));*/ private boolean collectStats = false; private void printStats() { System.out.println("formattedChars: " + formattedChars); //formattedChars = 0; collectStats = false; } /** * Updates the <code>TextMeasurer</code> after a single character has * been inserted * into the paragraph currently represented by this * <code>TextMeasurer</code>. After this call, this * <code>TextMeasurer</code> is equivalent to a new * <code>TextMeasurer</code> created from the text; however, it will * usually be more efficient to update an existing * <code>TextMeasurer</code> than to create a new one from scratch. * * @param newParagraph the text of the paragraph after performing * the insertion. Cannot be null. * @param insertPos the position in the text where the character was * inserted. Must not be less than the start of * <code>newParagraph</code>, and must be less than the end of * <code>newParagraph</code>. * @throws IndexOutOfBoundsException if <code>insertPos</code> is less * than the start of <code>newParagraph</code> or greater than * or equal to the end of <code>newParagraph</code> * @throws NullPointerException if <code>newParagraph</code> is * <code>null</code> */ public void insertChar(AttributedCharacterIterator newParagraph, int insertPos) { if (collectStats) { printStats(); } if (wantStats) { collectStats = true; } fStart = newParagraph.getBeginIndex(); int end = newParagraph.getEndIndex(); if (end - fStart != fChars.length+1) { initAll(newParagraph); } char[] newChars = new char[end-fStart]; int newCharIndex = insertPos - fStart; System.arraycopy(fChars, 0, newChars, 0, newCharIndex); char newChar = newParagraph.setIndex(insertPos); newChars[newCharIndex] = newChar; System.arraycopy(fChars, newCharIndex, newChars, newCharIndex+1, end-insertPos-1); fChars = newChars; if (fBidi != null || Bidi.requiresBidi(newChars, newCharIndex, newCharIndex + 1) || newParagraph.getAttribute(TextAttribute.BIDI_EMBEDDING) != null) { fBidi = new Bidi(newParagraph); if (fBidi.isLeftToRight()) { fBidi = null; } } fParagraph = StyledParagraph.insertChar(newParagraph, fChars, insertPos, fParagraph); invalidateComponents(); } /** * Updates the <code>TextMeasurer</code> after a single character has * been deleted * from the paragraph currently represented by this * <code>TextMeasurer</code>. After this call, this * <code>TextMeasurer</code> is equivalent to a new <code>TextMeasurer</code> * created from the text; however, it will usually be more efficient * to update an existing <code>TextMeasurer</code> than to create a new one * from scratch. * * @param newParagraph the text of the paragraph after performing * the deletion. Cannot be null. * @param deletePos the position in the text where the character was removed. * Must not be less than * the start of <code>newParagraph</code>, and must not be greater than the * end of <code>newParagraph</code>. * @throws IndexOutOfBoundsException if <code>deletePos</code> is * less than the start of <code>newParagraph</code> or greater * than the end of <code>newParagraph</code> * @throws NullPointerException if <code>newParagraph</code> is * <code>null</code> */ public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos) { fStart = newParagraph.getBeginIndex(); int end = newParagraph.getEndIndex(); if (end - fStart != fChars.length-1) { initAll(newParagraph); } char[] newChars = new char[end-fStart]; int changedIndex = deletePos-fStart; System.arraycopy(fChars, 0, newChars, 0, deletePos-fStart); System.arraycopy(fChars, changedIndex+1, newChars, changedIndex, end-deletePos); fChars = newChars; if (fBidi != null) { fBidi = new Bidi(newParagraph); if (fBidi.isLeftToRight()) { fBidi = null; } } fParagraph = StyledParagraph.deleteChar(newParagraph, fChars, deletePos, fParagraph); invalidateComponents(); } /** * NOTE: This method is only for LineBreakMeasurer's use. It is package- * private because it returns internal data. */ char[] getChars() { return fChars; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -