Exemple #1
0
  /** Returns the font associated with this rule or element. */
  public GVTFontFamily getFontFamily(BridgeContext ctx) {
    final FontFamilyResolver fontFamilyResolver = ctx.getFontFamilyResolver();
    GVTFontFamily family = fontFamilyResolver.resolve(familyName, this);
    if (family != null) {
      return family;
    }

    Iterator iter = srcs.iterator();
    while (iter.hasNext()) {
      Object o = iter.next();
      if (o instanceof String) {
        family = fontFamilyResolver.resolve((String) o, this);
        if (family != null) {
          return family;
        }
      } else if (o instanceof ParsedURL) {
        try {
          GVTFontFamily ff = getFontFamily(ctx, (ParsedURL) o);
          if (ff != null) return ff;
        } catch (SecurityException ex) {
          // Security violation notify the user but keep going.
          ctx.getUserAgent().displayError(ex);
        } catch (BridgeException ex) {
          // If Security violation notify
          // the user but keep going.
          if (ERR_URI_UNSECURE.equals(ex.getCode())) ctx.getUserAgent().displayError(ex);
        } catch (Exception ex) {
          // Do nothing couldn't get Referenced URL.
        }
      }
    }

    return null;
  }
  /**
   * Transcodes the specified Document as an image in the specified output.
   *
   * @param document the document to transcode
   * @param uri the uri of the document or null if any
   * @param output the ouput where to transcode
   * @exception org.apache.batik.transcoder.TranscoderException if an error occurred while
   *     transcoding
   */
  protected void transcode(Document document, String uri, TranscoderOutput output)
      throws TranscoderException {

    if (!(document instanceof SVGOMDocument)) {
      throw new TranscoderException(Messages.formatMessage("notsvg", null));
    }

    BridgeContext ctx = new BridgeContext(userAgent);
    SVGOMDocument svgDoc = (SVGOMDocument) document;

    // build the GVT tree
    GraphicsNode gvtRoot = buildGVT(ctx, svgDoc);

    // get the 'width' and 'height' attributes of the SVG document
    width = (int) (ctx.getDocumentSize().getWidth() + 0.5);
    height = (int) (ctx.getDocumentSize().getHeight() + 0.5);

    SpriteGraphics2D swf2d = new SpriteGraphics2D(width, height);
    gvtRoot.paint(swf2d);
    tags = swf2d.getTags();

    // Override width and height based on the SWF-specific bounds of the sprite contents
    // However we have to correct co-ordinates back to pixels... TODO: Remove all TWIPS references!
    Rect bounds = swf2d.getBounds();
    width = (int) Math.rint((bounds.xMax - bounds.xMin) / 20.0);
    height = (int) Math.rint((bounds.yMax - bounds.yMin) / 20.0);
  }
  public static List getFontFaces(Document doc, BridgeContext ctx) {
    // check fontFamilyMap to see if we have already created an
    // FontFamily that matches
    Map fontFamilyMap = ctx.getFontFamilyMap();
    List ret = (List) fontFamilyMap.get(doc);
    if (ret != null) return ret;

    ret = new LinkedList();

    NodeList fontFaceElements = doc.getElementsByTagNameNS(SVG_NAMESPACE_URI, SVG_FONT_FACE_TAG);

    SVGFontFaceElementBridge fontFaceBridge;
    fontFaceBridge = (SVGFontFaceElementBridge) ctx.getBridge(SVG_NAMESPACE_URI, SVG_FONT_FACE_TAG);

    for (int i = 0; i < fontFaceElements.getLength(); i++) {
      Element fontFaceElement = (Element) fontFaceElements.item(i);
      ret.add(fontFaceBridge.createFontFace(ctx, fontFaceElement));
    }

    CSSEngine engine = ((SVGOMDocument) doc).getCSSEngine();
    List sms = engine.getFontFaces();
    Iterator iter = sms.iterator();
    while (iter.hasNext()) {
      FontFaceRule ffr = (FontFaceRule) iter.next();
      ret.add(CSSFontFace.createCSSFontFace(engine, ffr));
    }
    return ret;
  }
