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.util.StringTokenizer;
022: import java.util.List;
023: import java.util.ArrayList;
024:
025: import org.apache.batik.gvt.font.Kern;
026: import org.apache.batik.gvt.font.UnicodeRange;
027: import org.w3c.dom.Element;
028:
029: /**
030: * A base Bridge class for the kerning elements.
031: *
032: * @author <a href="mailto:dean.jackson@cmis.csiro.au">Dean Jackson</a>
033: * @version $Id: SVGKernElementBridge.java 478160 2006-11-22 13:35:06Z dvholten $
034: */
035: public abstract class SVGKernElementBridge extends AbstractSVGBridge {
036:
037: /**
038: * Creates a Kern object that repesents the specified kerning element.
039: *
040: * @param ctx The bridge context.
041: * @param kernElement The kerning element. Should be either a <hkern>
042: * or <vkern> element.
043: * @param font The font the kerning is related to.
044: *
045: * @return kern The new Kern object
046: */
047: public Kern createKern(BridgeContext ctx, Element kernElement,
048: SVGGVTFont font) {
049:
050: // read all of the kern attributes
051: String u1 = kernElement.getAttributeNS(null, SVG_U1_ATTRIBUTE);
052: String u2 = kernElement.getAttributeNS(null, SVG_U2_ATTRIBUTE);
053: String g1 = kernElement.getAttributeNS(null, SVG_G1_ATTRIBUTE);
054: String g2 = kernElement.getAttributeNS(null, SVG_G2_ATTRIBUTE);
055: String k = kernElement.getAttributeNS(null, SVG_K_ATTRIBUTE);
056: if (k.length() == 0) {
057: k = SVG_KERN_K_DEFAULT_VALUE;
058: }
059:
060: // get the kern float value
061: float kernValue = Float.parseFloat(k);
062:
063: // set up the first and second glyph sets and unicode ranges
064: int firstGlyphLen = 0, secondGlyphLen = 0;
065: int[] firstGlyphSet = null;
066: int[] secondGlyphSet = null;
067: List firstUnicodeRanges = new ArrayList();
068: List secondUnicodeRanges = new ArrayList();
069:
070: // process the u1 attribute
071: StringTokenizer st = new StringTokenizer(u1, ",");
072: while (st.hasMoreTokens()) {
073: String token = st.nextToken();
074: if (token.startsWith("U+")) { // its a unicode range
075: firstUnicodeRanges.add(new UnicodeRange(token));
076: } else {
077: int[] glyphCodes = font.getGlyphCodesForUnicode(token);
078: if (firstGlyphSet == null) {
079: firstGlyphSet = glyphCodes;
080: firstGlyphLen = glyphCodes.length;
081: } else {
082: if ((firstGlyphLen + glyphCodes.length) > firstGlyphSet.length) {
083: int sz = firstGlyphSet.length * 2;
084: if (sz < firstGlyphLen + glyphCodes.length)
085: sz = firstGlyphLen + glyphCodes.length;
086: int[] tmp = new int[sz];
087: System.arraycopy(firstGlyphSet, 0, tmp, 0,
088: firstGlyphLen);
089: firstGlyphSet = tmp;
090: }
091: for (int i = 0; i < glyphCodes.length; i++)
092: firstGlyphSet[firstGlyphLen++] = glyphCodes[i];
093: }
094: }
095: }
096:
097: // process the u2 attrbute
098: st = new StringTokenizer(u2, ",");
099: while (st.hasMoreTokens()) {
100: String token = st.nextToken();
101: if (token.startsWith("U+")) { // its a unicode range
102: secondUnicodeRanges.add(new UnicodeRange(token));
103: } else {
104: int[] glyphCodes = font.getGlyphCodesForUnicode(token);
105: if (secondGlyphSet == null) {
106: secondGlyphSet = glyphCodes;
107: secondGlyphLen = glyphCodes.length;
108: } else {
109: if ((secondGlyphLen + glyphCodes.length) > secondGlyphSet.length) {
110: int sz = secondGlyphSet.length * 2;
111: if (sz < secondGlyphLen + glyphCodes.length)
112: sz = secondGlyphLen + glyphCodes.length;
113: int[] tmp = new int[sz];
114: System.arraycopy(secondGlyphSet, 0, tmp, 0,
115: secondGlyphLen);
116: secondGlyphSet = tmp;
117: }
118: for (int i = 0; i < glyphCodes.length; i++)
119: secondGlyphSet[secondGlyphLen++] = glyphCodes[i];
120: }
121: }
122: }
123:
124: // process the g1 attribute
125: st = new StringTokenizer(g1, ",");
126: while (st.hasMoreTokens()) {
127: String token = st.nextToken();
128: int[] glyphCodes = font.getGlyphCodesForName(token);
129: if (firstGlyphSet == null) {
130: firstGlyphSet = glyphCodes;
131: firstGlyphLen = glyphCodes.length;
132: } else {
133: if ((firstGlyphLen + glyphCodes.length) > firstGlyphSet.length) {
134: int sz = firstGlyphSet.length * 2;
135: if (sz < firstGlyphLen + glyphCodes.length)
136: sz = firstGlyphLen + glyphCodes.length;
137: int[] tmp = new int[sz];
138: System.arraycopy(firstGlyphSet, 0, tmp, 0,
139: firstGlyphLen);
140: firstGlyphSet = tmp;
141: }
142: for (int i = 0; i < glyphCodes.length; i++)
143: firstGlyphSet[firstGlyphLen++] = glyphCodes[i];
144: }
145: }
146:
147: // process the g2 attribute
148: st = new StringTokenizer(g2, ",");
149: while (st.hasMoreTokens()) {
150: String token = st.nextToken();
151: int[] glyphCodes = font.getGlyphCodesForName(token);
152: if (secondGlyphSet == null) {
153: secondGlyphSet = glyphCodes;
154: secondGlyphLen = glyphCodes.length;
155: } else {
156: if ((secondGlyphLen + glyphCodes.length) > secondGlyphSet.length) {
157: int sz = secondGlyphSet.length * 2;
158: if (sz < secondGlyphLen + glyphCodes.length)
159: sz = secondGlyphLen + glyphCodes.length;
160: int[] tmp = new int[sz];
161: System.arraycopy(secondGlyphSet, 0, tmp, 0,
162: secondGlyphLen);
163: secondGlyphSet = tmp;
164: }
165: for (int i = 0; i < glyphCodes.length; i++)
166: secondGlyphSet[secondGlyphLen++] = glyphCodes[i];
167: }
168: }
169:
170: // construct the arrays
171: int[] firstGlyphs;
172: if ((firstGlyphLen == 0)
173: || (firstGlyphLen == firstGlyphSet.length)) {
174: firstGlyphs = firstGlyphSet;
175: } else {
176: firstGlyphs = new int[firstGlyphLen];
177: System.arraycopy(firstGlyphSet, 0, firstGlyphs, 0,
178: firstGlyphLen);
179: }
180: int[] secondGlyphs;
181: if ((secondGlyphLen == 0)
182: || (secondGlyphLen == secondGlyphSet.length)) {
183: secondGlyphs = secondGlyphSet;
184: } else {
185: secondGlyphs = new int[secondGlyphLen];
186: System.arraycopy(secondGlyphSet, 0, secondGlyphs, 0,
187: secondGlyphLen);
188: }
189:
190: UnicodeRange[] firstRanges;
191: firstRanges = new UnicodeRange[firstUnicodeRanges.size()];
192: firstUnicodeRanges.toArray(firstRanges);
193:
194: UnicodeRange[] secondRanges;
195: secondRanges = new UnicodeRange[secondUnicodeRanges.size()];
196: secondUnicodeRanges.toArray(secondRanges);
197:
198: // return the new Kern object
199: return new Kern(firstGlyphs, secondGlyphs, firstRanges,
200: secondRanges, kernValue);
201: }
202: }
|