@ font-face with Flying Saucer

时间:2012-04-25 20:45:00

标签: css itext font-face flying-saucer

我正在跳跃,有人可以帮助我...似乎我想要做的事情应该相当简单,但我已经在这一天做了一天以上的事情并且没有想法。我在StackOverflow和Internet上发现了大量信息,但没有任何帮助我解决这个问题。

我正在尝试使用itext-2.0.8和core-renderer-R8来创建带有嵌入字体的PDF。我试图从有效的XHTML生成PDF并使用@ font-face样式标记嵌入字体。我已经确认@ font-face标签通过在浏览器中打开文件来包含字体。我总是小心翼翼地保持TTF领域相对于XHTML / CSS doc。

为了尝试通过这个方法,我创建了一个小的“Hello World”类型程序来尝试嵌入字体。我采取了两种不同的方法,但都无法产生预期的结果。我在http://christopherluft.com/FlyingSaucer.zip

放了一个这个小Eclipse程序的副本

该程序在两个实例中都生成PDF,但是没有按预期嵌入PDF。使用带有setDocument的文件的第一个方法不会产生错误,也不会产生任何字体。第二种方法生成PDF但在调试输出中显示java.net.MalformedURLException。

我尝试了各种路径和URL的多种排列;然而,没有一个不能产生预期的结果。我怀疑是我对ITextRenderer.setDocument没有理解;但是,我很难找到特定于我的用例的适当文档。

我正在尝试的第一种方法是:

public static void main(String[] args) throws IOException, DocumentException {

    System.getProperties().setProperty("xr.util-logging.loggingEnabled",
            "true");
    XRLog.setLoggingEnabled(true);

    String inputFile = "sample.xhtml";
    String url = new File(inputFile).toURI().toURL().toString();
    String outputFile = "firstdoc.pdf";

    OutputStream os = new FileOutputStream(outputFile);

    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocument(url);
    renderer.layout();
    renderer.createPDF(os);

    os.close();
}

我使用的第二种方法(更接近我们在应用程序中使用它的实际方式)是:

public static void main(String[] args)  throws IOException, DocumentException {

    System.getProperties().setProperty("xr.util-logging.loggingEnabled", "true");
    XRLog.setLoggingEnabled(true);

    String inputFile = "sample.xhtml";
    String url = new File(inputFile).toURI().toURL().toString();

    DocumentBuilder documentBuilder;
    org.w3c.dom.Document xhtmlContent;

    try 
    {
        documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        documentBuilder.setEntityResolver(new XhtmlEntityResolver(new SuppressingEntityResolver()));
        xhtmlContent = documentBuilder.parse(url);

        System.out.println(url);

        String outputFile = "firstdoc.pdf";
        OutputStream os = new FileOutputStream(outputFile);
        ITextRenderer renderer = new ITextRenderer();

        renderer.setDocument(xhtmlContent,".");
        renderer.layout();
        renderer.createPDF(os);

        System.out.println("Finishing up....");
        os.close();
    } 
    catch (SAXException e) 
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    catch (ParserConfigurationException e) 
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
}

XHTML中的@ font-face包含如下所示:

@font-face {

    font-family: 'MisoRegular';

    src: url("miso-regular-webfont.ttf");

    -fs-pdf-font-embed: embed;

    -fs-pdf-font-encoding: Identity-H;
}

现在我觉得这是一个非常常见的用例,我想我只是没有执行一个简单的步骤才能让它工作......问题是我已经在这一段时间了我想我无法通过树木看到森林。任何人都可以提供给我的任何帮助将不胜感激。谢谢你的时间。

3 个答案:

答案 0 :(得分:4)

我遇到了飞碟的问题,似乎字体没有正确嵌入,结果是我试图嵌入的字体已损坏或至少不完整。缺少有关字体系列和描述的属性。当我尝试使用OS X上的FontBook中的验证文件选项验证我的字体时,我立即收到警告说:

  • 'name'表可用性
  • 'name'表格结构

然而,FlyingSaucer无声地失败,只是继续将Times-Roman和Times-Bold作为默认字体嵌入。当我尝试使用通过FontBook验证的字体时,我发现字体已正确嵌入。

我花了好几个小时试图增加从FlyingSaucer登录的详细程度以获取更多信息,并且在我完成整个渲染过程并且恰好注意到FontFamily设置为“”之前没有发现这种情况。加载字体后调试器,并且它不包含我希望在其下注册的名称。

底线: 如果您遇到FlyingSaucer和字体问题,并且正在撞墙,请确保您的字体有效。

答案 1 :(得分:3)

我遇到了像tekgrunt这样的问题,但最后我得到了一个嵌入了自定义字体(Computer Modern)的PDF。我的经历:

  • 字体的OTF格式不起作用(在iText函数中崩溃)
  • TTF格式DID工作后,我做了以下更改:在CSS中,使用与字体中编码的字体名称相同的字体系列名称。在
    org.xhtmlrenderer.pdf.ITextFontResolver.addFontFaceFont()
    中设置断点,找出变量“fontFamily”得到的值。如果这与CSS字体系列不一样,我猜它不会起作用。

当然,库应该将这些问题报告给用户。

答案 2 :(得分:1)

我遇到了类似的问题,字体没有应用到最终的pdf中,m4t关于调试的建议确实帮助我确定了问题。所以谢谢你!

就我而言,实际上有两个问题:

  1. 作为src规则的一部分指定的@font-face属性具有两个值,即url和格式。看起来像
@font-face {
   src: url("../../static/fonts/OpenSans-Regular.ttf") format("ttf");
}

由于第二个值format,CSSParser中断,导致src属性被完全忽略。结果,在进行进一步处理时,渲染器不知道从何处挑选字体。一旦从值中删除了format部分,问题就解决了。

  1. 一旦URL被CSSParser成功解析,就无法正确解析,因为css中指定的URL是一个相对的URL,并且在调用{{1}时没有明确指定baseUrl(可选的第二个参数)。 }上。通过使用类加载器在代码中显式加载uri静态资源,然后将其设置为基本URL,解决了该问题。更改之后,字体文件的路径已成功解析,并也应用于我的pdf。

这里要注意的关键是,提供给 setDocumentAsString必须是URI(文件:/ folder / structure / static /), 并且必须以斜杠('/')结尾。否则,文件和URL 无法正确解决。

希望这可以帮助面临类似问题的人。