summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxQuartzNativeDrawing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/gfxQuartzNativeDrawing.cpp')
-rw-r--r--gfx/thebes/gfxQuartzNativeDrawing.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/gfx/thebes/gfxQuartzNativeDrawing.cpp b/gfx/thebes/gfxQuartzNativeDrawing.cpp
new file mode 100644
index 0000000000..0505e372ba
--- /dev/null
+++ b/gfx/thebes/gfxQuartzNativeDrawing.cpp
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 "gfxQuartzNativeDrawing.h"
+#include "gfxPlatform.h"
+#include "mozilla/gfx/Helpers.h"
+
+using namespace mozilla::gfx;
+using namespace mozilla;
+
+gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(DrawTarget& aDrawTarget,
+ const Rect& nativeRect)
+ : mDrawTarget(&aDrawTarget), mNativeRect(nativeRect), mCGContext(nullptr) {}
+
+CGContextRef gfxQuartzNativeDrawing::BeginNativeDrawing() {
+ NS_ASSERTION(!mCGContext,
+ "BeginNativeDrawing called when drawing already in progress");
+
+ DrawTarget* dt = mDrawTarget;
+ if (dt->IsDualDrawTarget() || dt->IsTiledDrawTarget() || dt->IsCaptureDT() ||
+ dt->GetBackendType() != BackendType::SKIA || dt->IsRecording()) {
+ // We need a DrawTarget that we can get a CGContextRef from:
+ Matrix transform = dt->GetTransform();
+
+ mNativeRect = transform.TransformBounds(mNativeRect);
+ mNativeRect.RoundOut();
+ if (mNativeRect.IsEmpty()) {
+ return nullptr;
+ }
+
+ mTempDrawTarget = Factory::CreateDrawTarget(
+ BackendType::SKIA,
+ IntSize::Truncate(mNativeRect.width, mNativeRect.height),
+ SurfaceFormat::B8G8R8A8);
+ if (!mTempDrawTarget) {
+ return nullptr;
+ }
+
+ transform.PostTranslate(-mNativeRect.x, -mNativeRect.y);
+ mTempDrawTarget->SetTransform(transform);
+
+ dt = mTempDrawTarget;
+ } else {
+ // Clip the DT in case BorrowedCGContext needs to create a new layer.
+ // This prevents it from creating a new layer the size of the window.
+ // But make sure that this clip is device pixel aligned.
+ Matrix transform = dt->GetTransform();
+
+ Rect deviceRect = transform.TransformBounds(mNativeRect);
+ deviceRect.RoundOut();
+ mNativeRect = transform.Inverse().TransformBounds(deviceRect);
+ mDrawTarget->PushClipRect(mNativeRect);
+ }
+
+ MOZ_ASSERT(dt->GetBackendType() == BackendType::SKIA);
+ mCGContext = mBorrowedContext.Init(dt);
+
+ if (NS_WARN_IF(!mCGContext)) {
+ // Failed borrowing CG context, so we need to clean up.
+ if (!mTempDrawTarget) {
+ mDrawTarget->PopClip();
+ }
+ return nullptr;
+ }
+
+ return mCGContext;
+}
+
+void gfxQuartzNativeDrawing::EndNativeDrawing() {
+ NS_ASSERTION(mCGContext,
+ "EndNativeDrawing called without BeginNativeDrawing");
+
+ mBorrowedContext.Finish();
+ if (mTempDrawTarget) {
+ RefPtr<SourceSurface> source = mTempDrawTarget->Snapshot();
+
+ AutoRestoreTransform autoRestore(mDrawTarget);
+ mDrawTarget->SetTransform(Matrix());
+ mDrawTarget->DrawSurface(source, mNativeRect,
+ Rect(0, 0, mNativeRect.width, mNativeRect.height));
+ } else {
+ mDrawTarget->PopClip();
+ }
+}