LCOV - code coverage report
Current view: top level - gfx/thebes - gfxDrawable.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 31 96 32.3 %
Date: 2017-07-14 16:53:18 Functions: 6 15 40.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       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             : #include "gfxDrawable.h"
       7             : #include "gfxASurface.h"
       8             : #include "gfxContext.h"
       9             : #include "gfxPlatform.h"
      10             : #include "gfx2DGlue.h"
      11             : #ifdef MOZ_X11
      12             : #include "cairo.h"
      13             : #include "gfxXlibSurface.h"
      14             : #endif
      15             : #include "mozilla/gfx/Logging.h"
      16             : 
      17             : using namespace mozilla;
      18             : using namespace mozilla::gfx;
      19             : 
      20         108 : gfxSurfaceDrawable::gfxSurfaceDrawable(SourceSurface* aSurface,
      21             :                                        const IntSize aSize,
      22         108 :                                        const gfxMatrix aTransform)
      23             :  : gfxDrawable(aSize)
      24             :  , mSourceSurface(aSurface)
      25         108 :  , mTransform(aTransform)
      26             : {
      27         108 :   if (!mSourceSurface) {
      28           0 :     gfxWarning() << "Creating gfxSurfaceDrawable with null SourceSurface";
      29             :   }
      30         108 : }
      31             : 
      32             : bool
      33           0 : gfxSurfaceDrawable::DrawWithSamplingRect(DrawTarget* aDrawTarget,
      34             :                                          CompositionOp aOp,
      35             :                                          AntialiasMode aAntialiasMode,
      36             :                                          const gfxRect& aFillRect,
      37             :                                          const gfxRect& aSamplingRect,
      38             :                                          ExtendMode aExtendMode,
      39             :                                          const SamplingFilter aSamplingFilter,
      40             :                                          gfxFloat aOpacity)
      41             : {
      42           0 :   if (!mSourceSurface) {
      43           0 :     return true;
      44             :   }
      45             : 
      46             :   // When drawing with CLAMP we can expand the sampling rect to the nearest pixel
      47             :   // without changing the result.
      48           0 :   IntRect intRect = IntRect::RoundOut(aSamplingRect.x, aSamplingRect.y,
      49           0 :                                       aSamplingRect.width, aSamplingRect.height);
      50             : 
      51           0 :   IntSize size = mSourceSurface->GetSize();
      52           0 :   if (!IntRect(IntPoint(), size).Contains(intRect)) {
      53           0 :     return false;
      54             :   }
      55             : 
      56             :   DrawInternal(aDrawTarget, aOp, aAntialiasMode, aFillRect, intRect,
      57           0 :                ExtendMode::CLAMP, aSamplingFilter, aOpacity, gfxMatrix());
      58           0 :   return true;
      59             : }
      60             : 
      61             : bool
      62         108 : gfxSurfaceDrawable::Draw(gfxContext* aContext,
      63             :                          const gfxRect& aFillRect,
      64             :                          ExtendMode aExtendMode,
      65             :                          const SamplingFilter aSamplingFilter,
      66             :                          gfxFloat aOpacity,
      67             :                          const gfxMatrix& aTransform)
      68             : 
      69             : {
      70         108 :   if (!mSourceSurface) {
      71           0 :     return true;
      72             :   }
      73             : 
      74         108 :   DrawInternal(aContext->GetDrawTarget(), aContext->CurrentOp(),
      75         216 :                aContext->CurrentAntialiasMode(), aFillRect, IntRect(),
      76         108 :                aExtendMode, aSamplingFilter, aOpacity, aTransform);
      77         108 :   return true;
      78             : }
      79             : 
      80             : void
      81         108 : gfxSurfaceDrawable::DrawInternal(DrawTarget* aDrawTarget,
      82             :                                  CompositionOp aOp,
      83             :                                  AntialiasMode aAntialiasMode,
      84             :                                  const gfxRect& aFillRect,
      85             :                                  const IntRect& aSamplingRect,
      86             :                                  ExtendMode aExtendMode,
      87             :                                  const SamplingFilter aSamplingFilter,
      88             :                                  gfxFloat aOpacity,
      89             :                                  const gfxMatrix& aTransform)
      90             : {
      91         108 :     Matrix patternTransform = ToMatrix(aTransform * mTransform);
      92         108 :     patternTransform.Invert();
      93             : 
      94             :     SurfacePattern pattern(mSourceSurface, aExtendMode,
      95         216 :                            patternTransform, aSamplingFilter, aSamplingRect);
      96             : 
      97         108 :     Rect fillRect = ToRect(aFillRect);
      98             : 
      99         108 :     if (aOp == CompositionOp::OP_SOURCE && aOpacity == 1.0) {
     100             :         // Emulate cairo operator source which is bound by mask!
     101           0 :         aDrawTarget->ClearRect(fillRect);
     102           0 :         aDrawTarget->FillRect(fillRect, pattern);
     103             :     } else {
     104             :         aDrawTarget->FillRect(fillRect, pattern,
     105         108 :                               DrawOptions(aOpacity, aOp, aAntialiasMode));
     106             :     }
     107         108 : }
     108             : 
     109          18 : gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback,
     110          18 :                                          const IntSize aSize)
     111             :  : gfxDrawable(aSize)
     112          18 :  , mCallback(aCallback)
     113             : {
     114          18 : }
     115             : 
     116             : already_AddRefed<gfxSurfaceDrawable>
     117           0 : gfxCallbackDrawable::MakeSurfaceDrawable(gfxContext *aContext, const SamplingFilter aSamplingFilter)
     118             : {
     119             :     SurfaceFormat format =
     120           0 :         gfxPlatform::GetPlatform()->Optimal2DFormatForContent(gfxContentType::COLOR_ALPHA);
     121             :     RefPtr<DrawTarget> dt =
     122           0 :         aContext->GetDrawTarget()->CreateSimilarDrawTarget(mSize, format);
     123             : 
     124           0 :     if (!dt || !dt->IsValid())
     125           0 :         return nullptr;
     126             : 
     127           0 :     RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
     128           0 :     MOZ_ASSERT(ctx); // already checked for target above
     129           0 :     Draw(ctx, gfxRect(0, 0, mSize.width, mSize.height), ExtendMode::CLAMP,
     130           0 :          aSamplingFilter);
     131             : 
     132           0 :     RefPtr<SourceSurface> surface = dt->Snapshot();
     133           0 :     if (surface) {
     134           0 :         RefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, mSize);
     135           0 :         return drawable.forget();
     136             :     }
     137           0 :     return nullptr;
     138             : }
     139             : 
     140             : static bool
     141          18 : IsRepeatingExtendMode(ExtendMode aExtendMode)
     142             : {
     143          18 :   switch (aExtendMode) {
     144             :   case ExtendMode::REPEAT:
     145             :   case ExtendMode::REPEAT_X:
     146             :   case ExtendMode::REPEAT_Y:
     147           0 :     return true;
     148             :   default:
     149          18 :     return false;
     150             :   }
     151             : }
     152             : 
     153             : bool
     154          18 : gfxCallbackDrawable::Draw(gfxContext* aContext,
     155             :                           const gfxRect& aFillRect,
     156             :                           ExtendMode aExtendMode,
     157             :                           const SamplingFilter aSamplingFilter,
     158             :                           gfxFloat aOpacity,
     159             :                           const gfxMatrix& aTransform)
     160             : {
     161          18 :     if ((IsRepeatingExtendMode(aExtendMode) || aOpacity != 1.0 || aContext->CurrentOp() != CompositionOp::OP_OVER) &&
     162           0 :         !mSurfaceDrawable) {
     163           0 :         mSurfaceDrawable = MakeSurfaceDrawable(aContext, aSamplingFilter);
     164             :     }
     165             : 
     166          18 :     if (mSurfaceDrawable)
     167           0 :         return mSurfaceDrawable->Draw(aContext, aFillRect, aExtendMode,
     168             :                                       aSamplingFilter,
     169           0 :                                       aOpacity, aTransform);
     170             : 
     171          18 :     if (mCallback)
     172          18 :         return (*mCallback)(aContext, aFillRect, aSamplingFilter, aTransform);
     173             : 
     174           0 :     return false;
     175             : }
     176             : 
     177           0 : gfxPatternDrawable::gfxPatternDrawable(gfxPattern* aPattern,
     178           0 :                                        const IntSize aSize)
     179             :  : gfxDrawable(aSize)
     180           0 :  , mPattern(aPattern)
     181             : {
     182           0 : }
     183             : 
     184             : gfxPatternDrawable::~gfxPatternDrawable() = default;
     185             : 
     186             : class DrawingCallbackFromDrawable : public gfxDrawingCallback {
     187             : public:
     188           0 :     explicit DrawingCallbackFromDrawable(gfxDrawable* aDrawable)
     189           0 :      : mDrawable(aDrawable) {
     190           0 :         NS_ASSERTION(aDrawable, "aDrawable is null!");
     191           0 :     }
     192             : 
     193           0 :     ~DrawingCallbackFromDrawable() override = default;
     194             : 
     195           0 :     bool operator()(gfxContext* aContext,
     196             :                     const gfxRect& aFillRect,
     197             :                     const SamplingFilter aSamplingFilter,
     198             :                     const gfxMatrix& aTransform = gfxMatrix()) override
     199             :     {
     200           0 :         return mDrawable->Draw(aContext, aFillRect, ExtendMode::CLAMP,
     201             :                                aSamplingFilter, 1.0,
     202           0 :                                aTransform);
     203             :     }
     204             : private:
     205             :     RefPtr<gfxDrawable> mDrawable;
     206             : };
     207             : 
     208             : already_AddRefed<gfxCallbackDrawable>
     209           0 : gfxPatternDrawable::MakeCallbackDrawable()
     210             : {
     211             :     RefPtr<gfxDrawingCallback> callback =
     212           0 :         new DrawingCallbackFromDrawable(this);
     213             :     RefPtr<gfxCallbackDrawable> callbackDrawable =
     214           0 :         new gfxCallbackDrawable(callback, mSize);
     215           0 :     return callbackDrawable.forget();
     216             : }
     217             : 
     218             : bool
     219           0 : gfxPatternDrawable::Draw(gfxContext* aContext,
     220             :                          const gfxRect& aFillRect,
     221             :                          ExtendMode aExtendMode,
     222             :                          const SamplingFilter aSamplingFilter,
     223             :                          gfxFloat aOpacity,
     224             :                          const gfxMatrix& aTransform)
     225             : {
     226           0 :     DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
     227             : 
     228           0 :     if (!mPattern)
     229           0 :         return false;
     230             : 
     231           0 :     if (IsRepeatingExtendMode(aExtendMode)) {
     232             :         // We can't use mPattern directly: We want our repeated tiles to have
     233             :         // the size mSize, which might not be the case in mPattern.
     234             :         // So we need to draw mPattern into a surface of size mSize, create
     235             :         // a pattern from the surface and draw that pattern.
     236             :         // gfxCallbackDrawable and gfxSurfaceDrawable already know how to do
     237             :         // those things, so we use them here. Drawing mPattern into the surface
     238             :         // will happen through this Draw() method with aRepeat = false.
     239           0 :         RefPtr<gfxCallbackDrawable> callbackDrawable = MakeCallbackDrawable();
     240           0 :         return callbackDrawable->Draw(aContext, aFillRect, aExtendMode,
     241             :                                       aSamplingFilter,
     242           0 :                                       aOpacity, aTransform);
     243             :     }
     244             : 
     245           0 :     gfxMatrix oldMatrix = mPattern->GetMatrix();
     246           0 :     mPattern->SetMatrix(aTransform * oldMatrix);
     247           0 :     DrawOptions drawOptions(aOpacity);
     248           0 :     aDrawTarget.FillRect(ToRect(aFillRect),
     249           0 :                          *mPattern->GetPattern(&aDrawTarget), drawOptions);
     250           0 :     mPattern->SetMatrix(oldMatrix);
     251           0 :     return true;
     252             : }

Generated by: LCOV version 1.13