我正在使用 Itext 7 和他们的 html2Pdf 库。有没有办法实现例如 cmyk 颜色。
.wootWorkingCMYK-color{
color: cmyk( 1 , 0.69 , 0.08 , 0.54);
}
Run Code Online (Sandbox Code Playgroud)
我非常了解 itext 核心部分,正在寻找使用 html2Pdf 方面的方法。我知道 CssApplierFactory 但这似乎太远了。
当然,有一种方法可以处理自定义 CSS 属性(例如cmyk颜色),但不幸的是,代码会非常庞大,并且您需要针对不同情况编写相当多的代码。我将展示如何为字体应用自定义颜色,但例如对于背景、边框或其他情况,您将需要以类似的方式编写单独的代码。其背后的原因是,iText 布局结构虽然在设计时考虑了 HTML/CSS,但并不是 100% 相似,并且存在一些差异,您必须在代码中解决这些差异。
话虽如此,如果您可以从源代码中分叉、构建和使用您的自定义版本,那么我建议您采用这种方式。尽管它有一些缺点,例如必须重新设置基准才能获取更新,但该解决方案会更简单、更通用。为此,请CssUtils.parseRgbaColor在 pdfHTML 模块中搜索 的用法,您会发现它用于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);
}
Run Code Online (Sandbox Code Playgroud)
我相信你也可以调整流程cmyk,因为你知道你非常了解核心部分。
现在,没有自定义 pdfHTML 版本的解决方案实际上是从实现ICssApplierFactory或子类化默认实现开始DefaultCssApplierFactory。SpanTagCssApplier我们最感兴趣的是自定义和的实现BlockCssApplier,但您可以咨询DefaultTagCssApplierMapping以获取应用程序和它们所使用的案例的完整列表,以便您可以决定要在代码中处理其中的哪些。
我将向您展示如何在我提到的两个主要应用程序类中添加对字体颜色的自定义颜色空间的支持,您可以从那里开始工作。
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]);
}
Run Code Online (Sandbox Code Playgroud)
有了该自定义代码,您应该进行相应的配置ConverterProperties并将其传递给 HtmlConverter:
ConverterProperties properties = new ConverterProperties();
properties.setCssApplierFactory(new CustomCssApplierFactory());
HtmlConverter.convertToPdf(..., properties);
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到我使用了color2而不是color,这是有原因的。pdfHTML 有一个 CSS 属性验证机制(浏览器也这样做),在计算元素的有效属性时丢弃无效的 CSS 属性。不幸的是,目前没有自定义此验证逻辑的机制,当然它cmyk目前将颜色视为无效声明。因此,如果您确实想要拥有自定义color属性,则必须预处理 HTML 并替换声明,例如color: cmyk...或color2: cmyk..您可能想要使用的任何属性名称。
正如我在答案开头提到的,我的建议是构建您自己的自定义版本:)
| 归档时间: |
|
| 查看次数: |
1358 次 |
| 最近记录: |