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 long psNameRef = OS.CFStringCreate(fontResource.getPSName()); 82 if (psNameRef != 0) { 83 long fileNameRef = OS.CFStringCreate(fontResource.getFileName()); 84 if (fileNameRef != 0) { 85 fontRef = OS.CTFontCreate(fileNameRef, psNameRef, size, matrix); 86 OS.CFRelease(fileNameRef); 87 } 88 OS.CFRelease(psNameRef); 89 } 90 if (fontRef == 0) { 91 if (PrismFontFactory.debugFonts) { 92 System.err.println("Failed to create CTFont for " + this); 93 } 94 } 95 } 96 97 long getFontRef() { 98 return fontRef; 99 } 100 101 @Override protected DisposerRecord createDisposer(FontStrikeDesc desc) { 102 CTFontFile fontResource = getFontResource(); 103 return new CTStrikeDisposer(fontResource, desc, fontRef); 104 } 105 106 @Override protected Glyph createGlyph(int glyphCode) { 107 return new CTGlyph(this, glyphCode, drawShapes); 108 } 109 110 @Override 111 public int getQuantizedPosition(Point2D point) { 112 if (SUBPIXEL && matrix == null) { 113 /* Prism only produces 3 position, so for sizes smaller than 12 use 114 * Coretext for LCD and grayscale text 115 */ 116 if (getSize() < SUBPIXEL4_SIZE) { 117 float subPixelX = point.x; 118 point.x = (int) point.x; 119 subPixelX -= point.x; 120 point.y = (float) Math.round(point.y); 121 if (subPixelX >= 0.75f) return 3; 122 if (subPixelX >= 0.50f) return 2; 123 if (subPixelX >= 0.25f) return 1; 124 return 0; 125 } 126 if (getAAMode() == FontResource.AA_GREYSCALE) { 127 if (getSize() < SUBPIXEL3_SIZE) { 128 float subPixelX = point.x; 129 point.x = (int) point.x; 130 subPixelX -= point.x; 131 point.y = (float) Math.round(point.y); 132 if (subPixelX >= 0.66f) return 2; 133 if (subPixelX >= 0.33f) return 1; 134 return 0; 135 } 136 if (getSize() < SUBPIXEL2_SIZE) { 137 float subPixelX = point.x; 138 point.x = (int) point.x; 139 subPixelX -= point.x; 140 point.y = (float) Math.round(point.y); 141 if (subPixelX >= 0.5f) return 1; 142 } 143 return 0; 144 } 145 } 146 return super.getQuantizedPosition(point); 147 } 148 149 float getSubPixelPosition(int index) { 150 if (index == 0) return 0; 151 float size = getSize(); 152 if (size < SUBPIXEL4_SIZE) { 153 if (index == 3) return 0.75f; 154 if (index == 2) return 0.50f; 155 if (index == 1) return 0.25f; 156 return 0; 157 } 158 if (getAAMode() == FontResource.AA_LCD) return 0; 159 if (size < SUBPIXEL3_SIZE) { 160 if (index == 2) return 0.66f; 161 if (index == 1) return 0.33f; 162 return 0; 163 } 164 if (size < SUBPIXEL2_SIZE) { 165 if (index == 1) return 0.50f; 166 } 167 return 0; 168 } 169 170 boolean isSubPixelGlyph() { 171 return SUBPIXEL && matrix == null; 172 } 173 174 @Override protected Path2D createGlyphOutline(int glyphCode) { 175 CTFontFile fontResource = getFontResource(); 176 return fontResource.getGlyphOutline(glyphCode, getSize()); 177 } 178 179 CGRect getBBox(int glyphCode) { 180 CTFontFile fontResource = getFontResource(); 181 return fontResource.getBBox(glyphCode, getSize()); 182 } 183 }