/*! * 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) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.libraries.css; import org.pentaho.reporting.libraries.css.dom.LayoutElement; import org.pentaho.reporting.libraries.css.keys.box.BoxStyleKeys; import org.pentaho.reporting.libraries.css.keys.font.FontStyleKeys; import org.pentaho.reporting.libraries.css.keys.page.PageStyleKeys; import org.pentaho.reporting.libraries.css.model.CSSPageRule; import org.pentaho.reporting.libraries.css.model.StyleSheet; import org.pentaho.reporting.libraries.css.values.CSSNumericType; import org.pentaho.reporting.libraries.css.values.CSSNumericValue; import org.pentaho.reporting.libraries.css.values.CSSValue; import org.pentaho.reporting.libraries.css.values.CSSValuePair; import java.awt.print.PageFormat; import java.awt.print.Paper; /** * Creation-Date: Dec 3, 2006, 3:29:10 PM * * @author Thomas Morgner */ public class StyleSheetUtility { private StyleSheetUtility() { } public static CSSPageRule createRuleForPage( final StyleSheet style, final PageFormat format ) { final CSSPageRule rule = new CSSPageRule( style, null, null, null ); updateRuleForPage( rule, format ); return rule; } public static void updateRuleForPage( final CSSPageRule rule, final PageFormat format ) { if ( format == null ) { rule.removeProperty( BoxStyleKeys.MARGIN_TOP ); rule.removeProperty( BoxStyleKeys.MARGIN_LEFT ); rule.removeProperty( BoxStyleKeys.MARGIN_BOTTOM ); rule.removeProperty( BoxStyleKeys.MARGIN_RIGHT ); rule.removeProperty( PageStyleKeys.SIZE ); // rule.removeProperty(PageStyleKeys.HORIZONTAL_PAGE_SPAN); // rule.removeProperty(PageStyleKeys.VERTICAL_PAGE_SPAN); return; } final double width = format.getWidth(); final double height = format.getHeight(); rule.setPropertyValueAsString( PageStyleKeys.SIZE, width + "pt " + height + "pt" ); rule.setPropertyValueAsString( BoxStyleKeys.MARGIN_TOP, format.getImageableY() + "pt" ); rule.setPropertyValueAsString( BoxStyleKeys.MARGIN_LEFT, format.getImageableX() + "pt" ); final double marginRight = width - format.getImageableX() - format.getImageableWidth(); final double marginBottom = height - format.getImageableY() - format.getImageableHeight(); rule.setPropertyValueAsString( BoxStyleKeys.MARGIN_BOTTOM, marginBottom + "pt" ); rule.setPropertyValueAsString( BoxStyleKeys.MARGIN_RIGHT, marginRight + "pt" ); // rule.setPropertyValueAsString(PageStyleKeys.HORIZONTAL_PAGE_SPAN, "1"); // rule.setPropertyValueAsString(PageStyleKeys.VERTICAL_PAGE_SPAN, "1"); } public static PageFormat getPageFormat( final CSSPageRule rule, final int resolution ) { // This does not take any inheritance into account. final CSSValue sizeValue = rule.getPropertyCSSValue( PageStyleKeys.SIZE ); if ( sizeValue instanceof CSSValuePair == false ) { // not a valid thing .. return null; } CSSValuePair sizePair = (CSSValuePair) sizeValue; final CSSValue firstValue = sizePair.getFirstValue(); final CSSValue secondValue = sizePair.getSecondValue(); final double width = convertLengthToDouble( firstValue, resolution ); final double height = convertLengthToDouble( secondValue, resolution ); if ( width == 0 || height == 0 ) { return null; } // next the margins .. final double marginLeft = convertLengthToDouble ( rule.getPropertyCSSValue( BoxStyleKeys.MARGIN_LEFT ), resolution ); final double marginTop = convertLengthToDouble ( rule.getPropertyCSSValue( BoxStyleKeys.MARGIN_TOP ), resolution ); final double marginRight = convertLengthToDouble ( rule.getPropertyCSSValue( BoxStyleKeys.MARGIN_RIGHT ), resolution ); final double marginBottom = convertLengthToDouble ( rule.getPropertyCSSValue( BoxStyleKeys.MARGIN_BOTTOM ), resolution ); if ( width < height ) { final Paper p = new Paper(); p.setSize( width, height ); p.setImageableArea( marginLeft, marginTop, width - marginLeft - marginRight, height - marginTop - marginBottom ); final PageFormat pageFormat = new PageFormat(); pageFormat.setPaper( p ); pageFormat.setOrientation( PageFormat.PORTRAIT ); return pageFormat; } else { final Paper p = new Paper(); p.setSize( height, width ); p.setImageableArea( marginLeft, marginTop, width - marginLeft - marginRight, height - marginTop - marginBottom ); final PageFormat pageFormat = new PageFormat(); pageFormat.setPaper( p ); pageFormat.setOrientation( PageFormat.LANDSCAPE ); return pageFormat; } } /** * Returns the length in point as a double primitive value. Be aware that using double-values is not very accurate. * * @param rawValue * @return */ public static strictfp double convertLengthToDouble( final CSSValue rawValue, final int resolution ) { if ( rawValue instanceof CSSNumericValue == false ) { return 0; } final CSSNumericValue value = (CSSNumericValue) rawValue; if ( CSSNumericType.PT.equals( value.getType() ) ) { return value.getValue(); } if ( CSSNumericType.PC.equals( value.getType() ) ) { return ( value.getValue() / 12.0d ); } if ( CSSNumericType.INCH.equals( value.getType() ) ) { return ( value.getValue() / 72.0d ); } if ( CSSNumericType.CM.equals( value.getType() ) ) { return ( ( value.getValue() * 100 * 72.0d ) / 254.0d ); } if ( CSSNumericType.MM.equals( value.getType() ) ) { return ( ( value.getValue() * 10 * 72.0d ) / 254.0d ); } if ( CSSNumericType.PX.equals( value.getType() ) ) { // todo Read from a configuration file or so .. if ( resolution <= 0 ) { // we assume 72 pixel per inch ... return value.getValue(); } return value.getValue() * 72d / resolution; } return 0; } public static strictfp double convertFontSizeToDouble( final CSSValue rawValue, final int resolution, final LayoutElement baseElement ) { if ( rawValue instanceof CSSNumericValue == false ) { return 0; } final CSSNumericValue value = (CSSNumericValue) rawValue; if ( CSSNumericType.PT.equals( value.getType() ) ) { return value.getValue(); } if ( CSSNumericType.PC.equals( value.getType() ) ) { return ( value.getValue() / 12.0d ); } if ( CSSNumericType.INCH.equals( value.getType() ) ) { return ( value.getValue() / 72.0d ); } if ( CSSNumericType.CM.equals( value.getType() ) ) { return ( ( value.getValue() * 100 * 72.0d ) / 254.0d ); } if ( CSSNumericType.MM.equals( value.getType() ) ) { return ( ( value.getValue() * 10 * 72.0d ) / 254.0d ); } if ( CSSNumericType.PX.equals( value.getType() ) ) { // todo Read from a configuration file or so .. if ( resolution <= 0 ) { // we assume 72 pixel per inch ... return value.getValue(); } return value.getValue() * 72d / resolution; } if ( baseElement != null ) { if ( CSSNumericType.EM.equals( value.getType() ) ) { // base is the font-size final CSSValue baseVal = baseElement.getLayoutStyle().getValue( FontStyleKeys.FONT_SIZE ); return value.getValue() * convertLengthToDouble( baseVal, resolution ); } if ( CSSNumericType.EX.equals( value.getType() ) ) { // base is the parent font's x-height. final CSSValue baseVal = baseElement.getLayoutStyle().getValue( FontStyleKeys.FONT_SIZE ); // todo: cheating for now: We assume a sensible default and do not ask the font system. return value.getValue() * convertLengthToDouble( baseVal, resolution ) * 0.58; } if ( CSSNumericType.PERCENTAGE.equals( value.getType() ) ) { final CSSValue baseVal = baseElement.getLayoutStyle().getValue( FontStyleKeys.FONT_SIZE ); return value.getValue() * convertLengthToDouble( baseVal, resolution ) / 100d; } } return 0; } public static strictfp CSSValue convertFontSize( final CSSValue rawValue, final int resolution, final LayoutElement baseElement ) { if ( rawValue instanceof CSSNumericValue == false ) { return rawValue; } final CSSNumericValue value = (CSSNumericValue) rawValue; if ( baseElement != null ) { final CSSValue baseVal = baseElement.getLayoutStyle().getValue( FontStyleKeys.FONT_SIZE ); if ( baseVal instanceof CSSNumericValue == false ) { return CSSNumericValue.ZERO_LENGTH; } final CSSNumericValue baseNValue = (CSSNumericValue) baseVal; if ( CSSNumericType.EM.equals( value.getType() ) ) { // base is the font-size return CSSNumericValue.createValue( baseNValue.getNumericType(), value.getValue() * baseNValue.getValue() ); } if ( CSSNumericType.EX.equals( value.getType() ) ) { // base is the parent font's x-height. // todo: cheating for now: We assume a sensible default and do not ask the font system. return CSSNumericValue .createValue( baseNValue.getNumericType(), value.getValue() * baseNValue.getValue() * 0.58 ); } if ( CSSNumericType.PERCENTAGE.equals( value.getType() ) ) { return CSSNumericValue .createValue( baseNValue.getNumericType(), value.getValue() * baseNValue.getValue() / 100d ); } } return rawValue; } public static strictfp CSSNumericValue convertLength( final CSSValue rawValue, final CSSNumericValue basePercentage, final LayoutElement baseElement ) { if ( rawValue instanceof CSSNumericValue == false ) { return CSSNumericValue.ZERO_LENGTH; } final CSSNumericValue value = (CSSNumericValue) rawValue; if ( CSSNumericType.PERCENTAGE.equals( value.getType() ) ) { return CSSNumericValue .createValue( basePercentage.getNumericType(), value.getValue() * basePercentage.getValue() / 100d ); } if ( baseElement != null ) { final CSSValue baseVal = baseElement.getLayoutStyle().getValue( FontStyleKeys.FONT_SIZE ); if ( baseVal instanceof CSSNumericValue == false ) { return CSSNumericValue.ZERO_LENGTH; } final CSSNumericValue baseNValue = (CSSNumericValue) baseVal; if ( CSSNumericType.EM.equals( value.getType() ) ) { // base is the font-size return CSSNumericValue.createValue( baseNValue.getNumericType(), value.getValue() * baseNValue.getValue() ); } if ( CSSNumericType.EX.equals( value.getType() ) ) { // base is the parent font's x-height. // todo: cheating for now: We assume a sensible default and do not ask the font system. return CSSNumericValue .createValue( baseNValue.getNumericType(), value.getValue() * baseNValue.getValue() * 0.58 ); } return baseNValue; } return CSSNumericValue.ZERO_LENGTH; } }