Source Code Cross Referenced for StyledParagraph.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         * Portions Copyright 1999-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        /*
028         * @(#)StyledParagraph.java	1.9 05/08/26
029         * (C) Copyright IBM Corp. 1999,  All rights reserved.
030         */
031        package java.awt.font;
032
033        import java.awt.Font;
034        import java.awt.Toolkit;
035        import java.awt.im.InputMethodHighlight;
036        import java.text.Annotation;
037        import java.text.AttributedCharacterIterator;
038        import java.util.Vector;
039        import java.util.HashMap;
040        import java.util.Map;
041        import sun.font.Decoration;
042        import sun.font.FontResolver;
043        import sun.text.CodePointIterator;
044
045        /**
046         * This class stores Font, GraphicAttribute, and Decoration intervals 
047         * on a paragraph of styled text.
048         * <p>
049         * Currently, this class is optimized for a small number of intervals
050         * (preferrably 1).
051         */
052        final class StyledParagraph {
053
054            // the length of the paragraph
055            private int length;
056
057            // If there is a single Decoration for the whole paragraph, it
058            // is stored here.  Otherwise this field is ignored.
059
060            private Decoration decoration;
061
062            // If there is a single Font or GraphicAttribute for the whole 
063            // paragraph, it is stored here.  Otherwise this field is ignored.
064            private Object font;
065
066            // If there are multiple Decorations in the paragraph, they are
067            // stored in this Vector, in order.  Otherwise this vector and
068            // the decorationStarts array are null.
069            private Vector decorations;
070            // If there are multiple Decorations in the paragraph, 
071            // decorationStarts[i] contains the index where decoration i
072            // starts.  For convenience, there is an extra entry at the
073            // end of this array with the length of the paragraph.
074            int[] decorationStarts;
075
076            // If there are multiple Fonts/GraphicAttributes in the paragraph, 
077            // they are
078            // stored in this Vector, in order.  Otherwise this vector and
079            // the fontStarts array are null.
080            private Vector fonts;
081            // If there are multiple Fonts/GraphicAttributes in the paragraph, 
082            // fontStarts[i] contains the index where decoration i
083            // starts.  For convenience, there is an extra entry at the
084            // end of this array with the length of the paragraph.
085            int[] fontStarts;
086
087            private static int INITIAL_SIZE = 8;
088
089            /**
090             * Create a new StyledParagraph over the given styled text.
091             * @param aci an iterator over the text
092             * @param chars the characters extracted from aci
093             */
094            public StyledParagraph(AttributedCharacterIterator aci, char[] chars) {
095
096                int start = aci.getBeginIndex();
097                int end = aci.getEndIndex();
098                length = end - start;
099
100                int index = start;
101                aci.first();
102
103                do {
104                    final int nextRunStart = aci.getRunLimit();
105                    final int localIndex = index - start;
106
107                    Map attributes = aci.getAttributes();
108                    attributes = addInputMethodAttrs(attributes);
109                    Decoration d = Decoration.getDecoration(attributes);
110                    addDecoration(d, localIndex);
111
112                    Object f = getGraphicOrFont(attributes);
113                    if (f == null) {
114                        addFonts(chars, attributes, localIndex, nextRunStart
115                                - start);
116                    } else {
117                        addFont(f, localIndex);
118                    }
119
120                    aci.setIndex(nextRunStart);
121                    index = nextRunStart;
122
123                } while (index < end);
124
125                // Add extra entries to starts arrays with the length 
126                // of the paragraph.  'this' is used as a dummy value
127                // in the Vector.
128                if (decorations != null) {
129                    decorationStarts = addToVector(this , length, decorations,
130                            decorationStarts);
131                }
132                if (fonts != null) {
133                    fontStarts = addToVector(this , length, fonts, fontStarts);
134                }
135            }
136
137            /** 
138             * Adjust indices in starts to reflect an insertion after pos.
139             * Any index in starts greater than pos will be increased by 1.
140             */
141            private static void insertInto(int pos, int[] starts, int numStarts) {
142
143                while (starts[--numStarts] > pos) {
144                    starts[numStarts] += 1;
145                }
146            }
147
148            /**
149             * Return a StyledParagraph reflecting the insertion of a single character
150             * into the text.  This method will attempt to reuse the given paragraph,
151             * but may create a new paragraph.
152             * @param aci an iterator over the text.  The text should be the same as the
153             *     text used to create (or most recently update) oldParagraph, with
154             *     the exception of inserting a single character at insertPos.
155             * @param chars the characters in aci
156             * @param insertPos the index of the new character in aci
157             * @param oldParagraph a StyledParagraph for the text in aci before the
158             *     insertion
159             */
160            public static StyledParagraph insertChar(
161                    AttributedCharacterIterator aci, char[] chars,
162                    int insertPos, StyledParagraph oldParagraph) {
163
164                // If the styles at insertPos match those at insertPos-1, 
165                // oldParagraph will be reused.  Otherwise we create a new
166                // paragraph.
167
168                char ch = aci.setIndex(insertPos);
169                int relativePos = Math.max(insertPos - aci.getBeginIndex() - 1,
170                        0);
171
172                Map attributes = addInputMethodAttrs(aci.getAttributes());
173                Decoration d = Decoration.getDecoration(attributes);
174                if (!oldParagraph.getDecorationAt(relativePos).equals(d)) {
175                    return new StyledParagraph(aci, chars);
176                }
177                Object f = getGraphicOrFont(attributes);
178                if (f == null) {
179                    FontResolver resolver = FontResolver.getInstance();
180                    int fontIndex = resolver.getFontIndex(ch);
181                    f = resolver.getFont(fontIndex, attributes);
182                }
183                if (!oldParagraph.getFontOrGraphicAt(relativePos).equals(f)) {
184                    return new StyledParagraph(aci, chars);
185                }
186
187                // insert into existing paragraph
188                oldParagraph.length += 1;
189                if (oldParagraph.decorations != null) {
190                    insertInto(relativePos, oldParagraph.decorationStarts,
191                            oldParagraph.decorations.size());
192                }
193                if (oldParagraph.fonts != null) {
194                    insertInto(relativePos, oldParagraph.fontStarts,
195                            oldParagraph.fonts.size());
196                }
197                return oldParagraph;
198            }
199
200            /** 
201             * Adjust indices in starts to reflect a deletion after deleteAt.
202             * Any index in starts greater than deleteAt will be increased by 1.
203             * It is the caller's responsibility to make sure that no 0-length
204             * runs result.
205             */
206            private static void deleteFrom(int deleteAt, int[] starts,
207                    int numStarts) {
208
209                while (starts[--numStarts] > deleteAt) {
210                    starts[numStarts] -= 1;
211                }
212            }
213
214            /**
215             * Return a StyledParagraph reflecting the insertion of a single character
216             * into the text.  This method will attempt to reuse the given paragraph,
217             * but may create a new paragraph.
218             * @param aci an iterator over the text.  The text should be the same as the
219             *     text used to create (or most recently update) oldParagraph, with
220             *     the exception of deleting a single character at deletePos.
221             * @param chars the characters in aci
222             * @param deletePos the index where a character was removed
223             * @param oldParagraph a StyledParagraph for the text in aci before the
224             *     insertion
225             */
226            public static StyledParagraph deleteChar(
227                    AttributedCharacterIterator aci, char[] chars,
228                    int deletePos, StyledParagraph oldParagraph) {
229
230                // We will reuse oldParagraph unless there was a length-1 run
231                // at deletePos.  We could do more work and check the individual
232                // Font and Decoration runs, but we don't right now...
233                deletePos -= aci.getBeginIndex();
234
235                if (oldParagraph.decorations == null
236                        && oldParagraph.fonts == null) {
237                    oldParagraph.length -= 1;
238                    return oldParagraph;
239                }
240
241                if (oldParagraph.getRunLimit(deletePos) == deletePos + 1) {
242                    if (deletePos == 0
243                            || oldParagraph.getRunLimit(deletePos - 1) == deletePos) {
244                        return new StyledParagraph(aci, chars);
245                    }
246                }
247
248                oldParagraph.length -= 1;
249                if (oldParagraph.decorations != null) {
250                    deleteFrom(deletePos, oldParagraph.decorationStarts,
251                            oldParagraph.decorations.size());
252                }
253                if (oldParagraph.fonts != null) {
254                    deleteFrom(deletePos, oldParagraph.fontStarts,
255                            oldParagraph.fonts.size());
256                }
257                return oldParagraph;
258            }
259
260            /**
261             * Return the index at which there is a different Font, GraphicAttribute, or
262             * Dcoration than at the given index.
263             * @param index a valid index in the paragraph
264             * @return the first index where there is a change in attributes from
265             *      those at index
266             */
267            public int getRunLimit(int index) {
268
269                if (index < 0 || index >= length) {
270                    throw new IllegalArgumentException("index out of range");
271                }
272                int limit1 = length;
273                if (decorations != null) {
274                    int run = findRunContaining(index, decorationStarts);
275                    limit1 = decorationStarts[run + 1];
276                }
277                int limit2 = length;
278                if (fonts != null) {
279                    int run = findRunContaining(index, fontStarts);
280                    limit2 = fontStarts[run + 1];
281                }
282                return Math.min(limit1, limit2);
283            }
284
285            /**
286             * Return the Decoration in effect at the given index.
287             * @param index a valid index in the paragraph
288             * @return the Decoration at index.
289             */
290            public Decoration getDecorationAt(int index) {
291
292                if (index < 0 || index >= length) {
293                    throw new IllegalArgumentException("index out of range");
294                }
295                if (decorations == null) {
296                    return decoration;
297                }
298                int run = findRunContaining(index, decorationStarts);
299                return (Decoration) decorations.elementAt(run);
300            }
301
302            /**
303             * Return the Font or GraphicAttribute in effect at the given index.
304             * The client must test the type of the return value to determine what
305             * it is.
306             * @param index a valid index in the paragraph
307             * @return the Font or GraphicAttribute at index.
308             */
309            public Object getFontOrGraphicAt(int index) {
310
311                if (index < 0 || index >= length) {
312                    throw new IllegalArgumentException("index out of range");
313                }
314                if (fonts == null) {
315                    return font;
316                }
317                int run = findRunContaining(index, fontStarts);
318                return fonts.elementAt(run);
319            }
320
321            /**
322             * Return i such that starts[i] <= index < starts[i+1].  starts
323             * must be in increasing order, with at least one element greater
324             * than index.
325             */
326            private static int findRunContaining(int index, int[] starts) {
327
328                for (int i = 1; true; i++) {
329                    if (starts[i] > index) {
330                        return i - 1;
331                    }
332                }
333            }
334
335            /**
336             * Append the given Object to the given Vector.  Add
337             * the given index to the given starts array.  If the
338             * starts array does not have room for the index, a
339             * new array is created and returned.
340             */
341            private static int[] addToVector(Object obj, int index, Vector v,
342                    int[] starts) {
343
344                if (!v.lastElement().equals(obj)) {
345                    v.addElement(obj);
346                    int count = v.size();
347                    if (starts.length == count) {
348                        int[] temp = new int[starts.length * 2];
349                        System.arraycopy(starts, 0, temp, 0, starts.length);
350                        starts = temp;
351                    }
352                    starts[count - 1] = index;
353                }
354                return starts;
355            }
356
357            /** 
358             * Add a new Decoration run with the given Decoration at the
359             * given index.
360             */
361            private void addDecoration(Decoration d, int index) {
362
363                if (decorations != null) {
364                    decorationStarts = addToVector(d, index, decorations,
365                            decorationStarts);
366                } else if (decoration == null) {
367                    decoration = d;
368                } else {
369                    if (!decoration.equals(d)) {
370                        decorations = new Vector(INITIAL_SIZE);
371                        decorations.addElement(decoration);
372                        decorations.addElement(d);
373                        decorationStarts = new int[INITIAL_SIZE];
374                        decorationStarts[0] = 0;
375                        decorationStarts[1] = index;
376                    }
377                }
378            }
379
380            /** 
381             * Add a new Font/GraphicAttribute run with the given object at the
382             * given index.
383             */
384            private void addFont(Object f, int index) {
385
386                if (fonts != null) {
387                    fontStarts = addToVector(f, index, fonts, fontStarts);
388                } else if (font == null) {
389                    font = f;
390                } else {
391                    if (!font.equals(f)) {
392                        fonts = new Vector(INITIAL_SIZE);
393                        fonts.addElement(font);
394                        fonts.addElement(f);
395                        fontStarts = new int[INITIAL_SIZE];
396                        fontStarts[0] = 0;
397                        fontStarts[1] = index;
398                    }
399                }
400            }
401
402            /**
403             * Resolve the given chars into Fonts using FontResolver, then add
404             * font runs for each.
405             */
406            private void addFonts(char[] chars, Map attributes, int start,
407                    int limit) {
408
409                FontResolver resolver = FontResolver.getInstance();
410                CodePointIterator iter = CodePointIterator.create(chars, start,
411                        limit);
412                for (int runStart = iter.charIndex(); runStart < limit; runStart = iter
413                        .charIndex()) {
414                    int fontIndex = resolver.nextFontRunIndex(iter);
415                    addFont(resolver.getFont(fontIndex, attributes), runStart);
416                }
417            }
418
419            /**
420             * Return a Map with entries from oldStyles, as well as input 
421             * method entries, if any.
422             */
423            static Map addInputMethodAttrs(Map oldStyles) {
424
425                Object value = oldStyles
426                        .get(TextAttribute.INPUT_METHOD_HIGHLIGHT);
427
428                try {
429                    if (value != null) {
430                        if (value instanceof  Annotation) {
431                            value = ((Annotation) value).getValue();
432                        }
433
434                        InputMethodHighlight hl;
435                        hl = (InputMethodHighlight) value;
436
437                        Map imStyles = null;
438                        try {
439                            imStyles = hl.getStyle();
440                        } catch (NoSuchMethodError e) {
441                        }
442
443                        if (imStyles == null) {
444                            Toolkit tk = Toolkit.getDefaultToolkit();
445                            imStyles = tk.mapInputMethodHighlight(hl);
446                        }
447
448                        if (imStyles != null) {
449                            HashMap newStyles = new HashMap(5, (float) 0.9);
450                            newStyles.putAll(oldStyles);
451
452                            newStyles.putAll(imStyles);
453
454                            return newStyles;
455                        }
456                    }
457                } catch (ClassCastException e) {
458                }
459
460                return oldStyles;
461            }
462
463            /** 
464             * Extract a GraphicAttribute or Font from the given attributes.
465             * If attributes does not contain a GraphicAttribute, Font, or
466             * Font family entry this method returns null.
467             */
468            private static Object getGraphicOrFont(Map attributes) {
469
470                Object value = attributes.get(TextAttribute.CHAR_REPLACEMENT);
471                if (value != null) {
472                    return value;
473                }
474                value = attributes.get(TextAttribute.FONT);
475                if (value != null) {
476                    return value;
477                }
478
479                if (attributes.get(TextAttribute.FAMILY) != null) {
480                    return Font.getFont(attributes);
481                } else {
482                    return null;
483                }
484            }
485        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.