/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2006 - 2016 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.util;
import org.pentaho.reporting.engine.classic.core.ElementAlignment;
import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory;
import org.pentaho.reporting.engine.classic.core.imagemap.ImageMap;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.style.TextRotation;
import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.resourceloader.factory.drawable.DrawableWrapper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
public class RotatedTextDrawable implements ReportDrawable {
public RotatedTextDrawable( final String text, final TextRotation rotation ) {
this.text = text;
this.rotation = rotation;
}
private String text;
private final TextRotation rotation;
private Font font;
private ElementAlignment hAlign;
private ElementAlignment vAlign;
@Override public void draw( final Graphics2D graphics2D, final Rectangle2D bounds ) {
boolean fromBottom = TextRotation.D_90.equals( rotation );
if ( font != null ) {
graphics2D.setFont( font );
}
final FontMetrics fontMetrics = graphics2D.getFontMetrics();
drawTransformed( graphics2D, getXPadding( fromBottom, fontMetrics, bounds ),
getYPadding( fromBottom, fontMetrics, bounds ),
fromBottom ? 3 * java.lang.Math.PI / 2 : java.lang.Math.PI / 2 );
}
private int getXPadding( final boolean fromBottom, final FontMetrics fontMetrics, final Rectangle2D bounds ) {
if ( ElementAlignment.CENTER.equals( hAlign ) ) {
return (int) ( bounds.getWidth() / 2 );
}
if ( ElementAlignment.LEFT.equals( hAlign ) || ElementAlignment.JUSTIFY.equals( hAlign ) ) {
return fromBottom ? fontMetrics.getAscent() : fontMetrics.getDescent();
}
if ( ElementAlignment.RIGHT.equals( hAlign ) ) {
return (int) ( bounds.getWidth() - ( fromBottom ? fontMetrics.getDescent() : fontMetrics.getAscent() ) );
}
return 0;
}
private int getYPadding( final boolean fromBottom, final FontMetrics fontMetrics, final Rectangle2D bounds ) {
final int stringWidth = fontMetrics.stringWidth( text );
if ( ElementAlignment.TOP.equals( vAlign ) ) {
return fromBottom ? stringWidth : 0;
}
if ( ElementAlignment.MIDDLE.equals( vAlign ) ) {
return (int) ( ( bounds.getHeight() + ( fromBottom ? 1 : -1 ) * stringWidth ) / 2 );
}
if ( ElementAlignment.BOTTOM.equals( vAlign ) ) {
return fromBottom ? (int) bounds.getHeight() : (int) ( bounds.getHeight() - stringWidth );
}
return 0;
}
private void drawTransformed( final Graphics2D g2D, final double x, final double y, final double theta ) {
AffineTransform fontAT = new AffineTransform();
Font theFont = g2D.getFont();
fontAT.rotate( theta );
Font theDerivedFont = theFont.deriveFont( fontAT );
g2D.setFont( theDerivedFont );
g2D.drawString( text, (int) x, (int) y );
g2D.setFont( theFont );
}
public Dimension getPreferredSize() {
BufferedImage bufferedImage = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_RGB );
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
graphics.setFont( font );
final FontMetrics fontMetrics = graphics.getFontMetrics();
return new Dimension( fontMetrics.getHeight(), fontMetrics.stringWidth( text ) );
}
public boolean isKeepAspectRatio() {
return true;
}
@Override public void setConfiguration( final Configuration config ) {
}
@Override public void setStyleSheet( final StyleSheet style ) {
if ( style != null ) {
final String fontName = (String) style.getStyleProperty( TextStyleKeys.FONT );
final int fontSize = style.getIntStyleProperty( TextStyleKeys.FONTSIZE, 0 );
final boolean bold = style.getBooleanStyleProperty( TextStyleKeys.BOLD );
final boolean italics = style.getBooleanStyleProperty( TextStyleKeys.ITALIC );
final boolean underlined = style.getBooleanStyleProperty( TextStyleKeys.UNDERLINED );
final boolean strikeThrough = style.getBooleanStyleProperty( TextStyleKeys.STRIKETHROUGH );
final Color foregroundColor = (Color) style.getStyleProperty( ElementStyleKeys.PAINT );
final Color backgroundColor = (Color) style.getStyleProperty( ElementStyleKeys.BACKGROUND_COLOR );
if ( fontName != null && fontSize > 0 ) {
int fontstyle = Font.PLAIN;
if ( bold ) {
fontstyle |= Font.BOLD;
}
if ( italics ) {
fontstyle |= Font.ITALIC;
}
final Map<TextAttribute, Object> fontAttributes = new HashMap<>();
if ( underlined ) {
fontAttributes.put( TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON );
}
if ( strikeThrough ) {
fontAttributes.put( TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON );
}
fontAttributes.put( TextAttribute.FOREGROUND, foregroundColor );
fontAttributes.put( TextAttribute.BACKGROUND, backgroundColor );
this.font = new Font( fontName, fontstyle, fontSize ).deriveFont( fontAttributes );
this.hAlign = (ElementAlignment) style.getStyleProperty( ElementStyleKeys.ALIGNMENT );
this.vAlign = (ElementAlignment) style.getStyleProperty( ElementStyleKeys.VALIGNMENT );
}
}
}
@Override public void setResourceBundleFactory( final ResourceBundleFactory bundleFactory ) {
}
@Override public ImageMap getImageMap( final Rectangle2D bounds ) {
return null;
}
@Override public String toString() {
return text;
}
public String getText() {
return text;
}
public TextRotation getRotation() {
return rotation;
}
public static RotatedTextDrawable extract( final Object value ) {
if ( value instanceof RotatedTextDrawable ) {
return (RotatedTextDrawable) value;
}
if ( value != null && value instanceof DrawableWrapper ) {
if ( ( (DrawableWrapper) value ).getBackend() instanceof RotatedTextDrawable ) {
return (RotatedTextDrawable) ( (DrawableWrapper) value ).getBackend();
}
}
return null;
}
public ElementAlignment gethAlign() {
return hAlign;
}
public ElementAlignment getvAlign() {
return vAlign;
}
}