Bug 1758688 [wpt PR 33067] - [FedCM] Make revoke a non-static method, a=testonly
[gecko.git] / gfx / thebes / PrintTargetCG.mm
blobdcb196fca4399815cb88acb3f4753e8fa55dc449
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/. */
6 #include "PrintTargetCG.h"
8 #include "cairo.h"
9 #include "cairo-quartz.h"
10 #include "mozilla/gfx/HelpersCairo.h"
11 #include "nsObjCExceptions.h"
12 #include "nsString.h"
14 namespace mozilla {
15 namespace gfx {
17 PrintTargetCG::PrintTargetCG(PMPrintSession aPrintSession, PMPageFormat aPageFormat,
18                              PMPrintSettings aPrintSettings, const IntSize& aSize)
19     : PrintTarget(/* aCairoSurface */ nullptr, aSize),
20       mPrintSession(aPrintSession),
21       mPageFormat(aPageFormat),
22       mPrintSettings(aPrintSettings) {
23   NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
25   MOZ_ASSERT(mPrintSession && mPageFormat && mPrintSettings);
27   ::PMRetain(mPrintSession);
28   ::PMRetain(mPageFormat);
29   ::PMRetain(mPrintSettings);
31   // TODO: Add memory reporting like gfxQuartzSurface.
32   // RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
34   NS_OBJC_END_TRY_IGNORE_BLOCK;
37 PrintTargetCG::~PrintTargetCG() {
38   NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
40   ::PMRelease(mPrintSession);
41   ::PMRelease(mPageFormat);
42   ::PMRelease(mPrintSettings);
44   NS_OBJC_END_TRY_IGNORE_BLOCK;
47 /* static */ already_AddRefed<PrintTargetCG> PrintTargetCG::CreateOrNull(
48     PMPrintSession aPrintSession, PMPageFormat aPageFormat, PMPrintSettings aPrintSettings,
49     const IntSize& aSize) {
50   if (!Factory::CheckSurfaceSize(aSize)) {
51     return nullptr;
52   }
54   RefPtr<PrintTargetCG> target =
55       new PrintTargetCG(aPrintSession, aPageFormat, aPrintSettings, aSize);
57   return target.forget();
60 static size_t PutBytesNull(void* info, const void* buffer, size_t count) { return count; }
62 already_AddRefed<DrawTarget> PrintTargetCG::GetReferenceDrawTarget() {
63   if (!mRefDT) {
64     const IntSize size(1, 1);
66     CGDataConsumerCallbacks callbacks = {PutBytesNull, nullptr};
67     CGDataConsumerRef consumer = CGDataConsumerCreate(nullptr, &callbacks);
68     CGContextRef pdfContext = CGPDFContextCreate(consumer, nullptr, nullptr);
69     CGDataConsumerRelease(consumer);
71     cairo_surface_t* similar =
72         cairo_quartz_surface_create_for_cg_context(pdfContext, size.width, size.height);
74     CGContextRelease(pdfContext);
76     if (cairo_surface_status(similar)) {
77       return nullptr;
78     }
80     RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForCairoSurface(similar, size);
82     // The DT addrefs the surface, so we need drop our own reference to it:
83     cairo_surface_destroy(similar);
85     if (!dt || !dt->IsValid()) {
86       return nullptr;
87     }
88     mRefDT = dt.forget();
89   }
91   return do_AddRef(mRefDT);
94 nsresult PrintTargetCG::BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName,
95                                       int32_t aStartPage, int32_t aEndPage) {
96   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
98   // Print Core of Application Service sent print job with names exceeding
99   // 255 bytes. This is a workaround until fix it.
100   // (https://openradar.appspot.com/34428043)
101   nsAutoString adjustedTitle;
102   PrintTarget::AdjustPrintJobNameForIPP(aTitle, adjustedTitle);
104   if (!adjustedTitle.IsEmpty()) {
105     CFStringRef cfString = ::CFStringCreateWithCharacters(
106         NULL, reinterpret_cast<const UniChar*>(adjustedTitle.BeginReading()),
107         adjustedTitle.Length());
108     if (cfString) {
109       ::PMPrintSettingsSetJobName(mPrintSettings, cfString);
110       ::CFRelease(cfString);
111     }
112   }
114   OSStatus status;
115   status = ::PMSetFirstPage(mPrintSettings, aStartPage, false);
116   NS_ASSERTION(status == noErr, "PMSetFirstPage failed");
117   status = ::PMSetLastPage(mPrintSettings, aEndPage, false);
118   NS_ASSERTION(status == noErr, "PMSetLastPage failed");
120   status = ::PMSessionBeginCGDocumentNoDialog(mPrintSession, mPrintSettings, mPageFormat);
122   return status == noErr ? NS_OK : NS_ERROR_ABORT;
124   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
127 nsresult PrintTargetCG::EndPrinting() {
128   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
130   ::PMSessionEndDocumentNoDialog(mPrintSession);
131   return NS_OK;
133   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
136 nsresult PrintTargetCG::AbortPrinting() {
137 #ifdef DEBUG
138   mHasActivePage = false;
139 #endif
140   return EndPrinting();
143 nsresult PrintTargetCG::BeginPage() {
144   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
146   PMSessionError(mPrintSession);
147   OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, NULL);
148   if (status != noErr) {
149     return NS_ERROR_ABORT;
150   }
152   CGContextRef context;
153   // This call will fail if it wasn't called between the PMSessionBeginPage/
154   // PMSessionEndPage calls:
155   ::PMSessionGetCGGraphicsContext(mPrintSession, &context);
157   if (!context) {
158     return NS_ERROR_FAILURE;
159   }
161   unsigned int width = static_cast<unsigned int>(mSize.width);
162   unsigned int height = static_cast<unsigned int>(mSize.height);
164   // Initially, origin is at bottom-left corner of the paper.
165   // Here, we translate it to top-left corner of the paper.
166   CGContextTranslateCTM(context, 0, height);
167   CGContextScaleCTM(context, 1.0, -1.0);
169   cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(context, width, height);
171   if (cairo_surface_status(surface)) {
172     return NS_ERROR_FAILURE;
173   }
175   mCairoSurface = surface;
177   return PrintTarget::BeginPage();
179   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
182 nsresult PrintTargetCG::EndPage() {
183   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
185   cairo_surface_finish(mCairoSurface);
186   mCairoSurface = nullptr;
188   OSStatus status = ::PMSessionEndPageNoDialog(mPrintSession);
189   if (status != noErr) {
190     return NS_ERROR_ABORT;
191   }
193   return PrintTarget::EndPage();
195   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
198 }  // namespace gfx
199 }  // namespace mozilla