FontDetails.java

1
/*
2
 * $Id: FontDetails.java 4024 2009-07-12 00:33:57Z xlv $
3
 *
4
 * Copyright 2001, 2002 by Paulo Soares.
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * (the "License"); you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9
 *
10
 * Software distributed under the License is distributed on an "AS IS" basis,
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
 * for the specific language governing rights and limitations under the License.
13
 *
14
 * The Original Code is 'iText, a free JAVA-PDF library'.
15
 *
16
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18
 * All Rights Reserved.
19
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21
 *
22
 * Contributor(s): all the names of the contributors are added in the source code
23
 * where applicable.
24
 *
25
 * Alternatively, the contents of this file may be used under the terms of the
26
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27
 * provisions of LGPL are applicable instead of those above.  If you wish to
28
 * allow use of your version of this file only under the terms of the LGPL
29
 * License and not to allow others to use your version of this file under
30
 * the MPL, indicate your decision by deleting the provisions above and
31
 * replace them with the notice and other provisions required by the LGPL.
32
 * If you do not delete the provisions above, a recipient may use your version
33
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34
 *
35
 * This library is free software; you can redistribute it and/or modify it
36
 * under the terms of the MPL as stated above or under the terms of the GNU
37
 * Library General Public License as published by the Free Software Foundation;
38
 * either version 2 of the License, or any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful, but WITHOUT
41
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42
 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43
 * details.
44
 *
45
 * If you didn't download this code from the following link, you should check if
46
 * you aren't using an obsolete version:
47
 * http://www.lowagie.com/iText/
48
 */
49
50
package com.lowagie.text.pdf;
51
52
import java.awt.font.GlyphVector;
53
import java.io.UnsupportedEncodingException;
54
import java.util.HashMap;
55
56
57
import com.lowagie.text.Utilities;
58
import com.lowagie.text.ExceptionConverter;
59
60
/**
61
 * Each font in the document will have an instance of this class
62
 * where the characters used will be represented.
63
 *
64
 * @author  Paulo Soares (psoares@consiste.pt)
65
 */
66
class FontDetails {
67
    
68
    /**
69
     * The indirect reference to this font
70
     */    
71
    PdfIndirectReference indirectReference;
72
    /**
73
     * The font name that appears in the document body stream
74
     */    
75
    PdfName fontName;
76
    /**
77
     * The font
78
     */    
79
    BaseFont baseFont;
80
    /**
81
     * The font if it's an instance of <CODE>TrueTypeFontUnicode</CODE>
82
     */    
83
    TrueTypeFontUnicode ttu;
84
    /**
85
     * The font if it's an instance of <CODE>CJKFont</CODE>
86
     */
87
    CJKFont cjkFont;
88
    /**
89
     * The array used with single byte encodings
90
     */
91
    byte[] shortTag;
92
    /**
93
     * The map used with double byte encodings. The key is Integer(glyph) and
94
     * the value is int[]{glyph, width, Unicode code}
95
     */    
96
    HashMap longTag;
97
    /**
98
     * IntHashtable with CIDs of CJK glyphs that are used in the text.
99
     */
100
    IntHashtable cjkTag;
101
    /**
102
     * The font type
103
     */    
104
    int fontType;
105
    /**
106
     * <CODE>true</CODE> if the font is symbolic
107
     */    
108
    boolean symbolic;
109
    /**
110
     * Indicates if only a subset of the glyphs and widths for that particular
111
     * encoding should be included in the document.
112
     */
113
    protected boolean subset = true;
114
    
115
    /**
116
     * Each font used in a document has an instance of this class.
117
     * This class stores the characters used in the document and other
118
     * specifics unique to the current working document.
119
     * @param fontName the font name
120
     * @param indirectReference the indirect reference to the font
121
     * @param baseFont the <CODE>BaseFont</CODE>
122
     */
123
    FontDetails(PdfName fontName, PdfIndirectReference indirectReference, BaseFont baseFont) {
124
        this.fontName = fontName;
125
        this.indirectReference = indirectReference;
126
        this.baseFont = baseFont;
127
        fontType = baseFont.getFontType();
128
        switch (fontType) {
129
            case BaseFont.FONT_TYPE_T1:
130
            case BaseFont.FONT_TYPE_TT:
131
                shortTag = new byte[256];
132
                break;
133
            case BaseFont.FONT_TYPE_CJK:
134
                cjkTag = new IntHashtable();
135
                cjkFont = (CJKFont)baseFont;
136
                break;
137
            case BaseFont.FONT_TYPE_TTUNI:
138
                longTag = new HashMap();
139
                ttu = (TrueTypeFontUnicode)baseFont;
140
                symbolic = baseFont.isFontSpecific();
141
                break;
142
        }
143
    }
144
    
145
    /**
146
     * Gets the indirect reference to this font.
147
     * @return the indirect reference to this font
148
     */    
149
    PdfIndirectReference getIndirectReference() {
150
        return indirectReference;
151
    }
152
    
153
    /**
154
     * Gets the font name as it appears in the document body.
155
     * @return the font name
156
     */    
157
    PdfName getFontName() {
158
        return fontName;
159
    }
160
    
161
    /**
162
     * Gets the <CODE>BaseFont</CODE> of this font.
163
     * @return the <CODE>BaseFont</CODE> of this font
164
     */    
165
    BaseFont getBaseFont() {
166
        return baseFont;
167
    }
168
    
169
    /**
170
     * Converts the text into bytes to be placed in the document.
171
     * The conversion is done according to the font and the encoding and the characters
172
     * used are stored.
173
     * @param text the text to convert
174
     * @return the conversion
175
     */    
176
    byte[] convertToBytes(String text) {
177
        byte[] b = null;
178
        switch (fontType) {
179
            case BaseFont.FONT_TYPE_T3:
180 1 1. convertToBytes : mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
                return baseFont.convertToBytes(text);
181
            case BaseFont.FONT_TYPE_T1:
182
            case BaseFont.FONT_TYPE_TT: {
183
                b = baseFont.convertToBytes(text);
184
                int len = b.length;
185 1 1. convertToBytes : Replaced bitwise AND with OR → NO_COVERAGE
                for (byte b1 : b) shortTag[b1 & 0xff] = 1;
186
                break;
187
            }
188
            case BaseFont.FONT_TYPE_CJK: {
189
                int len = text.length();
190 3 1. convertToBytes : changed conditional boundary → NO_COVERAGE
2. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
3. convertToBytes : negated conditional → NO_COVERAGE
                for (int k = 0; k < len; ++k)
191
                    cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
192
                b = baseFont.convertToBytes(text);
193
                break;
194
            }
195
            case BaseFont.FONT_TYPE_DOCUMENT: {
196
                b = baseFont.convertToBytes(text);
197
                break;
198
            }
199
            case BaseFont.FONT_TYPE_TTUNI: {
200
                try {
201
                    int len = text.length();
202
                    int[] metrics = null;
203
                    char[] glyph = new char[len];
204
                    int i = 0;
205 1 1. convertToBytes : negated conditional → NO_COVERAGE
                    if (symbolic) {
206
                        b = PdfEncodings.convertToBytes(text, "symboltt");
207
                        len = b.length;
208 3 1. convertToBytes : changed conditional boundary → NO_COVERAGE
2. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
3. convertToBytes : negated conditional → NO_COVERAGE
                        for (int k = 0; k < len; ++k) {
209 1 1. convertToBytes : Replaced bitwise AND with OR → NO_COVERAGE
                            metrics = ttu.getMetricsTT(b[k] & 0xff);
210 1 1. convertToBytes : negated conditional → NO_COVERAGE
                            if (metrics == null)
211
                                continue;
212 1 1. convertToBytes : Replaced bitwise AND with OR → NO_COVERAGE
                            longTag.put(metrics[0], new int[]{metrics[0], metrics[1], ttu.getUnicodeDifferences(b[k] & 0xff)});
213
                            glyph[i++] = (char)metrics[0];
214
                        }
215
                    }
216
                    else {
217 3 1. convertToBytes : changed conditional boundary → NO_COVERAGE
2. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
3. convertToBytes : negated conditional → NO_COVERAGE
                        for (int k = 0; k < len; ++k) {
218
                            int val;
219 1 1. convertToBytes : negated conditional → NO_COVERAGE
                            if (Utilities.isSurrogatePair(text, k)) {
220
                                val = Utilities.convertToUtf32(text, k);
221 1 1. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
                                k++;
222
                            }
223
                            else {
224
                                val = text.charAt(k);
225
                            }
226
                            metrics = ttu.getMetricsTT(val);
227 1 1. convertToBytes : negated conditional → NO_COVERAGE
                            if (metrics == null)
228
                                continue;
229
                            int m0 = metrics[0];
230
                            Integer gl = m0;
231 1 1. convertToBytes : negated conditional → NO_COVERAGE
                            if (!longTag.containsKey(gl))
232
                                longTag.put(gl, new int[]{m0, metrics[1], val});
233
                            glyph[i++] = (char)m0;
234
                        }
235
                    }
236
                    String s = new String(glyph, 0, i);
237
                    b = s.getBytes(CJKFont.CJK_ENCODING);
238
                }
239
                catch (UnsupportedEncodingException e) {
240
                    throw new ExceptionConverter(e);
241
                }
242
                break;
243
            }
244
        }
245 1 1. convertToBytes : mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return b;
246
    }
247
    
248
    byte[] convertToBytes(GlyphVector glyphVector) {
249 2 1. convertToBytes : negated conditional → NO_COVERAGE
2. convertToBytes : negated conditional → NO_COVERAGE
        if (fontType != BaseFont.FONT_TYPE_TTUNI || symbolic) {
250
            throw new UnsupportedOperationException("Only supported for True Type Unicode fonts");
251
        }
252
253
        char[] glyphs = new char[glyphVector.getNumGlyphs()];
254
        int glyphCount = 0;
255 3 1. convertToBytes : changed conditional boundary → NO_COVERAGE
2. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
3. convertToBytes : negated conditional → NO_COVERAGE
        for (int i = 0; i < glyphs.length; i++) {
256
            int code = glyphVector.getGlyphCode(i);
257 2 1. convertToBytes : negated conditional → NO_COVERAGE
2. convertToBytes : negated conditional → NO_COVERAGE
            if (code == 0xFFFE || code == 0xFFFF) {// considered non-glyphs by
258
                                                    // AWT
259
                continue;
260
            }
261
262 1 1. convertToBytes : Changed increment from 1 to -1 → NO_COVERAGE
            glyphs[glyphCount++] = (char) code;// FIXME supplementary plane?
263
264
            Integer codeKey = code;
265 1 1. convertToBytes : negated conditional → NO_COVERAGE
            if (!longTag.containsKey(codeKey)) {
266
                int glyphWidth = ttu.getGlyphWidth(code);
267
                Integer charCode = ttu.getCharacterCode(code);
268 1 1. convertToBytes : negated conditional → NO_COVERAGE
                int[] metrics = charCode != null ? new int[] { code, glyphWidth, charCode} : new int[] {
269
                        code, glyphWidth };
270
                longTag.put(codeKey, metrics);
271
            }
272
        }
273
274
        String s = new String(glyphs, 0, glyphCount);
275
        try {
276
            byte[] b = s.getBytes(CJKFont.CJK_ENCODING);
277 1 1. convertToBytes : mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
            return b;
278
        } catch (UnsupportedEncodingException e) {
279
            throw new ExceptionConverter(e);
280
        }
281
    }
282
    
283
    
284
    /**
285
     * Writes the font definition to the document.
286
     * @param writer the <CODE>PdfWriter</CODE> of this document
287
     */    
288
    void writeFont(PdfWriter writer) {
289
        try {
290
            switch (fontType) {
291
                case BaseFont.FONT_TYPE_T3:
292 1 1. writeFont : removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE
                    baseFont.writeFont(writer, indirectReference, null);
293
                    break;
294
                case BaseFont.FONT_TYPE_T1:
295
                case BaseFont.FONT_TYPE_TT: {
296
                    int firstChar;
297
                    int lastChar;
298 3 1. writeFont : changed conditional boundary → NO_COVERAGE
2. writeFont : Changed increment from 1 to -1 → NO_COVERAGE
3. writeFont : negated conditional → NO_COVERAGE
                    for (firstChar = 0; firstChar < 256; ++firstChar) {
299 1 1. writeFont : negated conditional → NO_COVERAGE
                        if (shortTag[firstChar] != 0)
300
                            break;
301
                    }
302 3 1. writeFont : changed conditional boundary → NO_COVERAGE
2. writeFont : Changed increment from -1 to 1 → NO_COVERAGE
3. writeFont : negated conditional → NO_COVERAGE
                    for (lastChar = 255; lastChar >= firstChar; --lastChar) {
303 1 1. writeFont : negated conditional → NO_COVERAGE
                        if (shortTag[lastChar] != 0)
304
                            break;
305
                    }
306 2 1. writeFont : changed conditional boundary → NO_COVERAGE
2. writeFont : negated conditional → NO_COVERAGE
                    if (firstChar > 255) {
307
                        firstChar = 255;
308
                        lastChar = 255;
309
                    }
310 1 1. writeFont : removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE
                    baseFont.writeFont(writer, indirectReference, new Object[]{firstChar, lastChar, shortTag, subset});
311
                    break;
312
                }
313
                case BaseFont.FONT_TYPE_CJK:
314 1 1. writeFont : removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE
                    baseFont.writeFont(writer, indirectReference, new Object[]{cjkTag});
315
                    break;
316
                case BaseFont.FONT_TYPE_TTUNI:
317 1 1. writeFont : removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE
                    baseFont.writeFont(writer, indirectReference, new Object[]{longTag, subset});
318
                    break;
319
            }
320
        }
321
        catch(Exception e) {
322
            throw new ExceptionConverter(e);
323
        }
324
    }
325
    
326
    /**
327
     * Indicates if all the glyphs and widths for that particular
328
     * encoding should be included in the document.
329
     * @return <CODE>false</CODE> to include all the glyphs and widths.
330
     */
331
    public boolean isSubset() {
332
        return subset;
333
    }
334
    
335
    /**
336
     * Indicates if all the glyphs and widths for that particular
337
     * encoding should be included in the document. Set to <CODE>false</CODE>
338
     * to include all.
339
     * @param subset new value of property subset
340
     */
341
    public void setSubset(boolean subset) {
342
        this.subset = subset;
343
    }
344
}