Exemple #4
0
  /**
   * Returns a <code>Marker</code> defined on the specified element by the specified value, and for
   * the specified shape node.
   *
   * @param e the painted element
   * @param v the CSS value describing the marker to construct
   * @param ctx the bridge context
   */
  public static Marker convertMarker(Element e, Value v, BridgeContext ctx) {

    if (v.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
      return null; // 'none'
    } else {
      String uri = v.getStringValue();
      Element markerElement = ctx.getReferencedElement(e, uri);
      Bridge bridge = ctx.getBridge(markerElement);
      if (bridge == null || !(bridge instanceof MarkerBridge)) {
        throw new BridgeException(ctx, e, ERR_CSS_URI_BAD_TARGET, new Object[] {uri});
      }
      return ((MarkerBridge) bridge).createMarker(ctx, markerElement, e);
    }
  }
 /** Method to dispatch SVG Resize event. */
 protected void dispatchSVGResizeEvent() {
   if (bridgeContext.isSVG12()) {
     dispatchSVGDocEvent("resize");
   } else {
     dispatchSVGDocEvent("SVGResize");
   }
 }
 /** Method to dispatch SVG Scroll event. */
 protected void dispatchSVGScrollEvent() {
   if (bridgeContext.isSVG12()) {
     dispatchSVGDocEvent("scroll");
   } else {
     dispatchSVGDocEvent("SVGScroll");
   }
 }
 /** Method to dispatch SVG Zoom event. */
 protected void dispatchSVGZoomEvent() {
   if (bridgeContext.isSVG12()) {
     dispatchSVGDocEvent("zoom");
   } else {
     dispatchSVGDocEvent("SVGZoom");
   }
 }
 /** Recursively dispatch the SVG 'onload' event. */
 public void dispatchSVGLoadEvent() {
   SVGSVGElement root = (SVGSVGElement) document.getDocumentElement();
   String lang = root.getContentScriptType();
   long documentStartTime = System.currentTimeMillis();
   bridgeContext.getAnimationEngine().start(documentStartTime);
   dispatchSVGLoad(root, true, lang);
 }
  @Override
  public XmlResourceParser getLayout(int id) throws NotFoundException {
    IResourceValue value = getResourceValue(id, mPlatformResourceFlag);

    if (value != null) {
      File xml = new File(value.getValue());
      if (xml.isFile()) {
        // we need to create a pull parser around the layout XML file, and then
        // give that to our XmlBlockParser
        try {
          KXmlParser parser = new KXmlParser();
          parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
          parser.setInput(new FileReader(xml));

          return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
        } catch (XmlPullParserException e) {
          mContext.getLogger().error(e);

          // we'll return null below.
        } catch (FileNotFoundException e) {
          // this shouldn't happen since we check above.
        }
      }
    }

    // id was not found or not resolved. Throw a NotFoundException.
    throwException(id);

    // this is not used since the method above always throws
    return null;
  }
