Exemplo n.º 1
0
  /**
   * Returns a Filter that represents a svg document or element as an image.
   *
   * @param ctx the bridge context
   * @param primitiveRegion the primitive region
   * @param refElement the referenced element
   * @param toBBoxNeeded true if there is a need to transform to ObjectBoundingBox space
   * @param filterElement parent filter element
   * @param filteredNode node to which the filter applies
   */
  protected static Filter createSVGFeImage(
      BridgeContext ctx,
      Rectangle2D primitiveRegion,
      Element refElement,
      boolean toBBoxNeeded,
      Element filterElement,
      GraphicsNode filteredNode) {

    //
    // <!> FIX ME
    // Unresolved issue on the feImage behavior when referencing an
    // image (PNG, JPEG or SVG image).
    // VH & TK, 03/08/2002
    // Furthermore, for feImage referencing doc fragment, should act
    // like a <use>, i.e., CSS cascading and the whole zing bang.
    //
    GraphicsNode node = ctx.getGVTBuilder().build(ctx, refElement);
    Filter filter = node.getGraphicsNodeRable(true);

    AffineTransform at = new AffineTransform();

    if (toBBoxNeeded) {
      // 'primitiveUnits' attribute - default is userSpaceOnUse
      short coordSystemType;
      Element filterDefElement = (Element) (filterElement.getParentNode());
      String s =
          SVGUtilities.getChainableAttributeNS(
              filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
      if (s.length() == 0) {
        coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
      } else {
        coordSystemType =
            SVGUtilities.parseCoordinateSystem(
                filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s, ctx);
      }

      if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
        at = SVGUtilities.toObjectBBox(at, filteredNode);
      }

      Rectangle2D bounds = filteredNode.getGeometryBounds();
      at.preConcatenate(
          AffineTransform.getTranslateInstance(
              primitiveRegion.getX() - bounds.getX(), primitiveRegion.getY() - bounds.getY()));

    } else {

      // Need to translate the image to the x, y coordinate to
      // have the same behavior as the <use> element
      at.translate(primitiveRegion.getX(), primitiveRegion.getY());
    }

    return new AffineRable8Bit(filter, at);
  }
 /**
  * Returns the specular exponent of the specular feSpecularLighting filter primitive element.
  *
  * @param filterElement the feSpecularLighting filter primitive element
  * @param ctx the BridgeContext to use for error information
  */
 protected static float convertSpecularExponent(Element filterElement, BridgeContext ctx) {
   String s = filterElement.getAttributeNS(null, SVG_SPECULAR_EXPONENT_ATTRIBUTE);
   if (s.length() == 0) {
     return 1; // default is 1
   } else {
     try {
       float v = SVGUtilities.convertSVGNumber(s);
       if (v < 1 || v > 128) {
         throw new BridgeException(
             ctx,
             filterElement,
             ERR_ATTRIBUTE_VALUE_MALFORMED,
             new Object[] {SVG_SPECULAR_CONSTANT_ATTRIBUTE, s});
       }
       return v;
     } catch (NumberFormatException nfEx) {
       throw new BridgeException(
           ctx,
           filterElement,
           nfEx,
           ERR_ATTRIBUTE_VALUE_MALFORMED,
           new Object[] {SVG_SPECULAR_CONSTANT_ATTRIBUTE, s, nfEx});
     }
   }
 }
  /**
   * Creates a <code>Filter</code> primitive according to the specified parameters.
   *
   * @param ctx the bridge context to use
   * @param filterElement the element that defines a filter
   * @param filteredElement the element that references the filter
   * @param filteredNode the graphics node to filter
   * @param inputFilter the <code>Filter</code> that represents the current filter input if the
   *     filter chain.
   * @param filterRegion the filter area defined for the filter chain the new node will be part of.
   * @param filterMap a map where the mediator can map a name to the <code>Filter</code> it creates.
   *     Other <code>FilterBridge</code>s can then access a filter node from the filterMap if they
   *     know its name.
   */
  public Filter createFilter(
      BridgeContext ctx,
      Element filterElement,
      Element filteredElement,
      GraphicsNode filteredNode,
      Filter inputFilter,
      Rectangle2D filterRegion,
      Map filterMap) {

    // 'scale' attribute - default is 0
    float scale = convertNumber(filterElement, SVG_SCALE_ATTRIBUTE, 0, ctx);

    // 'xChannelSelector' attribute - default is 'A'
    ARGBChannel xChannelSelector =
        convertChannelSelector(filterElement, SVG_X_CHANNEL_SELECTOR_ATTRIBUTE, ARGBChannel.A, ctx);

    // 'yChannelSelector' attribute - default is 'A'
    ARGBChannel yChannelSelector =
        convertChannelSelector(filterElement, SVG_Y_CHANNEL_SELECTOR_ATTRIBUTE, ARGBChannel.A, ctx);

    // 'in' attribute
    Filter in = getIn(filterElement, filteredElement, filteredNode, inputFilter, filterMap, ctx);
    if (in == null) {
      return null; // disable the filter
    }

    // 'in2' attribute - required
    Filter in2 = getIn2(filterElement, filteredElement, filteredNode, inputFilter, filterMap, ctx);
    if (in2 == null) {
      return null; // disable the filter
    }

    Rectangle2D defaultRegion;
    defaultRegion = (Rectangle2D) in.getBounds2D().clone();
    defaultRegion.add(in2.getBounds2D());
    // get filter primitive chain region
    Rectangle2D primitiveRegion =
        SVGUtilities.convertFilterPrimitiveRegion(
            filterElement, filteredElement, filteredNode, defaultRegion, filterRegion, ctx);

    PadRable pad = new PadRable8Bit(in, primitiveRegion, PadMode.ZERO_PAD);

    // build the displacement map filter
    List srcs = new ArrayList(2);
    srcs.add(pad);
    srcs.add(in2);
    Filter displacementMap =
        new DisplacementMapRable8Bit(srcs, scale, xChannelSelector, yChannelSelector);

    // handle the 'color-interpolation-filters' property
    handleColorInterpolationFilters(displacementMap, filterElement);

    PadRable filter = new PadRable8Bit(displacementMap, primitiveRegion, PadMode.ZERO_PAD);

    // update the filter Map
    updateFilterMap(filterElement, filter, filterMap);

    return filter;
  }
  /**
   * Creates a <code>Filter</code> primitive according to the specified parameters.
   *
   * @param ctx the bridge context to use
   * @param filterElement the element that defines a filter
   * @param filteredElement the element that references the filter
   * @param filteredNode the graphics node to filter
   * @param inputFilter the <code>Filter</code> that represents the current filter input if the
   *     filter chain.
   * @param filterRegion the filter area defined for the filter chain the new node will be part of.
   * @param filterMap a map where the mediator can map a name to the <code>Filter</code> it creates.
   *     Other <code>FilterBridge</code>s can then access a filter node from the filterMap if they
   *     know its name.
   */
  public Filter createFilter(
      BridgeContext ctx,
      Element filterElement,
      Element filteredElement,
      GraphicsNode filteredNode,
      Filter inputFilter,
      Rectangle2D filterRegion,
      Map filterMap) {

    // 'surfaceScale' attribute - default is 1
    float surfaceScale = convertNumber(filterElement, SVG_SURFACE_SCALE_ATTRIBUTE, 1, ctx);

    // 'specularConstant' attribute - default is 1
    float specularConstant = convertNumber(filterElement, SVG_SPECULAR_CONSTANT_ATTRIBUTE, 1, ctx);

    // 'specularExponent' attribute - default is 1
    float specularExponent = convertSpecularExponent(filterElement, ctx);

    // extract the light definition from the filterElement's children list
    Light light = extractLight(filterElement, ctx);

    // 'kernelUnitLength' attribute
    double[] kernelUnitLength = convertKernelUnitLength(filterElement, ctx);

    // 'in' attribute
    Filter in = getIn(filterElement, filteredElement, filteredNode, inputFilter, filterMap, ctx);
    if (in == null) {
      return null; // disable the filter
    }

    // Default region is the size of in (if in is SourceGraphic or
    // SourceAlpha it will already include a pad/crop to the
    // proper filter region size).
    Rectangle2D defaultRegion = in.getBounds2D();
    Rectangle2D primitiveRegion =
        SVGUtilities.convertFilterPrimitiveRegion(
            filterElement, filteredElement, filteredNode, defaultRegion, filterRegion, ctx);

    Filter filter =
        new SpecularLightingRable8Bit(
            in,
            primitiveRegion,
            light,
            specularConstant,
            specularExponent,
            surfaceScale,
            kernelUnitLength);

    // handle the 'color-interpolation-filters' property
    handleColorInterpolationFilters(filter, filterElement);

    // update the filter Map
    updateFilterMap(filterElement, filter, filterMap);

    return filter;
  }
 /**
  * Converts on the specified filter primitive element, the specified attribute that represents an
  * integer and with the specified default value.
  *
  * @param filterElement the filter primitive element
  * @param attrName the name of the attribute
  * @param defaultValue the default value of the attribute
  * @param ctx the BridgeContext to use for error information
  */
 protected static int convertInteger(
     Element filterElement, String attrName, int defaultValue, BridgeContext ctx) {
   String s = filterElement.getAttributeNS(null, attrName);
   if (s.length() == 0) {
     return defaultValue;
   } else {
     try {
       return SVGUtilities.convertSVGInteger(s);
     } catch (NumberFormatException nfEx) {
       throw new BridgeException(
           ctx, filterElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {attrName, s});
     }
   }
 }
