SVGBBox
nsSVGDisplayContainerFrame::GetBBoxContribution(
  const gfxMatrix &aToBBoxUserspace,
  uint32_t aFlags)
{
  SVGBBox bboxUnion;

  nsIFrame* kid = mFrames.FirstChild();
  while (kid) {
    nsISVGChildFrame* svgKid = do_QueryFrame(kid);
    if (svgKid) {
      gfxMatrix transform = aToBBoxUserspace;
      nsIContent *content = kid->GetContent();
      if (content->IsSVG()) {
        transform = static_cast<nsSVGElement*>(content)->
                      PrependLocalTransformsTo(aToBBoxUserspace);
      }
      // We need to include zero width/height vertical/horizontal lines, so we have
      // to use UnionEdges.
      bboxUnion.UnionEdges(svgKid->GetBBoxContribution(transform, aFlags));
    }
    kid = kid->GetNextSibling();
  }

  return bboxUnion;
}
Esempio n. 2
0
SVGBBox
nsSVGDisplayContainerFrame::GetBBoxContribution(
  const Matrix &aToBBoxUserspace,
  uint32_t aFlags)
{
  SVGBBox bboxUnion;

  nsIFrame* kid = mFrames.FirstChild();
  while (kid) {
    nsIContent *content = kid->GetContent();
    nsISVGChildFrame* svgKid = do_QueryFrame(kid);
    // content could be a XUL element so check for an SVG element before casting
    if (svgKid && (!content->IsSVG() ||
                   static_cast<const nsSVGElement*>(content)->HasValidDimensions())) {

      gfxMatrix transform = gfx::ThebesMatrix(aToBBoxUserspace);
      if (content->IsSVG()) {
        transform = static_cast<nsSVGElement*>(content)->
                      PrependLocalTransformsTo(transform);
      }
      // We need to include zero width/height vertical/horizontal lines, so we have
      // to use UnionEdges.
      bboxUnion.UnionEdges(svgKid->GetBBoxContribution(gfx::ToMatrix(transform), aFlags));
    }
    kid = kid->GetNextSibling();
  }

  return bboxUnion;
}
Esempio n. 3
0
SVGBBox
nsSVGMarkerFrame::GetMarkBBoxContribution(const gfxMatrix &aToBBoxUserspace,
                                          uint32_t aFlags,
                                          nsSVGPathGeometryFrame *aMarkedFrame,
                                          const nsSVGMark *aMark,
                                          float aStrokeWidth)
{
  SVGBBox bbox;

  // If the flag is set when we get here, it means this marker frame
  // has already been used in calculating the current mark bbox, and
  // the document has a marker reference loop.
  if (mInUse)
    return bbox;

  AutoMarkerReferencer markerRef(this, aMarkedFrame);

  SVGMarkerElement *content = static_cast<SVGMarkerElement*>(mContent);

  const nsSVGViewBoxRect viewBox = content->GetViewBoxRect();

  if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
    return bbox;
  }

  mStrokeWidth = aStrokeWidth;
  mX = aMark->x;
  mY = aMark->y;
  mAutoAngle = aMark->angle;
  mIsStart = aMark->type == nsSVGMark::eStart;

  gfxMatrix markerTM =
    content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle, mIsStart);
  gfxMatrix viewBoxTM = content->GetViewBoxTransform();

  gfxMatrix tm = viewBoxTM * markerTM * aToBBoxUserspace;

  for (nsIFrame* kid = mFrames.FirstChild();
       kid;
       kid = kid->GetNextSibling()) {
    nsISVGChildFrame* child = do_QueryFrame(kid);
    if (child) {
      // When we're being called to obtain the invalidation area, we need to
      // pass down all the flags so that stroke is included. However, once DOM
      // getBBox() accepts flags, maybe we should strip some of those here?

      // We need to include zero width/height vertical/horizontal lines, so we have
      // to use UnionEdges.
      bbox.UnionEdges(child->GetBBoxContribution(tm, aFlags));
    }
  }

  return bbox;
}
SVGBBox
nsSVGInnerSVGFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                        uint32_t aFlags)
{
  // XXXjwatt It seems like authors would want the result to be clipped by the
  // viewport we establish if IsScrollableOverflow() is true.  We should
  // consider doing that.  See bug 1350755.

  SVGBBox bbox;

  if (aFlags & nsSVGUtils::eForGetClientRects) {
    // XXXjwatt For consistency with the old code this code includes the
    // viewport we establish in the result, but only includes the bounds of our
    // descendants if they are not clipped to that viewport.  However, this is
    // both inconsistent with Chrome and with the specs.  See bug 1350755.
    // Ideally getClientRects/getBoundingClientRect should be consistent with
    // getBBox.
    float x, y, w, h;
    static_cast<SVGSVGElement*>(mContent)->
      GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
    if (w < 0.0f) w = 0.0f;
    if (h < 0.0f) h = 0.0f;
    Rect viewport(x, y, w, h);
    bbox = aToBBoxUserspace.TransformBounds(viewport);
    if (StyleDisplay()->IsScrollableOverflow()) {
      return bbox;
    }
    // Else we're not clipping to our viewport so we fall through and include
    // the bounds of our children.
  }

  SVGBBox descendantsBbox =
    nsSVGDisplayContainerFrame::GetBBoxContribution(aToBBoxUserspace, aFlags);

  bbox.UnionEdges(descendantsBbox);

  return bbox;
}