Bug 81467 - Draw2D fails to print on Mac OSX 10.3
Summary: Draw2D fails to print on Mac OSX 10.3
Status: RESOLVED FIXED
Alias: None
Product: GEF
Classification: Tools
Component: GEF-Legacy Draw2d (show other bugs)
Version: 3.0   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: gef-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2004-12-16 15:41 EST by nathan CLA
Modified: 2007-04-16 15:54 EDT (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nathan CLA 2004-12-16 15:41:14 EST
I am trying to print out a figure using Draw2D.  I have the  code working under Windows XP.  It is a 
standalone application using SWT (3062) and the Draw2D jar (3.0.0).  The code is below (it's sloppy, but 
this is just a prototyping application to make sure everything works).  The interesting part is:

		PrintDialog dialog = new PrintDialog(this.getShell(), SWT.NULL);
		Printer printer = new Printer(dialog.open());
		PrintFigureOperation pfo = new PrintFigureOperation(printer, c);
		pfo.run("TEST PRINT JOB");

This run method "hangs" the application.  I've tried debugging it and it looks like it's just printing really 
slowly down int the JNI code, but I'm not sure about that.  Anyway, I haven't gotten it to print anything 
yet on Mac OS X even after wait for about 10 minutes (on a really simple figure) so I know something is 
wrong there.  Let me know if I'm doing something wrong with the code ...



File NewSWTApp.java

import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.printing.*;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.draw2d.*;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.draw2d.parts.*;
import org.eclipse.draw2d.geometry.*;

/**import org.
* This code was generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a
* for-profit company or business) then you should purchase
* a license - please visit www.cloudgarden.com for details.
*/
public class NewSWTApp extends org.eclipse.swt.widgets.Composite {
	private Scale scale1;
	private Button button1;
	private Canvas thumbnailCanvas;
	private Combo scaleCombo;
	private Canvas canvas;
	private Composite composite1;
	private SashForm sashForm1;
	private MenuItem aboutMenuItem;
	private MenuItem contentsMenuItem;
	private Menu helpMenu;
	private MenuItem helpMenuItem;
	private MenuItem exitMenuItem;
	private MenuItem closeFileMenuItem;
	private MenuItem saveFileMenuItem;
	private MenuItem newFileMenuItem;
	private MenuItem openFileMenuItem;
	private Menu fileMenu;
	private MenuItem fileMenuItem;
	private Menu menu1;
	
	private ScalableLayeredPane p = null;
	private ScrollableThumbnail t = null;
	private IFigure c = null;
	
	public NewSWTApp(Composite parent, int style) {
		super(parent, style);
		initGUI();
	}

	/**
	* Initializes the GUI.
	* Auto-generated code - any changes you make will disappear.
	*/
	public void initGUI(){
		try {
			preInitGUI();
	
			sashForm1 = new SashForm(this,SWT.NULL);
			canvas = new Canvas(sashForm1,SWT.NULL);
			composite1 = new Composite(sashForm1,SWT.NULL);
			scaleCombo = new Combo(composite1,SWT.NULL);
			thumbnailCanvas = new Canvas(composite1,SWT.NULL);
			button1 = new Button(composite1,SWT.PUSH| SWT.CENTER);
			scale1 = new Scale(composite1,SWT.NULL);
	
			this.setSize(new org.eclipse.swt.graphics.Point(605,335));
			final Color NewSWTAppbackground = new Color(Display.getDefault(),128,128,128);
			this.setBackground(NewSWTAppbackground);
	
			FormData sashForm1LData = new FormData();
			sashForm1LData.height = 315;
			sashForm1LData.width = 605;
			sashForm1LData.left =  new FormAttachment(0, 1000, 0);
			sashForm1LData.right =  new FormAttachment(1000, 1000, 0);
			sashForm1LData.top =  new FormAttachment(0, 1000, 0);
			sashForm1LData.bottom =  new FormAttachment(1000, 1000, -20);
			sashForm1.setLayoutData(sashForm1LData);
			sashForm1.setSize(new org.eclipse.swt.graphics.Point(605,295));
	
			canvas.setSize(new org.eclipse.swt.graphics.Point(298,295));
			final Color canvasbackground = new Color(Display.getDefault(),255,255,255);
			canvas.setBackground(canvasbackground);
	
			composite1.setSize(new org.eclipse.swt.graphics.Point(304,295));
	
			FormData scaleComboLData = new FormData();
			scaleComboLData.height = 20;
			scaleComboLData.width = 290;
			scaleComboLData.left =  new FormAttachment(0, 1000, 5);
			scaleComboLData.right =  new FormAttachment(1000, 1000, -9);
			scaleComboLData.top =  new FormAttachment(0, 1000, 5);
			scaleComboLData.bottom =  new FormAttachment(0, 1000, 25);
			scaleCombo.setLayoutData(scaleComboLData);
			scaleCombo.setSize(new org.eclipse.swt.graphics.Point(290,20));
			scaleCombo.addSelectionListener( new SelectionAdapter() {
				public void widgetSelected(SelectionEvent evt) {
					scaleComboWidgetSelected(evt);
				}
			});
	
			FormData thumbnailCanvasLData = new FormData();
			thumbnailCanvasLData.height = 115;
			thumbnailCanvasLData.width = 290;
			thumbnailCanvasLData.left =  new FormAttachment(0, 1000, 5);
			thumbnailCanvasLData.right =  new FormAttachment(1000, 1000, -9);
			thumbnailCanvasLData.top =  new FormAttachment(0, 1000, 35);
			thumbnailCanvasLData.bottom =  new FormAttachment(0, 1000, 150);
			thumbnailCanvas.setLayoutData(thumbnailCanvasLData);
			thumbnailCanvas.setSize(new org.eclipse.swt.graphics.Point(290,115));
	
			FormData button1LData = new FormData();
			button1LData.height = 36;
			button1LData.width = 286;
			button1LData.left =  new FormAttachment(0, 1000, 5);
			button1LData.right =  new FormAttachment(1000, 1000, -9);
			button1LData.top =  new FormAttachment(0, 1000, 155);
			button1LData.bottom =  new FormAttachment(0, 1000, 195);
			button1.setLayoutData(button1LData);
			button1.setText("button1");
			button1.setSize(new org.eclipse.swt.graphics.Point(286,36));
			button1.addSelectionListener( new SelectionAdapter() {
				public void widgetSelected(SelectionEvent evt) {
					button1WidgetSelected(evt);
				}
			});
	
			FormData scale1LData = new FormData();
			scale1LData.height = 20;
			scale1LData.width = 290;
			scale1LData.left =  new FormAttachment(0, 1000, 5);
			scale1LData.right =  new FormAttachment(1000, 1000, -9);
			scale1LData.top =  new FormAttachment(0, 1000, 205);
			scale1LData.bottom =  new FormAttachment(0, 1000, 225);
			scale1.setLayoutData(scale1LData);
			scale1.setMaximum(800);
			scale1.setMinimum(25);
			scale1.setSize(new org.eclipse.swt.graphics.Point(290,20));
			scale1.addSelectionListener( new SelectionAdapter() {
				public void widgetSelected(SelectionEvent evt) {
					scale1WidgetSelected(evt);
				}
			});
			scale1.addMouseMoveListener( new MouseMoveListener() {
				public void mouseMove(MouseEvent evt) {
					scale1MouseMove(evt);
				}
			});
			FormLayout composite1Layout = new FormLayout();
			composite1.setLayout(composite1Layout);
			composite1Layout.marginWidth = 0;
			composite1Layout.marginHeight = 0;
			composite1Layout.spacing = 0;
			composite1.layout();
			FormLayout thisLayout = new FormLayout();
			this.setLayout(thisLayout);
			thisLayout.marginWidth = 0;
			thisLayout.marginHeight = 0;
			thisLayout.spacing = 0;
			this.layout();
			menu1 = new Menu(getShell(),SWT.BAR);
			fileMenuItem = new MenuItem(menu1,SWT.CASCADE);
			fileMenu = new Menu(fileMenuItem);
			openFileMenuItem = new MenuItem(fileMenu,SWT.CASCADE);
			newFileMenuItem = new MenuItem(fileMenu,SWT.CASCADE);
			saveFileMenuItem = new MenuItem(fileMenu,SWT.CASCADE);
			closeFileMenuItem = new MenuItem(fileMenu,SWT.CASCADE);
			exitMenuItem = new MenuItem(fileMenu,SWT.CASCADE);
			helpMenuItem = new MenuItem(menu1,SWT.CASCADE);
			helpMenu = new Menu(helpMenuItem);
			contentsMenuItem = new MenuItem(helpMenu,SWT.CASCADE);
			aboutMenuItem = new MenuItem(helpMenu,SWT.CASCADE);
	
			getShell().setMenuBar(menu1);
	
			fileMenuItem.setText("File");
	
			fileMenuItem.setMenu(fileMenu);
	
			openFileMenuItem.setText("Open");
	
			newFileMenuItem.setText("New");
	
			saveFileMenuItem.setText("Save");
	
			closeFileMenuItem.setText("Close");
	
			exitMenuItem.setText("Exit");
	
			helpMenuItem.setText("Help");
	
			helpMenuItem.setMenu(helpMenu);
	
			contentsMenuItem.setText("Contents");
	
			aboutMenuItem.setText("About");
			addDisposeListener(new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					NewSWTAppbackground.dispose();
					canvasbackground.dispose();
				}
			});
	
			postInitGUI();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/** Add your pre-init code in here 	*/
	public void preInitGUI(){
	}

	/** Add your post-init code in here 	*/
	public void postInitGUI(){
	
		scaleCombo.add("0.2");
		scaleCombo.add("0.4");
		scaleCombo.add("0.6");
		scaleCombo.add("0.8");
		scaleCombo.add("1.0");
		scaleCombo.add("1.5");
		scaleCombo.add("2.0");
		scaleCombo.add("4.0");
		scaleCombo.add("8.0");
	
		LightweightSystem lws = new LightweightSystem(canvas);
		final Layer contents = new Layer();
		final ScalableLayeredPane pane = new ScalableLayeredPane();
		final ScrollPane scroll = new ScrollPane();
		pane.add(contents, "1", 0);
		scroll.setContents(pane);
		final XYLayout layout = new XYLayout();
		contents.setLayoutManager(layout);
		
		c = contents;
		p = pane;
		
		IFigure old = null;
		int row = 0;
		int col = 0;
		for (int i = 0; i < 100; i++) {
			
			if (i % 10 == 0) System.out.println(i);
			
			IFigure btn = new WindowFrame();
			
			/*
			final IFigure btn = new Button("TEST" + i);
			btn.setBorder(new FrameBorder("WINDOW" + i));
			btn.addMouseMotionListener(new MouseMotionListener() {

				public void mouseDragged(MouseEvent arg0) {
				//	System.out.println(arg0.x + " " + arg0.y);
		//			btn.setBounds(new org.eclipse.draw2d.geometry.Rectangle(
		//					arg0.x, arg0.y, btn.getBounds().width, btn.getBounds().height));
					contents.setConstraint(btn, new org.eclipse.draw2d.geometry.Rectangle(
							arg0.x - 10, arg0.y - 10, btn.getBounds().width, 
btn.getBounds().height));
		//			btn.invalidate();
		//			contents.invalidate();
				}

				public void mouseEntered(MouseEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				public void mouseExited(MouseEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				public void mouseHover(MouseEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				public void mouseMoved(MouseEvent arg0) {
					//System.out.println("MOVED: " + arg0.x + " " + arg0.y);
					
				}
				
			});
			
			*/
			
			btn.setOpaque(true);
			layout.setConstraint(btn, new org.eclipse.draw2d.geometry.Rectangle(200 * row, 200 * 
col,-1,-1));
			contents.add(btn);
			if (old != null) {
				PolylineConnection conn = new PolylineConnection();
				ChopboxAnchor srcAnchor = new ChopboxAnchor(btn);
				ChopboxAnchor dstAnchor = new ChopboxAnchor(old);
				conn.setSourceAnchor(srcAnchor);
				conn.setTargetAnchor(dstAnchor);
				contents.add(conn);
			}
			old = btn;
			
			row++;
			if (row > 10) {
				row = 0;
				col++;
			}
			
		}


		LightweightSystem tlws = new LightweightSystem(thumbnailCanvas);
		ScrollableThumbnail thumb = new ScrollableThumbnail();
		thumb.setViewport(scroll.getViewport());
		thumb.setSource(contents);
		tlws.setContents(thumb);
		
		
		t = thumb;
		
		
		lws.setContents(scroll);
		

	}

	/** Auto-generated mainForm method */
	public static void main(String[] args){
		showGUI();
	}

	/**
	* This static method creates a new instance of this class and shows
	* it inside a new Shell.
	*
	* It is a convenience method for showing the GUI, but it can be
	* copied and used as a basis for your own code.	*
	* It is auto-generated code - the body of this method will be
	* re-generated after any changes are made to the GUI.
	* However, if you delete this method it will not be re-created.
	*/
	public static void showGUI(){
		try {
			Display display = Display.getDefault();
			Shell shell = new Shell(display);
			NewSWTApp inst = new NewSWTApp(shell, SWT.NULL);
			shell.setLayout(new org.eclipse.swt.layout.FillLayout());
			Rectangle shellBounds = shell.computeTrim(0,0,605,315);
			shell.setSize(shellBounds.width, shellBounds.height);
			shell.open();
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch())
					display.sleep();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/** Auto-generated event handler method */
	protected void scaleComboWidgetSelected(SelectionEvent evt){
		try {
		System.out.println("TEST");
			double scale = Double.parseDouble(scaleCombo.getText());
			p.setScale(scale);
			p.invalidate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** Auto-generated event handler method */
	protected void button1WidgetSelected(SelectionEvent evt){
	
		PrintDialog dialog = new PrintDialog(this.getShell(), SWT.NULL);
		Printer printer = new Printer(dialog.open());
		PrintFigureOperation pfo = new PrintFigureOperation(printer, c);
		pfo.run("TEST PRINT JOB");
	}

	/** Auto-generated event handler method */
	protected void scale1WidgetSelected(SelectionEvent evt){
		
		double s = scale1.getSelection() / 100f;
		p.setScale(s);
		t.setDirty(true);
		t.invalidate();
		//t.setDirty(true);
		scaleCombo.setText(String.valueOf(s));

	}

	/** Auto-generated event handler method */
	protected void scale1MouseMove(MouseEvent evt){
		double s = scale1.getSelection() / 100f;
		scaleCombo.setText(String.valueOf(s));
	}
}



File WindowFrame.java


import org.eclipse.draw2d.Clickable;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FrameBorder;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.*;

/*
 * Created on Dec 15, 2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author ncallender
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */


public class WindowFrame extends Clickable {
	
	public WindowFrame() {
		super();	
		ToolbarLayout layout = new ToolbarLayout(false);
		
		Label label1 = new Label("Line 1");
		Label label2 = new Label("Line 2");
		Label label3 = new Label("Line 3");
		Label label4 = new Label("Line 4");
		
		setLayoutManager(layout);
		add(label1);
		add(label2);
		add(label3);
		add(label4);
		
		
		
		label1.setBorder(new LineBorder(1));
		label2.setBorder(new LineBorder(1));
		label3.setBorder(new LineBorder(1));
		label4.setBorder(new LineBorder(1));

		FrameBorder border = new FrameBorder("ASF");
		setBorder(border);
		
		final Figure me = this;
		addMouseMotionListener(new MouseMotionListener() {

			public void mouseDragged(MouseEvent arg0) {
				
				getParent().setConstraint(me, new org.eclipse.draw2d.geometry.Rectangle(
						arg0.x - 10, arg0.y - 10, me.getBounds().width, 
me.getBounds().height));

			}

			public void mouseEntered(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void mouseExited(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void mouseHover(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void mouseMoved(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}
			
		});
	
	}
}
Comment 1 Pratik Shah CLA 2004-12-16 17:21:03 EST
This might be an SWT problem.  Although printing is not supported on all 
platforms, I believe Mac OSX is supported.  Can you successfully run the SWT 
printing snippet?

http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclip
se/swt/snippets/Snippet132.java?rev=HEAD&content-type=text/vnd.viewcvs-markup
Comment 2 nathan CLA 2004-12-16 17:37:37 EST
Yes, I can run the SWT printing snippet.  I just downloaded the code, compiled and ran the application 
and the output was correct.    I also modified the snippet to use the same PrinterData settings that I 
have been using in the Draw2D application:

        PrintDialog dialog = new PrintDialog(shell, SWT.NULL);
        PrinterData data = dialog.open();

This also produced the correct output.  So, SWT is working, but I'm wondering if Draw2D is either not 
drawing on the right GC or I'm not setting up the GC correctly (or some resources are on the wrong 
GC).  However, the sample code is pretty basic as far as the Draw2D functionality is concerned.  
Comment 3 Randy Hudson CLA 2005-01-21 13:14:36 EST
Whatever draw2d is doing, it works fine on win32.  You should try to reduce 
the snippet to its very basic elements.  Perhaps remove figures until the 
problem stops happening.  If you remove everything and the problem still 
occurs, it be related to simply drawing an Image.

I'd like to help but I don't have any printers installed on my Mac.
Comment 4 Randy Hudson CLA 2005-02-07 12:03:27 EST
Please try running the following test case and append the results here:

public class Bug81467 {

public static void main(String[] args) {
	Font font = new Font(null, "Helvetica", 12, 0);
	Printer printer = new Printer();
	printer.startJob("bugzilla 81467");

	GC gc = new GC(printer);
	SWTGraphics graphics = new SWTGraphics(gc);
	PrinterGraphics printGraphics = new PrinterGraphics(graphics, printer);
	
	printGraphics.scale((double)printer.getDPI().x / Display.getDefault
().getDPI().x);
	printGraphics.setFont(font);
	printGraphics.drawString("Hello world", 50, 50);
	printGraphics.dispose();
	
	graphics.dispose();
	gc.dispose();
	printer.endJob();
	printer.dispose();
	font.dispose();
}

}
Comment 5 Eric Wasserman CLA 2006-03-01 18:23:51 EST
I am having trouble printing a GEF editor's on Mac OS X 10.4.5. The symptom is an infinite loop that I traced down to the clip rect having zero extent.

I believe this bug is related.

Trying Randy Hudson's test case (see comment #4) I get a single blank page out of the printer.
Comment 6 Eric Wasserman CLA 2006-03-01 20:20:12 EST
some additional information. If I modify Randy's test case (see comment #4) thusly,

        ...
	GC gc = new GC(printer);
	SWTGraphics graphics = new SWTGraphics(gc);
        graphics.setClip(new Rectangle(0,0,500, 500)); // FORCE a clip rect
	PrinterGraphics printGraphics = new PrinterGraphics(graphics, printer);
        ...

Then the test produces the expected result ("Hello World").

The relevant code in SWTGraphics.init() is:
	currentState.relativeClip = new RectangleClipping(gc.getClipping());
GC.getClipping() is returning a rect {0,0,0,0}

I can't tell without a lot more study whether the fault lies in the GC class for Mac OS, in SWTGraphics (or somewhere else). I suspect GC.getClipping() is not adhering to its contract as laid out in the method comment:

/** 
 * Returns the bounding rectangle of the receiver's clipping
 * region. If no clipping region is set, the return value
 * will be a rectangle which covers the entire bounds of the
 * object the receiver is drawing on.
 *
 * @return the bounding rectangle of the clipping region

In this case no clipping region is set but the returned rectangle is clearly not covering the bounds of the printable area.
Comment 7 Randy Hudson CLA 2006-03-01 23:10:28 EST
Reopening. Sounds like we almost have a test snippet here.
SWT folks, any chance a printer fresh GC has empty clip rect on the Mac?
Comment 8 Steve Northover CLA 2006-03-02 11:42:49 EST
Mac was changed to use HIView for 3.2.  Could this be causing the trouble?  You can go and hammer a constant in org.eclipse.swt.internal.carbon.OS to test out this theory?
Comment 9 Randy Hudson CLA 2006-03-02 13:46:23 EST
Eric, please try removing Draw2d from the snippet:

Printer printer = new Printer();
printer.startJob("bugzilla 81467");
GC gc = new GC(printer);
System.out.println(gc.getClipping());
gc.dispose();
printer.dispose();

If getClipping() is returning an empty Rectangle, I think this should moved to SWT.

But, the infinite loop is interesting. Is your code in the loop, or is it 100% draw2d code looping? A partial stack trace would help.
Comment 10 Eric Wasserman CLA 2006-03-02 15:30:16 EST
Regarding comment #8

My tests have been on Eclipse 3.1.2 not 3.2 so changes in the latter version did not bring this about.

To what constant in org.eclipse.swt.internal.carbon.OS are you referring?
Comment 11 Eric Wasserman CLA 2006-03-02 15:33:23 EST
Regarding comment #9

Randy's draw2D-free snippet prints:

Rectangle {0, 0, 0, 0}

i.e. the clip rect has zero extent.
Comment 12 Eric Wasserman CLA 2006-03-02 16:00:52 EST
Regarding the second part of comment #9

The infinite loop is all in draw2D code: org.eclipse.draw2D.PrintFigureOperation.printPages()

protected void printPages() {
	Graphics graphics = getFreshPrinterGraphics();
	IFigure figure = getPrintSource();
	setupPrinterGraphicsFor(graphics, figure);
	Rectangle bounds = figure.getBounds();
	int x = bounds.x, y = bounds.y;
	Rectangle clipRect = new Rectangle();
	while (y < bounds.y + bounds.height) {
		while (x < bounds.x + bounds.width) {    // <<<----- (0)
			graphics.pushState();
			getPrinter().startPage();
			graphics.translate(-x, -y);
			graphics.getClip(clipRect);            // <<<------ (1) this always sets clipRect to {0,0,0,0}
			clipRect.setLocation(x, y);
			graphics.clipRect(clipRect);
			figure.paint(graphics);
			getPrinter().endPage();
			graphics.popState();
			x += clipRect.width;                   // <<<------- (2) clipRect.width is always 0
		}
		x = bounds.x;
		y += clipRect.height;
	}
}


(1) always sets clipRect to {0,0,0,0}
This is because the underlying SWTGraphics has a currentState.relativeClip which is {0,0,0,0}
in turn it has this zero size clip due to the SWTGraphics.init() doing 
  currentState.relativeClip = new RectangleClipping(gc.getClipping()); 
where the GC.getClipping() has returned {0,0,0,0}

(2) x increments by zero since the clipRect width is zero. Therefore the loop (0) never exits.


For what it's worth, I looked at how the StyledText prints (because printing of, for example, Java code works on OS X). In this case the bounds of the printer are derived from org.eclipse.swt.printing.Printer.getClientArea() instead of from the clipRect of the printer GC. This yields a Rectangle of non-zero size.
Comment 13 Steve Northover CLA 2006-03-02 21:47:06 EST
This clip rect thing looks like our bug.
Comment 14 Randy Hudson CLA 2006-03-03 00:07:55 EST
Changing Severity since there are several workarounds. One workaround would be to override setupPrinterGraphics to set the clipRect to the Printer's clientArea, as StyledText is doing.
Comment 15 Herman Lintvelt CLA 2007-04-16 05:52:21 EDT
What is the best workaround to use on Mac OS to get printing from GEF working?
Comment 16 Steve Northover CLA 2007-04-16 08:54:22 EDT
CAR, can you check out the clip rect bug?
Comment 17 Carolyn MacLeod CLA 2007-04-16 15:47:08 EDT
Fixed > 20070416.  Will be in tomorrow's I-build.
The Printer object now saves the page bounds in the GCData, so that the getClipping methods can return a clip rectangle for printers.
Comment 18 Carolyn MacLeod CLA 2007-04-16 15:54:54 EDT
Note that I only tested using Randy's snippet from comment 9:

import org.eclipse.swt.graphics.*;
import org.eclipse.swt.printing.*;

public class Bug81467 {

public static void main(String[] args) {
    Printer printer = new Printer();
    printer.startJob("bugzilla 81467");
    GC gc = new GC(printer);
    System.out.println(gc.getClipping());
    printer.endJob();
    printer.dispose();
}
}

i.e. I am unable to easily test GEF. Can someone please get tomorrow's I-build and try Randy's snippet in comment 4 to make sure that GEF no longer gets stuck in an infinite loop? I suspect that it should be ok.