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

Source Code of org.pentaho.reporting.engine.classic.core.layout.output.AbstractOutputProcessorMetaData$CacheKey

/*
* 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.util.HashMap;
import java.util.HashSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.ReportAttributeMap;
import org.pentaho.reporting.engine.classic.core.layout.text.ExtendedBaselineInfo;
import org.pentaho.reporting.engine.classic.core.layout.text.LegacyFontMetrics;
import org.pentaho.reporting.engine.classic.core.layout.text.TextUtility;
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.TextStyleKeys;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.config.ExtendedConfiguration;
import org.pentaho.reporting.libraries.base.config.ExtendedConfigurationWrapper;
import org.pentaho.reporting.libraries.base.util.LFUMap;
import org.pentaho.reporting.libraries.fonts.awt.AWTFontRegistry;
import org.pentaho.reporting.libraries.fonts.registry.DefaultFontStorage;
import org.pentaho.reporting.libraries.fonts.registry.FontContext;
import org.pentaho.reporting.libraries.fonts.registry.FontFamily;
import org.pentaho.reporting.libraries.fonts.registry.FontMetrics;
import org.pentaho.reporting.libraries.fonts.registry.FontRecord;
import org.pentaho.reporting.libraries.fonts.registry.FontRegistry;
import org.pentaho.reporting.libraries.fonts.registry.FontStorage;

/**
* Creation-Date: 07.04.2007, 19:21:44
*
* @author Thomas Morgner
*/
public abstract class AbstractOutputProcessorMetaData implements OutputProcessorMetaData
{
  private static final Log logger = LogFactory.getLog(AbstractOutputProcessorMetaData.class);

  private static class FontMetricsKey
  {
    private int hashCode;
    private boolean hashValid;
    private String fontFamily;
    private double fontSize;
    private boolean antiAliased;
    private boolean embedded;
    private String encoding;
    private boolean italics;
    private boolean bold;

    private FontMetricsKey()
    {
    }

    private FontMetricsKey(final FontMetricsKey derived)
    {
      this.fontFamily = derived.fontFamily;
      this.fontSize = derived.fontSize;
      this.antiAliased = derived.antiAliased;
      this.embedded = derived.embedded;
      this.encoding = derived.encoding;
      this.italics = derived.italics;
      this.bold = derived.bold;
    }

    public String getFontFamily()
    {
      return fontFamily;
    }

    public void setFontFamily(final String fontFamily)
    {
      this.fontFamily = fontFamily;
      this.hashValid = false;
    }

    public double getFontSize()
    {
      return fontSize;
    }

    public void setFontSize(final double fontSize)
    {
      this.fontSize = fontSize;
      this.hashValid = false;
    }

    public boolean isAntiAliased()
    {
      return antiAliased;
    }

    public void setAntiAliased(final boolean antiAliased)
    {
      this.antiAliased = antiAliased;
      this.hashValid = false;
    }

    public boolean isEmbedded()
    {
      return embedded;
    }

    public void setEmbedded(final boolean embedded)
    {
      this.embedded = embedded;
      this.hashValid = false;
    }

    public String getEncoding()
    {
      return encoding;
    }

    public void setEncoding(final String encoding)
    {
      this.encoding = encoding;
      this.hashValid = false;
    }

    public boolean isItalics()
    {
      return italics;
    }

    public void setItalics(final boolean italics)
    {
      this.italics = italics;
      this.hashValid = false;
    }

    public boolean isBold()
    {
      return bold;
    }

    public void setBold(final boolean bold)
    {
      this.bold = bold;
      this.hashValid = false;
    }

    public boolean equals(final Object o)
    {
      if (this == o)
      {
        return true;
      }
      if (o == null || getClass() != o.getClass())
      {
        return false;
      }

      final FontMetricsKey that = (FontMetricsKey) o;

      if (hashCode() != that.hashCode())
      {
        return false;
      }
      if (antiAliased != that.antiAliased)
      {
        return false;
      }
      if (embedded != that.embedded)
      {
        return false;
      }
      if (bold != that.bold)
      {
        return false;
      }
      if (italics != that.italics)
      {
        return false;
      }
      if (that.fontSize != fontSize)
      {
        return false;
      }
      if (encoding != null ? !encoding.equals(that.encoding) : that.encoding != null)
      {
        return false;
      }
      if (!fontFamily.equals(that.fontFamily))
      {
        return false;
      }

      return true;
    }