Exemple #10
0
  /**
   * Returns a Color object that corresponds to the input Paint's ICC color value or null if the
   * related color profile could not be used or loaded for any reason.
   *
   * @param e the element using the color
   * @param c the ICC color definition
   * @param opacity the opacity
   * @param ctx the bridge context to use
   */
  public static Color convertICCColor(Element e, ICCColor c, float opacity, BridgeContext ctx) {
    // Get ICC Profile's name
    String iccProfileName = c.getColorProfile();
    if (iccProfileName == null) {
      return null;
    }
    // Ask the bridge to map the ICC profile name to an  ICC_Profile object
    SVGColorProfileElementBridge profileBridge =
        (SVGColorProfileElementBridge) ctx.getBridge(SVG_NAMESPACE_URI, SVG_COLOR_PROFILE_TAG);
    if (profileBridge == null) {
      return null; // no bridge for color profile
    }

    ICCColorSpaceExt profileCS = profileBridge.createICCColorSpaceExt(ctx, e, iccProfileName);
    if (profileCS == null) {
      return null; // no profile
    }

    // Now, convert the colors to an array of floats
    int n = c.getNumberOfColors();
    float[] colorValue = new float[n];
    if (n == 0) {
      return null;
    }
    for (int i = 0; i < n; i++) {
      colorValue[i] = c.getColor(i);
    }

    // Convert values to RGB
    float[] rgb = profileCS.intendedToRGB(colorValue);
    return new Color(rgb[0], rgb[1], rgb[2], opacity);
  }
  /**
   * Returns a list of Filter objects that represents the feMergeNode of the specified feMerge
   * filter element.
   *
   * @param filterElement the feMerge filter element
   * @param filteredElement the filtered element
   * @param filteredNode the filtered graphics node
   * @param inputFilter the <tt>Filter</tt> that represents the current filter input if the filter
   *     chain.
   * @param filterMap the filter map that contains named filter primitives
   * @param ctx the bridge context
   */
  protected static List extractFeMergeNode(
      Element filterElement,
      Element filteredElement,
      GraphicsNode filteredNode,
      Filter inputFilter,
      Map filterMap,
      BridgeContext ctx) {

    List srcs = null;
    for (Node n = filterElement.getFirstChild(); n != null; n = n.getNextSibling()) {

      if (n.getNodeType() != Node.ELEMENT_NODE) {
        continue;
      }

      Element e = (Element) n;
      Bridge bridge = ctx.getBridge(e);
      if (bridge == null || !(bridge instanceof SVGFeMergeNodeElementBridge)) {
        continue;
      }
      Filter filter =
          ((SVGFeMergeNodeElementBridge) bridge)
              .createFilter(ctx, e, filteredElement, filteredNode, inputFilter, filterMap);
      if (filter != null) {
        if (srcs == null) {
          srcs = new LinkedList();
        }
        srcs.add(filter);
      }
    }
    return srcs;
  }
Exemple #12
0
  /**
   * Converts a Paint specified as a URI.
   *
   * @param paintedElement the element interested in a Paint
   * @param paintedNode the graphics node to paint (objectBoundingBox)
   * @param paintDef the paint definition
   * @param opacity the opacity to consider for the Paint
   * @param ctx the bridge context
   */
  public static Paint convertURIPaint(
      Element paintedElement,
      GraphicsNode paintedNode,
      Value paintDef,
      float opacity,
      BridgeContext ctx) {

    String uri = paintDef.getStringValue();
    Element paintElement = ctx.getReferencedElement(paintedElement, uri);

    Bridge bridge = ctx.getBridge(paintElement);
    if (bridge == null || !(bridge instanceof PaintBridge)) {
      throw new BridgeException(ctx, paintedElement, ERR_CSS_URI_BAD_TARGET, new Object[] {uri});
    }
    return ((PaintBridge) bridge)
        .createPaint(ctx, paintElement, paintedElement, paintedNode, opacity);
  }
  /**
   * Note: The reason why this method appears here in {@link ExternalContextCompatImpl} is because
   * it needs to be overridden by {@link ExternalContextCompat_2_2_Impl} since it has special
   * requirements for JSF 2.2.
   *
   * @see {@link ExternalContext#encodeActionURL(String, Map)}
   * @since JSF 1.0
   */
  @Override
  public String encodeActionURL(String url) {

    if (isEncodingFormWithPrimeFacesAjaxFileUpload()) {
      return encodePartialActionURL(url);
    } else {
      return bridgeContext.encodeActionURL(url).toString();
    }
  }
  /**
   * 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);
  }
  private IResourceValue getResourceValue(int id, boolean[] platformResFlag_out) {
    // first get the String related to this id in the framework
    String[] resourceInfo = Bridge.resolveResourceValue(id);

    if (resourceInfo != null) {
      platformResFlag_out[0] = true;
      return mContext.getFrameworkResource(resourceInfo[1], resourceInfo[0]);
    }

    // didn't find a match in the framework? look in the project.
    if (mProjectCallback != null) {
      resourceInfo = mProjectCallback.resolveResourceValue(id);

      if (resourceInfo != null) {
        platformResFlag_out[0] = false;
        return mContext.getProjectResource(resourceInfo[1], resourceInfo[0]);
      }
    }

    return null;
  }
  /** Invoked when an MutationEvent of type 'DOMNodeInserted' is fired. */
  public void handleDOMNodeInsertedEvent(MutationEvent evt) {
    if (evt.getTarget() instanceof Element) {
      Element childElt = (Element) evt.getTarget();

      GVTBuilder builder = ctx.getGVTBuilder();
      GraphicsNode childNode = builder.build(ctx, childElt);
      if (childNode == null) {
        return;
      }

      // There can only be one document element.
      node.add(childNode);
    }
  }
  /**
   * @see {@link ExternalContext#setResponseContentType(String)}
   * @since JSF 2.0
   */
  @Override
  public void setResponseContentType(String contentType) {

    if (portletResponse instanceof MimeResponse) {
      MimeResponse mimeResponse = (MimeResponse) portletResponse;
      bridgeContext.getPortletContainer().setMimeResponseContentType(mimeResponse, contentType);
    } else {

      if (manageIncongruities) {
        incongruityContext.setResponseContentType(contentType);
      } else {
        throw new IllegalStateException();
      }
    }
  }
  public ExternalContextCompatImpl(
      PortletContext portletContext,
      PortletRequest portletRequest,
      PortletResponse portletResponse) {

    this.portletContext = portletContext;
    this.portletRequest = portletRequest;
    this.portletResponse = portletResponse;

    // Get the bridge configuration.
    BridgeConfigFactory bridgeConfigFactory =
        (BridgeConfigFactory) BridgeFactoryFinder.getFactory(BridgeConfigFactory.class);
    this.bridgeConfig = bridgeConfigFactory.getBridgeConfig();

    // Get the BridgeContext.
    this.bridgeContext = BridgeContext.getCurrentInstance();

    this.incongruityContext = bridgeContext.getIncongruityContext();

    // Determine whether or not lifecycle incongruities should be managed.
    this.manageIncongruities =
        BooleanHelper.toBoolean(
            bridgeContext.getInitParameter(BridgeConfigConstants.PARAM_MANAGE_INCONGRUITIES), true);
  }
