LCOV - code coverage report
Current view: directory - layout/generic - nsImageFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 878 0 0.0 %
Date: 2012-06-02 Functions: 95 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : /* rendering object for replaced elements with bitmap image data */
      40                 : 
      41                 : #include "mozilla/Util.h"
      42                 : 
      43                 : #include "nsHTMLParts.h"
      44                 : #include "nsCOMPtr.h"
      45                 : #include "nsImageFrame.h"
      46                 : #include "nsIImageLoadingContent.h"
      47                 : #include "nsString.h"
      48                 : #include "nsPrintfCString.h"
      49                 : #include "nsPresContext.h"
      50                 : #include "nsRenderingContext.h"
      51                 : #include "nsIPresShell.h"
      52                 : #include "nsGkAtoms.h"
      53                 : #include "nsIDocument.h"
      54                 : #include "nsINodeInfo.h"
      55                 : #include "nsContentUtils.h"
      56                 : #include "nsCSSAnonBoxes.h"
      57                 : #include "nsStyleContext.h"
      58                 : #include "nsStyleConsts.h"
      59                 : #include "nsStyleCoord.h"
      60                 : #include "nsTransform2D.h"
      61                 : #include "nsImageMap.h"
      62                 : #include "nsILinkHandler.h"
      63                 : #include "nsIURL.h"
      64                 : #include "nsIIOService.h"
      65                 : #include "nsILoadGroup.h"
      66                 : #include "nsISupportsPriority.h"
      67                 : #include "nsIServiceManager.h"
      68                 : #include "nsNetUtil.h"
      69                 : #include "nsContainerFrame.h"
      70                 : #include "prprf.h"
      71                 : #include "nsCSSRendering.h"
      72                 : #include "nsILink.h"
      73                 : #include "nsIDOMHTMLAnchorElement.h"
      74                 : #include "nsIDOMHTMLImageElement.h"
      75                 : #include "nsINameSpaceManager.h"
      76                 : #include "nsTextFragment.h"
      77                 : #include "nsIDOMHTMLMapElement.h"
      78                 : #include "nsIScriptSecurityManager.h"
      79                 : #ifdef ACCESSIBILITY
      80                 : #include "nsAccessibilityService.h"
      81                 : #endif
      82                 : #include "nsIDOMNode.h"
      83                 : #include "nsGUIEvent.h"
      84                 : #include "nsLayoutUtils.h"
      85                 : #include "nsDisplayList.h"
      86                 : 
      87                 : #include "imgIContainer.h"
      88                 : #include "imgILoader.h"
      89                 : 
      90                 : #include "nsCSSFrameConstructor.h"
      91                 : #include "nsIDOMRange.h"
      92                 : 
      93                 : #include "nsIContentPolicy.h"
      94                 : #include "nsContentPolicyUtils.h"
      95                 : #include "nsEventStates.h"
      96                 : #include "nsLayoutErrors.h"
      97                 : #include "nsBidiUtils.h"
      98                 : #include "nsBidiPresUtils.h"
      99                 : 
     100                 : #include "gfxRect.h"
     101                 : #include "ImageLayers.h"
     102                 : 
     103                 : #include "mozilla/Preferences.h"
     104                 : #include "mozilla/Util.h" // for DebugOnly
     105                 : 
     106                 : using namespace mozilla;
     107                 : 
     108                 : // sizes (pixels) for image icon, padding and border frame
     109                 : #define ICON_SIZE        (16)
     110                 : #define ICON_PADDING     (3)
     111                 : #define ALT_BORDER_WIDTH (1)
     112                 : 
     113                 : 
     114                 : //we must add hooks soon
     115                 : #define IMAGE_EDITOR_CHECK 1
     116                 : 
     117                 : // Default alignment value (so we can tell an unset value from a set value)
     118                 : #define ALIGN_UNSET PRUint8(-1)
     119                 : 
     120                 : using namespace mozilla::layers;
     121                 : using namespace mozilla::dom;
     122                 : 
     123                 : // static icon information
     124                 : nsImageFrame::IconLoad* nsImageFrame::gIconLoad = nsnull;
     125                 : 
     126                 : // cached IO service for loading icons
     127                 : nsIIOService* nsImageFrame::sIOService;
     128                 : 
     129                 : // test if the width and height are fixed, looking at the style data
     130               0 : static bool HaveFixedSize(const nsStylePosition* aStylePosition)
     131                 : {
     132                 :   // check the width and height values in the reflow state's style struct
     133                 :   // - if width and height are specified as either coord or percentage, then
     134                 :   //   the size of the image frame is constrained
     135               0 :   return aStylePosition->mWidth.IsCoordPercentCalcUnit() &&
     136               0 :          aStylePosition->mHeight.IsCoordPercentCalcUnit();
     137                 : }
     138                 : // use the data in the reflow state to decide if the image has a constrained size
     139                 : // (i.e. width and height that are based on the containing block size and not the image size) 
     140                 : // so we can avoid animated GIF related reflows
     141               0 : inline bool HaveFixedSize(const nsHTMLReflowState& aReflowState)
     142                 : { 
     143               0 :   NS_ASSERTION(aReflowState.mStylePosition, "crappy reflowState - null stylePosition");
     144                 :   // when an image has percent css style height or width, but ComputedHeight() 
     145                 :   // or ComputedWidth() of reflow state is  NS_UNCONSTRAINEDSIZE  
     146                 :   // it needs to return false to cause an incremental reflow later
     147                 :   // if an image is inside table like bug 156731 simple testcase III, 
     148                 :   // during pass 1 reflow, ComputedWidth() is NS_UNCONSTRAINEDSIZE
     149                 :   // in pass 2 reflow, ComputedWidth() is 0, it also needs to return false
     150                 :   // see bug 156731
     151               0 :   const nsStyleCoord &height = aReflowState.mStylePosition->mHeight;
     152               0 :   const nsStyleCoord &width = aReflowState.mStylePosition->mWidth;
     153               0 :   return ((height.HasPercent() &&
     154               0 :            NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
     155               0 :           (width.HasPercent() &&
     156               0 :            (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
     157               0 :             0 == aReflowState.ComputedWidth())))
     158                 :           ? false
     159               0 :           : HaveFixedSize(aReflowState.mStylePosition); 
     160                 : }
     161                 : 
     162                 : nsIFrame*
     163               0 : NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     164                 : {
     165               0 :   return new (aPresShell) nsImageFrame(aContext);
     166                 : }
     167                 : 
     168               0 : NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
     169                 : 
     170                 : 
     171               0 : nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
     172                 :   ImageFrameSuper(aContext),
     173                 :   mComputedSize(0, 0),
     174                 :   mIntrinsicRatio(0, 0),
     175               0 :   mDisplayingIcon(false)
     176                 : {
     177                 :   // We assume our size is not constrained and we haven't gotten an
     178                 :   // initial reflow yet, so don't touch those flags.
     179               0 :   mIntrinsicSize.width.SetCoordValue(0);
     180               0 :   mIntrinsicSize.height.SetCoordValue(0);
     181               0 : }
     182                 : 
     183               0 : nsImageFrame::~nsImageFrame()
     184                 : {
     185               0 : }
     186                 : 
     187               0 : NS_QUERYFRAME_HEAD(nsImageFrame)
     188               0 :   NS_QUERYFRAME_ENTRY(nsImageFrame)
     189               0 : NS_QUERYFRAME_TAIL_INHERITING(ImageFrameSuper)
     190                 : 
     191                 : #ifdef ACCESSIBILITY
     192                 : already_AddRefed<nsAccessible>
     193               0 : nsImageFrame::CreateAccessible()
     194                 : {
     195               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
     196               0 :   if (accService) {
     197                 :     return accService->CreateHTMLImageAccessible(mContent,
     198               0 :                                                  PresContext()->PresShell());
     199                 :   }
     200                 : 
     201               0 :   return nsnull;
     202                 : }
     203                 : #endif
     204                 : 
     205                 : void
     206               0 : nsImageFrame::DisconnectMap()
     207                 : {
     208               0 :   if (mImageMap) {
     209               0 :     mImageMap->Destroy();
     210               0 :     NS_RELEASE(mImageMap);
     211                 :   }
     212               0 : }
     213                 : 
     214                 : void
     215               0 : nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
     216                 : {
     217                 :   // Tell our image map, if there is one, to clean up
     218                 :   // This causes the nsImageMap to unregister itself as
     219                 :   // a DOM listener.
     220               0 :   DisconnectMap();
     221                 : 
     222                 :   // set the frame to null so we don't send messages to a dead object.
     223               0 :   if (mListener) {
     224               0 :     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
     225               0 :     if (imageLoader) {
     226                 :       // Push a null JSContext on the stack so that code that runs
     227                 :       // within the below code doesn't think it's being called by
     228                 :       // JS. See bug 604262.
     229               0 :       nsCxPusher pusher;
     230               0 :       pusher.PushNull();
     231                 : 
     232                 :       // Notify our image loading content that we are going away so it can
     233                 :       // deregister with our refresh driver.
     234               0 :       imageLoader->FrameDestroyed(this);
     235                 : 
     236               0 :       imageLoader->RemoveObserver(mListener);
     237                 :     }
     238                 :     
     239               0 :     reinterpret_cast<nsImageListener*>(mListener.get())->SetFrame(nsnull);
     240                 :   }
     241                 :   
     242               0 :   mListener = nsnull;
     243                 : 
     244                 :   // If we were displaying an icon, take ourselves off the list
     245               0 :   if (mDisplayingIcon)
     246               0 :     gIconLoad->RemoveIconObserver(this);
     247                 : 
     248               0 :   nsSplittableFrame::DestroyFrom(aDestructRoot);
     249               0 : }
     250                 : 
     251                 : 
     252                 : 
     253                 : NS_IMETHODIMP
     254               0 : nsImageFrame::Init(nsIContent*      aContent,
     255                 :                    nsIFrame*        aParent,
     256                 :                    nsIFrame*        aPrevInFlow)
     257                 : {
     258               0 :   nsresult rv = nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
     259               0 :   NS_ENSURE_SUCCESS(rv, rv);
     260                 : 
     261               0 :   mListener = new nsImageListener(this);
     262                 : 
     263               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aContent);
     264               0 :   NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED);
     265                 : 
     266                 :   {
     267                 :     // Push a null JSContext on the stack so that code that runs
     268                 :     // within the below code doesn't think it's being called by
     269                 :     // JS. See bug 604262.
     270               0 :     nsCxPusher pusher;
     271               0 :     pusher.PushNull();
     272                 : 
     273               0 :     imageLoader->AddObserver(mListener);
     274                 :   }
     275                 : 
     276               0 :   nsPresContext *aPresContext = PresContext();
     277                 :   
     278               0 :   if (!gIconLoad)
     279               0 :     LoadIcons(aPresContext);
     280                 : 
     281                 :   // We have a PresContext now, so we need to notify the image content node
     282                 :   // that it can register images.
     283               0 :   imageLoader->FrameCreated(this);
     284                 : 
     285                 :   // Give image loads associated with an image frame a small priority boost!
     286               0 :   nsCOMPtr<imgIRequest> currentRequest;
     287               0 :   imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
     288               0 :                           getter_AddRefs(currentRequest));
     289               0 :   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(currentRequest);
     290               0 :   if (p)
     291               0 :     p->AdjustPriority(-1);
     292                 : 
     293                 :   // If we already have an image container, OnStartContainer won't be called
     294                 :   // Set the animation mode here
     295               0 :   if (currentRequest) {
     296               0 :     nsCOMPtr<imgIContainer> image;
     297               0 :     currentRequest->GetImage(getter_AddRefs(image));
     298               0 :     if (image) {
     299               0 :       image->SetAnimationMode(aPresContext->ImageAnimationMode());
     300                 :     }
     301                 :   }
     302                 : 
     303               0 :   return rv;
     304                 : }
     305                 : 
     306                 : bool
     307               0 : nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage)
     308                 : {
     309               0 :   NS_PRECONDITION(aImage, "null image");
     310               0 :   if (!aImage)
     311               0 :     return false;
     312                 : 
     313               0 :   nsIFrame::IntrinsicSize oldIntrinsicSize = mIntrinsicSize;
     314                 : 
     315               0 :   nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
     316               0 :   if (rootFrame) {
     317                 :     // Set intrinsic size to match that of aImage's rootFrame.
     318               0 :     mIntrinsicSize = rootFrame->GetIntrinsicSize();
     319                 :   } else {
     320                 :     // Set intrinsic size to match aImage's reported width & height.
     321               0 :     nsIntSize imageSizeInPx;
     322               0 :     if (NS_FAILED(aImage->GetWidth(&imageSizeInPx.width)) ||
     323               0 :         NS_FAILED(aImage->GetHeight(&imageSizeInPx.height))) {
     324               0 :       imageSizeInPx.SizeTo(0, 0);
     325                 :     }
     326                 :     mIntrinsicSize.width.SetCoordValue(
     327               0 :       nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.width));
     328                 :     mIntrinsicSize.height.SetCoordValue(
     329               0 :       nsPresContext::CSSPixelsToAppUnits(imageSizeInPx.height));
     330                 :   }
     331                 : 
     332               0 :   return mIntrinsicSize != oldIntrinsicSize;
     333                 : }
     334                 : 
     335                 : bool
     336               0 : nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage)
     337                 : {
     338               0 :   NS_PRECONDITION(aImage, "null image");
     339                 : 
     340               0 :   if (!aImage)
     341               0 :     return false;
     342                 : 
     343               0 :   nsSize oldIntrinsicRatio = mIntrinsicRatio;
     344                 : 
     345               0 :   nsIFrame* rootFrame = aImage->GetRootLayoutFrame();
     346               0 :   if (rootFrame) {
     347                 :     // Set intrinsic ratio to match that of aImage's rootFrame.
     348               0 :     mIntrinsicRatio = rootFrame->GetIntrinsicRatio();
     349                 :   } else {
     350               0 :     NS_ABORT_IF_FALSE(mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
     351                 :                       mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord,
     352                 :                       "since aImage doesn't have a rootFrame, our intrinsic "
     353                 :                       "dimensions must have coord units (not percent units)");
     354               0 :     mIntrinsicRatio.width = mIntrinsicSize.width.GetCoordValue();
     355               0 :     mIntrinsicRatio.height = mIntrinsicSize.height.GetCoordValue();
     356                 :   }
     357                 : 
     358               0 :   return mIntrinsicRatio != oldIntrinsicRatio;
     359                 : }
     360                 : 
     361                 : bool
     362               0 : nsImageFrame::GetSourceToDestTransform(nsTransform2D& aTransform)
     363                 : {
     364                 :   // Set the translation components.
     365                 :   // XXXbz does this introduce rounding errors because of the cast to
     366                 :   // float?  Should we just manually add that stuff in every time
     367                 :   // instead?
     368               0 :   nsRect innerArea = GetInnerArea();
     369                 :   aTransform.SetToTranslate(float(innerArea.x),
     370               0 :                             float(innerArea.y - GetContinuationOffset()));
     371                 : 
     372                 :   // Set the scale factors.
     373               0 :   if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
     374               0 :       mIntrinsicSize.width.GetCoordValue() != 0 &&
     375               0 :       mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
     376               0 :       mIntrinsicSize.height.GetCoordValue() != 0 &&
     377               0 :       mIntrinsicSize.width.GetCoordValue() != mComputedSize.width &&
     378               0 :       mIntrinsicSize.height.GetCoordValue() != mComputedSize.height) {
     379                 : 
     380                 :     aTransform.SetScale(float(mComputedSize.width)  /
     381               0 :                         float(mIntrinsicSize.width.GetCoordValue()),
     382                 :                         float(mComputedSize.height) /
     383               0 :                         float(mIntrinsicSize.height.GetCoordValue()));
     384               0 :     return true;
     385                 :   }
     386                 : 
     387               0 :   return false;
     388                 : }
     389                 : 
     390                 : /*
     391                 :  * These two functions basically do the same check.  The first one
     392                 :  * checks that the given request is the current request for our
     393                 :  * mContent.  The second checks that the given image container the
     394                 :  * same as the image container on the current request for our
     395                 :  * mContent.
     396                 :  */
     397                 : bool
     398               0 : nsImageFrame::IsPendingLoad(imgIRequest* aRequest) const
     399                 : {
     400                 :   // Default to pending load in case of errors
     401               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
     402               0 :   NS_ASSERTION(imageLoader, "No image loading content?");
     403                 : 
     404               0 :   PRInt32 requestType = nsIImageLoadingContent::UNKNOWN_REQUEST;
     405               0 :   imageLoader->GetRequestType(aRequest, &requestType);
     406                 : 
     407               0 :   return requestType != nsIImageLoadingContent::CURRENT_REQUEST;
     408                 : }
     409                 : 
     410                 : bool
     411               0 : nsImageFrame::IsPendingLoad(imgIContainer* aContainer) const
     412                 : {
     413                 :   //  default to pending load in case of errors
     414               0 :   if (!aContainer) {
     415               0 :     NS_ERROR("No image container!");
     416               0 :     return true;
     417                 :   }
     418                 : 
     419               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
     420               0 :   NS_ASSERTION(imageLoader, "No image loading content?");
     421                 :   
     422               0 :   nsCOMPtr<imgIRequest> currentRequest;
     423               0 :   imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
     424               0 :                           getter_AddRefs(currentRequest));
     425               0 :   if (!currentRequest) {
     426               0 :     NS_ERROR("No current request");
     427               0 :     return true;
     428                 :   }
     429                 : 
     430               0 :   nsCOMPtr<imgIContainer> currentContainer;
     431               0 :   currentRequest->GetImage(getter_AddRefs(currentContainer));
     432                 : 
     433               0 :   return currentContainer != aContainer;
     434                 :   
     435                 : }
     436                 : 
     437                 : nsRect
     438               0 : nsImageFrame::SourceRectToDest(const nsIntRect& aRect)
     439                 : {
     440                 :   // When scaling the image, row N of the source image may (depending on
     441                 :   // the scaling function) be used to draw any row in the destination image
     442                 :   // between floor(F * (N-1)) and ceil(F * (N+1)), where F is the
     443                 :   // floating-point scaling factor.  The same holds true for columns.
     444                 :   // So, we start by computing that bound without the floor and ceiling.
     445                 : 
     446                 :   nsRect r(nsPresContext::CSSPixelsToAppUnits(aRect.x - 1),
     447                 :            nsPresContext::CSSPixelsToAppUnits(aRect.y - 1),
     448                 :            nsPresContext::CSSPixelsToAppUnits(aRect.width + 2),
     449               0 :            nsPresContext::CSSPixelsToAppUnits(aRect.height + 2));
     450                 : 
     451               0 :   nsTransform2D sourceToDest;
     452               0 :   if (!GetSourceToDestTransform(sourceToDest)) {
     453                 :     // Failed to generate transform matrix. Return our whole inner area,
     454                 :     // to be on the safe side (since this method is used for generating
     455                 :     // invalidation rects).
     456               0 :     return GetInnerArea();
     457                 :   }
     458                 : 
     459               0 :   sourceToDest.TransformCoord(&r.x, &r.y, &r.width, &r.height);
     460                 : 
     461                 :   // Now, round the edges out to the pixel boundary.
     462               0 :   nscoord scale = nsPresContext::CSSPixelsToAppUnits(1);
     463               0 :   nscoord right = r.x + r.width;
     464               0 :   nscoord bottom = r.y + r.height;
     465                 : 
     466               0 :   r.x -= (scale + (r.x % scale)) % scale;
     467               0 :   r.y -= (scale + (r.y % scale)) % scale;
     468               0 :   r.width = right + ((scale - (right % scale)) % scale) - r.x;
     469               0 :   r.height = bottom + ((scale - (bottom % scale)) % scale) - r.y;
     470                 : 
     471               0 :   return r;
     472                 : }
     473                 : 
     474                 : // Note that we treat NS_EVENT_STATE_SUPPRESSED images as "OK".  This means
     475                 : // that we'll construct image frames for them as needed if their display is
     476                 : // toggled from "none" (though we won't paint them, unless their visibility
     477                 : // is changed too).
     478                 : #define BAD_STATES (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | \
     479                 :                     NS_EVENT_STATE_LOADING)
     480                 : 
     481                 : // This is a macro so that we don't evaluate the boolean last arg
     482                 : // unless we have to; it can be expensive
     483                 : #define IMAGE_OK(_state, _loadingOK)                                           \
     484                 :    (!(_state).HasAtLeastOneOfStates(BAD_STATES) ||                                    \
     485                 :     (!(_state).HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED) && \
     486                 :      (_state).HasState(NS_EVENT_STATE_LOADING) && (_loadingOK)))
     487                 : 
     488                 : /* static */
     489                 : bool
     490               0 : nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
     491                 :                                         nsStyleContext* aStyleContext)
     492                 : {
     493               0 :   nsEventStates state = aElement->State();
     494               0 :   if (IMAGE_OK(state,
     495                 :                HaveFixedSize(aStyleContext->GetStylePosition()))) {
     496                 :     // Image is fine; do the image frame thing
     497               0 :     return true;
     498                 :   }
     499                 : 
     500                 :   // Check if we want to use a placeholder box with an icon or just
     501                 :   // let the presShell make us into inline text.  Decide as follows:
     502                 :   //
     503                 :   //  - if our special "force icons" style is set, show an icon
     504                 :   //  - else if our "do not show placeholders" pref is set, skip the icon
     505                 :   //  - else:
     506                 :   //  - if QuirksMode, and there is no alt attribute, and this is not an
     507                 :   //    <object> (which could not possibly have such an attribute), show an
     508                 :   //    icon.
     509                 :   //  - if QuirksMode, and the IMG has a size show an icon.
     510                 :   //  - otherwise, skip the icon
     511                 :   bool useSizedBox;
     512                 :   
     513               0 :   if (aStyleContext->GetStyleUIReset()->mForceBrokenImageIcon) {
     514               0 :     useSizedBox = true;
     515                 :   }
     516               0 :   else if (gIconLoad && gIconLoad->mPrefForceInlineAltText) {
     517               0 :     useSizedBox = false;
     518                 :   }
     519                 :   else {
     520               0 :     if (aStyleContext->PresContext()->CompatibilityMode() !=
     521                 :         eCompatibility_NavQuirks) {
     522               0 :       useSizedBox = false;
     523                 :     }
     524                 :     else {
     525                 :       // We are in quirks mode, so we can just check the tag name; no need to
     526                 :       // check the namespace.
     527               0 :       nsIAtom *localName = aElement->Tag();
     528                 : 
     529                 :       // Use a sized box if we have no alt text.  This means no alt attribute
     530                 :       // and the node is not an object or an input (since those always have alt
     531                 :       // text).
     532               0 :       if (!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::alt) &&
     533                 :           localName != nsGkAtoms::object &&
     534                 :           localName != nsGkAtoms::input) {
     535               0 :         useSizedBox = true;
     536                 :       }
     537                 :       else {
     538                 :         // check whether we have fixed size
     539               0 :         useSizedBox = HaveFixedSize(aStyleContext->GetStylePosition());
     540                 :       }
     541                 :     }
     542                 :   }
     543                 :   
     544               0 :   return useSizedBox;
     545                 : }
     546                 : 
     547                 : nsresult
     548               0 : nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
     549                 : {
     550               0 :   if (!aImage) return NS_ERROR_INVALID_ARG;
     551                 : 
     552                 :   /* Get requested animation policy from the pres context:
     553                 :    *   normal = 0
     554                 :    *   one frame = 1
     555                 :    *   one loop = 2
     556                 :    */
     557               0 :   nsPresContext *presContext = PresContext();
     558               0 :   aImage->SetAnimationMode(presContext->ImageAnimationMode());
     559                 : 
     560               0 :   if (IsPendingLoad(aRequest)) {
     561                 :     // We don't care
     562               0 :     return NS_OK;
     563                 :   }
     564                 :   
     565               0 :   bool intrinsicSizeChanged = UpdateIntrinsicSize(aImage);
     566               0 :   intrinsicSizeChanged = UpdateIntrinsicRatio(aImage) || intrinsicSizeChanged;
     567                 : 
     568               0 :   if (intrinsicSizeChanged && (mState & IMAGE_GOTINITIALREFLOW)) {
     569                 :     // Now we need to reflow if we have an unconstrained size and have
     570                 :     // already gotten the initial reflow
     571               0 :     if (!(mState & IMAGE_SIZECONSTRAINED)) { 
     572               0 :       nsIPresShell *presShell = presContext->GetPresShell();
     573               0 :       NS_ASSERTION(presShell, "No PresShell.");
     574               0 :       if (presShell) { 
     575                 :         presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
     576               0 :                                     NS_FRAME_IS_DIRTY);
     577                 :       }
     578                 :     }
     579                 :   }
     580                 : 
     581               0 :   return NS_OK;
     582                 : }
     583                 : 
     584                 : nsresult
     585               0 : nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
     586                 :                               bool aCurrentFrame,
     587                 :                               const nsIntRect *aRect)
     588                 : {
     589                 :   // XXX do we need to make sure that the reflow from the
     590                 :   // OnStartContainer has been processed before we start calling
     591                 :   // invalidate?
     592                 : 
     593               0 :   NS_ENSURE_ARG_POINTER(aRect);
     594                 : 
     595               0 :   if (!(mState & IMAGE_GOTINITIALREFLOW)) {
     596                 :     // Don't bother to do anything; we have a reflow coming up!
     597               0 :     return NS_OK;
     598                 :   }
     599                 :   
     600               0 :   if (IsPendingLoad(aRequest)) {
     601                 :     // We don't care
     602               0 :     return NS_OK;
     603                 :   }
     604                 : 
     605                 :   // Don't invalidate if the current visible frame isn't the one the data is
     606                 :   // from
     607               0 :   if (!aCurrentFrame)
     608               0 :     return NS_OK;
     609                 : 
     610                 :   // XXX We really need to round this out, now that we're doing better
     611                 :   // image scaling!
     612               0 :   nsRect r = aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
     613                 :     GetInnerArea() :
     614               0 :     SourceRectToDest(*aRect);
     615                 : 
     616                 : #ifdef DEBUG_decode
     617                 :   printf("Source rect (%d,%d,%d,%d) -> invalidate dest rect (%d,%d,%d,%d)\n",
     618                 :          aRect->x, aRect->y, aRect->width, aRect->height,
     619                 :          r.x, r.y, r.width, r.height);
     620                 : #endif
     621                 : 
     622               0 :   Invalidate(r);
     623                 :   
     624               0 :   return NS_OK;
     625                 : }
     626                 : 
     627                 : nsresult
     628               0 : nsImageFrame::OnStopDecode(imgIRequest *aRequest,
     629                 :                            nsresult aStatus,
     630                 :                            const PRUnichar *aStatusArg)
     631                 : {
     632               0 :   nsPresContext *presContext = PresContext();
     633               0 :   nsIPresShell *presShell = presContext->GetPresShell();
     634               0 :   NS_ASSERTION(presShell, "No PresShell.");
     635                 : 
     636                 :   // Check what request type we're dealing with
     637               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
     638               0 :   NS_ASSERTION(imageLoader, "Who's notifying us??");
     639               0 :   PRInt32 loadType = nsIImageLoadingContent::UNKNOWN_REQUEST;
     640               0 :   imageLoader->GetRequestType(aRequest, &loadType);
     641               0 :   if (loadType != nsIImageLoadingContent::CURRENT_REQUEST &&
     642                 :       loadType != nsIImageLoadingContent::PENDING_REQUEST) {
     643               0 :     return NS_ERROR_FAILURE;
     644                 :   }
     645                 : 
     646               0 :   if (loadType == nsIImageLoadingContent::PENDING_REQUEST) {
     647                 :     // May have to switch sizes here!
     648               0 :     bool intrinsicSizeChanged = true;
     649               0 :     if (NS_SUCCEEDED(aStatus)) {
     650               0 :       nsCOMPtr<imgIContainer> imageContainer;
     651               0 :       aRequest->GetImage(getter_AddRefs(imageContainer));
     652               0 :       NS_ASSERTION(imageContainer, "Successful load with no container?");
     653               0 :       intrinsicSizeChanged = UpdateIntrinsicSize(imageContainer);
     654               0 :       intrinsicSizeChanged = UpdateIntrinsicRatio(imageContainer) ||
     655               0 :         intrinsicSizeChanged;
     656                 :     }
     657                 :     else {
     658                 :       // Have to size to 0,0 so that GetDesiredSize recalculates the size
     659               0 :       mIntrinsicSize.width.SetCoordValue(0);
     660               0 :       mIntrinsicSize.height.SetCoordValue(0);
     661               0 :       mIntrinsicRatio.SizeTo(0, 0);
     662                 :     }
     663                 : 
     664               0 :     if (mState & IMAGE_GOTINITIALREFLOW) { // do nothing if we haven't gotten the initial reflow yet
     665               0 :       if (!(mState & IMAGE_SIZECONSTRAINED) && intrinsicSizeChanged) {
     666               0 :         if (presShell) { 
     667                 :           presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
     668               0 :                                       NS_FRAME_IS_DIRTY);
     669                 :         }
     670                 :       } else {
     671               0 :         nsSize s = GetSize();
     672               0 :         nsRect r(0, 0, s.width, s.height);
     673                 :         // Update border+content to account for image change
     674               0 :         Invalidate(r);
     675                 :       }
     676                 :     }
     677                 :   }
     678                 : 
     679               0 :   return NS_OK;
     680                 : }
     681                 : 
     682                 : nsresult
     683               0 : nsImageFrame::FrameChanged(imgIRequest *aRequest,
     684                 :                            imgIContainer *aContainer,
     685                 :                            const nsIntRect *aDirtyRect)
     686                 : {
     687               0 :   if (!GetStyleVisibility()->IsVisible()) {
     688               0 :     return NS_OK;
     689                 :   }
     690                 : 
     691               0 :   if (IsPendingLoad(aContainer)) {
     692                 :     // We don't care about it
     693               0 :     return NS_OK;
     694                 :   }
     695                 : 
     696               0 :   nsRect r = aDirtyRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
     697                 :     GetInnerArea() :
     698               0 :     SourceRectToDest(*aDirtyRect);
     699                 : 
     700                 :   // Update border+content to account for image change
     701               0 :   Invalidate(r);
     702               0 :   return NS_OK;
     703                 : }
     704                 : 
     705                 : void
     706               0 : nsImageFrame::EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext)
     707                 : {
     708                 :   // if mIntrinsicSize.width and height are 0, then we should
     709                 :   // check to see if the size is already known by the image container.
     710               0 :   if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
     711               0 :       mIntrinsicSize.width.GetCoordValue() == 0 &&
     712               0 :       mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
     713               0 :       mIntrinsicSize.height.GetCoordValue() == 0) {
     714                 : 
     715                 :     // Jump through all the hoops to get the status of the request
     716               0 :     nsCOMPtr<imgIRequest> currentRequest;
     717               0 :     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
     718               0 :     if (imageLoader)
     719               0 :       imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
     720               0 :                               getter_AddRefs(currentRequest));
     721               0 :     PRUint32 status = 0;
     722               0 :     if (currentRequest)
     723               0 :       currentRequest->GetImageStatus(&status);
     724                 : 
     725                 :     // If we know the size, we can grab it and use it for an update
     726               0 :     if (status & imgIRequest::STATUS_SIZE_AVAILABLE) {
     727               0 :       nsCOMPtr<imgIContainer> imgCon;
     728               0 :       currentRequest->GetImage(getter_AddRefs(imgCon));
     729               0 :       NS_ABORT_IF_FALSE(imgCon, "SIZE_AVAILABLE, but no imgContainer?");
     730               0 :       UpdateIntrinsicSize(imgCon);
     731               0 :       UpdateIntrinsicRatio(imgCon);
     732                 :     } else {
     733                 :       // image request is null or image size not known, probably an
     734                 :       // invalid image specified
     735                 :       // - make the image big enough for the icon (it may not be
     736                 :       // used if inline alt expansion is used instead)
     737                 :       // XXX: we need this in composer, but it is also good for
     738                 :       // XXX: general quirks mode to always have room for the icon
     739               0 :       if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
     740                 :         nscoord edgeLengthToUse =
     741                 :           nsPresContext::CSSPixelsToAppUnits(
     742               0 :             ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
     743               0 :         mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
     744               0 :         mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
     745               0 :         mIntrinsicRatio.SizeTo(1, 1);
     746                 :       }
     747                 :     }
     748                 :   }
     749               0 : }
     750                 : 
     751                 : /* virtual */ nsSize
     752               0 : nsImageFrame::ComputeSize(nsRenderingContext *aRenderingContext,
     753                 :                           nsSize aCBSize, nscoord aAvailableWidth,
     754                 :                           nsSize aMargin, nsSize aBorder, nsSize aPadding,
     755                 :                           bool aShrinkWrap)
     756                 : {
     757               0 :   nsPresContext *presContext = PresContext();
     758               0 :   EnsureIntrinsicSizeAndRatio(presContext);
     759                 : 
     760                 :   return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
     761                 :                             aRenderingContext, this,
     762                 :                             mIntrinsicSize, mIntrinsicRatio, aCBSize,
     763               0 :                             aMargin, aBorder, aPadding);
     764                 : }
     765                 : 
     766                 : nsRect 
     767               0 : nsImageFrame::GetInnerArea() const
     768                 : {
     769               0 :   return GetContentRect() - GetPosition();
     770                 : }
     771                 : 
     772                 : // get the offset into the content area of the image where aImg starts if it is a continuation.
     773                 : nscoord 
     774               0 : nsImageFrame::GetContinuationOffset() const
     775                 : {
     776               0 :   nscoord offset = 0;
     777               0 :   for (nsIFrame *f = GetPrevInFlow(); f; f = f->GetPrevInFlow()) {
     778               0 :     offset += f->GetContentRect().height;
     779                 :   }
     780               0 :   NS_ASSERTION(offset >= 0, "bogus GetContentRect");
     781               0 :   return offset;
     782                 : }
     783                 : 
     784                 : /* virtual */ nscoord
     785               0 : nsImageFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     786                 : {
     787                 :   // XXX The caller doesn't account for constraints of the height,
     788                 :   // min-height, and max-height properties.
     789               0 :   DebugOnly<nscoord> result;
     790               0 :   DISPLAY_MIN_WIDTH(this, result);
     791               0 :   nsPresContext *presContext = PresContext();
     792               0 :   EnsureIntrinsicSizeAndRatio(presContext);
     793               0 :   return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
     794               0 :     mIntrinsicSize.width.GetCoordValue() : 0;
     795                 : }
     796                 : 
     797                 : /* virtual */ nscoord
     798               0 : nsImageFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     799                 : {
     800                 :   // XXX The caller doesn't account for constraints of the height,
     801                 :   // min-height, and max-height properties.
     802               0 :   DebugOnly<nscoord> result;
     803               0 :   DISPLAY_PREF_WIDTH(this, result);
     804               0 :   nsPresContext *presContext = PresContext();
     805               0 :   EnsureIntrinsicSizeAndRatio(presContext);
     806                 :   // convert from normal twips to scaled twips (printing...)
     807               0 :   return mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord ?
     808               0 :     mIntrinsicSize.width.GetCoordValue() : 0;
     809                 : }
     810                 : 
     811                 : /* virtual */ nsIFrame::IntrinsicSize
     812               0 : nsImageFrame::GetIntrinsicSize()
     813                 : {
     814               0 :   return mIntrinsicSize;
     815                 : }
     816                 : 
     817                 : /* virtual */ nsSize
     818               0 : nsImageFrame::GetIntrinsicRatio()
     819                 : {
     820               0 :   return mIntrinsicRatio;
     821                 : }
     822                 : 
     823                 : NS_IMETHODIMP
     824               0 : nsImageFrame::Reflow(nsPresContext*          aPresContext,
     825                 :                      nsHTMLReflowMetrics&     aMetrics,
     826                 :                      const nsHTMLReflowState& aReflowState,
     827                 :                      nsReflowStatus&          aStatus)
     828                 : {
     829               0 :   DO_GLOBAL_REFLOW_COUNT("nsImageFrame");
     830               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
     831               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     832                 :                   ("enter nsImageFrame::Reflow: availSize=%d,%d",
     833                 :                   aReflowState.availableWidth, aReflowState.availableHeight));
     834                 : 
     835               0 :   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
     836                 : 
     837               0 :   aStatus = NS_FRAME_COMPLETE;
     838                 : 
     839                 :   // see if we have a frozen size (i.e. a fixed width and height)
     840               0 :   if (HaveFixedSize(aReflowState)) {
     841               0 :     mState |= IMAGE_SIZECONSTRAINED;
     842                 :   } else {
     843               0 :     mState &= ~IMAGE_SIZECONSTRAINED;
     844                 :   }
     845                 : 
     846                 :   // XXXldb These two bits are almost exact opposites (except in the
     847                 :   // middle of the initial reflow); remove IMAGE_GOTINITIALREFLOW.
     848               0 :   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     849               0 :     mState |= IMAGE_GOTINITIALREFLOW;
     850                 :   }
     851                 : 
     852                 :   mComputedSize = 
     853               0 :     nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
     854                 : 
     855               0 :   aMetrics.width = mComputedSize.width;
     856               0 :   aMetrics.height = mComputedSize.height;
     857                 : 
     858                 :   // add borders and padding
     859               0 :   aMetrics.width  += aReflowState.mComputedBorderPadding.LeftRight();
     860               0 :   aMetrics.height += aReflowState.mComputedBorderPadding.TopBottom();
     861                 :   
     862               0 :   if (GetPrevInFlow()) {
     863               0 :     aMetrics.width = GetPrevInFlow()->GetSize().width;
     864               0 :     nscoord y = GetContinuationOffset();
     865               0 :     aMetrics.height -= y + aReflowState.mComputedBorderPadding.top;
     866               0 :     aMetrics.height = NS_MAX(0, aMetrics.height);
     867                 :   }
     868                 : 
     869                 : 
     870                 :   // we have to split images if we are:
     871                 :   //  in Paginated mode, we need to have a constrained height, and have a height larger than our available height
     872               0 :   PRUint32 loadStatus = imgIRequest::STATUS_NONE;
     873               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
     874               0 :   NS_ASSERTION(imageLoader, "No content node??");
     875               0 :   if (imageLoader) {
     876               0 :     nsCOMPtr<imgIRequest> currentRequest;
     877               0 :     imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
     878               0 :                             getter_AddRefs(currentRequest));
     879               0 :     if (currentRequest) {
     880               0 :       currentRequest->GetImageStatus(&loadStatus);
     881                 :     }
     882                 :   }
     883               0 :   if (aPresContext->IsPaginated() &&
     884                 :       ((loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (mState & IMAGE_SIZECONSTRAINED)) &&
     885                 :       NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight && 
     886                 :       aMetrics.height > aReflowState.availableHeight) { 
     887                 :     // our desired height was greater than 0, so to avoid infinite
     888                 :     // splitting, use 1 pixel as the min
     889               0 :     aMetrics.height = NS_MAX(nsPresContext::CSSPixelsToAppUnits(1), aReflowState.availableHeight);
     890               0 :     aStatus = NS_FRAME_NOT_COMPLETE;
     891                 :   }
     892                 : 
     893               0 :   aMetrics.SetOverflowAreasToDesiredBounds();
     894               0 :   FinishAndStoreOverflow(&aMetrics);
     895                 : 
     896                 :   // Now that that's all done, check whether we're resizing... if we are,
     897                 :   // invalidate our rect.
     898                 :   // XXXbz we really only want to do this when reflow is completely done, but
     899                 :   // we have no way to detect when mRect changes (since SetRect is non-virtual,
     900                 :   // so this is the best we can do).
     901               0 :   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
     902               0 :     Invalidate(nsRect(0, 0, mRect.width, mRect.height));
     903                 :   }
     904                 : 
     905               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     906                 :                   ("exit nsImageFrame::Reflow: size=%d,%d",
     907                 :                   aMetrics.width, aMetrics.height));
     908               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
     909               0 :   return NS_OK;
     910                 : }
     911                 : 
     912                 : // Computes the width of the specified string. aMaxWidth specifies the maximum
     913                 : // width available. Once this limit is reached no more characters are measured.
     914                 : // The number of characters that fit within the maximum width are returned in
     915                 : // aMaxFit. NOTE: it is assumed that the fontmetrics have already been selected
     916                 : // into the rendering context before this is called (for performance). MMP
     917                 : nscoord
     918               0 : nsImageFrame::MeasureString(const PRUnichar*     aString,
     919                 :                             PRInt32              aLength,
     920                 :                             nscoord              aMaxWidth,
     921                 :                             PRUint32&            aMaxFit,
     922                 :                             nsRenderingContext& aContext)
     923                 : {
     924               0 :   nscoord totalWidth = 0;
     925               0 :   aContext.SetTextRunRTL(false);
     926               0 :   nscoord spaceWidth = aContext.GetWidth(' ');
     927                 : 
     928               0 :   aMaxFit = 0;
     929               0 :   while (aLength > 0) {
     930                 :     // Find the next place we can line break
     931               0 :     PRUint32  len = aLength;
     932               0 :     bool      trailingSpace = false;
     933               0 :     for (PRInt32 i = 0; i < aLength; i++) {
     934               0 :       if (XP_IS_SPACE(aString[i]) && (i > 0)) {
     935               0 :         len = i;  // don't include the space when measuring
     936               0 :         trailingSpace = true;
     937               0 :         break;
     938                 :       }
     939                 :     }
     940                 :   
     941                 :     // Measure this chunk of text, and see if it fits
     942                 :     nscoord width =
     943               0 :       nsLayoutUtils::GetStringWidth(this, &aContext, aString, len);
     944               0 :     bool    fits = (totalWidth + width) <= aMaxWidth;
     945                 : 
     946                 :     // If it fits on the line, or it's the first word we've processed then
     947                 :     // include it
     948               0 :     if (fits || (0 == totalWidth)) {
     949                 :       // New piece fits
     950               0 :       totalWidth += width;
     951                 : 
     952                 :       // If there's a trailing space then see if it fits as well
     953               0 :       if (trailingSpace) {
     954               0 :         if ((totalWidth + spaceWidth) <= aMaxWidth) {
     955               0 :           totalWidth += spaceWidth;
     956                 :         } else {
     957                 :           // Space won't fit. Leave it at the end but don't include it in
     958                 :           // the width
     959               0 :           fits = false;
     960                 :         }
     961                 : 
     962               0 :         len++;
     963                 :       }
     964                 : 
     965               0 :       aMaxFit += len;
     966               0 :       aString += len;
     967               0 :       aLength -= len;
     968                 :     }
     969                 : 
     970               0 :     if (!fits) {
     971               0 :       break;
     972                 :     }
     973                 :   }
     974               0 :   return totalWidth;
     975                 : }
     976                 : 
     977                 : // Formats the alt-text to fit within the specified rectangle. Breaks lines
     978                 : // between words if a word would extend past the edge of the rectangle
     979                 : void
     980               0 : nsImageFrame::DisplayAltText(nsPresContext*      aPresContext,
     981                 :                              nsRenderingContext& aRenderingContext,
     982                 :                              const nsString&      aAltText,
     983                 :                              const nsRect&        aRect)
     984                 : {
     985                 :   // Set font and color
     986               0 :   aRenderingContext.SetColor(GetStyleColor()->mColor);
     987               0 :   nsRefPtr<nsFontMetrics> fm;
     988                 :   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
     989               0 :     nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eNotInReflow));
     990               0 :   aRenderingContext.SetFont(fm);
     991                 : 
     992                 :   // Format the text to display within the formatting rect
     993                 : 
     994               0 :   nscoord maxAscent = fm->MaxAscent();
     995               0 :   nscoord maxDescent = fm->MaxDescent();
     996               0 :   nscoord height = fm->MaxHeight();
     997                 : 
     998                 :   // XXX It would be nice if there was a way to have the font metrics tell
     999                 :   // use where to break the text given a maximum width. At a minimum we need
    1000                 :   // to be able to get the break character...
    1001               0 :   const PRUnichar* str = aAltText.get();
    1002               0 :   PRInt32          strLen = aAltText.Length();
    1003               0 :   nscoord          y = aRect.y;
    1004                 : 
    1005               0 :   if (!aPresContext->BidiEnabled() && HasRTLChars(aAltText)) {
    1006               0 :     aPresContext->SetBidiEnabled();
    1007                 :   }
    1008                 : 
    1009                 :   // Always show the first line, even if we have to clip it below
    1010               0 :   bool firstLine = true;
    1011               0 :   while ((strLen > 0) && (firstLine || (y + maxDescent) < aRect.YMost())) {
    1012                 :     // Determine how much of the text to display on this line
    1013                 :     PRUint32  maxFit;  // number of characters that fit
    1014                 :     nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
    1015               0 :                                      aRenderingContext);
    1016                 :     
    1017                 :     // Display the text
    1018               0 :     nsresult rv = NS_ERROR_FAILURE;
    1019                 : 
    1020               0 :     if (aPresContext->BidiEnabled()) {
    1021               0 :       const nsStyleVisibility* vis = GetStyleVisibility();
    1022               0 :       if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
    1023                 :         rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
    1024                 :                                          aPresContext, aRenderingContext,
    1025                 :                                          aRenderingContext,
    1026               0 :                                          aRect.XMost() - strWidth, y + maxAscent);
    1027                 :       else
    1028                 :         rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
    1029                 :                                          aPresContext, aRenderingContext,
    1030                 :                                          aRenderingContext,
    1031               0 :                                          aRect.x, y + maxAscent);
    1032                 :     }
    1033               0 :     if (NS_FAILED(rv))
    1034               0 :       aRenderingContext.DrawString(str, maxFit, aRect.x, y + maxAscent);
    1035                 : 
    1036                 :     // Move to the next line
    1037               0 :     str += maxFit;
    1038               0 :     strLen -= maxFit;
    1039               0 :     y += height;
    1040               0 :     firstLine = false;
    1041                 :   }
    1042               0 : }
    1043                 : 
    1044               0 : struct nsRecessedBorder : public nsStyleBorder {
    1045               0 :   nsRecessedBorder(nscoord aBorderWidth, nsPresContext* aPresContext)
    1046               0 :     : nsStyleBorder(aPresContext)
    1047                 :   {
    1048               0 :     NS_FOR_CSS_SIDES(side) {
    1049                 :       // Note: use SetBorderColor here because we want to make sure
    1050                 :       // the "special" flags are unset.
    1051               0 :       SetBorderColor(side, NS_RGB(0, 0, 0));
    1052               0 :       mBorder.Side(side) = aBorderWidth;
    1053                 :       // Note: use SetBorderStyle here because we want to affect
    1054                 :       // mComputedBorder
    1055               0 :       SetBorderStyle(side, NS_STYLE_BORDER_STYLE_INSET);
    1056                 :     }
    1057               0 :   }
    1058                 : };
    1059                 : 
    1060                 : void
    1061               0 : nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
    1062                 :                                  const nsRect&        aDirtyRect,
    1063                 :                                  imgIRequest*         aRequest,
    1064                 :                                  nsPoint              aPt)
    1065                 : {
    1066                 :   // We should definitely have a gIconLoad here.
    1067               0 :   NS_ABORT_IF_FALSE(gIconLoad, "How did we succeed in Init then?");
    1068                 : 
    1069                 :   // Calculate the inner area
    1070               0 :   nsRect  inner = GetInnerArea() + aPt;
    1071                 : 
    1072                 :   // Display a recessed one pixel border
    1073               0 :   nscoord borderEdgeWidth = nsPresContext::CSSPixelsToAppUnits(ALT_BORDER_WIDTH);
    1074                 : 
    1075                 :   // if inner area is empty, then make it big enough for at least the icon
    1076               0 :   if (inner.IsEmpty()){
    1077               0 :     inner.SizeTo(2*(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH)),
    1078               0 :                  2*(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH)));
    1079                 :   }
    1080                 : 
    1081                 :   // Make sure we have enough room to actually render the border within
    1082                 :   // our frame bounds
    1083               0 :   if ((inner.width < 2 * borderEdgeWidth) || (inner.height < 2 * borderEdgeWidth)) {
    1084                 :     return;
    1085                 :   }
    1086                 : 
    1087                 :   // Paint the border
    1088               0 :   nsRecessedBorder recessedBorder(borderEdgeWidth, PresContext());
    1089                 :   nsCSSRendering::PaintBorderWithStyleBorder(PresContext(), aRenderingContext,
    1090                 :                                              this, inner, inner,
    1091               0 :                                              recessedBorder, mStyleContext);
    1092                 : 
    1093                 :   // Adjust the inner rect to account for the one pixel recessed border,
    1094                 :   // and a six pixel padding on each edge
    1095                 :   inner.Deflate(nsPresContext::CSSPixelsToAppUnits(ICON_PADDING+ALT_BORDER_WIDTH), 
    1096               0 :                 nsPresContext::CSSPixelsToAppUnits(ICON_PADDING+ALT_BORDER_WIDTH));
    1097               0 :   if (inner.IsEmpty()) {
    1098                 :     return;
    1099                 :   }
    1100                 : 
    1101                 :   // Clip so we don't render outside the inner rect
    1102               0 :   aRenderingContext.PushState();
    1103               0 :   aRenderingContext.IntersectClip(inner);
    1104                 : 
    1105                 :   // Check if we should display image placeholders
    1106               0 :   if (gIconLoad->mPrefShowPlaceholders) {
    1107               0 :     const nsStyleVisibility* vis = GetStyleVisibility();
    1108               0 :     nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
    1109                 : 
    1110               0 :     bool iconUsed = false;
    1111                 : 
    1112                 :     // If we weren't previously displaying an icon, register ourselves
    1113                 :     // as an observer for load and animation updates and flag that we're
    1114                 :     // doing so now.
    1115               0 :     if (aRequest && !mDisplayingIcon) {
    1116               0 :       gIconLoad->AddIconObserver(this);
    1117               0 :       mDisplayingIcon = true;
    1118                 :     }
    1119                 : 
    1120                 : 
    1121                 :     // If the image in question is loaded and decoded, draw it
    1122               0 :     PRUint32 imageStatus = 0;
    1123               0 :     if (aRequest)
    1124               0 :       aRequest->GetImageStatus(&imageStatus);
    1125               0 :     if (imageStatus & imgIRequest::STATUS_FRAME_COMPLETE) {
    1126               0 :       nsCOMPtr<imgIContainer> imgCon;
    1127               0 :       aRequest->GetImage(getter_AddRefs(imgCon));
    1128               0 :       NS_ABORT_IF_FALSE(imgCon, "Frame Complete, but no image container?");
    1129                 :       nsRect dest((vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
    1130               0 :                   inner.XMost() - size : inner.x,
    1131               0 :                   inner.y, size, size);
    1132                 :       nsLayoutUtils::DrawSingleImage(&aRenderingContext, imgCon,
    1133                 :         nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
    1134               0 :         imgIContainer::FLAG_NONE);
    1135               0 :       iconUsed = true;
    1136                 :     }
    1137                 : 
    1138                 :     // if we could not draw the icon, flag that we're waiting for it and
    1139                 :     // just draw some graffiti in the mean time
    1140               0 :     if (!iconUsed) {
    1141                 :       nscoord iconXPos = (vis->mDirection ==   NS_STYLE_DIRECTION_RTL) ?
    1142               0 :                          inner.XMost() - size : inner.x;
    1143               0 :       nscoord twoPX = nsPresContext::CSSPixelsToAppUnits(2);
    1144               0 :       aRenderingContext.DrawRect(iconXPos, inner.y,size,size);
    1145               0 :       aRenderingContext.PushState();
    1146               0 :       aRenderingContext.SetColor(NS_RGB(0xFF,0,0));
    1147                 :       aRenderingContext.FillEllipse(size/2 + iconXPos, size/2 + inner.y,
    1148               0 :                                     size/2 - twoPX, size/2 - twoPX);
    1149               0 :       aRenderingContext.PopState();
    1150                 :     }
    1151                 : 
    1152                 :     // Reduce the inner rect by the width of the icon, and leave an
    1153                 :     // additional ICON_PADDING pixels for padding
    1154               0 :     PRInt32 iconWidth = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
    1155               0 :     if (vis->mDirection != NS_STYLE_DIRECTION_RTL)
    1156               0 :       inner.x += iconWidth;
    1157               0 :     inner.width -= iconWidth;
    1158                 :   }
    1159                 : 
    1160                 :   // If there's still room, display the alt-text
    1161               0 :   if (!inner.IsEmpty()) {
    1162               0 :     nsIContent* content = GetContent();
    1163               0 :     if (content) {
    1164               0 :       nsXPIDLString altText;
    1165                 :       nsCSSFrameConstructor::GetAlternateTextFor(content, content->Tag(),
    1166               0 :                                                  altText);
    1167               0 :       DisplayAltText(PresContext(), aRenderingContext, altText, inner);
    1168                 :     }
    1169                 :   }
    1170                 : 
    1171               0 :   aRenderingContext.PopState();
    1172                 : }
    1173                 : 
    1174               0 : static void PaintAltFeedback(nsIFrame* aFrame, nsRenderingContext* aCtx,
    1175                 :      const nsRect& aDirtyRect, nsPoint aPt)
    1176                 : {
    1177               0 :   nsImageFrame* f = static_cast<nsImageFrame*>(aFrame);
    1178               0 :   nsEventStates state = f->GetContent()->AsElement()->State();
    1179                 :   f->DisplayAltFeedback(*aCtx,
    1180                 :                         aDirtyRect,
    1181               0 :                         IMAGE_OK(state, true)
    1182                 :                            ? nsImageFrame::gIconLoad->mLoadingImage
    1183                 :                            : nsImageFrame::gIconLoad->mBrokenImage,
    1184               0 :                         aPt);
    1185               0 : }
    1186                 : 
    1187                 : #ifdef NS_DEBUG
    1188               0 : static void PaintDebugImageMap(nsIFrame* aFrame, nsRenderingContext* aCtx,
    1189                 :      const nsRect& aDirtyRect, nsPoint aPt) {
    1190               0 :   nsImageFrame* f = static_cast<nsImageFrame*>(aFrame);
    1191               0 :   nsRect inner = f->GetInnerArea() + aPt;
    1192                 : 
    1193               0 :   aCtx->SetColor(NS_RGB(0, 0, 0));
    1194               0 :   aCtx->PushState();
    1195               0 :   aCtx->Translate(inner.TopLeft());
    1196               0 :   f->GetImageMap()->Draw(aFrame, *aCtx);
    1197               0 :   aCtx->PopState();
    1198               0 : }
    1199                 : #endif
    1200                 : 
    1201                 : void
    1202               0 : nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
    1203                 :                       nsRenderingContext* aCtx) {
    1204                 :   static_cast<nsImageFrame*>(mFrame)->
    1205               0 :     PaintImage(*aCtx, ToReferenceFrame(), mVisibleRect, mImage,
    1206               0 :                aBuilder->ShouldSyncDecodeImages()
    1207                 :                  ? (PRUint32) imgIContainer::FLAG_SYNC_DECODE
    1208               0 :                  : (PRUint32) imgIContainer::FLAG_NONE);
    1209               0 : }
    1210                 : 
    1211                 : already_AddRefed<ImageContainer>
    1212               0 : nsDisplayImage::GetContainer()
    1213                 : {
    1214               0 :   nsRefPtr<ImageContainer> container;
    1215               0 :   nsresult rv = mImage->GetImageContainer(getter_AddRefs(container));
    1216               0 :   NS_ENSURE_SUCCESS(rv, nsnull);
    1217               0 :   return container.forget();
    1218                 : }
    1219                 : 
    1220                 : void
    1221               0 : nsDisplayImage::ConfigureLayer(ImageLayer* aLayer)
    1222                 : {
    1223               0 :   aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
    1224                 :   
    1225               0 :   PRInt32 factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    1226               0 :   nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame);
    1227                 : 
    1228               0 :   nsRect dest = imageFrame->GetInnerArea() + ToReferenceFrame();
    1229               0 :   gfxRect destRect(dest.x, dest.y, dest.width, dest.height);
    1230               0 :   destRect.ScaleInverse(factor); 
    1231                 : 
    1232                 :   PRInt32 imageWidth;
    1233                 :   PRInt32 imageHeight;
    1234               0 :   mImage->GetWidth(&imageWidth);
    1235               0 :   mImage->GetHeight(&imageHeight);
    1236                 : 
    1237               0 :   gfxMatrix transform;
    1238               0 :   transform.Translate(destRect.TopLeft());
    1239               0 :   transform.Scale(destRect.Width()/imageWidth,
    1240               0 :                   destRect.Height()/imageHeight);
    1241               0 :   aLayer->SetTransform(gfx3DMatrix::From2D(transform));
    1242                 : 
    1243               0 :   aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
    1244               0 : }
    1245                 : 
    1246                 : void
    1247               0 : nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
    1248                 :                          const nsRect& aDirtyRect, imgIContainer* aImage,
    1249                 :                          PRUint32 aFlags)
    1250                 : {
    1251                 :   // Render the image into our content area (the area inside
    1252                 :   // the borders and padding)
    1253               0 :   NS_ASSERTION(GetInnerArea().width == mComputedSize.width, "bad width");
    1254               0 :   nsRect inner = GetInnerArea() + aPt;
    1255               0 :   nsRect dest(inner.TopLeft(), mComputedSize);
    1256               0 :   dest.y -= GetContinuationOffset();
    1257                 : 
    1258                 :   nsLayoutUtils::DrawSingleImage(&aRenderingContext, aImage,
    1259                 :     nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
    1260               0 :     aFlags);
    1261                 : 
    1262               0 :   nsImageMap* map = GetImageMap();
    1263               0 :   if (nsnull != map) {
    1264               0 :     aRenderingContext.PushState();
    1265               0 :     aRenderingContext.SetColor(NS_RGB(0, 0, 0));
    1266               0 :     aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
    1267               0 :     aRenderingContext.Translate(inner.TopLeft());
    1268               0 :     map->Draw(this, aRenderingContext);
    1269               0 :     aRenderingContext.PopState();
    1270                 :   }
    1271               0 : }
    1272                 : 
    1273                 : NS_IMETHODIMP
    1274               0 : nsImageFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    1275                 :                                const nsRect&           aDirtyRect,
    1276                 :                                const nsDisplayListSet& aLists)
    1277                 : {
    1278               0 :   if (!IsVisibleForPainting(aBuilder))
    1279               0 :     return NS_OK;
    1280                 : 
    1281                 :   // REVIEW: We don't need any special logic here for deciding which layer
    1282                 :   // to put the background in ... it goes in aLists.BorderBackground() and
    1283                 :   // then if we have a block parent, it will put our background in the right
    1284                 :   // place.
    1285               0 :   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
    1286               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1287                 :   // REVIEW: Checking mRect.IsEmpty() makes no sense to me, so I removed it.
    1288                 :   // It can't have been protecting us against bad situations with zero-size
    1289                 :   // images since adding a border would make the rect non-empty.
    1290                 : 
    1291               0 :   nsDisplayList replacedContent;
    1292               0 :   if (mComputedSize.width != 0 && mComputedSize.height != 0) {
    1293               0 :     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
    1294               0 :     NS_ASSERTION(imageLoader, "Not an image loading content?");
    1295                 : 
    1296               0 :     nsCOMPtr<imgIRequest> currentRequest;
    1297               0 :     if (imageLoader) {
    1298               0 :       imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    1299               0 :                               getter_AddRefs(currentRequest));
    1300                 :     }
    1301                 : 
    1302               0 :     nsEventStates contentState = mContent->AsElement()->State();
    1303               0 :     bool imageOK = IMAGE_OK(contentState, true);
    1304                 : 
    1305               0 :     nsCOMPtr<imgIContainer> imgCon;
    1306               0 :     if (currentRequest) {
    1307               0 :       currentRequest->GetImage(getter_AddRefs(imgCon));
    1308                 :     }
    1309                 : 
    1310                 :     // Determine if the size is available
    1311               0 :     bool haveSize = false;
    1312               0 :     PRUint32 imageStatus = 0;
    1313               0 :     if (currentRequest)
    1314               0 :       currentRequest->GetImageStatus(&imageStatus);
    1315               0 :     if (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE)
    1316               0 :       haveSize = true;
    1317                 : 
    1318                 :     // We should never have the size and not have an image container
    1319               0 :     NS_ABORT_IF_FALSE(!haveSize || imgCon, "Have size but not container?");
    1320                 : 
    1321               0 :     if (!imageOK || !haveSize) {
    1322                 :       // No image yet, or image load failed. Draw the alt-text and an icon
    1323                 :       // indicating the status
    1324                 :       rv = replacedContent.AppendNewToTop(new (aBuilder)
    1325                 :           nsDisplayGeneric(aBuilder, this, PaintAltFeedback, "AltFeedback",
    1326               0 :                            nsDisplayItem::TYPE_ALT_FEEDBACK));
    1327               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1328                 :     }
    1329                 :     else {
    1330                 :       rv = replacedContent.AppendNewToTop(new (aBuilder)
    1331               0 :           nsDisplayImage(aBuilder, this, imgCon));
    1332               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1333                 : 
    1334                 :       // If we were previously displaying an icon, we're not anymore
    1335               0 :       if (mDisplayingIcon) {
    1336               0 :         gIconLoad->RemoveIconObserver(this);
    1337               0 :         mDisplayingIcon = false;
    1338                 :       }
    1339                 : 
    1340                 :         
    1341                 : #ifdef DEBUG
    1342               0 :       if (GetShowFrameBorders() && GetImageMap()) {
    1343                 :         rv = aLists.Outlines()->AppendNewToTop(new (aBuilder)
    1344                 :             nsDisplayGeneric(aBuilder, this, PaintDebugImageMap, "DebugImageMap",
    1345               0 :                              nsDisplayItem::TYPE_DEBUG_IMAGE_MAP));
    1346               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1347                 :       }
    1348                 : #endif
    1349                 :     }
    1350                 :   }
    1351                 : 
    1352               0 :   if (ShouldDisplaySelection()) {
    1353                 :     rv = DisplaySelectionOverlay(aBuilder, &replacedContent,
    1354               0 :                                  nsISelectionDisplay::DISPLAY_IMAGES);
    1355               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1356                 :   }
    1357                 : 
    1358               0 :   WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
    1359                 : 
    1360               0 :   return NS_OK;
    1361                 : }
    1362                 : 
    1363                 : bool
    1364               0 : nsImageFrame::ShouldDisplaySelection()
    1365                 : {
    1366                 :   // XXX what on EARTH is this code for?
    1367                 :   nsresult result;
    1368               0 :   nsPresContext* presContext = PresContext();
    1369               0 :   PRInt16 displaySelection = presContext->PresShell()->GetSelectionFlags();
    1370               0 :   if (!(displaySelection & nsISelectionDisplay::DISPLAY_IMAGES))
    1371               0 :     return false;//no need to check the blue border, we cannot be drawn selected
    1372                 : //insert hook here for image selection drawing
    1373                 : #if IMAGE_EDITOR_CHECK
    1374                 :   //check to see if this frame is in an editor context
    1375                 :   //isEditor check. this needs to be changed to have better way to check
    1376               0 :   if (displaySelection == nsISelectionDisplay::DISPLAY_ALL) 
    1377                 :   {
    1378               0 :     nsCOMPtr<nsISelectionController> selCon;
    1379               0 :     result = GetSelectionController(presContext, getter_AddRefs(selCon));
    1380               0 :     if (NS_SUCCEEDED(result) && selCon)
    1381                 :     {
    1382               0 :       nsCOMPtr<nsISelection> selection;
    1383               0 :       result = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
    1384               0 :       if (NS_SUCCEEDED(result) && selection)
    1385                 :       {
    1386                 :         PRInt32 rangeCount;
    1387               0 :         selection->GetRangeCount(&rangeCount);
    1388               0 :         if (rangeCount == 1) //if not one then let code drop to nsFrame::Paint
    1389                 :         {
    1390               0 :           nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
    1391               0 :           if (parentContent)
    1392                 :           {
    1393               0 :             PRInt32 thisOffset = parentContent->IndexOf(mContent);
    1394               0 :             nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(parentContent);
    1395               0 :             nsCOMPtr<nsIDOMNode> rangeNode;
    1396                 :             PRInt32 rangeOffset;
    1397               0 :             nsCOMPtr<nsIDOMRange> range;
    1398               0 :             selection->GetRangeAt(0,getter_AddRefs(range));
    1399               0 :             if (range)
    1400                 :             {
    1401               0 :               range->GetStartContainer(getter_AddRefs(rangeNode));
    1402               0 :               range->GetStartOffset(&rangeOffset);
    1403                 : 
    1404               0 :               if (parentNode && rangeNode && (rangeNode == parentNode) && rangeOffset == thisOffset)
    1405                 :               {
    1406               0 :                 range->GetEndContainer(getter_AddRefs(rangeNode));
    1407               0 :                 range->GetEndOffset(&rangeOffset);
    1408               0 :                 if ((rangeNode == parentNode) && (rangeOffset == (thisOffset +1))) //+1 since that would mean this whole content is selected only
    1409               0 :                   return false; //do not allow nsFrame do draw any further selection
    1410                 :               }
    1411                 :             }
    1412                 :           }
    1413                 :         }
    1414                 :       }
    1415                 :     }
    1416                 :   }
    1417                 : #endif
    1418               0 :   return true;
    1419                 : }
    1420                 : 
    1421                 : nsImageMap*
    1422               0 : nsImageFrame::GetImageMap()
    1423                 : {
    1424               0 :   if (!mImageMap) {
    1425               0 :     nsIDocument* doc = mContent->GetDocument();
    1426               0 :     if (!doc) {
    1427               0 :       return nsnull;
    1428                 :     }
    1429                 : 
    1430               0 :     nsAutoString usemap;
    1431               0 :     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, usemap);
    1432                 : 
    1433               0 :     nsCOMPtr<nsIContent> map = doc->FindImageMap(usemap);
    1434               0 :     if (map) {
    1435               0 :       mImageMap = new nsImageMap();
    1436               0 :       NS_ADDREF(mImageMap);
    1437               0 :       mImageMap->Init(this, map);
    1438                 :     }
    1439                 :   }
    1440                 : 
    1441               0 :   return mImageMap;
    1442                 : }
    1443                 : 
    1444                 : bool
    1445               0 : nsImageFrame::IsServerImageMap()
    1446                 : {
    1447               0 :   return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::ismap);
    1448                 : }
    1449                 : 
    1450                 : // Translate an point that is relative to our frame
    1451                 : // into a localized pixel coordinate that is relative to the
    1452                 : // content area of this frame (inside the border+padding).
    1453                 : void
    1454               0 : nsImageFrame::TranslateEventCoords(const nsPoint& aPoint,
    1455                 :                                    nsIntPoint&     aResult)
    1456                 : {
    1457               0 :   nscoord x = aPoint.x;
    1458               0 :   nscoord y = aPoint.y;
    1459                 : 
    1460                 :   // Subtract out border and padding here so that the coordinates are
    1461                 :   // now relative to the content area of this frame.
    1462               0 :   nsRect inner = GetInnerArea();
    1463               0 :   x -= inner.x;
    1464               0 :   y -= inner.y;
    1465                 : 
    1466               0 :   aResult.x = nsPresContext::AppUnitsToIntCSSPixels(x);
    1467               0 :   aResult.y = nsPresContext::AppUnitsToIntCSSPixels(y);
    1468               0 : }
    1469                 : 
    1470                 : bool
    1471               0 : nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
    1472                 :                                          nsIContent** aNode)
    1473                 : {
    1474               0 :   bool status = false;
    1475               0 :   aTarget.Truncate();
    1476               0 :   *aHref = nsnull;
    1477               0 :   *aNode = nsnull;
    1478                 : 
    1479                 :   // Walk up the content tree, looking for an nsIDOMAnchorElement
    1480               0 :   for (nsIContent* content = mContent->GetParent();
    1481               0 :        content; content = content->GetParent()) {
    1482               0 :     nsCOMPtr<nsILink> link(do_QueryInterface(content));
    1483               0 :     if (link) {
    1484               0 :       nsCOMPtr<nsIURI> href = content->GetHrefURI();
    1485               0 :       if (href) {
    1486               0 :         href->Clone(aHref);
    1487                 :       }
    1488               0 :       status = (*aHref != nsnull);
    1489                 : 
    1490               0 :       nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(content));
    1491               0 :       if (anchor) {
    1492               0 :         anchor->GetTarget(aTarget);
    1493                 :       }
    1494               0 :       NS_ADDREF(*aNode = content);
    1495                 :       break;
    1496                 :     }
    1497                 :   }
    1498               0 :   return status;
    1499                 : }
    1500                 : 
    1501                 : NS_IMETHODIMP  
    1502               0 : nsImageFrame::GetContentForEvent(nsEvent* aEvent,
    1503                 :                                  nsIContent** aContent)
    1504                 : {
    1505               0 :   NS_ENSURE_ARG_POINTER(aContent);
    1506                 : 
    1507               0 :   nsIFrame* f = nsLayoutUtils::GetNonGeneratedAncestor(this);
    1508               0 :   if (f != this) {
    1509               0 :     return f->GetContentForEvent(aEvent, aContent);
    1510                 :   }
    1511                 : 
    1512                 :   // XXX We need to make this special check for area element's capturing the
    1513                 :   // mouse due to bug 135040. Remove it once that's fixed.
    1514                 :   nsIContent* capturingContent =
    1515               0 :     NS_IS_MOUSE_EVENT(aEvent) ? nsIPresShell::GetCapturingContent() : nsnull;
    1516               0 :   if (capturingContent && capturingContent->GetPrimaryFrame() == this) {
    1517               0 :     *aContent = capturingContent;
    1518               0 :     NS_IF_ADDREF(*aContent);
    1519               0 :     return NS_OK;
    1520                 :   }
    1521                 : 
    1522               0 :   nsImageMap* map = GetImageMap();
    1523                 : 
    1524               0 :   if (nsnull != map) {
    1525               0 :     nsIntPoint p;
    1526                 :     TranslateEventCoords(
    1527               0 :       nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this), p);
    1528               0 :     nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
    1529               0 :     if (area) {
    1530               0 :       area.forget(aContent);
    1531               0 :       return NS_OK;
    1532                 :     }
    1533                 :   }
    1534                 : 
    1535               0 :   *aContent = GetContent();
    1536               0 :   NS_IF_ADDREF(*aContent);
    1537               0 :   return NS_OK;
    1538                 : }
    1539                 : 
    1540                 : // XXX what should clicks on transparent pixels do?
    1541                 : NS_IMETHODIMP
    1542               0 : nsImageFrame::HandleEvent(nsPresContext* aPresContext,
    1543                 :                           nsGUIEvent* aEvent,
    1544                 :                           nsEventStatus* aEventStatus)
    1545                 : {
    1546               0 :   NS_ENSURE_ARG_POINTER(aEventStatus);
    1547                 : 
    1548               0 :   if ((aEvent->eventStructType == NS_MOUSE_EVENT &&
    1549                 :        aEvent->message == NS_MOUSE_BUTTON_UP && 
    1550                 :        static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) ||
    1551                 :       aEvent->message == NS_MOUSE_MOVE) {
    1552               0 :     nsImageMap* map = GetImageMap();
    1553               0 :     bool isServerMap = IsServerImageMap();
    1554               0 :     if ((nsnull != map) || isServerMap) {
    1555               0 :       nsIntPoint p;
    1556                 :       TranslateEventCoords(
    1557               0 :         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this), p);
    1558               0 :       bool inside = false;
    1559                 :       // Even though client-side image map triggering happens
    1560                 :       // through content, we need to make sure we're not inside
    1561                 :       // (in case we deal with a case of both client-side and
    1562                 :       // sever-side on the same image - it happens!)
    1563               0 :       if (nsnull != map) {
    1564               0 :         inside = !!map->GetArea(p.x, p.y);
    1565                 :       }
    1566                 : 
    1567               0 :       if (!inside && isServerMap) {
    1568                 : 
    1569                 :         // Server side image maps use the href in a containing anchor
    1570                 :         // element to provide the basis for the destination url.
    1571               0 :         nsCOMPtr<nsIURI> uri;
    1572               0 :         nsAutoString target;
    1573               0 :         nsCOMPtr<nsIContent> anchorNode;
    1574               0 :         if (GetAnchorHREFTargetAndNode(getter_AddRefs(uri), target,
    1575               0 :                                        getter_AddRefs(anchorNode))) {
    1576                 :           // XXX if the mouse is over/clicked in the border/padding area
    1577                 :           // we should probably just pretend nothing happened. Nav4
    1578                 :           // keeps the x,y coordinates positive as we do; IE doesn't
    1579                 :           // bother. Both of them send the click through even when the
    1580                 :           // mouse is over the border.
    1581               0 :           if (p.x < 0) p.x = 0;
    1582               0 :           if (p.y < 0) p.y = 0;
    1583               0 :           nsCAutoString spec;
    1584               0 :           uri->GetSpec(spec);
    1585               0 :           spec += nsPrintfCString("?%d,%d", p.x, p.y);
    1586               0 :           uri->SetSpec(spec);                
    1587                 :           
    1588               0 :           bool clicked = false;
    1589               0 :           if (aEvent->message == NS_MOUSE_BUTTON_UP) {
    1590               0 :             *aEventStatus = nsEventStatus_eConsumeDoDefault; 
    1591               0 :             clicked = true;
    1592                 :           }
    1593                 :           nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target,
    1594               0 :                                       clicked, true, true);
    1595                 :         }
    1596                 :       }
    1597                 :     }
    1598                 :   }
    1599                 : 
    1600               0 :   return nsSplittableFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
    1601                 : }
    1602                 : 
    1603                 : NS_IMETHODIMP
    1604               0 : nsImageFrame::GetCursor(const nsPoint& aPoint,
    1605                 :                         nsIFrame::Cursor& aCursor)
    1606                 : {
    1607               0 :   nsImageMap* map = GetImageMap();
    1608               0 :   if (nsnull != map) {
    1609               0 :     nsIntPoint p;
    1610               0 :     TranslateEventCoords(aPoint, p);
    1611               0 :     nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
    1612               0 :     if (area) {
    1613                 :       // Use the cursor from the style of the *area* element.
    1614                 :       // XXX Using the image as the parent style context isn't
    1615                 :       // technically correct, but it's probably the right thing to do
    1616                 :       // here, since it means that areas on which the cursor isn't
    1617                 :       // specified will inherit the style from the image.
    1618                 :       nsRefPtr<nsStyleContext> areaStyle = 
    1619                 :         PresContext()->PresShell()->StyleSet()->
    1620               0 :           ResolveStyleFor(area->AsElement(), GetStyleContext());
    1621               0 :       if (areaStyle) {
    1622                 :         FillCursorInformationFromStyle(areaStyle->GetStyleUserInterface(),
    1623               0 :                                        aCursor);
    1624               0 :         if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) {
    1625               0 :           aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
    1626                 :         }
    1627               0 :         return NS_OK;
    1628                 :       }
    1629                 :     }
    1630                 :   }
    1631               0 :   return nsFrame::GetCursor(aPoint, aCursor);
    1632                 : }
    1633                 : 
    1634                 : NS_IMETHODIMP
    1635               0 : nsImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
    1636                 :                                nsIAtom* aAttribute,
    1637                 :                                PRInt32 aModType)
    1638                 : {
    1639                 :   nsresult rv = nsSplittableFrame::AttributeChanged(aNameSpaceID,
    1640               0 :                                                     aAttribute, aModType);
    1641               0 :   if (NS_FAILED(rv)) {
    1642               0 :     return rv;
    1643                 :   }
    1644               0 :   if (nsGkAtoms::alt == aAttribute)
    1645                 :   {
    1646               0 :     PresContext()->PresShell()->FrameNeedsReflow(this,
    1647                 :                                                  nsIPresShell::eStyleChange,
    1648               0 :                                                  NS_FRAME_IS_DIRTY);
    1649                 :   }
    1650                 : 
    1651               0 :   return NS_OK;
    1652                 : }
    1653                 : 
    1654                 : nsIAtom*
    1655               0 : nsImageFrame::GetType() const
    1656                 : {
    1657               0 :   return nsGkAtoms::imageFrame;
    1658                 : }
    1659                 : 
    1660                 : #ifdef DEBUG
    1661                 : NS_IMETHODIMP
    1662               0 : nsImageFrame::GetFrameName(nsAString& aResult) const
    1663                 : {
    1664               0 :   return MakeFrameName(NS_LITERAL_STRING("ImageFrame"), aResult);
    1665                 : }
    1666                 : 
    1667                 : NS_IMETHODIMP
    1668               0 : nsImageFrame::List(FILE* out, PRInt32 aIndent) const
    1669                 : {
    1670               0 :   IndentBy(out, aIndent);
    1671               0 :   ListTag(out);
    1672                 : #ifdef DEBUG_waterson
    1673                 :   fprintf(out, " [parent=%p]", mParent);
    1674                 : #endif
    1675               0 :   if (HasView()) {
    1676               0 :     fprintf(out, " [view=%p]", (void*)GetView());
    1677                 :   }
    1678               0 :   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
    1679               0 :   if (0 != mState) {
    1680               0 :     fprintf(out, " [state=%016llx]", (unsigned long long)mState);
    1681                 :   }
    1682               0 :   fprintf(out, " [content=%p]", (void*)mContent);
    1683               0 :   fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext));
    1684                 : 
    1685                 :   // output the img src url
    1686               0 :   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
    1687               0 :   if (imageLoader) {
    1688               0 :     nsCOMPtr<imgIRequest> currentRequest;
    1689               0 :     imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    1690               0 :                             getter_AddRefs(currentRequest));
    1691               0 :     if (currentRequest) {
    1692               0 :       nsCOMPtr<nsIURI> uri;
    1693               0 :       currentRequest->GetURI(getter_AddRefs(uri));
    1694               0 :       nsCAutoString uristr;
    1695               0 :       uri->GetAsciiSpec(uristr);
    1696               0 :       fprintf(out, " [src=%s]", uristr.get());
    1697                 :     }
    1698                 :   }
    1699               0 :   fputs("\n", out);
    1700               0 :   return NS_OK;
    1701                 : }
    1702                 : #endif
    1703                 : 
    1704                 : PRIntn
    1705               0 : nsImageFrame::GetSkipSides() const
    1706                 : {
    1707               0 :   PRIntn skip = 0;
    1708               0 :   if (nsnull != GetPrevInFlow()) {
    1709               0 :     skip |= 1 << NS_SIDE_TOP;
    1710                 :   }
    1711               0 :   if (nsnull != GetNextInFlow()) {
    1712               0 :     skip |= 1 << NS_SIDE_BOTTOM;
    1713                 :   }
    1714               0 :   return skip;
    1715                 : }
    1716                 : 
    1717                 : nsresult
    1718               0 : nsImageFrame::GetIntrinsicImageSize(nsSize& aSize)
    1719                 : {
    1720               0 :   if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
    1721               0 :       mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord) {
    1722                 :     aSize.SizeTo(mIntrinsicSize.width.GetCoordValue(),
    1723               0 :                  mIntrinsicSize.height.GetCoordValue());
    1724               0 :     return NS_OK;
    1725                 :   }
    1726                 : 
    1727               0 :   return NS_ERROR_FAILURE;
    1728                 : }
    1729                 : 
    1730                 : nsresult
    1731               0 : nsImageFrame::LoadIcon(const nsAString& aSpec,
    1732                 :                        nsPresContext *aPresContext,
    1733                 :                        imgIRequest** aRequest)
    1734                 : {
    1735               0 :   nsresult rv = NS_OK;
    1736               0 :   NS_PRECONDITION(!aSpec.IsEmpty(), "What happened??");
    1737                 : 
    1738               0 :   if (!sIOService) {
    1739               0 :     rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
    1740               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1741                 :   }
    1742                 : 
    1743               0 :   nsCOMPtr<nsIURI> realURI;
    1744               0 :   SpecToURI(aSpec, sIOService, getter_AddRefs(realURI));
    1745                 :  
    1746               0 :   nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
    1747               0 :   if (NS_FAILED(rv)) return rv;
    1748                 : 
    1749               0 :   nsCOMPtr<nsILoadGroup> loadGroup;
    1750               0 :   GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
    1751                 : 
    1752                 :   // For icon loads, we don't need to merge with the loadgroup flags
    1753               0 :   nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
    1754                 : 
    1755               0 :   return il->LoadImage(realURI,     /* icon URI */
    1756                 :                        nsnull,      /* initial document URI; this is only
    1757                 :                                        relevant for cookies, so does not
    1758                 :                                        apply to icons. */
    1759                 :                        nsnull,      /* referrer (not relevant for icons) */
    1760                 :                        nsnull,      /* principal (not relevant for icons) */
    1761                 :                        loadGroup,
    1762                 :                        gIconLoad,
    1763                 :                        nsnull,      /* Not associated with any particular document */
    1764                 :                        loadFlags,
    1765                 :                        nsnull,
    1766                 :                        nsnull,
    1767                 :                        nsnull,      /* channel policy not needed */
    1768               0 :                        aRequest);
    1769                 : }
    1770                 : 
    1771                 : void
    1772               0 : nsImageFrame::GetDocumentCharacterSet(nsACString& aCharset) const
    1773                 : {
    1774               0 :   if (mContent) {
    1775               0 :     NS_ASSERTION(mContent->GetDocument(),
    1776                 :                  "Frame still alive after content removed from document!");
    1777               0 :     aCharset = mContent->GetDocument()->GetDocumentCharacterSet();
    1778                 :   }
    1779               0 : }
    1780                 : 
    1781                 : void
    1782               0 : nsImageFrame::SpecToURI(const nsAString& aSpec, nsIIOService *aIOService,
    1783                 :                          nsIURI **aURI)
    1784                 : {
    1785               0 :   nsCOMPtr<nsIURI> baseURI;
    1786               0 :   if (mContent) {
    1787               0 :     baseURI = mContent->GetBaseURI();
    1788                 :   }
    1789               0 :   nsCAutoString charset;
    1790               0 :   GetDocumentCharacterSet(charset);
    1791                 :   NS_NewURI(aURI, aSpec, 
    1792               0 :             charset.IsEmpty() ? nsnull : charset.get(), 
    1793               0 :             baseURI, aIOService);
    1794               0 : }
    1795                 : 
    1796                 : void
    1797               0 : nsImageFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup)
    1798                 : {
    1799               0 :   if (!aPresContext)
    1800               0 :     return;
    1801                 : 
    1802               0 :   NS_PRECONDITION(nsnull != aLoadGroup, "null OUT parameter pointer");
    1803                 : 
    1804               0 :   nsIPresShell *shell = aPresContext->GetPresShell();
    1805                 : 
    1806               0 :   if (!shell)
    1807               0 :     return;
    1808                 : 
    1809               0 :   nsIDocument *doc = shell->GetDocument();
    1810               0 :   if (!doc)
    1811               0 :     return;
    1812                 : 
    1813               0 :   *aLoadGroup = doc->GetDocumentLoadGroup().get();  // already_AddRefed
    1814                 : }
    1815                 : 
    1816               0 : nsresult nsImageFrame::LoadIcons(nsPresContext *aPresContext)
    1817                 : {
    1818               0 :   NS_ASSERTION(!gIconLoad, "called LoadIcons twice");
    1819                 : 
    1820               0 :   NS_NAMED_LITERAL_STRING(loadingSrc,"resource://gre-resources/loading-image.png");
    1821               0 :   NS_NAMED_LITERAL_STRING(brokenSrc,"resource://gre-resources/broken-image.png");
    1822                 : 
    1823               0 :   gIconLoad = new IconLoad();
    1824               0 :   NS_ADDREF(gIconLoad);
    1825                 : 
    1826                 :   nsresult rv;
    1827                 :   // create a loader and load the images
    1828                 :   rv = LoadIcon(loadingSrc,
    1829                 :                 aPresContext,
    1830               0 :                 getter_AddRefs(gIconLoad->mLoadingImage));
    1831               0 :   if (NS_FAILED(rv)) {
    1832               0 :     return rv;
    1833                 :   }
    1834                 : 
    1835                 :   rv = LoadIcon(brokenSrc,
    1836                 :                 aPresContext,
    1837               0 :                 getter_AddRefs(gIconLoad->mBrokenImage));
    1838               0 :   return rv;
    1839                 : }
    1840                 : 
    1841               0 : NS_IMPL_ISUPPORTS2(nsImageFrame::IconLoad, nsIObserver,
    1842                 :                    imgIDecoderObserver)
    1843                 : 
    1844                 : static const char* kIconLoadPrefs[] = {
    1845                 :   "browser.display.force_inline_alttext",
    1846                 :   "browser.display.show_image_placeholders",
    1847                 :   nsnull
    1848                 : };
    1849                 : 
    1850               0 : nsImageFrame::IconLoad::IconLoad()
    1851                 : {
    1852                 :   // register observers
    1853               0 :   Preferences::AddStrongObservers(this, kIconLoadPrefs);
    1854               0 :   GetPrefs();
    1855               0 : }
    1856                 : 
    1857                 : void
    1858               0 : nsImageFrame::IconLoad::Shutdown()
    1859                 : {
    1860               0 :   Preferences::RemoveObservers(this, kIconLoadPrefs);
    1861                 :   // in case the pref service releases us later
    1862               0 :   if (mLoadingImage) {
    1863               0 :     mLoadingImage->CancelAndForgetObserver(NS_ERROR_FAILURE);
    1864               0 :     mLoadingImage = nsnull;
    1865                 :   }
    1866               0 :   if (mBrokenImage) {
    1867               0 :     mBrokenImage->CancelAndForgetObserver(NS_ERROR_FAILURE);
    1868               0 :     mBrokenImage = nsnull;
    1869                 :   }
    1870               0 : }
    1871                 : 
    1872                 : NS_IMETHODIMP
    1873               0 : nsImageFrame::IconLoad::Observe(nsISupports *aSubject, const char* aTopic,
    1874                 :                                 const PRUnichar* aData)
    1875                 : {
    1876               0 :   NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
    1877                 :                "wrong topic");
    1878                 : #ifdef DEBUG
    1879                 :   // assert |aData| is one of our prefs.
    1880               0 :   for (PRUint32 i = 0; i < ArrayLength(kIconLoadPrefs) ||
    1881               0 :                        (NS_NOTREACHED("wrong pref"), false); ++i)
    1882               0 :     if (NS_ConvertASCIItoUTF16(kIconLoadPrefs[i]) == nsDependentString(aData))
    1883               0 :       break;
    1884                 : #endif
    1885                 : 
    1886               0 :   GetPrefs();
    1887               0 :   return NS_OK;
    1888                 : }
    1889                 : 
    1890               0 : void nsImageFrame::IconLoad::GetPrefs()
    1891                 : {
    1892                 :   mPrefForceInlineAltText =
    1893               0 :     Preferences::GetBool("browser.display.force_inline_alttext");
    1894                 : 
    1895                 :   mPrefShowPlaceholders =
    1896               0 :     Preferences::GetBool("browser.display.show_image_placeholders", true);
    1897               0 : }
    1898                 : 
    1899                 : 
    1900                 : 
    1901                 : NS_IMETHODIMP
    1902               0 : nsImageFrame::IconLoad::OnStartRequest(imgIRequest *aRequest)
    1903                 : {
    1904               0 :   return NS_OK;
    1905                 : }
    1906                 : 
    1907                 : NS_IMETHODIMP
    1908               0 : nsImageFrame::IconLoad::OnStartDecode(imgIRequest *aRequest)
    1909                 : {
    1910               0 :   return NS_OK;
    1911                 : }
    1912                 : 
    1913                 : NS_IMETHODIMP
    1914               0 : nsImageFrame::IconLoad::OnStartContainer(imgIRequest *aRequest,
    1915                 :                                          imgIContainer *aContainer)
    1916                 : {
    1917               0 :   return NS_OK;
    1918                 : }
    1919                 : 
    1920                 : NS_IMETHODIMP
    1921               0 : nsImageFrame::IconLoad::OnStartFrame(imgIRequest *aRequest,
    1922                 :                                      PRUint32 aFrame)
    1923                 : {
    1924               0 :   return NS_OK;
    1925                 : }
    1926                 : 
    1927                 : NS_IMETHODIMP
    1928               0 : nsImageFrame::IconLoad::OnDataAvailable(imgIRequest *aRequest,
    1929                 :                                         bool aCurrentFrame,
    1930                 :                                         const nsIntRect * aRect)
    1931                 : {
    1932               0 :   return NS_OK;
    1933                 : }
    1934                 : 
    1935                 : NS_IMETHODIMP
    1936               0 : nsImageFrame::IconLoad::OnStopFrame(imgIRequest *aRequest,
    1937                 :                                     PRUint32 aFrame)
    1938                 : {
    1939               0 :   return NS_OK;
    1940                 : }
    1941                 : 
    1942                 : NS_IMETHODIMP
    1943               0 : nsImageFrame::IconLoad::OnStopContainer(imgIRequest *aRequest,
    1944                 :                                         imgIContainer *aContainer)
    1945                 : {
    1946               0 :   return NS_OK;
    1947                 : }
    1948                 : 
    1949                 : NS_IMETHODIMP
    1950               0 : nsImageFrame::IconLoad::OnStopDecode(imgIRequest *aRequest,
    1951                 :                                      nsresult status,
    1952                 :                                      const PRUnichar *statusArg)
    1953                 : {
    1954               0 :   return NS_OK;
    1955                 : }
    1956                 : 
    1957                 : NS_IMETHODIMP
    1958               0 : nsImageFrame::IconLoad::OnImageIsAnimated(imgIRequest *aRequest)
    1959                 : {
    1960               0 :   return NS_OK;
    1961                 : }
    1962                 : 
    1963                 : NS_IMETHODIMP
    1964               0 : nsImageFrame::IconLoad::OnStopRequest(imgIRequest *aRequest,
    1965                 :                                       bool aIsLastPart)
    1966                 : {
    1967               0 :   nsTObserverArray<nsImageFrame*>::ForwardIterator iter(mIconObservers);
    1968                 :   nsImageFrame *frame;
    1969               0 :   while (iter.HasMore()) {
    1970               0 :     frame = iter.GetNext();
    1971               0 :     frame->Invalidate(frame->GetRect());
    1972                 :   }
    1973                 : 
    1974               0 :   return NS_OK;
    1975                 : }
    1976                 : 
    1977                 : NS_IMETHODIMP
    1978               0 : nsImageFrame::IconLoad::OnDiscard(imgIRequest *aRequest)
    1979                 : {
    1980               0 :   return NS_OK;
    1981                 : }
    1982                 : 
    1983                 : NS_IMETHODIMP
    1984               0 : nsImageFrame::IconLoad::FrameChanged(imgIRequest *aRequest,
    1985                 :                                      imgIContainer *aContainer,
    1986                 :                                      const nsIntRect *aDirtyRect)
    1987                 : {
    1988               0 :   nsTObserverArray<nsImageFrame*>::ForwardIterator iter(mIconObservers);
    1989                 :   nsImageFrame *frame;
    1990               0 :   while (iter.HasMore()) {
    1991               0 :     frame = iter.GetNext();
    1992               0 :     frame->Invalidate(frame->GetRect());
    1993                 :   }
    1994                 : 
    1995               0 :   return NS_OK;
    1996                 : }
    1997                 : 
    1998                 : 
    1999                 : 
    2000               0 : NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver)
    2001                 : 
    2002               0 : nsImageListener::nsImageListener(nsImageFrame *aFrame) :
    2003               0 :   mFrame(aFrame)
    2004                 : {
    2005               0 : }
    2006                 : 
    2007               0 : nsImageListener::~nsImageListener()
    2008                 : {
    2009               0 : }
    2010                 : 
    2011               0 : NS_IMETHODIMP nsImageListener::OnStartContainer(imgIRequest *aRequest,
    2012                 :                                                 imgIContainer *aImage)
    2013                 : {
    2014               0 :   if (!mFrame)
    2015               0 :     return NS_ERROR_FAILURE;
    2016                 : 
    2017               0 :   return mFrame->OnStartContainer(aRequest, aImage);
    2018                 : }
    2019                 : 
    2020               0 : NS_IMETHODIMP nsImageListener::OnDataAvailable(imgIRequest *aRequest,
    2021                 :                                                bool aCurrentFrame,
    2022                 :                                                const nsIntRect *aRect)
    2023                 : {
    2024               0 :   if (!mFrame)
    2025               0 :     return NS_ERROR_FAILURE;
    2026                 : 
    2027               0 :   return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
    2028                 : }
    2029                 : 
    2030               0 : NS_IMETHODIMP nsImageListener::OnStopDecode(imgIRequest *aRequest,
    2031                 :                                             nsresult status,
    2032                 :                                             const PRUnichar *statusArg)
    2033                 : {
    2034               0 :   if (!mFrame)
    2035               0 :     return NS_ERROR_FAILURE;
    2036                 : 
    2037               0 :   return mFrame->OnStopDecode(aRequest, status, statusArg);
    2038                 : }
    2039                 : 
    2040               0 : NS_IMETHODIMP nsImageListener::FrameChanged(imgIRequest *aRequest,
    2041                 :                                             imgIContainer *aContainer,
    2042                 :                                             const nsIntRect *aDirtyRect)
    2043                 : {
    2044               0 :   if (!mFrame)
    2045               0 :     return NS_ERROR_FAILURE;
    2046                 : 
    2047               0 :   return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect);
    2048                 : }
    2049                 : 
    2050                 : static bool
    2051               0 : IsInAutoWidthTableCellForQuirk(nsIFrame *aFrame)
    2052                 : {
    2053               0 :   if (eCompatibility_NavQuirks != aFrame->PresContext()->CompatibilityMode())
    2054               0 :     return false;
    2055                 :   // Check if the parent of the closest nsBlockFrame has auto width.
    2056               0 :   nsBlockFrame *ancestor = nsLayoutUtils::FindNearestBlockAncestor(aFrame);
    2057               0 :   if (ancestor->GetStyleContext()->GetPseudo() == nsCSSAnonBoxes::cellContent) {
    2058                 :     // Assume direct parent is a table cell frame.
    2059               0 :     nsFrame *grandAncestor = static_cast<nsFrame*>(ancestor->GetParent());
    2060                 :     return grandAncestor &&
    2061               0 :       grandAncestor->GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto;
    2062                 :   }
    2063               0 :   return false;
    2064                 : }
    2065                 : 
    2066                 : /* virtual */ void
    2067               0 : nsImageFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
    2068                 :                                 nsIFrame::InlineMinWidthData *aData)
    2069                 : {
    2070                 : 
    2071               0 :   NS_ASSERTION(GetParent(), "Must have a parent if we get here!");
    2072                 :   
    2073                 :   bool canBreak =
    2074               0 :     !CanContinueTextRun() &&
    2075               0 :     GetParent()->GetStyleText()->WhiteSpaceCanWrap() &&
    2076               0 :     !IsInAutoWidthTableCellForQuirk(this);
    2077                 : 
    2078               0 :   if (canBreak)
    2079               0 :     aData->OptionallyBreak(aRenderingContext);
    2080                 :  
    2081               0 :   aData->trailingWhitespace = 0;
    2082               0 :   aData->skipWhitespace = false;
    2083               0 :   aData->trailingTextFrame = nsnull;
    2084                 :   aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    2085               0 :                             this, nsLayoutUtils::MIN_WIDTH);
    2086               0 :   aData->atStartOfLine = false;
    2087                 : 
    2088               0 :   if (canBreak)
    2089               0 :     aData->OptionallyBreak(aRenderingContext);
    2090                 : 
    2091               0 : }

Generated by: LCOV version 1.7