Mutations

180

1.1
Location : convertToBytes
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

185

1.1
Location : convertToBytes
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

190

1.1
Location : convertToBytes
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

205

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

208

1.1
Location : convertToBytes
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

209

1.1
Location : convertToBytes
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

210

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

212

1.1
Location : convertToBytes
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

217

1.1
Location : convertToBytes
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

219

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

221

1.1
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

227

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

231

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

245

1.1
Location : convertToBytes
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

249

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

255

1.1
Location : convertToBytes
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

257

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

262

1.1
Location : convertToBytes
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

265

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

268

1.1
Location : convertToBytes
Killed by : none
negated conditional → NO_COVERAGE

277

1.1
Location : convertToBytes
Killed by : none
mutated return of Object value for com/lowagie/text/pdf/FontDetails::convertToBytes to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

292

1.1
Location : writeFont
Killed by : none
removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE

298

1.1
Location : writeFont
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : writeFont
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : writeFont
Killed by : none
negated conditional → NO_COVERAGE

299

1.1
Location : writeFont
Killed by : none
negated conditional → NO_COVERAGE

302

1.1
Location : writeFont
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : writeFont
Killed by : none
Changed increment from -1 to 1 → NO_COVERAGE

3.3
Location : writeFont
Killed by : none
negated conditional → NO_COVERAGE

303

1.1
Location : writeFont
Killed by : none
negated conditional → NO_COVERAGE

306

1.1
Location : writeFont
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : writeFont
Killed by : none
negated conditional → NO_COVERAGE

310

1.1
Location : writeFont
Killed by : none
removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE

314

1.1
Location : writeFont
Killed by : none
removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE

317

1.1
Location : writeFont
Killed by : none
removed call to com/lowagie/text/pdf/BaseFont::writeFont → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.4.2