1 /* 2 * Copyright (c) 2013, 2014, 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.DisposerRecord; 29 import com.sun.javafx.font.FontResource; 30 import com.sun.javafx.font.FontStrikeDesc; 31 import com.sun.javafx.font.Glyph; 32 import com.sun.javafx.font.PrismFontFactory; 33 import com.sun.javafx.font.PrismFontStrike; 34 import com.sun.javafx.geom.Path2D; 35 import com.sun.javafx.geom.Point2D; 36 import com.sun.javafx.geom.transform.BaseTransform; 37 38 class CTFontStrike extends PrismFontStrike<CTFontFile> { 39 40 private long fontRef; 41 CGAffineTransform matrix; 42 /* CoreText uses different precision for subpixel text according 43 * to the font size. By observation, font sizes smaller than 12 44 * have 4 subpixel positions. Between 12 and 17 it decreases to 3. 45 * Between 18 and 33 it is only 2. Above 33 it rounds all positions 46 * to integral values. 47 */ 48 static final float SUBPIXEL4_SIZE = 12; 49 static final float SUBPIXEL3_SIZE = 18; 50 static final float SUBPIXEL2_SIZE = 34; 51 private static final boolean SUBPIXEL; 52 static { 53 int mode = PrismFontFactory.getFontFactory().getSubPixelMode(); 54 SUBPIXEL = (mode & PrismFontFactory.SUB_PIXEL_ON) != 0; 55 } 56 57 CTFontStrike(CTFontFile fontResource, float size, 58 BaseTransform graphicsTransform, int aaMode, 59 FontStrikeDesc desc) { 60 super(fontResource, size, graphicsTransform, aaMode, desc); 61 float maxDim = PrismFontFactory.getFontSizeLimit(); 62 if (graphicsTransform.isTranslateOrIdentity()) { 63 drawShapes = size > maxDim; 64 } else { 65 BaseTransform tx2d = getTransform(); 66 matrix = new CGAffineTransform(); 67 matrix.a = tx2d.getMxx(); 68 matrix.b = -tx2d.getMyx(); /*Inverted coordinates system */ 69 matrix.c = -tx2d.getMxy(); /*Inverted coordinates system */ 70 matrix.d = tx2d.getMyy(); 71 72 if (Math.abs(matrix.a * size) > maxDim || 73 Math.abs(matrix.b * size) > maxDim || 74 Math.abs(matrix.c * size) > maxDim || 75 Math.abs(matrix.d * size) > maxDim) 76 { 77 drawShapes = true; 78 } 79 } 80 81 if (fontResource.isEmbeddedFont()) { 82 final long cgFontRef = fontResource.getCGFontRef(); 83 if (cgFontRef != 0) { 84 fontRef = OS.CTFontCreateWithGraphicsFont( 85 cgFontRef, size, matrix, 0); 86 } 87 } else { 88 final long psNameRef = OS.CFStringCreate(fontResource.getPSName()); 89 if (psNameRef != 0) { 90 fontRef = OS.CTFontCreateWithName(psNameRef, size, matrix); 91 OS.CFRelease(psNameRef); 92 } 93 } 94 if (fontRef == 0) { 95 if (PrismFontFactory.debugFonts) { 96 System.err.println("Failed to create CTFont for " + this); 97 } 98 } 99 } 100 101 long getFontRef() { 102 return fontRef; 103 } 104 105 @Override protected DisposerRecord createDisposer(FontStrikeDesc desc) { 106 CTFontFile fontResource = getFontResource(); 107 return new CTStrikeDisposer(fontResource, desc, fontRef); 108 } 109 110 @Override protected Glyph createGlyph(int glyphCode) { 111 return new CTGlyph(this, glyphCode, drawShapes); 112 } 113 114 @Override 115 public int getQuantizedPosition(Point2D point) { 116 if (SUBPIXEL && matrix == null) { 117 /* Prism only produces 3 position, so for sizes smaller than 12 use 118 * Coretext for LCD and grayscale text 119 */ 120 if (getSize() < SUBPIXEL4_SIZE) { 121 float subPixelX = point.x; 122 point.x = (int) point.x; 123 subPixelX -= point.x; 124 point.y = (float) Math.round(point.y); 125 if (subPixelX >= 0.75f) return 3; 126 if (subPixelX >= 0.50f) return 2; 127 if (subPixelX >= 0.25f) return 1; 128 return 0; 129 } 130 if (getAAMode() == FontResource.AA_GREYSCALE) { 131 if (getSize() < SUBPIXEL3_SIZE) { 132 float subPixelX = point.x; 133 point.x = (int) point.x; 134 subPixelX -= point.x; 135 point.y = (float) Math.round(point.y); 136 if (subPixelX >= 0.66f) return 2; 137 if (subPixelX >= 0.33f) return 1; 138 return 0; 139 } 140 if (getSize() < SUBPIXEL2_SIZE) { 141 float subPixelX = point.x; 142 point.x = (int) point.x; 143 subPixelX -= point.x; 144 point.y = (float) Math.round(point.y); 145 if (subPixelX >= 0.5f) return 1; 146 } 147 return 0; 148 } 149 } 150 return super.getQuantizedPosition(point); 151 } 152 153 float getSubPixelPosition(int index) { 154 if (index == 0) return 0; 155 float size = getSize(); 156 if (size < SUBPIXEL4_SIZE) { 157 if (index == 3) return 0.75f; 158 if (index == 2) return 0.50f; 159 if (index == 1) return 0.25f; 160 return 0; 161 } 162 if (getAAMode() == FontResource.AA_LCD) return 0; 163 if (size < SUBPIXEL3_SIZE) { 164 if (index == 2) return 0.66f; 165 if (index == 1) return 0.33f; 166 return 0; 167 } 168 if (size < SUBPIXEL2_SIZE) { 169 if (index == 1) return 0.50f; 170 } 171 return 0; 172 } 173 174 boolean isSubPixelGlyph() { 175 return SUBPIXEL && matrix == null; 176 } 177 178 @Override protected Path2D createGlyphOutline(int glyphCode) { 179 CTFontFile fontResource = getFontResource(); 180 return fontResource.getGlyphOutline(glyphCode, getSize()); 181 } 182 183 CGRect getBBox(int glyphCode) { 184 CTFontFile fontResource = getFontResource(); 185 return fontResource.getBBox(glyphCode, getSize()); 186 } 187 }