diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 4d20df2885e..85175d5a007 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -31,6 +31,12 @@ class TimeStamp; class SVGImageContext; } +namespace mozilla { +namespace image { +class Orientation; +} +} + %} [ptr] native gfxImageSurface(gfxImageSurface); @@ -46,6 +52,7 @@ native nsSize(nsSize); [ptr] native nsIFrame(nsIFrame); [ptr] native ImageContainer(mozilla::layers::ImageContainer); [ptr] native LayerManager(mozilla::layers::LayerManager); +native Orientation(mozilla::image::Orientation); [ref] native TimeStamp(mozilla::TimeStamp); [ptr] native SVGImageContext(mozilla::SVGImageContext); @@ -57,7 +64,7 @@ native nsSize(nsSize); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(f9029a03-758c-4047-a1f3-4b2e51e47363)] +[scriptable, builtinclass, uuid(73340b79-e3ae-4f02-97d0-822db78017e5)] interface imgIContainer : nsISupports { /** @@ -302,6 +309,12 @@ interface imgIContainer : nsISupports */ [notxpcom] float getFrameIndex(in uint32_t aWhichFrame); + /* + * Returns the inherent orientation of the image, as described in the image's + * metadata (e.g. EXIF). + */ + [notxpcom] Orientation getOrientation(); + /* * Returns the delay, in ms, between the first and second frame. If this * returns 0, there is no delay between first and second frame (i.e., this diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp index cad1fe070fe..1d00bd43696 100644 --- a/image/src/ClippedImage.cpp +++ b/image/src/ClippedImage.cpp @@ -9,6 +9,7 @@ #include "mozilla/dom/SVGSVGElement.h" #include "ClippedImage.h" +#include "Orientation.h" using mozilla::layers::LayerManager; using mozilla::layers::ImageContainer; @@ -411,5 +412,13 @@ ClippedImage::RequestDiscard() return InnerImage()->RequestDiscard(); } +NS_IMETHODIMP_(Orientation) +ClippedImage::GetOrientation() +{ + // XXX(seth): This should not actually be here; this is just to work around a + // what appears to be a bug in MSVC's linker. + return InnerImage()->GetOrientation(); +} + } // namespace image } // namespace mozilla diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h index ff8ef0b5c15..1e640a269c1 100644 --- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -50,6 +50,7 @@ public: uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD RequestDiscard() MOZ_OVERRIDE; + NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE; protected: ClippedImage(Image* aImage, nsIntRect aClip); diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp index 4103724b86c..769ea813b33 100644 --- a/image/src/Decoder.cpp +++ b/image/src/Decoder.cpp @@ -266,7 +266,12 @@ Decoder::FlushInvalidations() void Decoder::SetSizeOnImage() { - mImage.SetSize(mImageMetadata.GetWidth(), mImageMetadata.GetHeight()); + MOZ_ASSERT(mImageMetadata.HasSize(), "Should have size"); + MOZ_ASSERT(mImageMetadata.HasOrientation(), "Should have orientation"); + + mImage.SetSize(mImageMetadata.GetWidth(), + mImageMetadata.GetHeight(), + mImageMetadata.GetOrientation()); } /* @@ -282,14 +287,16 @@ void Decoder::FinishInternal() { } */ void -Decoder::PostSize(int32_t aWidth, int32_t aHeight) +Decoder::PostSize(int32_t aWidth, + int32_t aHeight, + Orientation aOrientation /* = Orientation()*/) { // Validate NS_ABORT_IF_FALSE(aWidth >= 0, "Width can't be negative!"); NS_ABORT_IF_FALSE(aHeight >= 0, "Height can't be negative!"); // Tell the image - mImageMetadata.SetSize(aWidth, aHeight); + mImageMetadata.SetSize(aWidth, aHeight, aOrientation); // Notify the observer if (mObserver) diff --git a/image/src/Decoder.h b/image/src/Decoder.h index 463e4730066..7e0d01fa704 100644 --- a/image/src/Decoder.h +++ b/image/src/Decoder.h @@ -10,6 +10,7 @@ #include "imgDecoderObserver.h" #include "mozilla/RefPtr.h" #include "ImageMetadata.h" +#include "Orientation.h" namespace mozilla { namespace image { @@ -189,7 +190,9 @@ protected: // Called by decoders when they determine the size of the image. Informs // the image of its size and sends notifications. - void PostSize(int32_t aWidth, int32_t aHeight); + void PostSize(int32_t aWidth, + int32_t aHeight, + Orientation aOrientation = Orientation()); // Called by decoders when they begin a frame. Informs the image, sends // notifications, and does internal book-keeping. diff --git a/image/src/ImageMetadata.h b/image/src/ImageMetadata.h index 9a5db4e0122..1bddb0ededb 100644 --- a/image/src/ImageMetadata.h +++ b/image/src/ImageMetadata.h @@ -7,6 +7,7 @@ #include #include "mozilla/Util.h" #include "nsSize.h" +#include "Orientation.h" namespace mozilla { namespace image { @@ -42,15 +43,18 @@ public: mIsNonPremultiplied = nonPremult; } - void SetSize(int32_t width, int32_t height) + void SetSize(int32_t width, int32_t height, Orientation orientation) { mSize.construct(nsIntSize(width, height)); + mOrientation.construct(orientation); } bool HasSize() const { return !mSize.empty(); } + bool HasOrientation() const { return !mOrientation.empty(); } int32_t GetWidth() const { return mSize.ref().width; } int32_t GetHeight() const { return mSize.ref().height; } + Orientation GetOrientation() const { return mOrientation.ref(); } private: // The hotspot found on cursors, or -1 if none was found. @@ -61,6 +65,7 @@ private: int32_t mLoopCount; Maybe mSize; + Maybe mOrientation; bool mIsNonPremultiplied; }; diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index 5055b278468..8e630664597 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageWrapper.h" +#include "Orientation.h" #include "mozilla/MemoryReporting.h" @@ -167,6 +168,12 @@ ImageWrapper::GetIntrinsicRatio(nsSize* aSize) return mInnerImage->GetIntrinsicRatio(aSize); } +NS_IMETHODIMP_(Orientation) +ImageWrapper::GetOrientation() +{ + return mInnerImage->GetOrientation(); +} + NS_IMETHODIMP ImageWrapper::GetType(uint16_t* aType) { diff --git a/image/src/Orientation.h b/image/src/Orientation.h new file mode 100644 index 00000000000..c2fa82e6aed --- /dev/null +++ b/image/src/Orientation.h @@ -0,0 +1,62 @@ +/* -*- 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/. */ + +#ifndef MOZILLA_IMAGELIB_ORIENTATION_H_ +#define MOZILLA_IMAGELIB_ORIENTATION_H_ + +#include +#include "mozilla/TypedEnum.h" + +namespace mozilla { +namespace image { + +MOZ_BEGIN_ENUM_CLASS(Angle, uint8_t) + D0, + D90, + D180, + D270 +MOZ_END_ENUM_CLASS(Angle) + +MOZ_BEGIN_ENUM_CLASS(Flip, uint8_t) + Unflipped, + Horizontal +MOZ_END_ENUM_CLASS(Flip) + +/** + * A struct that describes an image's orientation as a rotation optionally + * followed by a reflection. This may be used to be indicate an image's inherent + * orientation or a desired orientation for the image. + */ +struct Orientation +{ + Orientation(Angle aRotation = Angle::D0, Flip mFlip = Flip::Unflipped) + : rotation(aRotation) + , flip(mFlip) + { } + + bool IsIdentity() const { + return (rotation == Angle::D0) && (flip == Flip::Unflipped); + } + + bool SwapsWidthAndHeight() const { + return (rotation == Angle::D90) || (rotation == Angle::D270); + } + + bool operator==(const Orientation& aOther) const { + return (rotation == aOther.rotation) && (flip == aOther.flip); + } + + bool operator!=(const Orientation& aOther) const { + return !(*this == aOther); + } + + Angle rotation; + Flip flip; +}; + +} +} + +#endif diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index e592fa5bc61..769d05bb75f 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -619,6 +619,12 @@ RasterImage::GetIntrinsicRatio(nsSize* aRatio) return NS_OK; } +NS_IMETHODIMP_(Orientation) +RasterImage::GetOrientation() +{ + return mOrientation; +} + //****************************************************************************** /* unsigned short GetType(); */ NS_IMETHODIMP @@ -1202,7 +1208,7 @@ RasterImage::ApplyDecodeFlags(uint32_t aNewFlags) } nsresult -RasterImage::SetSize(int32_t aWidth, int32_t aHeight) +RasterImage::SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation) { MOZ_ASSERT(NS_IsMainThread()); @@ -1216,7 +1222,9 @@ RasterImage::SetSize(int32_t aWidth, int32_t aHeight) // if we already have a size, check the new size against the old one if (!mMultipart && mHasSize && - ((aWidth != mSize.width) || (aHeight != mSize.height))) { + ((aWidth != mSize.width) || + (aHeight != mSize.height) || + (aOrientation != mOrientation))) { NS_WARNING("Image changed size on redecode! This should not happen!"); // Make the decoder aware of the error so that it doesn't try to call @@ -1230,6 +1238,7 @@ RasterImage::SetSize(int32_t aWidth, int32_t aHeight) // Set the size and flag that we have it mSize.SizeTo(aWidth, aHeight); + mOrientation = aOrientation; mHasSize = true; mFrameBlender.SetSize(mSize); diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index bc43fec8a01..80f9136069c 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -28,6 +28,7 @@ #include "imgFrame.h" #include "nsThreadUtils.h" #include "DiscardTracker.h" +#include "Orientation.h" #include "nsISupportsImpl.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TimeStamp.h" @@ -186,13 +187,11 @@ public: /* Callbacks for decoders */ nsresult SetFrameAsNonPremult(uint32_t aFrameNum, bool aIsNonPremult); - /** - * Sets the size of the container. This should only be called by the - * decoder. This function may be called multiple times, but will throw an - * error if subsequent calls do not match the first. + /** Sets the size and inherent orientation of the container. This should only + * be called by the decoder. This function may be called multiple times, but + * will throw an error if subsequent calls do not match the first. */ - nsresult SetSize(int32_t aWidth, int32_t aHeight); - + nsresult SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation); /** * Ensures that a given frame number exists with the given parameters, and @@ -583,6 +582,7 @@ private: private: // data nsIntSize mSize; + Orientation mOrientation; // Whether our frames were decoded using any special flags. // Some flags (e.g. unpremultiplied data) may not be compatible diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 489804492d5..4e8ce33d773 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -27,6 +27,7 @@ #include "nsStubDocumentObserver.h" #include "nsSVGEffects.h" // for nsSVGRenderingObserver #include "nsSVGUtils.h" // for nsSVGUtils::ConvertToSurfaceSize +#include "Orientation.h" #include "SVGDocumentWrapper.h" namespace mozilla { @@ -540,6 +541,12 @@ VectorImage::GetIntrinsicRatio(nsSize* aRatio) return NS_OK; } +NS_IMETHODIMP_(Orientation) +VectorImage::GetOrientation() +{ + return Orientation(); +} + //****************************************************************************** /* readonly attribute unsigned short type; */ NS_IMETHODIMP