    public int hashCode()
    {
      if (hashValid == false)
      {
        int result = fontFamily.hashCode();
        final long temp = fontSize != +0.0d ? Double.doubleToLongBits(fontSize) : 0L;
        result = 29 * result + (int) (temp ^ (temp >>> 32));
        result = 29 * result + (antiAliased ? 1 : 0);
        result = 29 * result + (embedded ? 1 : 0);
        result = 29 * result + (italics ? 1 : 0);
        result = 29 * result + (bold ? 1 : 0);
        result = 29 * result + (encoding != null ? encoding.hashCode() : 0);
        this.hashCode = result;
        this.hashValid = true;
        return result;
      }
      return hashCode;
    }
  }

  protected static class ReusableFontContext implements FontContext
  {
    private boolean antiAliased;
    private double fontSize;
    private boolean embedded;
    private String encoding;


    protected ReusableFontContext()
    {
    }

    public boolean isEmbedded()
    {
      return embedded;
    }

    public void setEmbedded(final boolean embedded)
    {
      this.embedded = embedded;
    }

    public String getEncoding()
    {
      return encoding;
    }

    public void setEncoding(final String encoding)
    {
      this.encoding = encoding;
    }

    public void setAntiAliased(final boolean antiAliased)
    {
      this.antiAliased = antiAliased;
    }

    public void setFontSize(final double fontSize)
    {
      this.fontSize = fontSize;
    }

    /**
     * This is controlled by the output target and the stylesheet. If the output target does not support aliasing, it
     * makes no sense to enable it and all such requests are ignored.
     *
     * @return
     */
    public boolean isAntiAliased()
    {
      return antiAliased;
    }

    /**
     * This is defined by the output target. This is not controlled by the stylesheet.
     *
     * @return
     */
    public boolean isFractionalMetrics()
    {
      return true;
    }

    /**
     * The requested font size. A font may have a fractional font size (ie. 8.5 point). The font size may be influenced
     * by the output target.
     *
     * @return the font size.
     */
    public double getFontSize()
    {
      return fontSize;
    }
  }


  private static class CacheKey
  {
    private Object instanceId;
    private String styleClass;

    protected CacheKey()
    {
    }

    protected CacheKey(final Object instanceId, final String styleClass)
    {
      if (instanceId == null)
      {
        throw new NullPointerException();
      }
      if (styleClass == null)
      {
        throw new NullPointerException();
      }
      this.instanceId = instanceId;
      this.styleClass = styleClass;
    }

    public Object getInstanceId()
    {
      return instanceId;
    }

    public void setInstanceId(final Object instanceId)
    {
      this.instanceId = instanceId;
    }

    public String getStyleClass()
    {
      return styleClass;
    }

    public void setStyleClass(final String styleClass)
    {
      this.styleClass = styleClass;
    }

    public boolean equals(final Object o)
    {
      if (this == o)
      {
        return true;
      }
      if (o == null || getClass() != o.getClass())
      {
        return false;
      }

      final CacheKey cacheKey = (CacheKey) o;

      if (!instanceId.equals(cacheKey.instanceId))
      {
        return false;
      }
      if (!styleClass.equals(cacheKey.styleClass))
      {
        return false;
      }

      return true;
    }

    public int hashCode()
    {
      int result = instanceId.hashCode();
      result = 31 * result + styleClass.hashCode();
      return result;
    }

    public String toString()
    {
      return "CacheKey{" +
          "instanceId=" + instanceId +
          ", styleClass='" + styleClass + '\'' +
          '}';
    }
  }

  private static class StyleCacheEntry
  {
    private long changeTracker;
    private FontMetrics metrics;

    private StyleCacheEntry(final long changeTracker, final FontMetrics metrics)
    {
      this.changeTracker = changeTracker;
      this.metrics = metrics;
    }

    public long getChangeTracker()
    {
      return changeTracker;
    }

