1 /* 2 * Copyright (c) 2013, 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 package com.sun.javafx.font.directwrite; 27 28 import com.sun.javafx.font.PrismFontFactory; 29 import com.sun.javafx.font.PrismFontFile; 30 import com.sun.javafx.text.GlyphLayout; 31 32 public class DWFactory extends PrismFontFactory { 33 34 /* Factories (Singletons) */ 35 private static IDWriteFactory DWRITE_FACTORY = null; 36 private static IDWriteFontCollection FONT_COLLECTION = null; 37 private static IWICImagingFactory WIC_FACTORY = null; 38 private static ID2D1Factory D2D_FACTORY = null; 39 private static Thread d2dThread; 40 41 public static PrismFontFactory getFactory() { 42 /* DirectWrite is not available on Windows Vista SP2 (JFX minimal 43 * requirement on Windows) without 'Platform Update'. 44 * To workaround this limitation this method first checks if a 45 * IDWriteFactory can be created. The DWriteCreateFactory is a dynamic 46 * method which fails gracefully (returns NULL) when the system does 47 * not support DirectWrite. 48 */ 49 if (getDWriteFactory() == null) { 50 /* Returning null here indicates to the PrismFontFactory 51 * to fallback to T2K. */ 52 return null; 53 } 54 return new DWFactory(); 55 } 56 57 private DWFactory() { 58 } 59 60 @Override 61 protected PrismFontFile createFontFile(String name, String filename, 62 int fIndex, boolean register, 63 boolean embedded, boolean copy, 64 boolean tracked) throws Exception { 65 return new DWFontFile(name, filename, fIndex, register, 66 embedded, copy, tracked); 67 } 68 69 @Override public GlyphLayout createGlyphLayout() { 70 return new DWGlyphLayout(); 71 } 72 73 @Override 74 protected boolean registerEmbeddedFont(String path) { 75 IDWriteFactory factory = DWFactory.getDWriteFactory(); 76 IDWriteFontFile fontFile = factory.CreateFontFileReference(path); 77 if (fontFile == null) return false; 78 boolean[] isSupportedFontType = new boolean[1]; 79 int[] fontFileType = new int[1]; 80 int[] fontFaceType = new int[1]; 81 int[] numberOfFaces = new int[1]; 82 int hr = fontFile.Analyze(isSupportedFontType, fontFileType, fontFaceType, numberOfFaces); 83 fontFile.Release(); 84 if (hr != OS.S_OK) return false; 85 return isSupportedFontType[0]; 86 } 87 88 static IDWriteFactory getDWriteFactory() { 89 /* Using multi threaded DWrite factory as the JFX thread requires access 90 * to DWrite resources for measuring and the Prism thread for rendering */ 91 if (DWRITE_FACTORY == null) { 92 DWRITE_FACTORY = OS.DWriteCreateFactory(OS.DWRITE_FACTORY_TYPE_SHARED); 93 } 94 return DWRITE_FACTORY; 95 } 96 97 static IDWriteFontCollection getFontCollection() { 98 if (FONT_COLLECTION == null) { 99 FONT_COLLECTION = getDWriteFactory().GetSystemFontCollection(false); 100 } 101 return FONT_COLLECTION; 102 } 103 104 private static void checkThread() { 105 /* Note: It is possible for the correct thread to acquire the factory and 106 * hand it over to some other thread. This would be a programming error 107 * and it is not check by this implementation. */ 108 Thread current = Thread.currentThread(); 109 if (d2dThread == null) { 110 d2dThread = current; 111 } 112 if (d2dThread != current) { 113 throw new IllegalStateException( 114 "This operation is not permitted on the current thread [" 115 + current.getName() + "]"); 116 } 117 } 118 119 static synchronized IWICImagingFactory getWICFactory() { 120 checkThread(); 121 /* Using single threaded WIC Factory as it should only be used by the rendering thread */ 122 if (WIC_FACTORY == null) { 123 WIC_FACTORY = OS.WICCreateImagingFactory(); 124 } 125 return WIC_FACTORY; 126 } 127 128 static synchronized ID2D1Factory getD2DFactory() { 129 checkThread(); 130 /* Using single threaded D2D Factory as it should only be used by the rendering thread */ 131 if (D2D_FACTORY == null) { 132 D2D_FACTORY = OS.D2D1CreateFactory(OS.D2D1_FACTORY_TYPE_SINGLE_THREADED); 133 } 134 return D2D_FACTORY; 135 } 136 }