/**
   * Creates a <tt>GraphicsNode</tt> according to the specified parameters.
   *
   * @param ctx the bridge context to use
   * @param e the element that describes the graphics node to build
   * @return a graphics node that represents the specified element
   */
  public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
    // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage'
    if (!SVGUtilities.matchUserAgent(e, ctx.getUserAgent())) {
      return null;
    }

    CompositeGraphicsNode cgn = new CompositeGraphicsNode();

    // 'transform'
    String s = e.getAttributeNS(null, SVG_TRANSFORM_ATTRIBUTE);
    if (s.length() != 0) {
      cgn.setTransform(SVGUtilities.convertTransform(e, SVG_TRANSFORM_ATTRIBUTE, s, ctx));
    }
    // 'visibility'
    cgn.setVisible(CSSUtilities.convertVisibility(e));

    // 'text-rendering' and 'color-rendering'
    RenderingHints hints = null;
    hints = CSSUtilities.convertColorRendering(e, hints);
    hints = CSSUtilities.convertTextRendering(e, hints);
    if (hints != null) {
      cgn.setRenderingHints(hints);
    }

    // first child holds the flow region nodes
    CompositeGraphicsNode cgn2 = new CompositeGraphicsNode();
    cgn.add(cgn2);

    // second child is the text node
    FlowTextNode tn = (FlowTextNode) instantiateGraphicsNode();
    tn.setLocation(getLocation(ctx, e));

    // specify the text painter to use
    if (ctx.getTextPainter() != null) {
      tn.setTextPainter(ctx.getTextPainter());
    }
    textNode = tn;
    cgn.add(tn);

    associateSVGContext(ctx, e, cgn);

    // traverse the children to add SVGContext
    Node child = getFirstChild(e);
    while (child != null) {
      if (child.getNodeType() == Node.ELEMENT_NODE) {
        addContextToChild(ctx, (Element) child);
      }
      child = getNextSibling(child);
    }

    return cgn;
  }