    public FontMetrics getMetrics()
    {
      return metrics;
    }
  }

  private FontStorage fontStorage;
  private FontRegistry fontRegistry;
  private HashMap numericFeatures;
  private HashMap fontFamilyMapping;
  private HashSet booleanFeatures;
  private Configuration configuration;
  private ReusableFontContext reusableFontContext;

  private HashMap fontMetricsCache;
  private LFUMap baselinesCache;
  private LFUMap fontMetricsByStyleCache;

  private FontMetricsKey lookupKey;

  private double defaultFontSize;
  private double fontSmoothThreshold;
  private double deviceResolution;

  protected AbstractOutputProcessorMetaData(final Configuration configuration)
  {
    this(configuration, new DefaultFontStorage(new AWTFontRegistry()));
  }


  protected AbstractOutputProcessorMetaData(final Configuration configuration,
                                            final FontStorage fontStorage)
  {
    if (configuration == null)
    {
      throw new NullPointerException();
    }
    if (fontStorage == null)
    {
      throw new NullPointerException();
    }

    this.configuration = configuration;
    this.fontRegistry = fontStorage.getFontRegistry();
    this.fontStorage = fontStorage;
    this.booleanFeatures = new HashSet();
    this.numericFeatures = new HashMap();
    this.reusableFontContext = new ReusableFontContext();
    this.fontMetricsCache = new HashMap(); // needs to be a strong reference ..
    this.baselinesCache = new LFUMap(200);
    this.lookupKey = new FontMetricsKey();
    this.fontMetricsByStyleCache = new LFUMap(200);

    final ExtendedConfiguration extendedConfig = new ExtendedConfigurationWrapper(configuration);

    final double defaultFontSize = extendedConfig.getIntProperty(
        "org.pentaho.reporting.engine.classic.core.layout.defaults.FontSize", 12);

    fontFamilyMapping = new HashMap();

    setNumericFeatureValue(OutputProcessorFeature.DEFAULT_FONT_SIZE, defaultFontSize);

    final double fontSmoothThreshold =
        extendedConfig.getIntProperty("org.pentaho.reporting.engine.classic.core.layout.defaults.FontSmoothThreshold",
            8);
    setNumericFeatureValue(OutputProcessorFeature.FONT_SMOOTH_THRESHOLD, fontSmoothThreshold);

    if (extendedConfig.getBoolProperty("org.pentaho.reporting.engine.classic.core.layout.fontrenderer.UseMaxCharBounds",
        true) == false)
    {
      addFeature(OutputProcessorFeature.LEGACY_LINEHEIGHT_CALC);
    }
    if (extendedConfig.getBoolProperty("org.pentaho.reporting.engine.classic.core.FixImageResolutionMapping", true))
    {
      addFeature(OutputProcessorFeature.IMAGE_RESOLUTION_MAPPING);
    }
    if (extendedConfig.getBoolProperty("org.pentaho.reporting.engine.classic.core.UseNativeScaling", true))
    {
      addFeature(OutputProcessorFeature.PREFER_NATIVE_SCALING);
    }
    if (extendedConfig.getBoolProperty("org.pentaho.reporting.engine.classic.core.DetectExtraContent", true))
    {
      addFeature(OutputProcessorFeature.DETECT_EXTRA_CONTENT);
    }

    final double deviceResolution = extendedConfig.getIntProperty(
        "org.pentaho.reporting.engine.classic.core.layout.DeviceResolution", 72);
    if (deviceResolution > 0)
    {
      setNumericFeatureValue(OutputProcessorFeature.DEVICE_RESOLUTION, deviceResolution);
    }
    else
    {
      setNumericFeatureValue(OutputProcessorFeature.DEVICE_RESOLUTION, 72);
    }

    setFamilyMapping(null, "SansSerif");
  }

  public Configuration getConfiguration()
  {
    return configuration;
  }

  protected void setFamilyMapping(final String family, final String name)
  {
    if (name == null)
    {
      throw new NullPointerException();
    }
    fontFamilyMapping.put(family, name);
  }

  protected void addFeature(final OutputProcessorFeature.BooleanOutputProcessorFeature feature)
  {
    if (feature == null)
    {
      throw new NullPointerException();
    }
    this.booleanFeatures.add(feature);
  }

