Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*

See the NOTICE file distributed with this work for additional
information regarding copyright ownership.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

package io.sf.carte.echosvg.svggen;

import java.io.IOException;
import java.io.Writer;

import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;

/**
* Compact SVG serialization.
*/
public class CompactXmlSerializer implements XmlSerializer {

@Override
public void serializeXML(Node node, Writer writer, boolean escaped)
throws IOException, SVGGraphics2DRuntimeException {
XmlWriter.IndentWriter iwriter = new XmlWriter.IndentWriter(writer) {

@Override
public void printIndent() throws IOException {
}

};

XmlWriter xmlWri = new XmlWriter(iwriter, escaped) {

@Override
protected void writeXml(DocumentType docType) throws IOException {
IndentWriter out = getWriter();
out.write("<!DOCTYPE ");
out.write(docType.getName());

String publicId = docType.getPublicId();
if (publicId != null) {
out.write(" PUBLIC '");
out.write(publicId);
out.write('\'');
}

String systemId = docType.getSystemId();
if (systemId != null) {
out.write(" '");
out.write(systemId);
out.write('\'');
}

out.write('>');
}

};

xmlWri.writeXml(node);
}

@Override
public void writeDocumentType(Writer out, String name, String publicId, String systemId)
throws IOException {
out.write("<!DOCTYPE ");
out.write(name);
if (publicId != null) {
out.write(" PUBLIC '");
out.write(publicId);
out.write('\'');
}
if (systemId != null) {
out.write(" '");
out.write(systemId);
out.write('\'');
}
out.write('>');
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public interface ErrorConstants {
String ERR_ACI = "AttributedCharacterIterator not supported yet";

// XmlWriter
String ERR_PROXY = "proxy should not be null";
String ERR_WRITER = "Writer should not be null";
String INVALID_NODE = "Unable to write node of type ";

// DOMGroup/TreeManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public class SVGGeneratorContext implements ErrorConstants {
*/
private Integer compressionLevel = null;

private XmlSerializer xmlSerializer = null;

/**
* Class to describe the GraphicContext defaults to be used. Note that this
* class does *not* contain a default for the initial transform, as this
Expand Down Expand Up @@ -473,4 +475,23 @@ public final String doubleString(double value) {
}
}

/**
* Get the object to use in SVG serialization.
*
* @return the SVG serializer, or {@code null} if the default should be used.
*/
public XmlSerializer getXmlSerializer() {
return xmlSerializer;
}

/**
* Set the object to use in SVG serialization.
*
* @param xmlSerializer the SVG serializer, or {@code null} if the default
* should be used.
*/
public void setXmlSerializer(XmlSerializer xmlSerializer) {
this.xmlSerializer = xmlSerializer;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -448,15 +448,31 @@ public void stream(Element svgRoot, Writer writer, boolean useCss, boolean escap
//
svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI, XMLNS_PREFIX, SVG_NAMESPACE_URI);

svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI, XMLNS_PREFIX + ":" + XLINK_PREFIX, XLINK_NAMESPACE_URI);
svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI, XMLNS_PREFIX + ":" + XLINK_PREFIX,
XLINK_NAMESPACE_URI);

DocumentFragment svgDocument = svgRoot.getOwnerDocument().createDocumentFragment();
svgDocument.appendChild(svgRoot);

if (useCss)
if (useCss) {
SVGCSSStyler.style(svgDocument);
}

XmlSerializer xmlWri = getGeneratorContext().getXmlSerializer();

if (xmlWri == null) {
xmlWri = new XmlSerializer() {
};
}

// <?xml version="1.0" encoding="..."?>
// Should end with a newline so the serializer starts at column 1
writeDocumentHeader(writer);

// Write DOCTYPE declaration here.
xmlWri.writeDocumentType(writer, SVG_SVG_TAG, SVG_PUBLIC_ID, SVG_SYSTEM_ID);
xmlWri.serializeXML(svgDocument, writer, escaped);

XmlWriter.writeXml(svgDocument, writer, escaped);
writer.flush();
} catch (SVGGraphics2DIOException e) {
// this catch prevents from catching an SVGGraphics2DIOException
Expand All @@ -466,6 +482,12 @@ public void stream(Element svgRoot, Writer writer, boolean useCss, boolean escap
generatorCtx.getErrorHandler().handleError(e);
} catch (IOException io) {
generatorCtx.getErrorHandler().handleError(new SVGGraphics2DIOException(io));
} catch (SVGGraphics2DRuntimeException e) {
// this catch prevents from catching an SVGGraphics2DRuntimeException
// and wrapping it again in another SVGGraphics2DRuntimeException
generatorCtx.getErrorHandler().handleError(e);
} catch (RuntimeException e) {
generatorCtx.getErrorHandler().handleError(new SVGGraphics2DRuntimeException(e));
} finally {
// Restore the svgRoot to its original tree position
if (rootParent != null) {
Expand All @@ -478,6 +500,17 @@ public void stream(Element svgRoot, Writer writer, boolean useCss, boolean escap
}
}

private void writeDocumentHeader(Writer out) throws IOException {
String encoding = null;

if (out instanceof OutputStreamWriter) {
OutputStreamWriter osw = (OutputStreamWriter) out;
encoding = XmlWriter.java2std(osw.getEncoding());
}

XmlWriter.writeXmlHeader(out, encoding);
}

/**
* Invoking this method will return a set of definition element that contain all
* the definitions referenced by the attributes generated by the various
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*

See the NOTICE file distributed with this work for additional
information regarding copyright ownership.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

package io.sf.carte.echosvg.svggen;

import java.io.IOException;
import java.io.Writer;

import org.w3c.dom.Node;

/**
* XML serializer.
*
* <p>
* Implementations should be able to correctly serialize SVG.
* </p>
*/
public interface XmlSerializer {

/**
* Serialize the given XML node to the given writer.
* <p>
* Callers of this method should catch {@code RuntimeException} in addition to
* the {@link SVGGraphics2DRuntimeException}.
* </p>
*
* @param node the node to serialize.
* @param writer the writer to write the serialization output.
* @param escaped defines if the characters in Text nodes and attribute values
* should be escaped.
* @throws IOException if an I/O error occurs.
* @throws SVGGraphics2DRuntimeException or other runtime exception if the node
* hierarchy is inconsistent or contains
* unknown nodes.
*/
default void serializeXML(Node node, Writer writer, boolean escaped)
throws IOException, SVGGraphics2DRuntimeException {
XmlWriter xmlWri = new XmlWriter(writer, escaped);
xmlWri.writeXml(node);
}

/**
* Serialize a document type with the given identifiers.
*
* @param writer the writer to write the serialization output.
* @param name the document type name.
* @param publicId the public identifier, or {@code null} if none.
* @param systemId the system identifier, or {@code null} if none.
* @throws IOException if an I/O error occurs.
*/
default void writeDocumentType(Writer writer, String name, String publicId, String systemId)
throws IOException {
XmlWriter.writeDocumentType(writer, name, publicId, systemId);
}

}
Loading