package com.moxun.s2v; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlDocument; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.moxun.s2v.utils.*; import java.util.*; /** * Created by moxun on 15/12/15. */ public class SVGParser { private XmlFile svg; private String dpi; private String opacity; private int width, height, viewportWidth, viewportHeight; private Map<String, String> styles; public SVGParser(XmlFile svg, String dpi) { styles = new HashMap<String, String>(); this.svg = svg; this.dpi = dpi; parseDimensions(); XmlDocument document = svg.getDocument(); if (document != null) { XmlTag rootTag = document.getRootTag(); if (rootTag != null) { XmlTag[] subTags = rootTag.getSubTags(); for (XmlTag tag : subTags) { getChildAttrs(tag); } } } } private void parseDimensions() { try { if (getValueFromRootTag("width") != null) { width = getNumber(getValueFromRootTag("width")); } else if (getValueFromRootTag("viewBox") != null) { width = getNumber(getValueFromRootTag("viewBox").split(" ")[2]); } if (getValueFromRootTag("height") != null) { height = getNumber(getValueFromRootTag("height")); } else if (getValueFromRootTag("viewBox") != null) { height = getNumber(getValueFromRootTag("viewBox").split(" ")[3]); } if (getValueFromRootTag("viewBox") != null) { viewportWidth = getNumber(getValueFromRootTag("viewBox").split(" ")[2]); viewportHeight = getNumber(getValueFromRootTag("viewBox").split(" ")[3]); } else { viewportWidth = width; viewportHeight = height; } if (getValueFromRootTag("opacity") != null) { opacity = getValueFromRootTag("opacity"); } } catch (Exception e) { //do nothing, maybe null pointer exception, don't care } } private String getValueFromRootTag(String key) { if (svg.getDocument() != null) { XmlTag rootTag = svg.getDocument().getRootTag(); if (rootTag != null) { XmlAttribute attribute = rootTag.getAttribute(key); if (attribute != null) { return rootTag.getAttributeValue(key); } } } return null; } public List<XmlTag> getGroups() { List<XmlTag> groups = new ArrayList<XmlTag>(); if (svg.getDocument() != null) { XmlTag rootTag = svg.getDocument().getRootTag(); if (rootTag != null) { for (XmlTag tag : rootTag.getSubTags()) { if (tag.getName().equals("g")) { groups.add(trim(tag, null)); } } } } return groups; } public List<XmlTag> getGroupChildes(String groupName) { List<XmlTag> childes = new ArrayList<XmlTag>(); if (svg.getDocument() != null) { XmlTag rootTag = svg.getDocument().getRootTag(); if (rootTag != null) { for (XmlTag tag : rootTag.getSubTags()) { if (tag.getName().equals(groupName)) { Collections.addAll(childes, tag.getSubTags()); } } } } return childes; } public List<XmlTag> getSubGroups(XmlTag parent) { List<XmlTag> list = new ArrayList<XmlTag>(); for (XmlTag tag : parent.getSubTags()) { if (tag.getName().equals("g")) { list.add(tag); } } return list; } public List<XmlTag> getSVGChildes() { List<XmlTag> childes = new ArrayList<XmlTag>(); if (svg.getDocument() != null) { XmlTag rootTag = svg.getDocument().getRootTag(); if (rootTag != null) { Collections.addAll(childes, rootTag.getSubTags()); } } return childes; } public XmlTag getStyles() { List<XmlTag> childes = getSVGChildes(); for (XmlTag tag : childes) { if ("defs".equals(tag.getName()) && tag.getSubTags() != null) { for (XmlTag subTag : tag.getSubTags()) { if ("style".equals(subTag.getName())) { return subTag; } } } } return null; } public List<XmlTag> getShapeTags(XmlTag parentTag) { List<XmlTag> tags = new ArrayList<XmlTag>(); XmlTag[] subTags = parentTag.getSubTags(); for (XmlTag tag : subTags) { if (AttrMapper.isShapeName(tag.getName())) { tags.add(tag); } } Logger.debug("shapeTag of " + parentTag.getName() + " :" + tags.toString()); return tags; } public List<XmlTag> getUseTags(XmlTag parentTag) { List<XmlTag> tags = new ArrayList<XmlTag>(); XmlTag[] subTags = parentTag.getSubTags(); for (XmlTag tag : subTags) { if ("use".equalsIgnoreCase(tag.getName())) { tags.add(tag); } } Logger.debug("use tags of " + parentTag.getName() + " :" + tags.toString()); return tags; } public Map<String, XmlTag> getAcceptedDefNodes() { XmlTag rootTag = svg.getRootTag(); Map<String, XmlTag> tags = new HashMap<String, XmlTag>(); XmlTag[] subTags = rootTag.getSubTags(); for (XmlTag tag : subTags) { if ("defs".equalsIgnoreCase(tag.getName())) { XmlTag[] defSubTags = tag.getSubTags(); if (defSubTags != null) { for (XmlTag defNode : defSubTags) { if (AttrMapper.isShapeName(defNode.getName())) { tags.put(defNode.getAttributeValue("id"), defNode); } else { Logger.info("Tag <" + tag.getName() + "> was not supported by android"); } } } } } Logger.debug("use tags of " + rootTag.getName() + " :" + tags.toString()); return tags; } public boolean hasGroupTag() { return getGroups().size() > 0; } public Map<String, String> getChildAttrs(XmlTag tag) { Map<String, String> styles = new HashMap<String, String>(); XmlAttribute attrs[] = tag.getAttributes(); for (XmlAttribute attr : attrs) { if (attr.getName().equals("style")) { String stylesValue = tag.getAttributeValue("style").replaceAll("\\s*", ""); String[] list = stylesValue.split(";"); for (String s : list) { String[] item = s.split(":"); if (item[0].equals("fill")) { item[1] = StdColorUtil.formatColor(item[1]); } styles.put(item[0], item[1]); } } else { if (attr.getName().equals("fill")) { styles.put(attr.getName(), StdColorUtil.formatColor(tag.getAttributeValue(attr.getName()))); } else { styles.put(attr.getName(), tag.getAttributeValue(attr.getName())); } } } Logger.debug(tag.getName() + styles.toString()); return styles; } public XmlTag trim(XmlTag rootTag, List<XmlAttribute> attr) { Logger.debug("Current tag: " + rootTag.getName()); CommonUtil.dumpAttrs("current attr", Arrays.asList(rootTag.getAttributes())); CommonUtil.dumpAttrs("parent attr", attr); if (attr == null) { attr = new ArrayList<XmlAttribute>(); attr.addAll(Arrays.asList(rootTag.getAttributes())); } XmlTag[] subTags = rootTag.getSubTags(); List<XmlAttribute> attrs = new ArrayList<XmlAttribute>(); if (subTags.length == 1 && subTags[0].getName().equals("g")) { Logger.debug("Tag" + rootTag + " has only a subTag and the tag is 'g'"); Collections.addAll(attrs, subTags[0].getAttributes()); attrs.addAll(attr); rootTag = trim(subTags[0], attrs); } else if (subTags.length > 0 && AttrMapper.isShapeName(subTags[0].getName())) { Logger.debug(rootTag.getSubTags()[0].getName()); Logger.debug("Tag" + rootTag + " is correct tag."); for (XmlAttribute attribute : attr) { Logger.debug(attribute.getName() + ":" + attribute.getValue()); } return AttrMergeUtil.mergeAttrs((XmlTag) rootTag.copy(), reduceAttrs(attr)); } return rootTag; } //only focusing attr id & transform & fill private Map<String, String> reduceAttrs(List<XmlAttribute> attributes) { CommonUtil.dumpAttrs("Will reduce", attributes); String reducedTranslate = ""; Map<String, String> result = new HashMap<String, String>(); for (XmlAttribute attr : attributes) { if (attr.getName().equals("transform")) { reducedTranslate = TranslateReduceUtil.reduce(reducedTranslate, attr.getValue()); } else { if (!result.containsKey(attr.getName())) { result.put(attr.getName(), attr.getValue()); } } } result.put("transform", reducedTranslate); Logger.debug("Reduced Attrs:" + result.toString()); return result; } private int getNumber(String src) { String result = src.split("\\D+")[0]; return Integer.valueOf(result); } public String getWidth() { return DensityUtil.px2dp(width, dpi) + "dp"; } public String getHeight() { return DensityUtil.px2dp(height, dpi) + "dp"; } public String getViewportWidth() { return String.valueOf(viewportWidth); } public String getViewportHeight() { return String.valueOf(viewportHeight); } public String getAlpha() { return opacity; } @Override public String toString() { return "SVGParser{" + "svg=" + svg + ", dpi='" + dpi + '\'' + ", width=" + width + ", height=" + height + ", viewportWidth=" + viewportWidth + ", viewportHeight=" + viewportHeight + ", styles=" + styles + '}'; } }