/* -*- Mode: C++; tab-width: 2; 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 "nsIDeviceContextSpec.h" #include "gfxPoint.h" #include "mozilla/gfx/PrintPromise.h" #include "nsError.h" #include "nsIPrintSettings.h" #include "mozilla/Components.h" #include "mozilla/TaskQueue.h" using mozilla::MakeRefPtr; using mozilla::gfx::PrintEndDocumentPromise; // We have some platform specific code here rather than in the appropriate // nsIDeviceContextSpec subclass. We structure the code this way so that // nsIDeviceContextSpecProxy gets the correct behavior without us having to // instantiate a platform specific nsIDeviceContextSpec subclass in content // processes. That is necessary for sandboxing. float nsIDeviceContextSpec::GetPrintingScale() { #ifdef XP_WIN if (mPrintSettings->GetOutputFormat() != nsIPrintSettings::kOutputFormatPDF # ifdef MOZ_ENABLE_SKIA_PDF && !mPrintViaSkPDF # endif ) { // The print settings will have the resolution stored from the real device. int32_t resolution; mPrintSettings->GetResolution(&resolution); return float(resolution) / GetDPI(); } #endif return 72.0f / GetDPI(); } gfxPoint nsIDeviceContextSpec::GetPrintingTranslate() { #ifdef XP_WIN // The underlying surface on windows is the size of the printable region. When // the region is smaller than the actual paper size the (0, 0) coordinate // refers top-left of that unwritable region. To instead have (0, 0) become // the top-left of the actual paper, translate it's coordinate system by the // unprintable region's width. double marginTop, marginLeft; mPrintSettings->GetUnwriteableMarginTop(&marginTop); mPrintSettings->GetUnwriteableMarginLeft(&marginLeft); int32_t resolution; mPrintSettings->GetResolution(&resolution); return gfxPoint(-marginLeft * resolution, -marginTop * resolution); #else return gfxPoint(0, 0); #endif } RefPtr nsIDeviceContextSpec::EndDocumentPromiseFromResult(nsresult aResult, const char* aSite) { return NS_SUCCEEDED(aResult) ? PrintEndDocumentPromise::CreateAndResolve(true, aSite) : PrintEndDocumentPromise::CreateAndReject(aResult, aSite); } RefPtr nsIDeviceContextSpec::EndDocumentAsync( const char* aCallSite, AsyncEndDocumentFunction aFunction) { auto promise = MakeRefPtr("PrintEndDocumentPromise"); NS_DispatchBackgroundTask( NS_NewRunnableFunction( "EndDocumentAsync", [promise, function = std::move(aFunction)]() mutable { const auto result = function(); if (NS_SUCCEEDED(result)) { promise->Resolve(true, __func__); } else { promise->Reject(result, __func__); } }), NS_DISPATCH_EVENT_MAY_BLOCK); return promise; }