|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 |
|
7 #include <QTemporaryFile> |
|
8 #include <QPrinterInfo> |
|
9 |
|
10 #define SET_PRINTER_FEATURES_VIA_PREFS 1 |
|
11 #define PRINTERFEATURES_PREF "print.tmp.printerfeatures" |
|
12 |
|
13 #ifdef MOZ_LOGGING |
|
14 #define FORCE_PR_LOG 1 /* Allow logging in the release build */ |
|
15 #endif /* MOZ_LOGGING */ |
|
16 #include "prlog.h" |
|
17 |
|
18 #include "plstr.h" |
|
19 |
|
20 #include "nsDeviceContextSpecQt.h" |
|
21 |
|
22 #include "prenv.h" /* for PR_GetEnv */ |
|
23 |
|
24 #include "nsReadableUtils.h" |
|
25 #include "nsStringEnumerator.h" |
|
26 #include "nsIServiceManager.h" |
|
27 #include "nsPrintSettingsQt.h" |
|
28 #include "nsIFileStreams.h" |
|
29 #include "nsIFile.h" |
|
30 #include "nsTArray.h" |
|
31 |
|
32 #include <unistd.h> |
|
33 #include <sys/types.h> |
|
34 #include <sys/stat.h> |
|
35 |
|
36 #include "gfxPDFSurface.h" |
|
37 |
|
38 #ifdef PR_LOGGING |
|
39 static PRLogModuleInfo* DeviceContextSpecQtLM = |
|
40 PR_NewLogModule("DeviceContextSpecQt"); |
|
41 #endif /* PR_LOGGING */ |
|
42 /* Macro to make lines shorter */ |
|
43 #define DO_PR_DEBUG_LOG(x) PR_LOG(DeviceContextSpecQtLM, PR_LOG_DEBUG, x) |
|
44 |
|
45 nsDeviceContextSpecQt::nsDeviceContextSpecQt() |
|
46 { |
|
47 DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::nsDeviceContextSpecQt()\n")); |
|
48 } |
|
49 |
|
50 nsDeviceContextSpecQt::~nsDeviceContextSpecQt() |
|
51 { |
|
52 DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::~nsDeviceContextSpecQt()\n")); |
|
53 } |
|
54 |
|
55 NS_IMPL_ISUPPORTS(nsDeviceContextSpecQt, |
|
56 nsIDeviceContextSpec) |
|
57 |
|
58 NS_IMETHODIMP nsDeviceContextSpecQt::GetSurfaceForPrinter( |
|
59 gfxASurface** aSurface) |
|
60 { |
|
61 NS_ENSURE_ARG_POINTER(aSurface); |
|
62 *aSurface = nullptr; |
|
63 |
|
64 double width, height; |
|
65 mPrintSettings->GetEffectivePageSize(&width, &height); |
|
66 |
|
67 // If we're in landscape mode, we'll be rotating the output -- |
|
68 // need to swap width & height. |
|
69 int32_t orientation; |
|
70 mPrintSettings->GetOrientation(&orientation); |
|
71 if (nsIPrintSettings::kLandscapeOrientation == orientation) { |
|
72 double tmp = width; |
|
73 width = height; |
|
74 height = tmp; |
|
75 } |
|
76 |
|
77 // convert twips to points |
|
78 width /= TWIPS_PER_POINT_FLOAT; |
|
79 height /= TWIPS_PER_POINT_FLOAT; |
|
80 |
|
81 DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", mPath, width, height)); |
|
82 |
|
83 QTemporaryFile file; |
|
84 if(!file.open()) { |
|
85 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; |
|
86 } |
|
87 file.setAutoRemove(false); |
|
88 |
|
89 nsresult rv = NS_NewNativeLocalFile( |
|
90 nsDependentCString(file.fileName().toUtf8().constData()), |
|
91 false, |
|
92 getter_AddRefs(mSpoolFile)); |
|
93 if (NS_FAILED(rv)) { |
|
94 file.remove(); |
|
95 return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; |
|
96 } |
|
97 |
|
98 mSpoolName = file.fileName().toUtf8().constData(); |
|
99 |
|
100 mSpoolFile->SetPermissions(0600); |
|
101 |
|
102 nsCOMPtr<nsIFileOutputStream> stream = |
|
103 do_CreateInstance("@mozilla.org/network/file-output-stream;1"); |
|
104 |
|
105 rv = stream->Init(mSpoolFile, -1, -1, 0); |
|
106 if (NS_FAILED(rv)) |
|
107 return rv; |
|
108 |
|
109 int16_t format; |
|
110 mPrintSettings->GetOutputFormat(&format); |
|
111 |
|
112 nsRefPtr<gfxASurface> surface; |
|
113 gfxSize surfaceSize(width, height); |
|
114 |
|
115 if (format == nsIPrintSettings::kOutputFormatNative) { |
|
116 if (mIsPPreview) { |
|
117 // There is nothing to detect on Print Preview, use PS. |
|
118 // TODO: implement for Qt? |
|
119 //format = nsIPrintSettings::kOutputFormatPS; |
|
120 return NS_ERROR_NOT_IMPLEMENTED; |
|
121 } |
|
122 format = nsIPrintSettings::kOutputFormatPDF; |
|
123 } |
|
124 if (format == nsIPrintSettings::kOutputFormatPDF) { |
|
125 surface = new gfxPDFSurface(stream, surfaceSize); |
|
126 } else { |
|
127 return NS_ERROR_NOT_IMPLEMENTED; |
|
128 } |
|
129 |
|
130 NS_ABORT_IF_FALSE(surface, "valid address expected"); |
|
131 |
|
132 surface.swap(*aSurface); |
|
133 return NS_OK; |
|
134 } |
|
135 |
|
136 NS_IMETHODIMP nsDeviceContextSpecQt::Init(nsIWidget* aWidget, |
|
137 nsIPrintSettings* aPS, |
|
138 bool aIsPrintPreview) |
|
139 { |
|
140 DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::Init(aPS=%p)\n", aPS)); |
|
141 |
|
142 mPrintSettings = aPS; |
|
143 mIsPPreview = aIsPrintPreview; |
|
144 |
|
145 // This is only set by embedders |
|
146 bool toFile; |
|
147 aPS->GetPrintToFile(&toFile); |
|
148 |
|
149 mToPrinter = !toFile && !aIsPrintPreview; |
|
150 |
|
151 nsCOMPtr<nsPrintSettingsQt> printSettingsQt(do_QueryInterface(aPS)); |
|
152 if (!printSettingsQt) |
|
153 return NS_ERROR_NO_INTERFACE; |
|
154 return NS_OK; |
|
155 } |
|
156 |
|
157 NS_IMETHODIMP nsDeviceContextSpecQt::GetPath(const char** aPath) |
|
158 { |
|
159 *aPath = mPath; |
|
160 return NS_OK; |
|
161 } |
|
162 |
|
163 NS_IMETHODIMP nsDeviceContextSpecQt::BeginDocument( |
|
164 const nsAString& aTitle, |
|
165 char16_t* aPrintToFileName, |
|
166 int32_t aStartPage, |
|
167 int32_t aEndPage) |
|
168 { |
|
169 if (mToPrinter) { |
|
170 return NS_ERROR_NOT_IMPLEMENTED; |
|
171 } |
|
172 return NS_OK; |
|
173 } |
|
174 |
|
175 NS_IMETHODIMP nsDeviceContextSpecQt::EndDocument() |
|
176 { |
|
177 if (mToPrinter) { |
|
178 return NS_ERROR_NOT_IMPLEMENTED; |
|
179 } |
|
180 // Handle print-to-file ourselves for the benefit of embedders |
|
181 nsXPIDLString targetPath; |
|
182 nsCOMPtr<nsIFile> destFile; |
|
183 mPrintSettings->GetToFileName(getter_Copies(targetPath)); |
|
184 |
|
185 nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), |
|
186 false, getter_AddRefs(destFile)); |
|
187 NS_ENSURE_SUCCESS(rv, rv); |
|
188 |
|
189 nsAutoString destLeafName; |
|
190 rv = destFile->GetLeafName(destLeafName); |
|
191 NS_ENSURE_SUCCESS(rv, rv); |
|
192 |
|
193 nsCOMPtr<nsIFile> destDir; |
|
194 rv = destFile->GetParent(getter_AddRefs(destDir)); |
|
195 NS_ENSURE_SUCCESS(rv, rv); |
|
196 |
|
197 rv = mSpoolFile->MoveTo(destDir, destLeafName); |
|
198 NS_ENSURE_SUCCESS(rv, rv); |
|
199 |
|
200 // This is the standard way to get the UNIX umask. Ugh. |
|
201 mode_t mask = umask(0); |
|
202 umask(mask); |
|
203 // If you're not familiar with umasks, they contain the bits of what NOT |
|
204 // to set in the permissions |
|
205 // (thats because files and directories have different numbers of bits |
|
206 // for their permissions) |
|
207 destFile->SetPermissions(0666 & ~(mask)); |
|
208 |
|
209 return NS_OK; |
|
210 } |
|
211 |
|
212 // Printer Enumerator |
|
213 nsPrinterEnumeratorQt::nsPrinterEnumeratorQt() |
|
214 { |
|
215 } |
|
216 |
|
217 NS_IMPL_ISUPPORTS(nsPrinterEnumeratorQt, nsIPrinterEnumerator) |
|
218 |
|
219 NS_IMETHODIMP nsPrinterEnumeratorQt::GetPrinterNameList( |
|
220 nsIStringEnumerator** aPrinterNameList) |
|
221 { |
|
222 NS_ENSURE_ARG_POINTER(aPrinterNameList); |
|
223 *aPrinterNameList = nullptr; |
|
224 |
|
225 QList<QPrinterInfo> qprinters = QPrinterInfo::availablePrinters(); |
|
226 if (qprinters.size() == 0) |
|
227 return NS_ERROR_NOT_AVAILABLE; |
|
228 |
|
229 nsTArray<nsString>* printers = |
|
230 new nsTArray<nsString>(qprinters.size()); |
|
231 |
|
232 for (int32_t i = 0; i < qprinters.size(); ++i) { |
|
233 printers->AppendElement( |
|
234 nsDependentString( |
|
235 (const char16_t*)qprinters[i].printerName().constData())); |
|
236 } |
|
237 |
|
238 return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); |
|
239 } |
|
240 |
|
241 NS_IMETHODIMP nsPrinterEnumeratorQt::GetDefaultPrinterName( |
|
242 char16_t** aDefaultPrinterName) |
|
243 { |
|
244 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorQt::GetDefaultPrinterName()\n")); |
|
245 NS_ENSURE_ARG_POINTER(aDefaultPrinterName); |
|
246 |
|
247 QString defprinter = QPrinterInfo::defaultPrinter().printerName(); |
|
248 *aDefaultPrinterName = ToNewUnicode(nsDependentString( |
|
249 (const char16_t*)defprinter.constData())); |
|
250 |
|
251 DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", |
|
252 NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get())); |
|
253 |
|
254 return NS_OK; |
|
255 } |
|
256 |
|
257 NS_IMETHODIMP nsPrinterEnumeratorQt::InitPrintSettingsFromPrinter( |
|
258 const char16_t* aPrinterName, |
|
259 nsIPrintSettings* aPrintSettings) |
|
260 { |
|
261 DO_PR_DEBUG_LOG(("nsPrinterEnumeratorQt::InitPrintSettingsFromPrinter()")); |
|
262 // XXX Leave NS_OK for now |
|
263 // Probably should use NS_ERROR_NOT_IMPLEMENTED |
|
264 return NS_OK; |
|
265 } |
|
266 |
|
267 NS_IMETHODIMP nsPrinterEnumeratorQt::DisplayPropertiesDlg( |
|
268 const char16_t* aPrinter, |
|
269 nsIPrintSettings* aPrintSettings) |
|
270 { |
|
271 return NS_ERROR_NOT_IMPLEMENTED; |
|
272 } |
|
273 |