gecko-dev/gfx/thebes/gfxQuartzNativeDrawing.cpp
Markus Stange 1cdb518fb7 Bug 1370757 - Only push device aligned clips. r=lsalzman
The new clip from bug 1364007 can cause us to clip to a rectangle that's not
aligned to device pixels. With the current rect inflation, we didn't notice,
but if we want to remove the inflation then we need to make sure to round out
the rect that we clip to.

MozReview-Commit-ID: BO9zds8fiKI

--HG--
extra : rebase_source : f71f283ef73cf58dbc2cc05d06ea9bc864fd5084
2017-06-06 19:19:51 -04:00

93 lines
2.9 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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->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();
}
}