  protected void removeFeature(final OutputProcessorFeature.BooleanOutputProcessorFeature feature)
  {
    if (feature == null)
    {
      throw new NullPointerException();
    }
    this.booleanFeatures.remove(feature);
  }

  public boolean isFeatureSupported(final OutputProcessorFeature.BooleanOutputProcessorFeature feature)
  {
    if (feature == null)
    {
      throw new NullPointerException();
    }
    return this.booleanFeatures.contains(feature);
  }

  protected void setNumericFeatureValue(final OutputProcessorFeature.NumericOutputProcessorFeature feature,
                                        final double value)
  {
    if (feature == null)
    {
      throw new NullPointerException();
    }
    if (OutputProcessorFeature.DEFAULT_FONT_SIZE.equals(feature))
    {
      numericFeatures.put(OutputProcessorFeature.DEFAULT_FONT_SIZE, new Double(value));
      this.defaultFontSize = value;
    }
    else if (OutputProcessorFeature.FONT_SMOOTH_THRESHOLD.equals(feature))
    {
      numericFeatures.put(OutputProcessorFeature.FONT_SMOOTH_THRESHOLD, new Double(value));
      this.fontSmoothThreshold = value;
    }
    else if (OutputProcessorFeature.DEVICE_RESOLUTION.equals(feature))
    {
      numericFeatures.put(OutputProcessorFeature.DEVICE_RESOLUTION, new Double(value));
      this.deviceResolution = value;
    }
    else
    {
      numericFeatures.put(feature, new Double(value));
    }
  }

  public double getNumericFeatureValue(final OutputProcessorFeature.NumericOutputProcessorFeature feature)
  {
    if (feature == null)
    {
      throw new NullPointerException();
    }

    if (OutputProcessorFeature.DEFAULT_FONT_SIZE == feature)
    {
      return this.defaultFontSize;
    }
    else if (OutputProcessorFeature.FONT_SMOOTH_THRESHOLD == feature)
    {
      return fontSmoothThreshold;
    }
    else if (OutputProcessorFeature.DEVICE_RESOLUTION == feature)
    {
      return this.deviceResolution;
    }

    final Double d = (Double) numericFeatures.get(feature);
    if (d == null)
    {
      return 0;
    }
    return d.doubleValue();
  }

  public boolean isContentSupported(final Object content)
  {
    return content != null;
  }

  protected FontRegistry getFontRegistry()
  {
    return fontRegistry;
  }

  protected FontStorage getFontStorage()
  {
    return fontStorage;
  }

  /**
   * @param name the raw name, maybe null.
   * @return the normalized name, but never null.
   */
  public String getNormalizedFontFamilyName(final String name)
  {
    final String normalizedFontFamily = (String) fontFamilyMapping.get(name);
    if (normalizedFontFamily == null)
    {
      if (name == null)
      {
        throw new IllegalStateException("There is no default mapping for <null> fonts defined.");
      }
      return name;
    }
    return normalizedFontFamily;
  }

