jdk/src/share/classes/sun/font/Type1Font.java
author malenkov
Tue, 29 Oct 2013 17:01:06 +0400
changeset 21278 ef8a3a2a72f2
parent 9035 1255eb81cc2f
child 23010 6dadb192ad81
child 23288 b7183846db97
permissions -rw-r--r--
8022746: List of spelling errors in API doc Reviewed-by: alexsch, smarks
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
9035
1255eb81cc2f 7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents: 8813
diff changeset
     2
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3928
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3928
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3928
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3928
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3928
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.ref.WeakReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.FontFormatException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.FileNotFoundException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.io.RandomAccessFile;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.io.UnsupportedEncodingException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.lang.ref.WeakReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.nio.ByteBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.nio.ByteOrder;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.nio.MappedByteBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.nio.BufferUnderflowException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.nio.channels.ClosedChannelException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.nio.channels.FileChannel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import sun.java2d.Disposer;
2609
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    42
import sun.java2d.DisposerRecord;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.HashSet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.HashMap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import java.awt.Font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * Adobe Technical Note 5040 details the format of PFB files.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * the file is divided into ascii and binary sections. Each section
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * starts with a header
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * 0x8001 - start of binary data, is followed by 4 bytes length, then data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * 0x8002 - start of ascii data, is followed by 4 bytes length, then data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * 0x8003 - end of data segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * The length is organised as LSB->MSB.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * Note: I experimented with using a MappedByteBuffer and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * there were two problems/questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * 1. If a global buffer is used rather than one allocated in the calling
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * context, then we need to synchronize on all uses of that data, which
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * means more code would beed to be synchronized with probable repercussions
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * elsewhere.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * 2. It is not clear whether to free the buffer when the file is closed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * If we have the contents in memory then why keep open files around?
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * The mmapped buffer doesn't need it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * Also regular GC is what frees the buffer. So closing the file and nulling
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * out the reference still needs to wait for the buffer to be GC'd to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * reclaim the storage.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * If the contents of the buffer are persistent there's no need
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * to worry about synchronization.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * Perhaps could use a WeakReference, and when its referent is gone, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * need it can just reopen the file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * Type1 fonts thus don't use up file descriptor references, but can
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * use memory footprint in a way that's managed by the host O/S.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * The main "pain" may be the different model means code needs to be written
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * without assumptions as to how this is handled by the different subclasses
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * of FileFont.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
public class Type1Font extends FileFont {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
2609
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    80
     private static class T1DisposerRecord  implements DisposerRecord {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    81
        String fileName = null;
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    82
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    83
        T1DisposerRecord(String name) {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    84
            fileName = name;
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    85
        }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    86
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    87
        public synchronized void dispose() {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    88
            java.security.AccessController.doPrivileged(
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    89
                new java.security.PrivilegedAction() {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    90
                    public Object run() {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    91
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    92
                        if (fileName != null) {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    93
                            (new java.io.File(fileName)).delete();
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    94
                        }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    95
                        return null;
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    96
                    }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    97
             });
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    98
        }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
    99
    }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   100
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    WeakReference bufferRef = new WeakReference(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    private String psName = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    static private HashMap styleAbbreviationsMapping;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    static private HashSet styleNameTokes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
        styleAbbreviationsMapping = new HashMap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        styleNameTokes = new HashSet();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        /* These abbreviation rules are taken from Appendix 1 of Adobe Technical Note #5088 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
        /* NB: this list is not complete - we did not include abbreviations which contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
               several capital letters because current expansion algorithm do not support this.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
               (namely we have omited MM aka "Multiple Master", OsF aka "Oldstyle figures",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                           OS aka "Oldstyle", SC aka "Small caps" and  DS aka "Display" */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        String nm[] = {"Black", "Bold", "Book", "Demi", "Heavy", "Light",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
                       "Meduium", "Nord", "Poster", "Regular", "Super", "Thin",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
                       "Compressed", "Condensed", "Compact", "Extended", "Narrow",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                       "Inclined", "Italic", "Kursiv", "Oblique", "Upright", "Sloped",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                       "Semi", "Ultra", "Extra",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
                       "Alternate", "Alternate", "Deutsche Fraktur", "Expert", "Inline", "Ornaments",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
                       "Outline", "Roman", "Rounded", "Script", "Shaded", "Swash", "Titling", "Typewriter"};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
        String abbrv[] = {"Blk", "Bd", "Bk", "Dm", "Hv", "Lt",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                          "Md", "Nd", "Po", "Rg", "Su", "Th",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                          "Cm", "Cn", "Ct", "Ex", "Nr",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
                          "Ic", "It", "Ks", "Obl", "Up", "Sl",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                          "Sm", "Ult", "X",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                          "A", "Alt", "Dfr", "Exp", "In", "Or",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                          "Ou", "Rm", "Rd", "Scr", "Sh", "Sw", "Ti", "Typ"};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
       /* This is only subset of names from nm[] because we want to distinguish things
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
           like "Lucida Sans TypeWriter Bold" and "Lucida Sans Bold".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
           Names from "Design and/or special purpose" group are omitted. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
       String styleTokens[] = {"Black", "Bold", "Book", "Demi", "Heavy", "Light",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                       "Medium", "Nord", "Poster", "Regular", "Super", "Thin",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                       "Compressed", "Condensed", "Compact", "Extended", "Narrow",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                       "Inclined", "Italic", "Kursiv", "Oblique", "Upright", "Sloped", "Slanted",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                       "Semi", "Ultra", "Extra"};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        for(int i=0; i<nm.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            styleAbbreviationsMapping.put(abbrv[i], nm[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        for(int i=0; i<styleTokens.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            styleNameTokes.add(styleTokens[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    /**
2609
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   150
     * Constructs a Type1 Font.
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   151
     * @param platname - Platform identifier of the font. Typically file name.
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   152
     * @param nativeNames - Native names - typically XLFDs on Unix.
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   153
     */
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   154
    public Type1Font(String platname, Object nativeNames)
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   155
        throws FontFormatException {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   156
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   157
        this(platname, nativeNames, false);
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   158
    }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   159
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   160
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
     * - does basic verification of the file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
     * - reads the names (full, family).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
     * - determines the style of the font.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
     * @throws FontFormatException - if the font can't be opened
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
     * or fails verification,  or there's no usable cmap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     */
2609
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   167
    public Type1Font(String platname, Object nativeNames, boolean createdCopy)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        super(platname, nativeNames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        fontRank = Font2D.TYPE1_RANK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        checkedNatives = true;
2609
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   172
        try {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   173
            verify();
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   174
        } catch (Throwable t) {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   175
            if (createdCopy) {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   176
                T1DisposerRecord ref = new T1DisposerRecord(platname);
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   177
                Disposer.addObjectRecord(bufferRef, ref);
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   178
                bufferRef = null;
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   179
            }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   180
            if (t instanceof FontFormatException) {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   181
                throw (FontFormatException)t;
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   182
            } else {
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   183
                throw new FontFormatException("Unexpected runtime exception.");
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   184
            }
1db65c97bddc 2163516: Font.createFont can be persuaded to leak temporary files
prr
parents: 558
diff changeset
   185
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
    private synchronized ByteBuffer getBuffer() throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        MappedByteBuffer mapBuf = (MappedByteBuffer)bufferRef.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        if (mapBuf == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
          //System.out.println("open T1 " + platName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                RandomAccessFile raf = (RandomAccessFile)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                java.security.AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                    new java.security.PrivilegedAction() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                        public Object run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                                return new RandomAccessFile(platName, "r");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                            } catch (FileNotFoundException ffne) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                FileChannel fc = raf.getChannel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                fileSize = (int)fc.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                mapBuf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                mapBuf.position(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                bufferRef = new WeakReference(mapBuf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                fc.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
            } catch (NullPointerException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                throw new FontFormatException(e.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            } catch (ClosedChannelException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                /* NIO I/O is interruptible, recurse to retry operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                 * Clear interrupts before recursing in case NIO didn't.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                Thread.interrupted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                return getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                throw new FontFormatException(e.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        return mapBuf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    protected void close() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    /* called from native code to read file into a direct byte buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    void readFile(ByteBuffer buffer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        RandomAccessFile raf = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        FileChannel fc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
            raf = (RandomAccessFile)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                java.security.AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                    new java.security.PrivilegedAction() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                        public Object run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                                return new RandomAccessFile(platName, "r");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                            } catch (FileNotFoundException fnfe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            fc = raf.getChannel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            while (buffer.remaining() > 0 && fc.read(buffer) != -1) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        } catch (NullPointerException npe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        } catch (ClosedChannelException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                if (raf != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                    raf.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                    raf = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
            } catch (IOException ioe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            /* NIO I/O is interruptible, recurse to retry operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
             * Clear interrupts before recursing in case NIO didn't.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
            Thread.interrupted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            readFile(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        } finally  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            if (raf != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                    raf.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    public synchronized ByteBuffer readBlock(int offset, int length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        ByteBuffer mappedBuf = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            mappedBuf = getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            if (offset > fileSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                offset = fileSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            mappedBuf.position(offset);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            return mappedBuf.slice();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        } catch (FontFormatException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    private void verify() throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        /* Normal usage should not call getBuffer(), as its state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
         * ie endianness, position etc, are shared. verify() can do
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
         * this as its called only from within the constructor before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
         * there are other users of this object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        ByteBuffer bb = getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        if (bb.capacity() < 6) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            throw new FontFormatException("short file");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        int val = bb.get(0) & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if ((bb.get(0) & 0xff) == 0x80) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            verifyPFB(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            bb.position(6);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            verifyPFA(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            bb.position(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        initNames(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        if (familyName == null || fullName == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            throw new FontFormatException("Font name not found");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        setStyle();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
    public int getFileSize() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        if (fileSize == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            } catch (FontFormatException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        return fileSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    private void verifyPFA(ByteBuffer bb) throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        if (bb.getShort() != 0x2521) { // 0x2521 is %!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
            throw new FontFormatException("bad pfa font");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        // remind - additional verification needed?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    private void verifyPFB(ByteBuffer bb) throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        int pos = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                int segType = bb.getShort(pos) & 0xffff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                if (segType == 0x8001 || segType == 0x8002) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                    bb.order(ByteOrder.LITTLE_ENDIAN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                    int segLen = bb.getInt(pos+2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                    bb.order(ByteOrder.BIG_ENDIAN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                    if (segLen <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                        throw new FontFormatException("bad segment length");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                    pos += segLen+6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                } else if (segType == 0x8003) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                    throw new FontFormatException("bad pfb file");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
            } catch (BufferUnderflowException bue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                throw new FontFormatException(bue.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                throw new FontFormatException(e.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
    private static final int PSEOFTOKEN = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    private static final int PSNAMETOKEN = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    private static final int PSSTRINGTOKEN = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
    /* Need to parse the ascii contents of the Type1 font file,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     * looking for FullName, FamilyName and FontName.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     * If explicit names are not found then extract them from first text line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     * Operating on bytes so can't use Java String utilities, which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     * is a large part of why this is a hack.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
     * Also check for mandatory FontType and verify if it is supported.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    private void initNames(ByteBuffer bb) throws FontFormatException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        boolean eof = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        String fontType = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
            //Parse font looking for explicit FullName, FamilyName and FontName
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 9035
diff changeset
   371
            //  (according to Type1 spec they are optional)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            while ((fullName == null || familyName == null || psName == null || fontType == null) && !eof) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                int tokenType = nextTokenType(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                if (tokenType == PSNAMETOKEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                    int pos = bb.position();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                    if (bb.get(pos) == 'F') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                        String s = getSimpleToken(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                        if ("FullName".equals(s)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                            if (nextTokenType(bb)==PSSTRINGTOKEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
                                fullName = getString(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                        } else if ("FamilyName".equals(s)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                            if (nextTokenType(bb)==PSSTRINGTOKEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                                familyName = getString(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                        } else if ("FontName".equals(s)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                            if (nextTokenType(bb)==PSNAMETOKEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                                psName = getSimpleToken(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                        } else if ("FontType".equals(s)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                            /* look for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                                 /FontType id def
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                            */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                            String token = getSimpleToken(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                            if ("def".equals(getSimpleToken(bb))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                                fontType = token;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                        while (bb.get() > ' '); // skip token
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                } else if (tokenType == PSEOFTOKEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                    eof = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                throw new FontFormatException(e.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        /* Ignore all fonts besides Type1 (e.g. Type3 fonts) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        if (!"1".equals(fontType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            throw new FontFormatException("Unsupported font type");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
    if (psName == null) { //no explicit FontName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                // Try to extract font name from the first text line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                // According to Type1 spec first line consist of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                //  "%!FontType1-SpecVersion: FontName FontVersion"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                // or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                //  "%!PS-AdobeFont-1.0: FontName version"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                bb.position(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                if (bb.getShort() != 0x2521) { //if pfb (do not start with "%!")
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                    //skip segment header and "%!"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                    bb.position(8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                    //NB: assume that first segment is ASCII one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                    //  (is it possible to have valid Type1 font with first binary segment?)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                String formatType = getSimpleToken(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                if (!formatType.startsWith("FontType1-") && !formatType.startsWith("PS-AdobeFont-")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                        throw new FontFormatException("Unsupported font format [" + formatType + "]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                psName = getSimpleToken(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    //if we got to the end of file then we did not find at least one of FullName or FamilyName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    //Try to deduce missing names from present ones
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
    //NB: At least psName must be already initialized by this moment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        if (eof) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            //if we find fullName or familyName then use it as another name too
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            if (fullName != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                familyName = fullName2FamilyName(fullName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            } else if (familyName != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                fullName = familyName;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            } else { //fallback - use postscript font name to deduce full and family names
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                fullName = psName2FullName(psName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                familyName = psName2FamilyName(psName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
    private String fullName2FamilyName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        String res, token;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        int len, start, end; //length of family name part
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        //FamilyName is truncated version of FullName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        //Truncated tail must contain only style modifiers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
        end = name.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        while (end > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            start = end - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            while (start > 0 && name.charAt(start) != ' ')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
              start--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            //as soon as we meet first non style token truncate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            // current tail and return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                        if (!isStyleToken(name.substring(start+1, end))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                                return name.substring(0, end);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                        end = start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                return name; //should not happen
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    private String expandAbbreviation(String abbr) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
        if (styleAbbreviationsMapping.containsKey(abbr))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                        return (String) styleAbbreviationsMapping.get(abbr);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
        return abbr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    private boolean isStyleToken(String token) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        return styleNameTokes.contains(token);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
    private String psName2FullName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
        String res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        int pos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        //According to Adobe technical note #5088 psName (aka FontName) has form
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        //   <Family Name><VendorID>-<Weight><Width><Slant><Character Set>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        //where spaces are not allowed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        //Conversion: Expand abbreviations in style portion (everything after '-'),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        //            replace '-' with space and insert missing spaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        pos = name.indexOf("-");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        if (pos >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            res =  expandName(name.substring(0, pos), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            res += " " + expandName(name.substring(pos+1), true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            res = expandName(name, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        return res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    private String psName2FamilyName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        String tmp = name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        //According to Adobe technical note #5088 psName (aka FontName) has form
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        //   <Family Name><VendorID>-<Weight><Width><Slant><Character Set>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        //where spaces are not allowed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        //Conversion: Truncate style portion (everything after '-')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
        //            and insert missing spaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        if (tmp.indexOf("-") > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
            tmp = tmp.substring(0, tmp.indexOf("-"));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        return expandName(tmp, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    private int nextCapitalLetter(String s, int off) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        for (; (off >=0) && off < s.length(); off++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            if (s.charAt(off) >= 'A' && s.charAt(off) <= 'Z')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                return off;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
    private String expandName(String s, boolean tryExpandAbbreviations) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        StringBuffer res = new StringBuffer(s.length() + 10);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        int start=0, end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        while(start < s.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            end = nextCapitalLetter(s, start + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            if (end < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                end = s.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
            if (start != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                res.append(" ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            if (tryExpandAbbreviations) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                res.append(expandAbbreviation(s.substring(start, end)));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                res.append(s.substring(start, end));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            start = end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        return res.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    /* skip lines beginning with "%" and leading white space on a line */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    private byte skip(ByteBuffer bb) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        byte b = bb.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        while (b == '%') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                b = bb.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                if (b == '\r' || b == '\n') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        while (b <= ' ') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            b = bb.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        return b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * Token types:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * PSNAMETOKEN - /
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     * PSSTRINGTOKEN - literal text string
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
    private int nextTokenType(ByteBuffer bb) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            byte b = skip(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                if (b == (byte)'/') { // PS defined name follows.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
                    return PSNAMETOKEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
                } else if (b == (byte)'(') { // PS string follows
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                    return PSSTRINGTOKEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
                } else if ((b == (byte)'\r') || (b == (byte)'\n')) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
                b = skip(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                    b = bb.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        } catch (BufferUnderflowException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
            return PSEOFTOKEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
    /* Read simple token (sequence of non-whitespace characters)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
         starting from the current position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
         Skip leading whitespaces (if any). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
    private String getSimpleToken(ByteBuffer bb) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        while (bb.get() <= ' ');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        int pos1 = bb.position()-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        while (bb.get() > ' ');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        int pos2 = bb.position();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        byte[] nameBytes = new byte[pos2-pos1-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        bb.position(pos1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        bb.get(nameBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            return new String(nameBytes, "US-ASCII");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
        } catch (UnsupportedEncodingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            return new String(nameBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
    private String getString(ByteBuffer bb) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        int pos1 = bb.position();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        while (bb.get() != ')');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        int pos2 = bb.position();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
        byte[] nameBytes = new byte[pos2-pos1-1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        bb.position(pos1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
        bb.get(nameBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            return new String(nameBytes, "US-ASCII");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
        } catch (UnsupportedEncodingException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            return new String(nameBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
    public String getPostscriptName() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        return psName;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    protected synchronized FontScaler getScaler() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        if (scaler == null) {
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2624
diff changeset
   638
            scaler = FontScaler.getScaler(this, 0, false, fileSize);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        return scaler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
    CharToGlyphMapper getMapper() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        if (mapper == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            mapper = new Type1GlyphMapper(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        return mapper;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
    public int getNumGlyphs() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            return getScaler().getNumGlyphs();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        } catch (FontScalerException e) {
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2624
diff changeset
   655
            scaler = FontScaler.getNullScaler();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
            return getNumGlyphs();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
    public int getMissingGlyphCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
            return getScaler().getMissingGlyphCode();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        } catch (FontScalerException e) {
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2624
diff changeset
   664
            scaler = FontScaler.getNullScaler();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
            return getMissingGlyphCode();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
    public int getGlyphCode(char charCode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            return getScaler().getGlyphCode(charCode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        } catch (FontScalerException e) {
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2624
diff changeset
   673
            scaler = FontScaler.getNullScaler();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
            return getGlyphCode(charCode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        return "** Type1 Font: Family="+familyName+ " Name="+fullName+
8813
d15a9204c2f0 6985453: Font.createFont may expose some system properties in exception text
bae
parents: 5506
diff changeset
   680
            " style="+style+" fileName="+getPublicFileName();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
}