diff options
Diffstat (limited to 'widget/cocoa/nsDeviceContextSpecX.mm')
-rw-r--r-- | widget/cocoa/nsDeviceContextSpecX.mm | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/widget/cocoa/nsDeviceContextSpecX.mm b/widget/cocoa/nsDeviceContextSpecX.mm new file mode 100644 index 0000000000..d252adef69 --- /dev/null +++ b/widget/cocoa/nsDeviceContextSpecX.mm @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; 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 "nsDeviceContextSpecX.h" + +#include "mozilla/gfx/PrintTargetCG.h" +#include "mozilla/RefPtr.h" +#include "nsCRT.h" +#include <unistd.h> + +#include "nsQueryObject.h" +#include "nsIServiceManager.h" +#include "nsPrintSettingsX.h" + +// This must be the last include: +#include "nsObjCExceptions.h" + +using namespace mozilla; +using namespace mozilla::gfx; + +nsDeviceContextSpecX::nsDeviceContextSpecX() +: mPrintSession(NULL) +, mPageFormat(kPMNoPageFormat) +, mPrintSettings(kPMNoPrintSettings) +{ +} + +nsDeviceContextSpecX::~nsDeviceContextSpecX() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + if (mPrintSession) + ::PMRelease(mPrintSession); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +NS_IMPL_ISUPPORTS(nsDeviceContextSpecX, nsIDeviceContextSpec) + +NS_IMETHODIMP nsDeviceContextSpecX::Init(nsIWidget *aWidget, + nsIPrintSettings* aPS, + bool aIsPrintPreview) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + RefPtr<nsPrintSettingsX> settings(do_QueryObject(aPS)); + if (!settings) + return NS_ERROR_NO_INTERFACE; + + mPrintSession = settings->GetPMPrintSession(); + ::PMRetain(mPrintSession); + mPageFormat = settings->GetPMPageFormat(); + mPrintSettings = settings->GetPMPrintSettings(); + + return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} + +NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle, + const nsAString& aPrintToFileName, + int32_t aStartPage, + int32_t aEndPage) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + if (!aTitle.IsEmpty()) { + CFStringRef cfString = + ::CFStringCreateWithCharacters(NULL, reinterpret_cast<const UniChar*>(aTitle.BeginReading()), + aTitle.Length()); + if (cfString) { + ::PMPrintSettingsSetJobName(mPrintSettings, cfString); + ::CFRelease(cfString); + } + } + + OSStatus status; + status = ::PMSetFirstPage(mPrintSettings, aStartPage, false); + NS_ASSERTION(status == noErr, "PMSetFirstPage failed"); + status = ::PMSetLastPage(mPrintSettings, aEndPage, false); + NS_ASSERTION(status == noErr, "PMSetLastPage failed"); + + status = ::PMSessionBeginCGDocumentNoDialog(mPrintSession, mPrintSettings, mPageFormat); + if (status != noErr) + return NS_ERROR_ABORT; + + return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} + +NS_IMETHODIMP nsDeviceContextSpecX::EndDocument() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + ::PMSessionEndDocumentNoDialog(mPrintSession); + return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} + +NS_IMETHODIMP nsDeviceContextSpecX::BeginPage() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + PMSessionError(mPrintSession); + OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, NULL); + if (status != noErr) return NS_ERROR_ABORT; + return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} + +NS_IMETHODIMP nsDeviceContextSpecX::EndPage() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + OSStatus status = ::PMSessionEndPageNoDialog(mPrintSession); + if (status != noErr) return NS_ERROR_ABORT; + return NS_OK; + + NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; +} + +void nsDeviceContextSpecX::GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + PMRect paperRect; + ::PMGetAdjustedPaperRect(mPageFormat, &paperRect); + + *aTop = paperRect.top, *aLeft = paperRect.left; + *aBottom = paperRect.bottom, *aRight = paperRect.right; + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +already_AddRefed<PrintTarget> nsDeviceContextSpecX::MakePrintTarget() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + double top, left, bottom, right; + GetPaperRect(&top, &left, &bottom, &right); + const double width = right - left; + const double height = bottom - top; + IntSize size = IntSize::Floor(width, height); + + CGContextRef context; + ::PMSessionGetCGGraphicsContext(mPrintSession, &context); + + if (context) { + // Initially, origin is at bottom-left corner of the paper. + // Here, we translate it to top-left corner of the paper. + CGContextTranslateCTM(context, 0, height); + CGContextScaleCTM(context, 1.0, -1.0); + return PrintTargetCG::CreateOrNull(context, size); + } + + // Apparently we do need this branch - bug 368933. + return PrintTargetCG::CreateOrNull(size, SurfaceFormat::A8R8G8B8_UINT32); + + NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; +} |