1 /*
   2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package sun.awt;
  28 
  29 import java.awt.FontFormatException;
  30 import java.awt.GraphicsEnvironment;
  31 import java.io.File;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import java.util.ArrayList;
  35 import java.util.HashMap;
  36 import java.util.Locale;
  37 import java.util.NoSuchElementException;
  38 import java.util.StringTokenizer;
  39 
  40 import sun.awt.Win32GraphicsEnvironment;
  41 import sun.awt.windows.WFontConfiguration;
  42 import sun.font.FontManager;
  43 import sun.font.SunFontManager;
  44 import sun.font.TrueTypeFont;
  45 import sun.java2d.HeadlessGraphicsEnvironment;
  46 import sun.java2d.SunGraphicsEnvironment;
  47 
  48 /**
  49  * The X11 implementation of {@link FontManager}.
  50  */
  51 public class Win32FontManager extends SunFontManager {
  52 
  53     private static String[] defaultPlatformFont = null;
  54 
  55     private static TrueTypeFont eudcFont;
  56 
  57     static {
  58 
  59         AccessController.doPrivileged(new PrivilegedAction() {
  60 
  61                 public Object run() {
  62                     String eudcFile = getEUDCFontFile();
  63                     if (eudcFile != null) {
  64                         try {
  65                             eudcFont = new TrueTypeFont(eudcFile, null, 0,
  66                                                         false);
  67                         } catch (FontFormatException e) {
  68                         }
  69                     }
  70                     return null;
  71                 }
  72 
  73             });
  74     }
  75 
  76     /* Used on Windows to obtain from the windows registry the name
  77      * of a file containing the system EUFC font. If running in one of
  78      * the locales for which this applies, and one is defined, the font
  79      * defined by this file is appended to all composite fonts as a
  80      * fallback component.
  81      */
  82     private static native String getEUDCFontFile();
  83 
  84     public TrueTypeFont getEUDCFont() {
  85         return eudcFont;
  86     }
  87 
  88     public Win32FontManager() {
  89         super();
  90         AccessController.doPrivileged(new PrivilegedAction() {
  91                 public Object run() {
  92 
  93                     /* Register the JRE fonts so that the native platform can
  94                      * access them. This is used only on Windows so that when
  95                      * printing the printer driver can access the fonts.
  96                      */
  97                     registerJREFontsWithPlatform(jreFontDirName);
  98                     return null;
  99                 }
 100             });
 101     }
 102 
 103     /* Unlike the shared code version, this expects a base file name -
 104      * not a full path name.
 105      * The font configuration file has base file names and the FontConfiguration
 106      * class reports these back to the GraphicsEnvironment, so these
 107      * are the componentFileNames of CompositeFonts.
 108      */
 109     protected void registerFontFile(String fontFileName, String[] nativeNames,
 110                                     int fontRank, boolean defer) {
 111 
 112         // REMIND: case compare depends on platform
 113         if (registeredFontFiles.contains(fontFileName)) {
 114             return;
 115         }
 116         registeredFontFiles.add(fontFileName);
 117 
 118         int fontFormat;
 119         if (getTrueTypeFilter().accept(null, fontFileName)) {
 120             fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
 121         } else if (getType1Filter().accept(null, fontFileName)) {
 122             fontFormat = SunFontManager.FONTFORMAT_TYPE1;
 123         } else {
 124             /* on windows we don't use/register native fonts */
 125             return;
 126         }
 127 
 128         if (fontPath == null) {
 129             fontPath = getPlatformFontPath(noType1Font);
 130         }
 131 
 132         /* Look in the JRE font directory first.
 133          * This is playing it safe as we would want to find fonts in the
 134          * JRE font directory ahead of those in the system directory
 135          */
 136         String tmpFontPath = jreFontDirName+File.pathSeparator+fontPath;
 137         StringTokenizer parser = new StringTokenizer(tmpFontPath,
 138                                                      File.pathSeparator);
 139 
 140         boolean found = false;
 141         try {
 142             while (!found && parser.hasMoreTokens()) {
 143                 String newPath = parser.nextToken();
 144                 boolean isJREFont = newPath.equals(jreFontDirName);
 145                 File theFile = new File(newPath, fontFileName);
 146                 if (theFile.canRead()) {
 147                     found = true;
 148                     String path = theFile.getAbsolutePath();
 149                     if (defer) {
 150                         registerDeferredFont(fontFileName, path,
 151                                              nativeNames,
 152                                              fontFormat, isJREFont,
 153                                              fontRank);
 154                     } else {
 155                         registerFontFile(path, nativeNames,
 156                                          fontFormat, isJREFont,
 157                                          fontRank);
 158                     }
 159                     break;
 160                 }
 161             }
 162         } catch (NoSuchElementException e) {
 163             System.err.println(e);
 164         }
 165         if (!found) {
 166             addToMissingFontFileList(fontFileName);
 167         }
 168     }
 169 
 170     @Override
 171     protected FontConfiguration createFontConfiguration() {
 172 
 173        FontConfiguration fc = new WFontConfiguration(this);
 174        fc.init();
 175        return fc;
 176     }
 177 
 178     @Override
 179     public FontConfiguration createFontConfiguration(boolean preferLocaleFonts,
 180             boolean preferPropFonts) {
 181 
 182         return new WFontConfiguration(this,
 183                                       preferLocaleFonts,preferPropFonts);
 184     }
 185 
 186     protected void
 187         populateFontFileNameMap(HashMap<String,String> fontToFileMap,
 188                                 HashMap<String,String> fontToFamilyNameMap,
 189                                 HashMap<String,ArrayList<String>>
 190                                 familyToFontListMap,
 191                                 Locale locale) {
 192 
 193         populateFontFileNameMap0(fontToFileMap, fontToFamilyNameMap,
 194                                  familyToFontListMap, locale);
 195 
 196     }
 197 
 198     private static native void
 199         populateFontFileNameMap0(HashMap<String,String> fontToFileMap,
 200                                  HashMap<String,String> fontToFamilyNameMap,
 201                                  HashMap<String,ArrayList<String>>
 202                                      familyToFontListMap,
 203                                  Locale locale);
 204 
 205     protected synchronized native String getFontPath(boolean noType1Fonts);
 206 
 207     public String[] getDefaultPlatformFont() {
 208 
 209         if (defaultPlatformFont != null) {
 210             return defaultPlatformFont;
 211         }
 212 
 213         String[] info = new String[2];
 214         info[0] = "Arial";
 215         info[1] = "c:\\windows\\fonts";
 216         final String[] dirs = getPlatformFontDirs(true);
 217         if (dirs.length > 1) {
 218             String dir = (String)
 219                 AccessController.doPrivileged(new PrivilegedAction() {
 220                         public Object run() {
 221                             for (int i=0; i<dirs.length; i++) {
 222                                 String path =
 223                                     dirs[i] + File.separator + "arial.ttf";
 224                                 File file = new File(path);
 225                                 if (file.exists()) {
 226                                     return dirs[i];
 227                                 }
 228                             }
 229                             return null;
 230                         }
 231                     });
 232             if (dir != null) {
 233                 info[1] = dir;
 234             }
 235         } else {
 236             info[1] = dirs[0];
 237         }
 238         info[1] = info[1] + File.separator + "arial.ttf";
 239         defaultPlatformFont = info;
 240         return defaultPlatformFont;
 241     }
 242 
 243     /* register only TrueType/OpenType fonts
 244      * Because these need to be registed just for use when printing,
 245      * we defer the actual registration and the static initialiser
 246      * for the printing class makes the call to registerJREFontsForPrinting()
 247      */
 248     static String fontsForPrinting = null;
 249     protected void registerJREFontsWithPlatform(String pathName) {
 250         fontsForPrinting = pathName;
 251     }
 252 
 253     public static void registerJREFontsForPrinting() {
 254         final String pathName;
 255         synchronized (Win32GraphicsEnvironment.class) {
 256             GraphicsEnvironment.getLocalGraphicsEnvironment();
 257             if (fontsForPrinting == null) {
 258                 return;
 259             }
 260             pathName = fontsForPrinting;
 261             fontsForPrinting = null;
 262         }
 263         java.security.AccessController.doPrivileged(
 264             new java.security.PrivilegedAction() {
 265                 public Object run() {
 266                     File f1 = new File(pathName);
 267                     String[] ls = f1.list(SunFontManager.getInstance().
 268                             getTrueTypeFilter());
 269                     if (ls == null) {
 270                         return null;
 271                     }
 272                     for (int i=0; i <ls.length; i++ ) {
 273                         File fontFile = new File(f1, ls[i]);
 274                         registerFontWithPlatform(fontFile.getAbsolutePath());
 275                     }
 276                     return null;
 277                 }
 278          });
 279     }
 280 
 281     protected static native void registerFontWithPlatform(String fontName);
 282 
 283     protected static native void deRegisterFontWithPlatform(String fontName);
 284 
 285     /**
 286      * populate the map with the most common windows fonts.
 287      */
 288     @Override
 289     public HashMap<String, FamilyDescription> populateHardcodedFileNameMap() {
 290         HashMap<String, FamilyDescription> platformFontMap
 291             = new HashMap<String, FamilyDescription>();
 292         FamilyDescription fd;
 293 
 294         /* Segoe UI is the default UI font for Vista and later, and
 295          * is used by the Win L&F which is used by FX too.
 296          * Tahoma is used for the Win L&F on XP.
 297          * Verdana is used in some FX UI controls.
 298          */
 299         fd = new FamilyDescription();
 300         fd.familyName = "Segoe UI";
 301         fd.plainFullName = "Segoe UI";
 302         fd.plainFileName = "segoeui.ttf";
 303         fd.boldFullName = "Segoe UI Bold";
 304         fd.boldFileName = "segoeuib.ttf";
 305         fd.italicFullName = "Segoe UI Italic";
 306         fd.italicFileName = "segoeuii.ttf";
 307         fd.boldItalicFullName = "Segoe UI Bold Italic";
 308         fd.boldItalicFileName = "segoeuiz.ttf";
 309         platformFontMap.put("segoe", fd);
 310 
 311         fd = new FamilyDescription();
 312         fd.familyName = "Tahoma";
 313         fd.plainFullName = "Tahoma";
 314         fd.plainFileName = "tahoma.ttf";
 315         fd.boldFullName = "Tahoma Bold";
 316         fd.boldFileName = "tahomabd.ttf";
 317         platformFontMap.put("tahoma", fd);
 318 
 319         fd = new FamilyDescription();
 320         fd.familyName = "Verdana";
 321         fd.plainFullName = "Verdana";
 322         fd.plainFileName = "verdana.TTF";
 323         fd.boldFullName = "Verdana Bold";
 324         fd.boldFileName = "verdanab.TTF";
 325         fd.italicFullName = "Verdana Italic";
 326         fd.italicFileName = "verdanai.TTF";
 327         fd.boldItalicFullName = "Verdana Bold Italic";
 328         fd.boldItalicFileName = "verdanaz.TTF";
 329         platformFontMap.put("verdana", fd);
 330 
 331         /* The following are important because they are the core
 332          * members of the default "Dialog" font.
 333          */
 334         fd = new FamilyDescription();
 335         fd.familyName = "Arial";
 336         fd.plainFullName = "Arial";
 337         fd.plainFileName = "ARIAL.TTF";
 338         fd.boldFullName = "Arial Bold";
 339         fd.boldFileName = "ARIALBD.TTF";
 340         fd.italicFullName = "Arial Italic";
 341         fd.italicFileName = "ARIALI.TTF";
 342         fd.boldItalicFullName = "Arial Bold Italic";
 343         fd.boldItalicFileName = "ARIALBI.TTF";
 344         platformFontMap.put("arial", fd);
 345 
 346         fd = new FamilyDescription();
 347         fd.familyName = "Symbol";
 348         fd.plainFullName = "Symbol";
 349         fd.plainFileName = "Symbol.TTF";
 350         platformFontMap.put("symbol", fd);
 351 
 352         fd = new FamilyDescription();
 353         fd.familyName = "WingDings";
 354         fd.plainFullName = "WingDings";
 355         fd.plainFileName = "WINGDING.TTF";
 356         platformFontMap.put("wingdings", fd);
 357 
 358         return platformFontMap;
 359     }
 360 }