Source Code Cross Referenced for TextMeasurer.java in  » 6.0-JDK-Core » AWT » java » awt » font » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt.font 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        /*
027         * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
028         * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
029         *
030         * The original version of this source code and documentation is
031         * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
032         * of IBM. These materials are provided under terms of a License
033         * Agreement between Taligent and Sun. This technology is protected
034         * by multiple US and International patents.
035         *
036         * This notice and attribution to Taligent may not be removed.
037         * Taligent is a registered trademark of Taligent, Inc.
038         *
039         */
040
041        package java.awt.font;
042
043        import java.awt.Font;
044
045        import java.text.AttributedCharacterIterator;
046        import java.text.AttributedString;
047        import java.text.Bidi;
048        import java.text.BreakIterator;
049        import java.text.CharacterIterator;
050
051        import java.awt.font.FontRenderContext;
052
053        import java.util.Hashtable;
054        import java.util.Map;
055
056        import sun.font.AttributeValues;
057        import sun.font.BidiUtils;
058        import sun.font.TextLineComponent;
059        import sun.font.TextLabelFactory;
060        import sun.font.FontResolver;
061
062        /**
063         * The <code>TextMeasurer</code> class provides the primitive operations 
064         * needed for line break: measuring up to a given advance, determining the 
065         * advance of a range of characters, and generating a
066         * <code>TextLayout</code> for a range of characters. It also provides 
067         * methods for incremental editing of paragraphs.
068         * <p>
069         * A <code>TextMeasurer</code> object is constructed with an 
070         * {@link java.text.AttributedCharacterIterator AttributedCharacterIterator} 
071         * representing a single paragraph of text.  The value returned by the
072         * {@link AttributedCharacterIterator#getBeginIndex() getBeginIndex} 
073         * method of <code>AttributedCharacterIterator</code>
074         * defines the absolute index of the first character.  The value
075         * returned by the 
076         * {@link AttributedCharacterIterator#getEndIndex() getEndIndex}
077         * method of <code>AttributedCharacterIterator</code> defines the index
078         * past the last character.  These values define the range of indexes to 
079         * use in calls to the <code>TextMeasurer</code>.  For example, calls to
080         * get the advance of a range of text or the line break of a range of text
081         * must use indexes between the beginning and end index values.  Calls to
082         * {@link #insertChar(java.text.AttributedCharacterIterator, int) insertChar} 
083         * and 
084         * {@link #deleteChar(java.text.AttributedCharacterIterator, int) deleteChar} 
085         * reset the <code>TextMeasurer</code> to use the beginning index and end
086         * index of the <code>AttributedCharacterIterator</code> passed in those calls.
087         * <p>
088         * Most clients will use the more convenient <code>LineBreakMeasurer</code>, 
089         * which implements the standard line break policy (placing as many words
090         * as will fit on each line). 
091         *
092         * @author John Raley
093         * @version 1.31, 04/20/01
094         * @see LineBreakMeasurer
095         * @since 1.3
096         */
097
098        public final class TextMeasurer implements  Cloneable {
099
100            // Number of lines to format to.
101            private static float EST_LINES = (float) 2.1;
102
103            /*
104            static {
105                String s = System.getProperty("estLines");
106                if (s != null) {
107                    try {
108                        Float f = new Float(s);
109                        EST_LINES = f.floatValue();
110                    }
111                    catch(NumberFormatException e) {
112                    }
113                }
114                //System.out.println("EST_LINES="+EST_LINES);
115            }
116             */
117
118            private FontRenderContext fFrc;
119
120            private int fStart;
121
122            // characters in source text
123            private char[] fChars;
124
125            // Bidi for this paragraph
126            private Bidi fBidi;
127
128            // Levels array for chars in this paragraph - needed to reorder
129            // trailing counterdirectional whitespace
130            private byte[] fLevels;
131
132            // line components in logical order
133            private TextLineComponent[] fComponents;
134
135            // index where components begin
136            private int fComponentStart;
137
138            // index where components end
139            private int fComponentLimit;
140
141            private boolean haveLayoutWindow;
142
143            // used to find valid starting points for line components
144            private BreakIterator fLineBreak = null;
145            private CharArrayIterator charIter = null;
146            int layoutCount = 0;
147            int layoutCharCount = 0;
148
149            // paragraph, with resolved fonts and styles
150            private StyledParagraph fParagraph;
151
152            // paragraph data - same across all layouts
153            private boolean fIsDirectionLTR;
154            private byte fBaseline;
155            private float[] fBaselineOffsets;
156            private float fJustifyRatio = 1;
157
158            /**
159             * Constructs a <code>TextMeasurer</code> from the source text.  
160             * The source text should be a single entire paragraph.
161             * @param text the source paragraph.  Cannot be null.
162             * @param frc the information about a graphics device which is needed 
163             *       to measure the text correctly.  Cannot be null.
164             */
165            public TextMeasurer(AttributedCharacterIterator text,
166                    FontRenderContext frc) {
167
168                fFrc = frc;
169                initAll(text);
170            }
171
172            protected Object clone() {
173                TextMeasurer other;
174                try {
175                    other = (TextMeasurer) super .clone();
176                } catch (CloneNotSupportedException e) {
177                    throw new Error();
178                }
179                if (fComponents != null) {
180                    other.fComponents = (TextLineComponent[]) fComponents
181                            .clone();
182                }
183                return other;
184            }
185
186            private void invalidateComponents() {
187                fComponentStart = fComponentLimit = fChars.length;
188                fComponents = null;
189                haveLayoutWindow = false;
190            }
191
192            /**
193             * Initialize state, including fChars array, direction, and
194             * fBidi.
195             */
196            private void initAll(AttributedCharacterIterator text) {
197
198                fStart = text.getBeginIndex();
199
200                // extract chars
201                fChars = new char[text.getEndIndex() - fStart];
202
203                int n = 0;
204                for (char c = text.first(); c != text.DONE; c = text.next()) {
205                    fChars[n++] = c;
206                }
207
208                text.first();
209
210                fBidi = new Bidi(text);
211                if (fBidi.isLeftToRight()) {
212                    fBidi = null;
213                }
214
215                text.first();
216                Map paragraphAttrs = text.getAttributes();
217                NumericShaper shaper = AttributeValues
218                        .getNumericShaping(paragraphAttrs);
219                if (shaper != null) {
220                    shaper.shape(fChars, 0, fChars.length);
221                }
222
223                fParagraph = new StyledParagraph(text, fChars);
224
225                // set paragraph attributes
226                {
227                    // If there's an embedded graphic at the start of the
228                    // paragraph, look for the first non-graphic character
229                    // and use it and its font to initialize the paragraph.
230                    // If not, use the first graphic to initialize.
231                    fJustifyRatio = AttributeValues
232                            .getJustification(paragraphAttrs);
233
234                    boolean haveFont = TextLine.advanceToFirstFont(text);
235
236                    if (haveFont) {
237                        Font defaultFont = TextLine.getFontAtCurrentPos(text);
238                        int charsStart = text.getIndex() - text.getBeginIndex();
239                        LineMetrics lm = defaultFont.getLineMetrics(fChars,
240                                charsStart, charsStart + 1, fFrc);
241                        fBaseline = (byte) lm.getBaselineIndex();
242                        fBaselineOffsets = lm.getBaselineOffsets();
243                    } else {
244                        // hmmm what to do here?  Just try to supply reasonable
245                        // values I guess.
246
247                        GraphicAttribute graphic = (GraphicAttribute) paragraphAttrs
248                                .get(TextAttribute.CHAR_REPLACEMENT);
249                        fBaseline = TextLayout.getBaselineFromGraphic(graphic);
250                        Font dummyFont = new Font(new Hashtable(5, (float) 0.9));
251                        LineMetrics lm = dummyFont.getLineMetrics(" ", 0, 1,
252                                fFrc);
253                        fBaselineOffsets = lm.getBaselineOffsets();
254                    }
255                    fBaselineOffsets = TextLine.getNormalizedOffsets(
256                            fBaselineOffsets, fBaseline);
257                }
258
259                invalidateComponents();
260            }
261
262            /**
263             * Generate components for the paragraph.  fChars, fBidi should have been 
264             * initialized already.
265             */
266            private void generateComponents(int startingAt, int endingAt) {
267
268                if (collectStats) {
269                    formattedChars += (endingAt - startingAt);
270                }
271                int layoutFlags = 0; // no extra info yet, bidi determines run and line direction
272                TextLabelFactory factory = new TextLabelFactory(fFrc, fChars,
273                        fBidi, layoutFlags);
274
275                int[] charsLtoV = null;
276
277                if (fBidi != null) {
278                    fLevels = BidiUtils.getLevels(fBidi);
279                    int[] charsVtoL = BidiUtils
280                            .createVisualToLogicalMap(fLevels);
281                    charsLtoV = BidiUtils.createInverseMap(charsVtoL);
282                    fIsDirectionLTR = fBidi.baseIsLeftToRight();
283                } else {
284                    fLevels = null;
285                    fIsDirectionLTR = true;
286                }
287
288                try {
289                    fComponents = TextLine.getComponents(fParagraph, fChars,
290                            startingAt, endingAt, charsLtoV, fLevels, factory);
291                } catch (IllegalArgumentException e) {
292                    System.out.println("startingAt=" + startingAt
293                            + "; endingAt=" + endingAt);
294                    System.out.println("fComponentLimit=" + fComponentLimit);
295                    throw e;
296                }
297
298                fComponentStart = startingAt;
299                fComponentLimit = endingAt;
300                //debugFormatCount += (endingAt-startingAt);
301            }
302
303            private int calcLineBreak(final int pos, final float maxAdvance) {
304
305                // either of these statements removes the bug:
306                //generateComponents(0, fChars.length);
307                //generateComponents(pos, fChars.length);
308
309                int startPos = pos;
310                float width = maxAdvance;
311
312                int tlcIndex;
313                int tlcStart = fComponentStart;
314
315                for (tlcIndex = 0; tlcIndex < fComponents.length; tlcIndex++) {
316                    int gaLimit = tlcStart
317                            + fComponents[tlcIndex].getNumCharacters();
318                    if (gaLimit > startPos) {
319                        break;
320                    } else {
321                        tlcStart = gaLimit;
322                    }
323                }
324
325                // tlcStart is now the start of the tlc at tlcIndex
326
327                for (; tlcIndex < fComponents.length; tlcIndex++) {
328
329                    TextLineComponent tlc = fComponents[tlcIndex];
330                    int numCharsInGa = tlc.getNumCharacters();
331
332                    int lineBreak = tlc.getLineBreakIndex(startPos - tlcStart,
333                            width);
334                    if (lineBreak == numCharsInGa
335                            && tlcIndex < fComponents.length) {
336                        width -= tlc.getAdvanceBetween(startPos - tlcStart,
337                                lineBreak);
338                        tlcStart += numCharsInGa;
339                        startPos = tlcStart;
340                    } else {
341                        return tlcStart + lineBreak;
342                    }
343                }
344
345                if (fComponentLimit < fChars.length) {
346                    // format more text and try again
347                    //if (haveLayoutWindow) {
348                    //    outOfWindow++;
349                    //}
350
351                    generateComponents(pos, fChars.length);
352                    return calcLineBreak(pos, maxAdvance);
353                }
354
355                return fChars.length;
356            }
357
358            /**
359             * According to the Unicode Bidirectional Behavior specification
360             * (Unicode Standard 2.0, section 3.11), whitespace at the ends
361             * of lines which would naturally flow against the base direction
362             * must be made to flow with the line direction, and moved to the
363             * end of the line.  This method returns the start of the sequence
364             * of trailing whitespace characters to move to the end of a
365             * line taken from the given range.
366             */
367            private int trailingCdWhitespaceStart(int startPos, int limitPos) {
368
369                if (fLevels != null) {
370                    // Back up over counterdirectional whitespace
371                    final byte baseLevel = (byte) (fIsDirectionLTR ? 0 : 1);
372                    for (int cdWsStart = limitPos; --cdWsStart >= startPos;) {
373                        if ((fLevels[cdWsStart] % 2) == baseLevel
374                                || Character
375                                        .getDirectionality(fChars[cdWsStart]) != Character.DIRECTIONALITY_WHITESPACE) {
376                            return ++cdWsStart;
377                        }
378                    }
379                }
380
381                return startPos;
382            }
383
384            private TextLineComponent[] makeComponentsOnRange(int startPos,
385                    int limitPos) {
386
387                // sigh I really hate to do this here since it's part of the
388                // bidi algorithm.
389                // cdWsStart is the start of the trailing counterdirectional
390                // whitespace
391                final int cdWsStart = trailingCdWhitespaceStart(startPos,
392                        limitPos);
393
394                int tlcIndex;
395                int tlcStart = fComponentStart;
396
397                for (tlcIndex = 0; tlcIndex < fComponents.length; tlcIndex++) {
398                    int gaLimit = tlcStart
399                            + fComponents[tlcIndex].getNumCharacters();
400                    if (gaLimit > startPos) {
401                        break;
402                    } else {
403                        tlcStart = gaLimit;
404                    }
405                }
406
407                // tlcStart is now the start of the tlc at tlcIndex
408
409                int componentCount;
410                {
411                    boolean split = false;
412                    int compStart = tlcStart;
413                    int lim = tlcIndex;
414                    for (boolean cont = true; cont; lim++) {
415                        int gaLimit = compStart
416                                + fComponents[lim].getNumCharacters();
417                        if (cdWsStart > Math.max(compStart, startPos)
418                                && cdWsStart < Math.min(gaLimit, limitPos)) {
419                            split = true;
420                        }
421                        if (gaLimit >= limitPos) {
422                            cont = false;
423                        } else {
424                            compStart = gaLimit;
425                        }
426                    }
427                    componentCount = lim - tlcIndex;
428                    if (split) {
429                        componentCount++;
430                    }
431                }
432
433                TextLineComponent[] components = new TextLineComponent[componentCount];
434                int newCompIndex = 0;
435                int linePos = startPos;
436
437                int breakPt = cdWsStart;
438
439                int subsetFlag;
440                if (breakPt == startPos) {
441                    subsetFlag = fIsDirectionLTR ? TextLineComponent.LEFT_TO_RIGHT
442                            : TextLineComponent.RIGHT_TO_LEFT;
443                    breakPt = limitPos;
444                } else {
445                    subsetFlag = TextLineComponent.UNCHANGED;
446                }
447
448                while (linePos < limitPos) {
449
450                    int compLength = fComponents[tlcIndex].getNumCharacters();
451                    int tlcLimit = tlcStart + compLength;
452
453                    int start = Math.max(linePos, tlcStart);
454                    int limit = Math.min(breakPt, tlcLimit);
455
456                    components[newCompIndex++] = fComponents[tlcIndex]
457                            .getSubset(start - tlcStart, limit - tlcStart,
458                                    subsetFlag);
459                    linePos += (limit - start);
460                    if (linePos == breakPt) {
461                        breakPt = limitPos;
462                        subsetFlag = fIsDirectionLTR ? TextLineComponent.LEFT_TO_RIGHT
463                                : TextLineComponent.RIGHT_TO_LEFT;
464                    }
465                    if (linePos == tlcLimit) {
466                        tlcIndex++;
467                        tlcStart = tlcLimit;
468                    }
469                }
470
471                return components;
472            }
473
474            private TextLine makeTextLineOnRange(int startPos, int limitPos) {
475
476                int[] charsLtoV = null;
477                byte[] charLevels = null;
478
479                if (fBidi != null) {
480                    Bidi lineBidi = fBidi.createLineBidi(startPos, limitPos);
481                    charLevels = BidiUtils.getLevels(lineBidi);
482                    int[] charsVtoL = BidiUtils
483                            .createVisualToLogicalMap(charLevels);
484                    charsLtoV = BidiUtils.createInverseMap(charsVtoL);
485                }
486
487                TextLineComponent[] components = makeComponentsOnRange(
488                        startPos, limitPos);
489
490                return new TextLine(fFrc, components, fBaselineOffsets, fChars,
491                        startPos, limitPos, charsLtoV, charLevels,
492                        fIsDirectionLTR);
493
494            }
495
496            private void ensureComponents(int start, int limit) {
497
498                if (start < fComponentStart || limit > fComponentLimit) {
499                    generateComponents(start, limit);
500                }
501            }
502
503            private void makeLayoutWindow(int localStart) {
504
505                int compStart = localStart;
506                int compLimit = fChars.length;
507
508                // If we've already gone past the layout window, format to end of paragraph
509                if (layoutCount > 0 && !haveLayoutWindow) {
510                    float avgLineLength = Math.max(layoutCharCount
511                            / layoutCount, 1);
512                    compLimit = Math.min(localStart
513                            + (int) (avgLineLength * EST_LINES), fChars.length);
514                }
515
516                if (localStart > 0 || compLimit < fChars.length) {
517                    if (charIter == null) {
518                        charIter = new CharArrayIterator(fChars);
519                    } else {
520                        charIter.reset(fChars);
521                    }
522                    if (fLineBreak == null) {
523                        fLineBreak = BreakIterator.getLineInstance();
524                    }
525                    fLineBreak.setText(charIter);
526                    if (localStart > 0) {
527                        if (!fLineBreak.isBoundary(localStart)) {
528                            compStart = fLineBreak.preceding(localStart);
529                        }
530                    }
531                    if (compLimit < fChars.length) {
532                        if (!fLineBreak.isBoundary(compLimit)) {
533                            compLimit = fLineBreak.following(compLimit);
534                        }
535                    }
536                }
537
538                ensureComponents(compStart, compLimit);
539                haveLayoutWindow = true;
540            }
541
542            /**
543             * Returns the index of the first character which will not fit on
544             * on a line beginning at <code>start</code> and possible
545             * measuring up to <code>maxAdvance</code> in graphical width.
546             *
547             * @param start the character index at which to start measuring.
548             *  <code>start</code> is an absolute index, not relative to the
549             *  start of the paragraph
550             * @param maxAdvance the graphical width in which the line must fit
551             * @return the index after the last character that will fit
552             *  on a line beginning at <code>start</code>, which is not longer
553             *  than <code>maxAdvance</code> in graphical width
554             * @throws IllegalArgumentException if <code>start</code> is
555             *          less than the beginning of the paragraph.
556             */
557            public int getLineBreakIndex(int start, float maxAdvance) {
558
559                int localStart = start - fStart;
560
561                if (!haveLayoutWindow || localStart < fComponentStart
562                        || localStart >= fComponentLimit) {
563                    makeLayoutWindow(localStart);
564                }
565
566                return calcLineBreak(localStart, maxAdvance) + fStart;
567            }
568
569            /**
570             * Returns the graphical width of a line beginning at <code>start</code>
571             * and including characters up to <code>limit</code>.
572             * <code>start</code> and <code>limit</code> are absolute indices,
573             * not relative to the start of the paragraph.
574             *
575             * @param start the character index at which to start measuring
576             * @param limit the character index at which to stop measuring
577             * @return the graphical width of a line beginning at <code>start</code>
578             *   and including characters up to <code>limit</code>
579             * @throws IndexOutOfBoundsException if <code>limit</code> is less
580             *         than <code>start</code>
581             * @throws IllegalArgumentException if <code>start</code> or 
582             *          <code>limit</code> is not between the beginning of
583             *          the paragraph and the end of the paragraph. 
584             */
585            public float getAdvanceBetween(int start, int limit) {
586
587                int localStart = start - fStart;
588                int localLimit = limit - fStart;
589
590                ensureComponents(localStart, localLimit);
591                TextLine line = makeTextLineOnRange(localStart, localLimit);
592                return line.getMetrics().advance;
593                // could cache line in case getLayout is called with same start, limit
594            }
595
596            /**
597             * Returns a <code>TextLayout</code> on the given character range.
598             *
599             * @param start the index of the first character
600             * @param limit the index after the last character.  Must be greater
601             *   than <code>start</code>
602             * @return a <code>TextLayout</code> for the characters beginning at
603             *  <code>start</code> up to (but not including) <code>limit</code>
604             * @throws IndexOutOfBoundsException if <code>limit</code> is less
605             *         than <code>start</code>
606             * @throws IllegalArgumentException if <code>start</code> or 
607             *          <code>limit</code> is not between the beginning of
608             *          the paragraph and the end of the paragraph. 
609             */
610            public TextLayout getLayout(int start, int limit) {
611
612                int localStart = start - fStart;
613                int localLimit = limit - fStart;
614
615                ensureComponents(localStart, localLimit);
616                TextLine textLine = makeTextLineOnRange(localStart, localLimit);
617
618                if (localLimit < fChars.length) {
619                    layoutCharCount += limit - start;
620                    layoutCount++;
621                }
622
623                return new TextLayout(textLine, fBaseline, fBaselineOffsets,
624                        fJustifyRatio);
625            }
626
627            private int formattedChars = 0;
628            private static boolean wantStats = false;/*"true".equals(System.getProperty("collectStats"));*/
629            private boolean collectStats = false;
630
631            private void printStats() {
632                System.out.println("formattedChars: " + formattedChars);
633                //formattedChars = 0;
634                collectStats = false;
635            }
636
637            /**
638             * Updates the <code>TextMeasurer</code> after a single character has 
639             * been inserted
640             * into the paragraph currently represented by this
641             * <code>TextMeasurer</code>.  After this call, this
642             * <code>TextMeasurer</code> is equivalent to a new 
643             * <code>TextMeasurer</code> created from the text;  however, it will
644             * usually be more efficient to update an existing
645             * <code>TextMeasurer</code> than to create a new one from scratch.
646             *
647             * @param newParagraph the text of the paragraph after performing
648             * the insertion.  Cannot be null.
649             * @param insertPos the position in the text where the character was 
650             * inserted.  Must not be less than the start of 
651             * <code>newParagraph</code>, and must be less than the end of
652             * <code>newParagraph</code>.
653             * @throws IndexOutOfBoundsException if <code>insertPos</code> is less
654             *         than the start of <code>newParagraph</code> or greater than
655             *         or equal to the end of <code>newParagraph</code>
656             * @throws NullPointerException if <code>newParagraph</code> is   
657             *         <code>null</code>
658             */
659            public void insertChar(AttributedCharacterIterator newParagraph,
660                    int insertPos) {
661
662                if (collectStats) {
663                    printStats();
664                }
665                if (wantStats) {
666                    collectStats = true;
667                }
668
669                fStart = newParagraph.getBeginIndex();
670                int end = newParagraph.getEndIndex();
671                if (end - fStart != fChars.length + 1) {
672                    initAll(newParagraph);
673                }
674
675                char[] newChars = new char[end - fStart];
676                int newCharIndex = insertPos - fStart;
677                System.arraycopy(fChars, 0, newChars, 0, newCharIndex);
678
679                char newChar = newParagraph.setIndex(insertPos);
680                newChars[newCharIndex] = newChar;
681                System.arraycopy(fChars, newCharIndex, newChars,
682                        newCharIndex + 1, end - insertPos - 1);
683                fChars = newChars;
684
685                if (fBidi != null
686                        || Bidi.requiresBidi(newChars, newCharIndex,
687                                newCharIndex + 1)
688                        || newParagraph
689                                .getAttribute(TextAttribute.BIDI_EMBEDDING) != null) {
690
691                    fBidi = new Bidi(newParagraph);
692                    if (fBidi.isLeftToRight()) {
693                        fBidi = null;
694                    }
695                }
696
697                fParagraph = StyledParagraph.insertChar(newParagraph, fChars,
698                        insertPos, fParagraph);
699                invalidateComponents();
700            }
701
702            /**
703             * Updates the <code>TextMeasurer</code> after a single character has 
704             * been deleted
705             * from the paragraph currently represented by this
706             * <code>TextMeasurer</code>.  After this call, this
707             * <code>TextMeasurer</code> is equivalent to a new <code>TextMeasurer</code>
708             * created from the text;  however, it will usually be more efficient
709             * to update an existing <code>TextMeasurer</code> than to create a new one
710             * from scratch.
711             *
712             * @param newParagraph the text of the paragraph after performing
713             * the deletion.  Cannot be null.
714             * @param deletePos the position in the text where the character was removed.  
715             * Must not be less than
716             * the start of <code>newParagraph</code>, and must not be greater than the
717             * end of <code>newParagraph</code>.
718             * @throws IndexOutOfBoundsException if <code>deletePos</code> is
719             *         less than the start of <code>newParagraph</code> or greater
720             *         than the end of <code>newParagraph</code>
721             * @throws NullPointerException if <code>newParagraph</code> is
722             *         <code>null</code>
723             */
724            public void deleteChar(AttributedCharacterIterator newParagraph,
725                    int deletePos) {
726
727                fStart = newParagraph.getBeginIndex();
728                int end = newParagraph.getEndIndex();
729                if (end - fStart != fChars.length - 1) {
730                    initAll(newParagraph);
731                }
732
733                char[] newChars = new char[end - fStart];
734                int changedIndex = deletePos - fStart;
735
736                System.arraycopy(fChars, 0, newChars, 0, deletePos - fStart);
737                System.arraycopy(fChars, changedIndex + 1, newChars,
738                        changedIndex, end - deletePos);
739                fChars = newChars;
740
741                if (fBidi != null) {
742                    fBidi = new Bidi(newParagraph);
743                    if (fBidi.isLeftToRight()) {
744                        fBidi = null;
745                    }
746                }
747
748                fParagraph = StyledParagraph.deleteChar(newParagraph, fChars,
749                        deletePos, fParagraph);
750                invalidateComponents();
751            }
752
753            /**
754             * NOTE:  This method is only for LineBreakMeasurer's use.  It is package-
755             * private because it returns internal data.
756             */
757            char[] getChars() {
758
759                return fChars;
760            }
761        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.