Exemplo n.º 6
0
  /**
   * Creates a <tt>Filter</tt> primitive according to the specified parameters.
   *
   * @param ctx the bridge context to use
   * @param filterElement the element that defines a filter
   * @param filteredElement the element that references the filter
   * @param filteredNode the graphics node to filter
   * @param inputFilter the <tt>Filter</tt> that represents the current filter input if the filter
   *     chain.
   * @param filterRegion the filter area defined for the filter chain the new node will be part of.
   * @param filterMap a map where the mediator can map a name to the <tt>Filter</tt> it creates.
   *     Other <tt>FilterBridge</tt>s can then access a filter node from the filterMap if they know
   *     its name.
   */
  public Filter createFilter(
      BridgeContext ctx,
      Element filterElement,
      Element filteredElement,
      GraphicsNode filteredNode,
      Filter inputFilter,
      Rectangle2D filterRegion,
      Map filterMap) {

    List srcs =
        extractFeMergeNode(
            filterElement, filteredElement, filteredNode, inputFilter, filterMap, ctx);

    if (srcs == null) {
      return null; // <!> FIXME: no subelement found, result unspecified
    }

    if (srcs.size() == 0) {
      return null; // <!> FIXME: no subelement found, result unspecified
    }

    // the default region is the input sources regions union
    Iterator iter = srcs.iterator();
    Rectangle2D defaultRegion = (Rectangle2D) ((Filter) iter.next()).getBounds2D().clone();

    while (iter.hasNext()) {
      defaultRegion.add(((Filter) iter.next()).getBounds2D());
    }

    // get filter primitive chain region
    Rectangle2D primitiveRegion =
        SVGUtilities.convertFilterPrimitiveRegion(
            filterElement, filteredElement, filteredNode, defaultRegion, filterRegion, ctx);

    Filter filter = new CompositeRable8Bit(srcs, CompositeRule.OVER, true);

    // handle the 'color-interpolation-filters' property
    handleColorInterpolationFilters(filter, filterElement);

    filter = new PadRable8Bit(filter, primitiveRegion, PadMode.ZERO_PAD);

    // update the filter Map
    updateFilterMap(filterElement, filter, filterMap);

    return filter;
  }
