LCOV - code coverage report
Current view: directory - layout/generic - nsHTMLCanvasFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 151 0 0.0 %
Date: 2012-06-02 Functions: 29 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                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2004
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *    Vladimir Vukicevic <vladimir@pobox.com> (original author)
      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 the HTML <canvas> element */
      40                 : 
      41                 : #include "nsHTMLParts.h"
      42                 : #include "nsCOMPtr.h"
      43                 : #include "nsIServiceManager.h"
      44                 : #include "nsGkAtoms.h"
      45                 : 
      46                 : #include "nsHTMLCanvasFrame.h"
      47                 : #include "nsHTMLCanvasElement.h"
      48                 : #include "nsDisplayList.h"
      49                 : #include "nsLayoutUtils.h"
      50                 : 
      51                 : #include "nsTransform2D.h"
      52                 : 
      53                 : #include "gfxContext.h"
      54                 : 
      55                 : #ifdef ACCESSIBILITY
      56                 : #include "nsAccessibilityService.h"
      57                 : #endif
      58                 : 
      59                 : using namespace mozilla;
      60                 : using namespace mozilla::layers;
      61                 : 
      62                 : static nsHTMLCanvasElement *
      63               0 : CanvasElementFromContent(nsIContent *content)
      64                 : {
      65               0 :   nsCOMPtr<nsIDOMHTMLCanvasElement> domCanvas(do_QueryInterface(content));
      66               0 :   return domCanvas ? static_cast<nsHTMLCanvasElement*>(domCanvas.get()) : nsnull;
      67                 : }
      68                 : 
      69                 : class nsDisplayCanvas : public nsDisplayItem {
      70                 : public:
      71               0 :   nsDisplayCanvas(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
      72               0 :     : nsDisplayItem(aBuilder, aFrame)
      73                 :   {
      74               0 :     MOZ_COUNT_CTOR(nsDisplayCanvas);
      75               0 :   }
      76                 : #ifdef NS_BUILD_REFCNT_LOGGING
      77               0 :   virtual ~nsDisplayCanvas() {
      78               0 :     MOZ_COUNT_DTOR(nsDisplayCanvas);
      79               0 :   }
      80                 : #endif
      81                 : 
      82               0 :   NS_DISPLAY_DECL_NAME("nsDisplayCanvas", TYPE_CANVAS)
      83                 : 
      84               0 :   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
      85                 :                                    bool* aForceTransparentSurface = nsnull) {
      86               0 :     if (aForceTransparentSurface) {
      87               0 :       *aForceTransparentSurface = false;
      88                 :     }
      89               0 :     nsIFrame* f = GetUnderlyingFrame();
      90               0 :     nsHTMLCanvasElement *canvas = CanvasElementFromContent(f->GetContent());
      91               0 :     nsRegion result;
      92               0 :     if (canvas->GetIsOpaque()) {
      93               0 :       result = GetBounds(aBuilder);
      94                 :     }
      95                 :     return result;
      96                 :   }
      97                 : 
      98               0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
      99               0 :     nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
     100               0 :     return f->GetInnerArea() + ToReferenceFrame();
     101                 :   }
     102                 : 
     103               0 :   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
     104                 :                                              LayerManager* aManager,
     105                 :                                              const ContainerParameters& aContainerParameters)
     106                 :   {
     107                 :     return static_cast<nsHTMLCanvasFrame*>(mFrame)->
     108               0 :       BuildLayer(aBuilder, aManager, this);
     109                 :   }
     110               0 :   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
     111                 :                                    LayerManager* aManager)
     112                 :   {
     113               0 :     if (CanvasElementFromContent(mFrame->GetContent())->ShouldForceInactiveLayer(aManager))
     114               0 :       return LAYER_INACTIVE;
     115                 : 
     116                 :     // If compositing is cheap, just do that
     117               0 :     if (aManager->IsCompositingCheap())
     118               0 :       return mozilla::LAYER_ACTIVE;
     119                 : 
     120               0 :     return mFrame->AreLayersMarkedActive() ? LAYER_ACTIVE : LAYER_INACTIVE;
     121                 :   }
     122                 : };
     123                 : 
     124                 : 
     125                 : nsIFrame*
     126               0 : NS_NewHTMLCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     127                 : {
     128               0 :   return new (aPresShell) nsHTMLCanvasFrame(aContext);
     129                 : }
     130                 : 
     131               0 : NS_IMPL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame)
     132                 : 
     133                 : NS_IMETHODIMP
     134               0 : nsHTMLCanvasFrame::Init(nsIContent* aContent,
     135                 :                         nsIFrame*   aParent,
     136                 :                         nsIFrame*   aPrevInFlow)
     137                 : {
     138               0 :   nsresult rv = nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
     139                 : 
     140                 :   // We can fill in the canvas before the canvas frame is created, in
     141                 :   // which case we never get around to marking the layer active. Therefore,
     142                 :   // we mark it active here when we create the frame.
     143               0 :   MarkLayersActive(nsChangeHint(0));
     144                 : 
     145               0 :   return rv;
     146                 : }
     147                 : 
     148               0 : nsHTMLCanvasFrame::~nsHTMLCanvasFrame()
     149                 : {
     150               0 : }
     151                 : 
     152                 : nsIntSize
     153               0 : nsHTMLCanvasFrame::GetCanvasSize()
     154                 : {
     155               0 :   nsIntSize size(0,0);
     156               0 :   nsHTMLCanvasElement *canvas = CanvasElementFromContent(GetContent());
     157               0 :   if (canvas) {
     158               0 :     size = canvas->GetSize();
     159                 :   } else {
     160               0 :     NS_NOTREACHED("couldn't get canvas size");
     161                 :   }
     162                 : 
     163                 :   return size;
     164                 : }
     165                 : 
     166                 : /* virtual */ nscoord
     167               0 : nsHTMLCanvasFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     168                 : {
     169                 :   // XXX The caller doesn't account for constraints of the height,
     170                 :   // min-height, and max-height properties.
     171               0 :   nscoord result = nsPresContext::CSSPixelsToAppUnits(GetCanvasSize().width);
     172               0 :   DISPLAY_MIN_WIDTH(this, result);
     173               0 :   return result;
     174                 : }
     175                 : 
     176                 : /* virtual */ nscoord
     177               0 : nsHTMLCanvasFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     178                 : {
     179                 :   // XXX The caller doesn't account for constraints of the height,
     180                 :   // min-height, and max-height properties.
     181               0 :   nscoord result = nsPresContext::CSSPixelsToAppUnits(GetCanvasSize().width);
     182               0 :   DISPLAY_PREF_WIDTH(this, result);
     183               0 :   return result;
     184                 : }
     185                 : 
     186                 : /* virtual */ nsSize
     187               0 : nsHTMLCanvasFrame::GetIntrinsicRatio()
     188                 : {
     189               0 :   nsIntSize size(GetCanvasSize());
     190                 :   return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width),
     191               0 :                 nsPresContext::CSSPixelsToAppUnits(size.height));
     192                 : }
     193                 : 
     194                 : /* virtual */ nsSize
     195               0 : nsHTMLCanvasFrame::ComputeSize(nsRenderingContext *aRenderingContext,
     196                 :                                nsSize aCBSize, nscoord aAvailableWidth,
     197                 :                                nsSize aMargin, nsSize aBorder, nsSize aPadding,
     198                 :                                bool aShrinkWrap)
     199                 : {
     200               0 :   nsIntSize size = GetCanvasSize();
     201                 : 
     202               0 :   IntrinsicSize intrinsicSize;
     203               0 :   intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.width));
     204               0 :   intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.height));
     205                 : 
     206               0 :   nsSize intrinsicRatio = GetIntrinsicRatio(); // won't actually be used
     207                 : 
     208                 :   return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
     209                 :                             aRenderingContext, this,
     210                 :                             intrinsicSize, intrinsicRatio, aCBSize,
     211               0 :                             aMargin, aBorder, aPadding);
     212                 : }
     213                 : 
     214                 : NS_IMETHODIMP
     215               0 : nsHTMLCanvasFrame::Reflow(nsPresContext*           aPresContext,
     216                 :                           nsHTMLReflowMetrics&     aMetrics,
     217                 :                           const nsHTMLReflowState& aReflowState,
     218                 :                           nsReflowStatus&          aStatus)
     219                 : {
     220               0 :   DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame");
     221               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
     222               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     223                 :                   ("enter nsHTMLCanvasFrame::Reflow: availSize=%d,%d",
     224                 :                   aReflowState.availableWidth, aReflowState.availableHeight));
     225                 : 
     226               0 :   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
     227                 : 
     228               0 :   aStatus = NS_FRAME_COMPLETE;
     229                 : 
     230               0 :   aMetrics.width = aReflowState.ComputedWidth();
     231               0 :   aMetrics.height = aReflowState.ComputedHeight();
     232                 : 
     233                 :   // stash this away so we can compute our inner area later
     234               0 :   mBorderPadding   = aReflowState.mComputedBorderPadding;
     235                 : 
     236               0 :   aMetrics.width += mBorderPadding.left + mBorderPadding.right;
     237               0 :   aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
     238                 : 
     239               0 :   if (GetPrevInFlow()) {
     240               0 :     nscoord y = GetContinuationOffset(&aMetrics.width);
     241               0 :     aMetrics.height -= y + mBorderPadding.top;
     242               0 :     aMetrics.height = NS_MAX(0, aMetrics.height);
     243                 :   }
     244                 : 
     245               0 :   aMetrics.SetOverflowAreasToDesiredBounds();
     246               0 :   FinishAndStoreOverflow(&aMetrics);
     247                 : 
     248               0 :   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
     249               0 :     Invalidate(nsRect(0, 0, mRect.width, mRect.height));
     250                 :   }
     251                 : 
     252                 :   // Reflow the single anon block child.
     253                 :   nsReflowStatus childStatus;
     254               0 :   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
     255               0 :   nsIFrame* childFrame = mFrames.FirstChild();
     256               0 :   NS_ASSERTION(!childFrame->GetNextSibling(), "HTML canvas should have 1 kid");
     257               0 :   nsHTMLReflowMetrics childDesiredSize(aMetrics.mFlags);
     258                 :   nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame,
     259               0 :                                      availSize);
     260                 :   ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState,
     261               0 :               0, 0, 0, childStatus, nsnull);
     262                 :   FinishReflowChild(childFrame, aPresContext, &childReflowState,
     263               0 :                     childDesiredSize, 0, 0, 0);
     264                 : 
     265               0 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     266                 :                   ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d",
     267                 :                   aMetrics.width, aMetrics.height));
     268               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
     269                 : 
     270               0 :   return NS_OK;
     271                 : }
     272                 : 
     273                 : // FIXME taken from nsImageFrame, but then had splittable frame stuff
     274                 : // removed.  That needs to be fixed.
     275                 : nsRect 
     276               0 : nsHTMLCanvasFrame::GetInnerArea() const
     277                 : {
     278               0 :   nsRect r;
     279               0 :   r.x = mBorderPadding.left;
     280               0 :   r.y = mBorderPadding.top;
     281               0 :   r.width = mRect.width - mBorderPadding.left - mBorderPadding.right;
     282               0 :   r.height = mRect.height - mBorderPadding.top - mBorderPadding.bottom;
     283                 :   return r;
     284                 : }
     285                 : 
     286                 : already_AddRefed<Layer>
     287               0 : nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
     288                 :                               LayerManager* aManager,
     289                 :                               nsDisplayItem* aItem)
     290                 : {
     291               0 :   nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
     292               0 :   nsHTMLCanvasElement* element = static_cast<nsHTMLCanvasElement*>(GetContent());
     293               0 :   nsIntSize canvasSize = GetCanvasSize();
     294                 : 
     295               0 :   if (canvasSize.width <= 0 || canvasSize.height <= 0 || area.IsEmpty())
     296               0 :     return nsnull;
     297                 : 
     298                 :   CanvasLayer* oldLayer = static_cast<CanvasLayer*>
     299               0 :     (aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
     300               0 :   nsRefPtr<CanvasLayer> layer = element->GetCanvasLayer(aBuilder, oldLayer, aManager);
     301               0 :   if (!layer)
     302               0 :     return nsnull;
     303                 : 
     304               0 :   nsPresContext* presContext = PresContext();
     305                 :   gfxRect r = gfxRect(presContext->AppUnitsToGfxUnits(area.x),
     306                 :                       presContext->AppUnitsToGfxUnits(area.y),
     307                 :                       presContext->AppUnitsToGfxUnits(area.width),
     308               0 :                       presContext->AppUnitsToGfxUnits(area.height));
     309                 : 
     310                 :   // Transform the canvas into the right place
     311               0 :   gfxMatrix transform;
     312               0 :   transform.Translate(r.TopLeft());
     313               0 :   transform.Scale(r.Width()/canvasSize.width, r.Height()/canvasSize.height);
     314               0 :   layer->SetTransform(gfx3DMatrix::From2D(transform));
     315               0 :   layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
     316               0 :   layer->SetVisibleRegion(nsIntRect(0, 0, canvasSize.width, canvasSize.height));
     317                 : 
     318               0 :   return layer.forget();
     319                 : }
     320                 : 
     321                 : NS_IMETHODIMP
     322               0 : nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     323                 :                                     const nsRect&           aDirtyRect,
     324                 :                                     const nsDisplayListSet& aLists)
     325                 : {
     326               0 :   if (!IsVisibleForPainting(aBuilder))
     327               0 :     return NS_OK;
     328                 : 
     329               0 :   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
     330               0 :   NS_ENSURE_SUCCESS(rv, rv);
     331                 : 
     332               0 :   nsDisplayList replacedContent;
     333                 : 
     334                 :   rv = replacedContent.AppendNewToTop(
     335               0 :       new (aBuilder) nsDisplayCanvas(aBuilder, this));
     336               0 :   NS_ENSURE_SUCCESS(rv, rv);
     337                 : 
     338                 :   rv = DisplaySelectionOverlay(aBuilder, &replacedContent,
     339               0 :                                nsISelectionDisplay::DISPLAY_IMAGES);
     340               0 :   NS_ENSURE_SUCCESS(rv, rv);
     341                 : 
     342               0 :   WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
     343                 : 
     344               0 :   return NS_OK;
     345                 : }
     346                 : 
     347                 : nsIAtom*
     348               0 : nsHTMLCanvasFrame::GetType() const
     349                 : {
     350               0 :   return nsGkAtoms::HTMLCanvasFrame;
     351                 : }
     352                 : 
     353                 : // get the offset into the content area of the image where aImg starts if it is a continuation.
     354                 : // from nsImageFrame
     355                 : nscoord 
     356               0 : nsHTMLCanvasFrame::GetContinuationOffset(nscoord* aWidth) const
     357                 : {
     358               0 :   nscoord offset = 0;
     359               0 :   if (aWidth) {
     360               0 :     *aWidth = 0;
     361                 :   }
     362                 : 
     363               0 :   if (GetPrevInFlow()) {
     364               0 :     for (nsIFrame* prevInFlow = GetPrevInFlow() ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) {
     365               0 :       nsRect rect = prevInFlow->GetRect();
     366               0 :       if (aWidth) {
     367               0 :         *aWidth = rect.width;
     368                 :       }
     369               0 :       offset += rect.height;
     370                 :     }
     371               0 :     offset -= mBorderPadding.top;
     372               0 :     offset = NS_MAX(0, offset);
     373                 :   }
     374               0 :   return offset;
     375                 : }
     376                 : 
     377                 : #ifdef ACCESSIBILITY
     378                 : already_AddRefed<nsAccessible>
     379               0 : nsHTMLCanvasFrame::CreateAccessible()
     380                 : {
     381               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
     382               0 :   if (accService) {
     383               0 :     return accService->CreateHTMLCanvasAccessible(mContent, PresContext()->PresShell());
     384                 :   }
     385               0 :   return nsnull;
     386                 : }
     387                 : #endif
     388                 : 
     389                 : #ifdef DEBUG
     390                 : NS_IMETHODIMP
     391               0 : nsHTMLCanvasFrame::GetFrameName(nsAString& aResult) const
     392                 : {
     393               0 :   return MakeFrameName(NS_LITERAL_STRING("HTMLCanvas"), aResult);
     394                 : }
     395                 : #endif
     396                 : 

Generated by: LCOV version 1.7