  /**
   * Computes the font-metrics using the given properties.
   * <p/>
   * This method is a implementation detail. Use it in an output target, but be aware that it may change between
   * releases.
   *
   * @param fontFamily   the font family.
   * @param fontSize     the font size.
   * @param bold         a flag indicating whether the font should be displayed in bold.
   * @param italics      a flag indicating whether the font should be displayed in italics.
   * @param encoding     a valid font encoding, can be null to use the default.
   * @param embedded     a flag indicating whether the font is intended for embedded use.
   * @param antiAliasing a flag indicating whether the font should be rendered in aliased mode.
   * @return the font metrics, never null.
   * @throws IllegalArgumentException if the font family was invalid and no default family could be located.
   */
  public FontMetrics getFontMetrics(final String fontFamily,
                                    final double fontSize,
                                    final boolean bold,
                                    final boolean italics,
                                    final String encoding,
                                    final boolean embedded,
                                    final boolean antiAliasing) throws IllegalArgumentException
  {
    if (fontFamily == null)
    {
      throw new NullPointerException();
    }

    lookupKey.setAntiAliased(antiAliasing);
    lookupKey.setEncoding(encoding);
    lookupKey.setEmbedded(embedded);
    lookupKey.setFontFamily(fontFamily);
    lookupKey.setFontSize(fontSize);
    lookupKey.setBold(bold);
    lookupKey.setItalics(italics);

    final FontMetrics cached = (FontMetrics) fontMetricsCache.get(lookupKey);
    if (cached != null)
    {
      return cached;
    }

    final FontRegistry registry = getFontRegistry();
    FontFamily family = registry.getFontFamily(fontFamily);
    if (family == null)
    {
      AbstractOutputProcessorMetaData.logger.warn("Unable to lookup the font family: " + fontFamily);

      // Get the default font name
      final String fallBack = getNormalizedFontFamilyName(null);
      if (fallBack == null)
      {
        // If this case happens, the output-processor meta-data does not provide a sensible
        // fall-back value. As we cannot continue without a font, we fail here instead of
        // waiting for a NullPointer or other weird error later.
        throw new IllegalArgumentException("No default family defined, aborting.");
      }

      family = registry.getFontFamily(fallBack);
      if (family == null)
      {
        // If this case happens, the output-processor meta-data does not provide a sensible
        // fall-back value. As we cannot continue without a font, we fail here instead of
        // waiting for a NullPointer or other weird error later.
        throw new IllegalArgumentException("Default family is invalid. Aborting.");
      }
    }


    reusableFontContext.setAntiAliased(antiAliasing);
    reusableFontContext.setFontSize(fontSize);
    reusableFontContext.setEncoding(encoding);
    reusableFontContext.setEmbedded(embedded);

    final FontRecord record = family.getFontRecord(bold, italics);
    final FontMetrics fm = getFontStorage().getFontMetrics(record.getIdentifier(), reusableFontContext);
    if (fm == null)
    {
      // If this case happens, then the previous steps of mapping the font name into sensible
      // defaults failed. The font-system's font-registry is not in sync with the actual font-metrics
      // provider (which indicates that the LibFonts font-system implementation is invalid).
      throw new NullPointerException("FontMetrics returned from factory is null.");
    }

    if (isFeatureSupported(OutputProcessorFeature.LEGACY_LINEHEIGHT_CALC))
    {
      // Wrap the font metrics into the legacy-metrics ..
      final LegacyFontMetrics legacyFontMetrics = new LegacyFontMetrics(fm, fontSize);
      fontMetricsCache.put(new FontMetricsKey(lookupKey), legacyFontMetrics);
      return legacyFontMetrics;
    }

    fontMetricsCache.put(new FontMetricsKey(lookupKey), fm);
    return fm;
  }

  public ExtendedBaselineInfo getBaselineInfo(final int codePoint, final StyleSheet styleSheet)
  {
    final FontMetrics fontMetrics = getFontMetrics(styleSheet);
    if (fontMetrics.isUniformFontMetrics())
    {
      final String fontFamily = getNormalizedFontFamilyName((String) styleSheet.getStyleProperty(TextStyleKeys.FONT));
      if (fontFamily == null)
      {
        // If this case happens, the stylesheet is not implemented correctly. At that point,
        // we have to assume that the whole engine is no longer behaving valid and therefore we
        // abort early.
        throw new IllegalArgumentException("No valid font family specified.");
      }

      final double fontSize = styleSheet.getDoubleStyleProperty
          (TextStyleKeys.FONTSIZE, defaultFontSize);

      final boolean antiAliasing = RenderUtility.isFontSmooth(styleSheet, this);
      final String encoding = (String) styleSheet.getStyleProperty(TextStyleKeys.FONTENCODING);
      final boolean embedded =
          isFeatureSupported(OutputProcessorFeature.EMBED_ALL_FONTS) ||
              styleSheet.getBooleanStyleProperty(TextStyleKeys.EMBEDDED_FONT);
      final boolean bold = styleSheet.getBooleanStyleProperty(TextStyleKeys.BOLD, false);
      final boolean italics = styleSheet.getBooleanStyleProperty(TextStyleKeys.ITALIC, false);

      lookupKey.setAntiAliased(antiAliasing);
      lookupKey.setEncoding(encoding);
      lookupKey.setEmbedded(embedded);
      lookupKey.setFontFamily(fontFamily);
      lookupKey.setFontSize(fontSize);
      lookupKey.setBold(bold);
      lookupKey.setItalics(italics);

      final ExtendedBaselineInfo cached = (ExtendedBaselineInfo) baselinesCache.get(lookupKey);
      if (cached != null)
      {
        return cached;
      }
    }
    final ExtendedBaselineInfo baselineInfo = TextUtility.createBaselineInfo('x', fontMetrics, null);
    if (fontMetrics.isUniformFontMetrics())
    {
      baselinesCache.put(new FontMetricsKey(lookupKey), baselineInfo);
    }
    return baselineInfo;
  }

