Bug 988818 - Stop creating a Thebes (gfxASurface) backed gfxContext in nsSVGImageFrame (Moz2D migration). r=longsonr

This commit is contained in:
Jonathan Watt 2014-03-31 12:53:54 +01:00
Родитель 00bb2b13a2
Коммит 87ad440e7c
3 изменённых файлов: 61 добавлений и 25 удалений

Просмотреть файл

@ -1801,6 +1801,34 @@ nsLayoutUtils::ChangeMatrixBasis(const gfxPoint3D &aOrigin,
return result;
}
static void ConstrainToCoordValues(float& aStart, float& aSize)
{
MOZ_ASSERT(aSize > 0);
// Here we try to make sure that the resulting nsRect will continue to cover
// as much of the area that was covered by the original gfx Rect as possible.
// We clamp the bounds of the rect to {nscoord_MIN,nscoord_MAX} since
// nsRect::X/Y() and nsRect::XMost/YMost() can't return values outwith this
// range:
float end = aStart + aSize;
aStart = clamped(aStart, float(nscoord_MIN), float(nscoord_MAX));
end = clamped(end, float(nscoord_MIN), float(nscoord_MAX));
aSize = end - aStart;
// We must also clamp aSize to {0,nscoord_MAX} since nsRect::Width/Height()
// can't return a value greater than nscoord_MAX. If aSize is greater than
// nscoord_MAX then we reduce it to nscoord_MAX while keeping the rect
// centered:
if (aSize > nscoord_MAX) {
float excess = aSize - nscoord_MAX;
excess /= 2;
aStart += excess;
aSize = nscoord_MAX;
}
}
/**
* Given a gfxFloat, constrains its value to be between nscoord_MIN and nscoord_MAX.
*
@ -1840,6 +1868,22 @@ static void ConstrainToCoordValues(gfxFloat& aStart, gfxFloat& aSize)
}
}
nsRect
nsLayoutUtils::RoundGfxRectToAppRect(const Rect &aRect, float aFactor)
{
/* Get a new Rect whose units are app units by scaling by the specified factor. */
Rect scaledRect = aRect;
scaledRect.ScaleRoundOut(aFactor);
/* We now need to constrain our results to the max and min values for coords. */
ConstrainToCoordValues(scaledRect.x, scaledRect.width);
ConstrainToCoordValues(scaledRect.y, scaledRect.height);
/* Now typecast everything back. This is guaranteed to be safe. */
return nsRect(nscoord(scaledRect.X()), nscoord(scaledRect.Y()),
nscoord(scaledRect.Width()), nscoord(scaledRect.Height()));
}
nsRect
nsLayoutUtils::RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor)
{

Просмотреть файл

@ -117,6 +117,7 @@ class nsLayoutUtils
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Rect Rect;
public:
typedef mozilla::layers::FrameMetrics FrameMetrics;
@ -790,6 +791,16 @@ public:
static nsPoint MatrixTransformPoint(const nsPoint &aPoint,
const gfx3DMatrix &aMatrix, float aFactor);
/**
* Given a graphics rectangle in graphics space, return a rectangle in
* app space that contains the graphics rectangle, rounding out as necessary.
*
* @param aRect The graphics rect to round outward.
* @param aFactor The number of app units per graphics unit.
* @return The smallest rectangle in app space that contains aRect.
*/
static nsRect RoundGfxRectToAppRect(const Rect &aRect, float aFactor);
/**
* Given a graphics rectangle in graphics space, return a rectangle in
* app space that contains the graphics rectangle, rounding out as necessary.

Просмотреть файл

@ -6,6 +6,7 @@
// Keep in (case-insensitive) order:
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "mozilla/gfx/2D.h"
#include "imgIContainer.h"
#include "nsIImageLoadingContent.h"
#include "nsLayoutUtils.h"
@ -23,6 +24,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
class nsSVGImageFrame;
@ -469,32 +471,11 @@ nsSVGImageFrame::ReflowSVG()
return;
}
gfxContext tmpCtx(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
float x, y, width, height;
SVGImageElement *element = static_cast<SVGImageElement*>(mContent);
element->GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
// We'd like to just pass the identity matrix to GeneratePath, but if
// this frame's user space size is _very_ large/small then the extents we
// obtain below might have overflowed or otherwise be broken. This would
// cause us to end up with a broken mRect and visual overflow rect and break
// painting of this frame. This is particularly noticeable if the transforms
// between us and our nsSVGOuterSVGFrame scale this frame to a reasonable
// size. To avoid this we sadly have to do extra work to account for the
// transforms between us and our nsSVGOuterSVGFrame, even though the
// overwhelming number of SVGs will never have this problem.
// XXX Will Azure eventually save us from having to do this?
gfxSize scaleFactors = GetCanvasTM(FOR_OUTERSVG_TM).ScaleFactors(true);
bool applyScaling = fabs(scaleFactors.width) >= 1e-6 &&
fabs(scaleFactors.height) >= 1e-6;
Matrix scaling;
if (applyScaling) {
scaling.Scale(scaleFactors.width, scaleFactors.height);
}
tmpCtx.Save();
GeneratePath(&tmpCtx, scaling);
tmpCtx.Restore();
gfxRect extent = tmpCtx.GetUserPathExtent();
if (applyScaling) {
extent.Scale(1 / scaleFactors.width, 1 / scaleFactors.height);
}
Rect extent(x, y, width, height);
if (!extent.IsEmpty()) {
mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent,