【问题标题】:Batik not rendering the correct font color?蜡染没有呈现正确的字体颜色?
【发布时间】:2017-08-04 21:49:21
【问题描述】:

我正在使用 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.

【问题讨论】:

  • 发布 SVG,或者至少是其中的一部分,这样我们就可以看到其中可能导致问题的内容。
  • @PaulLeBeau 给你:pastebin.com/XmLwKdWd

标签: svg fonts png batik


【解决方案1】:

Inkscape 将自定义 CSS 属性 -inkscape-font-specification 添加到与自定义字体文本关联的 style 属性。摘录如下:

style="...;-inkscape-font-specification:'Aharoni, Bold';..."

已知的 Batik bug 阻止呈现以连字符 (-) 开头的 CSS 属性。

一个简单的修复方法是编辑文件,然后删除“-inkscape-font-specification”属性。

或者,您可以使用 Batik 的 API 创建一个新的 CSS 样式解析器,以删除有问题的 CSS 样式类。例如:

  /**
   * <a href="https://issues.apache.org/jira/browse/BATIK-1112">Bug fix</a>
   */
  public static final class InkscapeCssParser extends Parser {
    public void parseStyleDeclaration( final String source )
      throws CSSException, IOException {
      super.parseStyleDeclaration(
        source.replaceAll( "-inkscape-font-specification:[^;\"]*;", "" )
      );
    }
  }

  static {
    XMLResourceDescriptor.setCSSParserClassName(
      InkscapeCssParser.class.getName()
    );
  }

【讨论】:

    【解决方案2】:

    接受的答案非常有帮助地指向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 源代码。对于每个具有style 属性的元素,都会调用parseStyleDeclaration

    虽然 Batik 错误中提供的解决方法重新实现了一大块 parseStyleDeclaration,但我只是简单地进行了一个简单的字符串替换来摆脱“;”之后的有问题的“-”因为这是问题的核心。

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

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

    【讨论】:

      猜你喜欢
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 2022-01-05
      相关资源
      最近更新 更多