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