Exemplo n.º 7
0
  /**
   * Creates a <tt>Filter</tt> primitive according to the specified parameters.
   *
   * @param ctx the bridge context to use
   * @param filterElement the element that defines a filter
   * @param filteredElement the element that references the filter
   * @param filteredNode the graphics node to filter
   * @param inputFilter the <tt>Filter</tt> that represents the current filter input if the filter
   *     chain.
   * @param filterRegion the filter area defined for the filter chain the new node will be part of.
   * @param filterMap a map where the mediator can map a name to the <tt>Filter</tt> it creates.
   *     Other <tt>FilterBridge</tt>s can then access a filter node from the filterMap if they know
   *     its name.
   */
  public Filter createFilter(
      BridgeContext ctx,
      Element filterElement,
      Element filteredElement,
      GraphicsNode filteredNode,
      Filter inputFilter,
      Rectangle2D filterRegion,
      Map filterMap) {

    // 'xlink:href' attribute
    String uriStr = XLinkSupport.getXLinkHref(filterElement);
    if (uriStr.length() == 0) {
      throw new BridgeException(
          ctx, filterElement, ERR_ATTRIBUTE_MISSING, new Object[] {"xlink:href"});
    }

    //
    // According the the SVG specification, feImage behaves like
    // <image> if it references an SVG document or a raster image
    // and it behaves like a <use> if it references a document
    // fragment.
    //
    // To provide this behavior, depending on whether the uri
    // contains a fragment identifier, we create either an
    // <image> or a <use> element and request the corresponding
    // bridges to build the corresponding GraphicsNode for us.
    //
    // Then, we take care of the possible transformation needed
    // from objectBoundingBox space to user space.
    //

    Document document = filterElement.getOwnerDocument();
    boolean isUse = uriStr.indexOf('#') != -1;
    Element contentElement = null;
    if (isUse) {
      contentElement = document.createElementNS(SVG_NAMESPACE_URI, SVG_USE_TAG);
    } else {
      contentElement = document.createElementNS(SVG_NAMESPACE_URI, SVG_IMAGE_TAG);
    }

    contentElement.setAttributeNS(XLINK_NAMESPACE_URI, XLINK_HREF_QNAME, uriStr);

    Element proxyElement = document.createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
    proxyElement.appendChild(contentElement);

    // feImage's default region is that of the filter chain.
    Rectangle2D defaultRegion = filterRegion;
    Element filterDefElement = (Element) (filterElement.getParentNode());

    Rectangle2D primitiveRegion =
        SVGUtilities.getBaseFilterPrimitiveRegion(
            filterElement, filteredElement, filteredNode, defaultRegion, ctx);

    // System.err.println(">>>>>>>> primitiveRegion : " + primitiveRegion);

    contentElement.setAttributeNS(null, SVG_X_ATTRIBUTE, String.valueOf(primitiveRegion.getX()));
    contentElement.setAttributeNS(null, SVG_Y_ATTRIBUTE, String.valueOf(primitiveRegion.getY()));
    contentElement.setAttributeNS(
        null, SVG_WIDTH_ATTRIBUTE, String.valueOf(primitiveRegion.getWidth()));
    contentElement.setAttributeNS(
        null, SVG_HEIGHT_ATTRIBUTE, String.valueOf(primitiveRegion.getHeight()));

    GraphicsNode node = ctx.getGVTBuilder().build(ctx, proxyElement);
    Filter filter = node.getGraphicsNodeRable(true);

    // 'primitiveUnits' attribute - default is userSpaceOnUse
    short coordSystemType;
    String s =
        SVGUtilities.getChainableAttributeNS(
            filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
    if (s.length() == 0) {
      coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
    } else {
      coordSystemType =
          SVGUtilities.parseCoordinateSystem(
              filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s, ctx);
    }

    // Compute the transform from object bounding box to user
    // space if needed.
    AffineTransform at = new AffineTransform();
    if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
      at = SVGUtilities.toObjectBBox(at, filteredNode);
    }
    filter = new AffineRable8Bit(filter, at);

    // handle the 'color-interpolation-filters' property
    handleColorInterpolationFilters(filter, filterElement);

    // get filter primitive chain region
    Rectangle2D primitiveRegionUserSpace =
        SVGUtilities.convertFilterPrimitiveRegion(
            filterElement, filteredElement, filteredNode, defaultRegion, filterRegion, ctx);
    filter = new PadRable8Bit(filter, primitiveRegionUserSpace, PadMode.ZERO_PAD);

    // update the filter Map
    updateFilterMap(filterElement, filter, filterMap);

    return filter;
  }