SVG import basic fill and line colors

This commit is contained in:
honfika@gmail.com
2015-12-15 10:26:33 +01:00
parent 09cfc173e7
commit d56c1d931e
2 changed files with 200 additions and 45 deletions

View File

@@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@@ -147,17 +148,10 @@ public class ShapeImporter {
SHAPEWITHSTYLE shapes = new SHAPEWITHSTYLE();
shapes.fillStyles = new FILLSTYLEARRAY();
shapes.lineStyles = new LINESTYLEARRAY();
shapes.fillStyles.fillStyles = new FILLSTYLE[0];
shapes.lineStyles.lineStyles = new LINESTYLE[0];
int shapeNum = st.getShapeNum();
shapes.fillStyles.fillStyles = new FILLSTYLE[1];
shapes.fillStyles.fillStyles[0] = new FILLSTYLE();
shapes.fillStyles.fillStyles[0].color = shapeNum >= 3 ? new RGBA(0, 255, 0, 255) : new RGB(0, 255, 0);
shapes.fillStyles.fillStyles[0].fillStyleType = FILLSTYLE.SOLID;
shapes.lineStyles.lineStyles = new LINESTYLE[1];
shapes.lineStyles.lineStyles[0] = shapeNum <= 3 ? new LINESTYLE() : new LINESTYLE2();
shapes.lineStyles.lineStyles[0].color = shapeNum >= 3 ? new RGBA(255, 0, 0, 255) : new RGB(255, 0, 0);
shapes.lineStyles.lineStyles[0].width = (int) SWF.unitDivisor;
shapes.shapeRecords = new ArrayList<>();
try {
@@ -170,7 +164,7 @@ public class ShapeImporter {
throw new IOException("SVG root element should be 'svg'");
}
processSvgObject(shapes, rootElement);
processSvgObject(shapeNum, shapes, rootElement);
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(ShapeImporter.class.getName()).log(Level.SEVERE, null, ex);
@@ -184,80 +178,125 @@ public class ShapeImporter {
return (Tag) st;
}
private void processSvgObject(SHAPEWITHSTYLE shapes, Element element) {
private void processSvgObject(int shapeNum, SHAPEWITHSTYLE shapes, Element element) {
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node childNode = element.getChildNodes().item(i);
if (childNode instanceof Element) {
Element childElement = (Element) childNode;
String tagName = childElement.getTagName();
if ("g".equals(tagName)) {
processSvgObject(shapes, childElement);
processSvgObject(shapeNum, shapes, childElement);
} else if ("path".equals(tagName)) {
processPath(shapes, childElement);
processPath(shapeNum, shapes, childElement);
}
}
}
}
private void processPath(SHAPEWITHSTYLE shapes, Element childElement) {
private void processPath(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement) {
String data = childElement.getAttribute("d");
if (data == null) {
return;
}
String attr = childElement.getAttribute("fill");
Color fillColor = parseColor(attr);
attr = childElement.getAttribute("fill-opacity");
if (fillColor != null && attr != null && attr.length() > 0) {
double opacity = Double.parseDouble(attr);
fillColor = new Color(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), (int) Math.round(opacity * 255));
}
attr = childElement.getAttribute("stroke");
Color lineColor = parseColor(attr);
attr = childElement.getAttribute("stroke-width");
int lineWidth = (int) Math.round((attr == null || attr.length() == 0 ? 1 : Double.parseDouble(attr)) * SWF.unitDivisor);
char command = 0;
String[] parts = data.split(" ");
double x0 = 0;
double y0 = 0;
for (int i = 0; i < parts.length; i += 2) {
String part = parts[i];
if (part.length() == 0) {
boolean newShape = true;
SvgPathReader pathReader = new SvgPathReader(data);
while (pathReader.hasNext()) {
char newCommand;
if ((newCommand = pathReader.readCommand()) != 0) {
command = newCommand;
continue;
}
char ch = part.charAt(0);
if (ch == 'M' || ch == 'L' || ch == 'Q') {
command = ch;
part = part.substring(1);
boolean isRelative = Character.isLowerCase(command);
double x = pathReader.readDouble();
double y = pathReader.readDouble();
if (isRelative) {
x += x0;
y += y0;
}
double x = Double.parseDouble(part);
part = parts[i + 1];
double y = Double.parseDouble(part);
switch (command) {
switch (Character.toUpperCase(command)) {
case 'M':
StyleChangeRecord scr = new StyleChangeRecord();
scr.moveDeltaX = (int) ((x - x0) * SWF.unitDivisor);
scr.moveDeltaY = (int) ((y - y0) * SWF.unitDivisor);
scr.moveDeltaX = (int) Math.round((x - x0) * SWF.unitDivisor);
scr.moveDeltaY = (int) Math.round((y - y0) * SWF.unitDivisor);
scr.stateMoveTo = true;
scr.stateFillStyle0 = true;
scr.stateLineStyle = true;
scr.fillStyle0 = 1;
scr.lineStyle = 1;
if (newShape) {
newShape = false;
scr.stateNewStyles = true;
scr.fillStyles = new FILLSTYLEARRAY();
scr.stateFillStyle1 = true;
scr.stateLineStyle = true;
if (fillColor != null) {
scr.fillStyles.fillStyles = new FILLSTYLE[1];
scr.fillStyles.fillStyles[0] = new FILLSTYLE();
scr.fillStyles.fillStyles[0].color = shapeNum >= 3 ? new RGBA(fillColor) : new RGB(fillColor);
scr.fillStyles.fillStyles[0].fillStyleType = FILLSTYLE.SOLID;
scr.fillStyle1 = 1;
} else {
scr.fillStyles.fillStyles = new FILLSTYLE[0];
scr.fillStyle1 = 0;
}
scr.lineStyles = new LINESTYLEARRAY();
if (lineColor != null) {
scr.lineStyles.lineStyles = new LINESTYLE[1];
scr.lineStyles.lineStyles[0] = shapeNum <= 3 ? new LINESTYLE() : new LINESTYLE2();
scr.lineStyles.lineStyles[0].color = shapeNum >= 3 ? new RGBA(lineColor) : new RGB(lineColor);
scr.lineStyles.lineStyles[0].width = lineWidth;
scr.lineStyle = 1;
} else {
scr.lineStyles.lineStyles = new LINESTYLE[0];
scr.lineStyle = 0;
}
}
shapes.shapeRecords.add(scr);
break;
case 'L':
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = (int) ((x - x0) * SWF.unitDivisor);
ser.deltaY = (int) ((y - y0) * SWF.unitDivisor);
ser.deltaX = (int) Math.round((x - x0) * SWF.unitDivisor);
ser.deltaY = (int) Math.round((y - y0) * SWF.unitDivisor);
ser.generalLineFlag = true;
shapes.shapeRecords.add(ser);
break;
case 'Q':
CurvedEdgeRecord cer = new CurvedEdgeRecord();
cer.controlDeltaX = (int) ((x - x0) * SWF.unitDivisor);
cer.controlDeltaY = (int) ((y - y0) * SWF.unitDivisor);
cer.controlDeltaX = (int) Math.round((x - x0) * SWF.unitDivisor);
cer.controlDeltaY = (int) Math.round((y - y0) * SWF.unitDivisor);
x0 = x;
y0 = y;
part = parts[i + 2];
x = Double.parseDouble(part);
part = parts[i + 3];
y = Double.parseDouble(part);
i += 2;
cer.anchorDeltaX = (int) ((x - x0) * SWF.unitDivisor);
cer.anchorDeltaY = (int) ((y - y0) * SWF.unitDivisor);
x = pathReader.readDouble();
y = pathReader.readDouble();
if (isRelative) {
x += x0;
y += y0;
}
cer.anchorDeltaX = (int) Math.round((x - x0) * SWF.unitDivisor);
cer.anchorDeltaY = (int) Math.round((y - y0) * SWF.unitDivisor);
shapes.shapeRecords.add(cer);
break;
}
@@ -267,6 +306,20 @@ public class ShapeImporter {
}
}
private Color parseColor(String rgbStr) {
if (rgbStr == null) {
return null;
}
if (rgbStr.startsWith("#")) {
String s = rgbStr.substring(1);
int i = Integer.parseInt(s, 16);
return new Color(i, s.length() > 6);
}
return null;
}
public static int getShapeTagType(String format) {
int res = 0;
switch (format) {

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.importers;
/**
*
* @author JPEXS
*/
public class SvgPathReader {
private String str;
private int pos;
public SvgPathReader(String str) {
this.str = str;
}
public boolean hasNext() {
return pos < str.length();
}
public char peek() {
return str.charAt(pos);
}
public char readChar() {
char ch = str.charAt(pos);
pos++;
return ch;
}
public char readCommand() {
if (!hasNext()) {
return 0;
}
char ch = peek();
char command = 0;
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
command = ch;
pos++;
readSeparators();
}
return command;
}
public double readDouble() {
int startPos = pos;
if (peek() == '-') {
pos++;
}
boolean pointFound = false;
while (hasNext()) {
char ch = str.charAt(pos);
if (ch == '.') {
if (pointFound) {
break;
}
pointFound = true;
} else if (ch >= '0' && ch <= '9') {
} else {
break;
}
pos++;
}
double result = Double.parseDouble(str.substring(startPos, pos));
readSeparators();
return result;
}
private void readSeparators() {
while (hasNext()) {
char ch = peek();
if (ch != ' ' && ch != ',' && ch != '\r' && ch != '\n') {
return;
}
readChar();
}
}
}