Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 130419

Summary: implement rotate for ScaledGraphics
Product: [Tools] GEF Reporter: Chris Lee <eclipse>
Component: GEF-Legacy Draw2dAssignee: gef-inbox <gef-inbox>
Status: RESOLVED WORKSFORME QA Contact:
Severity: enhancement    
Priority: P3 CC: ahunter.eclipse, dsciamma, hudsonr, morten-eclipse, nyssen, robert.moloney, sbernard
Version: 3.2Flags: ahunter.eclipse: galileo+
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
graphics modified
none
An plugin with example of use none

Description Chris Lee CLA 2006-03-03 20:28:47 EST
The primary reason for this request is to render rotated text.
Comment 1 Chris Lee CLA 2006-03-03 20:47:26 EST
It seems that rotate doesn't even work as expected on an SWTGraphics for trying to render rotated text (using a TextLayout)...
Comment 2 Steven R. Shaw CLA 2006-03-04 08:44:39 EST
have you taken a look at ImageUtilities#createRotatedImageOfString ?
Comment 3 Chris Lee CLA 2006-03-04 12:55:05 EST
I hadn't before; it's a good starting point though; it only handles basic strings - how about a TextLayout (which does multiple fonts, underline and strikethrough)?
Comment 4 Morten Moeller CLA 2007-12-30 22:16:41 EST
This really should be implemented, you cannot use the advanced transforms much if you cannot use it also in scaled graphics. rotate() works for so much more than just text.. 
Comment 5 Morten Moeller CLA 2007-12-30 22:24:49 EST
Disregard my other comment. In fact ScaledGraphics is obsolete as Graphics support scaling itself now and it works fine.

If you change ZoomContainer.java in the draw2d examples to this:


/**
 * @see org.eclipse.draw2d.Figure#paintClientArea(Graphics)
 */
protected void paintClientArea(Graphics graphics) {
	if (getChildren().isEmpty())
		return;

	boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

//	ScaledGraphics g = new ScaledGraphics(graphics);
//
//	if (!optimizeClip)
//		g.clipRect(getBounds().getCropped(getInsets()));
//	g.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
//	g.scale(zoom);
//	g.pushState();
//	paintChildren(g);
//	g.popState();
//	g.dispose();
//	graphics.restoreState();

	graphics.scale(zoom);
	graphics.pushState();
	paintChildren(graphics);
	graphics.popState();
}

---

It works fine (even better looking.. well on Mac at least, font scaling is much smoother). This might not work for non-windows/linux/mac platforms that doesn't support advanced graphics..



Comment 6 Chris Lee CLA 2007-12-31 11:31:12 EST
ScaledGraphics is definitely not obsolete :)

I actually tried using something similar to below for doing scaling on SWTGraphics and although it "mostly" worked, noticeable chunks of the rendering were much messier and/or simply didn't work.

As a note on this, is there any further discussion on the Eclipse side for the ability to render complex rotated text, or is this something we'll have to do ourselves?
Comment 7 Morten Moeller CLA 2008-01-01 22:44:08 EST
Uhm, ScaledGraphics were made to support the .scale() function/transform it looks like. Now that method exists in Graphics, ScaledGraphics provides no functionality beyond Graphics anymore. 

Obviously they both have flaws and bugs, but keeping two implementation of scale transforms doesn't sound good to me. If Graphics.scale() is buggy to you, maybe that should be bug reported? 
Comment 8 Randy Hudson CLA 2008-01-02 11:06:08 EST
(In reply to comment #7)
> Uhm, ScaledGraphics were made to support the .scale() function/transform it
> looks like. Now that method exists in Graphics, ScaledGraphics provides no
> functionality beyond Graphics anymore. 

There is still a significant performance hit on win32 win using native scaling, and many differences in the results, including poor font rendering. Both versions are still needed, but with the restriction that ScaledGraphics will never use advanced graphics, so rotate and other methods can not be implemented. Clients needing rotate will have to accept the trade-offs of the native scaling in those cases.
Comment 9 Anthony Hunter CLA 2008-09-29 17:18:22 EDT
(In reply to comment #0)
> The primary reason for this request is to render rotated text.
> 

Agree, we have this requirement as well, so adding to the preliminary GEF 3.5 plan.
Comment 10 Simon Bernard CLA 2008-09-30 04:31:16 EDT
I'm working on adding the rotation in GEF. I have began to add rotation on graphics and now I'm working on create a RotatableFigure. I will add an attachment of my work.
Comment 11 Simon Bernard CLA 2008-09-30 05:07:49 EDT
Created attachment 113844 [details]
graphics modified

Currently, the rotate method on graphics makes a rotation around the point (0,0).Not really useable ...
So, I modified the graphics to allow the rotation around a given point.

public void rotate(float degrees,int x,int y) {
	//Flush clipping, patter, etc., before applying transform
	checkGC();
	initTransform(true);
	initRotateTransform();
	
	//to make a rotation of center (x,y)
	//translate to the origin
	transformTranslateToOri.translate(-x,-y);
    //rotate around the origin
    transformRotate.rotate(degrees);
    //translate to the center of rotation
    transformTranslateToCenter.translate(x, y);

    transform.multiply(transformTranslateToCenter);
    transform.multiply(transformRotate);
    transform.multiply(transformTranslateToOri);
    
    //apply transform to gc
    gc.setTransform(transform);
    
	elementsNeedUpdate = true;

	//Can no longer operate or maintain clipping
	appliedState.relativeClip = currentState.relativeClip = null;
}
Comment 12 Simon Bernard CLA 2008-09-30 05:16:11 EDT
Created attachment 113846 [details]
An  plugin with example of use

I have created a plugin with examples of use

Extract:
--------
Figure figure = new Figure(){
	private final int insets= 25;

	@Override
	protected void paintFigure(Graphics graphics) {
		graphics.setAntialias(SWT.ON);
		
                // draw bounds
                graphics.drawRectangle
                     (getBounds().getCopy().crop(new Insets(1)));
		
                // draw rect rot 0
		Rectangle rect = getBounds().getCopy().crop(new Insets(insets));
		graphics.drawRectangle(rect);
				
		// draw rect rot 22.5
		graphics.rotate(22.5f,getBounds().getCenter());
                graphics.setForegroundColor
                      (Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
		graphics.drawRectangle(rect);
				
		// draw rect rot 22.5+22.5
		graphics.rotate(22.5f,getBounds().getCenter());
                graphics.setForegroundColor
                      (Display.getCurrent().getSystemColor(SWT.COLOR_RED));
		graphics.drawRectangle(rect);
	}
};
Comment 13 Randy Hudson CLA 2008-09-30 11:23:46 EDT
>                 // draw rect rot 22.5
>                 graphics.rotate(22.5f,getBounds().getCenter());
>                 graphics.setForegroundColor
>                       (Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
>                 graphics.drawRectangle(rect);

Simon, this new API is not needed.  You can do the same thing using:

Point center = getBounds().getCenter();
graphics.translate(center.x, center.y);
graphics.rotate(22.5f);
graphics.translate(-center.x, -center.y);

Chris, if there are issues with using the scaling support, please open separate bugs. BTW, I've submitted a patch to SWT that addresses many of the GDI+ inconsistencies.

ScaledGraphics will not support rotation. By design, ScaledGraphics avoids advanced graphics, so emulating rotation would be very hard. The recommendation is to use SWTGraphics instead and invoke the advanced graphics support.
Comment 14 Anthony Hunter CLA 2008-09-30 11:43:29 EDT
(In reply to comment #9)
> 
> Agree, we have this requirement as well, so adding to the preliminary GEF 3.5
> plan.
> 

Reopening, this enhancement is a plan item for GEF 3.5. Any dependent bugzillas need to be cross referenced here. 

Until we have a draw2d snippet checked into CVS demonstrating text rotation for scaled graphics, this Bugzilla will NOT be closed.
Comment 15 Simon Bernard CLA 2008-09-30 11:49:22 EDT
> ScaledGraphics will not support rotation. By design, ScaledGraphics avoids
> advanced graphics, so emulating rotation would be very hard. 

Why does it avoid advanced Graphics ?

Comment 16 Randy Hudson CLA 2008-09-30 13:02:06 EDT
Oops!  Sorry Anthony, didn't see your comment 9.

Isn't this related to bug 103717? If ScaledGraphics were not being used, then rendering rotated text is already working.
Comment 17 Alexander Nyßen CLA 2011-01-28 10:48:07 EST
(In reply to comment #8)
> (In reply to comment #7)
> > Uhm, ScaledGraphics were made to support the .scale() function/transform it
> > looks like. Now that method exists in Graphics, ScaledGraphics provides no
> > functionality beyond Graphics anymore. 
> 
> There is still a significant performance hit on win32 win using native scaling,
> and many differences in the results, including poor font rendering. Both
> versions are still needed, but with the restriction that ScaledGraphics will
> never use advanced graphics, so rotate and other methods can not be
> implemented. Clients needing rotate will have to accept the trade-offs of the
> native scaling in those cases.
 
If we provide a hook as required/desired in bug #103717 to allow choosing between native and emulated scaling, wouldn't it be straightforward to change the implementation of ZoomManager and ScalableFigure implementors to use Graphics.scale by default, and to use a ScaledGraphics only if the provided Graphics does not support advanced mode or the emulation mode is explicitly required?
Comment 18 Alexander Nyßen CLA 2011-03-04 14:28:32 EST
(In reply to comment #14)
> (In reply to comment #9)
> > 
> > Agree, we have this requirement as well, so adding to the preliminary GEF 3.5
> > plan.
> > 
> 
> Reopening, this enhancement is a plan item for GEF 3.5. Any dependent bugzillas
> need to be cross referenced here. 
> 
> Until we have a draw2d snippet checked into CVS demonstrating text rotation for
> scaled graphics, this Bugzilla will NOT be closed.

As far as simple text is concerned, I think ScaledGraphics as well as SWTGraphics are feature-complete to this extent, as demonstrated by the following snippet (which I have not checked in yet).

package org.eclipse.draw2d.examples.rotate;

import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.ScaledGraphics;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class RotatedTextExample {

	public static void main(String[] args) {
		Display d = new Display();
		Shell shell = new Shell(d);
		shell.setLayout(new FillLayout());

		shell.addPaintListener(new PaintListener() {

			public void paintControl(PaintEvent e) {
				SWTGraphics nativeGraphics = new SWTGraphics(e.gc);
				nativeGraphics.rotate(22);
				nativeGraphics.drawText("Hello World", new Point(25, 0));
				nativeGraphics.rotate(-22);
				ScaledGraphics emulatedGraphics = new ScaledGraphics(
						nativeGraphics);
				emulatedGraphics.rotate(22);
				emulatedGraphics.drawText("Hello World", new Point(125, 0));
				emulatedGraphics.dispose();
				nativeGraphics.dispose();
			}
		});

		shell.setText("Rotating Text");
		shell.setSize(200, 150);
		shell.open();
		while (!shell.isDisposed())
			while (!d.readAndDispatch())
				d.sleep();

	}
}
Comment 19 Alexander Nyßen CLA 2014-08-24 10:11:23 EDT
I extended the Draw2d PathExample as follows:
- Changed example to render a rotated text layout with a text style (underline) within PathFigure.
- Added a button that allows to switch between native and emulated scaling within ZoomFigure (added a setScaleMethod() option to ZoomFigure, as proposed for all scalable figures within bug #103717).

Resolving this as WORKSFORME, as the example can be used to demonstrate that rendering rotated text layout is feasible with SWTGraphics as well as ScaledGraphics.