LCOV - code coverage report
Current view: top level - layout/generic - nsBulletFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 685 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 79 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* rendering object for list-item bullets */
       7             : 
       8             : #include "nsBulletFrame.h"
       9             : 
      10             : #include "gfx2DGlue.h"
      11             : #include "gfxContext.h"
      12             : #include "gfxPrefs.h"
      13             : #include "gfxUtils.h"
      14             : #include "mozilla/gfx/2D.h"
      15             : #include "mozilla/gfx/PathHelpers.h"
      16             : #include "mozilla/layers/LayersMessages.h"
      17             : #include "mozilla/layers/StackingContextHelper.h"
      18             : #include "mozilla/layers/WebRenderDisplayItemLayer.h"
      19             : #include "mozilla/layers/WebRenderMessages.h"
      20             : #include "mozilla/MathAlgorithms.h"
      21             : #include "mozilla/Move.h"
      22             : #include "nsCOMPtr.h"
      23             : #include "nsFontMetrics.h"
      24             : #include "nsGkAtoms.h"
      25             : #include "nsGenericHTMLElement.h"
      26             : #include "nsAttrValueInlines.h"
      27             : #include "nsPresContext.h"
      28             : #include "nsIPresShell.h"
      29             : #include "nsIDocument.h"
      30             : #include "nsDisplayList.h"
      31             : #include "nsCounterManager.h"
      32             : #include "nsBidiUtils.h"
      33             : #include "CounterStyleManager.h"
      34             : #include "UnitTransforms.h"
      35             : 
      36             : #include "imgIContainer.h"
      37             : #include "ImageLayers.h"
      38             : #include "imgRequestProxy.h"
      39             : #include "nsIURI.h"
      40             : #include "SVGImageContext.h"
      41             : #include "mozilla/layers/WebRenderBridgeChild.h"
      42             : 
      43             : #include <algorithm>
      44             : 
      45             : #ifdef ACCESSIBILITY
      46             : #include "nsAccessibilityService.h"
      47             : #endif
      48             : 
      49             : using namespace mozilla;
      50             : using namespace mozilla::gfx;
      51             : using namespace mozilla::image;
      52             : 
      53           0 : NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FontSizeInflationProperty, float)
      54             : 
      55           0 : NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
      56             : 
      57             : #ifdef DEBUG
      58           0 : NS_QUERYFRAME_HEAD(nsBulletFrame)
      59           0 :   NS_QUERYFRAME_ENTRY(nsBulletFrame)
      60           0 : NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
      61             : #endif
      62             : 
      63           0 : nsBulletFrame::~nsBulletFrame()
      64             : {
      65           0 :   NS_ASSERTION(!mBlockingOnload, "Still blocking onload in destructor?");
      66           0 : }
      67             : 
      68             : void
      69           0 : nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
      70             : {
      71             :   // Stop image loading first.
      72           0 :   DeregisterAndCancelImageRequest();
      73             : 
      74           0 :   if (mListener) {
      75           0 :     mListener->SetFrame(nullptr);
      76             :   }
      77             : 
      78             :   // Let base class do the rest
      79           0 :   nsFrame::DestroyFrom(aDestructRoot);
      80           0 : }
      81             : 
      82             : #ifdef DEBUG_FRAME_DUMP
      83             : nsresult
      84           0 : nsBulletFrame::GetFrameName(nsAString& aResult) const
      85             : {
      86           0 :   return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult);
      87             : }
      88             : #endif
      89             : 
      90             : bool
      91           0 : nsBulletFrame::IsEmpty()
      92             : {
      93           0 :   return IsSelfEmpty();
      94             : }
      95             : 
      96             : bool
      97           0 : nsBulletFrame::IsSelfEmpty()
      98             : {
      99           0 :   return StyleList()->mCounterStyle->IsNone();
     100             : }
     101             : 
     102             : /* virtual */ void
     103           0 : nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     104             : {
     105           0 :   nsFrame::DidSetStyleContext(aOldStyleContext);
     106             : 
     107           0 :   imgRequestProxy *newRequest = StyleList()->GetListStyleImage();
     108             : 
     109           0 :   if (newRequest) {
     110             : 
     111           0 :     if (!mListener) {
     112           0 :       mListener = new nsBulletListener();
     113           0 :       mListener->SetFrame(this);
     114             :     }
     115             : 
     116           0 :     bool needNewRequest = true;
     117             : 
     118           0 :     if (mImageRequest) {
     119             :       // Reload the image, maybe...
     120           0 :       nsCOMPtr<nsIURI> oldURI;
     121           0 :       mImageRequest->GetURI(getter_AddRefs(oldURI));
     122           0 :       nsCOMPtr<nsIURI> newURI;
     123           0 :       newRequest->GetURI(getter_AddRefs(newURI));
     124           0 :       if (oldURI && newURI) {
     125             :         bool same;
     126           0 :         newURI->Equals(oldURI, &same);
     127           0 :         if (same) {
     128           0 :           needNewRequest = false;
     129             :         }
     130             :       }
     131             :     }
     132             : 
     133           0 :     if (needNewRequest) {
     134           0 :       RefPtr<imgRequestProxy> newRequestClone;
     135           0 :       newRequest->Clone(mListener, getter_AddRefs(newRequestClone));
     136             : 
     137             :       // Deregister the old request. We wait until after Clone is done in case
     138             :       // the old request and the new request are the same underlying image
     139             :       // accessed via different URLs.
     140           0 :       DeregisterAndCancelImageRequest();
     141             : 
     142             :       // Register the new request.
     143           0 :       mImageRequest = Move(newRequestClone);
     144           0 :       RegisterImageRequest(/* aKnownToBeAnimated = */ false);
     145             :     }
     146             :   } else {
     147             :     // No image request on the new style context.
     148           0 :     DeregisterAndCancelImageRequest();
     149             :   }
     150             : 
     151             : #ifdef ACCESSIBILITY
     152             :   // Update the list bullet accessible. If old style list isn't available then
     153             :   // no need to update the accessible tree because it's not created yet.
     154           0 :   if (aOldStyleContext) {
     155           0 :     nsAccessibilityService* accService = nsIPresShell::AccService();
     156           0 :     if (accService) {
     157           0 :       const nsStyleList* oldStyleList = aOldStyleContext->PeekStyleList();
     158           0 :       if (oldStyleList) {
     159           0 :         bool hadBullet = oldStyleList->GetListStyleImage() ||
     160           0 :           !oldStyleList->mCounterStyle->IsNone();
     161             : 
     162           0 :         const nsStyleList* newStyleList = StyleList();
     163           0 :         bool hasBullet = newStyleList->GetListStyleImage() ||
     164           0 :           !newStyleList->mCounterStyle->IsNone();
     165             : 
     166           0 :         if (hadBullet != hasBullet) {
     167           0 :           accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
     168           0 :                                        hasBullet);
     169             :         }
     170             :       }
     171             :     }
     172             :   }
     173             : #endif
     174           0 : }
     175             : 
     176           0 : class nsDisplayBulletGeometry
     177             :   : public nsDisplayItemGenericGeometry
     178             :   , public nsImageGeometryMixin<nsDisplayBulletGeometry>
     179             : {
     180             : public:
     181           0 :   nsDisplayBulletGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
     182           0 :     : nsDisplayItemGenericGeometry(aItem, aBuilder)
     183           0 :     , nsImageGeometryMixin(aItem, aBuilder)
     184             :   {
     185           0 :     nsBulletFrame* f = static_cast<nsBulletFrame*>(aItem->Frame());
     186           0 :     mOrdinal = f->GetOrdinal();
     187           0 :   }
     188             : 
     189             :   int32_t mOrdinal;
     190             : };
     191             : 
     192           0 : class BulletRenderer final
     193             : {
     194             : public:
     195           0 :   BulletRenderer(imgIContainer* image, const nsRect& dest)
     196           0 :     : mImage(image)
     197             :     , mDest(dest)
     198           0 :     , mListStyleType(NS_STYLE_LIST_STYLE_NONE)
     199             :   {
     200           0 :     MOZ_ASSERT(IsImageType());
     201           0 :   }
     202             : 
     203           0 :   BulletRenderer(Path* path, nscolor color, int32_t listStyleType)
     204           0 :     : mColor(color)
     205             :     , mPath(path)
     206           0 :     , mListStyleType(listStyleType)
     207             :   {
     208           0 :     MOZ_ASSERT(IsPathType());
     209           0 :   }
     210             : 
     211           0 :   BulletRenderer(const nsString& text,
     212             :                  nsFontMetrics* fm,
     213             :                  nscolor color,
     214             :                  const nsPoint& point,
     215             :                  int32_t listStyleType)
     216           0 :     : mColor(color)
     217             :     , mText(text)
     218             :     , mFontMetrics(fm)
     219             :     , mPoint(point)
     220           0 :     , mListStyleType(listStyleType)
     221             :   {
     222           0 :     MOZ_ASSERT(IsTextType());
     223           0 :   }
     224             : 
     225             :   void
     226             :   CreateWebRenderCommands(nsDisplayItem* aItem,
     227             :                           wr::DisplayListBuilder& aBuilder,
     228             :                           const layers::StackingContextHelper& aSc,
     229             :                           nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     230             :                           mozilla::layers::WebRenderLayerManager* aManager,
     231             :                           nsDisplayListBuilder* aDisplayListBuilder);
     232             : 
     233             :   DrawResult
     234             :   Paint(gfxContext& aRenderingContext, nsPoint aPt,
     235             :         const nsRect& aDirtyRect, uint32_t aFlags,
     236             :         bool aDisableSubpixelAA, nsIFrame* aFrame);
     237             : 
     238             :   bool
     239           0 :   IsImageType() const
     240             :   {
     241           0 :     return mListStyleType == NS_STYLE_LIST_STYLE_NONE && mImage;
     242             :   }
     243             : 
     244             :   bool
     245           0 :   IsPathType() const
     246             :   {
     247           0 :     return (mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
     248           0 :             mListStyleType == NS_STYLE_LIST_STYLE_CIRCLE ||
     249           0 :             mListStyleType == NS_STYLE_LIST_STYLE_SQUARE ||
     250           0 :             mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN ||
     251           0 :             mListStyleType == NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED) &&
     252           0 :            mPath;
     253             :   }
     254             : 
     255             :   bool
     256           0 :   IsTextType() const
     257             :   {
     258           0 :     return mListStyleType != NS_STYLE_LIST_STYLE_NONE &&
     259           0 :            mListStyleType != NS_STYLE_LIST_STYLE_DISC &&
     260           0 :            mListStyleType != NS_STYLE_LIST_STYLE_CIRCLE &&
     261           0 :            mListStyleType != NS_STYLE_LIST_STYLE_SQUARE &&
     262           0 :            mListStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN &&
     263           0 :            mListStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED &&
     264           0 :            !mText.IsEmpty();
     265             :   }
     266             : 
     267             :   bool
     268             :   BuildGlyphForText(nsDisplayItem* aItem, bool disableSubpixelAA);
     269             : 
     270             :   bool
     271             :   IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags);
     272             : 
     273             : private:
     274             :   void
     275             :   CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
     276             :                                   wr::DisplayListBuilder& aBuilder,
     277             :                                   const layers::StackingContextHelper& aSc,
     278             :                                   nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     279             :                                   mozilla::layers::WebRenderLayerManager* aManager,
     280             :                                   nsDisplayListBuilder* aDisplayListBuilder);
     281             : 
     282             :   void
     283             :   CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
     284             :                                  wr::DisplayListBuilder& aBuilder,
     285             :                                  const layers::StackingContextHelper& aSc,
     286             :                                  nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     287             :                                  mozilla::layers::WebRenderLayerManager* aManager,
     288             :                                  nsDisplayListBuilder* aDisplayListBuilder);
     289             : 
     290             :   void
     291             :   CreateWebRenderCommandsForText(nsDisplayItem* aItem,
     292             :                                  wr::DisplayListBuilder& aBuilder,
     293             :                                  const layers::StackingContextHelper& aSc,
     294             :                                  mozilla::layers::WebRenderLayerManager* aManager,
     295             :                                  nsDisplayListBuilder* aDisplayListBuilder);
     296             : 
     297             : private:
     298             :   // mImage and mDest are the properties for list-style-image.
     299             :   // mImage is the image content and mDest is the image position.
     300             :   RefPtr<imgIContainer> mImage;
     301             :   nsRect mDest;
     302             : 
     303             :   // mColor indicate the color of list-style. Both text and path type would use this memeber.
     304             :   nscolor mColor;
     305             : 
     306             :   // mPath record the path of the list-style for later drawing.
     307             :   // Included following types: square, circle, disc, disclosure open and disclosure closed.
     308             :   RefPtr<Path> mPath;
     309             : 
     310             :   // mText, mFontMertrics, mPoint, mFont and mGlyphs are for other
     311             :   // list-style-type which can be drawed by text.
     312             :   nsString mText;
     313             :   RefPtr<nsFontMetrics> mFontMetrics;
     314             :   nsPoint mPoint;
     315             :   RefPtr<ScaledFont> mFont;
     316             :   nsTArray<layers::GlyphArray> mGlyphs;
     317             : 
     318             :   // Store the type of list-style-type.
     319             :   int32_t mListStyleType;
     320             : };
     321             : 
     322             : void
     323           0 : BulletRenderer::CreateWebRenderCommands(nsDisplayItem* aItem,
     324             :                                         wr::DisplayListBuilder& aBuilder,
     325             :                                         const layers::StackingContextHelper& aSc,
     326             :                                         nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     327             :                                         mozilla::layers::WebRenderLayerManager* aManager,
     328             :                                         nsDisplayListBuilder* aDisplayListBuilder)
     329             : {
     330           0 :   if (IsImageType()) {
     331             :     CreateWebRenderCommandsForImage(aItem, aBuilder, aSc, aParentCommands,
     332           0 :                                     aManager, aDisplayListBuilder);
     333           0 :   } else if (IsPathType()) {
     334             :     CreateWebRenderCommandsForPath(aItem, aBuilder, aSc, aParentCommands,
     335           0 :                                    aManager, aDisplayListBuilder);
     336             :   } else {
     337           0 :     MOZ_ASSERT(IsTextType());
     338             :     CreateWebRenderCommandsForText(aItem, aBuilder, aSc,
     339           0 :                                    aManager, aDisplayListBuilder);
     340             :   }
     341           0 : }
     342             : 
     343             : DrawResult
     344           0 : BulletRenderer::Paint(gfxContext& aRenderingContext, nsPoint aPt,
     345             :                       const nsRect& aDirtyRect, uint32_t aFlags,
     346             :                       bool aDisableSubpixelAA, nsIFrame* aFrame)
     347             : {
     348           0 :   if (IsImageType()) {
     349           0 :     SamplingFilter filter = nsLayoutUtils::GetSamplingFilterForFrame(aFrame);
     350           0 :     return nsLayoutUtils::DrawSingleImage(aRenderingContext,
     351             :                                           aFrame->PresContext(), mImage, filter,
     352             :                                           mDest, aDirtyRect,
     353           0 :                                           /* no SVGImageContext */ Nothing(),
     354           0 :                                           aFlags);
     355             :   }
     356             : 
     357           0 :   if (IsPathType()) {
     358           0 :     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     359           0 :     switch (mListStyleType) {
     360             :     case NS_STYLE_LIST_STYLE_CIRCLE:
     361           0 :       MOZ_ASSERT(mPath);
     362           0 :       drawTarget->Stroke(mPath, ColorPattern(ToDeviceColor(mColor)));
     363           0 :       break;
     364             :     case NS_STYLE_LIST_STYLE_DISC:
     365             :     case NS_STYLE_LIST_STYLE_SQUARE:
     366             :     case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
     367             :     case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
     368           0 :       MOZ_ASSERT(mPath);
     369           0 :       drawTarget->Fill(mPath, ColorPattern(ToDeviceColor(mColor)));
     370           0 :       break;
     371             :     default:
     372           0 :       MOZ_CRASH("unreachable");
     373             :     }
     374             :   }
     375             : 
     376           0 :   if (IsTextType()) {
     377           0 :     DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     378             :     DrawTargetAutoDisableSubpixelAntialiasing
     379           0 :       disable(drawTarget, aDisableSubpixelAA);
     380             : 
     381           0 :     aRenderingContext.SetColor(Color::FromABGR(mColor));
     382             : 
     383           0 :     nsPresContext* presContext = aFrame->PresContext();
     384           0 :     if (!presContext->BidiEnabled() && HasRTLChars(mText)) {
     385           0 :       presContext->SetBidiEnabled();
     386             :     }
     387           0 :     nsLayoutUtils::DrawString(aFrame, *mFontMetrics, &aRenderingContext,
     388           0 :                               mText.get(), mText.Length(), mPoint);
     389             :   }
     390             : 
     391           0 :   return DrawResult::SUCCESS;
     392             : }
     393             : 
     394             : bool
     395           0 : BulletRenderer::BuildGlyphForText(nsDisplayItem* aItem, bool disableSubpixelAA)
     396             : {
     397           0 :   MOZ_ASSERT(IsTextType());
     398             : 
     399             :   RefPtr<DrawTargetCapture> capture =
     400           0 :     gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreateCaptureDT(IntSize());
     401           0 :   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(capture);
     402             : 
     403             :   {
     404             :     DrawTargetAutoDisableSubpixelAntialiasing
     405           0 :       disable(capture, disableSubpixelAA);
     406             : 
     407           0 :     captureCtx->SetColor(
     408           0 :       Color::FromABGR(mColor));
     409             : 
     410           0 :     nsPresContext* presContext = aItem->Frame()->PresContext();
     411           0 :     if (!presContext->BidiEnabled() && HasRTLChars(mText)) {
     412           0 :       presContext->SetBidiEnabled();
     413             :     }
     414             : 
     415           0 :     nsLayoutUtils::DrawString(aItem->Frame(), *mFontMetrics, captureCtx,
     416           0 :                               mText.get(), mText.Length(), mPoint);
     417             :   }
     418             : 
     419           0 :   layers::GlyphArray* g = mGlyphs.AppendElement();
     420           0 :   std::vector<Glyph> glyphs;
     421           0 :   Color color;
     422           0 :   if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs)) {
     423           0 :     mFont = nullptr;
     424           0 :     mGlyphs.Clear();
     425           0 :     return false;
     426             :   }
     427             : 
     428           0 :   g->glyphs().SetLength(glyphs.size());
     429           0 :   PodCopy(g->glyphs().Elements(), glyphs.data(), glyphs.size());
     430           0 :   g->color() = color;
     431             : 
     432           0 :   return true;
     433             : }
     434             : 
     435             : bool
     436           0 : BulletRenderer::IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags)
     437             : {
     438           0 :   MOZ_ASSERT(IsImageType());
     439             : 
     440           0 :   return mImage->IsImageContainerAvailable(aManager, aFlags);
     441             : }
     442             : 
     443             : void
     444           0 : BulletRenderer::CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
     445             :                                                 wr::DisplayListBuilder& aBuilder,
     446             :                                                 const layers::StackingContextHelper& aSc,
     447             :                                                 nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     448             :                                                 mozilla::layers::WebRenderLayerManager* aManager,
     449             :                                                 nsDisplayListBuilder* aDisplayListBuilder)
     450             : {
     451           0 :   MOZ_ASSERT(IsImageType());
     452             : 
     453           0 :   if (!mImage) {
     454           0 :      return;
     455             :   }
     456             : 
     457           0 :   uint32_t flags = aDisplayListBuilder->ShouldSyncDecodeImages() ?
     458             :                    imgIContainer::FLAG_SYNC_DECODE :
     459           0 :                    imgIContainer::FLAG_NONE;
     460             : 
     461             :   RefPtr<layers::ImageContainer> container =
     462           0 :     mImage->GetImageContainer(aManager, flags);
     463           0 :   if (!container) {
     464           0 :     return;
     465             :   }
     466             : 
     467           0 :   gfx::IntSize size;
     468           0 :   Maybe<wr::ImageKey> key = aManager->CreateImageKey(aItem, container, aBuilder, aSc, size);
     469           0 :   if (key.isNothing()) {
     470           0 :     return;
     471             :   }
     472             : 
     473           0 :   const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
     474           0 :   LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(mDest, appUnitsPerDevPixel);
     475           0 :   WrRect dest = aSc.ToRelativeWrRectRounded(destRect);
     476             : 
     477           0 :   aBuilder.PushImage(dest,
     478             :                      dest,
     479             :                      WrImageRendering::Auto,
     480           0 :                      key.value());
     481             : }
     482             : 
     483             : void
     484           0 : BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
     485             :                                                wr::DisplayListBuilder& aBuilder,
     486             :                                                const layers::StackingContextHelper& aSc,
     487             :                                                nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     488             :                                                mozilla::layers::WebRenderLayerManager* aManager,
     489             :                                                nsDisplayListBuilder* aDisplayListBuilder)
     490             : {
     491           0 :   MOZ_ASSERT(IsPathType());
     492             : 
     493           0 :   if (!aManager->PushItemAsImage(aItem, aBuilder, aSc, aDisplayListBuilder)) {
     494           0 :     NS_WARNING("Fail to create WebRender commands for Bullet path.");
     495             :   }
     496           0 : }
     497             : 
     498             : void
     499           0 : BulletRenderer::CreateWebRenderCommandsForText(nsDisplayItem* aItem,
     500             :                                                wr::DisplayListBuilder& aBuilder,
     501             :                                                const layers::StackingContextHelper& aSc,
     502             :                                                mozilla::layers::WebRenderLayerManager* aManager,
     503             :                                                nsDisplayListBuilder* aDisplayListBuilder)
     504             : {
     505           0 :   MOZ_ASSERT(IsTextType());
     506           0 :   MOZ_ASSERT(mFont);
     507           0 :   MOZ_ASSERT(!mGlyphs.IsEmpty());
     508             : 
     509           0 :   const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
     510             :   bool dummy;
     511             :   LayerRect destRect = ViewAs<LayerPixel>(
     512           0 :       LayoutDeviceRect::FromAppUnits(
     513           0 :           aItem->GetBounds(aDisplayListBuilder, &dummy), appUnitsPerDevPixel),
     514           0 :       PixelCastJustification::WebRenderHasUnitResolution);
     515             : 
     516           0 :   aManager->WrBridge()->PushGlyphs(aBuilder, mGlyphs, mFont, aSc, destRect, destRect);
     517           0 : }
     518             : 
     519             : class nsDisplayBullet final : public nsDisplayItem {
     520             : public:
     521           0 :   nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame)
     522           0 :     : nsDisplayItem(aBuilder, aFrame)
     523           0 :     , mDisableSubpixelAA(false)
     524             :   {
     525           0 :     MOZ_COUNT_CTOR(nsDisplayBullet);
     526           0 :   }
     527             : #ifdef NS_BUILD_REFCNT_LOGGING
     528           0 :   virtual ~nsDisplayBullet() {
     529           0 :     MOZ_COUNT_DTOR(nsDisplayBullet);
     530           0 :   }
     531             : #endif
     532             : 
     533           0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
     534             :                            bool* aSnap) override
     535             :   {
     536           0 :     *aSnap = false;
     537           0 :     return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
     538             :   }
     539             : 
     540             :   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
     541             :                                    LayerManager* aManager,
     542             :                                    const ContainerLayerParameters& aParameters) override;
     543             : 
     544             :   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
     545             :                                              LayerManager* aManager,
     546             :                                              const ContainerLayerParameters& aParameters) override;
     547             : 
     548             :   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
     549             :                                        const StackingContextHelper& aSc,
     550             :                                        nsTArray<WebRenderParentCommand>& aParentCommands,
     551             :                                        mozilla::layers::WebRenderLayerManager* aManager,
     552             :                                        nsDisplayListBuilder* aDisplayListBuilder) override;
     553             : 
     554           0 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     555             :                        HitTestState* aState,
     556             :                        nsTArray<nsIFrame*> *aOutFrames) override {
     557           0 :     aOutFrames->AppendElement(mFrame);
     558           0 :   }
     559             :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     560             :                      gfxContext* aCtx) override;
     561           0 :   NS_DISPLAY_DECL_NAME("Bullet", TYPE_BULLET)
     562             : 
     563           0 :   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override
     564             :   {
     565             :     bool snap;
     566           0 :     return GetBounds(aBuilder, &snap);
     567             :   }
     568             : 
     569           0 :   virtual void DisableComponentAlpha() override {
     570           0 :     mDisableSubpixelAA = true;
     571           0 :   }
     572             : 
     573           0 :   virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
     574             :   {
     575           0 :     return new nsDisplayBulletGeometry(this, aBuilder);
     576             :   }
     577             : 
     578           0 :   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
     579             :                                          const nsDisplayItemGeometry* aGeometry,
     580             :                                          nsRegion *aInvalidRegion) override
     581             :   {
     582           0 :     const nsDisplayBulletGeometry* geometry = static_cast<const nsDisplayBulletGeometry*>(aGeometry);
     583           0 :     nsBulletFrame* f = static_cast<nsBulletFrame*>(mFrame);
     584             : 
     585           0 :     if (f->GetOrdinal() != geometry->mOrdinal) {
     586             :       bool snap;
     587           0 :       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
     588           0 :       return;
     589             :     }
     590             : 
     591           0 :     nsCOMPtr<imgIContainer> image = f->GetImage();
     592           0 :     if (aBuilder->ShouldSyncDecodeImages() && image &&
     593           0 :         geometry->ShouldInvalidateToSyncDecodeImages()) {
     594             :       bool snap;
     595           0 :       aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
     596             :     }
     597             : 
     598           0 :     return nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
     599             :   }
     600             : 
     601             : protected:
     602             :   bool mDisableSubpixelAA;
     603             :   Maybe<BulletRenderer> mBulletRenderer;
     604             : };
     605             : 
     606             : LayerState
     607           0 : nsDisplayBullet::GetLayerState(nsDisplayListBuilder* aBuilder,
     608             :                                LayerManager* aManager,
     609             :                                const ContainerLayerParameters& aParameters)
     610             : {
     611           0 :   if (!ShouldUseAdvancedLayer(aManager, gfxPrefs::LayersAllowBulletLayers)) {
     612           0 :     return LAYER_NONE;
     613             :   }
     614             : 
     615             :   RefPtr<gfxContext> screenRefCtx =
     616           0 :     gfxContext::CreateOrNull(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
     617             : 
     618           0 :   Maybe<BulletRenderer> br = static_cast<nsBulletFrame*>(mFrame)->
     619           0 :     CreateBulletRenderer(*screenRefCtx, ToReferenceFrame());
     620             : 
     621           0 :   if (!br) {
     622           0 :     return LAYER_NONE;
     623             :   }
     624             : 
     625           0 :   if (br->IsImageType()) {
     626           0 :     uint32_t flags = aBuilder->ShouldSyncDecodeImages()
     627           0 :                    ? imgIContainer::FLAG_SYNC_DECODE
     628           0 :                    : imgIContainer::FLAG_NONE;
     629             : 
     630           0 :     if (!br->IsImageContainerAvailable(aManager, flags)) {
     631           0 :       return LAYER_NONE;
     632             :     }
     633             :   }
     634             : 
     635           0 :   if (br->IsTextType()) {
     636           0 :     if (!br->BuildGlyphForText(this, mDisableSubpixelAA)) {
     637           0 :       return LAYER_NONE;
     638             :     }
     639             :   }
     640             : 
     641           0 :   mBulletRenderer = br;
     642           0 :   return LAYER_ACTIVE;
     643             : }
     644             : 
     645             : already_AddRefed<layers::Layer>
     646           0 : nsDisplayBullet::BuildLayer(nsDisplayListBuilder* aBuilder,
     647             :                             LayerManager* aManager,
     648             :                             const ContainerLayerParameters& aContainerParameters)
     649             : {
     650           0 :   if (!mBulletRenderer) {
     651           0 :     return nullptr;
     652             :   }
     653             : 
     654           0 :   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
     655             : }
     656             : 
     657             : bool
     658           0 : nsDisplayBullet::CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
     659             :                                          const StackingContextHelper& aSc,
     660             :                                          nsTArray<layers::WebRenderParentCommand>& aParentCommands,
     661             :                                          mozilla::layers::WebRenderLayerManager* aManager,
     662             :                                          nsDisplayListBuilder* aDisplayListBuilder)
     663             : {
     664           0 :   if (aManager->IsLayersFreeTransaction()) {
     665           0 :     ContainerLayerParameters parameter;
     666           0 :     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
     667           0 :       return false;
     668             :     }
     669             :   }
     670             : 
     671           0 :   if (!mBulletRenderer)
     672           0 :     return false;
     673             : 
     674           0 :   mBulletRenderer->CreateWebRenderCommands(this, aBuilder, aSc, aParentCommands,
     675           0 :                                            aManager, aDisplayListBuilder);
     676           0 :   return true;
     677             : }
     678             : 
     679           0 : void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
     680             :                             gfxContext* aCtx)
     681             : {
     682           0 :   uint32_t flags = imgIContainer::FLAG_NONE;
     683           0 :   if (aBuilder->ShouldSyncDecodeImages()) {
     684           0 :     flags |= imgIContainer::FLAG_SYNC_DECODE;
     685             :   }
     686             : 
     687           0 :   DrawResult result = static_cast<nsBulletFrame*>(mFrame)->
     688           0 :     PaintBullet(*aCtx, ToReferenceFrame(), mVisibleRect, flags,
     689           0 :                 mDisableSubpixelAA);
     690             : 
     691           0 :   nsDisplayBulletGeometry::UpdateDrawResult(this, result);
     692           0 : }
     693             : 
     694             : void
     695           0 : nsBulletFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     696             :                                 const nsRect&           aDirtyRect,
     697             :                                 const nsDisplayListSet& aLists)
     698             : {
     699           0 :   if (!IsVisibleForPainting(aBuilder))
     700           0 :     return;
     701             : 
     702           0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsBulletFrame");
     703             : 
     704           0 :   aLists.Content()->AppendNewToTop(
     705           0 :     new (aBuilder) nsDisplayBullet(aBuilder, this));
     706             : }
     707             : 
     708             : Maybe<BulletRenderer>
     709           0 : nsBulletFrame::CreateBulletRenderer(gfxContext& aRenderingContext, nsPoint aPt)
     710             : {
     711           0 :   const nsStyleList* myList = StyleList();
     712           0 :   CounterStyle* listStyleType = myList->mCounterStyle;
     713           0 :   nsMargin padding = mPadding.GetPhysicalMargin(GetWritingMode());
     714             : 
     715           0 :   if (myList->GetListStyleImage() && mImageRequest) {
     716             :     uint32_t status;
     717           0 :     mImageRequest->GetImageStatus(&status);
     718           0 :     if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
     719           0 :         !(status & imgIRequest::STATUS_ERROR)) {
     720           0 :       nsCOMPtr<imgIContainer> imageCon;
     721           0 :       mImageRequest->GetImage(getter_AddRefs(imageCon));
     722           0 :       if (imageCon) {
     723             :         nsRect dest(padding.left, padding.top,
     724           0 :                     mRect.width - (padding.left + padding.right),
     725           0 :                     mRect.height - (padding.top + padding.bottom));
     726           0 :         BulletRenderer br(imageCon, dest + aPt);
     727           0 :         return Some(br);
     728             :       }
     729             :     }
     730             :   }
     731             : 
     732           0 :   nscolor color = nsLayoutUtils::GetColor(this, &nsStyleColor::mColor);
     733             : 
     734           0 :   DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
     735           0 :   int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
     736             : 
     737           0 :   switch (listStyleType->GetStyle()) {
     738             :   case NS_STYLE_LIST_STYLE_NONE:
     739           0 :     return Nothing();
     740             : 
     741             :   case NS_STYLE_LIST_STYLE_DISC:
     742             :   case NS_STYLE_LIST_STYLE_CIRCLE:
     743             :     {
     744           0 :       nsRect rect(padding.left + aPt.x,
     745           0 :                   padding.top + aPt.y,
     746           0 :                   mRect.width - (padding.left + padding.right),
     747           0 :                   mRect.height - (padding.top + padding.bottom));
     748           0 :       Rect devPxRect = NSRectToRect(rect, appUnitsPerDevPixel);
     749           0 :       RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
     750           0 :       AppendEllipseToPath(builder, devPxRect.Center(), devPxRect.Size());
     751             : 
     752           0 :       RefPtr<Path> path = builder->Finish();
     753           0 :       BulletRenderer br(path, color, listStyleType->GetStyle());
     754           0 :       return Some(br);
     755             :     }
     756             : 
     757             :   case NS_STYLE_LIST_STYLE_SQUARE:
     758             :     {
     759           0 :       nsRect rect(aPt, mRect.Size());
     760           0 :       rect.Deflate(padding);
     761             : 
     762             :       // Snap the height and the width of the rectangle to device pixels,
     763             :       // and then center the result within the original rectangle, so that
     764             :       // all square bullets at the same font size have the same visual
     765             :       // size (bug 376690).
     766             :       // FIXME: We should really only do this if we're not transformed
     767             :       // (like gfxContext::UserToDevicePixelSnapped does).
     768           0 :       nsPresContext *pc = PresContext();
     769             :       nsRect snapRect(rect.x, rect.y,
     770             :                       pc->RoundAppUnitsToNearestDevPixels(rect.width),
     771           0 :                       pc->RoundAppUnitsToNearestDevPixels(rect.height));
     772           0 :       snapRect.MoveBy((rect.width - snapRect.width) / 2,
     773           0 :                       (rect.height - snapRect.height) / 2);
     774             :       Rect devPxRect =
     775           0 :         NSRectToSnappedRect(snapRect, appUnitsPerDevPixel, *drawTarget);
     776           0 :       RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
     777           0 :       AppendRectToPath(builder, devPxRect);
     778             : 
     779           0 :       RefPtr<Path> path = builder->Finish();
     780           0 :       BulletRenderer br(path, color, listStyleType->GetStyle());
     781           0 :       return Some(br);
     782             :     }
     783             : 
     784             :   case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
     785             :   case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
     786             :     {
     787           0 :       nsRect rect(aPt, mRect.Size());
     788           0 :       rect.Deflate(padding);
     789             : 
     790           0 :       WritingMode wm = GetWritingMode();
     791           0 :       bool isVertical = wm.IsVertical();
     792             :       bool isClosed =
     793           0 :         listStyleType->GetStyle() == NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED;
     794           0 :       bool isDown = (!isVertical && !isClosed) || (isVertical && isClosed);
     795           0 :       nscoord diff = NSToCoordRound(0.1f * rect.height);
     796           0 :       if (isDown) {
     797           0 :         rect.y += diff * 2;
     798           0 :         rect.height -= diff * 2;
     799             :       } else {
     800           0 :         rect.Deflate(diff, 0);
     801             :       }
     802           0 :       nsPresContext *pc = PresContext();
     803           0 :       rect.x = pc->RoundAppUnitsToNearestDevPixels(rect.x);
     804           0 :       rect.y = pc->RoundAppUnitsToNearestDevPixels(rect.y);
     805             : 
     806           0 :       RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
     807           0 :       if (isDown) {
     808             :         // to bottom
     809           0 :         builder->MoveTo(NSPointToPoint(rect.TopLeft(), appUnitsPerDevPixel));
     810           0 :         builder->LineTo(NSPointToPoint(rect.TopRight(), appUnitsPerDevPixel));
     811           0 :         builder->LineTo(NSPointToPoint((rect.BottomLeft() + rect.BottomRight()) / 2,
     812           0 :                                        appUnitsPerDevPixel));
     813             :       } else {
     814           0 :         bool isLR = isVertical ? wm.IsVerticalLR() : wm.IsBidiLTR();
     815           0 :         if (isLR) {
     816             :           // to right
     817           0 :           builder->MoveTo(NSPointToPoint(rect.TopLeft(), appUnitsPerDevPixel));
     818           0 :           builder->LineTo(NSPointToPoint((rect.TopRight() + rect.BottomRight()) / 2,
     819           0 :                                          appUnitsPerDevPixel));
     820           0 :           builder->LineTo(NSPointToPoint(rect.BottomLeft(), appUnitsPerDevPixel));
     821             :         } else {
     822             :           // to left
     823           0 :           builder->MoveTo(NSPointToPoint(rect.TopRight(), appUnitsPerDevPixel));
     824           0 :           builder->LineTo(NSPointToPoint(rect.BottomRight(), appUnitsPerDevPixel));
     825           0 :           builder->LineTo(NSPointToPoint((rect.TopLeft() + rect.BottomLeft()) / 2,
     826           0 :                                          appUnitsPerDevPixel));
     827             :         }
     828             :       }
     829             : 
     830           0 :       RefPtr<Path> path = builder->Finish();
     831           0 :       BulletRenderer br(path, color, listStyleType->GetStyle());
     832           0 :       return Some(br);
     833             :     }
     834             : 
     835             :   default:
     836             :     {
     837             :       RefPtr<nsFontMetrics> fm =
     838           0 :         nsLayoutUtils::GetFontMetricsForFrame(this, GetFontSizeInflation());
     839           0 :       nsAutoString text;
     840           0 :       GetListItemText(text);
     841           0 :       WritingMode wm = GetWritingMode();
     842           0 :       nscoord ascent = wm.IsLineInverted()
     843           0 :                          ? fm->MaxDescent() : fm->MaxAscent();
     844           0 :       aPt.MoveBy(padding.left, padding.top);
     845           0 :       if (wm.IsVertical()) {
     846           0 :         if (wm.IsVerticalLR()) {
     847           0 :           aPt.x = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineX(
     848             :                                    this, &aRenderingContext, aPt.x, ascent));
     849             :         } else {
     850           0 :           aPt.x = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineX(
     851           0 :                                    this, &aRenderingContext, aPt.x + mRect.width,
     852             :                                    -ascent));
     853             :         }
     854             :       } else {
     855           0 :         aPt.y = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineY(
     856             :                                  this, &aRenderingContext, aPt.y, ascent));
     857             :       }
     858             : 
     859           0 :       BulletRenderer br(text, fm, color, aPt, listStyleType->GetStyle());
     860           0 :       return Some(br);
     861             :     }
     862             :   }
     863             : 
     864             :   MOZ_CRASH("unreachable");
     865             :   return Nothing();
     866             : }
     867             : 
     868             : DrawResult
     869           0 : nsBulletFrame::PaintBullet(gfxContext& aRenderingContext, nsPoint aPt,
     870             :                            const nsRect& aDirtyRect, uint32_t aFlags,
     871             :                            bool aDisableSubpixelAA)
     872             : {
     873           0 :   Maybe<BulletRenderer> br = CreateBulletRenderer(aRenderingContext, aPt);
     874             : 
     875           0 :   if (!br) {
     876           0 :     return DrawResult::SUCCESS;
     877             :   }
     878             : 
     879           0 :   return br->Paint(aRenderingContext, aPt, aDirtyRect,
     880           0 :                    aFlags, aDisableSubpixelAA, this);
     881             : }
     882             : 
     883             : int32_t
     884           0 : nsBulletFrame::SetListItemOrdinal(int32_t aNextOrdinal,
     885             :                                   bool* aChanged,
     886             :                                   int32_t aIncrement)
     887             : {
     888           0 :   MOZ_ASSERT(aIncrement == 1 || aIncrement == -1,
     889             :              "We shouldn't have weird increments here");
     890             : 
     891             :   // Assume that the ordinal comes from the caller
     892           0 :   int32_t oldOrdinal = mOrdinal;
     893           0 :   mOrdinal = aNextOrdinal;
     894             : 
     895             :   // Try to get value directly from the list-item, if it specifies a
     896             :   // value attribute. Note: we do this with our parent's content
     897             :   // because our parent is the list-item.
     898           0 :   nsIContent* parentContent = GetParent()->GetContent();
     899           0 :   if (parentContent) {
     900             :     nsGenericHTMLElement *hc =
     901           0 :       nsGenericHTMLElement::FromContent(parentContent);
     902           0 :     if (hc) {
     903           0 :       const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::value);
     904           0 :       if (attr && attr->Type() == nsAttrValue::eInteger) {
     905             :         // Use ordinal specified by the value attribute
     906           0 :         mOrdinal = attr->GetIntegerValue();
     907             :       }
     908             :     }
     909             :   }
     910             : 
     911           0 :   *aChanged = oldOrdinal != mOrdinal;
     912             : 
     913           0 :   return nsCounterManager::IncrementCounter(mOrdinal, aIncrement);
     914             : }
     915             : 
     916             : void
     917           0 : nsBulletFrame::GetListItemText(nsAString& aResult)
     918             : {
     919           0 :   CounterStyle* style = StyleList()->mCounterStyle;
     920           0 :   NS_ASSERTION(style->GetStyle() != NS_STYLE_LIST_STYLE_NONE &&
     921             :                style->GetStyle() != NS_STYLE_LIST_STYLE_DISC &&
     922             :                style->GetStyle() != NS_STYLE_LIST_STYLE_CIRCLE &&
     923             :                style->GetStyle() != NS_STYLE_LIST_STYLE_SQUARE &&
     924             :                style->GetStyle() != NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED &&
     925             :                style->GetStyle() != NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN,
     926             :                "we should be using specialized code for these types");
     927             : 
     928             :   bool isRTL;
     929           0 :   nsAutoString counter, prefix, suffix;
     930           0 :   style->GetPrefix(prefix);
     931           0 :   style->GetSuffix(suffix);
     932           0 :   style->GetCounterText(mOrdinal, GetWritingMode(), counter, isRTL);
     933             : 
     934           0 :   aResult.Truncate();
     935           0 :   aResult.Append(prefix);
     936           0 :   if (GetWritingMode().IsBidiLTR() != isRTL) {
     937           0 :     aResult.Append(counter);
     938             :   } else {
     939             :     // RLM = 0x200f, LRM = 0x200e
     940           0 :     char16_t mark = isRTL ? 0x200f : 0x200e;
     941           0 :     aResult.Append(mark);
     942           0 :     aResult.Append(counter);
     943           0 :     aResult.Append(mark);
     944             :   }
     945           0 :   aResult.Append(suffix);
     946           0 : }
     947             : 
     948             : #define MIN_BULLET_SIZE 1
     949             : 
     950             : void
     951           0 : nsBulletFrame::AppendSpacingToPadding(nsFontMetrics* aFontMetrics,
     952             :                                       LogicalMargin* aPadding)
     953             : {
     954           0 :   aPadding->IEnd(GetWritingMode()) += aFontMetrics->EmHeight() / 2;
     955           0 : }
     956             : 
     957             : void
     958           0 : nsBulletFrame::GetDesiredSize(nsPresContext*  aCX,
     959             :                               gfxContext *aRenderingContext,
     960             :                               ReflowOutput& aMetrics,
     961             :                               float aFontSizeInflation,
     962             :                               LogicalMargin* aPadding)
     963             : {
     964             :   // Reset our padding.  If we need it, we'll set it below.
     965           0 :   WritingMode wm = GetWritingMode();
     966           0 :   aPadding->SizeTo(wm, 0, 0, 0, 0);
     967           0 :   LogicalSize finalSize(wm);
     968             : 
     969           0 :   const nsStyleList* myList = StyleList();
     970             :   nscoord ascent;
     971             :   RefPtr<nsFontMetrics> fm =
     972           0 :     nsLayoutUtils::GetFontMetricsForFrame(this, aFontSizeInflation);
     973             : 
     974           0 :   RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
     975             : 
     976           0 :   if (myList->GetListStyleImage() && mImageRequest) {
     977             :     uint32_t status;
     978           0 :     mImageRequest->GetImageStatus(&status);
     979           0 :     if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
     980           0 :         !(status & imgIRequest::STATUS_ERROR)) {
     981             :       // auto size the image
     982           0 :       finalSize.ISize(wm) = mIntrinsicSize.ISize(wm);
     983           0 :       aMetrics.SetBlockStartAscent(finalSize.BSize(wm) =
     984           0 :                                    mIntrinsicSize.BSize(wm));
     985           0 :       aMetrics.SetSize(wm, finalSize);
     986             : 
     987           0 :       AppendSpacingToPadding(fm, aPadding);
     988             : 
     989           0 :       AddStateBits(BULLET_FRAME_IMAGE_LOADING);
     990             : 
     991           0 :       return;
     992             :     }
     993             :   }
     994             : 
     995             :   // If we're getting our desired size and don't have an image, reset
     996             :   // mIntrinsicSize to (0,0).  Otherwise, if we used to have an image, it
     997             :   // changed, and the new one is coming in, but we're reflowing before it's
     998             :   // fully there, we'll end up with mIntrinsicSize not matching our size, but
     999             :   // won't trigger a reflow in OnStartContainer (because mIntrinsicSize will
    1000             :   // match the image size).
    1001           0 :   mIntrinsicSize.SizeTo(wm, 0, 0);
    1002             : 
    1003             :   nscoord bulletSize;
    1004             : 
    1005           0 :   nsAutoString text;
    1006           0 :   switch (myList->mCounterStyle->GetStyle()) {
    1007             :     case NS_STYLE_LIST_STYLE_NONE:
    1008           0 :       finalSize.ISize(wm) = finalSize.BSize(wm) = 0;
    1009           0 :       aMetrics.SetBlockStartAscent(0);
    1010           0 :       break;
    1011             : 
    1012             :     case NS_STYLE_LIST_STYLE_DISC:
    1013             :     case NS_STYLE_LIST_STYLE_CIRCLE:
    1014             :     case NS_STYLE_LIST_STYLE_SQUARE: {
    1015           0 :       ascent = fm->MaxAscent();
    1016           0 :       bulletSize = std::max(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1017           0 :                           NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
    1018           0 :       aPadding->BEnd(wm) = NSToCoordRound(float(ascent) / 8.0f);
    1019           0 :       finalSize.ISize(wm) = finalSize.BSize(wm) = bulletSize;
    1020           0 :       aMetrics.SetBlockStartAscent(bulletSize + aPadding->BEnd(wm));
    1021           0 :       AppendSpacingToPadding(fm, aPadding);
    1022           0 :       break;
    1023             :     }
    1024             : 
    1025             :     case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
    1026             :     case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
    1027           0 :       ascent = fm->EmAscent();
    1028           0 :       bulletSize = std::max(
    1029           0 :           nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1030           0 :           NSToCoordRound(0.75f * ascent));
    1031           0 :       aPadding->BEnd(wm) = NSToCoordRound(0.125f * ascent);
    1032           0 :       finalSize.ISize(wm) = finalSize.BSize(wm) = bulletSize;
    1033           0 :       if (!wm.IsVertical()) {
    1034           0 :         aMetrics.SetBlockStartAscent(bulletSize + aPadding->BEnd(wm));
    1035             :       }
    1036           0 :       AppendSpacingToPadding(fm, aPadding);
    1037           0 :       break;
    1038             : 
    1039             :     default:
    1040           0 :       GetListItemText(text);
    1041           0 :       finalSize.BSize(wm) = fm->MaxHeight();
    1042           0 :       finalSize.ISize(wm) =
    1043           0 :         nsLayoutUtils::AppUnitWidthOfStringBidi(text, this, *fm, *aRenderingContext);
    1044           0 :       aMetrics.SetBlockStartAscent(wm.IsLineInverted()
    1045           0 :                                      ? fm->MaxDescent() : fm->MaxAscent());
    1046           0 :       break;
    1047             :   }
    1048           0 :   aMetrics.SetSize(wm, finalSize);
    1049             : }
    1050             : 
    1051             : void
    1052           0 : nsBulletFrame::Reflow(nsPresContext* aPresContext,
    1053             :                       ReflowOutput& aMetrics,
    1054             :                       const ReflowInput& aReflowInput,
    1055             :                       nsReflowStatus& aStatus)
    1056             : {
    1057           0 :   MarkInReflow();
    1058           0 :   DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
    1059           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
    1060             : 
    1061           0 :   float inflation = nsLayoutUtils::FontSizeInflationFor(this);
    1062           0 :   SetFontSizeInflation(inflation);
    1063             : 
    1064             :   // Get the base size
    1065           0 :   GetDesiredSize(aPresContext, aReflowInput.mRenderingContext, aMetrics, inflation,
    1066           0 :                  &mPadding);
    1067             : 
    1068             :   // Add in the border and padding; split the top/bottom between the
    1069             :   // ascent and descent to make things look nice
    1070           0 :   WritingMode wm = aReflowInput.GetWritingMode();
    1071           0 :   const LogicalMargin& bp = aReflowInput.ComputedLogicalBorderPadding();
    1072           0 :   mPadding.BStart(wm) += NSToCoordRound(bp.BStart(wm) * inflation);
    1073           0 :   mPadding.IEnd(wm) += NSToCoordRound(bp.IEnd(wm) * inflation);
    1074           0 :   mPadding.BEnd(wm) += NSToCoordRound(bp.BEnd(wm) * inflation);
    1075           0 :   mPadding.IStart(wm) += NSToCoordRound(bp.IStart(wm) * inflation);
    1076             : 
    1077           0 :   WritingMode lineWM = aMetrics.GetWritingMode();
    1078           0 :   LogicalMargin linePadding = mPadding.ConvertTo(lineWM, wm);
    1079           0 :   aMetrics.ISize(lineWM) += linePadding.IStartEnd(lineWM);
    1080           0 :   aMetrics.BSize(lineWM) += linePadding.BStartEnd(lineWM);
    1081           0 :   aMetrics.SetBlockStartAscent(aMetrics.BlockStartAscent() +
    1082           0 :                                linePadding.BStart(lineWM));
    1083             : 
    1084             :   // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
    1085             :   // overflow their font-boxes. It'll do for now; to fix it for real, we really
    1086             :   // should rewrite all the text-handling code here to use gfxTextRun (bug
    1087             :   // 397294).
    1088           0 :   aMetrics.SetOverflowAreasToDesiredBounds();
    1089             : 
    1090           0 :   aStatus.Reset();
    1091           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
    1092           0 : }
    1093             : 
    1094             : /* virtual */ nscoord
    1095           0 : nsBulletFrame::GetMinISize(gfxContext *aRenderingContext)
    1096             : {
    1097           0 :   WritingMode wm = GetWritingMode();
    1098           0 :   ReflowOutput reflowOutput(wm);
    1099           0 :   DISPLAY_MIN_WIDTH(this, reflowOutput.ISize(wm));
    1100           0 :   LogicalMargin padding(wm);
    1101           0 :   GetDesiredSize(PresContext(), aRenderingContext, reflowOutput, 1.0f, &padding);
    1102           0 :   reflowOutput.ISize(wm) += padding.IStartEnd(wm);
    1103           0 :   return reflowOutput.ISize(wm);
    1104             : }
    1105             : 
    1106             : /* virtual */ nscoord
    1107           0 : nsBulletFrame::GetPrefISize(gfxContext *aRenderingContext)
    1108             : {
    1109           0 :   WritingMode wm = GetWritingMode();
    1110           0 :   ReflowOutput metrics(wm);
    1111           0 :   DISPLAY_PREF_WIDTH(this, metrics.ISize(wm));
    1112           0 :   LogicalMargin padding(wm);
    1113           0 :   GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f, &padding);
    1114           0 :   metrics.ISize(wm) += padding.IStartEnd(wm);
    1115           0 :   return metrics.ISize(wm);
    1116             : }
    1117             : 
    1118             : // If a bullet has zero size and is "ignorable" from its styling, we behave
    1119             : // as if it doesn't exist, from a line-breaking/isize-computation perspective.
    1120             : // Otherwise, we use the default implementation, same as nsFrame.
    1121             : static inline bool
    1122           0 : IsIgnoreable(const nsIFrame* aFrame, nscoord aISize)
    1123             : {
    1124           0 :   if (aISize != nscoord(0)) {
    1125           0 :     return false;
    1126             :   }
    1127           0 :   auto listStyle = aFrame->StyleList();
    1128           0 :   return listStyle->mCounterStyle->IsNone() &&
    1129           0 :          !listStyle->GetListStyleImage();
    1130             : }
    1131             : 
    1132             : /* virtual */ void
    1133           0 : nsBulletFrame::AddInlineMinISize(gfxContext* aRenderingContext,
    1134             :                                  nsIFrame::InlineMinISizeData* aData)
    1135             : {
    1136           0 :   nscoord isize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    1137           0 :                     this, nsLayoutUtils::MIN_ISIZE);
    1138           0 :   if (MOZ_LIKELY(!::IsIgnoreable(this, isize))) {
    1139           0 :     aData->DefaultAddInlineMinISize(this, isize);
    1140             :   }
    1141           0 : }
    1142             : 
    1143             : /* virtual */ void
    1144           0 : nsBulletFrame::AddInlinePrefISize(gfxContext* aRenderingContext,
    1145             :                                   nsIFrame::InlinePrefISizeData* aData)
    1146             : {
    1147           0 :   nscoord isize = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    1148           0 :                     this, nsLayoutUtils::PREF_ISIZE);
    1149           0 :   if (MOZ_LIKELY(!::IsIgnoreable(this, isize))) {
    1150           0 :     aData->DefaultAddInlinePrefISize(isize);
    1151             :   }
    1152           0 : }
    1153             : 
    1154             : NS_IMETHODIMP
    1155           0 : nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
    1156             : {
    1157           0 :   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
    1158           0 :     nsCOMPtr<imgIContainer> image;
    1159           0 :     aRequest->GetImage(getter_AddRefs(image));
    1160           0 :     return OnSizeAvailable(aRequest, image);
    1161             :   }
    1162             : 
    1163           0 :   if (aType == imgINotificationObserver::FRAME_UPDATE) {
    1164             :     // The image has changed.
    1165             :     // Invalidate the entire content area. Maybe it's not optimal but it's simple and
    1166             :     // always correct, and I'll be a stunned mullet if it ever matters for performance
    1167           0 :     InvalidateFrame();
    1168             :   }
    1169             : 
    1170           0 :   if (aType == imgINotificationObserver::IS_ANIMATED) {
    1171             :     // Register the image request with the refresh driver now that we know it's
    1172             :     // animated.
    1173           0 :     if (aRequest == mImageRequest) {
    1174           0 :       RegisterImageRequest(/* aKnownToBeAnimated = */ true);
    1175             :     }
    1176             :   }
    1177             : 
    1178           0 :   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
    1179             :     // Unconditionally start decoding for now.
    1180             :     // XXX(seth): We eventually want to decide whether to do this based on
    1181             :     // visibility. We should get that for free from bug 1091236.
    1182           0 :     nsCOMPtr<imgIContainer> container;
    1183           0 :     aRequest->GetImage(getter_AddRefs(container));
    1184           0 :     if (container) {
    1185             :       // Retrieve the intrinsic size of the image.
    1186           0 :       int32_t width = 0;
    1187           0 :       int32_t height = 0;
    1188           0 :       container->GetWidth(&width);
    1189           0 :       container->GetHeight(&height);
    1190             : 
    1191             :       // Request a decode at that size.
    1192           0 :       container->RequestDecodeForSize(IntSize(width, height),
    1193           0 :                                       imgIContainer::DECODE_FLAGS_DEFAULT);
    1194             :     }
    1195             : 
    1196           0 :     InvalidateFrame();
    1197             :   }
    1198             : 
    1199           0 :   if (aType == imgINotificationObserver::DECODE_COMPLETE) {
    1200           0 :     if (nsIDocument* parent = GetOurCurrentDoc()) {
    1201           0 :       nsCOMPtr<imgIContainer> container;
    1202           0 :       aRequest->GetImage(getter_AddRefs(container));
    1203           0 :       if (container) {
    1204           0 :         container->PropagateUseCounters(parent);
    1205             :       }
    1206             :     }
    1207             :   }
    1208             : 
    1209           0 :   return NS_OK;
    1210             : }
    1211             : 
    1212             : NS_IMETHODIMP
    1213           0 : nsBulletFrame::BlockOnload(imgIRequest* aRequest)
    1214             : {
    1215           0 :   if (aRequest != mImageRequest) {
    1216           0 :     return NS_OK;
    1217             :   }
    1218             : 
    1219           0 :   NS_ASSERTION(!mBlockingOnload, "Double BlockOnload for an nsBulletFrame?");
    1220             : 
    1221           0 :   nsIDocument* doc = GetOurCurrentDoc();
    1222           0 :   if (doc) {
    1223           0 :     mBlockingOnload = true;
    1224           0 :     doc->BlockOnload();
    1225             :   }
    1226             : 
    1227           0 :   return NS_OK;
    1228             : }
    1229             : 
    1230             : NS_IMETHODIMP
    1231           0 : nsBulletFrame::UnblockOnload(imgIRequest* aRequest)
    1232             : {
    1233           0 :   if (aRequest != mImageRequest) {
    1234           0 :     return NS_OK;
    1235             :   }
    1236             : 
    1237           0 :   NS_ASSERTION(!mBlockingOnload, "Double UnblockOnload for an nsBulletFrame?");
    1238             : 
    1239           0 :   nsIDocument* doc = GetOurCurrentDoc();
    1240           0 :   if (doc) {
    1241           0 :     doc->UnblockOnload(false);
    1242             :   }
    1243           0 :   mBlockingOnload = false;
    1244             : 
    1245           0 :   return NS_OK;
    1246             : }
    1247             : 
    1248             : nsIDocument*
    1249           0 : nsBulletFrame::GetOurCurrentDoc() const
    1250             : {
    1251           0 :   nsIContent* parentContent = GetParent()->GetContent();
    1252           0 :   return parentContent ? parentContent->GetComposedDoc()
    1253           0 :                        : nullptr;
    1254             : }
    1255             : 
    1256             : nsresult
    1257           0 : nsBulletFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
    1258             : {
    1259           0 :   if (!aImage) return NS_ERROR_INVALID_ARG;
    1260           0 :   if (!aRequest) return NS_ERROR_INVALID_ARG;
    1261             : 
    1262             :   uint32_t status;
    1263           0 :   aRequest->GetImageStatus(&status);
    1264           0 :   if (status & imgIRequest::STATUS_ERROR) {
    1265           0 :     return NS_OK;
    1266             :   }
    1267             : 
    1268             :   nscoord w, h;
    1269           0 :   aImage->GetWidth(&w);
    1270           0 :   aImage->GetHeight(&h);
    1271             : 
    1272           0 :   nsPresContext* presContext = PresContext();
    1273             : 
    1274             :   LogicalSize newsize(GetWritingMode(),
    1275           0 :                       nsSize(nsPresContext::CSSPixelsToAppUnits(w),
    1276           0 :                              nsPresContext::CSSPixelsToAppUnits(h)));
    1277             : 
    1278           0 :   if (mIntrinsicSize != newsize) {
    1279           0 :     mIntrinsicSize = newsize;
    1280             : 
    1281             :     // Now that the size is available (or an error occurred), trigger
    1282             :     // a reflow of the bullet frame.
    1283           0 :     nsIPresShell *shell = presContext->GetPresShell();
    1284           0 :     if (shell) {
    1285           0 :       shell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
    1286           0 :                               NS_FRAME_IS_DIRTY);
    1287             :     }
    1288             :   }
    1289             : 
    1290             :   // Handle animations
    1291           0 :   aImage->SetAnimationMode(presContext->ImageAnimationMode());
    1292             :   // Ensure the animation (if any) is started. Note: There is no
    1293             :   // corresponding call to Decrement for this. This Increment will be
    1294             :   // 'cleaned up' by the Request when it is destroyed, but only then.
    1295           0 :   aRequest->IncrementAnimationConsumers();
    1296             : 
    1297           0 :   return NS_OK;
    1298             : }
    1299             : 
    1300             : void
    1301           0 : nsBulletFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup)
    1302             : {
    1303           0 :   if (!aPresContext)
    1304           0 :     return;
    1305             : 
    1306           0 :   NS_PRECONDITION(nullptr != aLoadGroup, "null OUT parameter pointer");
    1307             : 
    1308           0 :   nsIPresShell *shell = aPresContext->GetPresShell();
    1309             : 
    1310           0 :   if (!shell)
    1311           0 :     return;
    1312             : 
    1313           0 :   nsIDocument *doc = shell->GetDocument();
    1314           0 :   if (!doc)
    1315           0 :     return;
    1316             : 
    1317           0 :   *aLoadGroup = doc->GetDocumentLoadGroup().take();
    1318             : }
    1319             : 
    1320             : float
    1321           0 : nsBulletFrame::GetFontSizeInflation() const
    1322             : {
    1323           0 :   if (!HasFontSizeInflation()) {
    1324           0 :     return 1.0f;
    1325             :   }
    1326           0 :   return GetProperty(FontSizeInflationProperty());
    1327             : }
    1328             : 
    1329             : void
    1330           0 : nsBulletFrame::SetFontSizeInflation(float aInflation)
    1331             : {
    1332           0 :   if (aInflation == 1.0f) {
    1333           0 :     if (HasFontSizeInflation()) {
    1334           0 :       RemoveStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
    1335           0 :       DeleteProperty(FontSizeInflationProperty());
    1336             :     }
    1337           0 :     return;
    1338             :   }
    1339             : 
    1340           0 :   AddStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
    1341           0 :   SetProperty(FontSizeInflationProperty(), aInflation);
    1342             : }
    1343             : 
    1344             : already_AddRefed<imgIContainer>
    1345           0 : nsBulletFrame::GetImage() const
    1346             : {
    1347           0 :   if (mImageRequest && StyleList()->GetListStyleImage()) {
    1348           0 :     nsCOMPtr<imgIContainer> imageCon;
    1349           0 :     mImageRequest->GetImage(getter_AddRefs(imageCon));
    1350           0 :     return imageCon.forget();
    1351             :   }
    1352             : 
    1353           0 :   return nullptr;
    1354             : }
    1355             : 
    1356             : nscoord
    1357           0 : nsBulletFrame::GetLogicalBaseline(WritingMode aWritingMode) const
    1358             : {
    1359           0 :   nscoord ascent = 0, baselinePadding;
    1360           0 :   if (GetStateBits() & BULLET_FRAME_IMAGE_LOADING) {
    1361           0 :     ascent = BSize(aWritingMode);
    1362             :   } else {
    1363             :     RefPtr<nsFontMetrics> fm =
    1364           0 :       nsLayoutUtils::GetFontMetricsForFrame(this, GetFontSizeInflation());
    1365           0 :     CounterStyle* listStyleType = StyleList()->mCounterStyle;
    1366           0 :     switch (listStyleType->GetStyle()) {
    1367             :       case NS_STYLE_LIST_STYLE_NONE:
    1368           0 :         break;
    1369             : 
    1370             :       case NS_STYLE_LIST_STYLE_DISC:
    1371             :       case NS_STYLE_LIST_STYLE_CIRCLE:
    1372             :       case NS_STYLE_LIST_STYLE_SQUARE:
    1373           0 :         ascent = fm->MaxAscent();
    1374           0 :         baselinePadding = NSToCoordRound(float(ascent) / 8.0f);
    1375           0 :         ascent = std::max(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1376           0 :                         NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
    1377           0 :         ascent += baselinePadding;
    1378           0 :         break;
    1379             : 
    1380             :       case NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED:
    1381             :       case NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN:
    1382           0 :         ascent = fm->EmAscent();
    1383           0 :         baselinePadding = NSToCoordRound(0.125f * ascent);
    1384           0 :         ascent = std::max(
    1385           0 :             nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1386           0 :             NSToCoordRound(0.75f * ascent));
    1387           0 :         ascent += baselinePadding;
    1388           0 :         break;
    1389             : 
    1390             :       default:
    1391           0 :         ascent = fm->MaxAscent();
    1392           0 :         break;
    1393             :     }
    1394             :   }
    1395             :   return ascent +
    1396           0 :     GetLogicalUsedMargin(aWritingMode).BStart(aWritingMode);
    1397             : }
    1398             : 
    1399             : void
    1400           0 : nsBulletFrame::GetSpokenText(nsAString& aText)
    1401             : {
    1402           0 :   CounterStyle* style = StyleList()->mCounterStyle;
    1403             :   bool isBullet;
    1404           0 :   style->GetSpokenCounterText(mOrdinal, GetWritingMode(), aText, isBullet);
    1405           0 :   if (isBullet) {
    1406           0 :     if (!style->IsNone()) {
    1407           0 :       aText.Append(' ');
    1408             :     }
    1409             :   } else {
    1410           0 :     nsAutoString prefix, suffix;
    1411           0 :     style->GetPrefix(prefix);
    1412           0 :     style->GetSuffix(suffix);
    1413           0 :     aText = prefix + aText + suffix;
    1414             :   }
    1415           0 : }
    1416             : 
    1417             : void
    1418           0 : nsBulletFrame::RegisterImageRequest(bool aKnownToBeAnimated)
    1419             : {
    1420           0 :   if (mImageRequest) {
    1421             :     // mRequestRegistered is a bitfield; unpack it temporarily so we can take
    1422             :     // the address.
    1423           0 :     bool isRequestRegistered = mRequestRegistered;
    1424             : 
    1425           0 :     if (aKnownToBeAnimated) {
    1426           0 :       nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
    1427           0 :                                           &isRequestRegistered);
    1428             :     } else {
    1429           0 :       nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(),
    1430             :                                                     mImageRequest,
    1431           0 :                                                     &isRequestRegistered);
    1432             :     }
    1433             : 
    1434           0 :     isRequestRegistered = mRequestRegistered;
    1435             :   }
    1436           0 : }
    1437             : 
    1438             : 
    1439             : void
    1440           0 : nsBulletFrame::DeregisterAndCancelImageRequest()
    1441             : {
    1442           0 :   if (mImageRequest) {
    1443             :     // mRequestRegistered is a bitfield; unpack it temporarily so we can take
    1444             :     // the address.
    1445           0 :     bool isRequestRegistered = mRequestRegistered;
    1446             : 
    1447             :     // Deregister our image request from the refresh driver.
    1448           0 :     nsLayoutUtils::DeregisterImageRequest(PresContext(),
    1449             :                                           mImageRequest,
    1450           0 :                                           &isRequestRegistered);
    1451             : 
    1452           0 :     isRequestRegistered = mRequestRegistered;
    1453             : 
    1454             :     // Unblock onload if we blocked it.
    1455           0 :     if (mBlockingOnload) {
    1456           0 :       nsIDocument* doc = GetOurCurrentDoc();
    1457           0 :       if (doc) {
    1458           0 :         doc->UnblockOnload(false);
    1459             :       }
    1460           0 :       mBlockingOnload = false;
    1461             :     }
    1462             : 
    1463             :     // Cancel the image request and forget about it.
    1464           0 :     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
    1465           0 :     mImageRequest = nullptr;
    1466             :   }
    1467           0 : }
    1468             : 
    1469             : 
    1470             : 
    1471             : 
    1472             : 
    1473             : 
    1474           0 : NS_IMPL_ISUPPORTS(nsBulletListener, imgINotificationObserver)
    1475             : 
    1476           0 : nsBulletListener::nsBulletListener() :
    1477           0 :   mFrame(nullptr)
    1478             : {
    1479           0 : }
    1480             : 
    1481           0 : nsBulletListener::~nsBulletListener()
    1482             : {
    1483           0 : }
    1484             : 
    1485             : NS_IMETHODIMP
    1486           0 : nsBulletListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
    1487             : {
    1488           0 :   if (!mFrame) {
    1489           0 :     return NS_ERROR_FAILURE;
    1490             :   }
    1491           0 :   return mFrame->Notify(aRequest, aType, aData);
    1492             : }
    1493             : 
    1494             : NS_IMETHODIMP
    1495           0 : nsBulletListener::BlockOnload(imgIRequest* aRequest)
    1496             : {
    1497           0 :   if (!mFrame) {
    1498           0 :     return NS_ERROR_FAILURE;
    1499             :   }
    1500           0 :   return mFrame->BlockOnload(aRequest);
    1501             : }
    1502             : 
    1503             : NS_IMETHODIMP
    1504           0 : nsBulletListener::UnblockOnload(imgIRequest* aRequest)
    1505             : {
    1506           0 :   if (!mFrame) {
    1507           0 :     return NS_ERROR_FAILURE;
    1508             :   }
    1509           0 :   return mFrame->UnblockOnload(aRequest);
    1510             : }

Generated by: LCOV version 1.13