зеркало из https://github.com/mozilla/gecko-dev.git
Bug 988818 - Stop creating a Thebes (gfxASurface) backed gfxContext in nsSVGImageFrame (Moz2D migration). r=longsonr
This commit is contained in:
Родитель
00bb2b13a2
Коммит
87ad440e7c
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче