2001-09-29 00:14:13 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2006-03-29 22:29:03 +04:00
|
|
|
|
|
|
|
/* rendering object for replaced elements with bitmap image data */
|
|
|
|
|
2013-09-25 05:43:43 +04:00
|
|
|
#include "nsImageFrame.h"
|
|
|
|
|
2012-12-15 03:58:45 +04:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2013-09-25 15:21:18 +04:00
|
|
|
#include "mozilla/MouseEvents.h"
|
2011-10-11 09:50:08 +04:00
|
|
|
|
1999-07-08 23:38:08 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2003-03-19 06:47:09 +03:00
|
|
|
#include "nsIImageLoadingContent.h"
|
1998-09-09 02:34:40 +04:00
|
|
|
#include "nsString.h"
|
2002-11-20 03:44:26 +03:00
|
|
|
#include "nsPrintfCString.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
2011-04-08 05:04:40 +04:00
|
|
|
#include "nsRenderingContext.h"
|
1998-09-09 02:34:40 +04:00
|
|
|
#include "nsIPresShell.h"
|
2007-01-30 03:06:41 +03:00
|
|
|
#include "nsGkAtoms.h"
|
1998-09-09 02:34:40 +04:00
|
|
|
#include "nsIDocument.h"
|
2004-04-30 03:34:19 +04:00
|
|
|
#include "nsContentUtils.h"
|
2007-12-03 12:24:49 +03:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
#include "nsStyleContext.h"
|
1998-09-09 02:34:40 +04:00
|
|
|
#include "nsStyleConsts.h"
|
2010-09-09 00:40:38 +04:00
|
|
|
#include "nsStyleCoord.h"
|
2010-09-09 00:40:38 +04:00
|
|
|
#include "nsTransform2D.h"
|
1999-01-09 03:13:19 +03:00
|
|
|
#include "nsImageMap.h"
|
1999-06-18 21:34:08 +04:00
|
|
|
#include "nsIIOService.h"
|
2001-03-22 04:38:35 +03:00
|
|
|
#include "nsILoadGroup.h"
|
2005-02-21 23:58:01 +03:00
|
|
|
#include "nsISupportsPriority.h"
|
1999-11-30 07:50:42 +03:00
|
|
|
#include "nsNetUtil.h"
|
1998-09-09 02:34:40 +04:00
|
|
|
#include "nsCSSRendering.h"
|
1999-07-08 23:38:08 +04:00
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
1998-12-20 04:21:23 +03:00
|
|
|
#include "nsINameSpaceManager.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2001-08-17 07:13:07 +04:00
|
|
|
#ifdef ACCESSIBILITY
|
2011-01-28 07:38:14 +03:00
|
|
|
#include "nsAccessibilityService.h"
|
2001-08-17 07:13:07 +04:00
|
|
|
#endif
|
2001-04-01 05:01:33 +04:00
|
|
|
#include "nsIDOMNode.h"
|
2005-08-23 07:57:07 +04:00
|
|
|
#include "nsLayoutUtils.h"
|
2006-01-26 05:29:17 +03:00
|
|
|
#include "nsDisplayList.h"
|
2001-04-01 05:01:33 +04:00
|
|
|
|
2001-05-04 10:29:59 +04:00
|
|
|
#include "imgIContainer.h"
|
2012-11-16 22:24:58 +04:00
|
|
|
#include "imgLoader.h"
|
2012-10-12 16:43:01 +04:00
|
|
|
#include "imgRequestProxy.h"
|
2001-05-04 10:29:59 +04:00
|
|
|
|
2001-11-07 08:02:42 +03:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
2003-04-23 03:18:34 +04:00
|
|
|
#include "nsIDOMRange.h"
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-09 01:31:05 +04:00
|
|
|
|
2011-04-21 21:35:52 +04:00
|
|
|
#include "nsEventStates.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2006-07-31 11:08:45 +04:00
|
|
|
#include "nsBidiUtils.h"
|
|
|
|
#include "nsBidiPresUtils.h"
|
2003-04-22 03:57:47 +04:00
|
|
|
|
2011-01-18 00:47:18 +03:00
|
|
|
#include "gfxRect.h"
|
2011-04-26 10:04:18 +04:00
|
|
|
#include "ImageLayers.h"
|
2012-08-19 23:33:25 +04:00
|
|
|
#include "ImageContainer.h"
|
2013-08-20 02:55:18 +04:00
|
|
|
#include "nsStyleSet.h"
|
|
|
|
#include "nsBlockFrame.h"
|
2013-10-02 01:01:49 +04:00
|
|
|
#include "nsStyleStructInlines.h"
|
2011-01-18 00:47:18 +03:00
|
|
|
|
2011-05-25 10:31:59 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
|
|
|
|
2013-08-08 09:26:32 +04:00
|
|
|
#include "mozilla/dom/Link.h"
|
|
|
|
|
2011-05-25 10:31:59 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2002-03-26 23:14:05 +03:00
|
|
|
// sizes (pixels) for image icon, padding and border frame
|
|
|
|
#define ICON_SIZE (16)
|
|
|
|
#define ICON_PADDING (3)
|
|
|
|
#define ALT_BORDER_WIDTH (1)
|
|
|
|
|
|
|
|
|
2003-04-23 03:18:34 +04:00
|
|
|
//we must add hooks soon
|
|
|
|
#define IMAGE_EDITOR_CHECK 1
|
|
|
|
|
1998-09-09 02:34:40 +04:00
|
|
|
// Default alignment value (so we can tell an unset value from a set value)
|
2012-08-22 19:56:38 +04:00
|
|
|
#define ALIGN_UNSET uint8_t(-1)
|
1998-09-09 02:34:40 +04:00
|
|
|
|
2011-01-18 00:47:18 +03:00
|
|
|
using namespace mozilla::layers;
|
2011-06-01 05:46:56 +04:00
|
|
|
using namespace mozilla::dom;
|
2011-01-18 00:47:18 +03:00
|
|
|
|
2004-02-03 23:30:02 +03:00
|
|
|
// static icon information
|
2012-07-30 18:20:58 +04:00
|
|
|
nsImageFrame::IconLoad* nsImageFrame::gIconLoad = nullptr;
|
2001-11-07 08:02:42 +03:00
|
|
|
|
2004-01-21 12:35:59 +03:00
|
|
|
// cached IO service for loading icons
|
|
|
|
nsIIOService* nsImageFrame::sIOService;
|
|
|
|
|
2001-11-07 08:02:42 +03:00
|
|
|
// test if the width and height are fixed, looking at the style data
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool HaveFixedSize(const nsStylePosition* aStylePosition)
|
2001-11-07 08:02:42 +03:00
|
|
|
{
|
|
|
|
// check the width and height values in the reflow state's style struct
|
|
|
|
// - if width and height are specified as either coord or percentage, then
|
|
|
|
// the size of the image frame is constrained
|
2010-08-11 23:32:53 +04:00
|
|
|
return aStylePosition->mWidth.IsCoordPercentCalcUnit() &&
|
|
|
|
aStylePosition->mHeight.IsCoordPercentCalcUnit();
|
2001-11-07 08:02:42 +03:00
|
|
|
}
|
2001-03-06 03:47:46 +03:00
|
|
|
// use the data in the reflow state to decide if the image has a constrained size
|
|
|
|
// (i.e. width and height that are based on the containing block size and not the image size)
|
|
|
|
// so we can avoid animated GIF related reflows
|
2011-09-29 10:19:26 +04:00
|
|
|
inline bool HaveFixedSize(const nsHTMLReflowState& aReflowState)
|
2001-11-07 08:02:42 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aReflowState.mStylePosition, "crappy reflowState - null stylePosition");
|
2007-08-02 22:08:05 +04:00
|
|
|
// when an image has percent css style height or width, but ComputedHeight()
|
2007-01-26 03:05:12 +03:00
|
|
|
// or ComputedWidth() of reflow state is NS_UNCONSTRAINEDSIZE
|
2011-10-17 18:59:28 +04:00
|
|
|
// it needs to return false to cause an incremental reflow later
|
2002-11-07 05:50:39 +03:00
|
|
|
// if an image is inside table like bug 156731 simple testcase III,
|
2007-01-26 03:05:12 +03:00
|
|
|
// during pass 1 reflow, ComputedWidth() is NS_UNCONSTRAINEDSIZE
|
2011-10-17 18:59:28 +04:00
|
|
|
// in pass 2 reflow, ComputedWidth() is 0, it also needs to return false
|
2002-11-07 05:50:39 +03:00
|
|
|
// see bug 156731
|
2010-08-11 23:32:53 +04:00
|
|
|
const nsStyleCoord &height = aReflowState.mStylePosition->mHeight;
|
|
|
|
const nsStyleCoord &width = aReflowState.mStylePosition->mWidth;
|
2010-08-25 14:17:55 +04:00
|
|
|
return ((height.HasPercent() &&
|
2010-08-11 23:32:53 +04:00
|
|
|
NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
|
2010-08-25 14:17:55 +04:00
|
|
|
(width.HasPercent() &&
|
2010-08-11 23:32:53 +04:00
|
|
|
(NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
|
|
|
|
0 == aReflowState.ComputedWidth())))
|
2011-10-17 18:59:28 +04:00
|
|
|
? false
|
2003-05-15 07:42:21 +04:00
|
|
|
: HaveFixedSize(aReflowState.mStylePosition);
|
2001-11-07 08:02:42 +03:00
|
|
|
}
|
2001-03-06 03:47:46 +03:00
|
|
|
|
2005-11-01 23:40:54 +03:00
|
|
|
nsIFrame*
|
2006-03-27 01:30:36 +04:00
|
|
|
NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2006-03-27 01:30:36 +04:00
|
|
|
return new (aPresShell) nsImageFrame(aContext);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
2009-09-12 20:49:24 +04:00
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
|
|
|
|
|
2001-10-06 09:08:16 +04:00
|
|
|
|
2006-03-27 01:30:36 +04:00
|
|
|
nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
|
|
|
|
ImageFrameSuper(aContext),
|
2003-03-19 06:47:09 +03:00
|
|
|
mComputedSize(0, 0),
|
2010-09-09 00:40:38 +04:00
|
|
|
mIntrinsicRatio(0, 0),
|
2012-10-12 20:11:23 +04:00
|
|
|
mDisplayingIcon(false),
|
2013-09-15 04:05:05 +04:00
|
|
|
mFirstFrameComplete(false),
|
|
|
|
mReflowCallbackPosted(false)
|
2000-04-19 18:00:11 +04:00
|
|
|
{
|
2003-03-19 06:47:09 +03:00
|
|
|
// We assume our size is not constrained and we haven't gotten an
|
|
|
|
// initial reflow yet, so don't touch those flags.
|
2010-09-09 00:40:38 +04:00
|
|
|
mIntrinsicSize.width.SetCoordValue(0);
|
|
|
|
mIntrinsicSize.height.SetCoordValue(0);
|
2000-04-19 18:00:11 +04:00
|
|
|
}
|
|
|
|
|
1998-11-20 20:21:02 +03:00
|
|
|
nsImageFrame::~nsImageFrame()
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-01-12 22:20:59 +03:00
|
|
|
NS_QUERYFRAME_HEAD(nsImageFrame)
|
2011-04-26 10:52:19 +04:00
|
|
|
NS_QUERYFRAME_ENTRY(nsImageFrame)
|
2009-01-12 22:20:59 +03:00
|
|
|
NS_QUERYFRAME_TAIL_INHERITING(ImageFrameSuper)
|
2001-02-20 00:50:04 +03:00
|
|
|
|
2001-08-17 07:13:07 +04:00
|
|
|
#ifdef ACCESSIBILITY
|
2012-09-29 01:53:44 +04:00
|
|
|
a11y::AccType
|
|
|
|
nsImageFrame::AccessibleType()
|
2001-05-18 03:52:32 +04:00
|
|
|
{
|
2012-09-29 01:53:44 +04:00
|
|
|
// Don't use GetImageMap() to avoid reentrancy into accessibility.
|
|
|
|
if (HasImageMap()) {
|
2012-12-18 05:25:52 +04:00
|
|
|
return a11y::eHTMLImageMapType;
|
2001-05-18 03:52:32 +04:00
|
|
|
}
|
|
|
|
|
2012-12-18 05:25:52 +04:00
|
|
|
return a11y::eImageType;
|
2001-05-18 03:52:32 +04:00
|
|
|
}
|
2001-08-17 07:13:07 +04:00
|
|
|
#endif
|
2001-05-18 03:52:32 +04:00
|
|
|
|
2006-04-10 04:16:29 +04:00
|
|
|
void
|
2011-10-29 14:44:50 +04:00
|
|
|
nsImageFrame::DisconnectMap()
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2003-03-19 06:47:09 +03:00
|
|
|
if (mImageMap) {
|
2001-05-04 10:29:59 +04:00
|
|
|
mImageMap->Destroy();
|
|
|
|
NS_RELEASE(mImageMap);
|
2012-03-16 00:16:02 +04:00
|
|
|
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
nsAccessibilityService* accService = GetAccService();
|
|
|
|
if (accService) {
|
|
|
|
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
|
|
|
|
}
|
|
|
|
#endif
|
2001-05-04 10:29:59 +04:00
|
|
|
}
|
2011-10-29 14:44:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|
|
|
{
|
2013-09-15 04:05:05 +04:00
|
|
|
if (mReflowCallbackPosted) {
|
|
|
|
PresContext()->PresShell()->CancelReflowCallback(this);
|
|
|
|
mReflowCallbackPosted = false;
|
|
|
|
}
|
|
|
|
|
2011-10-29 14:44:50 +04:00
|
|
|
// Tell our image map, if there is one, to clean up
|
|
|
|
// This causes the nsImageMap to unregister itself as
|
|
|
|
// a DOM listener.
|
|
|
|
DisconnectMap();
|
1998-09-09 02:34:40 +04:00
|
|
|
|
2001-04-15 06:13:49 +04:00
|
|
|
// set the frame to null so we don't send messages to a dead object.
|
2003-03-19 06:47:09 +03:00
|
|
|
if (mListener) {
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
|
|
|
if (imageLoader) {
|
2011-11-10 01:39:16 +04:00
|
|
|
// Notify our image loading content that we are going away so it can
|
|
|
|
// deregister with our refresh driver.
|
|
|
|
imageLoader->FrameDestroyed(this);
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
imageLoader->RemoveObserver(mListener);
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
reinterpret_cast<nsImageListener*>(mListener.get())->SetFrame(nullptr);
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mListener = nullptr;
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
// If we were displaying an icon, take ourselves off the list
|
|
|
|
if (mDisplayingIcon)
|
|
|
|
gIconLoad->RemoveIconObserver(this);
|
|
|
|
|
2009-12-24 08:21:15 +03:00
|
|
|
nsSplittableFrame::DestroyFrom(aDestructRoot);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
2001-03-22 04:38:35 +03:00
|
|
|
|
|
|
|
|
2013-03-20 05:47:48 +04:00
|
|
|
void
|
2006-03-09 21:55:21 +03:00
|
|
|
nsImageFrame::Init(nsIContent* aContent,
|
1999-01-14 08:16:23 +03:00
|
|
|
nsIFrame* aParent,
|
1999-02-25 06:27:57 +03:00
|
|
|
nsIFrame* aPrevInFlow)
|
1998-12-29 06:38:16 +03:00
|
|
|
{
|
2013-03-20 05:47:48 +04:00
|
|
|
nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
|
2003-02-26 08:51:32 +03:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
mListener = new nsImageListener(this);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent);
|
2013-03-20 05:47:48 +04:00
|
|
|
if (!imageLoader) {
|
|
|
|
NS_RUNTIMEABORT("Why do we have an nsImageFrame here at all?");
|
|
|
|
}
|
2011-02-01 07:50:01 +03:00
|
|
|
|
2013-06-12 11:00:09 +04:00
|
|
|
imageLoader->AddObserver(mListener);
|
2003-03-19 06:47:09 +03:00
|
|
|
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *aPresContext = PresContext();
|
2006-03-09 21:55:21 +03:00
|
|
|
|
2004-02-03 23:30:02 +03:00
|
|
|
if (!gIconLoad)
|
|
|
|
LoadIcons(aPresContext);
|
2003-03-19 06:47:09 +03:00
|
|
|
|
2011-11-10 01:39:16 +04:00
|
|
|
// We have a PresContext now, so we need to notify the image content node
|
|
|
|
// that it can register images.
|
|
|
|
imageLoader->FrameCreated(this);
|
|
|
|
|
2005-09-18 22:05:40 +04:00
|
|
|
// Give image loads associated with an image frame a small priority boost!
|
2003-03-19 06:47:09 +03:00
|
|
|
nsCOMPtr<imgIRequest> currentRequest;
|
|
|
|
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(currentRequest));
|
2005-09-18 22:05:40 +04:00
|
|
|
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(currentRequest);
|
|
|
|
if (p)
|
|
|
|
p->AdjustPriority(-1);
|
2005-02-21 23:58:01 +03:00
|
|
|
|
2003-05-04 22:06:10 +04:00
|
|
|
// If we already have an image container, OnStartContainer won't be called
|
2003-12-26 07:24:11 +03:00
|
|
|
if (currentRequest) {
|
2004-01-08 21:29:28 +03:00
|
|
|
nsCOMPtr<imgIContainer> image;
|
2003-05-04 22:06:10 +04:00
|
|
|
currentRequest->GetImage(getter_AddRefs(image));
|
2013-08-29 02:39:06 +04:00
|
|
|
OnStartContainer(currentRequest, image);
|
2003-05-04 22:06:10 +04:00
|
|
|
}
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2007-03-20 03:58:20 +03:00
|
|
|
nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage)
|
2003-03-19 06:47:09 +03:00
|
|
|
{
|
2007-03-20 03:58:20 +03:00
|
|
|
NS_PRECONDITION(aImage, "null image");
|
2010-09-09 00:40:38 +04:00
|
|
|
if (!aImage)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-03-20 03:58:20 +03:00
|
|
|
|
2013-10-01 01:26:04 +04:00
|
|
|
IntrinsicSize oldIntrinsicSize = mIntrinsicSize;
|
|
|
|
mIntrinsicSize = IntrinsicSize();
|
2013-01-11 07:38:34 +04:00
|
|
|
|
|
|
|
// Set intrinsic size to match aImage's reported intrinsic width & height.
|
|
|
|
nsSize intrinsicSize;
|
|
|
|
if (NS_SUCCEEDED(aImage->GetIntrinsicSize(&intrinsicSize))) {
|
|
|
|
// If the image has no intrinsic width, intrinsicSize.width will be -1, and
|
|
|
|
// we can leave mIntrinsicSize.width at its default value of eStyleUnit_None.
|
|
|
|
// Otherwise we use intrinsicSize.width. Height works the same way.
|
|
|
|
if (intrinsicSize.width != -1)
|
|
|
|
mIntrinsicSize.width.SetCoordValue(intrinsicSize.width);
|
|
|
|
if (intrinsicSize.height != -1)
|
|
|
|
mIntrinsicSize.height.SetCoordValue(intrinsicSize.height);
|
2010-09-09 00:40:38 +04:00
|
|
|
} else {
|
2013-01-11 07:38:34 +04:00
|
|
|
// Failure means that the image hasn't loaded enough to report a result. We
|
|
|
|
// treat this case as if the image's intrinsic size was 0x0.
|
|
|
|
mIntrinsicSize.width.SetCoordValue(0);
|
|
|
|
mIntrinsicSize.height.SetCoordValue(0);
|
1999-02-27 03:57:04 +03:00
|
|
|
}
|
|
|
|
|
2010-09-09 00:40:38 +04:00
|
|
|
return mIntrinsicSize != oldIntrinsicSize;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-09-09 00:40:38 +04:00
|
|
|
nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aImage, "null image");
|
|
|
|
|
|
|
|
if (!aImage)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-09-09 00:40:38 +04:00
|
|
|
|
|
|
|
nsSize oldIntrinsicRatio = mIntrinsicRatio;
|
|
|
|
|
2013-01-11 07:38:34 +04:00
|
|
|
// Set intrinsic ratio to match aImage's reported intrinsic ratio.
|
|
|
|
if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio)))
|
|
|
|
mIntrinsicRatio.SizeTo(0, 0);
|
2010-09-09 00:40:38 +04:00
|
|
|
|
|
|
|
return mIntrinsicRatio != oldIntrinsicRatio;
|
2007-03-20 03:58:20 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-09-09 00:40:38 +04:00
|
|
|
nsImageFrame::GetSourceToDestTransform(nsTransform2D& aTransform)
|
2007-03-20 03:58:20 +03:00
|
|
|
{
|
2010-09-09 00:40:38 +04:00
|
|
|
// Set the translation components.
|
2003-03-19 06:47:09 +03:00
|
|
|
// XXXbz does this introduce rounding errors because of the cast to
|
|
|
|
// float? Should we just manually add that stuff in every time
|
|
|
|
// instead?
|
2010-09-09 00:40:38 +04:00
|
|
|
nsRect innerArea = GetInnerArea();
|
|
|
|
aTransform.SetToTranslate(float(innerArea.x),
|
|
|
|
float(innerArea.y - GetContinuationOffset()));
|
|
|
|
|
|
|
|
// Set the scale factors.
|
2010-09-09 00:40:38 +04:00
|
|
|
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) {
|
2010-09-09 00:40:38 +04:00
|
|
|
|
|
|
|
aTransform.SetScale(float(mComputedSize.width) /
|
2010-09-09 00:40:38 +04:00
|
|
|
float(mIntrinsicSize.width.GetCoordValue()),
|
|
|
|
float(mComputedSize.height) /
|
|
|
|
float(mIntrinsicSize.height.GetCoordValue()));
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2010-09-09 00:40:38 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
/*
|
|
|
|
* These two functions basically do the same check. The first one
|
|
|
|
* checks that the given request is the current request for our
|
|
|
|
* mContent. The second checks that the given image container the
|
|
|
|
* same as the image container on the current request for our
|
|
|
|
* mContent.
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2003-03-19 06:47:09 +03:00
|
|
|
nsImageFrame::IsPendingLoad(imgIRequest* aRequest) const
|
|
|
|
{
|
|
|
|
// Default to pending load in case of errors
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
|
|
|
|
NS_ASSERTION(imageLoader, "No image loading content?");
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t requestType = nsIImageLoadingContent::UNKNOWN_REQUEST;
|
2003-03-19 06:47:09 +03:00
|
|
|
imageLoader->GetRequestType(aRequest, &requestType);
|
|
|
|
|
|
|
|
return requestType != nsIImageLoadingContent::CURRENT_REQUEST;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2003-03-19 06:47:09 +03:00
|
|
|
nsImageFrame::IsPendingLoad(imgIContainer* aContainer) const
|
|
|
|
{
|
|
|
|
// default to pending load in case of errors
|
|
|
|
if (!aContainer) {
|
|
|
|
NS_ERROR("No image container!");
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
|
|
|
|
NS_ASSERTION(imageLoader, "No image loading content?");
|
|
|
|
|
|
|
|
nsCOMPtr<imgIRequest> currentRequest;
|
|
|
|
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(currentRequest));
|
|
|
|
if (!currentRequest) {
|
|
|
|
NS_ERROR("No current request");
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<imgIContainer> currentContainer;
|
|
|
|
currentRequest->GetImage(getter_AddRefs(currentContainer));
|
|
|
|
|
|
|
|
return currentContainer != aContainer;
|
|
|
|
|
1998-12-29 06:38:16 +03:00
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsRect
|
2009-01-15 06:27:09 +03:00
|
|
|
nsImageFrame::SourceRectToDest(const nsIntRect& aRect)
|
2003-03-19 06:47:09 +03:00
|
|
|
{
|
2004-08-29 03:59:15 +04:00
|
|
|
// When scaling the image, row N of the source image may (depending on
|
|
|
|
// the scaling function) be used to draw any row in the destination image
|
|
|
|
// between floor(F * (N-1)) and ceil(F * (N+1)), where F is the
|
|
|
|
// floating-point scaling factor. The same holds true for columns.
|
|
|
|
// So, we start by computing that bound without the floor and ceiling.
|
|
|
|
|
2007-02-07 10:46:44 +03:00
|
|
|
nsRect r(nsPresContext::CSSPixelsToAppUnits(aRect.x - 1),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(aRect.y - 1),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(aRect.width + 2),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(aRect.height + 2));
|
2004-08-29 03:59:15 +04:00
|
|
|
|
2010-09-09 00:40:38 +04:00
|
|
|
nsTransform2D sourceToDest;
|
|
|
|
if (!GetSourceToDestTransform(sourceToDest)) {
|
|
|
|
// Failed to generate transform matrix. Return our whole inner area,
|
|
|
|
// to be on the safe side (since this method is used for generating
|
|
|
|
// invalidation rects).
|
|
|
|
return GetInnerArea();
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceToDest.TransformCoord(&r.x, &r.y, &r.width, &r.height);
|
2004-08-29 03:59:15 +04:00
|
|
|
|
|
|
|
// Now, round the edges out to the pixel boundary.
|
2010-09-09 00:40:38 +04:00
|
|
|
nscoord scale = nsPresContext::CSSPixelsToAppUnits(1);
|
2004-08-29 03:59:15 +04:00
|
|
|
nscoord right = r.x + r.width;
|
|
|
|
nscoord bottom = r.y + r.height;
|
|
|
|
|
|
|
|
r.x -= (scale + (r.x % scale)) % scale;
|
|
|
|
r.y -= (scale + (r.y % scale)) % scale;
|
|
|
|
r.width = right + ((scale - (right % scale)) % scale) - r.x;
|
|
|
|
r.height = bottom + ((scale - (bottom % scale)) % scale) - r.y;
|
|
|
|
|
|
|
|
return r;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2005-11-02 03:04:29 +03:00
|
|
|
// Note that we treat NS_EVENT_STATE_SUPPRESSED images as "OK". This means
|
|
|
|
// that we'll construct image frames for them as needed if their display is
|
|
|
|
// toggled from "none" (though we won't paint them, unless their visibility
|
|
|
|
// is changed too).
|
|
|
|
#define BAD_STATES (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | \
|
|
|
|
NS_EVENT_STATE_LOADING)
|
|
|
|
|
|
|
|
// This is a macro so that we don't evaluate the boolean last arg
|
|
|
|
// unless we have to; it can be expensive
|
2010-10-20 15:26:32 +04:00
|
|
|
#define IMAGE_OK(_state, _loadingOK) \
|
|
|
|
(!(_state).HasAtLeastOneOfStates(BAD_STATES) || \
|
|
|
|
(!(_state).HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED) && \
|
|
|
|
(_state).HasState(NS_EVENT_STATE_LOADING) && (_loadingOK)))
|
2003-03-19 06:47:09 +03:00
|
|
|
|
2005-09-18 22:05:40 +04:00
|
|
|
/* static */
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2011-06-01 05:46:56 +04:00
|
|
|
nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
|
2005-09-18 22:05:40 +04:00
|
|
|
nsStyleContext* aStyleContext)
|
|
|
|
{
|
2011-06-01 05:46:57 +04:00
|
|
|
nsEventStates state = aElement->State();
|
2005-11-02 03:04:29 +03:00
|
|
|
if (IMAGE_OK(state,
|
2013-02-17 01:51:02 +04:00
|
|
|
HaveFixedSize(aStyleContext->StylePosition()))) {
|
2005-09-18 22:05:40 +04:00
|
|
|
// Image is fine; do the image frame thing
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2005-10-17 04:50:39 +04:00
|
|
|
|
2003-04-29 22:49:42 +04:00
|
|
|
// Check if we want to use a placeholder box with an icon or just
|
2005-11-21 01:05:24 +03:00
|
|
|
// let the presShell make us into inline text. Decide as follows:
|
2003-04-29 22:49:42 +04:00
|
|
|
//
|
|
|
|
// - if our special "force icons" style is set, show an icon
|
|
|
|
// - else if our "do not show placeholders" pref is set, skip the icon
|
|
|
|
// - else:
|
2013-10-06 00:25:49 +04:00
|
|
|
// - if there is a src attribute, there is no alt attribute,
|
|
|
|
// and this is not an <object> (which could not possibly have
|
|
|
|
// such an attribute), show an icon.
|
2005-09-18 22:05:40 +04:00
|
|
|
// - if QuirksMode, and the IMG has a size show an icon.
|
2003-04-29 22:49:42 +04:00
|
|
|
// - otherwise, skip the icon
|
2011-09-29 10:19:26 +04:00
|
|
|
bool useSizedBox;
|
2003-04-29 22:49:42 +04:00
|
|
|
|
2013-02-17 01:51:02 +04:00
|
|
|
if (aStyleContext->StyleUIReset()->mForceBrokenImageIcon) {
|
2011-10-17 18:59:28 +04:00
|
|
|
useSizedBox = true;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2004-02-03 23:30:02 +03:00
|
|
|
else if (gIconLoad && gIconLoad->mPrefForceInlineAltText) {
|
2011-10-17 18:59:28 +04:00
|
|
|
useSizedBox = false;
|
2003-04-29 22:49:42 +04:00
|
|
|
}
|
2013-10-06 00:25:49 +04:00
|
|
|
else if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
|
|
|
|
!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::alt) &&
|
|
|
|
!aElement->IsHTML(nsGkAtoms::object) &&
|
|
|
|
!aElement->IsHTML(nsGkAtoms::input)) {
|
|
|
|
// Use a sized box if we have no alt text. This means no alt attribute
|
|
|
|
// and the node is not an object or an input (since those always have alt
|
|
|
|
// text).
|
|
|
|
useSizedBox = true;
|
|
|
|
}
|
|
|
|
else if (aStyleContext->PresContext()->CompatibilityMode() !=
|
|
|
|
eCompatibility_NavQuirks) {
|
|
|
|
useSizedBox = false;
|
|
|
|
}
|
2003-04-29 22:49:42 +04:00
|
|
|
else {
|
2013-10-06 00:25:49 +04:00
|
|
|
// check whether we have fixed size
|
|
|
|
useSizedBox = HaveFixedSize(aStyleContext->StylePosition());
|
2003-04-29 22:49:42 +04:00
|
|
|
}
|
2013-10-06 00:25:49 +04:00
|
|
|
|
2005-09-18 22:05:40 +04:00
|
|
|
return useSizedBox;
|
2001-03-22 04:38:35 +03:00
|
|
|
}
|
|
|
|
|
2012-10-12 20:11:22 +04:00
|
|
|
nsresult
|
|
|
|
nsImageFrame::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData)
|
|
|
|
{
|
2012-10-12 20:11:23 +04:00
|
|
|
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
|
2012-10-12 20:11:22 +04:00
|
|
|
nsCOMPtr<imgIContainer> image;
|
|
|
|
aRequest->GetImage(getter_AddRefs(image));
|
|
|
|
return OnStartContainer(aRequest, image);
|
|
|
|
}
|
|
|
|
|
2012-10-12 20:11:23 +04:00
|
|
|
if (aType == imgINotificationObserver::FRAME_UPDATE) {
|
2012-10-12 20:11:22 +04:00
|
|
|
return OnDataAvailable(aRequest, aData);
|
|
|
|
}
|
|
|
|
|
2012-10-12 20:11:23 +04:00
|
|
|
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
|
|
|
|
mFirstFrameComplete = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
|
2012-10-12 20:11:22 +04:00
|
|
|
uint32_t imgStatus;
|
|
|
|
aRequest->GetImageStatus(&imgStatus);
|
|
|
|
nsresult status =
|
|
|
|
imgStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK;
|
2012-10-12 20:11:22 +04:00
|
|
|
return OnStopRequest(aRequest, status);
|
2012-10-12 20:11:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-08-29 02:39:06 +04:00
|
|
|
static bool
|
|
|
|
SizeIsAvailable(imgIRequest* aRequest)
|
|
|
|
{
|
|
|
|
if (!aRequest)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
uint32_t imageStatus = 0;
|
|
|
|
nsresult rv = aRequest->GetImageStatus(&imageStatus);
|
|
|
|
|
|
|
|
return NS_SUCCEEDED(rv) && (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE);
|
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsresult
|
|
|
|
nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
2001-10-06 09:08:16 +04:00
|
|
|
if (!aImage) return NS_ERROR_INVALID_ARG;
|
|
|
|
|
2003-12-26 07:24:11 +03:00
|
|
|
/* Get requested animation policy from the pres context:
|
|
|
|
* normal = 0
|
|
|
|
* one frame = 1
|
|
|
|
* one loop = 2
|
|
|
|
*/
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *presContext = PresContext();
|
2004-02-03 23:30:02 +03:00
|
|
|
aImage->SetAnimationMode(presContext->ImageAnimationMode());
|
2001-04-17 02:02:39 +04:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
if (IsPendingLoad(aRequest)) {
|
|
|
|
// We don't care
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2013-08-29 02:39:06 +04:00
|
|
|
|
|
|
|
bool intrinsicSizeChanged = false;
|
|
|
|
if (SizeIsAvailable(aRequest)) {
|
|
|
|
// This is valid and for the current request, so update our stored image
|
2013-08-29 02:39:07 +04:00
|
|
|
// container, orienting according to our style.
|
|
|
|
mImage = nsLayoutUtils::OrientImage(aImage, StyleVisibility()->mImageOrientation);
|
2013-08-29 02:39:06 +04:00
|
|
|
|
|
|
|
intrinsicSizeChanged = UpdateIntrinsicSize(mImage);
|
|
|
|
intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged;
|
|
|
|
} else {
|
|
|
|
// We no longer have a valid image, so release our stored image container.
|
|
|
|
mImage = nullptr;
|
|
|
|
|
|
|
|
// Have to size to 0,0 so that GetDesiredSize recalculates the size.
|
|
|
|
mIntrinsicSize.width.SetCoordValue(0);
|
|
|
|
mIntrinsicSize.height.SetCoordValue(0);
|
|
|
|
mIntrinsicRatio.SizeTo(0, 0);
|
|
|
|
intrinsicSizeChanged = true;
|
|
|
|
}
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2011-08-24 01:03:02 +04:00
|
|
|
if (intrinsicSizeChanged && (mState & IMAGE_GOTINITIALREFLOW)) {
|
2009-02-06 19:52:13 +03:00
|
|
|
// Now we need to reflow if we have an unconstrained size and have
|
|
|
|
// already gotten the initial reflow
|
|
|
|
if (!(mState & IMAGE_SIZECONSTRAINED)) {
|
|
|
|
nsIPresShell *presShell = presContext->GetPresShell();
|
|
|
|
NS_ASSERTION(presShell, "No PresShell.");
|
|
|
|
if (presShell) {
|
|
|
|
presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
|
|
|
|
NS_FRAME_IS_DIRTY);
|
|
|
|
}
|
2001-03-22 04:38:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsresult
|
|
|
|
nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
|
2009-01-15 06:27:09 +03:00
|
|
|
const nsIntRect *aRect)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
2012-10-12 20:11:23 +04:00
|
|
|
if (mFirstFrameComplete) {
|
|
|
|
nsCOMPtr<imgIContainer> container;
|
|
|
|
aRequest->GetImage(getter_AddRefs(container));
|
|
|
|
return FrameChanged(aRequest, container);
|
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
// XXX do we need to make sure that the reflow from the
|
|
|
|
// OnStartContainer has been processed before we start calling
|
|
|
|
// invalidate?
|
2001-04-04 12:23:14 +04:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aRect);
|
2003-03-19 09:51:46 +03:00
|
|
|
|
|
|
|
if (!(mState & IMAGE_GOTINITIALREFLOW)) {
|
|
|
|
// Don't bother to do anything; we have a reflow coming up!
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
if (IsPendingLoad(aRequest)) {
|
|
|
|
// We don't care
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-10-06 09:08:16 +04:00
|
|
|
|
2004-08-29 03:59:15 +04:00
|
|
|
#ifdef DEBUG_decode
|
2012-08-29 09:39:31 +04:00
|
|
|
printf("Source rect (%d,%d,%d,%d)\n",
|
|
|
|
aRect->x, aRect->y, aRect->width, aRect->height);
|
2004-08-29 03:59:15 +04:00
|
|
|
#endif
|
2012-09-26 03:59:56 +04:00
|
|
|
|
2012-08-29 09:48:45 +04:00
|
|
|
if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
|
2012-09-26 03:59:56 +04:00
|
|
|
InvalidateFrame(nsDisplayItem::TYPE_IMAGE);
|
|
|
|
InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK);
|
2012-08-29 09:48:45 +04:00
|
|
|
} else {
|
2012-09-26 03:59:56 +04:00
|
|
|
nsRect invalid = SourceRectToDest(*aRect);
|
|
|
|
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE);
|
|
|
|
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK);
|
2012-08-29 09:48:45 +04:00
|
|
|
}
|
2012-10-12 20:11:23 +04:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
return NS_OK;
|
2001-07-11 09:44:12 +04:00
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsresult
|
2012-10-12 20:11:22 +04:00
|
|
|
nsImageFrame::OnStopRequest(imgIRequest *aRequest,
|
|
|
|
nsresult aStatus)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
2003-03-19 06:47:09 +03:00
|
|
|
// Check what request type we're dealing with
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
|
|
|
NS_ASSERTION(imageLoader, "Who's notifying us??");
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t loadType = nsIImageLoadingContent::UNKNOWN_REQUEST;
|
2003-03-19 06:47:09 +03:00
|
|
|
imageLoader->GetRequestType(aRequest, &loadType);
|
|
|
|
if (loadType != nsIImageLoadingContent::CURRENT_REQUEST &&
|
|
|
|
loadType != nsIImageLoadingContent::PENDING_REQUEST) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2001-10-06 09:08:16 +04:00
|
|
|
|
2013-08-29 02:39:06 +04:00
|
|
|
NotifyNewCurrentRequest(aRequest, aStatus);
|
2012-03-20 02:22:02 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
2013-08-29 02:39:06 +04:00
|
|
|
nsCOMPtr<imgIContainer> image;
|
|
|
|
aRequest->GetImage(getter_AddRefs(image));
|
|
|
|
NS_ASSERTION(image || NS_FAILED(aStatus), "Successful load with no container?");
|
|
|
|
|
2012-03-20 02:22:02 +04:00
|
|
|
// May have to switch sizes here!
|
|
|
|
bool intrinsicSizeChanged = true;
|
2013-08-29 02:39:06 +04:00
|
|
|
if (NS_SUCCEEDED(aStatus) && image && SizeIsAvailable(aRequest)) {
|
2013-08-29 02:39:07 +04:00
|
|
|
// Update our stored image container, orienting according to our style.
|
|
|
|
mImage = nsLayoutUtils::OrientImage(image, StyleVisibility()->mImageOrientation);
|
|
|
|
|
2013-08-29 02:39:06 +04:00
|
|
|
intrinsicSizeChanged = UpdateIntrinsicSize(mImage);
|
|
|
|
intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged;
|
2013-08-29 02:39:07 +04:00
|
|
|
} else {
|
2013-08-29 02:39:06 +04:00
|
|
|
// We no longer have a valid image, so release our stored image container.
|
|
|
|
mImage = nullptr;
|
|
|
|
|
2012-03-20 02:22:02 +04:00
|
|
|
// Have to size to 0,0 so that GetDesiredSize recalculates the size
|
|
|
|
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
|
|
|
|
if (!(mState & IMAGE_SIZECONSTRAINED) && intrinsicSizeChanged) {
|
|
|
|
nsIPresShell *presShell = PresContext()->GetPresShell();
|
|
|
|
if (presShell) {
|
|
|
|
presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
|
|
|
|
NS_FRAME_IS_DIRTY);
|
2002-06-19 01:28:53 +04:00
|
|
|
}
|
2001-10-06 09:08:16 +04:00
|
|
|
}
|
2012-11-01 05:25:44 +04:00
|
|
|
// Update border+content to account for image change
|
|
|
|
InvalidateFrame();
|
2001-04-15 06:13:49 +04:00
|
|
|
}
|
2001-03-22 04:38:35 +03:00
|
|
|
}
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsresult
|
2012-01-06 16:32:38 +04:00
|
|
|
nsImageFrame::FrameChanged(imgIRequest *aRequest,
|
2012-10-12 20:11:22 +04:00
|
|
|
imgIContainer *aContainer)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
2013-02-17 01:51:02 +04:00
|
|
|
if (!StyleVisibility()->IsVisible()) {
|
2002-07-01 22:17:35 +04:00
|
|
|
return NS_OK;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
2002-07-01 22:17:35 +04:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
if (IsPendingLoad(aContainer)) {
|
|
|
|
// We don't care about it
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-09-09 00:40:39 +04:00
|
|
|
|
2012-09-25 00:31:30 +04:00
|
|
|
InvalidateLayer(nsDisplayItem::TYPE_IMAGE);
|
2001-03-22 04:38:35 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-03-13 14:32:43 +03:00
|
|
|
|
1998-09-09 02:34:40 +04:00
|
|
|
void
|
2010-09-09 00:40:38 +04:00
|
|
|
nsImageFrame::EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2013-08-29 02:39:06 +04:00
|
|
|
// If mIntrinsicSize.width and height are 0, then we need to update from the
|
|
|
|
// image container.
|
2010-09-09 00:40:38 +04:00
|
|
|
if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
|
|
|
|
mIntrinsicSize.width.GetCoordValue() == 0 &&
|
|
|
|
mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
|
|
|
|
mIntrinsicSize.height.GetCoordValue() == 0) {
|
2009-08-12 18:23:38 +04:00
|
|
|
|
2013-08-29 02:39:06 +04:00
|
|
|
if (mImage) {
|
|
|
|
UpdateIntrinsicSize(mImage);
|
|
|
|
UpdateIntrinsicRatio(mImage);
|
2003-03-19 06:47:09 +03:00
|
|
|
} else {
|
|
|
|
// image request is null or image size not known, probably an
|
|
|
|
// invalid image specified
|
|
|
|
// - make the image big enough for the icon (it may not be
|
|
|
|
// used if inline alt expansion is used instead)
|
2013-10-06 00:25:49 +04:00
|
|
|
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
|
2010-09-09 00:40:38 +04:00
|
|
|
nscoord edgeLengthToUse =
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(
|
|
|
|
ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
|
|
|
|
mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
|
|
|
|
mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
|
|
|
|
mIntrinsicRatio.SizeTo(1, 1);
|
2001-10-06 12:19:44 +04:00
|
|
|
}
|
2001-10-06 09:08:16 +04:00
|
|
|
}
|
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2001-10-06 09:08:16 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
/* virtual */ nsSize
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *presContext = PresContext();
|
2010-09-09 00:40:38 +04:00
|
|
|
EnsureIntrinsicSizeAndRatio(presContext);
|
2007-11-18 15:09:03 +03:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
|
|
|
|
aRenderingContext, this,
|
2010-09-09 00:40:38 +04:00
|
|
|
mIntrinsicSize, mIntrinsicRatio, aCBSize,
|
2007-11-18 15:09:03 +03:00
|
|
|
aMargin, aBorder, aPadding);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
2004-12-26 22:48:54 +03:00
|
|
|
nsRect
|
|
|
|
nsImageFrame::GetInnerArea() const
|
1998-11-20 20:21:02 +03:00
|
|
|
{
|
2007-03-20 03:58:20 +03:00
|
|
|
return GetContentRect() - GetPosition();
|
2001-11-01 18:31:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// get the offset into the content area of the image where aImg starts if it is a continuation.
|
|
|
|
nscoord
|
2007-03-20 03:58:20 +03:00
|
|
|
nsImageFrame::GetContinuationOffset() const
|
2001-11-01 18:31:13 +03:00
|
|
|
{
|
|
|
|
nscoord offset = 0;
|
2007-03-20 03:58:20 +03:00
|
|
|
for (nsIFrame *f = GetPrevInFlow(); f; f = f->GetPrevInFlow()) {
|
|
|
|
offset += f->GetContentRect().height;
|
2001-11-01 18:31:13 +03:00
|
|
|
}
|
2007-03-20 03:58:20 +03:00
|
|
|
NS_ASSERTION(offset >= 0, "bogus GetContentRect");
|
2001-11-01 18:31:13 +03:00
|
|
|
return offset;
|
1998-11-20 20:21:02 +03:00
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
/* virtual */ nscoord
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
// XXX The caller doesn't account for constraints of the height,
|
|
|
|
// min-height, and max-height properties.
|
2011-06-21 19:37:47 +04:00
|
|
|
DebugOnly<nscoord> result;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
DISPLAY_MIN_WIDTH(this, result);
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *presContext = PresContext();
|
2010-09-09 00:40:38 +04:00
|
|
|
EnsureIntrinsicSizeAndRatio(presContext);
|
|
|
|
return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
|
|
|
|
mIntrinsicSize.width.GetCoordValue() : 0;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
// XXX The caller doesn't account for constraints of the height,
|
|
|
|
// min-height, and max-height properties.
|
2011-06-21 19:37:47 +04:00
|
|
|
DebugOnly<nscoord> result;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
DISPLAY_PREF_WIDTH(this, result);
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *presContext = PresContext();
|
2010-09-09 00:40:38 +04:00
|
|
|
EnsureIntrinsicSizeAndRatio(presContext);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// convert from normal twips to scaled twips (printing...)
|
2010-09-09 00:40:38 +04:00
|
|
|
return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
|
|
|
|
mIntrinsicSize.width.GetCoordValue() : 0;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
2013-10-01 01:26:04 +04:00
|
|
|
/* virtual */ IntrinsicSize
|
2010-09-15 00:20:32 +04:00
|
|
|
nsImageFrame::GetIntrinsicSize()
|
|
|
|
{
|
|
|
|
return mIntrinsicSize;
|
|
|
|
}
|
|
|
|
|
2007-06-12 22:27:09 +04:00
|
|
|
/* virtual */ nsSize
|
|
|
|
nsImageFrame::GetIntrinsicRatio()
|
|
|
|
{
|
2010-09-09 00:40:38 +04:00
|
|
|
return mIntrinsicRatio;
|
2007-06-12 22:27:09 +04:00
|
|
|
}
|
|
|
|
|
1998-11-20 20:21:02 +03:00
|
|
|
NS_IMETHODIMP
|
2004-08-01 03:15:21 +04:00
|
|
|
nsImageFrame::Reflow(nsPresContext* aPresContext,
|
1998-11-20 20:21:02 +03:00
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsImageFrame");
|
2001-11-14 16:40:03 +03:00
|
|
|
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
1998-11-20 20:21:02 +03:00
|
|
|
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
2000-05-14 08:43:52 +04:00
|
|
|
("enter nsImageFrame::Reflow: availSize=%d,%d",
|
1999-01-06 02:31:18 +03:00
|
|
|
aReflowState.availableWidth, aReflowState.availableHeight));
|
1998-11-20 20:21:02 +03:00
|
|
|
|
|
|
|
NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
|
|
|
|
|
2001-11-01 18:31:13 +03:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
|
2001-03-06 03:47:46 +03:00
|
|
|
// see if we have a frozen size (i.e. a fixed width and height)
|
2003-02-25 01:20:26 +03:00
|
|
|
if (HaveFixedSize(aReflowState)) {
|
|
|
|
mState |= IMAGE_SIZECONSTRAINED;
|
|
|
|
} else {
|
2003-03-19 06:47:09 +03:00
|
|
|
mState &= ~IMAGE_SIZECONSTRAINED;
|
2003-02-25 01:20:26 +03:00
|
|
|
}
|
2001-03-06 03:47:46 +03:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// XXXldb These two bits are almost exact opposites (except in the
|
|
|
|
// middle of the initial reflow); remove IMAGE_GOTINITIALREFLOW.
|
|
|
|
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
2003-02-25 01:20:26 +03:00
|
|
|
mState |= IMAGE_GOTINITIALREFLOW;
|
2003-03-19 06:47:09 +03:00
|
|
|
}
|
|
|
|
|
2007-03-20 03:58:20 +03:00
|
|
|
mComputedSize =
|
2007-08-02 22:08:05 +04:00
|
|
|
nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
aMetrics.width = mComputedSize.width;
|
|
|
|
aMetrics.height = mComputedSize.height;
|
2001-11-01 18:31:13 +03:00
|
|
|
|
|
|
|
// add borders and padding
|
2007-03-20 03:58:20 +03:00
|
|
|
aMetrics.width += aReflowState.mComputedBorderPadding.LeftRight();
|
|
|
|
aMetrics.height += aReflowState.mComputedBorderPadding.TopBottom();
|
2001-11-01 18:31:13 +03:00
|
|
|
|
2006-02-22 00:33:47 +03:00
|
|
|
if (GetPrevInFlow()) {
|
2007-03-20 03:58:20 +03:00
|
|
|
aMetrics.width = GetPrevInFlow()->GetSize().width;
|
|
|
|
nscoord y = GetContinuationOffset();
|
|
|
|
aMetrics.height -= y + aReflowState.mComputedBorderPadding.top;
|
2013-01-15 16:22:03 +04:00
|
|
|
aMetrics.height = std::max(0, aMetrics.height);
|
2001-11-01 18:31:13 +03:00
|
|
|
}
|
|
|
|
|
2002-01-11 22:32:55 +03:00
|
|
|
|
|
|
|
// we have to split images if we are:
|
|
|
|
// in Paginated mode, we need to have a constrained height, and have a height larger than our available height
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t loadStatus = imgIRequest::STATUS_NONE;
|
2003-03-19 06:47:09 +03:00
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
|
|
|
NS_ASSERTION(imageLoader, "No content node??");
|
|
|
|
if (imageLoader) {
|
|
|
|
nsCOMPtr<imgIRequest> currentRequest;
|
|
|
|
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(currentRequest));
|
|
|
|
if (currentRequest) {
|
|
|
|
currentRequest->GetImageStatus(&loadStatus);
|
|
|
|
}
|
2002-08-29 05:44:15 +04:00
|
|
|
}
|
2004-03-03 21:24:20 +03:00
|
|
|
if (aPresContext->IsPaginated() &&
|
2003-02-25 01:20:26 +03:00
|
|
|
((loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (mState & IMAGE_SIZECONSTRAINED)) &&
|
2003-03-19 06:47:09 +03:00
|
|
|
NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight &&
|
|
|
|
aMetrics.height > aReflowState.availableHeight) {
|
2008-01-05 09:44:38 +03:00
|
|
|
// our desired height was greater than 0, so to avoid infinite
|
|
|
|
// splitting, use 1 pixel as the min
|
2013-01-15 16:22:03 +04:00
|
|
|
aMetrics.height = std::max(nsPresContext::CSSPixelsToAppUnits(1), aReflowState.availableHeight);
|
2008-01-05 09:44:38 +03:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
2001-11-01 18:31:13 +03:00
|
|
|
}
|
|
|
|
|
2010-10-07 08:25:46 +04:00
|
|
|
aMetrics.SetOverflowAreasToDesiredBounds();
|
2012-08-29 09:48:44 +04:00
|
|
|
nsEventStates contentState = mContent->AsElement()->State();
|
|
|
|
bool imageOK = IMAGE_OK(contentState, true);
|
|
|
|
|
|
|
|
// Determine if the size is available
|
|
|
|
bool haveSize = false;
|
|
|
|
if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) {
|
|
|
|
haveSize = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!imageOK || !haveSize) {
|
|
|
|
nsRect altFeedbackSize(0, 0,
|
2012-11-14 22:05:41 +04:00
|
|
|
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+2*(ICON_PADDING+ALT_BORDER_WIDTH)),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+2*(ICON_PADDING+ALT_BORDER_WIDTH)));
|
2013-01-18 08:17:41 +04:00
|
|
|
// We include the altFeedbackSize in our visual overflow, but not in our
|
|
|
|
// scrollable overflow, since it doesn't really need to be scrolled to
|
|
|
|
// outside the image.
|
2013-07-18 21:59:53 +04:00
|
|
|
static_assert(eOverflowType_LENGTH == 2, "Unknown overflow types?");
|
2013-01-18 08:17:41 +04:00
|
|
|
nsRect& visualOverflow = aMetrics.VisualOverflow();
|
|
|
|
visualOverflow.UnionRect(visualOverflow, altFeedbackSize);
|
2012-08-29 09:48:44 +04:00
|
|
|
}
|
2012-09-27 19:34:46 +04:00
|
|
|
FinishAndStoreOverflow(&aMetrics);
|
2012-08-29 09:48:44 +04:00
|
|
|
|
2013-09-15 04:05:05 +04:00
|
|
|
if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) && !mReflowCallbackPosted) {
|
|
|
|
nsIPresShell* shell = PresContext()->PresShell();
|
2013-09-15 04:05:06 +04:00
|
|
|
mReflowCallbackPosted = true;
|
|
|
|
shell->PostReflowCallback(this);
|
2013-09-15 04:05:05 +04:00
|
|
|
}
|
|
|
|
|
1998-11-20 20:21:02 +03:00
|
|
|
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
2000-05-14 08:43:52 +04:00
|
|
|
("exit nsImageFrame::Reflow: size=%d,%d",
|
1998-11-20 20:21:02 +03:00
|
|
|
aMetrics.width, aMetrics.height));
|
2002-05-29 02:50:43 +04:00
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
1998-11-20 20:21:02 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-09-15 04:05:05 +04:00
|
|
|
bool
|
|
|
|
nsImageFrame::ReflowFinished()
|
|
|
|
{
|
|
|
|
mReflowCallbackPosted = false;
|
|
|
|
|
|
|
|
nsLayoutUtils::UpdateImageVisibilityForFrame(this);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsImageFrame::ReflowCallbackCanceled()
|
|
|
|
{
|
|
|
|
mReflowCallbackPosted = false;
|
|
|
|
}
|
|
|
|
|
1998-09-09 02:34:40 +04:00
|
|
|
// Computes the width of the specified string. aMaxWidth specifies the maximum
|
|
|
|
// width available. Once this limit is reached no more characters are measured.
|
|
|
|
// The number of characters that fit within the maximum width are returned in
|
1998-10-02 05:12:39 +04:00
|
|
|
// aMaxFit. NOTE: it is assumed that the fontmetrics have already been selected
|
|
|
|
// into the rendering context before this is called (for performance). MMP
|
2006-07-31 11:08:45 +04:00
|
|
|
nscoord
|
1998-11-20 20:21:02 +03:00
|
|
|
nsImageFrame::MeasureString(const PRUnichar* aString,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aLength,
|
1998-11-20 20:21:02 +03:00
|
|
|
nscoord aMaxWidth,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t& aMaxFit,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aContext)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
|
|
|
nscoord totalWidth = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
aContext.SetTextRunRTL(false);
|
2011-04-08 05:04:40 +04:00
|
|
|
nscoord spaceWidth = aContext.GetWidth(' ');
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
aMaxFit = 0;
|
|
|
|
while (aLength > 0) {
|
|
|
|
// Find the next place we can line break
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t len = aLength;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool trailingSpace = false;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t i = 0; i < aLength; i++) {
|
2012-11-30 20:04:11 +04:00
|
|
|
if (dom::IsSpaceCharacter(aString[i]) && (i > 0)) {
|
1998-09-09 02:34:40 +04:00
|
|
|
len = i; // don't include the space when measuring
|
2011-10-17 18:59:28 +04:00
|
|
|
trailingSpace = true;
|
1998-09-09 02:34:40 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Measure this chunk of text, and see if it fits
|
2007-01-23 05:58:55 +03:00
|
|
|
nscoord width =
|
|
|
|
nsLayoutUtils::GetStringWidth(this, &aContext, aString, len);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool fits = (totalWidth + width) <= aMaxWidth;
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
// If it fits on the line, or it's the first word we've processed then
|
|
|
|
// include it
|
|
|
|
if (fits || (0 == totalWidth)) {
|
|
|
|
// New piece fits
|
|
|
|
totalWidth += width;
|
|
|
|
|
|
|
|
// If there's a trailing space then see if it fits as well
|
|
|
|
if (trailingSpace) {
|
|
|
|
if ((totalWidth + spaceWidth) <= aMaxWidth) {
|
|
|
|
totalWidth += spaceWidth;
|
|
|
|
} else {
|
|
|
|
// Space won't fit. Leave it at the end but don't include it in
|
|
|
|
// the width
|
2011-10-17 18:59:28 +04:00
|
|
|
fits = false;
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
|
|
|
|
aMaxFit += len;
|
|
|
|
aString += len;
|
|
|
|
aLength -= len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fits) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-07-31 11:08:45 +04:00
|
|
|
return totalWidth;
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Formats the alt-text to fit within the specified rectangle. Breaks lines
|
|
|
|
// between words if a word would extend past the edge of the rectangle
|
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aRenderingContext,
|
1998-11-20 20:21:02 +03:00
|
|
|
const nsString& aAltText,
|
|
|
|
const nsRect& aRect)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
|
|
|
// Set font and color
|
2013-02-17 01:51:02 +04:00
|
|
|
aRenderingContext.SetColor(StyleColor()->mColor);
|
2011-08-14 21:08:04 +04:00
|
|
|
nsRefPtr<nsFontMetrics> fm;
|
2011-11-24 06:48:23 +04:00
|
|
|
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
|
2012-05-21 09:18:28 +04:00
|
|
|
nsLayoutUtils::FontSizeInflationFor(this));
|
2011-08-14 21:08:04 +04:00
|
|
|
aRenderingContext.SetFont(fm);
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
// Format the text to display within the formatting rect
|
|
|
|
|
2011-04-08 08:18:43 +04:00
|
|
|
nscoord maxAscent = fm->MaxAscent();
|
|
|
|
nscoord maxDescent = fm->MaxDescent();
|
|
|
|
nscoord height = fm->MaxHeight();
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
// XXX It would be nice if there was a way to have the font metrics tell
|
|
|
|
// use where to break the text given a maximum width. At a minimum we need
|
|
|
|
// to be able to get the break character...
|
2001-06-30 15:02:25 +04:00
|
|
|
const PRUnichar* str = aAltText.get();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t strLen = aAltText.Length();
|
1998-09-09 02:34:40 +04:00
|
|
|
nscoord y = aRect.y;
|
2009-07-12 17:32:48 +04:00
|
|
|
|
|
|
|
if (!aPresContext->BidiEnabled() && HasRTLChars(aAltText)) {
|
|
|
|
aPresContext->SetBidiEnabled();
|
|
|
|
}
|
|
|
|
|
2004-10-12 01:52:36 +04:00
|
|
|
// Always show the first line, even if we have to clip it below
|
2011-09-29 10:19:26 +04:00
|
|
|
bool firstLine = true;
|
2004-10-12 01:52:36 +04:00
|
|
|
while ((strLen > 0) && (firstLine || (y + maxDescent) < aRect.YMost())) {
|
1998-09-09 02:34:40 +04:00
|
|
|
// Determine how much of the text to display on this line
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t maxFit; // number of characters that fit
|
2006-07-31 11:08:45 +04:00
|
|
|
nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
|
|
|
|
aRenderingContext);
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
// Display the text
|
2006-07-31 11:08:45 +04:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (aPresContext->BidiEnabled()) {
|
2013-02-17 01:51:02 +04:00
|
|
|
const nsStyleVisibility* vis = StyleVisibility();
|
2011-04-13 13:23:49 +04:00
|
|
|
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
|
|
|
|
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
|
|
|
|
aPresContext, aRenderingContext,
|
|
|
|
aRenderingContext,
|
|
|
|
aRect.XMost() - strWidth, y + maxAscent);
|
|
|
|
else
|
|
|
|
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
|
|
|
|
aPresContext, aRenderingContext,
|
|
|
|
aRenderingContext,
|
|
|
|
aRect.x, y + maxAscent);
|
2006-07-31 11:08:45 +04:00
|
|
|
}
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
aRenderingContext.DrawString(str, maxFit, aRect.x, y + maxAscent);
|
1998-09-09 02:34:40 +04:00
|
|
|
|
|
|
|
// Move to the next line
|
|
|
|
str += maxFit;
|
|
|
|
strLen -= maxFit;
|
|
|
|
y += height;
|
2011-10-17 18:59:28 +04:00
|
|
|
firstLine = false;
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-07 12:57:26 +03:00
|
|
|
struct nsRecessedBorder : public nsStyleBorder {
|
2006-12-27 17:21:43 +03:00
|
|
|
nsRecessedBorder(nscoord aBorderWidth, nsPresContext* aPresContext)
|
|
|
|
: nsStyleBorder(aPresContext)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2005-04-29 19:44:38 +04:00
|
|
|
NS_FOR_CSS_SIDES(side) {
|
2005-05-05 20:03:06 +04:00
|
|
|
// Note: use SetBorderColor here because we want to make sure
|
|
|
|
// the "special" flags are unset.
|
|
|
|
SetBorderColor(side, NS_RGB(0, 0, 0));
|
2011-04-19 07:07:22 +04:00
|
|
|
mBorder.Side(side) = aBorderWidth;
|
2005-05-05 20:03:06 +04:00
|
|
|
// Note: use SetBorderStyle here because we want to affect
|
|
|
|
// mComputedBorder
|
2005-04-29 19:44:38 +04:00
|
|
|
SetBorderStyle(side, NS_STYLE_BORDER_STYLE_INSET);
|
|
|
|
}
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-29 09:48:44 +04:00
|
|
|
class nsDisplayAltFeedback : public nsDisplayItem {
|
|
|
|
public:
|
|
|
|
nsDisplayAltFeedback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
|
|
|
: nsDisplayItem(aBuilder, aFrame) {}
|
|
|
|
|
|
|
|
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
|
|
|
|
{
|
|
|
|
*aSnap = false;
|
|
|
|
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx)
|
|
|
|
{
|
|
|
|
nsImageFrame* f = static_cast<nsImageFrame*>(mFrame);
|
|
|
|
nsEventStates state = f->GetContent()->AsElement()->State();
|
|
|
|
f->DisplayAltFeedback(*aCtx,
|
|
|
|
mVisibleRect,
|
|
|
|
IMAGE_OK(state, true)
|
|
|
|
? nsImageFrame::gIconLoad->mLoadingImage
|
|
|
|
: nsImageFrame::gIconLoad->mBrokenImage,
|
|
|
|
ToReferenceFrame());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DISPLAY_DECL_NAME("AltFeedback", TYPE_ALT_FEEDBACK)
|
|
|
|
};
|
|
|
|
|
1998-09-22 07:34:44 +04:00
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
2007-03-20 03:58:20 +03:00
|
|
|
const nsRect& aDirtyRect,
|
2006-01-26 05:29:17 +03:00
|
|
|
imgIRequest* aRequest,
|
|
|
|
nsPoint aPt)
|
1998-09-22 07:34:44 +04:00
|
|
|
{
|
2009-08-12 18:23:38 +04:00
|
|
|
// We should definitely have a gIconLoad here.
|
|
|
|
NS_ABORT_IF_FALSE(gIconLoad, "How did we succeed in Init then?");
|
|
|
|
|
1999-09-17 01:37:37 +04:00
|
|
|
// Calculate the inner area
|
2006-01-26 05:29:17 +03:00
|
|
|
nsRect inner = GetInnerArea() + aPt;
|
1998-09-22 07:34:44 +04:00
|
|
|
|
1999-09-17 01:37:37 +04:00
|
|
|
// Display a recessed one pixel border
|
2007-02-07 10:46:44 +03:00
|
|
|
nscoord borderEdgeWidth = nsPresContext::CSSPixelsToAppUnits(ALT_BORDER_WIDTH);
|
1999-09-17 01:37:37 +04:00
|
|
|
|
2002-03-26 23:14:05 +03:00
|
|
|
// if inner area is empty, then make it big enough for at least the icon
|
|
|
|
if (inner.IsEmpty()){
|
2007-02-07 10:46:44 +03:00
|
|
|
inner.SizeTo(2*(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH)),
|
|
|
|
2*(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH)));
|
2002-03-26 23:14:05 +03:00
|
|
|
}
|
|
|
|
|
1999-09-17 01:37:37 +04:00
|
|
|
// Make sure we have enough room to actually render the border within
|
|
|
|
// our frame bounds
|
|
|
|
if ((inner.width < 2 * borderEdgeWidth) || (inner.height < 2 * borderEdgeWidth)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Paint the border
|
2007-03-31 01:11:41 +04:00
|
|
|
nsRecessedBorder recessedBorder(borderEdgeWidth, PresContext());
|
2010-04-03 05:58:26 +04:00
|
|
|
nsCSSRendering::PaintBorderWithStyleBorder(PresContext(), aRenderingContext,
|
|
|
|
this, inner, inner,
|
|
|
|
recessedBorder, mStyleContext);
|
1998-09-22 07:34:44 +04:00
|
|
|
|
|
|
|
// Adjust the inner rect to account for the one pixel recessed border,
|
|
|
|
// and a six pixel padding on each edge
|
2007-02-07 10:46:44 +03:00
|
|
|
inner.Deflate(nsPresContext::CSSPixelsToAppUnits(ICON_PADDING+ALT_BORDER_WIDTH),
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(ICON_PADDING+ALT_BORDER_WIDTH));
|
1998-09-22 07:34:44 +04:00
|
|
|
if (inner.IsEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clip so we don't render outside the inner rect
|
|
|
|
aRenderingContext.PushState();
|
2011-04-08 05:04:40 +04:00
|
|
|
aRenderingContext.IntersectClip(inner);
|
1998-09-22 07:34:44 +04:00
|
|
|
|
2002-04-10 18:45:05 +04:00
|
|
|
// Check if we should display image placeholders
|
2009-08-12 18:23:38 +04:00
|
|
|
if (gIconLoad->mPrefShowPlaceholders) {
|
2013-02-17 01:51:02 +04:00
|
|
|
const nsStyleVisibility* vis = StyleVisibility();
|
2007-02-07 10:46:44 +03:00
|
|
|
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
|
1998-09-22 07:34:44 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool iconUsed = false;
|
1998-09-22 07:34:44 +04:00
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
// If we weren't previously displaying an icon, register ourselves
|
|
|
|
// as an observer for load and animation updates and flag that we're
|
|
|
|
// doing so now.
|
2009-08-31 01:06:11 +04:00
|
|
|
if (aRequest && !mDisplayingIcon) {
|
2009-08-12 18:23:38 +04:00
|
|
|
gIconLoad->AddIconObserver(this);
|
2011-10-17 18:59:28 +04:00
|
|
|
mDisplayingIcon = true;
|
2009-08-12 18:23:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the image in question is loaded and decoded, draw it
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t imageStatus = 0;
|
2009-08-31 01:06:11 +04:00
|
|
|
if (aRequest)
|
|
|
|
aRequest->GetImageStatus(&imageStatus);
|
2009-08-12 18:23:38 +04:00
|
|
|
if (imageStatus & imgIRequest::STATUS_FRAME_COMPLETE) {
|
2002-04-10 18:45:05 +04:00
|
|
|
nsCOMPtr<imgIContainer> imgCon;
|
2009-08-12 18:23:38 +04:00
|
|
|
aRequest->GetImage(getter_AddRefs(imgCon));
|
|
|
|
NS_ABORT_IF_FALSE(imgCon, "Frame Complete, but no image container?");
|
|
|
|
nsRect dest((vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
|
|
|
|
inner.XMost() - size : inner.x,
|
|
|
|
inner.y, size, size);
|
|
|
|
nsLayoutUtils::DrawSingleImage(&aRenderingContext, imgCon,
|
2009-09-13 02:44:18 +04:00
|
|
|
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
|
2013-03-01 00:22:43 +04:00
|
|
|
nullptr, imgIContainer::FLAG_NONE);
|
2011-10-17 18:59:28 +04:00
|
|
|
iconUsed = true;
|
2001-11-07 08:02:42 +03:00
|
|
|
}
|
1998-09-22 07:34:44 +04:00
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
// if we could not draw the icon, flag that we're waiting for it and
|
|
|
|
// just draw some graffiti in the mean time
|
2002-04-10 18:45:05 +04:00
|
|
|
if (!iconUsed) {
|
2006-07-31 11:08:45 +04:00
|
|
|
nscoord iconXPos = (vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
|
|
|
|
inner.XMost() - size : inner.x;
|
2007-02-07 10:46:44 +03:00
|
|
|
nscoord twoPX = nsPresContext::CSSPixelsToAppUnits(2);
|
2006-07-31 11:08:45 +04:00
|
|
|
aRenderingContext.DrawRect(iconXPos, inner.y,size,size);
|
2011-04-08 05:04:40 +04:00
|
|
|
aRenderingContext.PushState();
|
2004-02-03 23:30:02 +03:00
|
|
|
aRenderingContext.SetColor(NS_RGB(0xFF,0,0));
|
2007-02-07 10:46:44 +03:00
|
|
|
aRenderingContext.FillEllipse(size/2 + iconXPos, size/2 + inner.y,
|
|
|
|
size/2 - twoPX, size/2 - twoPX);
|
2011-04-08 05:04:40 +04:00
|
|
|
aRenderingContext.PopState();
|
|
|
|
}
|
2001-11-07 08:02:42 +03:00
|
|
|
|
2002-04-10 18:45:05 +04:00
|
|
|
// Reduce the inner rect by the width of the icon, and leave an
|
|
|
|
// additional ICON_PADDING pixels for padding
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t iconWidth = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
|
2006-07-31 11:08:45 +04:00
|
|
|
if (vis->mDirection != NS_STYLE_DIRECTION_RTL)
|
|
|
|
inner.x += iconWidth;
|
2002-04-10 18:45:05 +04:00
|
|
|
inner.width -= iconWidth;
|
|
|
|
}
|
1998-09-22 07:34:44 +04:00
|
|
|
|
|
|
|
// If there's still room, display the alt-text
|
|
|
|
if (!inner.IsEmpty()) {
|
2003-06-29 07:43:05 +04:00
|
|
|
nsIContent* content = GetContent();
|
2001-11-07 08:02:42 +03:00
|
|
|
if (content) {
|
2005-01-19 02:46:59 +03:00
|
|
|
nsXPIDLString altText;
|
2003-11-19 04:20:56 +03:00
|
|
|
nsCSSFrameConstructor::GetAlternateTextFor(content, content->Tag(),
|
|
|
|
altText);
|
2007-03-31 01:11:41 +04:00
|
|
|
DisplayAltText(PresContext(), aRenderingContext, altText, inner);
|
1998-09-22 07:34:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-18 17:13:35 +04:00
|
|
|
aRenderingContext.PopState();
|
1998-09-22 07:34:44 +04:00
|
|
|
}
|
|
|
|
|
2012-06-25 23:59:42 +04:00
|
|
|
#ifdef DEBUG
|
2011-04-08 05:04:40 +04:00
|
|
|
static void PaintDebugImageMap(nsIFrame* aFrame, nsRenderingContext* aCtx,
|
2006-01-26 05:29:17 +03:00
|
|
|
const nsRect& aDirtyRect, nsPoint aPt) {
|
2007-07-08 11:08:04 +04:00
|
|
|
nsImageFrame* f = static_cast<nsImageFrame*>(aFrame);
|
2006-01-26 05:29:17 +03:00
|
|
|
nsRect inner = f->GetInnerArea() + aPt;
|
|
|
|
|
|
|
|
aCtx->SetColor(NS_RGB(0, 0, 0));
|
|
|
|
aCtx->PushState();
|
2011-04-08 05:04:39 +04:00
|
|
|
aCtx->Translate(inner.TopLeft());
|
2011-09-27 00:55:04 +04:00
|
|
|
f->GetImageMap()->Draw(aFrame, *aCtx);
|
2006-01-26 05:29:17 +03:00
|
|
|
aCtx->PopState();
|
|
|
|
}
|
|
|
|
#endif
|
2001-10-06 09:08:16 +04:00
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
void
|
|
|
|
nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext* aCtx) {
|
2013-04-26 02:08:58 +04:00
|
|
|
uint32_t flags = imgIContainer::FLAG_NONE;
|
|
|
|
if (aBuilder->ShouldSyncDecodeImages()) {
|
|
|
|
flags |= imgIContainer::FLAG_SYNC_DECODE;
|
|
|
|
}
|
|
|
|
if (aBuilder->IsPaintingToWindow()) {
|
|
|
|
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
|
|
|
|
}
|
2007-07-08 11:08:04 +04:00
|
|
|
static_cast<nsImageFrame*>(mFrame)->
|
2013-04-26 02:08:58 +04:00
|
|
|
PaintImage(*aCtx, ToReferenceFrame(), mVisibleRect, mImage, flags);
|
2006-01-26 05:29:17 +03:00
|
|
|
}
|
2002-03-26 23:14:05 +03:00
|
|
|
|
2013-06-26 20:43:27 +04:00
|
|
|
void
|
|
|
|
nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayItemGeometry* aGeometry,
|
|
|
|
nsRegion* aInvalidRegion)
|
|
|
|
{
|
|
|
|
if (aBuilder->ShouldSyncDecodeImages() && mImage && !mImage->IsDecoded()) {
|
|
|
|
bool snap;
|
|
|
|
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
|
|
|
}
|
|
|
|
|
2012-01-30 09:16:54 +04:00
|
|
|
already_AddRefed<ImageContainer>
|
2012-11-28 06:34:45 +04:00
|
|
|
nsDisplayImage::GetContainer(LayerManager* aManager,
|
|
|
|
nsDisplayListBuilder* aBuilder)
|
2011-01-18 00:47:18 +03:00
|
|
|
{
|
2012-01-30 09:16:54 +04:00
|
|
|
nsRefPtr<ImageContainer> container;
|
2012-11-28 06:34:45 +04:00
|
|
|
nsresult rv = mImage->GetImageContainer(aManager, getter_AddRefs(container));
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
2012-01-30 09:16:54 +04:00
|
|
|
return container.forget();
|
2011-01-18 00:47:18 +03:00
|
|
|
}
|
|
|
|
|
2012-05-03 18:05:55 +04:00
|
|
|
gfxRect
|
|
|
|
nsDisplayImage::GetDestRect()
|
2011-01-18 00:47:18 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
|
2011-01-18 00:47:18 +03:00
|
|
|
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame);
|
|
|
|
|
|
|
|
nsRect dest = imageFrame->GetInnerArea() + ToReferenceFrame();
|
|
|
|
gfxRect destRect(dest.x, dest.y, dest.width, dest.height);
|
|
|
|
destRect.ScaleInverse(factor);
|
|
|
|
|
2012-05-03 18:05:55 +04:00
|
|
|
return destRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
LayerState
|
|
|
|
nsDisplayImage::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|
|
|
LayerManager* aManager,
|
2013-09-27 10:01:16 +04:00
|
|
|
const ContainerLayerParameters& aParameters)
|
2012-05-03 18:05:55 +04:00
|
|
|
{
|
2013-05-30 17:50:50 +04:00
|
|
|
bool animated = false;
|
2013-05-31 05:33:17 +04:00
|
|
|
if (!nsLayoutUtils::AnimatedImageLayersEnabled() ||
|
|
|
|
mImage->GetType() != imgIContainer::TYPE_RASTER ||
|
2013-05-30 17:50:50 +04:00
|
|
|
NS_FAILED(mImage->GetAnimated(&animated)) ||
|
|
|
|
!animated) {
|
|
|
|
if (!aManager->IsCompositingCheap() ||
|
|
|
|
!nsLayoutUtils::GPUImageScalingEnabled()) {
|
|
|
|
return LAYER_NONE;
|
|
|
|
}
|
2012-05-03 18:05:55 +04:00
|
|
|
}
|
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
if (!animated) {
|
|
|
|
int32_t imageWidth;
|
|
|
|
int32_t imageHeight;
|
|
|
|
mImage->GetWidth(&imageWidth);
|
|
|
|
mImage->GetHeight(&imageHeight);
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
gfxRect destRect = GetDestRect();
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
destRect.width *= aParameters.mXScale;
|
|
|
|
destRect.height *= aParameters.mYScale;
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
// Calculate the scaling factor for the frame.
|
|
|
|
gfxSize scale = gfxSize(destRect.width / imageWidth,
|
|
|
|
destRect.height / imageHeight);
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
// If we are not scaling at all, no point in separating this into a layer.
|
|
|
|
if (scale.width == 1.0f && scale.height == 1.0f) {
|
|
|
|
return LAYER_NONE;
|
|
|
|
}
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 17:50:50 +04:00
|
|
|
// If the target size is pretty small, no point in using a layer.
|
|
|
|
if (destRect.width * destRect.height < 64 * 64) {
|
|
|
|
return LAYER_NONE;
|
|
|
|
}
|
2012-11-28 06:34:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<ImageContainer> container;
|
2012-11-29 10:01:48 +04:00
|
|
|
mImage->GetImageContainer(aManager, getter_AddRefs(container));
|
2012-11-28 06:34:45 +04:00
|
|
|
if (!container) {
|
|
|
|
return LAYER_NONE;
|
2012-05-03 18:05:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return LAYER_ACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<Layer>
|
|
|
|
nsDisplayImage::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|
|
|
LayerManager* aManager,
|
2013-09-27 10:01:16 +04:00
|
|
|
const ContainerLayerParameters& aParameters)
|
2012-05-03 18:05:55 +04:00
|
|
|
{
|
|
|
|
nsRefPtr<ImageContainer> container;
|
2012-11-28 06:34:45 +04:00
|
|
|
nsresult rv = mImage->GetImageContainer(aManager, getter_AddRefs(container));
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
2012-05-03 18:05:55 +04:00
|
|
|
|
2013-05-30 06:42:28 +04:00
|
|
|
nsRefPtr<ImageLayer> layer = static_cast<ImageLayer*>
|
|
|
|
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
|
|
|
|
if (!layer) {
|
|
|
|
layer = aManager->CreateImageLayer();
|
|
|
|
if (!layer)
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-05-03 18:05:55 +04:00
|
|
|
layer->SetContainer(container);
|
2012-09-17 02:25:33 +04:00
|
|
|
ConfigureLayer(layer, aParameters.mOffset);
|
2012-05-03 18:05:55 +04:00
|
|
|
return layer.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-09-17 02:25:33 +04:00
|
|
|
nsDisplayImage::ConfigureLayer(ImageLayer *aLayer, const nsIntPoint& aOffset)
|
2012-05-03 18:05:55 +04:00
|
|
|
{
|
|
|
|
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t imageWidth;
|
|
|
|
int32_t imageHeight;
|
2011-01-18 00:47:18 +03:00
|
|
|
mImage->GetWidth(&imageWidth);
|
|
|
|
mImage->GetHeight(&imageHeight);
|
|
|
|
|
2012-05-03 18:05:55 +04:00
|
|
|
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
|
|
|
|
|
|
|
|
const gfxRect destRect = GetDestRect();
|
|
|
|
|
2011-01-18 00:47:18 +03:00
|
|
|
gfxMatrix transform;
|
2012-09-17 02:25:33 +04:00
|
|
|
transform.Translate(destRect.TopLeft() + aOffset);
|
2011-04-19 07:07:21 +04:00
|
|
|
transform.Scale(destRect.Width()/imageWidth,
|
|
|
|
destRect.Height()/imageHeight);
|
2012-07-31 06:20:00 +04:00
|
|
|
aLayer->SetBaseTransform(gfx3DMatrix::From2D(transform));
|
2011-01-18 00:47:18 +03:00
|
|
|
aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
|
|
|
|
}
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
|
2009-09-13 02:44:18 +04:00
|
|
|
const nsRect& aDirtyRect, imgIContainer* aImage,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
2006-01-26 05:29:17 +03:00
|
|
|
{
|
|
|
|
// Render the image into our content area (the area inside
|
|
|
|
// the borders and padding)
|
2007-03-20 03:58:20 +03:00
|
|
|
NS_ASSERTION(GetInnerArea().width == mComputedSize.width, "bad width");
|
2006-01-26 05:29:17 +03:00
|
|
|
nsRect inner = GetInnerArea() + aPt;
|
2007-03-20 03:58:20 +03:00
|
|
|
nsRect dest(inner.TopLeft(), mComputedSize);
|
|
|
|
dest.y -= GetContinuationOffset();
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2009-04-05 13:52:14 +04:00
|
|
|
nsLayoutUtils::DrawSingleImage(&aRenderingContext, aImage,
|
2009-09-13 02:44:18 +04:00
|
|
|
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
|
2013-03-01 00:22:43 +04:00
|
|
|
nullptr, aFlags);
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-09 01:31:05 +04:00
|
|
|
|
2011-09-27 00:55:04 +04:00
|
|
|
nsImageMap* map = GetImageMap();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != map) {
|
2006-01-26 05:29:17 +03:00
|
|
|
aRenderingContext.PushState();
|
2013-04-27 12:54:36 +04:00
|
|
|
aRenderingContext.Translate(inner.TopLeft());
|
|
|
|
aRenderingContext.SetColor(NS_RGB(255, 255, 255));
|
|
|
|
aRenderingContext.SetLineStyle(nsLineStyle_kSolid);
|
|
|
|
map->Draw(this, aRenderingContext);
|
2006-01-26 05:29:17 +03:00
|
|
|
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
|
|
|
|
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
|
2008-08-07 18:44:04 +04:00
|
|
|
map->Draw(this, aRenderingContext);
|
2006-01-26 05:29:17 +03:00
|
|
|
aRenderingContext.PopState();
|
|
|
|
}
|
|
|
|
}
|
2003-11-06 19:03:34 +03:00
|
|
|
|
2013-02-14 15:12:27 +04:00
|
|
|
void
|
2006-01-26 05:29:17 +03:00
|
|
|
nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
if (!IsVisibleForPainting(aBuilder))
|
2013-02-14 15:12:27 +04:00
|
|
|
return;
|
2006-01-26 05:29:17 +03:00
|
|
|
|
2013-02-14 15:08:08 +04:00
|
|
|
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
2010-09-09 19:21:47 +04:00
|
|
|
|
2013-03-04 13:56:02 +04:00
|
|
|
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
|
|
|
|
clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
if (mComputedSize.width != 0 && mComputedSize.height != 0) {
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
|
|
|
NS_ASSERTION(imageLoader, "Not an image loading content?");
|
|
|
|
|
|
|
|
nsCOMPtr<imgIRequest> currentRequest;
|
|
|
|
if (imageLoader) {
|
|
|
|
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(currentRequest));
|
|
|
|
}
|
|
|
|
|
2011-06-01 05:46:57 +04:00
|
|
|
nsEventStates contentState = mContent->AsElement()->State();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool imageOK = IMAGE_OK(contentState, true);
|
2006-01-26 05:29:17 +03:00
|
|
|
|
2013-08-29 02:39:06 +04:00
|
|
|
// XXX(seth): The SizeIsAvailable check here should not be necessary - the
|
|
|
|
// intention is that a non-null mImage means we have a size, but there is
|
|
|
|
// currently some code that violates this invariant.
|
|
|
|
if (!imageOK || !mImage || !SizeIsAvailable(currentRequest)) {
|
2006-01-26 05:29:17 +03:00
|
|
|
// No image yet, or image load failed. Draw the alt-text and an icon
|
|
|
|
// indicating the status
|
2013-03-04 13:56:02 +04:00
|
|
|
aLists.Content()->AppendNewToTop(new (aBuilder)
|
2013-02-14 15:08:08 +04:00
|
|
|
nsDisplayAltFeedback(aBuilder, this));
|
2013-08-29 02:39:06 +04:00
|
|
|
} else {
|
2013-03-04 13:56:02 +04:00
|
|
|
aLists.Content()->AppendNewToTop(new (aBuilder)
|
2013-08-29 02:39:06 +04:00
|
|
|
nsDisplayImage(aBuilder, this, mImage));
|
2009-08-12 18:23:38 +04:00
|
|
|
|
|
|
|
// If we were previously displaying an icon, we're not anymore
|
|
|
|
if (mDisplayingIcon) {
|
|
|
|
gIconLoad->RemoveIconObserver(this);
|
2011-10-17 18:59:28 +04:00
|
|
|
mDisplayingIcon = false;
|
2009-08-12 18:23:38 +04:00
|
|
|
}
|
|
|
|
|
2003-11-06 19:03:34 +03:00
|
|
|
#ifdef DEBUG
|
2011-09-27 00:55:04 +04:00
|
|
|
if (GetShowFrameBorders() && GetImageMap()) {
|
2013-02-14 15:08:08 +04:00
|
|
|
aLists.Outlines()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayGeneric(aBuilder, this, PaintDebugImageMap, "DebugImageMap",
|
|
|
|
nsDisplayItem::TYPE_DEBUG_IMAGE_MAP));
|
2003-11-06 19:03:34 +03:00
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
#endif
|
1999-04-10 21:32:33 +04:00
|
|
|
}
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
2001-12-18 04:29:49 +03:00
|
|
|
|
2010-10-07 08:25:47 +04:00
|
|
|
if (ShouldDisplaySelection()) {
|
2013-03-04 13:56:02 +04:00
|
|
|
DisplaySelectionOverlay(aBuilder, aLists.Content(),
|
2013-02-14 15:08:08 +04:00
|
|
|
nsISelectionDisplay::DISPLAY_IMAGES);
|
2010-10-07 08:25:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsImageFrame::ShouldDisplaySelection()
|
|
|
|
{
|
2006-01-26 05:29:17 +03:00
|
|
|
// XXX what on EARTH is this code for?
|
|
|
|
nsresult result;
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext* presContext = PresContext();
|
2012-08-22 19:56:38 +04:00
|
|
|
int16_t displaySelection = presContext->PresShell()->GetSelectionFlags();
|
2001-12-18 04:29:49 +03:00
|
|
|
if (!(displaySelection & nsISelectionDisplay::DISPLAY_IMAGES))
|
2010-10-07 08:25:47 +04:00
|
|
|
return false;//no need to check the blue border, we cannot be drawn selected
|
2003-04-23 03:18:34 +04:00
|
|
|
//insert hook here for image selection drawing
|
|
|
|
#if IMAGE_EDITOR_CHECK
|
|
|
|
//check to see if this frame is in an editor context
|
|
|
|
//isEditor check. this needs to be changed to have better way to check
|
|
|
|
if (displaySelection == nsISelectionDisplay::DISPLAY_ALL)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
2006-01-26 05:29:17 +03:00
|
|
|
result = GetSelectionController(presContext, getter_AddRefs(selCon));
|
2003-04-23 03:18:34 +04:00
|
|
|
if (NS_SUCCEEDED(result) && selCon)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISelection> selection;
|
|
|
|
result = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(result) && selection)
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rangeCount;
|
2003-04-23 03:18:34 +04:00
|
|
|
selection->GetRangeCount(&rangeCount);
|
|
|
|
if (rangeCount == 1) //if not one then let code drop to nsFrame::Paint
|
|
|
|
{
|
2003-07-29 01:25:13 +04:00
|
|
|
nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
|
2003-04-23 03:18:34 +04:00
|
|
|
if (parentContent)
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t thisOffset = parentContent->IndexOf(mContent);
|
2003-04-23 03:18:34 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(parentContent);
|
|
|
|
nsCOMPtr<nsIDOMNode> rangeNode;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rangeOffset;
|
2003-04-23 03:18:34 +04:00
|
|
|
nsCOMPtr<nsIDOMRange> range;
|
|
|
|
selection->GetRangeAt(0,getter_AddRefs(range));
|
|
|
|
if (range)
|
|
|
|
{
|
|
|
|
range->GetStartContainer(getter_AddRefs(rangeNode));
|
|
|
|
range->GetStartOffset(&rangeOffset);
|
|
|
|
|
|
|
|
if (parentNode && rangeNode && (rangeNode == parentNode) && rangeOffset == thisOffset)
|
|
|
|
{
|
|
|
|
range->GetEndContainer(getter_AddRefs(rangeNode));
|
|
|
|
range->GetEndOffset(&rangeOffset);
|
|
|
|
if ((rangeNode == parentNode) && (rangeOffset == (thisOffset +1))) //+1 since that would mean this whole content is selected only
|
2010-10-07 08:25:47 +04:00
|
|
|
return false; //do not allow nsFrame do draw any further selection
|
2003-04-23 03:18:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2010-10-07 08:25:47 +04:00
|
|
|
return true;
|
2002-08-17 05:46:58 +04:00
|
|
|
}
|
|
|
|
|
1999-01-09 03:13:19 +03:00
|
|
|
nsImageMap*
|
2011-09-27 00:55:04 +04:00
|
|
|
nsImageFrame::GetImageMap()
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2001-04-18 04:14:34 +04:00
|
|
|
if (!mImageMap) {
|
2012-03-16 00:16:02 +04:00
|
|
|
nsIContent* map = GetMapElement();
|
2004-02-19 21:56:13 +03:00
|
|
|
if (map) {
|
2001-04-18 04:14:34 +04:00
|
|
|
mImageMap = new nsImageMap();
|
2011-05-30 15:00:00 +04:00
|
|
|
NS_ADDREF(mImageMap);
|
2011-09-27 00:55:04 +04:00
|
|
|
mImageMap->Init(this, map);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
}
|
1999-01-09 03:13:19 +03:00
|
|
|
|
1998-09-09 02:34:40 +04:00
|
|
|
return mImageMap;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
1998-11-20 20:21:02 +03:00
|
|
|
nsImageFrame::IsServerImageMap()
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2006-12-26 20:47:52 +03:00
|
|
|
return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::ismap);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
2005-08-23 07:57:07 +04:00
|
|
|
// Translate an point that is relative to our frame
|
|
|
|
// into a localized pixel coordinate that is relative to the
|
1999-07-08 23:38:08 +04:00
|
|
|
// content area of this frame (inside the border+padding).
|
|
|
|
void
|
2004-12-26 22:48:54 +03:00
|
|
|
nsImageFrame::TranslateEventCoords(const nsPoint& aPoint,
|
2007-02-18 19:49:54 +03:00
|
|
|
nsIntPoint& aResult)
|
1999-07-08 23:38:08 +04:00
|
|
|
{
|
|
|
|
nscoord x = aPoint.x;
|
|
|
|
nscoord y = aPoint.y;
|
|
|
|
|
|
|
|
// Subtract out border and padding here so that the coordinates are
|
|
|
|
// now relative to the content area of this frame.
|
2004-12-26 22:48:54 +03:00
|
|
|
nsRect inner = GetInnerArea();
|
1999-07-08 23:38:08 +04:00
|
|
|
x -= inner.x;
|
|
|
|
y -= inner.y;
|
|
|
|
|
2007-02-07 10:46:44 +03:00
|
|
|
aResult.x = nsPresContext::AppUnitsToIntCSSPixels(x);
|
|
|
|
aResult.y = nsPresContext::AppUnitsToIntCSSPixels(y);
|
1999-07-08 23:38:08 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2006-02-02 23:02:34 +03:00
|
|
|
nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
|
2007-07-11 17:05:05 +04:00
|
|
|
nsIContent** aNode)
|
1999-07-08 23:38:08 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool status = false;
|
2001-04-11 12:12:10 +04:00
|
|
|
aTarget.Truncate();
|
2012-07-30 18:20:58 +04:00
|
|
|
*aHref = nullptr;
|
|
|
|
*aNode = nullptr;
|
1999-07-08 23:38:08 +04:00
|
|
|
|
|
|
|
// Walk up the content tree, looking for an nsIDOMAnchorElement
|
2003-07-29 01:25:13 +04:00
|
|
|
for (nsIContent* content = mContent->GetParent();
|
|
|
|
content; content = content->GetParent()) {
|
2013-08-08 09:26:32 +04:00
|
|
|
nsCOMPtr<dom::Link> link(do_QueryInterface(content));
|
2004-02-10 19:57:00 +03:00
|
|
|
if (link) {
|
2009-09-23 19:11:48 +04:00
|
|
|
nsCOMPtr<nsIURI> href = content->GetHrefURI();
|
|
|
|
if (href) {
|
|
|
|
href->Clone(aHref);
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
status = (*aHref != nullptr);
|
2004-02-10 19:57:00 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(content));
|
|
|
|
if (anchor) {
|
|
|
|
anchor->GetTarget(aTarget);
|
1999-07-08 23:44:42 +04:00
|
|
|
}
|
2006-02-02 23:02:34 +03:00
|
|
|
NS_ADDREF(*aNode = content);
|
1999-07-08 23:38:08 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-07-08 23:44:42 +04:00
|
|
|
return status;
|
1999-07-08 23:38:08 +04:00
|
|
|
}
|
|
|
|
|
2000-02-11 04:24:59 +03:00
|
|
|
NS_IMETHODIMP
|
2013-10-02 07:46:04 +04:00
|
|
|
nsImageFrame::GetContentForEvent(WidgetEvent* aEvent,
|
2000-02-11 04:24:59 +03:00
|
|
|
nsIContent** aContent)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aContent);
|
2009-09-02 06:46:33 +04:00
|
|
|
|
|
|
|
nsIFrame* f = nsLayoutUtils::GetNonGeneratedAncestor(this);
|
|
|
|
if (f != this) {
|
2011-09-27 00:55:04 +04:00
|
|
|
return f->GetContentForEvent(aEvent, aContent);
|
2009-09-02 06:46:33 +04:00
|
|
|
}
|
|
|
|
|
2010-02-03 05:07:19 +03:00
|
|
|
// XXX We need to make this special check for area element's capturing the
|
|
|
|
// mouse due to bug 135040. Remove it once that's fixed.
|
|
|
|
nsIContent* capturingContent =
|
2013-09-24 14:04:16 +04:00
|
|
|
aEvent->HasMouseEventMessage() ? nsIPresShell::GetCapturingContent() :
|
|
|
|
nullptr;
|
2010-02-03 05:07:19 +03:00
|
|
|
if (capturingContent && capturingContent->GetPrimaryFrame() == this) {
|
|
|
|
*aContent = capturingContent;
|
|
|
|
NS_IF_ADDREF(*aContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-27 00:55:04 +04:00
|
|
|
nsImageMap* map = GetImageMap();
|
2000-02-11 04:24:59 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != map) {
|
2007-02-18 19:49:54 +03:00
|
|
|
nsIntPoint p;
|
2005-08-23 07:57:07 +04:00
|
|
|
TranslateEventCoords(
|
|
|
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this), p);
|
2011-10-30 23:51:19 +04:00
|
|
|
nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
|
|
|
|
if (area) {
|
2011-11-17 22:01:24 +04:00
|
|
|
area.forget(aContent);
|
2000-02-11 04:24:59 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-29 07:43:05 +04:00
|
|
|
*aContent = GetContent();
|
|
|
|
NS_IF_ADDREF(*aContent);
|
|
|
|
return NS_OK;
|
2000-02-11 04:24:59 +03:00
|
|
|
}
|
|
|
|
|
1998-09-09 02:34:40 +04:00
|
|
|
// XXX what should clicks on transparent pixels do?
|
2006-04-21 01:02:10 +04:00
|
|
|
NS_IMETHODIMP
|
2004-08-01 03:15:21 +04:00
|
|
|
nsImageFrame::HandleEvent(nsPresContext* aPresContext,
|
2013-10-02 07:46:03 +04:00
|
|
|
WidgetGUIEvent* aEvent,
|
1999-11-24 09:03:41 +03:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
1999-11-24 09:03:41 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
1998-09-09 02:34:40 +04:00
|
|
|
|
2013-10-22 12:55:20 +04:00
|
|
|
if ((aEvent->message == NS_MOUSE_BUTTON_UP &&
|
|
|
|
aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) ||
|
2006-11-17 00:35:39 +03:00
|
|
|
aEvent->message == NS_MOUSE_MOVE) {
|
2011-09-27 00:55:04 +04:00
|
|
|
nsImageMap* map = GetImageMap();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isServerMap = IsServerImageMap();
|
2012-07-30 18:20:58 +04:00
|
|
|
if ((nullptr != map) || isServerMap) {
|
2007-02-18 19:49:54 +03:00
|
|
|
nsIntPoint p;
|
2006-11-17 00:35:39 +03:00
|
|
|
TranslateEventCoords(
|
|
|
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this), p);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool inside = false;
|
2006-11-17 00:35:39 +03:00
|
|
|
// Even though client-side image map triggering happens
|
|
|
|
// through content, we need to make sure we're not inside
|
|
|
|
// (in case we deal with a case of both client-side and
|
|
|
|
// sever-side on the same image - it happens!)
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != map) {
|
2011-10-30 23:51:19 +04:00
|
|
|
inside = !!map->GetArea(p.x, p.y);
|
2006-11-17 00:35:39 +03:00
|
|
|
}
|
2001-05-23 11:00:37 +04:00
|
|
|
|
2006-11-17 00:35:39 +03:00
|
|
|
if (!inside && isServerMap) {
|
|
|
|
|
|
|
|
// Server side image maps use the href in a containing anchor
|
|
|
|
// element to provide the basis for the destination url.
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsAutoString target;
|
2007-07-11 17:05:05 +04:00
|
|
|
nsCOMPtr<nsIContent> anchorNode;
|
2006-11-17 00:35:39 +03:00
|
|
|
if (GetAnchorHREFTargetAndNode(getter_AddRefs(uri), target,
|
|
|
|
getter_AddRefs(anchorNode))) {
|
|
|
|
// XXX if the mouse is over/clicked in the border/padding area
|
|
|
|
// we should probably just pretend nothing happened. Nav4
|
|
|
|
// keeps the x,y coordinates positive as we do; IE doesn't
|
|
|
|
// bother. Both of them send the click through even when the
|
|
|
|
// mouse is over the border.
|
|
|
|
if (p.x < 0) p.x = 0;
|
|
|
|
if (p.y < 0) p.y = 0;
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString spec;
|
2006-11-17 00:35:39 +03:00
|
|
|
uri->GetSpec(spec);
|
|
|
|
spec += nsPrintfCString("?%d,%d", p.x, p.y);
|
|
|
|
uri->SetSpec(spec);
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool clicked = false;
|
2006-11-17 00:35:39 +03:00
|
|
|
if (aEvent->message == NS_MOUSE_BUTTON_UP) {
|
|
|
|
*aEventStatus = nsEventStatus_eConsumeDoDefault;
|
2011-10-17 18:59:28 +04:00
|
|
|
clicked = true;
|
1999-07-08 23:44:42 +04:00
|
|
|
}
|
2007-07-11 17:05:05 +04:00
|
|
|
nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target,
|
2011-10-17 18:59:28 +04:00
|
|
|
clicked, true, true);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-04-13 01:24:07 +04:00
|
|
|
|
2001-11-01 18:31:13 +03:00
|
|
|
return nsSplittableFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
2006-04-21 01:02:10 +04:00
|
|
|
NS_IMETHODIMP
|
2004-12-31 00:56:11 +03:00
|
|
|
nsImageFrame::GetCursor(const nsPoint& aPoint,
|
|
|
|
nsIFrame::Cursor& aCursor)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2011-09-27 00:55:04 +04:00
|
|
|
nsImageMap* map = GetImageMap();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != map) {
|
2007-02-18 19:49:54 +03:00
|
|
|
nsIntPoint p;
|
2004-12-26 22:48:54 +03:00
|
|
|
TranslateEventCoords(aPoint, p);
|
2011-10-30 23:51:19 +04:00
|
|
|
nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
|
|
|
|
if (area) {
|
2006-04-21 01:02:10 +04:00
|
|
|
// Use the cursor from the style of the *area* element.
|
|
|
|
// XXX Using the image as the parent style context isn't
|
|
|
|
// technically correct, but it's probably the right thing to do
|
|
|
|
// here, since it means that areas on which the cursor isn't
|
|
|
|
// specified will inherit the style from the image.
|
|
|
|
nsRefPtr<nsStyleContext> areaStyle =
|
2007-03-31 01:11:41 +04:00
|
|
|
PresContext()->PresShell()->StyleSet()->
|
2013-02-16 09:38:33 +04:00
|
|
|
ResolveStyleFor(area->AsElement(), StyleContext());
|
2013-08-03 08:11:06 +04:00
|
|
|
FillCursorInformationFromStyle(areaStyle->StyleUserInterface(),
|
|
|
|
aCursor);
|
|
|
|
if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
|
|
|
|
aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
|
1998-11-24 01:21:13 +03:00
|
|
|
}
|
2013-08-03 08:11:06 +04:00
|
|
|
return NS_OK;
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
}
|
2004-12-31 00:56:11 +03:00
|
|
|
return nsFrame::GetCursor(aPoint, aCursor);
|
1998-09-09 02:34:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsImageFrame::AttributeChanged(int32_t aNameSpaceID,
|
1998-11-20 20:21:02 +03:00
|
|
|
nsIAtom* aAttribute,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aModType)
|
1998-09-09 02:34:40 +04:00
|
|
|
{
|
2005-09-07 20:49:21 +04:00
|
|
|
nsresult rv = nsSplittableFrame::AttributeChanged(aNameSpaceID,
|
2004-12-31 04:13:27 +03:00
|
|
|
aAttribute, aModType);
|
2004-09-30 23:23:40 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
1998-09-29 01:22:31 +04:00
|
|
|
return rv;
|
|
|
|
}
|
2006-12-26 20:47:52 +03:00
|
|
|
if (nsGkAtoms::alt == aAttribute)
|
2004-09-30 23:23:40 +04:00
|
|
|
{
|
2007-05-06 23:16:51 +04:00
|
|
|
PresContext()->PresShell()->FrameNeedsReflow(this,
|
|
|
|
nsIPresShell::eStyleChange,
|
|
|
|
NS_FRAME_IS_DIRTY);
|
2000-04-17 18:40:46 +04:00
|
|
|
}
|
1998-09-09 02:34:40 +04:00
|
|
|
|
1998-09-25 20:35:01 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-08-31 07:09:40 +04:00
|
|
|
|
2003-10-31 23:19:18 +03:00
|
|
|
nsIAtom*
|
|
|
|
nsImageFrame::GetType() const
|
1999-08-31 07:09:40 +04:00
|
|
|
{
|
2006-12-26 20:47:52 +03:00
|
|
|
return nsGkAtoms::imageFrame;
|
1999-08-31 07:09:40 +04:00
|
|
|
}
|
|
|
|
|
2001-10-31 07:43:48 +03:00
|
|
|
#ifdef DEBUG
|
2005-05-09 21:46:06 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsImageFrame::GetFrameName(nsAString& aResult) const
|
|
|
|
{
|
|
|
|
return MakeFrameName(NS_LITERAL_STRING("ImageFrame"), aResult);
|
|
|
|
}
|
|
|
|
|
2013-04-30 22:38:52 +04:00
|
|
|
void
|
2012-09-19 18:36:35 +04:00
|
|
|
nsImageFrame::List(FILE* out, int32_t aIndent, uint32_t aFlags) const
|
2001-10-31 07:43:48 +03:00
|
|
|
{
|
2013-04-30 22:38:52 +04:00
|
|
|
ListGeneric(out, aIndent, aFlags);
|
2001-10-31 07:43:48 +03:00
|
|
|
|
|
|
|
// output the img src url
|
2003-03-19 06:47:09 +03:00
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
|
|
|
if (imageLoader) {
|
|
|
|
nsCOMPtr<imgIRequest> currentRequest;
|
|
|
|
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(currentRequest));
|
|
|
|
if (currentRequest) {
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
currentRequest->GetURI(getter_AddRefs(uri));
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString uristr;
|
2003-03-19 06:47:09 +03:00
|
|
|
uri->GetAsciiSpec(uristr);
|
|
|
|
fprintf(out, " [src=%s]", uristr.get());
|
|
|
|
}
|
2002-03-21 01:14:27 +03:00
|
|
|
}
|
2001-10-31 07:43:48 +03:00
|
|
|
fputs("\n", out);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-08-09 11:09:40 +04:00
|
|
|
int
|
2013-07-25 19:34:27 +04:00
|
|
|
nsImageFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const
|
2007-03-20 03:58:20 +03:00
|
|
|
{
|
2012-08-09 11:09:40 +04:00
|
|
|
int skip = 0;
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != GetPrevInFlow()) {
|
2007-03-20 03:58:20 +03:00
|
|
|
skip |= 1 << NS_SIDE_TOP;
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != GetNextInFlow()) {
|
2007-03-20 03:58:20 +03:00
|
|
|
skip |= 1 << NS_SIDE_BOTTOM;
|
|
|
|
}
|
|
|
|
return skip;
|
|
|
|
}
|
|
|
|
|
2011-04-26 10:52:19 +04:00
|
|
|
nsresult
|
2000-01-04 06:06:13 +03:00
|
|
|
nsImageFrame::GetIntrinsicImageSize(nsSize& aSize)
|
|
|
|
{
|
2010-09-09 00:40:38 +04:00
|
|
|
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;
|
2000-01-04 06:06:13 +03:00
|
|
|
}
|
|
|
|
|
2001-10-07 22:02:13 +04:00
|
|
|
nsresult
|
2003-03-19 06:47:09 +03:00
|
|
|
nsImageFrame::LoadIcon(const nsAString& aSpec,
|
2004-08-01 03:15:21 +04:00
|
|
|
nsPresContext *aPresContext,
|
2012-10-12 16:43:01 +04:00
|
|
|
imgRequestProxy** aRequest)
|
2001-05-04 10:29:59 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2003-03-19 06:47:09 +03:00
|
|
|
NS_PRECONDITION(!aSpec.IsEmpty(), "What happened??");
|
2001-05-04 10:29:59 +04:00
|
|
|
|
2004-01-21 12:35:59 +03:00
|
|
|
if (!sIOService) {
|
2006-06-19 01:18:22 +04:00
|
|
|
rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
2004-01-21 12:35:59 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2001-06-06 00:22:52 +04:00
|
|
|
nsCOMPtr<nsIURI> realURI;
|
2004-01-21 12:35:59 +03:00
|
|
|
SpecToURI(aSpec, sIOService, getter_AddRefs(realURI));
|
2003-03-19 06:47:09 +03:00
|
|
|
|
2012-11-16 22:24:58 +04:00
|
|
|
nsRefPtr<imgLoader> il =
|
2012-06-26 08:20:12 +04:00
|
|
|
nsContentUtils::GetImgLoaderForDocument(aPresContext->Document());
|
2001-05-04 10:29:59 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
|
|
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
// For icon loads, we don't need to merge with the loadgroup flags
|
2001-09-29 21:50:15 +04:00
|
|
|
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
|
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
return il->LoadImage(realURI, /* icon URI */
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, /* initial document URI; this is only
|
2003-03-19 06:47:09 +03:00
|
|
|
relevant for cookies, so does not
|
|
|
|
apply to icons. */
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, /* referrer (not relevant for icons) */
|
|
|
|
nullptr, /* principal (not relevant for icons) */
|
2003-03-19 06:47:09 +03:00
|
|
|
loadGroup,
|
2009-08-12 18:23:38 +04:00
|
|
|
gIconLoad,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, /* Not associated with any particular document */
|
2003-03-19 06:47:09 +03:00
|
|
|
loadFlags,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr,
|
|
|
|
nullptr, /* channel policy not needed */
|
2003-03-19 06:47:09 +03:00
|
|
|
aRequest);
|
2001-05-04 10:29:59 +04:00
|
|
|
}
|
|
|
|
|
2002-03-13 01:26:11 +03:00
|
|
|
void
|
2003-06-17 20:40:34 +04:00
|
|
|
nsImageFrame::GetDocumentCharacterSet(nsACString& aCharset) const
|
2002-03-13 01:26:11 +03:00
|
|
|
{
|
2003-07-29 01:25:13 +04:00
|
|
|
if (mContent) {
|
|
|
|
NS_ASSERTION(mContent->GetDocument(),
|
|
|
|
"Frame still alive after content removed from document!");
|
2003-10-22 10:09:48 +04:00
|
|
|
aCharset = mContent->GetDocument()->GetDocumentCharacterSet();
|
2002-03-13 01:26:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-15 06:13:49 +04:00
|
|
|
void
|
2003-03-19 06:47:09 +03:00
|
|
|
nsImageFrame::SpecToURI(const nsAString& aSpec, nsIIOService *aIOService,
|
2002-11-06 15:58:05 +03:00
|
|
|
nsIURI **aURI)
|
2001-05-04 10:29:59 +04:00
|
|
|
{
|
2001-04-15 06:13:49 +04:00
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
2003-07-03 06:45:34 +04:00
|
|
|
if (mContent) {
|
2004-01-10 02:54:21 +03:00
|
|
|
baseURI = mContent->GetBaseURI();
|
2003-07-03 06:45:34 +04:00
|
|
|
}
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString charset;
|
2002-03-13 01:26:11 +03:00
|
|
|
GetDocumentCharacterSet(charset);
|
|
|
|
NS_NewURI(aURI, aSpec,
|
2012-07-30 18:20:58 +04:00
|
|
|
charset.IsEmpty() ? nullptr : charset.get(),
|
2002-11-06 15:58:05 +03:00
|
|
|
baseURI, aIOService);
|
2001-04-15 06:13:49 +04:00
|
|
|
}
|
|
|
|
|
2001-03-22 04:38:35 +03:00
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
nsImageFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
|
|
|
if (!aPresContext)
|
|
|
|
return;
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_PRECONDITION(nullptr != aLoadGroup, "null OUT parameter pointer");
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2003-12-21 08:36:36 +03:00
|
|
|
nsIPresShell *shell = aPresContext->GetPresShell();
|
2001-03-22 04:38:35 +03:00
|
|
|
|
|
|
|
if (!shell)
|
|
|
|
return;
|
|
|
|
|
2004-08-02 08:52:55 +04:00
|
|
|
nsIDocument *doc = shell->GetDocument();
|
2001-03-22 04:38:35 +03:00
|
|
|
if (!doc)
|
|
|
|
return;
|
|
|
|
|
2003-10-22 10:09:48 +04:00
|
|
|
*aLoadGroup = doc->GetDocumentLoadGroup().get(); // already_AddRefed
|
2001-03-22 04:38:35 +03:00
|
|
|
}
|
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
nsresult nsImageFrame::LoadIcons(nsPresContext *aPresContext)
|
2001-11-07 08:02:42 +03:00
|
|
|
{
|
2004-02-03 23:30:02 +03:00
|
|
|
NS_ASSERTION(!gIconLoad, "called LoadIcons twice");
|
|
|
|
|
2009-10-12 23:31:50 +04:00
|
|
|
NS_NAMED_LITERAL_STRING(loadingSrc,"resource://gre-resources/loading-image.png");
|
|
|
|
NS_NAMED_LITERAL_STRING(brokenSrc,"resource://gre-resources/broken-image.png");
|
2001-11-07 08:02:42 +03:00
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
gIconLoad = new IconLoad();
|
2004-02-03 23:30:02 +03:00
|
|
|
NS_ADDREF(gIconLoad);
|
2001-11-07 08:02:42 +03:00
|
|
|
|
2003-03-19 06:47:09 +03:00
|
|
|
nsresult rv;
|
|
|
|
// create a loader and load the images
|
|
|
|
rv = LoadIcon(loadingSrc,
|
|
|
|
aPresContext,
|
2004-02-03 23:30:02 +03:00
|
|
|
getter_AddRefs(gIconLoad->mLoadingImage));
|
2003-03-19 06:47:09 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = LoadIcon(brokenSrc,
|
|
|
|
aPresContext,
|
2004-02-03 23:30:02 +03:00
|
|
|
getter_AddRefs(gIconLoad->mBrokenImage));
|
2001-11-07 08:02:42 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
NS_IMPL_ISUPPORTS2(nsImageFrame::IconLoad, nsIObserver,
|
2012-10-12 20:11:22 +04:00
|
|
|
imgINotificationObserver)
|
2004-02-03 23:30:02 +03:00
|
|
|
|
2011-05-29 03:39:27 +04:00
|
|
|
static const char* kIconLoadPrefs[] = {
|
2004-02-03 23:30:02 +03:00
|
|
|
"browser.display.force_inline_alttext",
|
2011-05-29 03:39:27 +04:00
|
|
|
"browser.display.show_image_placeholders",
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr
|
2004-02-03 23:30:02 +03:00
|
|
|
};
|
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
nsImageFrame::IconLoad::IconLoad()
|
2004-02-03 23:30:02 +03:00
|
|
|
{
|
2011-05-29 03:39:27 +04:00
|
|
|
// register observers
|
2011-05-29 03:39:27 +04:00
|
|
|
Preferences::AddStrongObservers(this, kIconLoadPrefs);
|
2004-04-30 03:34:19 +04:00
|
|
|
GetPrefs();
|
2001-11-07 08:02:42 +03:00
|
|
|
}
|
|
|
|
|
2011-06-03 10:07:10 +04:00
|
|
|
void
|
|
|
|
nsImageFrame::IconLoad::Shutdown()
|
|
|
|
{
|
|
|
|
Preferences::RemoveObservers(this, kIconLoadPrefs);
|
|
|
|
// in case the pref service releases us later
|
|
|
|
if (mLoadingImage) {
|
|
|
|
mLoadingImage->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
2012-07-30 18:20:58 +04:00
|
|
|
mLoadingImage = nullptr;
|
2011-06-03 10:07:10 +04:00
|
|
|
}
|
|
|
|
if (mBrokenImage) {
|
|
|
|
mBrokenImage->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
2012-07-30 18:20:58 +04:00
|
|
|
mBrokenImage = nullptr;
|
2011-06-03 10:07:10 +04:00
|
|
|
}
|
|
|
|
}
|
2004-02-03 23:30:02 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsImageFrame::IconLoad::Observe(nsISupports *aSubject, const char* aTopic,
|
|
|
|
const PRUnichar* aData)
|
2001-11-07 08:02:42 +03:00
|
|
|
{
|
2004-02-03 23:30:02 +03:00
|
|
|
NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
|
|
|
|
"wrong topic");
|
|
|
|
#ifdef DEBUG
|
|
|
|
// assert |aData| is one of our prefs.
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < ArrayLength(kIconLoadPrefs) ||
|
2011-10-17 18:59:28 +04:00
|
|
|
(NS_NOTREACHED("wrong pref"), false); ++i)
|
2004-02-03 23:30:02 +03:00
|
|
|
if (NS_ConvertASCIItoUTF16(kIconLoadPrefs[i]) == nsDependentString(aData))
|
|
|
|
break;
|
|
|
|
#endif
|
2001-11-07 08:02:42 +03:00
|
|
|
|
2004-04-30 03:34:19 +04:00
|
|
|
GetPrefs();
|
2004-02-03 23:30:02 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-04-30 03:34:19 +04:00
|
|
|
void nsImageFrame::IconLoad::GetPrefs()
|
2004-02-03 23:30:02 +03:00
|
|
|
{
|
2004-04-30 03:34:19 +04:00
|
|
|
mPrefForceInlineAltText =
|
2011-05-25 10:31:59 +04:00
|
|
|
Preferences::GetBool("browser.display.force_inline_alttext");
|
2004-04-30 03:34:19 +04:00
|
|
|
|
|
|
|
mPrefShowPlaceholders =
|
2011-09-29 10:19:26 +04:00
|
|
|
Preferences::GetBool("browser.display.show_image_placeholders", true);
|
2001-11-07 08:02:42 +03:00
|
|
|
}
|
2001-04-15 06:13:49 +04:00
|
|
|
|
2009-08-12 18:23:38 +04:00
|
|
|
NS_IMETHODIMP
|
2012-10-12 20:11:22 +04:00
|
|
|
nsImageFrame::IconLoad::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
|
2009-08-12 18:23:38 +04:00
|
|
|
{
|
2012-10-12 20:11:23 +04:00
|
|
|
if (aType != imgINotificationObserver::LOAD_COMPLETE &&
|
|
|
|
aType != imgINotificationObserver::FRAME_UPDATE) {
|
2012-10-12 20:11:22 +04:00
|
|
|
return NS_OK;
|
2009-08-12 18:23:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsTObserverArray<nsImageFrame*>::ForwardIterator iter(mIconObservers);
|
|
|
|
nsImageFrame *frame;
|
|
|
|
while (iter.HasMore()) {
|
|
|
|
frame = iter.GetNext();
|
2012-08-29 09:39:31 +04:00
|
|
|
frame->InvalidateFrame();
|
2009-08-12 18:23:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-12 20:11:22 +04:00
|
|
|
NS_IMPL_ISUPPORTS1(nsImageListener, imgINotificationObserver)
|
2001-03-22 04:38:35 +03:00
|
|
|
|
2001-04-15 06:13:49 +04:00
|
|
|
nsImageListener::nsImageListener(nsImageFrame *aFrame) :
|
|
|
|
mFrame(aFrame)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsImageListener::~nsImageListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-10-12 20:11:22 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
|
2001-03-22 04:38:35 +03:00
|
|
|
{
|
|
|
|
if (!mFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2012-10-12 20:11:22 +04:00
|
|
|
return mFrame->Notify(aRequest, aType, aData);
|
2001-03-22 04:38:35 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2007-12-03 12:24:49 +03:00
|
|
|
IsInAutoWidthTableCellForQuirk(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
if (eCompatibility_NavQuirks != aFrame->PresContext()->CompatibilityMode())
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-12-03 12:24:49 +03:00
|
|
|
// Check if the parent of the closest nsBlockFrame has auto width.
|
|
|
|
nsBlockFrame *ancestor = nsLayoutUtils::FindNearestBlockAncestor(aFrame);
|
2013-02-16 09:38:33 +04:00
|
|
|
if (ancestor->StyleContext()->GetPseudo() == nsCSSAnonBoxes::cellContent) {
|
2007-12-03 12:24:49 +03:00
|
|
|
// Assume direct parent is a table cell frame.
|
|
|
|
nsFrame *grandAncestor = static_cast<nsFrame*>(ancestor->GetParent());
|
|
|
|
return grandAncestor &&
|
2013-02-17 01:51:02 +04:00
|
|
|
grandAncestor->StylePosition()->mWidth.GetUnit() == eStyleUnit_Auto;
|
2007-12-03 12:24:49 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-12-03 12:24:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsImageFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
|
2007-12-03 12:24:49 +03:00
|
|
|
nsIFrame::InlineMinWidthData *aData)
|
|
|
|
{
|
|
|
|
|
|
|
|
NS_ASSERTION(GetParent(), "Must have a parent if we get here!");
|
|
|
|
|
2013-03-25 07:50:59 +04:00
|
|
|
nsIFrame* parent = GetParent();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool canBreak =
|
2007-12-03 12:24:49 +03:00
|
|
|
!CanContinueTextRun() &&
|
2013-03-25 07:50:59 +04:00
|
|
|
parent->StyleText()->WhiteSpaceCanWrap(parent) &&
|
2007-12-03 12:24:49 +03:00
|
|
|
!IsInAutoWidthTableCellForQuirk(this);
|
|
|
|
|
|
|
|
if (canBreak)
|
|
|
|
aData->OptionallyBreak(aRenderingContext);
|
|
|
|
|
|
|
|
aData->trailingWhitespace = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
aData->skipWhitespace = false;
|
2012-07-30 18:20:58 +04:00
|
|
|
aData->trailingTextFrame = nullptr;
|
2007-12-03 12:24:49 +03:00
|
|
|
aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
|
|
|
this, nsLayoutUtils::MIN_WIDTH);
|
2011-10-17 18:59:28 +04:00
|
|
|
aData->atStartOfLine = false;
|
2007-12-03 12:24:49 +03:00
|
|
|
|
|
|
|
if (canBreak)
|
|
|
|
aData->OptionallyBreak(aRenderingContext);
|
|
|
|
|
|
|
|
}
|