mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-17 00:44:40 -04:00
adds very basic css formatting to support Adobe Illustrator
This commit is contained in:
parent
814a9fd20b
commit
53c15330d7
@ -366,6 +366,13 @@ public class CustomShapeDescription implements Iterable<CustomShapeDescription.H
|
||||
p1 = p1.transform(tr).round();
|
||||
p2 = p2.transform(tr).round();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the text position
|
||||
*/
|
||||
public Vector getPos() {
|
||||
return p1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,10 @@
|
||||
*/
|
||||
package de.neemann.digital.draw.shapes.custom.svg;
|
||||
|
||||
import de.neemann.digital.draw.graphics.*;
|
||||
import de.neemann.digital.draw.graphics.Orientation;
|
||||
import de.neemann.digital.draw.graphics.Transform;
|
||||
import de.neemann.digital.draw.graphics.VectorFloat;
|
||||
import de.neemann.digital.draw.graphics.VectorInterface;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
@ -30,6 +33,7 @@ class Context {
|
||||
PARSER.put("style", Context::readStyle);
|
||||
PARSER.put("text-anchor", (c, value) -> c.textAnchor = value);
|
||||
PARSER.put("fill-rule", (c, value) -> c.fillRuleEvenOdd = value.equalsIgnoreCase("evenodd"));
|
||||
PARSER.put("class", Context::evalClass);
|
||||
}
|
||||
|
||||
private Transform tr;
|
||||
@ -41,6 +45,7 @@ class Context {
|
||||
private float fontSize;
|
||||
private String textAnchor;
|
||||
private boolean fillRuleEvenOdd;
|
||||
private HashMap<String, String> classesMap;
|
||||
|
||||
Context() {
|
||||
tr = Transform.IDENTITY;
|
||||
@ -48,6 +53,7 @@ class Context {
|
||||
stroke = Color.BLACK;
|
||||
fillOpacity = 1;
|
||||
strokeOpacity = 1;
|
||||
classesMap = new HashMap<>();
|
||||
}
|
||||
|
||||
private Context(Context parent) {
|
||||
@ -60,6 +66,8 @@ class Context {
|
||||
fontSize = parent.fontSize;
|
||||
textAnchor = parent.textAnchor;
|
||||
fillRuleEvenOdd = parent.fillRuleEvenOdd;
|
||||
classesMap = new HashMap<>();
|
||||
classesMap.putAll(parent.classesMap);
|
||||
}
|
||||
|
||||
Context(Context parent, Element element) throws SvgException {
|
||||
@ -146,6 +154,34 @@ class Context {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
void addClasses(String classes) {
|
||||
classes = classes.trim();
|
||||
while (classes.startsWith(".")) {
|
||||
int p1 = classes.indexOf("{");
|
||||
int p2 = classes.indexOf("}");
|
||||
if (p1 < 0 || p2 < 0)
|
||||
return;
|
||||
String key = classes.substring(1, p1);
|
||||
String val = classes.substring(p1 + 1, p2);
|
||||
classesMap.put(key, val);
|
||||
classes = classes.substring(p2 + 1).trim();
|
||||
}
|
||||
}
|
||||
|
||||
String getCssClass(String key) {
|
||||
return classesMap.get(key);
|
||||
}
|
||||
|
||||
private static void evalClass(Context c, String value) throws SvgException {
|
||||
StringTokenizer st = new StringTokenizer(value, ", ");
|
||||
while (st.hasMoreTokens()) {
|
||||
String cl = st.nextToken();
|
||||
String style = c.getCssClass(cl);
|
||||
if (style != null)
|
||||
readStyle(c, style);
|
||||
}
|
||||
}
|
||||
|
||||
private interface AttrParser {
|
||||
void parse(Context c, String value) throws SvgException;
|
||||
}
|
||||
|
@ -89,8 +89,13 @@ public class SvgImporter {
|
||||
private void create(CustomShapeDescription csd, NodeList gList, Context c) throws SvgException {
|
||||
for (int i = 0; i < gList.getLength(); i++) {
|
||||
final Node node = gList.item(i);
|
||||
if (node instanceof Element)
|
||||
create(csd, (Element) node, c);
|
||||
if (node instanceof Element) {
|
||||
final Element element = (Element) node;
|
||||
if (element.getNodeName().equals("style"))
|
||||
c.addClasses(element.getTextContent());
|
||||
else
|
||||
create(csd, element, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ package de.neemann.digital.draw.shapes.custom;
|
||||
import de.neemann.digital.draw.elements.PinException;
|
||||
import de.neemann.digital.draw.graphics.Polygon;
|
||||
import de.neemann.digital.draw.graphics.PolygonParser;
|
||||
import de.neemann.digital.draw.graphics.Vector;
|
||||
import de.neemann.digital.draw.graphics.VectorInterface;
|
||||
import de.neemann.digital.draw.shapes.Drawable;
|
||||
import de.neemann.digital.draw.shapes.custom.svg.SvgException;
|
||||
@ -490,9 +489,10 @@ public class SvgImporterTest extends TestCase {
|
||||
|
||||
new CSDChecker(custom)
|
||||
.checkPolygon("M 0,-10 C 0,-10 15,-10 30,-10 C 70,-10 70,50 35,50 C 20,50 0,50 0,50 L 0,-10 Z")
|
||||
.checkText(10, 10, "A")
|
||||
.checkText(10, 10, "B")
|
||||
.checkText(10, 10, "Y")
|
||||
.checkPolygon("M 0,-10 C 0,-10 15,-10 30,-10 C 70,-10 70,50 35,50 C 20,50 0,50 0,50 L 0,-10 Z")
|
||||
.checkText(4, 6, "A")
|
||||
.checkText(4, 45, "B")
|
||||
.checkText(45, 25, "Y")
|
||||
.checkPin(0, 0, "A", false)
|
||||
.checkPin(0, 40, "B", false)
|
||||
.checkPin(60, 20, "Y", false)
|
||||
@ -596,7 +596,10 @@ public class SvgImporterTest extends TestCase {
|
||||
|
||||
private CSDChecker checkText(int x, int y, String text) {
|
||||
checker.add(d -> {
|
||||
assertTrue(d instanceof CustomShapeDescription.TextHolder);
|
||||
assertTrue("Text expected, found " + d.getClass().getSimpleName(), d instanceof CustomShapeDescription.TextHolder);
|
||||
CustomShapeDescription.TextHolder t = (CustomShapeDescription.TextHolder) d;
|
||||
assertEquals("text x", x, t.getPos().x);
|
||||
assertEquals("text y", y, t.getPos().y);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
@ -27,4 +27,12 @@ public class ContextTest extends TestCase {
|
||||
assertEquals(new Color(0, 0, 0, 127), c.getFilled());
|
||||
}
|
||||
|
||||
|
||||
public void testCSS() {
|
||||
Context c = new Context();
|
||||
c.addClasses(" .z{a:1}\n .y{a:2}");
|
||||
assertEquals("a:1", c.getCssClass("z"));
|
||||
assertEquals("a:2", c.getCssClass("y"));
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user