/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.draw2d.graphics;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.LineAttributes;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.TextLayout;
/**
* @author Frank Shaka
*
*/
public abstract class ColorMaskGraphics extends Graphics {
private Graphics delegate;
private Stack<Color> fgColors;
private Stack<Color> bgColors;
private Color localForeground;
private Color localBackground;
private int localAlpha;
private Map<RGB, Color> workingColors;
private Stack<Pattern> fgPatterns;
private Stack<Pattern> bgPatterns;
private Pattern currentFgPattern;
private Pattern currentBgPattern;
public ColorMaskGraphics(Graphics delegate, Object... args) {
this.delegate = delegate;
init(args);
delegate.pushState();
this.localForeground = delegate.getForegroundColor();
this.localBackground = delegate.getBackgroundColor();
pushColors();
this.localAlpha = delegate.getAlpha();
delegate.setForegroundColor(getWorkingColor(localForeground));
delegate.setBackgroundColor(getWorkingColor(localBackground));
delegate.setAlpha(0xff);
}
protected void init(Object... args) {
}
protected abstract RGB getMaskColor(RGB rgb);
private void pushColors() {
if (fgColors == null)
fgColors = new Stack<Color>();
fgColors.push(localForeground);
if (bgColors == null)
bgColors = new Stack<Color>();
bgColors.push(localBackground);
}
private void restoreColors() {
if (fgColors != null && !fgColors.isEmpty())
localForeground = fgColors.peek();
if (bgColors != null && !bgColors.isEmpty())
localBackground = bgColors.peek();
}
private void popupColors() {
if (fgColors != null && !fgColors.isEmpty())
localForeground = fgColors.pop();
if (bgColors != null && !bgColors.isEmpty())
localBackground = bgColors.pop();
}
protected Graphics getDelegate() {
return delegate;
}
protected Color getWorkingColor(Color c) {
if (c == null)
return null;
RGB rgb = c.getRGB();
if (workingColors == null)
workingColors = new HashMap<RGB, Color>();
Color grayed = workingColors.get(rgb);
if (grayed == null) {
grayed = createWorkingColor(c.getDevice(), rgb);
workingColors.put(rgb, grayed);
}
return grayed;
}
private Color createWorkingColor(Device device, RGB rgb) {
return new Color(device, getMaskColor(rgb));
}
public void setForegroundColor(Color rgb) {
if (rgb.isDisposed()) {
System.out.println("!!!Color Disposed: " + rgb); //$NON-NLS-1$
}
localForeground = rgb;
delegate.setForegroundColor(getWorkingColor(rgb));
}
public void setBackgroundColor(Color rgb) {
localBackground = rgb;
delegate.setBackgroundColor(getWorkingColor(rgb));
}
public Color getForegroundColor() {
return localForeground;
}
public Color getBackgroundColor() {
return localBackground;
}
public void setAlpha(int alpha) {
this.localAlpha = alpha;
if (alpha == 0)
delegate.setAlpha(alpha);
else
delegate.setAlpha(0xff);
}
public int getAlpha() {
return localAlpha;
}
public void setForegroundPattern(Pattern pattern) {
if (currentFgPattern != null) {
currentFgPattern.dispose();
currentFgPattern = null;
}
if (pattern instanceof GradientPattern) {
GradientPattern gp = (GradientPattern) pattern;
pattern = createGrayedPattern(gp);
currentFgPattern = pattern;
}
delegate.setForegroundPattern(pattern);
}
public void setBackgroundPattern(Pattern pattern) {
if (currentBgPattern != null) {
currentBgPattern.dispose();
currentBgPattern = null;
}
if (pattern instanceof GradientPattern) {
GradientPattern gp = (GradientPattern) pattern;
pattern = createGrayedPattern(gp);
currentBgPattern = pattern;
}
delegate.setBackgroundPattern(pattern);
}
private Pattern createGrayedPattern(GradientPattern p) {
return new GradientPattern(p.getDevice(), p.x1, p.y1, p.x2, p.y2,
getWorkingColor(p.color1), 0xff, getWorkingColor(p.color2),
0xff);
}
public void dispose() {
popupColors();
delegate.popState();
if (workingColors != null) {
for (Color c : workingColors.values()) {
c.dispose();
}
workingColors = null;
}
if (currentFgPattern != null) {
currentFgPattern.dispose();
currentFgPattern = null;
}
if (currentBgPattern != null) {
currentBgPattern.dispose();
currentBgPattern = null;
}
if (fgPatterns != null) {
for (Pattern p : fgPatterns) {
if (p != null)
p.dispose();
}
fgPatterns = null;
}
if (bgPatterns != null) {
for (Pattern p : bgPatterns) {
if (p != null)
p.dispose();
}
bgPatterns = null;
}
}
public void pushState() {
delegate.pushState();
pushColors();
if (fgPatterns == null)
fgPatterns = new Stack<Pattern>();
fgPatterns.push(currentFgPattern);
currentFgPattern = null;
if (bgPatterns == null)
bgPatterns = new Stack<Pattern>();
bgPatterns.push(currentBgPattern);
currentBgPattern = null;
}
public void popState() {
delegate.popState();
popupColors();
if (currentFgPattern != null) {
currentFgPattern.dispose();
currentFgPattern = null;
}
if (fgPatterns != null) {
currentFgPattern = fgPatterns.pop();
}
if (currentBgPattern != null) {
currentBgPattern.dispose();
currentBgPattern = null;
}
if (bgPatterns != null) {
currentBgPattern = bgPatterns.pop();
}
}
public void restoreState() {
delegate.restoreState();
restoreColors();
}
// ---------------------------
// Delegating Methods
// ---------------------------
public void clipRect(Rectangle r) {
delegate.clipRect(r);
}
public void clipPath(Path path) {
delegate.clipPath(path);
}
public void drawArc(int x, int y, int w, int h, int offset, int length) {
delegate.drawArc(x, y, w, h, offset, length);
}
public void drawFocus(int x, int y, int w, int h) {
delegate.drawFocus(x, y, w, h);
}
public void drawImage(Image srcImage, int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2) {
delegate.drawImage(srcImage, x1, y1, w1, h1, x2, y2, w2, h2);
}
public void drawImage(Image srcImage, int x, int y) {
delegate.drawImage(srcImage, x, y);
}
public void drawLine(int x1, int y1, int x2, int y2) {
delegate.drawLine(x1, y1, x2, y2);
}
public void drawOval(int x, int y, int w, int h) {
delegate.drawOval(x, y, w, h);
}
public void drawPath(Path path) {
delegate.drawPath(path);
}
public void drawPoint(int x, int y) {
delegate.drawPoint(x, y);
}
public void drawPolygon(int[] points) {
delegate.drawPolygon(points);
}
public void drawPolygon(PointList points) {
delegate.drawPolygon(points);
}
public void drawPolyline(int[] points) {
delegate.drawPolyline(points);
}
public void drawPolyline(PointList points) {
delegate.drawPolyline(points);
}
public void drawRectangle(int x, int y, int width, int height) {
delegate.drawRectangle(x, y, width, height);
}
public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
delegate.drawRoundRectangle(r, arcWidth, arcHeight);
}
public void drawString(String s, int x, int y) {
delegate.drawString(s, x, y);
}
public void drawText(String s, int x, int y, int style) {
delegate.drawText(s, x, y, style);
}
public void drawText(String s, int x, int y) {
delegate.drawText(s, x, y);
}
public void drawTextLayout(TextLayout layout, int x, int y,
int selectionStart, int selectionEnd, Color selectionForeground,
Color selectionBackground) {
delegate.drawTextLayout(layout, x, y, selectionStart, selectionEnd,
selectionForeground, selectionBackground);
}
public void fillArc(int x, int y, int w, int h, int offset, int length) {
delegate.fillArc(x, y, w, h, offset, length);
}
public void fillGradient(int x, int y, int w, int h, boolean vertical) {
delegate.fillGradient(x, y, w, h, vertical);
}
public void fillOval(int x, int y, int w, int h) {
delegate.fillOval(x, y, w, h);
}
public void fillPath(Path path) {
delegate.fillPath(path);
}
public void fillPolygon(int[] points) {
delegate.fillPolygon(points);
}
public void fillPolygon(PointList points) {
delegate.fillPolygon(points);
}
public void fillRectangle(int x, int y, int width, int height) {
delegate.fillRectangle(x, y, width, height);
}
public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
delegate.fillRoundRectangle(r, arcWidth, arcHeight);
}
public void fillString(String s, int x, int y) {
delegate.fillString(s, x, y);
}
public void fillText(String s, int x, int y) {
delegate.fillText(s, x, y);
}
public double getAbsoluteScale() {
return delegate.getAbsoluteScale();
}
public int getAntialias() {
return delegate.getAntialias();
}
public Rectangle getClip(Rectangle rect) {
return delegate.getClip(rect);
}
public int getFillRule() {
return delegate.getFillRule();
}
public Font getFont() {
return delegate.getFont();
}
public FontMetrics getFontMetrics() {
return delegate.getFontMetrics();
}
public int getInterpolation() {
return delegate.getInterpolation();
}
public int getLineCap() {
return delegate.getLineCap();
}
public int getLineJoin() {
return delegate.getLineJoin();
}
public int getLineStyle() {
return delegate.getLineStyle();
}
public int getLineWidth() {
return delegate.getLineWidth();
}
public int getTextAntialias() {
return delegate.getTextAntialias();
}
public boolean getXORMode() {
return delegate.getXORMode();
}
public void rotate(float degrees) {
delegate.rotate(degrees);
}
public void scale(double amount) {
delegate.scale(amount);
}
public void scale(float horizontal, float vertical) {
delegate.scale(horizontal, vertical);
}
public void setAntialias(int value) {
delegate.setAntialias(value);
}
public void setClip(Path path) {
delegate.setClip(path);
}
public void setClip(Rectangle r) {
delegate.setClip(r);
}
public void setFillRule(int rule) {
delegate.setFillRule(rule);
}
public void setFont(Font f) {
delegate.setFont(f);
}
public void setInterpolation(int interpolation) {
delegate.setInterpolation(interpolation);
}
public void setLineCap(int cap) {
delegate.setLineCap(cap);
}
public void setLineDash(int[] dash) {
delegate.setLineDash(dash);
}
public void setLineJoin(int join) {
delegate.setLineJoin(join);
}
public void setLineStyle(int style) {
delegate.setLineStyle(style);
}
public void setLineWidth(int width) {
delegate.setLineWidth(width);
}
public void setTextAntialias(int value) {
delegate.setTextAntialias(value);
}
public void setXORMode(boolean b) {
delegate.setXORMode(b);
}
public void shear(float horz, float vert) {
delegate.shear(horz, vert);
}
public void translate(float dx, float dy) {
delegate.translate(dx, dy);
}
public void translate(int dx, int dy) {
delegate.translate(dx, dy);
}
// ==========================================================
// Since 3.5
// ==========================================================
public boolean getAdvanced() {
return delegate.getAdvanced();
}
public float getLineMiterLimit() {
return delegate.getLineMiterLimit();
}
public LineAttributes getLineAttributes() {
return delegate.getLineAttributes();
}
public float getLineWidthFloat() {
return delegate.getLineWidthFloat();
}
public void setAdvanced(boolean advanced) {
delegate.setAdvanced(advanced);
}
public void setLineMiterLimit(float miterLimit) {
delegate.setLineMiterLimit(miterLimit);
}
public void setLineWidthFloat(float width) {
delegate.setLineWidthFloat(width);
}
public void setLineAttributes(LineAttributes attributes) {
delegate.setLineAttributes(attributes);
}
public void setLineDash(float[] value) {
delegate.setLineDash(value);
}
}