forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			226 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
	
		
			8.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 "DrawTargetOffset.h"
 | |
| #include "Logging.h"
 | |
| #include "PathHelpers.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace gfx {
 | |
| 
 | |
| DrawTargetOffset::DrawTargetOffset() = default;
 | |
| 
 | |
| bool DrawTargetOffset::Init(DrawTarget* aDrawTarget, IntPoint aOrigin) {
 | |
|   mDrawTarget = aDrawTarget;
 | |
|   mOrigin = aOrigin;
 | |
|   mDrawTarget->SetTransform(Matrix::Translation(-mOrigin.x, -mOrigin.y));
 | |
|   mFormat = mDrawTarget->GetFormat();
 | |
|   SetPermitSubpixelAA(IsOpaque(mFormat));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| already_AddRefed<SourceSurface> DrawTargetOffset::Snapshot() {
 | |
|   RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
 | |
| 
 | |
|   if (!snapshot) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return MakeAndAddRef<SourceSurfaceOffset>(snapshot, mOrigin);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::DetachAllSnapshots() {}
 | |
| 
 | |
| // Skip the mClippedOut check since this is only used for Flush() which
 | |
| // should happen even if we're clipped.
 | |
| #define OFFSET_COMMAND(command) \
 | |
|   void DrawTargetOffset::command() { mDrawTarget->command(); }
 | |
| #define OFFSET_COMMAND1(command, type1) \
 | |
|   void DrawTargetOffset::command(type1 arg1) { mDrawTarget->command(arg1); }
 | |
| #define OFFSET_COMMAND3(command, type1, type2, type3)                  \
 | |
|   void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3) { \
 | |
|     mDrawTarget->command(arg1, arg2, arg3);                            \
 | |
|   }
 | |
| #define OFFSET_COMMAND4(command, type1, type2, type3, type4)         \
 | |
|   void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3, \
 | |
|                                  type4 arg4) {                       \
 | |
|     mDrawTarget->command(arg1, arg2, arg3, arg4);                    \
 | |
|   }
 | |
| #define OFFSET_COMMAND5(command, type1, type2, type3, type4, type5)  \
 | |
|   void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3, \
 | |
|                                  type4 arg4, type5 arg5) {           \
 | |
|     mDrawTarget->command(arg1, arg2, arg3, arg4, arg5);              \
 | |
|   }
 | |
| 
 | |
| OFFSET_COMMAND(Flush)
 | |
| OFFSET_COMMAND1(ClearRect, const Rect&)
 | |
| OFFSET_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point,
 | |
|                 const DrawOptions&)
 | |
| OFFSET_COMMAND4(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&,
 | |
|                 const DrawOptions&)
 | |
| OFFSET_COMMAND5(StrokeGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&,
 | |
|                 const StrokeOptions&, const DrawOptions&)
 | |
| OFFSET_COMMAND3(FillRoundedRect, const RoundedRect&, const Pattern&,
 | |
|                 const DrawOptions&)
 | |
| 
 | |
| bool DrawTargetOffset::Draw3DTransformedSurface(SourceSurface* aSrc,
 | |
|                                                 const Matrix4x4& aMatrix) {
 | |
|   return mDrawTarget->Draw3DTransformedSurface(aSrc, aMatrix);
 | |
| }
 | |
| 
 | |
| OFFSET_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
 | |
| 
 | |
| void DrawTargetOffset::DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
 | |
|                                   const Point& aDestPoint,
 | |
|                                   const DrawOptions& aOptions) {
 | |
|   auto clone = mTransform;
 | |
|   bool invertible = clone.Invert();
 | |
|   // aSourceRect is in filter space. The filter outputs from aSourceRect need
 | |
|   // to be drawn at aDestPoint in user space.
 | |
|   Rect userSpaceSource = Rect(aDestPoint, aSourceRect.Size());
 | |
|   if (invertible) {
 | |
|     // Try to reduce the source rect so that it's not much bigger
 | |
|     // than the draw target. The result is not minimal. Examples
 | |
|     // are left as an exercise for the reader.
 | |
|     auto destRect = Rect(mDrawTarget->GetRect() + mOrigin);
 | |
|     Rect userSpaceBounds = clone.TransformBounds(destRect);
 | |
|     userSpaceSource = userSpaceSource.Intersect(userSpaceBounds);
 | |
|   }
 | |
| 
 | |
|   // Compute how much we moved the top-left of the source rect by, and use that
 | |
|   // to compute the new dest point, and move our intersected source rect back
 | |
|   // into the (new) filter space.
 | |
|   Point shift = userSpaceSource.TopLeft() - aDestPoint;
 | |
|   Rect filterSpaceSource =
 | |
|       Rect(aSourceRect.TopLeft() + shift, userSpaceSource.Size());
 | |
|   mDrawTarget->DrawFilter(aNode, filterSpaceSource, aDestPoint + shift,
 | |
|                           aOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PushClip(const Path* aPath) {
 | |
|   mDrawTarget->PushClip(aPath);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PushClipRect(const Rect& aRect) {
 | |
|   mDrawTarget->PushClipRect(aRect);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PopClip() { mDrawTarget->PopClip(); }
 | |
| 
 | |
| void DrawTargetOffset::CopySurface(SourceSurface* aSurface,
 | |
|                                    const IntRect& aSourceRect,
 | |
|                                    const IntPoint& aDestination) {
 | |
|   IntPoint tileOrigin = mOrigin;
 | |
|   // CopySurface ignores the transform, account for that here.
 | |
|   mDrawTarget->CopySurface(aSurface, aSourceRect, aDestination - tileOrigin);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::SetTransform(const Matrix& aTransform) {
 | |
|   Matrix mat = aTransform;
 | |
|   mat.PostTranslate(Float(-mOrigin.x), Float(-mOrigin.y));
 | |
|   mDrawTarget->SetTransform(mat);
 | |
| 
 | |
|   DrawTarget::SetTransform(aTransform);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::SetPermitSubpixelAA(bool aPermitSubpixelAA) {
 | |
|   mDrawTarget->SetPermitSubpixelAA(aPermitSubpixelAA);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::DrawSurface(SourceSurface* aSurface, const Rect& aDest,
 | |
|                                    const Rect& aSource,
 | |
|                                    const DrawSurfaceOptions& aSurfaceOptions,
 | |
|                                    const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->DrawSurface(aSurface, aDest, aSource, aSurfaceOptions,
 | |
|                            aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::FillRect(const Rect& aRect, const Pattern& aPattern,
 | |
|                                 const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->FillRect(aRect, aPattern, aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::Stroke(const Path* aPath, const Pattern& aPattern,
 | |
|                               const StrokeOptions& aStrokeOptions,
 | |
|                               const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->Stroke(aPath, aPattern, aStrokeOptions, aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::StrokeRect(const Rect& aRect, const Pattern& aPattern,
 | |
|                                   const StrokeOptions& aStrokeOptions,
 | |
|                                   const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->StrokeRect(aRect, aPattern, aStrokeOptions, aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::StrokeLine(const Point& aStart, const Point& aEnd,
 | |
|                                   const Pattern& aPattern,
 | |
|                                   const StrokeOptions& aStrokeOptions,
 | |
|                                   const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->StrokeLine(aStart, aEnd, aPattern, aStrokeOptions, aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::Fill(const Path* aPath, const Pattern& aPattern,
 | |
|                             const DrawOptions& aDrawOptions) {
 | |
|   mDrawTarget->Fill(aPath, aPattern, aDrawOptions);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PushLayer(bool aOpaque, Float aOpacity,
 | |
|                                  SourceSurface* aMask,
 | |
|                                  const Matrix& aMaskTransform,
 | |
|                                  const IntRect& aBounds, bool aCopyBackground) {
 | |
|   IntRect bounds = aBounds - mOrigin;
 | |
| 
 | |
|   mDrawTarget->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, bounds,
 | |
|                          aCopyBackground);
 | |
|   SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
 | |
| }
 | |
| 
 | |
| already_AddRefed<SourceSurface> DrawTargetOffset::IntoLuminanceSource(
 | |
|     LuminanceType aLuminanceType, float aOpacity) {
 | |
|   RefPtr<SourceSurface> surface =
 | |
|       mDrawTarget->IntoLuminanceSource(aLuminanceType, aOpacity);
 | |
| 
 | |
|   if (!surface) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return MakeAndAddRef<SourceSurfaceOffset>(surface, mOrigin);
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PushLayerWithBlend(bool aOpaque, Float aOpacity,
 | |
|                                           SourceSurface* aMask,
 | |
|                                           const Matrix& aMaskTransform,
 | |
|                                           const IntRect& aBounds,
 | |
|                                           bool aCopyBackground,
 | |
|                                           CompositionOp aOp) {
 | |
|   IntRect bounds = aBounds - mOrigin;
 | |
| 
 | |
|   mDrawTarget->PushLayerWithBlend(aOpaque, aOpacity, aMask, aMaskTransform,
 | |
|                                   bounds, aCopyBackground, aOp);
 | |
|   SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
 | |
| }
 | |
| 
 | |
| void DrawTargetOffset::PopLayer() {
 | |
|   mDrawTarget->PopLayer();
 | |
|   SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
 | |
| }
 | |
| 
 | |
| RefPtr<DrawTarget> DrawTargetOffset::CreateClippedDrawTarget(
 | |
|     const Rect& aBounds, SurfaceFormat aFormat) {
 | |
|   RefPtr<DrawTarget> result;
 | |
|   RefPtr<DrawTarget> dt =
 | |
|       mDrawTarget->CreateClippedDrawTarget(aBounds, aFormat);
 | |
|   if (dt) {
 | |
|     result = gfx::Factory::CreateOffsetDrawTarget(dt, mOrigin);
 | |
|     if (result) {
 | |
|       result->SetTransform(mTransform);
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| }  // namespace gfx
 | |
| }  // namespace mozilla
 | 
