tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }