Package org.pentaho.reporting.engine.classic.core.layout.output

Source Code of org.pentaho.reporting.engine.classic.core.layout.output.RenderUtility

/*
* 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) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.layout.output;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.DefaultImageReference;
import org.pentaho.reporting.engine.classic.core.ElementAlignment;
import org.pentaho.reporting.engine.classic.core.ImageContainer;
import org.pentaho.reporting.engine.classic.core.ReportAttributeMap;
import org.pentaho.reporting.engine.classic.core.imagemap.ImageMap;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderableReplacedContentBox;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.FontSmooth;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys;
import org.pentaho.reporting.engine.classic.core.util.ImageUtils;
import org.pentaho.reporting.engine.classic.core.util.MemoryByteArrayOutputStream;
import org.pentaho.reporting.engine.classic.core.util.ReportDrawable;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictBounds;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility;
import org.pentaho.reporting.libraries.base.encoder.ImageEncoder;
import org.pentaho.reporting.libraries.base.encoder.ImageEncoderRegistry;
import org.pentaho.reporting.libraries.base.encoder.UnsupportedEncoderException;
import org.pentaho.reporting.libraries.base.util.WaitingImageObserver;
import org.pentaho.reporting.libraries.resourceloader.factory.drawable.DrawableWrapper;

/**
* Creation-Date: 12.05.2007, 15:58:43
*
* @author Thomas Morgner
*/
public class RenderUtility
{
  private static final Log logger = LogFactory.getLog(RenderUtility.class);

  private RenderUtility()
  {
  }

  public static String getEncoderType(final ReportAttributeMap attributes)
  {
    final Object attribute =
        attributes.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.IMAGE_ENCODING_TYPE);
    if (attribute == null)
    {
      return ImageEncoderRegistry.IMAGE_PNG;
    }

    final String encoder = String.valueOf(attribute);
    if (ImageEncoderRegistry.getInstance().isEncoderAvailable(encoder))
    {
      return encoder;
    }

