001/* ============ 002 * FXGraphics2D 003 * ============ 004 * 005 * (C)opyright 2014-2022, by David Gilbert. 006 * 007 * https://github.com/jfree/fxgraphics2d 008 * 009 * The FXGraphics2D class has been developed by David Gilbert for 010 * use in Orson Charts (https://github.com/jfree/orson-charts) and 011 * JFreeChart (http://www.jfree.org/jfreechart). It may be useful for other 012 * code that uses the Graphics2D API provided by Java2D. 013 * 014 * Redistribution and use in source and binary forms, with or without 015 * modification, are permitted provided that the following conditions are met: 016 * - Redistributions of source code must retain the above copyright 017 * notice, this list of conditions and the following disclaimer. 018 * - Redistributions in binary form must reproduce the above copyright 019 * notice, this list of conditions and the following disclaimer in the 020 * documentation and/or other materials provided with the distribution. 021 * - Neither the name of JFree.org nor the names of its contributors may 022 * be used to endorse or promote products derived from this software 023 * without specific prior written permission. 024 * 025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 035 * THE POSSIBILITY OF SUCH DAMAGE. 036 * 037 */ 038 039package org.jfree.fx; 040 041import java.awt.Font; 042import java.awt.FontMetrics; 043import java.awt.Graphics; 044import java.awt.Graphics2D; 045import java.awt.geom.Rectangle2D; 046import java.text.CharacterIterator; 047import javafx.geometry.Bounds; 048import javafx.scene.text.FontPosture; 049import javafx.scene.text.FontWeight; 050import javafx.scene.text.Text; 051 052/** 053 * A font metrics implementation for JavaFX. This uses the JavaFX APIs to 054 * get string bounds, which is more exact than relying on the Java2D/AWT 055 * measurements. The remaining font metrics, however, still come from 056 * Java2D/AWT. 057 * 058 * @since 1.5 059 */ 060public class FXFontMetrics extends FontMetrics { 061 062 /** The graphics target. */ 063 private final Graphics2D g2; 064 065 /** 066 * Creates a new instance. 067 * 068 * @param font the font ({@code null} not permitted). 069 * @param g2 the graphics target ({@code null} not permitted). 070 */ 071 public FXFontMetrics(Font font, Graphics2D g2) { 072 super(font); 073 this.g2 = g2; 074 } 075 076 @Override 077 public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex, 078 int limit, Graphics context) { 079 char[] arr = new char[limit - beginIndex]; 080 ci.setIndex(beginIndex); 081 for(int idx = 0; idx < arr.length; idx++) { 082 arr[idx] = ci.current(); 083 ci.next(); 084 } 085 return getStringBounds(arr, beginIndex, limit, context); 086 } 087 088 @Override 089 public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit, 090 Graphics context) { 091 String str = new String(chars, beginIndex, limit - beginIndex); 092 return getStringBounds(str, context); 093 } 094 095 @Override 096 public Rectangle2D getStringBounds(String str, int beginIndex, int limit, 097 Graphics context) { 098 String substr = str.substring(beginIndex, limit); 099 return super.getStringBounds(substr, context); 100 } 101 102 @Override 103 public Rectangle2D getStringBounds(String str, Graphics context) { 104 Text text = new Text(str); 105 FontWeight weight = font.isBold() ? FontWeight.BOLD : FontWeight.NORMAL; 106 FontPosture posture = font.isItalic() 107 ? FontPosture.ITALIC : FontPosture.REGULAR; 108 javafx.scene.text.Font jfxfont = javafx.scene.text.Font.font( 109 font.getFamily(), weight, posture, font.getSize()); 110 text.setFont(jfxfont); 111 Bounds b = text.getLayoutBounds(); 112 return new Rectangle2D.Double(b.getMinX(), b.getMinY(), b.getWidth(), 113 b.getHeight()); 114 } 115 116 @Override 117 public int stringWidth(String str) { 118 return (int) getStringBounds(str, this.g2).getWidth(); 119 } 120 121}