Exemple #19
0
 protected GraphicsNode buildGVT(BridgeContext ctx, SVGOMDocument svgDoc)
     throws TranscoderException {
   GVTBuilder builder = new GVTBuilder();
   GraphicsNode gvtRoot;
   try {
     gvtRoot = builder.build(ctx, svgDoc);
     // dispatch an 'onload' event if needed
     if (ctx.isDynamic()) {
       BaseScriptingEnvironment se = new BaseScriptingEnvironment(ctx);
       se.loadScripts();
       se.dispatchSVGLoadEvent();
     }
   } catch (BridgeException ex) {
     throw new TranscoderException(ex);
   }
   return gvtRoot;
 }
  /**
   * @see {@link ExternalContext#setResponseBufferSize(int)}
   * @since JSF 2.0
   */
  @Override
  public void setResponseBufferSize(int size) {

    if (portletResponse instanceof ResourceResponse) {

      if (bridgeContext.getPortletContainer().isAbleToSetResourceResponseBufferSize()) {
        ResourceResponse resourceResponse = (ResourceResponse) portletResponse;
        resourceResponse.setBufferSize(size);
      }
    } else {

      if (manageIncongruities) {
        incongruityContext.setResponseBufferSize(size);
      } else {
        throw new IllegalStateException();
      }
    }
  }
  public Interpreter getInterpreter(String lang) {
    interpreter = bridgeContext.getInterpreter(lang);
    if (interpreter == null) {
      if (languages.contains(lang)) {
        // Already issued warning so just return null;
        return null;
      }

      // So we know we have processed this interpreter.
      languages.add(lang);
      return null;
    }

    if (!languages.contains(lang)) {
      languages.add(lang);
      initializeEnvironment(interpreter, lang);
    }
    return interpreter;
  }
  /**
   * @see {@link ExternalContext#getResponseOutputWriter()}
   * @since JSF 2.0
   */
  @Override
  public Writer getResponseOutputWriter() throws IOException {

    if (portletResponse instanceof MimeResponse) {

      if (facesImplementationServletResponse != null) {
        logger.debug(
            "Delegating to AFTER_VIEW_CONTENT servletResponse=[{0}]",
            facesImplementationServletResponse);

        return facesImplementationServletResponse.getWriter();
      } else {
        return bridgeContext.getResponseOutputWriter();
      }

    } else {

      if (manageIncongruities) {
        return incongruityContext.getResponseOutputWriter();
      } else {
        throw new IllegalStateException();
      }
    }
  }
