forked from mirrors/gecko-dev
		
	 00ef028ed3
			
		
	
	
		00ef028ed3
		
	
	
	
	
		
			
			The core of this change is in gfxContext.*: - change gfxContext::CurrentMatrix() and gfxContext::SetMatrix() to return and take a Matrix respectively, instead of converting to and from a gfxMatrix (which uses doubles). These functions therefore will now match the native representation of the transform in gfxContext. - add two new functions CurrentMatrixDouble() and SetMatrixDouble() that do what the old CurrentMatrix() and SetMatrix() used to do, i.e. convert between the float matrix and the double matrix. The rest of the change is just updating the call sites to avoid round- tripping between floats and doubles where possible. Call sites that are hard to fix are migrated to the new XXXDouble functions which preserves the existing behaviour. MozReview-Commit-ID: 5sbBpLUus3U
		
			
				
	
	
		
			275 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			275 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "BasicLayersImpl.h"
 | |
| #include <new>                          // for operator new
 | |
| #include "Layers.h"                     // for Layer, etc
 | |
| #include "basic/BasicImplData.h"        // for BasicImplData
 | |
| #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 | |
| #include "mozilla/DebugOnly.h"          // for DebugOnly
 | |
| #include "mozilla/layers/CompositorTypes.h"
 | |
| #include "mozilla/layers/ISurfaceAllocator.h"
 | |
| #include "AutoMaskData.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace layers {
 | |
| 
 | |
| using namespace mozilla::gfx;
 | |
| 
 | |
| bool
 | |
| GetMaskData(Layer* aMaskLayer,
 | |
|             const Point& aDeviceOffset,
 | |
|             AutoMoz2DMaskData* aMaskData)
 | |
