LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsImageBoxFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 273 0 0.0 %
Date: 2012-06-02 Functions: 48 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 Communicator client 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                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : //
      39                 : // Eric Vaughan
      40                 : // Netscape Communications
      41                 : //
      42                 : // See documentation in associated header file
      43                 : //
      44                 : 
      45                 : #include "nsImageBoxFrame.h"
      46                 : #include "nsGkAtoms.h"
      47                 : #include "nsStyleContext.h"
      48                 : #include "nsStyleConsts.h"
      49                 : #include "nsCOMPtr.h"
      50                 : #include "nsPresContext.h"
      51                 : #include "nsBoxLayoutState.h"
      52                 : 
      53                 : #include "nsHTMLParts.h"
      54                 : #include "nsString.h"
      55                 : #include "nsLeafFrame.h"
      56                 : #include "nsIPresShell.h"
      57                 : #include "nsIDocument.h"
      58                 : #include "nsIHTMLDocument.h"
      59                 : #include "nsImageMap.h"
      60                 : #include "nsILinkHandler.h"
      61                 : #include "nsIURL.h"
      62                 : #include "nsILoadGroup.h"
      63                 : #include "nsContainerFrame.h"
      64                 : #include "prprf.h"
      65                 : #include "nsCSSRendering.h"
      66                 : #include "nsIDOMHTMLImageElement.h"
      67                 : #include "nsINameSpaceManager.h"
      68                 : #include "nsTextFragment.h"
      69                 : #include "nsIDOMHTMLMapElement.h"
      70                 : #include "nsIDOMDocument.h"
      71                 : #include "nsTransform2D.h"
      72                 : #include "nsITheme.h"
      73                 : #include "nsIImageLoadingContent.h"
      74                 : 
      75                 : #include "nsIServiceManager.h"
      76                 : #include "nsIURI.h"
      77                 : #include "nsNetUtil.h"
      78                 : #include "nsThreadUtils.h"
      79                 : #include "nsGUIEvent.h"
      80                 : #include "nsEventDispatcher.h"
      81                 : #include "nsDisplayList.h"
      82                 : 
      83                 : #include "nsContentUtils.h"
      84                 : 
      85                 : #define ONLOAD_CALLED_TOO_EARLY 1
      86                 : 
      87                 : class nsImageBoxFrameEvent : public nsRunnable
      88               0 : {
      89                 : public:
      90               0 :   nsImageBoxFrameEvent(nsIContent *content, PRUint32 message)
      91               0 :     : mContent(content), mMessage(message) {}
      92                 : 
      93                 :   NS_IMETHOD Run();
      94                 : 
      95                 : private:
      96                 :   nsCOMPtr<nsIContent> mContent;
      97                 :   PRUint32 mMessage;
      98                 : };
      99                 : 
     100                 : NS_IMETHODIMP
     101               0 : nsImageBoxFrameEvent::Run()
     102                 : {
     103               0 :   nsIPresShell *pres_shell = mContent->OwnerDoc()->GetShell();
     104               0 :   if (!pres_shell) {
     105               0 :     return NS_OK;
     106                 :   }
     107                 : 
     108               0 :   nsRefPtr<nsPresContext> pres_context = pres_shell->GetPresContext();
     109               0 :   if (!pres_context) {
     110               0 :     return NS_OK;
     111                 :   }
     112                 : 
     113               0 :   nsEventStatus status = nsEventStatus_eIgnore;
     114               0 :   nsEvent event(true, mMessage);
     115                 : 
     116               0 :   event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
     117               0 :   nsEventDispatcher::Dispatch(mContent, pres_context, &event, nsnull, &status);
     118               0 :   return NS_OK;
     119                 : }
     120                 : 
     121                 : // Fire off an event that'll asynchronously call the image elements
     122                 : // onload handler once handled. This is needed since the image library
     123                 : // can't decide if it wants to call it's observer methods
     124                 : // synchronously or asynchronously. If an image is loaded from the
     125                 : // cache the notifications come back synchronously, but if the image
     126                 : // is loaded from the netswork the notifications come back
     127                 : // asynchronously.
     128                 : 
     129                 : void
     130               0 : FireImageDOMEvent(nsIContent* aContent, PRUint32 aMessage)
     131                 : {
     132               0 :   NS_ASSERTION(aMessage == NS_LOAD || aMessage == NS_LOAD_ERROR,
     133                 :                "invalid message");
     134                 : 
     135               0 :   nsCOMPtr<nsIRunnable> event = new nsImageBoxFrameEvent(aContent, aMessage);
     136               0 :   if (NS_FAILED(NS_DispatchToCurrentThread(event)))
     137               0 :     NS_WARNING("failed to dispatch image event");
     138               0 : }
     139                 : 
     140                 : //
     141                 : // NS_NewImageBoxFrame
     142                 : //
     143                 : // Creates a new image frame and returns it
     144                 : //
     145                 : nsIFrame*
     146               0 : NS_NewImageBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
     147                 : {
     148               0 :   return new (aPresShell) nsImageBoxFrame (aPresShell, aContext);
     149                 : }
     150                 : 
     151               0 : NS_IMPL_FRAMEARENA_HELPERS(nsImageBoxFrame)
     152                 : 
     153                 : NS_IMETHODIMP
     154               0 : nsImageBoxFrame::AttributeChanged(PRInt32 aNameSpaceID,
     155                 :                                   nsIAtom* aAttribute,
     156                 :                                   PRInt32 aModType)
     157                 : {
     158                 :   nsresult rv = nsLeafBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
     159               0 :                                                  aModType);
     160                 : 
     161               0 :   if (aAttribute == nsGkAtoms::src) {
     162               0 :     UpdateImage();
     163               0 :     PresContext()->PresShell()->
     164               0 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
     165                 :   }
     166               0 :   else if (aAttribute == nsGkAtoms::validate)
     167               0 :     UpdateLoadFlags();
     168                 : 
     169               0 :   return rv;
     170                 : }
     171                 : 
     172               0 : nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
     173                 :   nsLeafBoxFrame(aShell, aContext),
     174                 :   mIntrinsicSize(0,0),
     175                 :   mRequestRegistered(false),
     176                 :   mLoadFlags(nsIRequest::LOAD_NORMAL),
     177                 :   mUseSrcAttr(false),
     178               0 :   mSuppressStyleCheck(false)
     179                 : {
     180               0 :   MarkIntrinsicWidthsDirty();
     181               0 : }
     182                 : 
     183               0 : nsImageBoxFrame::~nsImageBoxFrame()
     184                 : {
     185               0 : }
     186                 : 
     187                 : 
     188                 : /* virtual */ void
     189               0 : nsImageBoxFrame::MarkIntrinsicWidthsDirty()
     190                 : {
     191               0 :   SizeNeedsRecalc(mImageSize);
     192               0 :   nsLeafBoxFrame::MarkIntrinsicWidthsDirty();
     193               0 : }
     194                 : 
     195                 : void
     196               0 : nsImageBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
     197                 : {
     198               0 :   if (mImageRequest) {
     199                 :     nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
     200               0 :                                           &mRequestRegistered);
     201                 : 
     202                 :     // Release image loader first so that it's refcnt can go to zero
     203               0 :     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     204                 :   }
     205                 : 
     206               0 :   if (mListener)
     207               0 :     reinterpret_cast<nsImageBoxListener*>(mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
     208                 : 
     209               0 :   nsLeafBoxFrame::DestroyFrom(aDestructRoot);
     210               0 : }
     211                 : 
     212                 : 
     213                 : NS_IMETHODIMP
     214               0 : nsImageBoxFrame::Init(nsIContent*      aContent,
     215                 :                       nsIFrame*        aParent,
     216                 :                       nsIFrame*        aPrevInFlow)
     217                 : {
     218               0 :   if (!mListener) {
     219               0 :     nsImageBoxListener *listener = new nsImageBoxListener();
     220               0 :     NS_ADDREF(listener);
     221               0 :     listener->SetFrame(this);
     222               0 :     listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener));
     223               0 :     NS_RELEASE(listener);
     224                 :   }
     225                 : 
     226               0 :   mSuppressStyleCheck = true;
     227               0 :   nsresult rv = nsLeafBoxFrame::Init(aContent, aParent, aPrevInFlow);
     228               0 :   mSuppressStyleCheck = false;
     229                 : 
     230               0 :   UpdateLoadFlags();
     231               0 :   UpdateImage();
     232                 : 
     233               0 :   return rv;
     234                 : }
     235                 : 
     236                 : void
     237               0 : nsImageBoxFrame::UpdateImage()
     238                 : {
     239               0 :   nsPresContext* presContext = PresContext();
     240                 : 
     241               0 :   if (mImageRequest) {
     242                 :     nsLayoutUtils::DeregisterImageRequest(presContext, mImageRequest,
     243               0 :                                           &mRequestRegistered);
     244               0 :     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     245               0 :     mImageRequest = nsnull;
     246                 :   }
     247                 : 
     248                 :   // get the new image src
     249               0 :   nsAutoString src;
     250               0 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
     251               0 :   mUseSrcAttr = !src.IsEmpty();
     252               0 :   if (mUseSrcAttr) {
     253               0 :     nsIDocument* doc = mContent->GetDocument();
     254               0 :     if (!doc) {
     255                 :       // No need to do anything here...
     256                 :       return;
     257                 :     }
     258               0 :     nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
     259               0 :     nsCOMPtr<nsIURI> uri;
     260               0 :     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
     261                 :                                               src,
     262                 :                                               doc,
     263               0 :                                               baseURI);
     264                 : 
     265               0 :     if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
     266               0 :                                             mContent->NodePrincipal())) {
     267                 :       nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
     268                 :                                 doc->GetDocumentURI(), mListener, mLoadFlags,
     269               0 :                                 getter_AddRefs(mImageRequest));
     270                 : 
     271               0 :       if (mImageRequest) {
     272                 :         nsLayoutUtils::RegisterImageRequestIfAnimated(presContext,
     273                 :                                                       mImageRequest,
     274               0 :                                                       &mRequestRegistered);
     275                 :       }
     276                 :     }
     277                 :   } else {
     278                 :     // Only get the list-style-image if we aren't being drawn
     279                 :     // by a native theme.
     280               0 :     PRUint8 appearance = GetStyleDisplay()->mAppearance;
     281               0 :     if (!(appearance && nsBox::gTheme &&
     282               0 :           nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) {
     283                 :       // get the list-style-image
     284               0 :       imgIRequest *styleRequest = GetStyleList()->GetListStyleImage();
     285               0 :       if (styleRequest) {
     286               0 :         styleRequest->Clone(mListener, getter_AddRefs(mImageRequest));
     287                 :       }
     288                 :     }
     289                 :   }
     290                 : 
     291               0 :   if (!mImageRequest) {
     292                 :     // We have no image, so size to 0
     293               0 :     mIntrinsicSize.SizeTo(0, 0);
     294                 :   } else {
     295                 :     // We don't want discarding or decode-on-draw for xul images.
     296               0 :     mImageRequest->RequestDecode();
     297               0 :     mImageRequest->LockImage();
     298                 :   }
     299                 : }
     300                 : 
     301                 : void
     302               0 : nsImageBoxFrame::UpdateLoadFlags()
     303                 : {
     304                 :   static nsIContent::AttrValuesArray strings[] =
     305                 :     {&nsGkAtoms::always, &nsGkAtoms::never, nsnull};
     306               0 :   switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::validate,
     307               0 :                                     strings, eCaseMatters)) {
     308                 :     case 0:
     309               0 :       mLoadFlags = nsIRequest::VALIDATE_ALWAYS;
     310               0 :       break;
     311                 :     case 1:
     312               0 :       mLoadFlags = nsIRequest::VALIDATE_NEVER|nsIRequest::LOAD_FROM_CACHE;
     313               0 :       break;
     314                 :     default:
     315               0 :       mLoadFlags = nsIRequest::LOAD_NORMAL;
     316               0 :       break;
     317                 :   }
     318               0 : }
     319                 : 
     320                 : class nsDisplayXULImage : public nsDisplayItem {
     321                 : public:
     322               0 :   nsDisplayXULImage(nsDisplayListBuilder* aBuilder,
     323                 :                     nsImageBoxFrame* aFrame) :
     324               0 :     nsDisplayItem(aBuilder, aFrame) {
     325               0 :     MOZ_COUNT_CTOR(nsDisplayXULImage);
     326               0 :   }
     327                 : #ifdef NS_BUILD_REFCNT_LOGGING
     328               0 :   virtual ~nsDisplayXULImage() {
     329               0 :     MOZ_COUNT_DTOR(nsDisplayXULImage);
     330               0 :   }
     331                 : #endif
     332                 : 
     333                 :   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
     334                 :   // event receiver for us
     335                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     336                 :                      nsRenderingContext* aCtx);
     337               0 :   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
     338                 : };
     339                 : 
     340               0 : void nsDisplayXULImage::Paint(nsDisplayListBuilder* aBuilder,
     341                 :                               nsRenderingContext* aCtx)
     342                 : {
     343                 :   static_cast<nsImageBoxFrame*>(mFrame)->
     344               0 :     PaintImage(*aCtx, mVisibleRect, ToReferenceFrame(),
     345               0 :                aBuilder->ShouldSyncDecodeImages()
     346                 :                  ? (PRUint32) imgIContainer::FLAG_SYNC_DECODE
     347               0 :                  : (PRUint32) imgIContainer::FLAG_NONE);
     348               0 : }
     349                 : 
     350                 : NS_IMETHODIMP
     351               0 : nsImageBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     352                 :                                   const nsRect&           aDirtyRect,
     353                 :                                   const nsDisplayListSet& aLists)
     354                 : {
     355               0 :   nsresult rv = nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
     356               0 :   NS_ENSURE_SUCCESS(rv, rv);
     357                 : 
     358               0 :   if ((0 == mRect.width) || (0 == mRect.height)) {
     359                 :     // Do not render when given a zero area. This avoids some useless
     360                 :     // scaling work while we wait for our image dimensions to arrive
     361                 :     // asynchronously.
     362               0 :     return NS_OK;
     363                 :   }
     364                 : 
     365               0 :   if (!IsVisibleForPainting(aBuilder))
     366               0 :     return NS_OK;
     367                 : 
     368                 :   return aLists.Content()->AppendNewToTop(
     369               0 :       new (aBuilder) nsDisplayXULImage(aBuilder, this));
     370                 : }
     371                 : 
     372                 : void
     373               0 : nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext,
     374                 :                             const nsRect& aDirtyRect, nsPoint aPt,
     375                 :                             PRUint32 aFlags)
     376                 : {
     377               0 :   nsRect rect;
     378               0 :   GetClientRect(rect);
     379                 : 
     380               0 :   rect += aPt;
     381                 : 
     382               0 :   if (!mImageRequest)
     383                 :     return;
     384                 : 
     385                 :   // don't draw if the image is not dirty
     386               0 :   nsRect dirty;
     387               0 :   if (!dirty.IntersectRect(aDirtyRect, rect))
     388                 :     return;
     389                 : 
     390               0 :   nsCOMPtr<imgIContainer> imgCon;
     391               0 :   mImageRequest->GetImage(getter_AddRefs(imgCon));
     392                 : 
     393               0 :   if (imgCon) {
     394               0 :     bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0);
     395                 :     nsLayoutUtils::DrawSingleImage(&aRenderingContext, imgCon,
     396                 :         nsLayoutUtils::GetGraphicsFilterForFrame(this),
     397               0 :         rect, dirty, aFlags, hasSubRect ? &mSubRect : nsnull);
     398                 :   }
     399                 : }
     400                 : 
     401                 : 
     402                 : //
     403                 : // DidSetStyleContext
     404                 : //
     405                 : // When the style context changes, make sure that all of our image is up to date.
     406                 : //
     407                 : /* virtual */ void
     408               0 : nsImageBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     409                 : {
     410               0 :   nsLeafBoxFrame::DidSetStyleContext(aOldStyleContext);
     411                 : 
     412                 :   // Fetch our subrect.
     413               0 :   const nsStyleList* myList = GetStyleList();
     414               0 :   mSubRect = myList->mImageRegion; // before |mSuppressStyleCheck| test!
     415                 : 
     416               0 :   if (mUseSrcAttr || mSuppressStyleCheck)
     417               0 :     return; // No more work required, since the image isn't specified by style.
     418                 : 
     419                 :   // If we're using a native theme implementation, we shouldn't draw anything.
     420               0 :   const nsStyleDisplay* disp = GetStyleDisplay();
     421               0 :   if (disp->mAppearance && nsBox::gTheme &&
     422               0 :       nsBox::gTheme->ThemeSupportsWidget(nsnull, this, disp->mAppearance))
     423               0 :     return;
     424                 : 
     425                 :   // If list-style-image changes, we have a new image.
     426               0 :   nsCOMPtr<nsIURI> oldURI, newURI;
     427               0 :   if (mImageRequest)
     428               0 :     mImageRequest->GetURI(getter_AddRefs(oldURI));
     429               0 :   if (myList->GetListStyleImage())
     430               0 :     myList->GetListStyleImage()->GetURI(getter_AddRefs(newURI));
     431                 :   bool equal;
     432               0 :   if (newURI == oldURI ||   // handles null==null
     433               0 :       (newURI && oldURI &&
     434               0 :        NS_SUCCEEDED(newURI->Equals(oldURI, &equal)) && equal))
     435                 :     return;
     436                 : 
     437               0 :   UpdateImage();
     438                 : } // DidSetStyleContext
     439                 : 
     440                 : void
     441               0 : nsImageBoxFrame::GetImageSize()
     442                 : {
     443               0 :   if (mIntrinsicSize.width > 0 && mIntrinsicSize.height > 0) {
     444               0 :     mImageSize.width = mIntrinsicSize.width;
     445               0 :     mImageSize.height = mIntrinsicSize.height;
     446                 :   } else {
     447               0 :     mImageSize.width = 0;
     448               0 :     mImageSize.height = 0;
     449                 :   }
     450               0 : }
     451                 : 
     452                 : /**
     453                 :  * Ok return our dimensions
     454                 :  */
     455                 : nsSize
     456               0 : nsImageBoxFrame::GetPrefSize(nsBoxLayoutState& aState)
     457                 : {
     458               0 :   nsSize size(0,0);
     459               0 :   DISPLAY_PREF_SIZE(this, size);
     460               0 :   if (DoesNeedRecalc(mImageSize))
     461               0 :      GetImageSize();
     462                 : 
     463               0 :   if (!mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0))
     464               0 :     size = nsSize(mSubRect.width, mSubRect.height);
     465                 :   else
     466               0 :     size = mImageSize;
     467                 : 
     468               0 :   nsSize intrinsicSize = size;
     469                 : 
     470               0 :   nsMargin borderPadding(0,0,0,0);
     471               0 :   GetBorderAndPadding(borderPadding);
     472               0 :   size.width += borderPadding.LeftRight();
     473               0 :   size.height += borderPadding.TopBottom();
     474                 : 
     475                 :   bool widthSet, heightSet;
     476               0 :   nsIBox::AddCSSPrefSize(this, size, widthSet, heightSet);
     477               0 :   NS_ASSERTION(size.width != NS_INTRINSICSIZE && size.height != NS_INTRINSICSIZE,
     478                 :                "non-intrinsic size expected");
     479                 : 
     480               0 :   nsSize minSize = GetMinSize(aState);
     481               0 :   nsSize maxSize = GetMaxSize(aState);
     482                 : 
     483               0 :   if (!widthSet && !heightSet) {
     484               0 :     if (minSize.width != NS_INTRINSICSIZE)
     485               0 :       minSize.width -= borderPadding.LeftRight();
     486               0 :     if (minSize.height != NS_INTRINSICSIZE)
     487               0 :       minSize.height -= borderPadding.TopBottom();
     488               0 :     if (maxSize.width != NS_INTRINSICSIZE)
     489               0 :       maxSize.width -= borderPadding.LeftRight();
     490               0 :     if (maxSize.height != NS_INTRINSICSIZE)
     491               0 :       maxSize.height -= borderPadding.TopBottom();
     492                 : 
     493                 :     size = nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(minSize.width, minSize.height,
     494                 :                                                                  maxSize.width, maxSize.height,
     495               0 :                                                                  intrinsicSize.width, intrinsicSize.height);
     496               0 :     NS_ASSERTION(size.width != NS_INTRINSICSIZE && size.height != NS_INTRINSICSIZE,
     497                 :                  "non-intrinsic size expected");
     498               0 :     size.width += borderPadding.LeftRight();
     499               0 :     size.height += borderPadding.TopBottom();
     500               0 :     return size;
     501                 :   }
     502                 : 
     503               0 :   if (!widthSet) {
     504               0 :     if (intrinsicSize.height > 0) {
     505                 :       // Subtract off the border and padding from the height because the
     506                 :       // content-box needs to be used to determine the ratio
     507               0 :       nscoord height = size.height - borderPadding.TopBottom();
     508                 :       size.width = nscoord(PRInt64(height) * PRInt64(intrinsicSize.width) /
     509               0 :                            PRInt64(intrinsicSize.height));
     510                 :     }
     511                 :     else {
     512               0 :       size.width = intrinsicSize.width;
     513                 :     }
     514                 : 
     515               0 :     size.width += borderPadding.LeftRight();
     516                 :   }
     517               0 :   else if (!heightSet) {
     518               0 :     if (intrinsicSize.width > 0) {
     519               0 :       nscoord width = size.width - borderPadding.LeftRight();
     520                 :       size.height = nscoord(PRInt64(width) * PRInt64(intrinsicSize.height) /
     521               0 :                             PRInt64(intrinsicSize.width));
     522                 :     }
     523                 :     else {
     524               0 :       size.height = intrinsicSize.height;
     525                 :     }
     526                 : 
     527               0 :     size.height += borderPadding.TopBottom();
     528                 :   }
     529                 : 
     530               0 :   return BoundsCheck(minSize, size, maxSize);
     531                 : }
     532                 : 
     533                 : nsSize
     534               0 : nsImageBoxFrame::GetMinSize(nsBoxLayoutState& aState)
     535                 : {
     536                 :   // An image can always scale down to (0,0).
     537               0 :   nsSize size(0,0);
     538               0 :   DISPLAY_MIN_SIZE(this, size);
     539               0 :   AddBorderAndPadding(size);
     540                 :   bool widthSet, heightSet;
     541               0 :   nsIBox::AddCSSMinSize(aState, this, size, widthSet, heightSet);
     542                 :   return size;
     543                 : }
     544                 : 
     545                 : nscoord
     546               0 : nsImageBoxFrame::GetBoxAscent(nsBoxLayoutState& aState)
     547                 : {
     548               0 :   return GetPrefSize(aState).height;
     549                 : }
     550                 : 
     551                 : nsIAtom*
     552               0 : nsImageBoxFrame::GetType() const
     553                 : {
     554               0 :   return nsGkAtoms::imageBoxFrame;
     555                 : }
     556                 : 
     557                 : #ifdef DEBUG
     558                 : NS_IMETHODIMP
     559               0 : nsImageBoxFrame::GetFrameName(nsAString& aResult) const
     560                 : {
     561               0 :   return MakeFrameName(NS_LITERAL_STRING("ImageBox"), aResult);
     562                 : }
     563                 : #endif
     564                 : 
     565                 : 
     566               0 : NS_IMETHODIMP nsImageBoxFrame::OnStartContainer(imgIRequest *request,
     567                 :                                                 imgIContainer *image)
     568                 : {
     569               0 :   NS_ENSURE_ARG_POINTER(image);
     570                 : 
     571                 :   // Ensure the animation (if any) is started. Note: There is no
     572                 :   // corresponding call to Decrement for this. This Increment will be
     573                 :   // 'cleaned up' by the Request when it is destroyed, but only then.
     574               0 :   request->IncrementAnimationConsumers();
     575                 : 
     576                 :   nscoord w, h;
     577               0 :   image->GetWidth(&w);
     578               0 :   image->GetHeight(&h);
     579                 : 
     580                 :   mIntrinsicSize.SizeTo(nsPresContext::CSSPixelsToAppUnits(w),
     581               0 :                         nsPresContext::CSSPixelsToAppUnits(h));
     582                 : 
     583               0 :   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     584               0 :     PresContext()->PresShell()->
     585               0 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
     586                 :   }
     587                 : 
     588               0 :   return NS_OK;
     589                 : }
     590                 : 
     591               0 : NS_IMETHODIMP nsImageBoxFrame::OnStopContainer(imgIRequest *request,
     592                 :                                                imgIContainer *image)
     593                 : {
     594               0 :   nsBoxLayoutState state(PresContext());
     595               0 :   this->Redraw(state);
     596                 : 
     597               0 :   return NS_OK;
     598                 : }
     599                 : 
     600               0 : NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request,
     601                 :                                             nsresult aStatus,
     602                 :                                             const PRUnichar *statusArg)
     603                 : {
     604               0 :   if (NS_SUCCEEDED(aStatus))
     605                 :     // Fire an onload DOM event.
     606               0 :     FireImageDOMEvent(mContent, NS_LOAD);
     607                 :   else {
     608                 :     // Fire an onerror DOM event.
     609               0 :     mIntrinsicSize.SizeTo(0, 0);
     610               0 :     PresContext()->PresShell()->
     611               0 :       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
     612               0 :     FireImageDOMEvent(mContent, NS_LOAD_ERROR);
     613                 :   }
     614                 : 
     615               0 :   return NS_OK;
     616                 : }
     617                 : 
     618               0 : NS_IMETHODIMP nsImageBoxFrame::OnImageIsAnimated(imgIRequest *aRequest)
     619                 : {
     620                 :   // Register with our refresh driver, if we're animated.
     621                 :   nsLayoutUtils::RegisterImageRequest(PresContext(), aRequest,
     622               0 :                                       &mRequestRegistered);
     623                 : 
     624               0 :   return NS_OK;
     625                 : }
     626                 : 
     627               0 : NS_IMETHODIMP nsImageBoxFrame::FrameChanged(imgIRequest *aRequest,
     628                 :                                             imgIContainer *aContainer,
     629                 :                                             const nsIntRect *aDirtyRect)
     630                 : {
     631               0 :   nsBoxLayoutState state(PresContext());
     632               0 :   this->Redraw(state);
     633                 : 
     634               0 :   return NS_OK;
     635                 : }
     636                 : 
     637               0 : NS_IMPL_ISUPPORTS2(nsImageBoxListener, imgIDecoderObserver, imgIContainerObserver)
     638                 : 
     639               0 : nsImageBoxListener::nsImageBoxListener()
     640                 : {
     641               0 : }
     642                 : 
     643               0 : nsImageBoxListener::~nsImageBoxListener()
     644                 : {
     645               0 : }
     646                 : 
     647               0 : NS_IMETHODIMP nsImageBoxListener::OnStartContainer(imgIRequest *request,
     648                 :                                                    imgIContainer *image)
     649                 : {
     650               0 :   if (!mFrame)
     651               0 :     return NS_OK;
     652                 : 
     653               0 :   return mFrame->OnStartContainer(request, image);
     654                 : }
     655                 : 
     656               0 : NS_IMETHODIMP nsImageBoxListener::OnStopContainer(imgIRequest *request,
     657                 :                                                   imgIContainer *image)
     658                 : {
     659               0 :   if (!mFrame)
     660               0 :     return NS_OK;
     661                 : 
     662               0 :   return mFrame->OnStopContainer(request, image);
     663                 : }
     664                 : 
     665               0 : NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
     666                 :                                                nsresult status,
     667                 :                                                const PRUnichar *statusArg)
     668                 : {
     669               0 :   if (!mFrame)
     670               0 :     return NS_OK;
     671                 : 
     672               0 :   return mFrame->OnStopDecode(request, status, statusArg);
     673                 : }
     674                 : 
     675               0 : NS_IMETHODIMP nsImageBoxListener::OnImageIsAnimated(imgIRequest* aRequest)
     676                 : {
     677               0 :   if (!mFrame)
     678               0 :     return NS_OK;
     679                 : 
     680               0 :   return mFrame->OnImageIsAnimated(aRequest);
     681                 : }
     682                 : 
     683               0 : NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIRequest *aRequest,
     684                 :                                                imgIContainer *aContainer,
     685                 :                                                const nsIntRect *aDirtyRect)
     686                 : {
     687               0 :   if (!mFrame)
     688               0 :     return NS_ERROR_FAILURE;
     689                 : 
     690               0 :   return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect);
     691                 : }
     692                 : 

Generated by: LCOV version 1.7