Exemple #23
0
  /**
   * Given a font family name tries to find a matching SVG font object. If finds one, returns an
   * SVGFontFamily otherwise returns an UnresolvedFontFamily.
   *
   * @param textElement The text element that the font family will be attached to.
   * @param ctx The bridge context, used to search for a matching SVG font element.
   * @param fontFamilyName The name of the font family to search for.
   * @param fontWeight The weight of the font to use when trying to match an SVG font family.
   * @param fontStyle The style of the font to use when trying to match as SVG font family.
   * @return A GVTFontFamily for the specified font attributes. This will be unresolved unless a
   *     matching SVG font was found.
   */
  public static GVTFontFamily getFontFamily(
      Element textElement,
      BridgeContext ctx,
      String fontFamilyName,
      String fontWeight,
      String fontStyle) {

    // TODO: should match against font-variant as well
    String fontKeyName = fontFamilyName.toLowerCase() + " " + fontWeight + " " + fontStyle;

    // check fontFamilyMap to see if we have already created an
    // FontFamily that matches
    Map fontFamilyMap = ctx.getFontFamilyMap();
    GVTFontFamily fontFamily = (GVTFontFamily) fontFamilyMap.get(fontKeyName);
    if (fontFamily != null) {
      return fontFamily;
    }

    // try to find a matching SVGFontFace element
    Document doc = textElement.getOwnerDocument();

    List fontFaces = (List) fontFamilyMap.get(doc);

    if (fontFaces == null) {
      fontFaces = getFontFaces(doc, ctx);
      fontFamilyMap.put(doc, fontFaces);
    }

    Iterator iter = fontFaces.iterator();
    List svgFontFamilies = new LinkedList();
    while (iter.hasNext()) {
      FontFace fontFace = (FontFace) iter.next();

      if (!fontFace.hasFamilyName(fontFamilyName)) {
        continue;
      }

      String fontFaceStyle = fontFace.getFontStyle();
      if (fontFaceStyle.equals(SVG_ALL_VALUE) || fontFaceStyle.indexOf(fontStyle) != -1) {
        GVTFontFamily ffam = fontFace.getFontFamily(ctx);
        if (ffam != null) svgFontFamilies.add(ffam);
      }
    }

    if (svgFontFamilies.size() == 1) {
      // only found one matching svg font family
      fontFamilyMap.put(fontKeyName, svgFontFamilies.get(0));
      return (GVTFontFamily) svgFontFamilies.get(0);

    } else if (svgFontFamilies.size() > 1) {
      // need to find font face that matches the font-weight closest
      String fontWeightNumber = getFontWeightNumberString(fontWeight);

      // create lists of font weight numbers for each font family
      List fontFamilyWeights = new ArrayList(svgFontFamilies.size());
      Iterator ffiter = svgFontFamilies.iterator();
      while (ffiter.hasNext()) {
        GVTFontFace fontFace;
        fontFace = ((GVTFontFamily) ffiter.next()).getFontFace();
        String fontFaceWeight = fontFace.getFontWeight();
        fontFaceWeight = getFontWeightNumberString(fontFaceWeight);
        fontFamilyWeights.add(fontFaceWeight);
      }

      // make sure that each possible font-weight has been
      // assigned to a font-face, if not then need to "fill the
      // holes"

      List newFontFamilyWeights = new ArrayList(fontFamilyWeights);
      for (int i = 100; i <= 900; i += 100) {
        String weightString = String.valueOf(i);
        boolean matched = false;
        int minDifference = 1000;
        int minDifferenceIndex = 0;
        for (int j = 0; j < fontFamilyWeights.size(); j++) {
          String fontFamilyWeight = (String) fontFamilyWeights.get(j);
          if (fontFamilyWeight.indexOf(weightString) > -1) {
            matched = true;
            break;
          }
          StringTokenizer st = new StringTokenizer(fontFamilyWeight, " ,");
          while (st.hasMoreTokens()) {
            int weightNum = Integer.parseInt(st.nextToken());
            int difference = Math.abs(weightNum - i);
            if (difference < minDifference) {
              minDifference = difference;
              minDifferenceIndex = j;
            }
          }
        }
        if (!matched) {
          String newFontFamilyWeight =
              newFontFamilyWeights.get(minDifferenceIndex) + ", " + weightString;
          newFontFamilyWeights.set(minDifferenceIndex, newFontFamilyWeight);
        }
      }

      // now find matching font weight
      for (int i = 0; i < svgFontFamilies.size(); i++) {
        String fontFaceWeight = (String) newFontFamilyWeights.get(i);
        if (fontFaceWeight.indexOf(fontWeightNumber) > -1) {
          fontFamilyMap.put(fontKeyName, svgFontFamilies.get(i));
          return (GVTFontFamily) svgFontFamilies.get(i);
        }
      }
      // should not get here, just return the first svg font family
      fontFamilyMap.put(fontKeyName, svgFontFamilies.get(0));
      return (GVTFontFamily) svgFontFamilies.get(0);

    } else {
      // couldn't find one so return an UnresolvedFontFamily object
      GVTFontFamily gvtFontFamily = new UnresolvedFontFamily(fontFamilyName);
      fontFamilyMap.put(fontKeyName, gvtFontFamily);
      return gvtFontFamily;
    }
  }
 public void setScreenTransform(AffineTransform at) {
   ctx.getUserAgent().setTransform(at);
 }
 public AffineTransform getScreenTransform() {
   return ctx.getUserAgent().getTransform();
 }
 /** Returns the size of a px CSS unit in millimeters. */
 public float getPixelUnitToMillimeter() {
   return ctx.getUserAgent().getPixelUnitToMillimeter();
 }
 /**
  * Builds using the specified BridgeContext and element, the specified graphics node. This is
  * called after all the children of the node have been constructed and added, so it is safe to do
  * work that depends on being able to see your children nodes in this method.
  *
  * @param ctx the bridge context to use
  * @param doc the document node that describes the graphics node to build
  * @param node the graphics node to build
  */
 public void buildGraphicsNode(BridgeContext ctx, Document doc, RootGraphicsNode node) {
   if (ctx.isDynamic()) {
     ctx.bind(doc, node);
   }
 }
  /**
   * 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;
  }
 @Override
 public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
   return mContext.obtainStyledAttributes(set, attrs);
 }
 /** Disposes this BridgeUpdateHandler and releases all resources. */
 public void dispose() {
   ((SVGOMDocument) document).setSVGContext(null);
   ctx.unbind(document);
 }