зеркало из https://github.com/mozilla/pjs.git
Bug 276431 part 3: Make nsImageFrame store an intrinsic ratio separate from its intrinsic size, and accept percentages in its intrinsic size. r=roc a=blocking
This commit is contained in:
Родитель
fd97e737fe
Коммит
6ab297b42d
|
@ -783,7 +783,7 @@ static PRBool
|
|||
GetIntrinsicSizeFor(nsIFrame* aFrame, nsSize& aIntrinsicSize)
|
||||
{
|
||||
// See if it is an image frame
|
||||
PRBool result = PR_FALSE;
|
||||
PRBool success = PR_FALSE;
|
||||
|
||||
// Currently the only type of replaced frame that we can get the intrinsic
|
||||
// size for is an image frame
|
||||
|
@ -792,10 +792,11 @@ GetIntrinsicSizeFor(nsIFrame* aFrame, nsSize& aIntrinsicSize)
|
|||
if (aFrame->GetType() == nsGkAtoms::imageFrame) {
|
||||
nsImageFrame* imageFrame = (nsImageFrame*)aFrame;
|
||||
|
||||
imageFrame->GetIntrinsicImageSize(aIntrinsicSize);
|
||||
result = (aIntrinsicSize != nsSize(0, 0));
|
||||
if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(aIntrinsicSize))) {
|
||||
success = (aIntrinsicSize != nsSize(0, 0));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1505,6 +1505,12 @@ public:
|
|||
IntrinsicSize& operator=(const IntrinsicSize& rhs) {
|
||||
width = rhs.width; height = rhs.height; return *this;
|
||||
}
|
||||
PRBool operator==(const IntrinsicSize& rhs) {
|
||||
return width == rhs.width && height == rhs.height;
|
||||
}
|
||||
PRBool operator!=(const IntrinsicSize& rhs) {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
virtual IntrinsicSize GetIntrinsicSize() = 0;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsStyleCoord.h"
|
||||
#include "nsImageMap.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIURL.h"
|
||||
|
@ -164,11 +165,13 @@ NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
|
|||
nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
|
||||
ImageFrameSuper(aContext),
|
||||
mComputedSize(0, 0),
|
||||
mIntrinsicSize(0, 0),
|
||||
mIntrinsicRatio(0, 0),
|
||||
mDisplayingIcon(PR_FALSE)
|
||||
{
|
||||
// We assume our size is not constrained and we haven't gotten an
|
||||
// initial reflow yet, so don't touch those flags.
|
||||
mIntrinsicSize.width.SetCoordValue(0);
|
||||
mIntrinsicSize.height.SetCoordValue(0);
|
||||
}
|
||||
|
||||
nsImageFrame::~nsImageFrame()
|
||||
|
@ -271,24 +274,55 @@ PRBool
|
|||
nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage)
|
||||
{
|
||||
NS_PRECONDITION(aImage, "null image");
|
||||
if (!aImage)
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool intrinsicSizeChanged = PR_FALSE;
|
||||
|
||||
if (aImage) {
|
||||
nsIFrame::IntrinsicSize oldIntrinsicSize = mIntrinsicSize;
|
||||
|
||||
nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
|
||||
if (rootFrame) {
|
||||
// Set intrinsic size to match that of aImage's rootFrame.
|
||||
mIntrinsicSize = rootFrame->GetIntrinsicSize();
|
||||
} else {
|
||||
// Set intrinsic size to match aImage's reported width & height.
|
||||
nsIntSize imageSizeInPx;
|
||||
if (NS_FAILED(aImage->GetWidth(&imageSizeInPx.width)) ||
|
||||
NS_FAILED(aImage->GetHeight(&imageSizeInPx.height))) {
|
||||
imageSizeInPx.SizeTo(0, 0);
|
||||
}
|
||||
nsSize newSize(nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.height));
|
||||
if (mIntrinsicSize != newSize) {
|
||||
intrinsicSizeChanged = PR_TRUE;
|
||||
mIntrinsicSize = newSize;
|
||||
}
|
||||
mIntrinsicSize.width.SetCoordValue(
|
||||
nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.width));
|
||||
mIntrinsicSize.height.SetCoordValue(
|
||||
nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.height));
|
||||
}
|
||||
|
||||
return intrinsicSizeChanged;
|
||||
return mIntrinsicSize != oldIntrinsicSize;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage)
|
||||
{
|
||||
NS_PRECONDITION(aImage, "null image");
|
||||
|
||||
if (!aImage)
|
||||
return PR_FALSE;
|
||||
|
||||
nsSize oldIntrinsicRatio = mIntrinsicRatio;
|
||||
|
||||
nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
|
||||
if (rootFrame) {
|
||||
// Set intrinsic ratio to match that of aImage's rootFrame.
|
||||
mIntrinsicRatio = rootFrame->GetIntrinsicRatio();
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord,
|
||||
"since aImage doesn't have a rootFrame, our intrinsic "
|
||||
"dimensions must have coord units (not percent units)");
|
||||
mIntrinsicRatio.width = mIntrinsicSize.width.GetCoordValue();
|
||||
mIntrinsicRatio.height = mIntrinsicSize.height.GetCoordValue();
|
||||
}
|
||||
|
||||
return mIntrinsicRatio != oldIntrinsicRatio;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -308,10 +342,16 @@ nsImageFrame::RecalculateTransform(PRBool aInnerAreaChanged)
|
|||
}
|
||||
|
||||
// Set the scale factors
|
||||
if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0 &&
|
||||
mIntrinsicSize != mComputedSize) {
|
||||
mTransform.SetScale(float(mComputedSize.width) / float(mIntrinsicSize.width),
|
||||
float(mComputedSize.height) / float(mIntrinsicSize.height));
|
||||
if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.width.GetCoordValue() != 0 &&
|
||||
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.height.GetCoordValue() != 0 &&
|
||||
mIntrinsicSize.width.GetCoordValue() != mComputedSize.width &&
|
||||
mIntrinsicSize.height.GetCoordValue() != mComputedSize.height) {
|
||||
mTransform.SetScale(float(mComputedSize.width) /
|
||||
float(mIntrinsicSize.width.GetCoordValue()),
|
||||
float(mComputedSize.height) /
|
||||
float(mIntrinsicSize.height.GetCoordValue()));
|
||||
} else {
|
||||
mTransform.SetScale(1.0f, 1.0f);
|
||||
}
|
||||
|
@ -485,9 +525,10 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
|
|||
}
|
||||
|
||||
UpdateIntrinsicSize(aImage);
|
||||
UpdateIntrinsicRatio(aImage);
|
||||
|
||||
if (mState & IMAGE_GOTINITIALREFLOW) {
|
||||
// If we previously set the intrinsic size (in EnsureIntrinsicSize)
|
||||
// If we previously set the intrinsic size (in EnsureIntrinsicSizeAndRatio)
|
||||
// to the size of the loading-image icon and reflowed the frame,
|
||||
// we'll have an mTransform computed from that intrinsic size. But
|
||||
// if we still have that transform when we get OnDataAvailable
|
||||
|
@ -578,10 +619,14 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest,
|
|||
aRequest->GetImage(getter_AddRefs(imageContainer));
|
||||
NS_ASSERTION(imageContainer, "Successful load with no container?");
|
||||
intrinsicSizeChanged = UpdateIntrinsicSize(imageContainer);
|
||||
intrinsicSizeChanged = UpdateIntrinsicRatio(imageContainer) ||
|
||||
intrinsicSizeChanged;
|
||||
}
|
||||
else {
|
||||
// Have to size to 0,0 so that GetDesiredSize recalculates the size
|
||||
mIntrinsicSize.SizeTo(0, 0);
|
||||
mIntrinsicSize.width.SetCoordValue(0);
|
||||
mIntrinsicSize.height.SetCoordValue(0);
|
||||
mIntrinsicRatio.SizeTo(0, 0);
|
||||
}
|
||||
|
||||
if (mState & IMAGE_GOTINITIALREFLOW) { // do nothing if we haven't gotten the initial reflow yet
|
||||
|
@ -623,11 +668,14 @@ nsImageFrame::FrameChanged(imgIContainer *aContainer,
|
|||
}
|
||||
|
||||
void
|
||||
nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext)
|
||||
nsImageFrame::EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext)
|
||||
{
|
||||
// if mIntrinsicSize.width and height are 0, then we should
|
||||
// check to see if the size is already known by the image container.
|
||||
if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0) {
|
||||
if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.width.GetCoordValue() == 0 &&
|
||||
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.height.GetCoordValue() == 0) {
|
||||
|
||||
// Jump through all the hoops to get the status of the request
|
||||
nsCOMPtr<imgIRequest> currentRequest;
|
||||
|
@ -645,6 +693,7 @@ nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext)
|
|||
currentRequest->GetImage(getter_AddRefs(imgCon));
|
||||
NS_ABORT_IF_FALSE(imgCon, "SIZE_AVAILABLE, but no imgContainer?");
|
||||
UpdateIntrinsicSize(imgCon);
|
||||
UpdateIntrinsicRatio(imgCon);
|
||||
} else {
|
||||
// image request is null or image size not known, probably an
|
||||
// invalid image specified
|
||||
|
@ -653,8 +702,12 @@ nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext)
|
|||
// XXX: we need this in composer, but it is also good for
|
||||
// XXX: general quirks mode to always have room for the icon
|
||||
if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
|
||||
mIntrinsicSize.SizeTo(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH))),
|
||||
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH))));
|
||||
nscoord edgeLengthToUse =
|
||||
nsPresContext::CSSPixelsToAppUnits(
|
||||
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
|
||||
mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
|
||||
mIntrinsicRatio.SizeTo(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -667,17 +720,11 @@ nsImageFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
|||
PRBool aShrinkWrap)
|
||||
{
|
||||
nsPresContext *presContext = PresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
|
||||
IntrinsicSize intrinsicSize;
|
||||
intrinsicSize.width.SetCoordValue(mIntrinsicSize.width);
|
||||
intrinsicSize.height.SetCoordValue(mIntrinsicSize.height);
|
||||
|
||||
nsSize& intrinsicRatio = mIntrinsicSize; // won't actually be used
|
||||
EnsureIntrinsicSizeAndRatio(presContext);
|
||||
|
||||
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
|
||||
aRenderingContext, this,
|
||||
intrinsicSize, intrinsicRatio, aCBSize,
|
||||
mIntrinsicSize, mIntrinsicRatio, aCBSize,
|
||||
aMargin, aBorder, aPadding);
|
||||
}
|
||||
|
||||
|
@ -707,9 +754,9 @@ nsImageFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
|||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
nsPresContext *presContext = PresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
result = mIntrinsicSize.width;
|
||||
return result;
|
||||
EnsureIntrinsicSizeAndRatio(presContext);
|
||||
return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
|
||||
mIntrinsicSize.width.GetCoordValue() : 0;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
|
@ -720,17 +767,16 @@ nsImageFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
|||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
nsPresContext *presContext = PresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
EnsureIntrinsicSizeAndRatio(presContext);
|
||||
// convert from normal twips to scaled twips (printing...)
|
||||
result = mIntrinsicSize.width;
|
||||
return result;
|
||||
return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
|
||||
mIntrinsicSize.width.GetCoordValue() : 0;
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsImageFrame::GetIntrinsicRatio()
|
||||
{
|
||||
EnsureIntrinsicSize(PresContext());
|
||||
return mIntrinsicSize;
|
||||
return mIntrinsicRatio;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1630,8 +1676,14 @@ nsImageFrame::GetSkipSides() const
|
|||
NS_IMETHODIMP
|
||||
nsImageFrame::GetIntrinsicImageSize(nsSize& aSize)
|
||||
{
|
||||
aSize = mIntrinsicSize;
|
||||
return NS_OK;
|
||||
if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
||||
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord) {
|
||||
aSize.SizeTo(mIntrinsicSize.width.GetCoordValue(),
|
||||
mIntrinsicSize.height.GetCoordValue());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -181,7 +181,7 @@ public:
|
|||
protected:
|
||||
virtual ~nsImageFrame();
|
||||
|
||||
void EnsureIntrinsicSize(nsPresContext* aPresContext);
|
||||
void EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext);
|
||||
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
|
@ -244,10 +244,18 @@ private:
|
|||
* Recalculate mIntrinsicSize from the image.
|
||||
*
|
||||
* @return whether aImage's size did _not_
|
||||
* match our previous intrinsic size
|
||||
* match our previous intrinsic size.
|
||||
*/
|
||||
PRBool UpdateIntrinsicSize(imgIContainer* aImage);
|
||||
|
||||
/**
|
||||
* Recalculate mIntrinsicRatio from the image.
|
||||
*
|
||||
* @return whether aImage's ratio did _not_
|
||||
* match our previous intrinsic ratio.
|
||||
*/
|
||||
PRBool UpdateIntrinsicRatio(imgIContainer* aImage);
|
||||
|
||||
/**
|
||||
* This function will recalculate mTransform.
|
||||
*/
|
||||
|
@ -272,7 +280,9 @@ private:
|
|||
nsCOMPtr<imgIDecoderObserver> mListener;
|
||||
|
||||
nsSize mComputedSize;
|
||||
nsSize mIntrinsicSize;
|
||||
nsIFrame::IntrinsicSize mIntrinsicSize;
|
||||
nsSize mIntrinsicRatio;
|
||||
|
||||
nsTransform2D mTransform;
|
||||
PRBool mDisplayingIcon;
|
||||
|
||||
|
|
|
@ -554,8 +554,9 @@ nsVideoFrame::GetVideoIntrinsicSize(nsIRenderingContext *aRenderingContext)
|
|||
if (child && child->GetType() == nsGkAtoms::imageFrame) {
|
||||
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
|
||||
nsSize imgsize;
|
||||
imageFrame->GetIntrinsicImageSize(imgsize);
|
||||
return imgsize;
|
||||
if (NS_SUCCEEDED(imageFrame->GetIntrinsicImageSize(imgsize))) {
|
||||
return imgsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче