gfxQuartzNativeDrawing.cpp (2898B)
1 /* -*- Mode: C++; tab-width: 20; 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 #include "gfxQuartzNativeDrawing.h" 7 #include "gfxPlatform.h" 8 #include "mozilla/gfx/Helpers.h" 9 10 using namespace mozilla::gfx; 11 using namespace mozilla; 12 13 gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(DrawTarget& aDrawTarget, 14 const Rect& nativeRect) 15 : mDrawTarget(&aDrawTarget), mNativeRect(nativeRect), mCGContext(nullptr) {} 16 17 CGContextRef gfxQuartzNativeDrawing::BeginNativeDrawing() { 18 NS_ASSERTION(!mCGContext, 19 "BeginNativeDrawing called when drawing already in progress"); 20 21 DrawTarget* dt = mDrawTarget; 22 if (dt->IsTiledDrawTarget() || dt->GetBackendType() != BackendType::SKIA || 23 dt->IsRecording()) { 24 // We need a DrawTarget that we can get a CGContextRef from: 25 Matrix transform = dt->GetTransform(); 26 27 mNativeRect = transform.TransformBounds(mNativeRect); 28 mNativeRect.RoundOut(); 29 if (mNativeRect.IsEmpty()) { 30 return nullptr; 31 } 32 33 mTempDrawTarget = Factory::CreateDrawTarget( 34 BackendType::SKIA, 35 IntSize::Truncate(mNativeRect.width, mNativeRect.height), 36 SurfaceFormat::B8G8R8A8); 37 if (!mTempDrawTarget) { 38 return nullptr; 39 } 40 41 transform.PostTranslate(-mNativeRect.x, -mNativeRect.y); 42 mTempDrawTarget->SetTransform(transform); 43 44 dt = mTempDrawTarget; 45 } else { 46 // Clip the DT in case BorrowedCGContext needs to create a new layer. 47 // This prevents it from creating a new layer the size of the window. 48 // But make sure that this clip is device pixel aligned. 49 Matrix transform = dt->GetTransform(); 50 51 Rect deviceRect = transform.TransformBounds(mNativeRect); 52 deviceRect.RoundOut(); 53 mNativeRect = transform.Inverse().TransformBounds(deviceRect); 54 mDrawTarget->PushClipRect(mNativeRect); 55 } 56 57 MOZ_ASSERT(dt->GetBackendType() == BackendType::SKIA); 58 mCGContext = mBorrowedContext.Init(dt); 59 60 if (NS_WARN_IF(!mCGContext)) { 61 // Failed borrowing CG context, so we need to clean up. 62 if (!mTempDrawTarget) { 63 mDrawTarget->PopClip(); 64 } 65 return nullptr; 66 } 67 68 return mCGContext; 69 } 70 71 void gfxQuartzNativeDrawing::EndNativeDrawing() { 72 NS_ASSERTION(mCGContext, 73 "EndNativeDrawing called without BeginNativeDrawing"); 74 75 mBorrowedContext.Finish(); 76 if (mTempDrawTarget) { 77 RefPtr<SourceSurface> source = mTempDrawTarget->Snapshot(); 78 79 AutoRestoreTransform autoRestore(mDrawTarget); 80 mDrawTarget->SetTransform(Matrix()); 81 mDrawTarget->DrawSurface(source, mNativeRect, 82 Rect(0, 0, mNativeRect.width, mNativeRect.height)); 83 } else { 84 mDrawTarget->PopClip(); 85 } 86 }