/****************************************************************************
* Copyright (c) 2008, 2009 Jeremy Dowdall
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jeremy Dowdall <jeremyd@aspencloud.com> - initial API and implementation
*****************************************************************************/
package org.eclipse.nebula.cwt.svg;
import org.eclipse.nebula.cwt.svg.SvgPaint.PaintType;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Transform;
/**
* A base abstract class for all types of svg elements which can be
* applied (painted) to a graphics context. These may be shapes which
* can be painted directly, or containers which will paint their children.
*/
public abstract class SvgGraphic extends SvgElement {
String title;
String description;
SvgFill fill;
SvgStroke stroke;
SvgTransform transform;
SvgGraphic(SvgContainer container, String id) {
super(container, id);
fill = new SvgFill(this);
stroke = new SvgStroke(this);
}
/**
* Apply this svg graphic to the given graphics context.
* <p>Note that to support the rather abstract structure of svg,
* each time this method is called all transformations and css properties
* to be calculated and applied. If this is a shape, it will be
* painted to the graphics context. Containers will recursively
* make this call on their children.</p>
* @param gc the gc to use in all graphics operations
*/
public abstract void apply(GC gc);
/**
* Returns the value of the <code>desc</code> element that is a child of this svg element.
* If there is no <code>desc</code> element that is a direct decendent of this element, null
* is returned.
* @return the <code>desc</code> of this svg element
*/
public String getDescription() {
return (description == null) ? null : description;
}
SvgFill getFill() {
SvgFill df = new SvgFill(this);
for(SvgElement el : getAncestry(this)) {
if(el instanceof SvgGraphic) {
SvgFill tmp = ((SvgGraphic) el).fill;
if(tmp.type != null) {
df.type = tmp.type;
}
if(tmp.color != null) {
df.color = tmp.color;
}
if(tmp.linkId != null) {
df.linkId = tmp.linkId;
}
if(tmp.opacity != null) {
df.opacity = tmp.opacity;
}
if(tmp.rule != null) {
df.rule = tmp.rule;
}
}
}
if(df.type == null) {
df.type = PaintType.Color;
}
if(df.color == null) {
df.color = 0;
}
if(df.opacity == null) {
df.opacity = 1f;
}
if(df.rule == null) {
df.rule = SWT.FILL_EVEN_ODD;
}
return df;
}
SvgStroke getStroke() {
SvgStroke ds = new SvgStroke(this);
for(SvgElement el : getAncestry(this)) {
if(el instanceof SvgGraphic) {
SvgStroke tmp = ((SvgGraphic) el).stroke;
if(tmp.type != null) {
ds.type = tmp.type;
}
if(tmp.color != null) {
ds.color = tmp.color;
}
if(tmp.linkId != null) {
ds.linkId = tmp.linkId;
}
if(tmp.opacity != null) {
ds.opacity = tmp.opacity;
}
if(tmp.width != null) {
ds.width = tmp.width;
}
if(tmp.lineCap != null) {
ds.lineCap = tmp.lineCap;
}
if(tmp.lineJoin != null) {
ds.lineJoin = tmp.lineJoin;
}
}
}
if(ds.type == null) {
ds.type = PaintType.None;
}
if(ds.type != PaintType.None) {
if(ds.color == null) {
ds.color = 0;
}
if(ds.opacity == null) {
ds.opacity = 1f;
}
if(ds.width == null) {
ds.width = 1f;
}
if(ds.lineCap == null) {
ds.lineCap = SWT.CAP_FLAT;
}
if(ds.lineJoin == null) {
ds.lineJoin = SWT.JOIN_MITER;
}
}
return ds;
}
Transform getTransform(GC gc) {
Transform t = new Transform(gc.getDevice());
gc.getTransform(t);
for(SvgElement el : getAncestry(this)) {
if(el instanceof SvgFragment) {
SvgTransform st = ((SvgFragment) el).boundsTransform;
if(!st.isIdentity()) {
Transform tmp = new Transform(gc.getDevice());
tmp.setElements(st.data[0], st.data[1], st.data[2], st.data[3], st.data[4], st.data[5]);
t.multiply(tmp);
tmp.dispose();
}
} else if(el instanceof SvgGraphic) {
SvgTransform st = ((SvgGraphic) el).transform;
while(st != null) {
if(!st.isIdentity()) {
Transform tmp = new Transform(gc.getDevice());
tmp.setElements(st.data[0], st.data[1], st.data[2], st.data[3], st.data[4], st.data[5]);
t.multiply(tmp);
tmp.dispose();
}
st = st.next;
}
}
}
return t;
}
/**
* Returns the value of the <code>title</code> element that is a child of this svg element.
* If there is no <code>title</code> element that is a direct decendent of this element, null
* is returned.
* @return the <code>title</code> of this svg element
*/
public String getTitle() {
return (title == null) ? null : title;
}
}