Esempio n. 1
0
nsRect
nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame, const nsRect& aRect)
{
  PRInt32 appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
  nsIntRect rect = aRect.ToOutsidePixels(appUnitsPerDevPixel);

  while (aFrame) {
    if (aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)
      break;

    nsSVGFilterFrame *filter = nsSVGEffects::GetFilterFrame(aFrame);
    if (filter) {
      // When we are under AttributeChanged, we can no longer get the old bbox
      // by calling GetBBox(), and we need that to set up the filter region
      // with the correct position. :-(
      //rect = filter->GetInvalidationBBox(aFrame, rect);

      // XXX [perf] As a horrible workaround, for now we just invalidate the
      // entire area of the nearest viewport establishing frame that doesnt
      // have overflow:visible. See bug 463939.
      nsSVGDisplayContainerFrame* viewportFrame = GetNearestSVGViewport(aFrame);
      while (viewportFrame && !viewportFrame->GetStyleDisplay()->IsScrollableOverflow()) {
        viewportFrame = GetNearestSVGViewport(viewportFrame);
      }
      if (!viewportFrame) {
        viewportFrame = GetOuterSVGFrame(aFrame);
      }
      if (viewportFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
        nsRect r = viewportFrame->GetVisualOverflowRect();
        // GetOverflowRect is relative to our border box, but we need it
        // relative to our content box.
        r.MoveBy(viewportFrame->GetPosition() - viewportFrame->GetContentRect().TopLeft());
        return r;
      }
      NS_ASSERTION(viewportFrame->GetType() == nsGkAtoms::svgInnerSVGFrame,
                   "Wrong frame type");
      nsSVGInnerSVGFrame* innerSvg = do_QueryFrame(static_cast<nsIFrame*>(viewportFrame));
      nsSVGDisplayContainerFrame* innerSvgParent = do_QueryFrame(viewportFrame->GetParent());
      float x, y, width, height;
      static_cast<nsSVGSVGElement*>(innerSvg->GetContent())->
        GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
      gfxRect bounds = nsSVGUtils::GetCanvasTM(innerSvgParent).
                         TransformBounds(gfxRect(x, y, width, height));
      bounds.RoundOut();
      nsIntRect r;
      if (gfxUtils::GfxRectToIntRect(bounds, &r)) {
        rect = r;
      } else {
        NS_NOTREACHED("Not going to invalidate the correct area");
      }
      aFrame = viewportFrame;
    }
    aFrame = aFrame->GetParent();
  }

  nsRect r = rect.ToAppUnits(appUnitsPerDevPixel);
  if (aFrame) {
    NS_ASSERTION(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG,
                 "outer SVG frame expected");
    r.MoveBy(aFrame->GetContentRect().TopLeft() - aFrame->GetPosition());
  }
  return r;
}