/*!
* 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 java.awt.print.PageFormat;
import java.awt.print.Paper;
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;
/**
* 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;
}
}