/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
if (mOrientation.SwapsWidthAndHeight()) { auto i = aNativeSizes.Length(); while (i > 0) {
--i;
swap(aNativeSizes[i].width, aNativeSizes[i].height);
}
}
// If the image does not require any re-orientation, return aSurface itself. if (aOrientation.IsIdentity()) { return do_AddRef(aSurface);
}
// Determine the size of the new surface.
nsIntSize originalSize = aSurface->GetSize();
nsIntSize targetSize = originalSize; if (aOrientation.SwapsWidthAndHeight()) {
swap(targetSize.width, targetSize.height);
}
// Create our drawable.
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(aSurface, originalSize);
// Determine an appropriate format for the surface.
gfx::SurfaceFormat surfaceFormat = IsOpaque(aSurface->GetFormat())
? gfx::SurfaceFormat::OS_RGBX
: gfx::SurfaceFormat::OS_RGBA;
// Create the new surface to draw into.
RefPtr<DrawTarget> target =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
targetSize, surfaceFormat); if (!target || !target->IsValid()) {
NS_ERROR("Could not create a DrawTarget"); return nullptr;
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
OrientedImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { // Get a SourceSurface for the inner image then orient it according to // mOrientation.
RefPtr<SourceSurface> innerSurface =
InnerImage()->GetFrame(aWhichFrame, aFlags);
NS_ENSURE_TRUE(innerSurface, nullptr);
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
OrientedImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
uint32_t aFlags) { // Get a SourceSurface for the inner image then orient it according to // mOrientation.
IntSize innerSize = aSize; if (mOrientation.SwapsWidthAndHeight()) {
swap(innerSize.width, innerSize.height);
}
RefPtr<SourceSurface> innerSurface =
InnerImage()->GetFrameAtSize(innerSize, aWhichFrame, aFlags);
NS_ENSURE_TRUE(innerSurface, nullptr);
NS_IMETHODIMP_(ImgDrawResult)
OrientedImage::GetImageProvider(WindowRenderer* aRenderer, const gfx::IntSize& aSize, const SVGImageContext& aSVGContext, const Maybe<ImageIntRegion>& aRegion,
uint32_t aFlags,
WebRenderImageProvider** aProvider) { // XXX(seth): We currently don't have a way of orienting the result of // GetImageContainer. We work around this by always returning null, but if it // ever turns out that OrientedImage is widely used on codepaths that can // actually benefit from GetImageContainer, it would be a good idea to fix // that method for performance reasons.
// Apply reflection, if present. (For a regular, non-flipFirst reflection, // this logically happens second, but we apply it first because these // transformations are all premultiplied.) A translation is necessary to place // the image back in the first quadrant. if (aOrientation.flip == Flip::Horizontal && !aOrientation.flipFirst) { if (aOrientation.SwapsWidthAndHeight()) {
builder.Translate(gfxPoint(aSize.height, 0));
} else {
builder.Translate(gfxPoint(aSize.width, 0));
}
builder.Scale(-1.0, 1.0);
}
// Apply rotation, if present. Again, a translation is used to place the // image back in the first quadrant. switch (aOrientation.rotation) { case Angle::D0: break; case Angle::D90:
builder.Translate(gfxPoint(aSize.height, 0));
builder.Rotate(-1.5 * M_PI); break; case Angle::D180:
builder.Translate(gfxPoint(aSize.width, aSize.height));
builder.Rotate(-1.0 * M_PI); break; case Angle::D270:
builder.Translate(gfxPoint(0, aSize.width));
builder.Rotate(-0.5 * M_PI); break; default:
MOZ_ASSERT(false, "Invalid rotation value");
}
// Apply a flipFirst reflection. if (aOrientation.flip == Flip::Horizontal && aOrientation.flipFirst) {
builder.Translate(gfxPoint(aSize.width, 0.0));
builder.Scale(-1.0, 1.0);
}
// Update the image size to match the image's coordinate system. (This could // be done using TransformBounds but since it's only a size a swap is enough.)
nsIntSize size(aSize); if (mOrientation.SwapsWidthAndHeight()) {
swap(size.width, size.height);
}
// Update the matrix so that we transform the image into the orientation // expected by the caller before drawing.
gfxMatrix matrix(OrientationMatrix(size));
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
aContext->Multiply(matrix);
// The region is already in the orientation expected by the caller, but we // need it to be in the image's coordinate system, so we transform it using // the inverse of the orientation matrix.
gfxMatrix inverseMatrix(OrientationMatrix(size, /* aInvert = */ true));
ImageRegion region(aRegion);
region.TransformBoundsBy(inverseMatrix);
auto orientViewport = [&](const SVGImageContext& aOldContext) {
SVGImageContext context(aOldContext); auto oldViewport = aOldContext.GetViewportSize(); if (oldViewport && mOrientation.SwapsWidthAndHeight()) { // Swap width and height:
CSSIntSize newViewport(oldViewport->height, oldViewport->width);
context.SetViewportSize(Some(newViewport));
} return context;
};
// Swap the size for the calculation, then swap it back for the caller.
gfxSize destSize(aDest.height, aDest.width);
nsIntSize innerImageSize(InnerImage()->OptimalImageSizeForDest(
destSize, aWhichFrame, aSamplingFilter, aFlags)); return nsIntSize(innerImageSize.height, innerImageSize.width);
}
nsIntSize innerSize;
nsresult rv = InnerImage()->GetWidth(&innerSize.width);
rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&innerSize.height); if (NS_FAILED(rv)) { // Fall back to identity if the width and height aren't available. return rect;
}
// Transform the invalidation rect into the correct orientation.
gfxMatrix matrix(OrientationMatrix(innerSize));
gfxRect invalidRect(matrix.TransformBounds(
gfxRect(rect.X(), rect.Y(), rect.Width(), rect.Height())));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.