| {
 | |
|   if (aMaskLayer) {
 | |
|     RefPtr<SourceSurface> surface =
 | |
|       static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSourceSurface();
 | |
|     if (surface) {
 | |
|       Matrix transform;
 | |
|       Matrix4x4 effectiveTransform = aMaskLayer->GetEffectiveTransform();
 | |
|       DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform);
 | |
|       NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
 | |
|       transform.PostTranslate(-aDeviceOffset.x, -aDeviceOffset.y);
 | |
|       aMaskData->Construct(transform, surface);
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| already_AddRefed<SourceSurface>
 | |
| GetMaskForLayer(Layer* aLayer, Matrix* aMaskTransform)
 | |
| {
 | |
|   if (!aLayer->GetMaskLayer()) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(aMaskTransform);
 | |
| 
 | |
|   AutoMoz2DMaskData mask;
 | |
|   if (GetMaskData(aLayer->GetMaskLayer(), Point(), &mask)) {
 | |
|     *aMaskTransform = mask.GetTransform();
 | |
|     RefPtr<SourceSurface> surf = mask.GetSurface();
 | |
|     return surf.forget();
 | |
|   }
 | |
| 
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| void
 | |
| PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
 | |
| {
 | |
|   AutoMoz2DMaskData mask;
 | |
|   if (GetMaskData(aMaskLayer, Point(), &mask)) {
 | |
|     aContext->SetMatrix(mask.GetTransform());
 | |
|     aContext->Mask(mask.GetSurface(), aOpacity);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // if there is no mask, just paint normally
 | |
|   aContext->Paint(aOpacity);
 | |
| }
 | |
| 
 | |
| void
 | |
| FillRectWithMask(DrawTarget* aDT,
 | |
|                  const Rect& aRect,
 | |
|                  const Color& aColor,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  SourceSurface* aMaskSource,
 | |
|                  const Matrix* aMaskTransform)
 | |
| {
 | |
|   if (aMaskSource && aMaskTransform) {
 | |
|     aDT->PushClipRect(aRect);
 | |
|     Matrix oldTransform = aDT->GetTransform();
 | |
| 
 | |
|     aDT->SetTransform(*aMaskTransform);
 | |
|     aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions);
 | |
|     aDT->SetTransform(oldTransform);
 | |
|     aDT->PopClip();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   aDT->FillRect(aRect, ColorPattern(aColor), aOptions);
 | |
| }
 | |
| void
 | |
| FillRectWithMask(DrawTarget* aDT,
 | |
|                  const gfx::Point& aDeviceOffset,
 | |
|                  const Rect& aRect,
 | |
|                  const Color& aColor,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  Layer* aMaskLayer)
 | |
| {
 | |
|   AutoMoz2DMaskData mask;
 | |
|   if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
 | |
|     const Matrix& maskTransform = mask.GetTransform();
 | |
|     FillRectWithMask(aDT, aRect, aColor, aOptions, mask.GetSurface(), &maskTransform);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   FillRectWithMask(aDT, aRect, aColor, aOptions);
 | |
| }
 | |
| 
 | |
| void
 | |
| FillRectWithMask(DrawTarget* aDT,
 | |
|                  const Rect& aRect,
 | |
|                  SourceSurface* aSurface,
 | |
|                  SamplingFilter aSamplingFilter,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  ExtendMode aExtendMode,
 | |
|                  SourceSurface* aMaskSource,
 | |
|                  const Matrix* aMaskTransform,
 | |
|                  const Matrix* aSurfaceTransform)
 | |
| {
 | |
|   if (aMaskSource && aMaskTransform) {
 | |
|     aDT->PushClipRect(aRect);
 | |
|     Matrix oldTransform = aDT->GetTransform();
 | |
| 
 | |
|     Matrix inverseMask = *aMaskTransform;
 | |
|     inverseMask.Invert();
 | |
| 
 | |
|     Matrix transform = oldTransform * inverseMask;
 | |
|     if (aSurfaceTransform) {
 | |
|       transform = (*aSurfaceTransform) * transform;
 | |
|     }
 | |
| 
 | |
|     SurfacePattern source(aSurface, aExtendMode, transform, aSamplingFilter);
 | |
| 
 | |
|     aDT->SetTransform(*aMaskTransform);
 | |
|     aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
 | |
| 
 | |
|     aDT->SetTransform(oldTransform);
 | |
|     aDT->PopClip();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   aDT->FillRect(aRect,
 | |
|                 SurfacePattern(aSurface, aExtendMode,
 | |
|                                aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
 | |
|                                aSamplingFilter), aOptions);
 | |
| }
 | |
| 
 | |
| void
 | |
| FillRectWithMask(DrawTarget* aDT,
 | |
|                  const gfx::Point& aDeviceOffset,
 | |
|                  const Rect& aRect,
 | |
|                  SourceSurface* aSurface,
 | |
|                  SamplingFilter aSamplingFilter,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  Layer* aMaskLayer)
 | |
| {
 | |
|   AutoMoz2DMaskData mask;
 | |
|   if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
 | |
|     const Matrix& maskTransform = mask.GetTransform();
 | |
|     FillRectWithMask(aDT, aRect, aSurface, aSamplingFilter, aOptions,
 | |
|                      ExtendMode::CLAMP,
 | |
|                      mask.GetSurface(), &maskTransform);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   FillRectWithMask(aDT, aRect, aSurface, aSamplingFilter, aOptions,
 | |
|                    ExtendMode::CLAMP);
 | |
| }
 | |
| 
 | |
| void
 | |
| FillPathWithMask(DrawTarget* aDT,
 | |
|                  const Path* aPath,
 | |
|                  const Rect& aClipRect,
 | |
|                  const Color& aColor,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  SourceSurface* aMaskSource,
 | |
|                  const Matrix* aMaskTransform)
 | |
| {
 | |
|   if (aMaskSource && aMaskTransform) {
 | |
|     aDT->PushClipRect(aClipRect);
 | |
|     Matrix oldTransform = aDT->GetTransform();
 | |
| 
 | |
|     aDT->SetTransform(*aMaskTransform);
 | |
|     aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions);
 | |
|     aDT->SetTransform(oldTransform);
 | |
|     aDT->PopClip();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   aDT->Fill(aPath, ColorPattern(aColor), aOptions);
 | |
| }
 | |
| 
 | |
| void
 | |
| FillPathWithMask(DrawTarget* aDT,
 | |
|                  const Path* aPath,
 | |
|                  const Rect& aClipRect,
 | |
|                  SourceSurface* aSurface,
 | |
|                  SamplingFilter aSamplingFilter,
 | |
|                  const DrawOptions& aOptions,
 | |
|                  ExtendMode aExtendMode,
 | |
|                  SourceSurface* aMaskSource,
 | |
|                  const Matrix* aMaskTransform,
 | |
|                  const Matrix* aSurfaceTransform)
 | |
| {
 | |
|   if (aMaskSource && aMaskTransform) {
 | |
|     aDT->PushClipRect(aClipRect);
 | |
|     Matrix oldTransform = aDT->GetTransform();
 | |
| 
 | |
|     Matrix inverseMask = *aMaskTransform;
 | |
|     inverseMask.Invert();
 | |
| 
 | |
|     Matrix transform = oldTransform * inverseMask;
 | |
|     if (aSurfaceTransform) {
 | |
|       transform = (*aSurfaceTransform) * transform;
 | |
|     }
 | |
| 
 | |
|     SurfacePattern source(aSurface, aExtendMode, transform, aSamplingFilter);
 | |
| 
 | |
|     aDT->SetTransform(*aMaskTransform);
 | |
|     aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
 | |
|     aDT->SetTransform(oldTransform);
 | |
|     aDT->PopClip();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   aDT->Fill(aPath,
 | |
|             SurfacePattern(aSurface, aExtendMode,
 | |
|                            aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
 | |
|                            aSamplingFilter), aOptions);
 | |
| }
 | |
| 
 | |
| BasicImplData*
 | |
| ToData(Layer* aLayer)
 | |
| {
 | |
|   return static_cast<BasicImplData*>(aLayer->ImplData());
 | |
| }
 | |
| 
 | |
| gfx::CompositionOp
 | |
| GetEffectiveOperator(Layer* aLayer)
 | |
| {
 | |
|   CompositionOp op = aLayer->GetEffectiveMixBlendMode();
 | |
| 
 | |
|   if (op != CompositionOp::OP_OVER) {
 | |
|     return op;
 | |
|   }
 | |
| 
 | |
|   return ToData(aLayer)->GetOperator();
 | |
| }
 | |
| 
 | |
| ShadowableLayer*
 | |
| ToShadowable(Layer* aLayer)
 | |
| {
 | |
|   return aLayer->AsShadowableLayer();
 | |
| }
 | |
| 
 | |
| bool
 | |
| ShouldShadow(Layer* aLayer)
 | |
| {
 | |
|   if (!ToShadowable(aLayer)) {
 | |
|     MOZ_ASSERT(aLayer->GetType() == Layer::TYPE_READBACK,
 | |
|                "Only expect not to shadow ReadbackLayers");
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| } // namespace layers
 | |
| } // namespace mozilla
 |