⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linebreakmeasurer.java

📁 JAVA基本类源代码,大家可以学习学习!
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * @(#)LineBreakMeasurer.java	1.22 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved * * The original version of this source code and documentation is * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary * of IBM. These materials are provided under terms of a License * Agreement between Taligent and Sun. This technology is protected * by multiple US and International patents. * * This notice and attribution to Taligent may not be removed. * Taligent is a registered trademark of Taligent, Inc. * */package java.awt.font;import java.text.BreakIterator;import java.text.CharacterIterator;import java.text.AttributedCharacterIterator;import java.awt.font.FontRenderContext;/** * The <code>LineBreakMeasurer</code> class allows styled text to be * broken into lines (or segments) that fit within a particular visual * advance.  This is useful for clients who wish to display a paragraph of * text that fits within a specific width, called the <b>wrapping * width</b>. * <p> * <code>LineBreakMeasurer</code> is constructed with an iterator over * styled text.  The iterator's range should be a single paragraph in the * text. * <code>LineBreakMeasurer</code> maintains a position in the text for the * start of the next text segment.  Initially, this position is the * start of text.  Paragraphs are assigned an overall direction (either * left-to-right or right-to-left) according to the bidirectional * formatting rules.  All segments obtained from a paragraph have the * same direction as the paragraph. * <p> * Segments of text are obtained by calling the method * <code>nextLayout</code>, which returns a {@link TextLayout} * representing the text that fits within the wrapping width. * The <code>nextLayout</code> method moves the current position * to the end of the layout returned from <code>nextLayout</code>. * <p> * <code>LineBreakMeasurer</code> implements the most commonly used * line-breaking policy: Every word that fits within the wrapping * width is placed on the line. If the first word does not fit, then all * of the characters that fit within the wrapping width are placed on the * line.  At least one character is placed on each line. * <p> * The <code>TextLayout</code> instances returned by  * <code>LineBreakMeasurer</code> treat tabs like 0-width spaces.  Clients * who wish to obtain tab-delimited segments for positioning should use * the overload of <code>nextLayout</code> which takes a limiting offset * in the text. * The limiting offset should be the first character after the tab. * The <code>TextLayout</code> objects returned from this method end * at the limit provided (or before, if the text between the current * position and the limit won't fit entirely within the  wrapping * width). * <p> * Clients who are laying out tab-delimited text need a slightly * different line-breaking policy after the first segment has been * placed on a line.  Instead of fitting partial words in the * remaining space, they should place words which don't fit in the * remaining space entirely on the next line.  This change of policy * can be requested in the overload of <code>nextLayout</code> which * takes a <code>boolean</code> parameter.  If this parameter is * <code>true</code>, <code>nextLayout</code> returns  * <code>null</code> if the first word won't fit in * the given space.  See the tab sample below. * <p> * In general, if the text used to construct the  * <code>LineBreakMeasurer</code> changes, a new  * <code>LineBreakMeasurer</code> must be constructed to reflect * the change.  (The old <code>LineBreakMeasurer</code> continues to * function properly, but it won't be aware of the text change.) * Nevertheless, if the text change is the insertion or deletion of a * single character, an existing <code>LineBreakMeasurer</code> can be * 'updated' by calling <code>insertChar</code> or * <code>deleteChar</code>. Updating an existing * <code>LineBreakMeasurer</code> is much faster than creating a new one. * Clients who modify text based on user typing should take advantage * of these methods. * <p> * <strong>Examples</strong>:<p> * Rendering a paragraph in a component * <blockquote> * <pre> * public void paint(Graphics graphics) { * *     Point2D pen = new Point2D(10, 20); *     Graphics2D g2d = (Graphics2D)graphics; *     FontRenderContext frc = g2d.getFontRenderContext(); * *     // let styledText be an AttributedCharacterIterator containing at least *     // one character * *     LineBreakMeasurer measurer = new LineBreakMeasurer(styledText, frc); *     float wrappingWidth = getSize().width - 15; * *     while (measurer.getPosition() < fStyledText.length()) { * *         TextLayout layout = measurer.nextLayout(wrappingWidth); * *         pen.y += (layout.getAscent()); *         float dx = layout.isLeftToRight() ? *             0 : (wrappingWidth - layout.getAdvance()); * *         layout.draw(graphics, pen.x + dx, pen.y); *         pen.y += layout.getDescent() + layout.getLeading(); *     } * } * </pre> * </blockquote> * <p> * Rendering text with tabs.  For simplicity, the overall text * direction is assumed to be left-to-right * <blockquote> * <pre> * public void paint(Graphics graphics) { * *     float leftMargin = 10, rightMargin = 310; *     float[] tabStops = { 100, 250 }; * *     // assume styledText is an AttributedCharacterIterator, and the number *     // of tabs in styledText is tabCount * *     int[] tabLocations = new int[tabCount+1]; * *     int i = 0; *     for (char c = styledText.first(); c != styledText.DONE; c = styledText.next()) { *         if (c == '\t') { *             tabLocations[i++] = styledText.getIndex(); *         } *     } *     tabLocations[tabCount] = styledText.getEndIndex() - 1; * *     // Now tabLocations has an entry for every tab's offset in *     // the text.  For convenience, the last entry is tabLocations *     // is the offset of the last character in the text. * *     LineBreakMeasurer measurer = new LineBreakMeasurer(styledText); *     int currentTab = 0; *     float verticalPos = 20; * *     while (measurer.getPosition() < styledText.getEndIndex()) { * *         // Lay out and draw each line.  All segments on a line *         // must be computed before any drawing can occur, since *         // we must know the largest ascent on the line. *         // TextLayouts are computed and stored in a Vector; *         // their horizontal positions are stored in a parallel *         // Vector. * *         // lineContainsText is true after first segment is drawn *         boolean lineContainsText = false; *         boolean lineComplete = false; *         float maxAscent = 0, maxDescent = 0; *         float horizontalPos = leftMargin; *         Vector layouts = new Vector(1); *         Vector penPositions = new Vector(1); * *         while (!lineComplete) { *             float wrappingWidth = rightMargin - horizontalPos; *             TextLayout layout = *                     measurer.nextLayout(wrappingWidth, *                                         tabLocations[currentTab]+1, *                                         lineContainsText); * *             // layout can be null if lineContainsText is true *             if (layout != null) { *                 layouts.addElement(layout); *                 penPositions.addElement(new Float(horizontalPos)); *                 horizontalPos += layout.getAdvance(); *                 maxAscent = Math.max(maxAscent, layout.getAscent()); *                 maxDescent = Math.max(maxDescent, *                     layout.getDescent() + layout.getLeading()); *             } else { *                 lineComplete = true; *             } * *             lineContainsText = true; * *             if (measurer.getPosition() == tabLocations[currentTab]+1) { *                 currentTab++; *             } * *             if (measurer.getPosition() == styledText.getEndIndex()) *                 lineComplete = true; *             else if (horizontalPos >= tabStops[tabStops.length-1]) *                 lineComplete = true; * *             if (!lineComplete) { *                 // move to next tab stop *                 int j; *                 for (j=0; horizontalPos >= tabStops[j]; j++) {} *                 horizontalPos = tabStops[j]; *             } *         } * *         verticalPos += maxAscent; * *         Enumeration layoutEnum = layouts.elements(); *         Enumeration positionEnum = penPositions.elements(); * *         // now iterate through layouts and draw them *         while (layoutEnum.hasMoreElements()) { *             TextLayout nextLayout = (TextLayout) layoutEnum.nextElement(); *             Float nextPosition = (Float) positionEnum.nextElement(); *             nextLayout.draw(graphics, nextPosition.floatValue(), verticalPos); *         } * *         verticalPos += maxDescent; *     } * } * </pre> * </blockquote> * @see TextLayout */public final class LineBreakMeasurer {        private BreakIterator breakIter;    private int start;    private int pos;    private int limit;    private TextMeasurer measurer;    private CharArrayIterator charIter;    /**     * Constructs a <code>LineBreakMeasurer</code> for the specified text.     *     * @param text the text for which this <code>LineBreakMeasurer</code>     *       produces <code>TextLayout</code> objects; the text must contain      *       at least one character; if the text available through      *       <code>iter</code> changes, further calls to this      *       <code>LineBreakMeasurer</code> instance are undefined (except,     *       in some cases, when <code>insertChar</code> or      *       <code>deleteChar</code> are invoked afterward - see below)     * @param frc contains information about a graphics device which is      *       needed to measure the text correctly;     *       text measurements can vary slightly depending on the     *       device resolution, and attributes such as antialiasing; this     *       parameter does not specify a translation between the     *       <code>LineBreakMeasurer</code> and user space     * @see LineBreakMeasurer#insertChar     * @see LineBreakMeasurer#deleteChar     */    public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) {        this(text, BreakIterator.getLineInstance(), frc);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -