Source Code Cross Referenced for SVGGVTFont.java in  » Graphic-Library » batik » org » apache » batik » bridge » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » batik » org.apache.batik.bridge 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:           Licensed to the Apache Software Foundation (ASF) under one or more
004:           contributor license agreements.  See the NOTICE file distributed with
005:           this work for additional information regarding copyright ownership.
006:           The ASF licenses this file to You under the Apache License, Version 2.0
007:           (the "License"); you may not use this file except in compliance with
008:           the License.  You may obtain a copy of the License at
009:
010:               http://www.apache.org/licenses/LICENSE-2.0
011:
012:           Unless required by applicable law or agreed to in writing, software
013:           distributed under the License is distributed on an "AS IS" BASIS,
014:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015:           See the License for the specific language governing permissions and
016:           limitations under the License.
017:
018:         */
019:        package org.apache.batik.bridge;
020:
021:        import java.awt.Font;
022:        import java.awt.font.FontRenderContext;
023:        import java.text.AttributedCharacterIterator;
024:        import java.text.CharacterIterator;
025:        import java.text.StringCharacterIterator;
026:        import java.util.StringTokenizer;
027:        import java.util.List;
028:        import java.util.ArrayList;
029:
030:        import org.apache.batik.css.engine.SVGCSSEngine;
031:        import org.apache.batik.css.engine.value.Value;
032:        import org.apache.batik.dom.util.XMLSupport;
033:        import org.apache.batik.gvt.font.GVTFont;
034:        import org.apache.batik.gvt.font.GVTFontFace;
035:        import org.apache.batik.gvt.font.GVTGlyphVector;
036:        import org.apache.batik.gvt.font.GVTLineMetrics;
037:        import org.apache.batik.gvt.font.Glyph;
038:        import org.apache.batik.gvt.font.Kern;
039:        import org.apache.batik.gvt.font.KerningTable;
040:        import org.apache.batik.gvt.font.SVGGVTGlyphVector;
041:        import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
042:        import org.apache.batik.gvt.text.TextPaintInfo;
043:        import org.apache.batik.util.SVGConstants;
044:
045:        import org.w3c.dom.Element;
046:
047:        /**
048:         * Represents an SVG font.
049:         *
050:         * @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
051:         * @version $Id: SVGGVTFont.java 489226 2006-12-21 00:05:36Z cam $
052:         */
053:        public final class SVGGVTFont implements  GVTFont, SVGConstants {
054:
055:            public static final AttributedCharacterIterator.Attribute PAINT_INFO = GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO;
056:
057:            private float fontSize;
058:            private GVTFontFace fontFace;
059:            private String[] glyphUnicodes;
060:            private String[] glyphNames;
061:            private String[] glyphLangs;
062:            private String[] glyphOrientations;
063:            private String[] glyphForms;
064:            private Element[] glyphElements;
065:            private Element[] hkernElements;
066:            private Element[] vkernElements;
067:            private BridgeContext ctx;
068:            private Element textElement;
069:            private Element missingGlyphElement;
070:            private KerningTable hKerningTable;
071:            private KerningTable vKerningTable;
072:            private String language;
073:            private String orientation;
074:            private float scale;
075:            private GVTLineMetrics lineMetrics = null;
076:
077:            /**
078:             * Constructs a new SVGGVTFont of the specified size.
079:             *
080:             * @param fontSize The size of the font to create.
081:             * @param fontFace The font face that describes the font.
082:             * @param glyphUnicodes An array containing the unicode values for
083:             * all the glyphs this font can display.
084:             * @param glyphNames An array containing the names of all the
085:             * glyphs this font can display.
086:             * @param ctx The bridge context.
087:             * @param glyphElements An array containing the children glyph
088:             * elements of the SVG font.
089:             * @param missingGlyphElement The missing glyph element for this
090:             * font.
091:             * @param hkernElements An array containing all hkern elements for
092:             * this font.
093:             * @param vkernElements An array containing all vkern elements for
094:             * this font.
095:             * @param textElement The text element that contains the text to
096:             * be rendered using this font.
097:             */
098:            public SVGGVTFont(float fontSize, GVTFontFace fontFace,
099:                    String[] glyphUnicodes, String[] glyphNames,
100:                    String[] glyphLangs, String[] glyphOrientations,
101:                    String[] glyphForms, BridgeContext ctx,
102:                    Element[] glyphElements, Element missingGlyphElement,
103:                    Element[] hkernElements, Element[] vkernElements,
104:                    Element textElement) {
105:                this .fontFace = fontFace;
106:                this .fontSize = fontSize;
107:                this .glyphUnicodes = glyphUnicodes;
108:                this .glyphNames = glyphNames;
109:                this .glyphLangs = glyphLangs;
110:                this .glyphOrientations = glyphOrientations;
111:                this .glyphForms = glyphForms;
112:                this .ctx = ctx;
113:                this .glyphElements = glyphElements;
114:                this .missingGlyphElement = missingGlyphElement;
115:                this .hkernElements = hkernElements;
116:                this .vkernElements = vkernElements;
117:                this .scale = fontSize / fontFace.getUnitsPerEm();
118:                this .textElement = textElement;
119:
120:                this .language = XMLSupport.getXMLLang(textElement);
121:
122:                Value v = CSSUtilities.getComputedStyle(textElement,
123:                        SVGCSSEngine.WRITING_MODE_INDEX);
124:                if (v.getStringValue().startsWith(CSS_TB_VALUE)) {
125:                    // top to bottom, so set orientation to "v"
126:                    this .orientation = SVG_V_VALUE;
127:                } else {
128:                    this .orientation = SVG_H_VALUE;
129:                }
130:
131:                createKerningTables();
132:            }
133:
134:            /**
135:             * Creates the kerning tables for this font. Two tables are created,
136:             * horizontal and vertical. If there are not children vkern or hkern
137:             * elements these tables will be empty.
138:             */
139:            private void createKerningTables() {
140:
141:                Kern[] hEntries = new Kern[hkernElements.length];
142:                for (int i = 0; i < hkernElements.length; i++) {
143:                    Element hkernElement = hkernElements[i];
144:                    SVGHKernElementBridge hkernBridge = (SVGHKernElementBridge) ctx
145:                            .getBridge(hkernElement);
146:                    Kern hkern = hkernBridge
147:                            .createKern(ctx, hkernElement, this );
148:                    hEntries[i] = hkern;
149:                }
150:                hKerningTable = new KerningTable(hEntries);
151:
152:                Kern[] vEntries = new Kern[vkernElements.length];
153:                for (int i = 0; i < vkernElements.length; i++) {
154:                    Element vkernElement = vkernElements[i];
155:                    SVGVKernElementBridge vkernBridge = (SVGVKernElementBridge) ctx
156:                            .getBridge(vkernElement);
157:                    Kern vkern = vkernBridge
158:                            .createKern(ctx, vkernElement, this );
159:                    vEntries[i] = vkern;
160:                }
161:                vKerningTable = new KerningTable(vEntries);
162:
163:            }
164:
165:            /**
166:             * Returns the horizontal kerning value for the specified glyph pair.
167:             * This will be zero if there is no explicit horizontal kerning value
168:             * for this particular glyph pair.
169:             *
170:             * @param glyphCode1 The id of the first glyph.
171:             * @param glyphCode2 The id of the second glyph.
172:             *
173:             * @return The horizontal kerning value.
174:             */
175:            public float getHKern(int glyphCode1, int glyphCode2) {
176:                if (glyphCode1 < 0 || glyphCode1 >= glyphUnicodes.length
177:                        || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
178:                    return 0f;
179:                }
180:                float ret;
181:                ret = hKerningTable.getKerningValue(glyphCode1, glyphCode2,
182:                        glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
183:                return ret * scale;
184:            }
185:
186:            /**
187:             * Returns the vertical kerning value for the specified glyph pair.
188:             * This will be zero if there is no explicit vertical kerning value for
189:             * for this particular glyph pair.
190:             *
191:             * @param glyphCode1 The id of the first glyph.
192:             * @param glyphCode2 The id of the second glyph.
193:             *
194:             * @return The vertical kerning value.
195:             */
196:            public float getVKern(int glyphCode1, int glyphCode2) {
197:                if (glyphCode1 < 0 || glyphCode1 >= glyphUnicodes.length
198:                        || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
199:                    return 0f;
200:                }
201:                float ret;
202:                ret = vKerningTable.getKerningValue(glyphCode1, glyphCode2,
203:                        glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
204:                return ret * scale;
205:            }
206:
207:            /**
208:             * Returns an array of glyph codes (unique ids) of the glyphs with the
209:             * specified name (there may be more than one).
210:             *
211:             * @param name The name of the glyph.
212:             *
213:             * @return An array of matching glyph codes. This may be empty.
214:             */
215:            public int[] getGlyphCodesForName(String name) {
216:                List glyphCodes = new ArrayList();
217:                for (int i = 0; i < glyphNames.length; i++) {
218:                    if (glyphNames[i] != null && glyphNames[i].equals(name)) {
219:                        glyphCodes.add(new Integer(i));
220:                    }
221:                }
222:                int[] glyphCodeArray = new int[glyphCodes.size()];
223:                for (int i = 0; i < glyphCodes.size(); i++) {
224:                    glyphCodeArray[i] = ((Integer) glyphCodes.get(i))
225:                            .intValue();
226:                }
227:                return glyphCodeArray;
228:            }
229:
230:            /**
231:             * Returns an array of glyph codes (unique ids) of the glyphs with the
232:             * specified unicode value (there may be more than one).
233:             *
234:             * @param unicode The unicode value of the glyph.
235:             *
236:             * @return An array of matching glyph codes. This may be empty.
237:             */
238:            public int[] getGlyphCodesForUnicode(String unicode) {
239:                List glyphCodes = new ArrayList();
240:                for (int i = 0; i < glyphUnicodes.length; i++) {
241:                    if (glyphUnicodes[i] != null
242:                            && glyphUnicodes[i].equals(unicode)) {
243:                        glyphCodes.add(new Integer(i));
244:                    }
245:                }
246:                int[] glyphCodeArray = new int[glyphCodes.size()];
247:                for (int i = 0; i < glyphCodes.size(); i++) {
248:                    glyphCodeArray[i] = ((Integer) glyphCodes.get(i))
249:                            .intValue();
250:                }
251:                return glyphCodeArray;
252:            }
253:
254:            /**
255:             * Returns true if the glyph language matches the language of the
256:             * text node to be rendered by this font.  This will be the case
257:             * if one of the languages in glyphLang matches exactly with the
258:             * xml:lang attibute of the text node, or if the xml:lang
259:             * attribute exactly equals a prefix of one glyph languages.
260:             *
261:             * @param glyphLang A comma separated list of languages that are associated
262:             * with a glyph.
263:             *
264:             * @return Whether or not the glyph language matches the language of the
265:             * text node.
266:             */
267:            private boolean languageMatches(String glyphLang) {
268:                if (glyphLang == null || glyphLang.length() == 0) {
269:                    return true; // will match all languages
270:                }
271:                StringTokenizer st = new StringTokenizer(glyphLang, ",");
272:                while (st.hasMoreTokens()) {
273:                    String s = st.nextToken();
274:                    if (s.equals(language)
275:                            || (s.startsWith(language)
276:                                    && s.length() > language.length() && s
277:                                    .charAt(language.length()) == '-')) {
278:                        return true;
279:                    }
280:                }
281:                return false;
282:            }
283:
284:            /**
285:             * Returns true if the glyph orientation matches the orientation of the
286:             * text node to be rendered by this font.
287:             *
288:             * @param glyphOrientation The glyph orientation attribute value. Will be
289:             * "h", "v" or empty.
290:             *
291:             * @return Whether or not the glyph orientation matches the text to be
292:             * rendered by this font object.
293:             */
294:            private boolean orientationMatches(String glyphOrientation) {
295:                if (glyphOrientation == null || glyphOrientation.length() == 0) {
296:                    return true;
297:                }
298:                return glyphOrientation.equals(orientation);
299:            }
300:
301:            /**
302:             * Returns true if the glyph form matches that of the current character in
303:             * the aci.
304:             *
305:             * @param glyphUnicode The unicode value of the glyph.
306:             * @param glyphForm The arabic-form glyph attribute.
307:             * @param aci The aci containing the character to check.
308:             * @param currentIndex The index of the character to check.
309:             */
310:            private boolean formMatches(String glyphUnicode, String glyphForm,
311:                    AttributedCharacterIterator aci, int currentIndex) {
312:                if (aci == null || glyphForm == null || glyphForm.length() == 0) {
313:                    // there aren't any attributes attached to the text
314:                    // or the glyph doesn't have an arabic form
315:                    return true;
316:                }
317:
318:                char c = aci.setIndex(currentIndex);
319:                Integer form = (Integer) aci
320:                        .getAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
321:
322:                if (form == null
323:                        || form
324:                                .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_NONE)) {
325:                    // the glyph has an arabic form and the current character
326:                    // form is "none" so don't match
327:                    return false;
328:                }
329:
330:                // see if c is the start of an arabic ligature
331:                if (glyphUnicode.length() > 1) {
332:
333:                    boolean matched = true;
334:                    for (int j = 1; j < glyphUnicode.length(); j++) {
335:                        c = aci.next();
336:                        if (glyphUnicode.charAt(j) != c) {
337:                            matched = false;
338:                            break;
339:                        }
340:                    }
341:
342:                    // reset the aci
343:                    aci.setIndex(currentIndex);
344:
345:                    if (matched) {
346:
347:                        // ligature matches, now check that the arabic forms are ok
348:                        aci.setIndex(currentIndex + glyphUnicode.length() - 1);
349:                        Integer lastForm = (Integer) aci
350:                                .getAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
351:
352:                        // reset the aci again
353:                        aci.setIndex(currentIndex);
354:
355:                        if (form != null && lastForm != null) {
356:                            if (form
357:                                    .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)
358:                                    && lastForm
359:                                            .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL)) {
360:                                // return true if the glyph form is isolated
361:                                return glyphForm
362:                                        .equals(SVGConstants.SVG_ISOLATED_VALUE);
363:
364:                            } else if (form
365:                                    .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)) {
366:                                // return true if the glyph form is terminal
367:                                return glyphForm
368:                                        .equals(SVGConstants.SVG_TERMINAL_VALUE);
369:
370:                            } else if (form
371:                                    .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)
372:                                    && lastForm
373:                                            .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)) {
374:                                // return true if the glyph form is medial
375:                                return glyphForm
376:                                        .equals(SVGConstants.SVG_MEDIAL_VALUE);
377:                            }
378:                            // should test for other combos as well here
379:                        }
380:                    }
381:                }
382:
383:                if (form
384:                        .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_ISOLATED)) {
385:                    return glyphForm.equals(SVGConstants.SVG_ISOLATED_VALUE);
386:                }
387:                if (form
388:                        .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)) {
389:                    return glyphForm.equals(SVGConstants.SVG_TERMINAL_VALUE);
390:                }
391:                if (form
392:                        .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL)) {
393:                    return glyphForm.equals(SVGConstants.SVG_INITIAL_VALUE);
394:                }
395:                if (form
396:                        .equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)) {
397:                    return glyphForm.equals(SVGConstants.SVG_MEDIAL_VALUE);
398:                }
399:                return false;
400:            }
401:
402:            /**
403:             * Indicates whether or not the specified glyph can be displayed by this
404:             * font.
405:             *
406:             * @param name The name of the glyph to check.
407:             *
408:             * @return true if the glyph can be displayed.
409:             */
410:            public boolean canDisplayGivenName(String name) {
411:                for (int i = 0; i < glyphNames.length; i++) {
412:                    if (glyphNames[i] != null && glyphNames[i].equals(name)
413:                            && languageMatches(glyphLangs[i])
414:                            && orientationMatches(glyphOrientations[i])) {
415:                        return true;
416:                    }
417:                }
418:                return false;
419:            }
420:
421:            /**
422:             * Indicates whether or not the specified character can be
423:             * displayed by this font.
424:             *
425:             * @param c The character to check.
426:             *
427:             * @return true if the character can be displayed.
428:             */
429:            public boolean canDisplay(char c) {
430:                for (int i = 0; i < glyphUnicodes.length; i++) {
431:                    if (glyphUnicodes[i].indexOf(c) != -1
432:                            && languageMatches(glyphLangs[i])
433:                            && orientationMatches(glyphOrientations[i])) {
434:                        return true;
435:                    }
436:                }
437:                return false;
438:            }
439:
440:            /**
441:             * Checks whether this Font can display the characters in the
442:             * specified character array starting at start and ending at limit.
443:             *
444:             * @param text An array containing the characters to check.
445:             * @param start The index of the first character to check.
446:             * @param limit The index of the last character to check.
447:             *
448:             * @return The index of the first character it can't display or -1 if
449:             * it can display the whole string.
450:             */
451:            public int canDisplayUpTo(char[] text, int start, int limit) {
452:                StringCharacterIterator sci = new StringCharacterIterator(
453:                        new String(text));
454:                return canDisplayUpTo(sci, start, limit);
455:            }
456:
457:            /**
458:             * Checks whether this Font can display the characters in the
459:             * specified character iterator starting at start and ending at limit.
460:             *
461:             * @param iter The iterator containing the characters to check.
462:             * @param start The index of the first character to check.
463:             * @param limit The index of the last character to check.
464:             *
465:             * @return The index of the first character it can't display or -1 if
466:             * it can display the whole string.
467:             */
468:            public int canDisplayUpTo(CharacterIterator iter, int start,
469:                    int limit) {
470:
471:                AttributedCharacterIterator aci = null;
472:                if (iter instanceof  AttributedCharacterIterator) {
473:                    aci = (AttributedCharacterIterator) iter;
474:                }
475:
476:                char c = iter.setIndex(start);
477:                int currentIndex = start;
478:
479:                while (c != CharacterIterator.DONE && currentIndex < limit) {
480:
481:                    boolean foundMatchingGlyph = false;
482:
483:                    for (int i = 0; i < glyphUnicodes.length; i++) {
484:                        if (glyphUnicodes[i].indexOf(c) == 0
485:                                && languageMatches(glyphLangs[i])
486:                                && orientationMatches(glyphOrientations[i])
487:                                && formMatches(glyphUnicodes[i], glyphForms[i],
488:                                        aci, currentIndex)) {
489:                            // found a possible match
490:
491:                            if (glyphUnicodes[i].length() == 1) { // not a ligature
492:                                foundMatchingGlyph = true;
493:                                break;
494:
495:                            } else {
496:                                // glyphCodes[i] is a ligature so try and
497:                                // match the rest of the glyphCode chars
498:                                boolean matched = true;
499:                                for (int j = 1; j < glyphUnicodes[i].length(); j++) {
500:                                    c = iter.next();
501:                                    if (glyphUnicodes[i].charAt(j) != c) {
502:                                        matched = false;
503:                                        break;
504:                                    }
505:                                }
506:                                if (matched) { // found a matching ligature!
507:                                    foundMatchingGlyph = true;
508:                                    break;
509:
510:                                } else {
511:                                    // did not match ligature, keep looking
512:                                    // for another glyph
513:                                    c = iter.setIndex(currentIndex);
514:                                }
515:                            }
516:                        }
517:                    }
518:                    if (!foundMatchingGlyph) {
519:                        return currentIndex;
520:                    }
521:                    c = iter.next();
522:                    currentIndex = iter.getIndex();
523:                }
524:                return -1;
525:            }
526:
527:            /**
528:             * Checks whether or not this font can display the characters in the
529:             * specified String.
530:             *
531:             * @param str The string containing the characters to check.
532:             *
533:             * @return The index of the first character it can't display or -1 if
534:             * it can display the whole string.
535:             */
536:            public int canDisplayUpTo(String str) {
537:                StringCharacterIterator sci = new StringCharacterIterator(str);
538:                return canDisplayUpTo(sci, 0, str.length());
539:            }
540:
541:            /**
542:             * Returns a new GVTGlyphVector object for the specified array of
543:             * characters.
544:             *
545:             * @param frc The current font render context.
546:             * @param chars The array of chars that the glyph vector will represent.
547:             *
548:             * @return The new glyph vector.
549:             */
550:            public GVTGlyphVector createGlyphVector(FontRenderContext frc,
551:                    char[] chars) {
552:                StringCharacterIterator sci = new StringCharacterIterator(
553:                        new String(chars));
554:                return createGlyphVector(frc, sci);
555:            }
556:
557:            /**
558:             * Returns a new GVTGlyphVector object for the characters in the
559:             * specified character iterator.
560:             *
561:             * @param frc The current font render context.
562:             * @param ci The character iterator that the glyph vector will represent.
563:             *
564:             * @return The new glyph vector.
565:             */
566:            public GVTGlyphVector createGlyphVector(FontRenderContext frc,
567:                    CharacterIterator ci) {
568:
569:                AttributedCharacterIterator aci = null;
570:                if (ci instanceof  AttributedCharacterIterator) {
571:                    aci = (AttributedCharacterIterator) ci;
572:                }
573:
574:                List glyphs = new ArrayList();
575:                char c = ci.first();
576:                while (c != CharacterIterator.DONE) {
577:                    boolean foundMatchingGlyph = false;
578:                    for (int i = 0; i < glyphUnicodes.length; i++) {
579:                        if (glyphUnicodes[i].indexOf(c) == 0
580:                                && languageMatches(glyphLangs[i])
581:                                && orientationMatches(glyphOrientations[i])
582:                                && formMatches(glyphUnicodes[i], glyphForms[i],
583:                                        aci, ci.getIndex())) { // found a possible match
584:
585:                            if (glyphUnicodes[i].length() == 1) { // not a ligature
586:                                Element glyphElement = glyphElements[i];
587:                                SVGGlyphElementBridge glyphBridge = (SVGGlyphElementBridge) ctx
588:                                        .getBridge(glyphElement);
589:                                TextPaintInfo tpi = null;
590:                                if (aci != null) {
591:                                    tpi = (TextPaintInfo) aci
592:                                            .getAttribute(PAINT_INFO);
593:                                }
594:                                Glyph glyph = glyphBridge.createGlyph(ctx,
595:                                        glyphElement, textElement, i, fontSize,
596:                                        fontFace, tpi);
597:                                glyphs.add(glyph);
598:                                foundMatchingGlyph = true;
599:                                break;
600:                            } else {
601:                                // glyphCodes[i] is a ligature so try and
602:                                // match the rest of the glyphCode chars
603:                                int current = ci.getIndex();
604:                                boolean matched = true;
605:                                for (int j = 1; j < glyphUnicodes[i].length(); j++) {
606:                                    c = ci.next();
607:                                    if (glyphUnicodes[i].charAt(j) != c) {
608:                                        matched = false;
609:                                        break;
610:                                    }
611:                                }
612:                                if (matched) { // found a matching ligature!
613:
614:                                    Element glyphElement = glyphElements[i];
615:                                    SVGGlyphElementBridge glyphBridge = (SVGGlyphElementBridge) ctx
616:                                            .getBridge(glyphElement);
617:                                    TextPaintInfo tpi = null;
618:                                    if (aci != null) {
619:                                        aci.setIndex(ci.getIndex());
620:                                        tpi = (TextPaintInfo) aci
621:                                                .getAttribute(PAINT_INFO);
622:                                    }
623:                                    Glyph glyph = glyphBridge.createGlyph(ctx,
624:                                            glyphElement, textElement, i,
625:                                            fontSize, fontFace, tpi);
626:                                    glyphs.add(glyph);
627:                                    foundMatchingGlyph = true;
628:                                    break;
629:
630:                                } else {
631:                                    // did not match ligature, keep looking
632:                                    // for another glyph
633:                                    c = ci.setIndex(current);
634:                                }
635:                            }
636:                        }
637:                    }
638:                    if (!foundMatchingGlyph) {
639:                        // add the missing glyph
640:                        SVGGlyphElementBridge glyphBridge = (SVGGlyphElementBridge) ctx
641:                                .getBridge(missingGlyphElement);
642:                        TextPaintInfo tpi = null;
643:                        if (aci != null) {
644:                            aci.setIndex(ci.getIndex());
645:                            tpi = (TextPaintInfo) aci.getAttribute(PAINT_INFO);
646:                        }
647:                        Glyph glyph = glyphBridge.createGlyph(ctx,
648:                                missingGlyphElement, textElement, -1, fontSize,
649:                                fontFace, tpi);
650:                        glyphs.add(glyph);
651:                    }
652:                    c = ci.next();
653:                }
654:
655:                // turn the vector of glyphs into an array;
656:                int numGlyphs = glyphs.size();
657:
658:                Glyph[] glyphArray = (Glyph[]) glyphs
659:                        .toArray(new Glyph[numGlyphs]);
660:
661:                // return a new SVGGVTGlyphVector
662:                return new SVGGVTGlyphVector(this , glyphArray, frc);
663:            }
664:
665:            /**
666:             * Returns a new GVTGlyphVector object for the glyphs in the
667:             * the glyph code array.
668:             *
669:             * @param frc The current font render context.
670:             * @param glyphCodes An array containin the ids of the glyphs that
671:             * the glyph vector will represent.
672:             *
673:             * @return The new glyph vector.
674:             */
675:            public GVTGlyphVector createGlyphVector(FontRenderContext frc,
676:                    int[] glyphCodes, CharacterIterator ci) {
677:                // construct a string from the glyphCodes
678:                int nGlyphs = glyphCodes.length;
679:                StringBuffer workBuff = new StringBuffer(nGlyphs);
680:                for (int i = 0; i < nGlyphs; i++) {
681:                    workBuff.append(glyphUnicodes[glyphCodes[i]]);
682:                }
683:                StringCharacterIterator sci = new StringCharacterIterator(
684:                        workBuff.toString());
685:                return createGlyphVector(frc, sci);
686:            }
687:
688:            /**
689:             * Returns a new GVTGlyphVector object for the specified String.
690:             *
691:             * @param frc The current font render context.
692:             * @param str The string that the glyph vector will represent.
693:             *
694:             * @return The new glyph vector.
695:             */
696:            public GVTGlyphVector createGlyphVector(FontRenderContext frc,
697:                    String str) {
698:                StringCharacterIterator sci = new StringCharacterIterator(str);
699:                return createGlyphVector(frc, sci);
700:            }
701:
702:            /**
703:             * Creates a new GVTFont object by replicating this font object and
704:             * applying a new size to it.
705:             *
706:             * @param size The size of the new font.
707:             *
708:             * @return The new font object.
709:             */
710:            public GVTFont deriveFont(float size) {
711:                return new SVGGVTFont(size, fontFace, glyphUnicodes,
712:                        glyphNames, glyphLangs, glyphOrientations, glyphForms,
713:                        ctx, glyphElements, missingGlyphElement, hkernElements,
714:                        vkernElements, textElement);
715:            }
716:
717:            public String getFamilyName() {
718:                return fontFace.getFamilyName();
719:            }
720:
721:            protected GVTLineMetrics getLineMetrics(int beginIndex, int limit) {
722:                if (lineMetrics != null)
723:                    return lineMetrics;
724:
725:                float fontHeight = fontFace.getUnitsPerEm();
726:                float scale = fontSize / fontHeight;
727:
728:                float ascent = fontFace.getAscent() * scale;
729:                float descent = fontFace.getDescent() * scale;
730:
731:                float[] baselineOffsets = new float[3];
732:                baselineOffsets[Font.ROMAN_BASELINE] = 0;
733:                baselineOffsets[Font.CENTER_BASELINE] = (ascent + descent) / 2
734:                        - ascent;
735:                baselineOffsets[Font.HANGING_BASELINE] = -ascent;
736:
737:                float stOffset = fontFace.getStrikethroughPosition() * -scale;
738:                float stThickness = fontFace.getStrikethroughThickness()
739:                        * scale;
740:                float ulOffset = fontFace.getUnderlinePosition() * scale;
741:                float ulThickness = fontFace.getUnderlineThickness() * scale;
742:                float olOffset = fontFace.getOverlinePosition() * -scale;
743:                float olThickness = fontFace.getOverlineThickness() * scale;
744:
745:                lineMetrics = new GVTLineMetrics(ascent, Font.ROMAN_BASELINE,
746:                        baselineOffsets, descent, fontHeight, fontHeight, limit
747:                                - beginIndex, stOffset, stThickness, ulOffset,
748:                        ulThickness, olOffset, olThickness);
749:                return lineMetrics;
750:            }
751:
752:            /**
753:             * Returns the line metrics for the specified text.
754:             *
755:             * @param chars The character array containing the text.
756:             * @param beginIndex The index of the first character.
757:             * @param limit The limit of characters.
758:             * @param frc The current font render context.
759:             *
760:             * @return The new GVTLineMetrics object.
761:             */
762:            public GVTLineMetrics getLineMetrics(char[] chars, int beginIndex,
763:                    int limit, FontRenderContext frc) {
764:                return getLineMetrics(beginIndex, limit);
765:            }
766:
767:            /**
768:             * Returns the line metrics for the specified text.
769:             *
770:             * @param ci The character iterator containing the text.
771:             * @param beginIndex The index of the first character.
772:             * @param limit The limit of characters.
773:             * @param frc The current font render context.
774:             *
775:             * @return The new GVTLineMetrics object.
776:             */
777:            public GVTLineMetrics getLineMetrics(CharacterIterator ci,
778:                    int beginIndex, int limit, FontRenderContext frc) {
779:                return getLineMetrics(beginIndex, limit);
780:            }
781:
782:            /**
783:             * Returns the line metrics for the specified text.
784:             *
785:             * @param str The string containing the text.
786:             * @param frc The current font render context.
787:             *
788:             * @return The new GVTLineMetrics object.
789:             */
790:            public GVTLineMetrics getLineMetrics(String str,
791:                    FontRenderContext frc) {
792:                StringCharacterIterator sci = new StringCharacterIterator(str);
793:                return getLineMetrics(sci, 0, str.length(), frc);
794:            }
795:
796:            /**
797:             * Returns the line metrics for the specified text.
798:             *
799:             * @param str The string containing the text.
800:             * @param beginIndex The index of the first character.
801:             * @param limit The limit of characters.
802:             * @param frc The current font render context.
803:             *
804:             * @return The new GVTLineMetrics object.
805:             */
806:            public GVTLineMetrics getLineMetrics(String str, int beginIndex,
807:                    int limit, FontRenderContext frc) {
808:                StringCharacterIterator sci = new StringCharacterIterator(str);
809:                return getLineMetrics(sci, beginIndex, limit, frc);
810:            }
811:
812:            /**
813:             * Returns the size of this font.
814:             *
815:             * @return The font size.
816:             */
817:            public float getSize() {
818:                return fontSize;
819:            }
820:
821:            /**
822:             * Returns a string representation of this font.
823:             * This is for debugging purposes only.
824:             *
825:             * @return A string representation of this font.
826:             */
827:            public String toString() {
828:                return fontFace.getFamilyName() + " "
829:                        + fontFace.getFontWeight() + " "
830:                        + fontFace.getFontStyle();
831:            }
832:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.