001/* ============ 002 * FXGraphics2D 003 * ============ 004 * 005 * (C)opyright 2014-2021, by Object Refinery Limited. 006 * 007 * http://www.jfree.org/fxgraphics2d/index.html 008 * 009 * The FXGraphics2D class has been developed by Object Refinery Limited for 010 * use in Orson Charts (http://www.object-refinery.com/orsoncharts) 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 the Object Refinery Limited nor the 022 * names of its contributors may be used to endorse or promote products 023 * derived from this software 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 OBJECT REFINERY LIMITED BE LIABLE FOR ANY 029 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 030 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 031 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 032 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 033 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 034 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 035 * 036 */ 037 038package org.jfree.fx; 039 040import java.awt.Font; 041import java.awt.FontMetrics; 042import java.awt.Graphics; 043import java.awt.Graphics2D; 044import java.awt.geom.Rectangle2D; 045import java.text.CharacterIterator; 046import javafx.geometry.Bounds; 047import javafx.scene.text.FontPosture; 048import javafx.scene.text.FontWeight; 049import javafx.scene.text.Text; 050 051/** 052 * A font metrics implementation for JavaFX. This uses the JavaFX APIs to 053 * get string bounds, which is more exact than relying on the Java2D/AWT 054 * measurements. The remaining font metrics, however, still come from 055 * Java2D/AWT. 056 * 057 * @since 1.5 058 */ 059public class FXFontMetrics extends FontMetrics { 060 061 /** The graphics target. */ 062 private Graphics2D g2; 063 064 /** 065 * Creates a new instance. 066 * 067 * @param font the font ({@code null} not permitted). 068 * @param g2 the graphics target ({@code null} not permitted). 069 */ 070 public FXFontMetrics(Font font, Graphics2D g2) { 071 super(font); 072 this.g2 = g2; 073 } 074 075 @Override 076 public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex, 077 int limit, Graphics context) { 078 char[] arr = new char[limit - beginIndex]; 079 ci.setIndex(beginIndex); 080 for(int idx = 0; idx < arr.length; idx++) { 081 arr[idx] = ci.current(); 082 ci.next(); 083 } 084 return getStringBounds(arr, beginIndex, limit, context); 085 } 086 087 @Override 088 public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit, 089 Graphics context) { 090 String str = new String(chars, beginIndex, limit - beginIndex); 091 return getStringBounds(str, context); 092 } 093 094 @Override 095 public Rectangle2D getStringBounds(String str, int beginIndex, int limit, 096 Graphics context) { 097 String substr = str.substring(beginIndex, limit); 098 return super.getStringBounds(substr, context); 099 } 100 101 @Override 102 public Rectangle2D getStringBounds(String str, Graphics context) { 103 Text text = new Text(str); 104 FontWeight weight = font.isBold() ? FontWeight.BOLD : FontWeight.NORMAL; 105 FontPosture posture = font.isItalic() 106 ? FontPosture.ITALIC : FontPosture.REGULAR; 107 javafx.scene.text.Font jfxfont = javafx.scene.text.Font.font( 108 font.getFamily(), weight, posture, font.getSize()); 109 text.setFont(jfxfont); 110 Bounds b = text.getLayoutBounds(); 111 return new Rectangle2D.Double(b.getMinX(), b.getMinY(), b.getWidth(), 112 b.getHeight()); 113 } 114 115 @Override 116 public int stringWidth(String str) { 117 return (int) getStringBounds(str, this.g2).getWidth(); 118 } 119 120}