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.coretext; 27 28 import com.sun.javafx.font.FontStrikeDesc; 29 import com.sun.javafx.font.PrismFontFile; 30 import com.sun.javafx.font.PrismFontStrike; 31 import com.sun.javafx.geom.Path2D; 32 import com.sun.javafx.geom.transform.BaseTransform; 33 34 class CTFontFile extends PrismFontFile { 35 36 /* Transform used for outline and bounds */ 37 private final static CGAffineTransform tx = new CGAffineTransform(); 38 static { 39 tx.a = 1; /* scale x */ 40 tx.d = -1; /* scale y */ 41 } 42 43 CTFontFile(String name, String filename, int fIndex, boolean register, 44 boolean embedded, boolean copy, boolean tracked) throws Exception { 45 super(name, filename, fIndex, register, embedded, copy, tracked); 46 } 47 48 public static boolean registerFont(String fontfile) { 49 if (fontfile == null) return false; 50 long alloc = OS.kCFAllocatorDefault(); 51 boolean result = false; 52 long fileRef = OS.CFStringCreate(fontfile); 53 if (fileRef != 0) { 54 int pathStyle = OS.kCFURLPOSIXPathStyle; 55 long urlRef = OS.CFURLCreateWithFileSystemPath(alloc, fileRef, pathStyle, false); 56 if (urlRef != 0) { 57 int scope = OS.kCTFontManagerScopeProcess; 58 result = OS.CTFontManagerRegisterFontsForURL(urlRef, scope, 0); 59 OS.CFRelease(urlRef); 60 } 61 OS.CFRelease(fileRef); 62 } 63 return result; 64 } 65 66 CGRect getBBox(int gc, float size) { 67 CTFontStrike strike = (CTFontStrike)getStrike(size, BaseTransform.IDENTITY_TRANSFORM); 68 long fontRef = strike.getFontRef(); 69 if (fontRef == 0) return null; 70 long pathRef = OS.CTFontCreatePathForGlyph(fontRef, (short)gc, tx); 71 if (pathRef == 0) return null; 72 CGRect rect = OS.CGPathGetPathBoundingBox(pathRef); 73 OS.CGPathRelease(pathRef); 74 return rect; 75 } 76 77 Path2D getGlyphOutline(int gc, float size) { 78 CTFontStrike strike = (CTFontStrike)getStrike(size, BaseTransform.IDENTITY_TRANSFORM); 79 long fontRef = strike.getFontRef(); 80 if (fontRef == 0) return null; 81 long pathRef = OS.CTFontCreatePathForGlyph(fontRef, (short)gc, tx); 82 if (pathRef == 0) return null; 83 Path2D path = OS.CGPathApply(pathRef); 84 OS.CGPathRelease(pathRef); 85 return path; 86 } 87 88 @Override protected int[] createGlyphBoundingBox(int gc) { 89 float size = 12; 90 CTFontStrike strike = (CTFontStrike)getStrike(size, 91 BaseTransform.IDENTITY_TRANSFORM); 92 93 long fontRef = strike.getFontRef(); 94 if (fontRef == 0) return null; 95 int[] bb = new int[4]; 96 97 /* For some reason CTFontGetBoundingRectsForGlyphs has poor performance. 98 * The fix is to use the 'loca' and the 'glyf' tables to determine 99 * the glyph bounding box (same as T2K). This implementation 100 * uses native code to read these tables since they can be large. 101 * In case it fails, or the font doesn't have a glyph table 102 * (CFF fonts), then the bounds of the glyph outline is used instead. 103 */ 104 if (!isCFF()) { 105 short format = getIndexToLocFormat(); 106 if (OS.CTFontGetBoundingRectForGlyphUsingTables(fontRef, (short)gc, format, bb)) { 107 return bb; 108 } 109 } 110 /* Note: not using tx here as the bounds need to be y up */ 111 long pathRef = OS.CTFontCreatePathForGlyph(fontRef, (short)gc, null); 112 if (pathRef == 0) return null; 113 CGRect rect = OS.CGPathGetPathBoundingBox(pathRef); 114 OS.CGPathRelease(pathRef); 115 float scale = getUnitsPerEm() / size; 116 bb[0] = (int)(Math.round(rect.origin.x * scale)); 117 bb[1] = (int)(Math.round(rect.origin.y * scale)); 118 bb[2] = (int)(Math.round((rect.origin.x + rect.size.width) * scale)); 119 bb[3] = (int)(Math.round((rect.origin.y + rect.size.height) * scale)); 120 return bb; 121 } 122 123 @Override 124 protected PrismFontStrike<CTFontFile> createStrike(float size, 125 BaseTransform transform, int aaMode, FontStrikeDesc desc) { 126 return new CTFontStrike(this, size, transform, aaMode, desc); 127 } 128 129 }