我正在使用Itext 7及其html2Pdf库。 有没有一种方法可以实现例如cmyk颜色。
.wootWorkingCMYK-color{
color: cmyk( 1 , 0.69 , 0.08 , 0.54);
}
我知道itext核心部分相当不错,正在寻找使用html2Pdf的一面。我知道CssApplierFactory,但是这似乎已经远远超过了。
答案 0 :(得分:4)
当然,有一种方法可以处理自定义CSS属性,例如cmyk
颜色,但是不幸的是,代码会非常庞大,并且您需要针对不同的情况编写一些代码。我将展示如何为字体应用自定义颜色,例如对于背景,边框或其他情况,您将需要以类似的方式编写单独的代码。其背后的原因是,尽管iText布局结构是在考虑HTML / CSS的前提下设计的,但并非100%相似,并且您必须编写一些区别。
话虽如此,如果您可以从源代码中派生,构建和使用自定义版本,这就是我建议的方法。尽管它有必须重新获得更新的缺点,但该解决方案将更简单,更通用。为此,请在pdfHTML模块中搜索CssUtils.parseRgbaColor
的用法,您会发现它已在BackgroundApplierUtil
,BorderStyleApplierUtil
,FontStyleApplierUtil
,OutlineApplierUtil
中使用。在那里,您会找到类似
if (!CssConstants.TRANSPARENT.equals(cssColorPropValue)) {
float[] rgbaColor = CssUtils.parseRgbaColor(cssColorPropValue);
Color color = new DeviceRgb(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
float opacity = rgbaColor[3];
transparentColor = new TransparentColor(color, opacity);
} else {
transparentColor = new TransparentColor(ColorConstants.BLACK, 0f);
}
我相信您也可以调整处理cmyk
,因为您已经非常了解核心部分。
现在,没有自定义pdfHTML版本的解决方案实际上是从实现ICssApplierFactory
开始或将默认实现DefaultCssApplierFactory
子类化。我们主要对定制SpanTagCssApplier
和BlockCssApplier
的实现感兴趣,但是您可以咨询DefaultTagCssApplierMapping
以获得应用程序及其使用案例的完整列表,以便您确定您要在代码中处理的其中的一个。
我将向您展示如何在我提到的两个主要的applier类中增加对字体颜色的自定义颜色空间的支持,然后您就可以在那里工作了。
private static class CustomCssApplierFactory implements ICssApplierFactory {
private static final ICssApplierFactory DEFAULT_FACTORY = new DefaultCssApplierFactory();
@Override
public ICssApplier getCssApplier(IElementNode tag) {
ICssApplier defaultApplier = DEFAULT_FACTORY.getCssApplier(tag);
if (defaultApplier instanceof SpanTagCssApplier) {
return new CustomSpanTagCssApplier();
} else if (defaultApplier instanceof BlockCssApplier) {
return new CustomBlockCssApplier();
} else {
return defaultApplier;
}
}
}
private static class CustomSpanTagCssApplier extends SpanTagCssApplier {
@Override
protected void applyChildElementStyles(IPropertyContainer element, Map<String, String> css, ProcessorContext context, IStylesContainer stylesContainer) {
super.applyChildElementStyles(element, css, context, stylesContainer);
String color = css.get("color2");
if (color != null) {
color = color.trim();
if (color.startsWith("cmyk")) {
element.setProperty(Property.FONT_COLOR, new TransparentColor(parseCmykColor(color)));
}
}
}
}
private static class CustomBlockCssApplier extends BlockCssApplier {
@Override
public void apply(ProcessorContext context, IStylesContainer stylesContainer, ITagWorker tagWorker) {
super.apply(context, stylesContainer, tagWorker);
IPropertyContainer container = tagWorker.getElementResult();
if (container != null) {
String color = stylesContainer.getStyles().get("color2");
if (color != null) {
color = color.trim();
if (color.startsWith("cmyk")) {
container.setProperty(Property.FONT_COLOR, new TransparentColor(parseCmykColor(color)));
}
}
}
}
}
// You might want a safer implementation with better handling of corner cases
private static DeviceCmyk parseCmykColor(String color) {
final String delim = "cmyk(), \t\r\n\f";
StringTokenizer tok = new StringTokenizer(color, delim);
float[] res = new float[]{0, 0, 0, 0};
for (int k = 0; k < 3; ++k) {
if (tok.hasMoreTokens()) {
res[k] = Float.parseFloat(tok.nextToken());
}
}
return new DeviceCmyk(res[0], res[1], res[2], res[3]);
}
拥有该自定义代码后,您应该相应配置ConverterProperties
并将其传递给HtmlConverter:
ConverterProperties properties = new ConverterProperties();
properties.setCssApplierFactory(new CustomCssApplierFactory());
HtmlConverter.convertToPdf(..., properties);
您可能已经注意到我使用color2
而不是color
,这是有原因的。 pdfHTML具有CSS属性验证的机制(就像浏览器一样),可以在计算元素的有效属性时丢弃无效的CSS属性。不幸的是,目前没有自定义此验证逻辑的机制,当然,目前它会将cmyk
颜色视为无效声明。因此,如果您确实要拥有自定义color
属性,则必须预处理HTML并将color: cmyk...
之类的声明替换为color2: cmyk..
或任何您想使用的属性名。 / p>
正如我在答案开头提到的那样,我的建议是构建自己的自定义版本:)