jdk/src/share/classes/java/awt/Font.java
changeset 2624 1ae5a9028dd4
parent 715 f16baef3a20e
parent 2606 09ad5edb5330
child 3017 217bf37bb0ea
equal deleted inserted replaced
2589:af4853bc7e87 2624:1ae5a9028dd4
    35 import java.awt.geom.Point2D;
    35 import java.awt.geom.Point2D;
    36 import java.awt.geom.Rectangle2D;
    36 import java.awt.geom.Rectangle2D;
    37 import java.awt.peer.FontPeer;
    37 import java.awt.peer.FontPeer;
    38 import java.io.*;
    38 import java.io.*;
    39 import java.lang.ref.SoftReference;
    39 import java.lang.ref.SoftReference;
       
    40 import java.security.AccessController;
       
    41 import java.security.PrivilegedExceptionAction;
    40 import java.text.AttributedCharacterIterator.Attribute;
    42 import java.text.AttributedCharacterIterator.Attribute;
    41 import java.text.CharacterIterator;
    43 import java.text.CharacterIterator;
    42 import java.text.StringCharacterIterator;
    44 import java.text.StringCharacterIterator;
    43 import java.util.HashMap;
    45 import java.util.HashMap;
    44 import java.util.Hashtable;
    46 import java.util.Hashtable;
    49 
    51 
    50 import sun.font.AttributeMap;
    52 import sun.font.AttributeMap;
    51 import sun.font.AttributeValues;
    53 import sun.font.AttributeValues;
    52 import sun.font.EAttribute;
    54 import sun.font.EAttribute;
    53 import sun.font.CompositeFont;
    55 import sun.font.CompositeFont;
       
    56 import sun.font.CreatedFontTracker;
    54 import sun.font.Font2D;
    57 import sun.font.Font2D;
    55 import sun.font.Font2DHandle;
    58 import sun.font.Font2DHandle;
    56 import sun.font.FontManager;
    59 import sun.font.FontManager;
    57 import sun.font.GlyphLayout;
    60 import sun.font.GlyphLayout;
    58 import sun.font.FontLineMetrics;
    61 import sun.font.FontLineMetrics;
   573             }
   576             }
   574         }
   577         }
   575     }
   578     }
   576 
   579 
   577     /* used to implement Font.createFont */
   580     /* used to implement Font.createFont */
   578     private Font(File fontFile, int fontFormat, boolean isCopy)
   581     private Font(File fontFile, int fontFormat,
       
   582                  boolean isCopy, CreatedFontTracker tracker)
   579         throws FontFormatException {
   583         throws FontFormatException {
   580         this.createdFont = true;
   584         this.createdFont = true;
   581         /* Font2D instances created by this method track their font file
   585         /* Font2D instances created by this method track their font file
   582          * so that when the Font2D is GC'd it can also remove the file.
   586          * so that when the Font2D is GC'd it can also remove the file.
   583          */
   587          */
   584         this.font2DHandle =
   588         this.font2DHandle =
   585             FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
   589             FontManager.createFont2D(fontFile, fontFormat,
       
   590                                      isCopy, tracker).handle;
   586         this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
   591         this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
   587         this.style = Font.PLAIN;
   592         this.style = Font.PLAIN;
   588         this.size = 1;
   593         this.size = 1;
   589         this.pointSize = 1f;
   594         this.pointSize = 1f;
   590     }
   595     }
   783 
   788 
   784             return font;
   789             return font;
   785         }
   790         }
   786 
   791 
   787         return new Font(attributes);
   792         return new Font(attributes);
       
   793     }
       
   794 
       
   795     /**
       
   796      * Used with the byte count tracker for fonts created from streams.
       
   797      * If a thread can create temp files anyway, no point in counting
       
   798      * font bytes.
       
   799      */
       
   800     private static boolean hasTempPermission() {
       
   801 
       
   802         if (System.getSecurityManager() == null) {
       
   803             return true;
       
   804         }
       
   805         File f = null;
       
   806         boolean hasPerm = false;
       
   807         try {
       
   808             f = File.createTempFile("+~JT", ".tmp", null);
       
   809             f.delete();
       
   810             f = null;
       
   811             hasPerm = true;
       
   812         } catch (Throwable t) {
       
   813             /* inc. any kind of SecurityException */
       
   814         }
       
   815         return hasPerm;
   788     }
   816     }
   789 
   817 
   790     /**
   818     /**
   791      * Returns a new <code>Font</code> using the specified font type
   819      * Returns a new <code>Font</code> using the specified font type
   792      * and input data.  The new <code>Font</code> is
   820      * and input data.  The new <code>Font</code> is
   820 
   848 
   821         if (fontFormat != Font.TRUETYPE_FONT &&
   849         if (fontFormat != Font.TRUETYPE_FONT &&
   822             fontFormat != Font.TYPE1_FONT) {
   850             fontFormat != Font.TYPE1_FONT) {
   823             throw new IllegalArgumentException ("font format not recognized");
   851             throw new IllegalArgumentException ("font format not recognized");
   824         }
   852         }
   825         final InputStream fStream = fontStream;
   853         boolean copiedFontData = false;
   826         Object ret = java.security.AccessController.doPrivileged(
   854 
   827            new java.security.PrivilegedAction() {
   855         try {
   828               public Object run() {
   856             final File tFile = AccessController.doPrivileged(
   829                   File tFile = null;
   857                 new PrivilegedExceptionAction<File>() {
   830                   FileOutputStream outStream = null;
   858                     public File run() throws IOException {
   831                   try {
   859                         return File.createTempFile("+~JF", ".tmp", null);
   832                       tFile = File.createTempFile("+~JF", ".tmp", null);
   860                     }
   833                       /* Temp file deleted by font shutdown hook */
   861                 }
   834                       BufferedInputStream inStream =
   862             );
   835                           new BufferedInputStream(fStream);
   863 
   836                       outStream = new FileOutputStream(tFile);
   864             int totalSize = 0;
   837                       int bytesRead = 0;
   865             CreatedFontTracker tracker = null;
   838                       int bufSize = 8192;
   866             try {
   839                       byte [] buf = new byte[bufSize];
   867                 final OutputStream outStream =
   840                       while (bytesRead != -1) {
   868                     AccessController.doPrivileged(
   841                           try {
   869                         new PrivilegedExceptionAction<OutputStream>() {
   842                               bytesRead = inStream.read(buf, 0, bufSize);
   870                             public OutputStream run() throws IOException {
   843                           } catch (Throwable t) {
   871                                 return new FileOutputStream(tFile);
   844                               throw new IOException();
   872                             }
   845                           }
   873                         }
   846                           if (bytesRead != -1) {
   874                     );
   847                               outStream.write(buf, 0, bytesRead);
   875                 if (!hasTempPermission()) {
   848                           }
   876                     tracker = CreatedFontTracker.getTracker();
   849                       }
   877                 }
   850                       /* don't close the input stream */
   878                 try {
   851                       outStream.close();
   879                     byte[] buf = new byte[8192];
   852                   } catch (IOException e) {
   880                     for (;;) {
   853                       if (outStream != null) {
   881                         int bytesRead = fontStream.read(buf);
   854                           try {
   882                         if (bytesRead < 0) {
   855                               outStream.close();
   883                             break;
   856                           } catch (Exception e1) {
   884                         }
   857                           }
   885                         if (tracker != null) {
   858                       }
   886                             if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
   859                       if (tFile != null) {
   887                                 throw new IOException("File too big.");
   860                           try {
   888                             }
   861                               tFile.delete();
   889                             if (totalSize+tracker.getNumBytes() >
   862                           }  catch (Exception e2) {
   890                                 tracker.MAX_TOTAL_BYTES)
   863                           }
   891                               {
   864                       }
   892                                 throw new IOException("Total files too big.");
   865                       return e;
   893                             }
   866                   }
   894                             totalSize += bytesRead;
   867                   return tFile;
   895                             tracker.addBytes(bytesRead);
   868               }
   896                         }
   869           });
   897                         outStream.write(buf, 0, bytesRead);
   870 
   898                     }
   871         if (ret instanceof File) {
   899                     /* don't close the input stream */
   872             return new Font((File)ret, fontFormat, true);
   900                 } finally {
   873         } else if (ret instanceof IOException) {
   901                     outStream.close();
   874             throw (IOException)ret;
   902                 }
   875         } else {
   903                 /* After all references to a Font2D are dropped, the file
   876             throw new FontFormatException("Couldn't access font stream");
   904                  * will be removed. To support long-lived AppContexts,
       
   905                  * we need to then decrement the byte count by the size
       
   906                  * of the file.
       
   907                  * If the data isn't a valid font, the implementation will
       
   908                  * delete the tmp file and decrement the byte count
       
   909                  * in the tracker object before returning from the
       
   910                  * constructor, so we can set 'copiedFontData' to true here
       
   911                  * without waiting for the results of that constructor.
       
   912                  */
       
   913                 copiedFontData = true;
       
   914                 Font font = new Font(tFile, fontFormat, true, tracker);
       
   915                 return font;
       
   916             } finally {
       
   917                 if (!copiedFontData) {
       
   918                     if (tracker != null) {
       
   919                         tracker.subBytes(totalSize);
       
   920                     }
       
   921                     AccessController.doPrivileged(
       
   922                         new PrivilegedExceptionAction<Void>() {
       
   923                             public Void run() {
       
   924                                 tFile.delete();
       
   925                                 return null;
       
   926                             }
       
   927                         }
       
   928                     );
       
   929                 }
       
   930             }
       
   931         } catch (Throwable t) {
       
   932             if (t instanceof FontFormatException) {
       
   933                 throw (FontFormatException)t;
       
   934             }
       
   935             if (t instanceof IOException) {
       
   936                 throw (IOException)t;
       
   937             }
       
   938             Throwable cause = t.getCause();
       
   939             if (cause instanceof FontFormatException) {
       
   940                 throw (FontFormatException)cause;
       
   941             }
       
   942             throw new IOException("Problem reading font data.");
   877         }
   943         }
   878     }
   944     }
   879 
   945 
   880     /**
   946     /**
   881      * Returns a new <code>Font</code> using the specified font type
   947      * Returns a new <code>Font</code> using the specified font type
   911      * @see GraphicsEnvironment#registerFont(Font)
   977      * @see GraphicsEnvironment#registerFont(Font)
   912      * @since 1.5
   978      * @since 1.5
   913      */
   979      */
   914     public static Font createFont(int fontFormat, File fontFile)
   980     public static Font createFont(int fontFormat, File fontFile)
   915         throws java.awt.FontFormatException, java.io.IOException {
   981         throws java.awt.FontFormatException, java.io.IOException {
       
   982 
       
   983         fontFile = new File(fontFile.getPath());
       
   984 
   916         if (fontFormat != Font.TRUETYPE_FONT &&
   985         if (fontFormat != Font.TRUETYPE_FONT &&
   917             fontFormat != Font.TYPE1_FONT) {
   986             fontFormat != Font.TYPE1_FONT) {
   918             throw new IllegalArgumentException ("font format not recognized");
   987             throw new IllegalArgumentException ("font format not recognized");
   919         }
   988         }
   920         SecurityManager sm = System.getSecurityManager();
   989         SecurityManager sm = System.getSecurityManager();
   924             sm.checkPermission(filePermission);
   993             sm.checkPermission(filePermission);
   925         }
   994         }
   926         if (!fontFile.canRead()) {
   995         if (!fontFile.canRead()) {
   927             throw new IOException("Can't read " + fontFile);
   996             throw new IOException("Can't read " + fontFile);
   928         }
   997         }
   929         return new Font(fontFile, fontFormat, false);
   998         return new Font(fontFile, fontFormat, false, null);
   930     }
   999     }
   931 
  1000 
   932     /**
  1001     /**
   933      * Returns a copy of the transform associated with this
  1002      * Returns a copy of the transform associated with this
   934      * <code>Font</code>.  This transform is not necessarily the one
  1003      * <code>Font</code>.  This transform is not necessarily the one