蜡染不能呈现正确的字体颜色?

时间:2017-03-14 13:59:31

标签: svg fonts png batik

我使用Apache Batik Java库将.svg矢量图像文件转换为.png文件。问题是生成的.png图像的字体颜色都变黑了。以下是我用来进行转换的代码:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;

public class SVGHelperDesktop extends SVGHelper {
    @Override
    public byte[] convertSvgToPng(String svgXml, float png_width)
            throws SVGConversionException {
        byte[] resultPngBytes = null;

        try {
            ByteArrayInputStream inputSvgBytes = new 
                    ByteArrayInputStream(svgXml.getBytes());
            TranscoderInput input_svg_image = new 
                    TranscoderInput(inputSvgBytes);

            ByteArrayOutputStream outputPngBytes = new ByteArrayOutputStream();
            TranscoderOutput output_png_image = new TranscoderOutput(outputPngBytes);

            PNGTranscoder svgToPngConverter = new PNGTranscoder(); 
            svgToPngConverter.addTranscodingHint(PNGTranscoder.KEY_WIDTH, png_width);
            svgToPngConverter.transcode(input_svg_image, output_png_image);

            resultPngBytes = outputPngBytes.toByteArray();

            outputPngBytes.flush();
            outputPngBytes.close(); 
        } catch (Exception e) {
            throw new SVGConversionException("Error converting SVG to PNG", e);
        }

        return resultPngBytes;
    }
}

使用同一.svg文件上的AndroidSVG library生成具有正确颜色的正确.png图片。

另一个说明;使用默认字体inkscape(我用来创建矢量图形的程序)解决了这个问题。使用任何其他字体使Batik将其颜色更改为黑色。

Here's a link to my SVG file.

2 个答案:

答案 0 :(得分:1)

确定。解决了问题所在。

当您使用自定义字体时,Inkscape会在-inkscape-font-specification字母的style属性中添加自定义CSS属性<path>。以下是您文件的摘录:

style="... font-family:Aharoni;-inkscape-font-specification:'Aharoni, Bold';font-variant-ligatures:normal; ..."

然而,似乎Batik有一个错误,它不喜欢以短划线/连字符(“ - ”)开头的CSS属性。 This is a known bug it seems

如果您需要使用一组固定的SVG,那么最简单的修复就是手动编辑SVG文件,例如,搜索并将“-inkscape-font-specification”替换为“inkscape-”字体规格”。

如果你想要一个更通用的解决方法,那么上面的Batik bug链接有一个建议的解决方法来覆盖Batik的样式属性解析器。

答案 1 :(得分:0)

接受的答案非常有帮助地指向Batik bug 1112,指示未正确解析“ -inkscape-font-specification”。该错误报告提供了一种变通方法,该方法可以通过重新实现Batik中的CSS解析器的一部分来实现。要对此进行扩展并在此处使其可用,这是我的变通方法的简化版本。

首先需要一个CSS解析器类来覆盖Batik中的类:

import org.apache.batik.css.parser.ExtendedParser;
import org.apache.batik.css.parser.Parser;
import org.w3c.css.sac.CSSException;
import java.io.IOException;

public class InkscapeCssParser extends Parser {
    public void parseStyleDeclaration(String source)
            throws CSSException, IOException {
        source = source.replaceAll(";-inkscape", ";inkscape");
        super.parseStyleDeclaration(source);
    }
}

请注意,source参数是特定SVG元素的CSS样式,而不是完整的SVG源。具有parseStyleDeclaration属性的每个元素都会调用style

Batik错误中提供的解决方法重新实现了一个不错的parseStyleDeclaration块,但我只是简单地执行了一个天真的字符串替换,以消除“;”之后令人讨厌的“-”。因为这是问题的核心。

要使用此功能,请在加载文档之前设置CSS解析器类名称:

JSVGCanvas mSvgCanvas;
XMLResourceDescriptor.setCSSParserClassName(InkscapeCssParser.class.getName());
mSvgCanvas.setURI(svgUrl.toString());