  /**
   * Returns the font metrics for the font specified in the style sheet.
   * <p/>
   * <B>NOTE: This method will throw an <code>IllegalArgumentException</code> if the specified font family can not be
   * found and the default font family can not be found</B>
   *
   * @param styleSheet ths style sheet from which the font information will be extracted
   * @return FontMetrics for the specified font. If the font family can not be found, the FontMetrics for the default
   *         font family will be returned
   * @throws IllegalArgumentException indicated the font metrics could not be determined (this is thrown since methods
   *                                  depending upon this method can not handle a <code>null</code> return).
   */
  public FontMetrics getFontMetrics(final StyleSheet styleSheet) throws IllegalArgumentException
  {
    final CacheKey key = new CacheKey(styleSheet.getId(), styleSheet.getClass().getName());
    final StyleCacheEntry o = (StyleCacheEntry) fontMetricsByStyleCache.get(key);
    if (o != null)
    {
      if (o.getChangeTracker() == styleSheet.getChangeTracker())
      {
        return o.getMetrics();
      }
    }

    final String fontFamily = getNormalizedFontFamilyName((String) styleSheet.getStyleProperty(TextStyleKeys.FONT));
    if (fontFamily == null)
    {
      // If this case happens, the stylesheet is not implemented correctly. At that point,
      // we have to assume that the whole engine is no longer behaving valid and therefore we
      // abort early.
      throw new IllegalArgumentException("No valid font family specified.");
    }

    final double fontSize = styleSheet.getDoubleStyleProperty
        (TextStyleKeys.FONTSIZE, defaultFontSize);

    final boolean antiAliasing = RenderUtility.isFontSmooth(styleSheet, this);
    final String encoding = (String) styleSheet.getStyleProperty(TextStyleKeys.FONTENCODING);
    final boolean embedded =
        isFeatureSupported(OutputProcessorFeature.EMBED_ALL_FONTS) ||
            styleSheet.getBooleanStyleProperty(TextStyleKeys.EMBEDDED_FONT);
    final boolean bold = styleSheet.getBooleanStyleProperty(TextStyleKeys.BOLD, false);
    final boolean italics = styleSheet.getBooleanStyleProperty(TextStyleKeys.ITALIC, false);

    final FontMetrics metrics = getFontMetrics(fontFamily, fontSize, bold, italics, encoding, embedded, antiAliasing);
    fontMetricsByStyleCache.put(key, new StyleCacheEntry(styleSheet.getChangeTracker(), metrics));
    return metrics;
  }

  public void commit()
  {
    fontStorage.commit();
    fontMetricsByStyleCache.clear();
  }


  /**
   * Checks whether this element provides some extra content that is not part of the visible layout structure.
   * This can be embedded scripts, anchors etc.
   *
   * @param style
   * @param attributes
   * @return
   */
  public boolean isExtraContentElement(final StyleSheet style, final ReportAttributeMap attributes)
  {
    if (isFeatureSupported(OutputProcessorFeature.DETECT_EXTRA_CONTENT) == false)
    {
      return false;
    }
    if (style.getStyleProperty(ElementStyleKeys.ANCHOR_NAME) != null)
    {
      return true;
    }
    if (style.getStyleProperty(ElementStyleKeys.HREF_TARGET) != null)
    {
      return true;
    }
    return false;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.output.AbstractOutputProcessorMetaData$CacheKey

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.