    return ImageEncoderRegistry.IMAGE_PNG;
  }

  public static float getEncoderQuality(final ReportAttributeMap attributeMap)
  {
    final Object attribute =
        attributeMap.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.IMAGE_ENCODING_QUALITY);
    if (attribute == null)
    {
      return 0.9f;
    }

    if (attribute instanceof Number)
    {
      final Number n = (Number) attribute;
      final float v = n.floatValue();
      if (v < 0.01)
      {
        return 0.01f;
      }
      if (v > 0.999)
      {
        return 0.999f;
      }
      return v;
    }
    return 0.9f;
  }

  public static boolean isFontSmooth(final StyleSheet styleSheet,
                                     final OutputProcessorMetaData metaData)
  {
    final double fontSize = styleSheet.getDoubleStyleProperty
        (TextStyleKeys.FONTSIZE, metaData.getNumericFeatureValue(OutputProcessorFeature.DEFAULT_FONT_SIZE));

    final FontSmooth smoothing = (FontSmooth) styleSheet.getStyleProperty(TextStyleKeys.FONT_SMOOTH);
    final boolean antiAliasing;
    if (FontSmooth.NEVER.equals(smoothing))
    {
      antiAliasing = false;
    }
    else if (FontSmooth.AUTO.equals(smoothing) &&
        fontSize <= metaData.getNumericFeatureValue(OutputProcessorFeature.FONT_SMOOTH_THRESHOLD))
    {
      antiAliasing = false;
    }
    else
    {
      antiAliasing = true;
    }
    return antiAliasing;
  }

  /**
   * Encodes the given image as PNG, stores the image in the generated file and returns the name of the new image file.
   *
   * @param image the image to be encoded
   * @return the name of the image, never null.
   * @throws IOException if an IO erro occured.
   */
  public static byte[] encodeImage(final Image image) throws UnsupportedEncoderException, IOException
  {
    return encodeImage(image, ImageEncoderRegistry.IMAGE_PNG, 0.9f, true);
  }

  public static byte[] encodeImage(final Image image,
                                   final String mimeType,
                                   final float quality,
                                   final boolean alpha) throws UnsupportedEncoderException, IOException
  {
    final MemoryByteArrayOutputStream byteOut = new MemoryByteArrayOutputStream(65536, 65536 * 2);
    encodeImage(byteOut, image, mimeType, quality, alpha);
    return byteOut.toByteArray();
  }

  public static void encodeImage(final OutputStream outputStream,
                                 final Image image,
                                 final String mimeType,
                                 final float quality,
                                 final boolean alpha)
      throws UnsupportedEncoderException, IOException
  {
    final WaitingImageObserver obs = new WaitingImageObserver(image);
    obs.waitImageLoaded();

    final ImageEncoder imageEncoder = ImageEncoderRegistry.getInstance().createEncoder(mimeType);
    if (imageEncoder == null)
    {
      throw new UnsupportedEncoderException("The encoder for mime-type '" + mimeType + "' is not available");
    }

    imageEncoder.encodeImage(image, outputStream, quality, alpha);
  }

  public static Image scaleImage(final Image img,
                                 final int targetWidth,
                                 final int targetHeight,
                                 final Object hintValue,
                                 final boolean higherQuality)
  {
    final int type = BufferedImage.TYPE_INT_ARGB;

    Image ret = img;
    int w;
    int h;
    do
    {

      if (higherQuality)
      {
        final int imageWidth = ret.getWidth(null);
        final int imageHeight = ret.getHeight(null);
        if (imageWidth < targetWidth)
        {
          // This is a up-scale operation.
          w = Math.min(imageWidth << 1, targetWidth);
        }
        else if (imageWidth > targetWidth)
        {
          // downscale
          w = Math.max(imageWidth >> 1, targetWidth);
        }
        else
        {
          w = imageWidth;
        }

        if (imageHeight < targetHeight)
        {
          // This is a up-scale operation.
          h = Math.min(imageHeight << 1, targetHeight);
        }
        else if (imageHeight > targetHeight)
        {
          // downscale
          h = Math.max(imageHeight >> 1, targetHeight);
        }
        else
        {
          h = imageHeight;
        }
      }
      else
      {
        w = targetWidth;
        h = targetHeight;
      }

      final BufferedImage tmp = new BufferedImage(w, h, type);
      final Graphics2D g2 = tmp.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hintValue);
      // this one scales the image ..
      if (ret instanceof BufferedImage)
      {
        if (g2.drawImage(ret, 0, 0, w, h, null) == false)
        {
          logger.debug("Failed to scale the image. This should not happen.");
        }
      }
      else
      {
        final WaitingImageObserver obs = new WaitingImageObserver(ret);
        while (g2.drawImage(ret, 0, 0, w, h, null) == false)
        {
          obs.waitImageLoaded();
          if (obs.isError())
          {
            logger.warn("Error while loading the image during the rendering.");
            break;
          }
        }

      }
      g2.dispose();

      ret = tmp;
    }
    while (w != targetWidth || h != targetHeight);

    return ret;
  }

  public static double getNormalizationScale(final OutputProcessorMetaData metaData)
  {
    final double devResolution = metaData.getNumericFeatureValue(OutputProcessorFeature.DEVICE_RESOLUTION);
    final double scale;
    if (metaData.isFeatureSupported(OutputProcessorFeature.IMAGE_RESOLUTION_MAPPING) &&
        devResolution > 0)
    {
      scale = devResolution / 72.0;
    }
    else
    {
      scale = 1;
    }
    return scale;
  }

  public static ImageContainer createImageFromDrawable(final DrawableWrapper drawable,
                                                       final StrictBounds rect,
                                                       final RenderNode box,
                                                       final OutputProcessorMetaData metaData)
  {
    final int imageWidth = (int) StrictGeomUtility.toExternalValue(rect.getWidth());
    final int imageHeight = (int) StrictGeomUtility.toExternalValue(rect.getHeight());

    if (imageWidth == 0 || imageHeight == 0)
    {
      return null;
    }

    final double scale = RenderUtility.getNormalizationScale(metaData);
    final Image image = ImageUtils.createTransparentImage((int) (imageWidth * scale), (int) (imageHeight * scale));
    final Graphics2D g2 = (Graphics2D) image.getGraphics();

    final Object attribute =
        box.getStyleSheet().getStyleProperty(ElementStyleKeys.ANTI_ALIASING);
    if (attribute != null)
    {
      if (Boolean.TRUE.equals(attribute))
      {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      }
      else if (Boolean.FALSE.equals(attribute))
      {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
      }

    }
    if (RenderUtility.isFontSmooth(box.getStyleSheet(), metaData))
    {
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    }
    else
    {
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    }

    g2.scale(scale, scale);
    // the clipping bounds are a sub-area of the whole drawable
    // we only want to print a certain area ...

    final StyleSheet style = box.getStyleSheet();
    final String fontName = (String) style.getStyleProperty(TextStyleKeys.FONT);
    final int fontSize = style.getIntStyleProperty(TextStyleKeys.FONTSIZE, 8);
    final boolean bold = style.getBooleanStyleProperty(TextStyleKeys.BOLD);
    final boolean italics = style.getBooleanStyleProperty(TextStyleKeys.ITALIC);
    if (bold && italics)
    {
      g2.setFont(new Font(fontName, Font.BOLD | Font.ITALIC, fontSize));
    }
    else if (bold)
    {
      g2.setFont(new Font(fontName, Font.BOLD, fontSize));
    }
    else if (italics)
    {
      g2.setFont(new Font(fontName, Font.ITALIC, fontSize));
    }
    else
    {
      g2.setFont(new Font(fontName, Font.PLAIN, fontSize));
    }

    g2.setStroke((Stroke) style.getStyleProperty(ElementStyleKeys.STROKE));
    g2.setPaint((Paint) style.getStyleProperty(ElementStyleKeys.PAINT));

    drawable.draw(g2, new Rectangle2D.Double(0, 0, imageWidth, imageHeight));
    g2.dispose();

    try
    {
      return new DefaultImageReference(image);
    }
    catch (final IOException e1)
    {
      logger.warn("Unable to fully load a given image. (It should not happen here.)", e1);
      return null;
    }
  }


  public static long computeHorizontalAlignment(final ElementAlignment alignment,
                                                final long width,
                                                final long imageWidth)
  {
    if (ElementAlignment.RIGHT.equals(alignment))
    {
      return Math.max(0, width - imageWidth);
    }
    if (ElementAlignment.CENTER.equals(alignment))
    {
      return Math.max(0, (width - imageWidth) / 2);
    }
    return 0;
  }

  public static long computeVerticalAlignment(final ElementAlignment alignment,
                                              final long height,
                                              final long imageHeight)
  {
    if (ElementAlignment.BOTTOM.equals(alignment))
    {
      return Math.max(0, height - imageHeight);
    }
    if (ElementAlignment.MIDDLE.equals(alignment))
    {
      return Math.max(0, (height - imageHeight) / 2);
    }
    return 0;
  }


  public static ImageMap extractImageMap(final RenderableReplacedContentBox node, final DrawableWrapper drawable)
  {
    final Object backend = drawable.getBackend();
    if (backend instanceof ReportDrawable)
    {
      final ReportDrawable rdrawable = (ReportDrawable) backend;
      final int imageWidth = (int) StrictGeomUtility.toExternalValue(node.getWidth());
      final int imageHeight = (int) StrictGeomUtility.toExternalValue(node.getHeight());
      if (imageWidth == 0 || imageHeight == 0)
      {
        return null;
      }
      return rdrawable.getImageMap(new Rectangle2D.Double(0, 0, imageWidth, imageHeight));
    }
    return null;
  }

  public static ImageMap extractImageMap(final RenderableReplacedContentBox content)
  {
    final ReportAttributeMap attributes = content.getAttributes();
    final Object manualImageMap = attributes.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.IMAGE_MAP);
    if (manualImageMap instanceof ImageMap)
    {
      return (ImageMap) manualImageMap;
    }
    else
    {
      final Object o = content.getContent().getRawObject();
      if (o instanceof DrawableWrapper)
      {
        final DrawableWrapper drawable = (DrawableWrapper) o;
        return RenderUtility.extractImageMap(content, drawable);
      }
      else
      {
        return null;
      }
    }
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.output.RenderUtility

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.