001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.pdf.font;
031:
032: import java.util.Iterator;
033: import de.intarsys.pdf.cos.COSArray;
034: import de.intarsys.pdf.cos.COSDictionary;
035: import de.intarsys.pdf.cos.COSName;
036: import de.intarsys.pdf.cos.COSNumber;
037: import de.intarsys.pdf.cos.COSObject;
038: import de.intarsys.pdf.encoding.Encoding;
039: import de.intarsys.pdf.encoding.GlyphNameMap;
040: import de.intarsys.pdf.encoding.MappedEncoding;
041:
042: /**
043: * An encoding defined as a delta to another base encoding.
044: *
045: * <p>
046: *
047: * <pre>
048: * the encoding difference is defined in the form
049: * ...
050: * num name name name
051: * num name..
052: * ...
053: * </pre>
054: *
055: * </p>
056: *
057: * <p>
058: * where num is the codepoint for the first glyph name in the list. The
059: * following names are mapped to the codepoint of the predecessor + 1. Multiple
060: * redefinition offsets can be defined.
061: * </p>
062: */
063: public class DifferenceEncoding extends Encoding {
064: //
065: public static final COSName DK_Differences = COSName
066: .constant("Differences");
067:
068: public static final COSName DK_BaseEncoding = COSName
069: .constant("BaseEncoding");
070:
071: // the dictionary object representing the encoding
072: private COSDictionary dict;
073:
074: // the base encoding
075: private Encoding baseEncoding;
076:
077: // the difference declaration
078: private MappedEncoding differenceEncoding;
079:
080: /**
081: * DictionaryEncoding constructor comment.
082: */
083: public DifferenceEncoding() {
084: super ();
085: }
086:
087: /**
088: * Create the difference encoding from the values defined in the
089: * <code>dict</code>.
090: *
091: * <p>
092: * todo 2 remove dependency to font and refactor
093: * </p>
094: *
095: * @param dict
096: * The dictionary defining the difference.
097: * @param font
098: * The font defining the base encoding.
099: *
100: * @return The difference encoding from the values defined in the
101: * <code>dict</code>.
102: */
103: public static Encoding create(COSDictionary dict, PDFont font) {
104: DifferenceEncoding encoding = new DifferenceEncoding();
105: encoding.cosSetDict(dict);
106:
107: COSObject base = dict.get(DK_BaseEncoding);
108: Encoding baseEncoding = null;
109: if (base.isNull()) {
110: baseEncoding = font.createDefaultEncoding();
111: }
112: if (base instanceof COSName) {
113: baseEncoding = Encoding.create((COSName) base);
114: }
115: encoding.setBaseEncoding(baseEncoding);
116: MappedEncoding differenceEncoding = new MappedEncoding();
117: encoding.setDifferenceEncoding(differenceEncoding);
118:
119: COSArray differences = dict.get(DK_Differences).asArray();
120: if (differences != null) {
121: int start = -1;
122: for (Iterator it = differences.iterator(); it.hasNext();) {
123: COSObject element = (COSObject) it.next();
124: if (element instanceof COSNumber) {
125: start = ((COSNumber) element).intValue();
126: }
127: if (element instanceof COSName && (start > -1)) {
128: String name = ((COSName) element).stringValue();
129: differenceEncoding.addEncoding(start, name);
130: start++;
131: }
132: }
133: }
134: return encoding;
135: }
136:
137: /*
138: * (non-Javadoc)
139: *
140: * @see de.intarsys.pdf.font.FontEncoding#getCode(java.lang.String)
141: */
142: public int getByteCode(java.lang.String name) {
143: int code = getDifferenceEncoding().getByteCode(name);
144: if (code == -1) {
145: code = getBaseEncoding().getByteCode(name);
146: }
147: return code;
148: }
149:
150: /*
151: * (non-Javadoc)
152: *
153: * @see de.intarsys.pdf.encoding.Encoding#getDifferenceCode(int)
154: */
155: public int getDifferenceUnicode(int codePoint) {
156: int code = getDifferenceEncoding().getUnicode(codePoint);
157: if (code == -1) {
158: return codePoint;
159: }
160: return code;
161: }
162:
163: /*
164: * (non-Javadoc)
165: *
166: * @see de.intarsys.pdf.encoding.Encoding#getByteCode(int)
167: */
168: public int getByteCode(int unicode) {
169: int code = getDifferenceEncoding().getByteCode(unicode);
170: if (code == -1) {
171: code = getBaseEncoding().getByteCode(unicode);
172: }
173: return code;
174: }
175:
176: /*
177: * (non-Javadoc)
178: *
179: * @see de.intarsys.pdf.encoding.Encoding#getCosObject(de.intarsys.pdf.cos.COSDocument)
180: */
181: public COSObject getCosObject() {
182: return cosGetDict();
183: }
184:
185: /*
186: * (non-Javadoc)
187: *
188: * @see de.intarsys.pdf.font.FontEncoding#getName(int)
189: */
190: public String getGlyphName(int codePoint) {
191: String name = getDifferenceEncoding().getGlyphName(codePoint);
192: if ((name == null) || name.equals(GlyphNameMap.GLYPH_NOTDEF)) {
193: name = getBaseEncoding().getGlyphName(codePoint);
194: }
195: return name;
196: }
197:
198: public String getDifferenceGlyphName(int codePoint) {
199: String name = getDifferenceEncoding().getGlyphName(codePoint);
200: if ((name == null) || name.equals(GlyphNameMap.GLYPH_NOTDEF)) {
201: return null;
202: }
203: return name;
204: }
205:
206: /*
207: * (non-Javadoc)
208: *
209: * @see de.intarsys.pdf.encoding.Encoding#getName()
210: */
211: public String getName() {
212: return "DifferenceEncoding";
213: }
214:
215: /*
216: * (non-Javadoc)
217: *
218: * @see de.intarsys.pdf.encoding.Encoding#getUnicode(int)
219: */
220: public int getUnicode(int byteCode) {
221: int code = getDifferenceEncoding().getUnicode(byteCode);
222: if (code == -1) {
223: code = getBaseEncoding().getUnicode(byteCode);
224: }
225: return code;
226: }
227:
228: /*
229: * (non-Javadoc)
230: *
231: * @see de.intarsys.pdf.encoding.Encoding#getValidByteCode(java.lang.String)
232: */
233: public int getValidByteCode(java.lang.String name) {
234: int code = getDifferenceEncoding().getByteCode(name);
235: if (code == -1) {
236: code = getBaseEncoding().getValidByteCode(name);
237: }
238: return code;
239: }
240:
241: /*
242: * (non-Javadoc)
243: *
244: * @see de.intarsys.pdf.encoding.Encoding#getValidByteCode(int)
245: */
246: public int getValidByteCode(int unicode) {
247: int code = getDifferenceEncoding().getByteCode(unicode);
248: if (code == -1) {
249: code = getBaseEncoding().getValidByteCode(unicode);
250: }
251: return code;
252: }
253:
254: /**
255: * Return the base encoding against which we defined the difference.
256: *
257: * @return Return the base encoding against which we defined the difference.
258: */
259: protected Encoding getBaseEncoding() {
260: return baseEncoding;
261: }
262:
263: /**
264: * Set the {@link MappedEncoding} decoded from the differences dictionary.
265: *
266: * @param newDifferenceEncoding
267: * The {@link MappedEncoding} decoded from the differences
268: * dictionary.
269: */
270: protected void setDifferenceEncoding(
271: MappedEncoding newDifferenceEncoding) {
272: differenceEncoding = newDifferenceEncoding;
273: }
274:
275: /**
276: * Get the {@link MappedEncoding} built from the differences dictionary.
277: *
278: * @return The {@link MappedEncoding} built from the differences dictionary.
279: */
280: protected MappedEncoding getDifferenceEncoding() {
281: return differenceEncoding;
282: }
283:
284: /**
285: * Return the COSDictionary used to define the difference in the encoding.
286: *
287: * @return Return the COSDictionary used to define the difference in the
288: * encoding.
289: */
290: protected COSDictionary cosGetDict() {
291: return dict;
292: }
293:
294: /**
295: * Set the COSDictionary that defines the difference to the base encoding.
296: *
297: * @param dictionary
298: * The COSDictionary that defines the difference to the base
299: * encoding.
300: */
301: protected void cosSetDict(COSDictionary dictionary) {
302: dict = dictionary;
303: }
304:
305: /**
306: * Set the base encoding against which we defined the difference.
307: *
308: * @param newBaseEncoding
309: * The base encoding against which we defined the difference.
310: */
311: private void setBaseEncoding(Encoding newBaseEncoding) {
312: baseEncoding = newBaseEncoding;
313: }
314:
315: /*
316: * (non-Javadoc)
317: *
318: * @see de.intarsys.pdf.encoding.Encoding#isFontSpecificEncoding()
319: */
320: public boolean isFontSpecificEncoding() {
321: return getBaseEncoding().isFontSpecificEncoding();
322: }
323: }
|