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 }