package org.xmind.ui.internal.svgsupport; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Display; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xmind.gef.draw2d.geometry.PrecisionPoint; import org.xmind.gef.draw2d.geometry.PrecisionRectangle; import org.xmind.gef.draw2d.graphics.Path; /** * * @author Enki Xiong * */ final public class SVGTextElement extends SVGShape { private FontResourceDescriptor fontDescriptor; private List<TextSpan> spans; private static class TextSpan { private float x; private float y; private String text; public TextSpan(float x, float y, String text) { this.x = x; this.y = y; this.text = text; } } SVGTextElement() { super(); this.spans = new ArrayList<SVGTextElement.TextSpan>(); } public SVGTextElement(FontResourceDescriptor fontDescriptor) { this.fontDescriptor = fontDescriptor; } @Override public void parse(Element implemention, SVGShape parent) { super.parse(implemention, parent); parseText(implemention, parent); } @Override public Path generatePath(Display device) { //FIXME correct x,y Font font = (Font) getResourceManager().create(fontDescriptor); Path path = new Path(device); for (TextSpan span : spans) { path.addString(span.text, new PrecisionPoint(span.x, span.y), font); } return path; } @Override PrecisionRectangle generateRectangle() { return INVALID_RECT; } private void parseText(Element implemention, SVGShape parent) { String fontFamily = implemention .getAttribute(SVGDefinitionConstants.FONT_FAMILY).trim(); int fontSize = (int) getFloatAttribute(implemention, SVGDefinitionConstants.FONT_SIZE); String fontStyle = implemention .getAttribute(SVGDefinitionConstants.FONT_WEIGHT).trim(); int style = 0; if (fontStyle.contains(SVGDefinitionConstants.BOLD)) { style |= SWT.BOLD; } if (fontStyle.contains(SVGDefinitionConstants.ITALIC)) { style |= SWT.ITALIC; } fontDescriptor = new FontResourceDescriptor(fontFamily, fontSize, style); NodeList list = implemention.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { Node node = list.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element ele = (Element) node; String text = ele.getTextContent(); float x = getFloatAttribute(implemention, SVGDefinitionConstants.X); float y = getFloatAttribute(implemention, SVGDefinitionConstants.Y); this.spans.add(new TextSpan(x, y, text)); } } } @Override protected SVGShape clone() { SVGTextElement text = new SVGTextElement(); text.fontDescriptor = this.fontDescriptor; text.spans = spans; text.setInfo(getInfo().clone()); return text; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj instanceof SVGTextElement) { SVGTextElement text = (SVGTextElement) obj; if (getInfo() != null && getInfo().equals(text.getInfo()) && fontDescriptor != null && fontDescriptor.equals(text.fontDescriptor)) if (spans.size() == text.spans.size()) { for (int i = 0; i < spans.size(); i++) { TextSpan span1 = spans.get(i); TextSpan span2 = text.spans.get(i); if (!(span1.x == span2.x && span1.y == span2.y && span1.text.equals(span2.text))) return false; } return true; } } return false; } @Override public int hashCode() { int result = 17; result = result * 31 + getInfo().hashCode(); result = result * 31 + fontDescriptor.hashCode(); for (TextSpan span : spans) { result = result * 31 + Float.floatToIntBits(span.x); result = result * 31 + Float.floatToIntBits(span.y); result = result * 31 + span.text.hashCode(); } return result; } @Override public String toString() { return "SVGText(" + fontDescriptor.toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } public void addText(float x, float y, String text) { if (spans == null) { spans = new ArrayList<TextSpan>(); } spans.add(new TextSpan(x, y, text)); } }