LCOV - code coverage report
Current view: top level - layout/svg - nsSVGMaskFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 7 101 6.9 %
Date: 2017-07-14 16:53:18 Functions: 3 9 33.3 %
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             : // Main header first:
       7             : #include "nsSVGMaskFrame.h"
       8             : 
       9             : // Keep others in (case-insensitive) order:
      10             : #include "AutoReferenceChainGuard.h"
      11             : #include "gfx2DGlue.h"
      12             : #include "gfxContext.h"
      13             : #include "mozilla/gfx/2D.h"
      14             : #include "mozilla/RefPtr.h"
      15             : #include "nsSVGEffects.h"
      16             : #include "mozilla/dom/SVGMaskElement.h"
      17             : 
      18             : using namespace mozilla;
      19             : using namespace mozilla::dom;
      20             : using namespace mozilla::gfx;
      21             : using namespace mozilla::image;
      22             : 
      23             : static LuminanceType
      24           0 : GetLuminanceType(uint8_t aNSMaskType)
      25             : {
      26           0 :   switch (aNSMaskType) {
      27             :     case NS_STYLE_MASK_TYPE_LUMINANCE:
      28           0 :       return LuminanceType::LUMINANCE;
      29             :     case NS_STYLE_COLOR_INTERPOLATION_LINEARRGB:
      30           0 :       return LuminanceType::LINEARRGB;
      31             :     default:
      32             :     {
      33           0 :       NS_WARNING("Unknown SVG mask type, defaulting to luminance");
      34           0 :       return LuminanceType::LUMINANCE;
      35             :     }
      36             :   }
      37             : }
      38             : 
      39             : nsIFrame*
      40           2 : NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      41             : {
      42           2 :   return new (aPresShell) nsSVGMaskFrame(aContext);
      43             : }
      44             : 
      45           2 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame)
      46             : 
      47             : already_AddRefed<SourceSurface>
      48           0 : nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
      49             : {
      50             :   // Make sure we break reference loops and over long reference chains:
      51             :   static int16_t sRefChainLengthCounter = AutoReferenceChainGuard::noChain;
      52             :   AutoReferenceChainGuard refChainGuard(this, &mInUse,
      53           0 :                                         &sRefChainLengthCounter);
      54           0 :   if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
      55             :     // Break reference chain
      56           0 :     return nullptr;
      57             :   }
      58             : 
      59           0 :   gfxRect maskArea = GetMaskArea(aParams.maskedFrame);
      60           0 :   gfxContext* context = aParams.ctx;
      61             :   // Get the clip extents in device space:
      62             :   // Minimizing the mask surface extents (using both the current clip extents
      63             :   // and maskArea) is important for performance.
      64           0 :   context->Save();
      65           0 :   nsSVGUtils::SetClipRect(context, aParams.toUserSpace, maskArea);
      66           0 :   context->SetMatrix(gfxMatrix());
      67           0 :   gfxRect maskSurfaceRect = context->GetClipExtents();
      68           0 :   maskSurfaceRect.RoundOut();
      69           0 :   context->Restore();
      70             : 
      71             :   bool resultOverflows;
      72             :   IntSize maskSurfaceSize =
      73           0 :     nsSVGUtils::ConvertToSurfaceSize(maskSurfaceRect.Size(), &resultOverflows);
      74             : 
      75           0 :   if (resultOverflows || maskSurfaceSize.IsEmpty()) {
      76             :     // Return value other then DrawResult::SUCCESS, so the caller can skip
      77             :     // painting the masked frame(aParams.maskedFrame).
      78           0 :     return nullptr;
      79             :   }
      80             : 
      81             :   uint8_t maskType;
      82           0 :   if (aParams.maskMode == NS_STYLE_MASK_MODE_MATCH_SOURCE) {
      83           0 :     maskType = StyleSVGReset()->mMaskType;
      84             :   } else {
      85           0 :     maskType = aParams.maskMode == NS_STYLE_MASK_MODE_LUMINANCE
      86           0 :                ? NS_STYLE_MASK_TYPE_LUMINANCE : NS_STYLE_MASK_TYPE_ALPHA;
      87             :   }
      88             : 
      89           0 :   RefPtr<DrawTarget> maskDT;
      90           0 :   if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
      91           0 :     maskDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
      92           0 :                maskSurfaceSize, SurfaceFormat::B8G8R8A8);
      93             :   } else {
      94           0 :     maskDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
      95           0 :                maskSurfaceSize, SurfaceFormat::A8);
      96             :   }
      97             : 
      98           0 :   if (!maskDT || !maskDT->IsValid()) {
      99           0 :     return nullptr;
     100             :   }
     101             : 
     102             :   gfxMatrix maskSurfaceMatrix =
     103           0 :     context->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
     104             : 
     105           0 :   RefPtr<gfxContext> tmpCtx = gfxContext::CreateOrNull(maskDT);
     106           0 :   MOZ_ASSERT(tmpCtx); // already checked the draw target above
     107           0 :   tmpCtx->SetMatrix(maskSurfaceMatrix);
     108             : 
     109           0 :   mMatrixForChildren = GetMaskTransform(aParams.maskedFrame) *
     110           0 :                        aParams.toUserSpace;
     111             : 
     112           0 :   for (nsIFrame* kid = mFrames.FirstChild(); kid;
     113             :        kid = kid->GetNextSibling()) {
     114             :     // The CTM of each frame referencing us can be different
     115           0 :     nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
     116           0 :     if (SVGFrame) {
     117           0 :       SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
     118             :     }
     119           0 :     gfxMatrix m = mMatrixForChildren;
     120           0 :     if (kid->GetContent()->IsSVGElement()) {
     121           0 :       m = static_cast<nsSVGElement*>(kid->GetContent())->
     122           0 :             PrependLocalTransformsTo(m, eUserSpaceToParent);
     123             :     }
     124           0 :     nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m, aParams.imgParams);
     125             :   }
     126             : 
     127           0 :   RefPtr<SourceSurface> surface;
     128           0 :   if (maskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
     129           0 :     if (StyleSVG()->mColorInterpolation ==
     130             :         NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
     131           0 :       maskType = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
     132             :     }
     133             : 
     134             :     RefPtr<SourceSurface> maskSnapshot =
     135           0 :       maskDT->IntoLuminanceSource(GetLuminanceType(maskType),
     136           0 :                                   aParams.opacity);
     137           0 :     if (!maskSnapshot) {
     138           0 :       return nullptr;
     139             :     }
     140           0 :     surface = maskSnapshot.forget();
     141             :   } else {
     142           0 :     maskDT->SetTransform(Matrix());
     143           0 :     maskDT->FillRect(Rect(0, 0, maskSurfaceSize.width, maskSurfaceSize.height), ColorPattern(Color(1.0f, 1.0f, 1.0f, aParams.opacity)), DrawOptions(1, CompositionOp::OP_IN));
     144           0 :     RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
     145           0 :     if (!maskSnapshot) {
     146           0 :       return nullptr;
     147             :     }
     148           0 :     surface = maskSnapshot.forget();
     149             :   }
     150             : 
     151             :   // Moz2D transforms in the opposite direction to Thebes
     152           0 :   if (!maskSurfaceMatrix.Invert()) {
     153           0 :     return nullptr;
     154             :   }
     155             : 
     156           0 :   *aParams.maskTransform = ToMatrix(maskSurfaceMatrix);
     157           0 :   return surface.forget();
     158             : }
     159             : 
     160             : gfxRect
     161           0 : nsSVGMaskFrame::GetMaskArea(nsIFrame* aMaskedFrame)
     162             : {
     163           0 :   SVGMaskElement *maskElem = static_cast<SVGMaskElement*>(mContent);
     164             : 
     165             :   uint16_t units =
     166           0 :     maskElem->mEnumAttributes[SVGMaskElement::MASKUNITS].GetAnimValue();
     167           0 :   gfxRect bbox;
     168           0 :   if (units == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
     169             :     bbox =
     170             :       nsSVGUtils::GetBBox(aMaskedFrame,
     171             :                           nsSVGUtils::eUseFrameBoundsForOuterSVG |
     172           0 :                           nsSVGUtils::eBBoxIncludeFillGeometry);
     173             :   }
     174             : 
     175             :   // Bounds in the user space of aMaskedFrame
     176             :   gfxRect maskArea = nsSVGUtils::GetRelativeRect(units,
     177           0 :                        &maskElem->mLengthAttributes[SVGMaskElement::ATTR_X],
     178           0 :                        bbox, aMaskedFrame);
     179             : 
     180           0 :   return maskArea;
     181             : }
     182             : 
     183             : nsresult
     184           0 : nsSVGMaskFrame::AttributeChanged(int32_t  aNameSpaceID,
     185             :                                  nsIAtom* aAttribute,
     186             :                                  int32_t  aModType)
     187             : {
     188           0 :   if (aNameSpaceID == kNameSpaceID_None &&
     189           0 :       (aAttribute == nsGkAtoms::x ||
     190           0 :        aAttribute == nsGkAtoms::y ||
     191           0 :        aAttribute == nsGkAtoms::width ||
     192           0 :        aAttribute == nsGkAtoms::height||
     193           0 :        aAttribute == nsGkAtoms::maskUnits ||
     194           0 :        aAttribute == nsGkAtoms::maskContentUnits)) {
     195           0 :     nsSVGEffects::InvalidateDirectRenderingObservers(this);
     196             :   }
     197             : 
     198           0 :   return nsSVGContainerFrame::AttributeChanged(aNameSpaceID,
     199           0 :                                                aAttribute, aModType);
     200             : }
     201             : 
     202             : #ifdef DEBUG
     203             : void
     204           2 : nsSVGMaskFrame::Init(nsIContent*       aContent,
     205             :                      nsContainerFrame* aParent,
     206             :                      nsIFrame*         aPrevInFlow)
     207             : {
     208           2 :   NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::mask),
     209             :                "Content is not an SVG mask");
     210             : 
     211           2 :   nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow);
     212           2 : }
     213             : #endif /* DEBUG */
     214             : 
     215             : gfxMatrix
     216           0 : nsSVGMaskFrame::GetCanvasTM()
     217             : {
     218           0 :   return mMatrixForChildren;
     219             : }
     220             : 
     221             : gfxMatrix
     222           0 : nsSVGMaskFrame::GetMaskTransform(nsIFrame* aMaskedFrame)
     223             : {
     224           0 :   SVGMaskElement *content = static_cast<SVGMaskElement*>(mContent);
     225             : 
     226             :   nsSVGEnum* maskContentUnits =
     227           0 :     &content->mEnumAttributes[SVGMaskElement::MASKCONTENTUNITS];
     228             : 
     229           0 :   return nsSVGUtils::AdjustMatrixForUnits(gfxMatrix(), maskContentUnits,
     230           0 :                                           aMaskedFrame);
     231             : }

Generated by: LCOV version 1.13