Mercurial > projects > dwt-mac
comparison dwt/printing/Printer.d @ 45:d8635bb48c7c
Merge with SWT 3.5
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Mon, 01 Dec 2008 17:07:00 +0100 |
parents | db5a898b2119 |
children | cfa563df4fdd |
comparison
equal
deleted
inserted
replaced
44:ca5e494f2bbf | 45:d8635bb48c7c |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
18 import dwt.graphics.Device; | 18 import dwt.graphics.Device; |
19 import dwt.graphics.DeviceData; | 19 import dwt.graphics.DeviceData; |
20 import dwt.graphics.GCData; | 20 import dwt.graphics.GCData; |
21 import dwt.graphics.Point; | 21 import dwt.graphics.Point; |
22 import dwt.graphics.Rectangle; | 22 import dwt.graphics.Rectangle; |
23 import dwt.internal.cocoa.NSAffineTransform; | |
23 import dwt.internal.cocoa.NSArray; | 24 import dwt.internal.cocoa.NSArray; |
25 import dwt.internal.cocoa.NSBezierPath; | |
26 import dwt.internal.cocoa.NSData; | |
27 import dwt.internal.cocoa.NSGraphicsContext; | |
28 import dwt.internal.cocoa.NSKeyedUnarchiver; | |
29 import dwt.internal.cocoa.NSPoint; | |
30 import dwt.internal.cocoa.NSPrintInfo; | |
31 import dwt.internal.cocoa.NSPrintOperation; | |
24 import dwt.internal.cocoa.NSPrinter; | 32 import dwt.internal.cocoa.NSPrinter; |
33 import dwt.internal.cocoa.NSRect; | |
34 import dwt.internal.cocoa.NSSize; | |
25 import dwt.internal.cocoa.NSString; | 35 import dwt.internal.cocoa.NSString; |
36 import dwt.internal.cocoa.NSView; | |
37 import dwt.internal.cocoa.NSWindow; | |
38 import dwt.internal.cocoa.OS; | |
26 | 39 |
27 /** | 40 /** |
28 * Instances of this class are used to print to a printer. | 41 * Instances of this class are used to print to a printer. |
29 * Applications create a GC on a printer using <code>new GC(printer)</code> | 42 * Applications create a GC on a printer using <code>new GC(printer)</code> |
30 * and then draw on the printer GC using the usual graphics calls. | 43 * and then draw on the printer GC using the usual graphics calls. |
41 * when those instances are no longer required. | 54 * when those instances are no longer required. |
42 * </p> | 55 * </p> |
43 * | 56 * |
44 * @see PrinterData | 57 * @see PrinterData |
45 * @see PrintDialog | 58 * @see PrintDialog |
46 */ | 59 * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a> |
47 public final class Printer : Device { | 60 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
61 */ | |
62 public final class Printer extends Device { | |
48 PrinterData data; | 63 PrinterData data; |
49 NSPrinter printer; | 64 NSPrinter printer; |
50 bool inPage, isGCCreated; | 65 NSPrintInfo printInfo; |
66 NSPrintOperation operation; | |
67 NSView view; | |
68 NSWindow window; | |
69 bool isGCCreated; | |
51 | 70 |
52 static final String DRIVER = "Mac"; | 71 static final String DRIVER = "Mac"; |
53 static final String PRINTER_DRIVER = "Printer"; | |
54 static final String FILE_DRIVER = "File"; | |
55 static final String PREVIEW_DRIVER = "Preview"; | |
56 static final String FAX_DRIVER = "Fax"; | |
57 | 72 |
58 /** | 73 /** |
59 * Returns an array of <code>PrinterData</code> objects | 74 * Returns an array of <code>PrinterData</code> objects |
60 * representing all available printers. | 75 * representing all available printers. |
61 * | 76 * |
62 * @return the list of available printers | 77 * @return the list of available printers |
63 */ | 78 */ |
64 public static PrinterData[] getPrinterList() { | 79 public static PrinterData[] getPrinterList() { |
65 NSArray printers = NSPrinter.printerNames(); | 80 NSArray printers = NSPrinter.printerNames(); |
66 int count = printers.count(); | 81 int count = (int)/*64*/printers.count(); |
67 PrinterData[] result = new PrinterData[count]; | 82 PrinterData[] result = new PrinterData[count]; |
68 for (int i = 0; i < count; i++) { | 83 for (int i = 0; i < count; i++) { |
69 NSString str = new NSString(printers.objectAtIndex(i)); | 84 NSString str = new NSString(printers.objectAtIndex(i)); |
70 char[] buffer = new char[str.length()]; | 85 result[i] = new PrinterData(DRIVER, str.getString()); |
71 str.getCharacters_(buffer); | |
72 result[i] = new PrinterData(DRIVER, new String(buffer)); | |
73 } | 86 } |
74 return result; | 87 return result; |
75 } | 88 } |
76 | 89 |
77 /** | 90 /** |
82 * @return the default printer data or null | 95 * @return the default printer data or null |
83 * | 96 * |
84 * @since 2.1 | 97 * @since 2.1 |
85 */ | 98 */ |
86 public static PrinterData getDefaultPrinterData() { | 99 public static PrinterData getDefaultPrinterData() { |
87 //TODO - get default | 100 NSPrinter printer = NSPrintInfo.defaultPrinter(); |
88 PrinterData[] printers = getPrinterList(); | 101 if (printer is null) return null; |
89 if (printers.length > 0) return printers[0]; | 102 NSString str = printer.name(); |
90 return null; | 103 return new PrinterData(DRIVER, str.getString()); |
91 } | 104 |
92 //static int packData(int handle, byte[] buffer, int offset) { | 105 } |
93 // int length = OS.GetHandleSize (handle); | |
94 // buffer[offset++] = cast(byte)((length & 0xFF) >> 0); | |
95 // buffer[offset++] = cast(byte)((length & 0xFF00) >> 8); | |
96 // buffer[offset++] = cast(byte)((length & 0xFF0000) >> 16); | |
97 // buffer[offset++] = cast(byte)((length & 0xFF000000) >> 24); | |
98 // int [] ptr = new int [1]; | |
99 // OS.HLock(handle); | |
100 // OS.memmove(ptr, handle, 4); | |
101 // byte[] buffer1 = new byte[length]; | |
102 // OS.memmove(buffer1, ptr [0], length); | |
103 // OS.HUnlock(handle); | |
104 // System.arraycopy(buffer1, 0, buffer, offset, length); | |
105 // return offset + length; | |
106 //} | |
107 //static int unpackData(int[] handle, byte[] buffer, int offset) { | |
108 // int length = | |
109 // ((buffer[offset++] & 0xFF) << 0) | | |
110 // ((buffer[offset++] & 0xFF) << 8) | | |
111 // ((buffer[offset++] & 0xFF) << 16) | | |
112 // ((buffer[offset++] & 0xFF) << 24); | |
113 // handle[0] = OS.NewHandle(length); | |
114 // if (handle[0] is 0) DWT.error(DWT.ERROR_NO_HANDLES); | |
115 // int[] ptr = new int[1]; | |
116 // OS.HLock(handle[0]); | |
117 // OS.memmove(ptr, handle[0], 4); | |
118 // byte[] buffer1 = new byte[length]; | |
119 // System.arraycopy(buffer, offset, buffer1, 0, length); | |
120 // OS.memmove(ptr[0], buffer1, length); | |
121 // OS.HUnlock(handle[0]); | |
122 // return offset + length; | |
123 //} | |
124 | 106 |
125 /** | 107 /** |
126 * Constructs a new printer representing the default printer. | 108 * Constructs a new printer representing the default printer. |
127 * <p> | 109 * <p> |
128 * You must dispose the printer when it is no longer required. | 110 * You must dispose the printer when it is no longer required. |
132 * <li>ERROR_NO_HANDLES - if there are no valid printers | 114 * <li>ERROR_NO_HANDLES - if there are no valid printers |
133 * </ul> | 115 * </ul> |
134 * | 116 * |
135 * @see Device#dispose | 117 * @see Device#dispose |
136 */ | 118 */ |
137 public this() { | 119 public Printer() { |
138 this(null); | 120 this(null); |
139 } | 121 } |
140 | 122 |
141 /** | 123 /** |
142 * Constructs a new printer given a <code>PrinterData</code> | 124 * Constructs a new printer given a <code>PrinterData</code> |
154 * <li>ERROR_NO_HANDLES - if there are no valid printers | 136 * <li>ERROR_NO_HANDLES - if there are no valid printers |
155 * </ul> | 137 * </ul> |
156 * | 138 * |
157 * @see Device#dispose | 139 * @see Device#dispose |
158 */ | 140 */ |
159 public this(PrinterData data) { | 141 public Printer(PrinterData data) { |
160 super (checkNull(data)); | 142 super (checkNull(data)); |
161 } | 143 } |
162 | 144 |
163 /** | 145 /** |
164 * Given a desired <em>client area</em> for the receiver | 146 * Given a <em>client area</em> (as described by the arguments), |
165 * (as described by the arguments), returns the bounding | 147 * returns a rectangle, relative to the client area's coordinates, |
166 * rectangle which would be required to produce that client | 148 * that is the client area expanded by the printer's trim (or minimum margins). |
167 * area. | 149 * <p> |
168 * <p> | 150 * Most printers have a minimum margin on each edge of the paper where the |
169 * In other words, it returns a rectangle such that, if the | 151 * printer device is unable to print. This margin is known as the "trim." |
170 * receiver's bounds were set to that rectangle, the area | 152 * This method can be used to calculate the printer's minimum margins |
171 * of the receiver which is capable of displaying data | 153 * by passing in a client area of 0, 0, 0, 0 and then using the resulting |
172 * (that is, not covered by the "trimmings") would be the | 154 * x and y coordinates (which will be <= 0) to determine the minimum margins |
173 * rectangle described by the arguments (relative to the | 155 * for the top and left edges of the paper, and the resulting width and height |
174 * receiver's parent). | 156 * (offset by the resulting x and y) to determine the minimum margins for the |
175 * </p><p> | 157 * bottom and right edges of the paper, as follows: |
176 * Note that there is no setBounds for a printer. This method | 158 * <ul> |
177 * is usually used by passing in the client area (the 'printable | 159 * <li>The left trim width is -x pixels</li> |
178 * area') of the printer. It can also be useful to pass in 0, 0, 0, 0. | 160 * <li>The top trim height is -y pixels</li> |
161 * <li>The right trim width is (x + width) pixels</li> | |
162 * <li>The bottom trim height is (y + height) pixels</li> | |
163 * </ul> | |
179 * </p> | 164 * </p> |
180 * | 165 * |
181 * @param x the desired x coordinate of the client area | 166 * @param x the x coordinate of the client area |
182 * @param y the desired y coordinate of the client area | 167 * @param y the y coordinate of the client area |
183 * @param width the desired width of the client area | 168 * @param width the width of the client area |
184 * @param height the desired height of the client area | 169 * @param height the height of the client area |
185 * @return the required bounds to produce the given client area | 170 * @return a rectangle, relative to the client area's coordinates, that is |
171 * the client area expanded by the printer's trim (or minimum margins) | |
186 * | 172 * |
187 * @exception DWTException <ul> | 173 * @exception DWTException <ul> |
188 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | 174 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> |
189 * </ul> | 175 * </ul> |
190 * | 176 * |
191 * @see #getBounds | 177 * @see #getBounds |
192 * @see #getClientArea | 178 * @see #getClientArea |
193 */ | 179 */ |
194 public Rectangle computeTrim(int x, int y, int width, int height) { | 180 public Rectangle computeTrim(int x, int y, int width, int height) { |
195 checkDevice(); | 181 checkDevice(); |
196 // PMRect pageRect = new PMRect(); | 182 NSSize paperSize = printInfo.paperSize(); |
197 // PMRect paperRect = new PMRect(); | 183 NSRect bounds = printInfo.imageablePageBounds(); |
198 // OS.PMGetAdjustedPageRect(pageFormat, pageRect); | 184 Point dpi = getDPI (), screenDPI = getIndependentDPI(); |
199 // OS.PMGetAdjustedPaperRect(pageFormat, paperRect); | 185 x -= (bounds.x * dpi.x / screenDPI.x); |
200 // return new Rectangle(x+cast(int)paperRect.left, y+cast(int)paperRect.top, width+cast(int)(paperRect.right-pageRect.right), height+cast(int)(paperRect.bottom-pageRect.bottom)); | 186 y -= (bounds.y * dpi.y / screenDPI.y); |
201 return null; | 187 width += (paperSize.width - bounds.width) * dpi.x / screenDPI.x; |
188 height += (paperSize.height - bounds.height) * dpi.y / screenDPI.y; | |
189 return new Rectangle(x, y, width, height); | |
202 } | 190 } |
203 | 191 |
204 /** | 192 /** |
205 * Creates the printer handle. | 193 * Creates the printer handle. |
206 * This method is called internally by the instance creation | 194 * This method is called internally by the instance creation |
207 * mechanism of the <code>Device</code> class. | 195 * mechanism of the <code>Device</code> class. |
208 * @param deviceData the device data | 196 * @param deviceData the device data |
209 */ | 197 */ |
210 protected void create(DeviceData deviceData) { | 198 protected void create(DeviceData deviceData) { |
211 data = cast(PrinterData)deviceData; | 199 data = (PrinterData)deviceData; |
212 | 200 if (data.otherData !is null) { |
213 printer = NSPrinter.static_printerWithName_(NSString.stringWith(data.name)); | 201 NSData nsData = NSData.dataWithBytes(data.otherData, data.otherData.length); |
214 printer.retain(); | 202 printInfo = new NSPrintInfo(NSKeyedUnarchiver.unarchiveObjectWithData(nsData).id); |
215 | 203 } else { |
216 // int[] buffer = new int[1]; | 204 printInfo = NSPrintInfo.sharedPrintInfo(); |
217 // if (OS.PMCreateSession(buffer) !is OS.noErr) DWT.error(DWT.ERROR_NO_HANDLES); | 205 } |
218 // printSession = buffer[0]; | 206 printInfo.retain(); |
219 // if (printSession is 0) DWT.error(DWT.ERROR_NO_HANDLES); | 207 printer = NSPrinter.printerWithName(NSString.stringWith(data.name)); |
220 // | 208 if (printer !is null) { |
221 // if (data.otherData !is null) { | 209 printer.retain(); |
222 // /* Deserialize settings */ | 210 printInfo.setPrinter(printer); |
223 // int offset = 0; | 211 } |
224 // byte[] otherData = data.otherData; | 212 /* |
225 // offset = unpackData(buffer, otherData, offset); | 213 * Bug in Cocoa. For some reason, the output still goes to the printer when |
226 // int flatSettings = buffer[0]; | 214 * the user chooses the preview button. The fix is to reset the job disposition. |
227 // offset = unpackData(buffer, otherData, offset); | 215 */ |
228 // int flatFormat = buffer[0]; | 216 NSString job = printInfo.jobDisposition(); |
229 // if (OS.PMUnflattenPrintSettings(flatSettings, buffer) !is OS.noErr) DWT.error(DWT.ERROR_NO_HANDLES); | 217 if (job.isEqual(new NSString(OS.NSPrintPreviewJob()))) { |
230 // printSettings = buffer[0]; | 218 printInfo.setJobDisposition(job); |
231 // if (printSettings is 0) DWT.error(DWT.ERROR_NO_HANDLES); | 219 } |
232 // if (OS.PMUnflattenPageFormat(flatFormat, buffer) !is OS.noErr) DWT.error(DWT.ERROR_NO_HANDLES); | 220 NSRect rect = new NSRect(); |
233 // pageFormat = buffer[0]; | 221 window = (NSWindow)new NSWindow().alloc(); |
234 // if (pageFormat is 0) DWT.error(DWT.ERROR_NO_HANDLES); | 222 window.initWithContentRect(rect, OS.NSBorderlessWindowMask, OS.NSBackingStoreBuffered, false); |
235 // OS.DisposeHandle(flatSettings); | 223 view = (NSView)new NSView().alloc(); |
236 // OS.DisposeHandle(flatFormat); | 224 view.initWithFrame(rect); |
237 // } else { | 225 window.setContentView(view); |
238 // /* Create default settings */ | 226 operation = NSPrintOperation.printOperationWithView(view, printInfo); |
239 // if (OS.PMCreatePrintSettings(buffer) !is OS.noErr) DWT.error(DWT.ERROR_NO_HANDLES); | 227 operation.retain(); |
240 // printSettings = buffer[0]; | 228 operation.setShowsPrintPanel(false); |
241 // if (printSettings is 0) DWT.error(DWT.ERROR_NO_HANDLES); | 229 operation.setShowsProgressPanel(false); |
242 // OS.PMSessionDefaultPrintSettings(printSession, printSettings); | |
243 // if (OS.PMCreatePageFormat(buffer) !is OS.noErr) DWT.error(DWT.ERROR_NO_HANDLES); | |
244 // pageFormat = buffer[0]; | |
245 // if (pageFormat is 0) DWT.error(DWT.ERROR_NO_HANDLES); | |
246 // OS.PMSessionDefaultPageFormat(printSession, pageFormat); | |
247 // } | |
248 // | |
249 // if (PREVIEW_DRIVER.equals(data.driver)) { | |
250 // OS.PMSessionSetDestination(printSession, printSettings, cast(short) OS.kPMDestinationPreview, 0, 0); | |
251 // } | |
252 // String name = data.name; | |
253 // char[] buffer1 = new char[name.length ()]; | |
254 // name.getChars(0, buffer1.length, buffer1, 0); | |
255 // int ptr = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer1, buffer1.length); | |
256 // if (ptr !is 0) { | |
257 // OS.PMSessionSetCurrentPrinter(printSession, ptr); | |
258 // OS.CFRelease(ptr); | |
259 // } | |
260 // | |
261 // OS.PMSessionValidatePrintSettings(printSession, printSettings, null); | |
262 // OS.PMSessionValidatePageFormat(printSession, pageFormat, null); | |
263 // | |
264 // int graphicsContextsArray = OS.CFArrayCreateMutable(OS.kCFAllocatorDefault, 1, 0); | |
265 // if (graphicsContextsArray !is 0) { | |
266 // OS.CFArrayAppendValue(graphicsContextsArray, OS.kPMGraphicsContextCoreGraphics()); | |
267 // OS.PMSessionSetDocumentFormatGeneration(printSession, OS.kPMDocumentFormatPDF(), graphicsContextsArray, 0); | |
268 // OS.CFRelease(graphicsContextsArray); | |
269 // } | |
270 } | 230 } |
271 | 231 |
272 /** | 232 /** |
273 * Destroys the printer handle. | 233 * Destroys the printer handle. |
274 * This method is called internally by the dispose | 234 * This method is called internally by the dispose |
275 * mechanism of the <code>Device</code> class. | 235 * mechanism of the <code>Device</code> class. |
276 */ | 236 */ |
277 protected void destroy() { | 237 protected void destroy() { |
278 if (printer !is null) printer.release(); | 238 if (printer !is null) printer.release(); |
239 if (printInfo !is null) printInfo.release(); | |
240 if (view !is null) view.release(); | |
241 if (window !is null) window.release(); | |
242 if (operation !is null) operation.release(); | |
279 printer = null; | 243 printer = null; |
244 printInfo = null; | |
245 view = null; | |
246 operation = null; | |
280 } | 247 } |
281 | 248 |
282 /** | 249 /** |
283 * Invokes platform specific functionality to allocate a new GC handle. | 250 * Invokes platform specific functionality to allocate a new GC handle. |
284 * <p> | 251 * <p> |
290 * </p> | 257 * </p> |
291 * | 258 * |
292 * @param data the platform specific GC data | 259 * @param data the platform specific GC data |
293 * @return the platform specific GC handle | 260 * @return the platform specific GC handle |
294 */ | 261 */ |
295 public int internal_new_GC(GCData data) { | 262 public int /*long*/ internal_new_GC(GCData data) { |
296 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); | 263 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); |
297 setupNewPage(); | 264 if (data !is null) { |
298 // if (data !is null) { | 265 if (isGCCreated) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
299 // if (isGCCreated) DWT.error(DWT.ERROR_INVALID_ARGUMENT); | 266 data.device = this; |
300 // data.device = this; | 267 data.background = getSystemColor(DWT.COLOR_WHITE).handle; |
301 // data.background = getSystemColor(DWT.COLOR_WHITE).handle; | 268 data.foreground = getSystemColor(DWT.COLOR_BLACK).handle; |
302 // data.foreground = getSystemColor(DWT.COLOR_BLACK).handle; | 269 data.font = getSystemFont (); |
303 // data.font = getSystemFont (); | 270 data.size = printInfo.paperSize(); |
304 // PMRect paperRect= new PMRect(); | 271 isGCCreated = true; |
305 // OS.PMGetAdjustedPaperRect(pageFormat, paperRect); | 272 } |
306 // Rect portRect = new Rect(); | 273 return operation.context().id; |
307 // portRect.left = cast(short)paperRect.left; | 274 } |
308 // portRect.right = cast(short)paperRect.right; | 275 |
309 // portRect.top = cast(short)paperRect.top; | 276 protected void init () { |
310 // portRect.bottom = cast(short)paperRect.bottom; | 277 super.init(); |
311 // data.portRect = portRect; | |
312 // isGCCreated = true; | |
313 // } | |
314 // return context; | |
315 return 0; | |
316 } | |
317 | |
318 protected void init_ () { | |
319 super.init_(); | |
320 } | 278 } |
321 | 279 |
322 /** | 280 /** |
323 * Invokes platform specific functionality to dispose a GC handle. | 281 * Invokes platform specific functionality to dispose a GC handle. |
324 * <p> | 282 * <p> |
330 * </p> | 288 * </p> |
331 * | 289 * |
332 * @param hDC the platform specific GC handle | 290 * @param hDC the platform specific GC handle |
333 * @param data the platform specific GC data | 291 * @param data the platform specific GC data |
334 */ | 292 */ |
335 public void internal_dispose_GC(int context, GCData data) { | 293 public void internal_dispose_GC(int /*long*/ context, GCData data) { |
336 if (data !is null) isGCCreated = false; | 294 if (data !is null) isGCCreated = false; |
337 } | 295 } |
338 | 296 |
339 /** | 297 /** |
340 * Releases any internal state prior to destroying this printer. | 298 * Releases any internal state prior to destroying this printer. |
366 * @see #endPage | 324 * @see #endPage |
367 * @see #endJob | 325 * @see #endJob |
368 */ | 326 */ |
369 public bool startJob(String jobName) { | 327 public bool startJob(String jobName) { |
370 checkDevice(); | 328 checkDevice(); |
371 // if (jobName !is null && jobName.length() !is 0) { | 329 if (jobName !is null && jobName.length() !is 0) { |
372 // char[] buffer = new char[jobName.length ()]; | 330 operation.setJobTitle(NSString.stringWith(jobName)); |
373 // jobName.getChars(0, buffer.length, buffer, 0); | 331 } |
374 // int ptr = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, buffer.length); | 332 printInfo.setUpPrintOperationDefaultValues(); |
375 // if (ptr !is 0) { | 333 NSPrintOperation.setCurrentOperation(operation); |
376 // OS.PMSetJobNameCFString(printSettings, ptr); | 334 NSGraphicsContext context = operation.createContext(); |
377 // OS.CFRelease (ptr); | 335 if (context !is null) { |
378 // } | 336 view.beginDocument(); |
379 // } | 337 return true; |
380 // return OS.PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat) is OS.noErr; | 338 } |
381 return false; | 339 return false; |
382 } | 340 } |
383 | 341 |
384 /** | 342 /** |
385 * Ends the current print job. | 343 * Ends the current print job. |
392 * @see #startPage | 350 * @see #startPage |
393 * @see #endPage | 351 * @see #endPage |
394 */ | 352 */ |
395 public void endJob() { | 353 public void endJob() { |
396 checkDevice(); | 354 checkDevice(); |
397 // if (inPage) { | 355 view.endDocument(); |
398 // OS.PMSessionEndPageNoDialog(printSession); | 356 operation.deliverResult(); |
399 // inPage = false; | 357 operation.destroyContext(); |
400 // } | 358 operation.cleanUpOperation(); |
401 // OS.PMSessionEndDocumentNoDialog(printSession); | |
402 // context = 0; | |
403 } | 359 } |
404 | 360 |
405 /** | 361 /** |
406 * Cancels a print job in progress. | 362 * Cancels a print job in progress. |
407 * | 363 * |
409 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | 365 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> |
410 * </ul> | 366 * </ul> |
411 */ | 367 */ |
412 public void cancelJob() { | 368 public void cancelJob() { |
413 checkDevice(); | 369 checkDevice(); |
414 // OS.PMSessionSetError(printSession, OS.kPMCancel); | 370 operation.destroyContext(); |
415 // if (inPage) { | 371 operation.cleanUpOperation(); |
416 // OS.PMSessionEndPageNoDialog(printSession); | |
417 // inPage = false; | |
418 // } | |
419 // OS.PMSessionEndDocumentNoDialog(printSession); | |
420 // context = 0; | |
421 } | 372 } |
422 | 373 |
423 static DeviceData checkNull (PrinterData data) { | 374 static DeviceData checkNull (PrinterData data) { |
424 if (data is null) data = new PrinterData(); | 375 if (data is null) data = new PrinterData(); |
425 if (data.driver is null || data.name is null) { | 376 if (data.driver is null || data.name is null) { |
449 * @see #startJob | 400 * @see #startJob |
450 * @see #endJob | 401 * @see #endJob |
451 */ | 402 */ |
452 public bool startPage() { | 403 public bool startPage() { |
453 checkDevice(); | 404 checkDevice(); |
454 // if (OS.PMSessionError(printSession) !is OS.noErr) return false; | 405 NSSize paperSize = printInfo.paperSize(); |
455 // setupNewPage(); | 406 NSRect rect = new NSRect(); |
456 // return context !is 0; | 407 rect.width = paperSize.width; |
457 return false; | 408 rect.height = paperSize.height; |
409 view.beginPageInRect(rect, new NSPoint()); | |
410 NSRect imageBounds = printInfo.imageablePageBounds(); | |
411 NSBezierPath.bezierPathWithRect(imageBounds).setClip(); | |
412 NSAffineTransform transform = NSAffineTransform.transform(); | |
413 transform.translateXBy(imageBounds.x, rect.height - imageBounds.y); | |
414 transform.scaleXBy(1, -1); | |
415 Point dpi = getDPI (), screenDPI = getIndependentDPI(); | |
416 transform.scaleXBy(screenDPI.x / (float)dpi.x, screenDPI.y / (float)dpi.y); | |
417 transform.concat(); | |
418 return true; | |
458 } | 419 } |
459 | 420 |
460 /** | 421 /** |
461 * Ends the current page. | 422 * Ends the current page. |
462 * | 423 * |
468 * @see #startJob | 429 * @see #startJob |
469 * @see #endJob | 430 * @see #endJob |
470 */ | 431 */ |
471 public void endPage() { | 432 public void endPage() { |
472 checkDevice(); | 433 checkDevice(); |
473 // if (inPage) { | 434 view.endPage(); |
474 // OS.PMSessionEndPageNoDialog(printSession); | |
475 // inPage = false; | |
476 // } | |
477 } | 435 } |
478 | 436 |
479 /** | 437 /** |
480 * Returns a point whose x coordinate is the horizontal | 438 * Returns a point whose x coordinate is the horizontal |
481 * dots per inch of the printer, and whose y coordinate | 439 * dots per inch of the printer, and whose y coordinate |
487 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | 445 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> |
488 * </ul> | 446 * </ul> |
489 */ | 447 */ |
490 public Point getDPI() { | 448 public Point getDPI() { |
491 checkDevice(); | 449 checkDevice(); |
492 // PMResolution resolution = new PMResolution(); | 450 //TODO get output resolution |
493 // OS.PMGetResolution(pageFormat, resolution); | 451 return getIndependentDPI(); |
494 // return new Point(cast(int)resolution.hRes, cast(int)resolution.vRes); | 452 } |
495 return null; | 453 |
454 Point getIndependentDPI() { | |
455 return super.getDPI(); | |
496 } | 456 } |
497 | 457 |
498 /** | 458 /** |
499 * Returns a rectangle describing the receiver's size and location. | 459 * Returns a rectangle describing the receiver's size and location. |
500 * For a printer, this is the size of a physical page, in pixels. | 460 * <p> |
461 * For a printer, this is the size of the physical page, in pixels. | |
462 * </p> | |
501 * | 463 * |
502 * @return the bounding rectangle | 464 * @return the bounding rectangle |
503 * | 465 * |
504 * @exception DWTException <ul> | 466 * @exception DWTException <ul> |
505 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | 467 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> |
508 * @see #getClientArea | 470 * @see #getClientArea |
509 * @see #computeTrim | 471 * @see #computeTrim |
510 */ | 472 */ |
511 public Rectangle getBounds() { | 473 public Rectangle getBounds() { |
512 checkDevice(); | 474 checkDevice(); |
513 // PMRect paperRect = new PMRect(); | 475 NSSize size = printInfo.paperSize(); |
514 // OS.PMGetAdjustedPaperRect(pageFormat, paperRect); | 476 Point dpi = getDPI (), screenDPI = getIndependentDPI(); |
515 // return new Rectangle(0, 0, cast(int)(paperRect.right-paperRect.left), cast(int)(paperRect.bottom-paperRect.top)); | 477 return new Rectangle (0, 0, (int)(size.width * dpi.x / screenDPI.x), (int)(size.height * dpi.y / screenDPI.y)); |
516 return null; | |
517 } | 478 } |
518 | 479 |
519 /** | 480 /** |
520 * Returns a rectangle which describes the area of the | 481 * Returns a rectangle which describes the area of the |
521 * receiver which is capable of displaying data. | 482 * receiver which is capable of displaying data. |
483 * <p> | |
522 * For a printer, this is the size of the printable area | 484 * For a printer, this is the size of the printable area |
523 * of a page, in pixels. | 485 * of the page, in pixels. |
486 * </p> | |
524 * | 487 * |
525 * @return the client area | 488 * @return the client area |
526 * | 489 * |
527 * @exception DWTException <ul> | 490 * @exception DWTException <ul> |
528 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | 491 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> |
531 * @see #getBounds | 494 * @see #getBounds |
532 * @see #computeTrim | 495 * @see #computeTrim |
533 */ | 496 */ |
534 public Rectangle getClientArea() { | 497 public Rectangle getClientArea() { |
535 checkDevice(); | 498 checkDevice(); |
536 // PMRect pageRect = new PMRect(); | 499 NSRect rect = printInfo.imageablePageBounds(); |
537 // OS.PMGetAdjustedPageRect(pageFormat, pageRect); | 500 Point dpi = getDPI (), screenDPI = getIndependentDPI(); |
538 // return new Rectangle(0, 0, cast(int)(pageRect.right-pageRect.left), cast(int)(pageRect.bottom-pageRect.top)); | 501 return new Rectangle(0, 0, (int)(rect.width * dpi.x / screenDPI.x), (int)(rect.height * dpi.y / screenDPI.y)); |
539 return null; | |
540 } | 502 } |
541 | 503 |
542 /** | 504 /** |
543 * Returns a <code>PrinterData</code> object representing the | 505 * Returns a <code>PrinterData</code> object representing the |
544 * target printer for this print job. | 506 * target printer for this print job. |
547 */ | 509 */ |
548 public PrinterData getPrinterData() { | 510 public PrinterData getPrinterData() { |
549 checkDevice(); | 511 checkDevice(); |
550 return data; | 512 return data; |
551 } | 513 } |
552 | 514 } |
553 /** | |
554 * On the Mac the core graphics context for printing is only valid between PMSessionBeginPage and PMSessionEndPage, | |
555 * so printing code has to retrieve and initializes a graphic context for every page like this: | |
556 * | |
557 * <pre> | |
558 * PMSessionBeginDocument | |
559 * PMSessionBeginPage | |
560 * PMSessionGetGraphicsContext | |
561 * // ... use context | |
562 * PMSessionEndPage | |
563 * PMSessionEndDocument | |
564 * </pre> | |
565 * | |
566 * In DWT it is OK to create a GC once between startJob / endJob and use it for all pages in between: | |
567 * | |
568 * <pre> | |
569 * startJob(...); | |
570 * GC gc= new GC(printer); | |
571 * startPage(); | |
572 * // ... use gc | |
573 * endPage(); | |
574 * gc.dispose(); | |
575 * endJob(); | |
576 * </pre> | |
577 * | |
578 * The solution to resolve this difference is to rely on the fact that Mac OS X returns the same but | |
579 * reinitialized graphics context for every page. So we only have to account for the fact that DWT assumes | |
580 * that the graphics context keeps it settings across a page break when it actually does not. | |
581 * So we have to copy some settings that exist in the CGC before a PMSessionEndPage to the CGC after a PMSessionBeginPage. | |
582 * <p> | |
583 * In addition to this we have to cope with the situation that in DWT we can create a GC before a call to | |
584 * PMSessionBeginPage. For this we decouple the call to PMSessionBeginPage from | |
585 * DWT's method startPage as follows: if a new GC is created before a call to startPage, internal_new_GC | |
586 * does the PMSessionBeginPage and the next following startPage does nothing. | |
587 * </p> | |
588 */ | |
589 void setupNewPage() { | |
590 // if (!inPage) { | |
591 // inPage= true; | |
592 // OS.PMSessionBeginPageNoDialog(printSession, pageFormat, null); | |
593 // int[] buffer = new int[1]; | |
594 // OS.PMSessionGetGraphicsContext(printSession, 0, buffer); | |
595 // if (context is 0) { | |
596 // context = buffer[0]; | |
597 // } else { | |
598 // if (context !is buffer[0]) DWT.error(DWT.ERROR_UNSPECIFIED); | |
599 // } | |
600 // PMRect paperRect= new PMRect(); | |
601 // OS.PMGetAdjustedPaperRect(pageFormat, paperRect); | |
602 // OS.CGContextScaleCTM(context, 1, -1); | |
603 // OS.CGContextTranslateCTM(context, 0, -cast(float)(paperRect.bottom-paperRect.top)); | |
604 // OS.CGContextSetStrokeColorSpace(context, colorspace); | |
605 // OS.CGContextSetFillColorSpace(context, colorspace); | |
606 // } | |
607 } | |
608 | |
609 } |