带有许多文本元素的事件下划线 itext7
event underline with many Text element itext7
我需要为自定义下划线扩展 TextRenderer,但在一个元素文本中我有一个字母。
我有大文本并执行此操作:
String s = "d < like to filter > RENDER_TEXT events as they are <written> to an output file. I have a <PDF that has some text in it> that I want filtered out. I've found that I can walk the document once and determine the characteristics of the render events that I want to filter. Now I'd like to copy the pages of the source document and skip over some RENDER_TEXT events so that the text does not appear in the destination document. I have an IEventFilter that will accept the correct events. I just need to know how to put this filter on the document writer.";
String[] words = s.split("");
Paragraph paragraph = new Paragraph();
Text text = null;
boolean isUnderStart = false;
boolean isUnderEnd = false;
int i = 1;
for (String word : words) {
if (word.equals("<")) {
isUnderStart = true;
}
if (word.equals(">")) {
isUnderEnd = true;
}
text = new Text(word);
text.setNextRenderer(new Word25TextRenderer(text, isUnderStart,isUnderEnd));
isUnderStart = false;
isUnderEnd = false;
paragraph.add(text);
i++;
}
doc.add(paragraph);
doc.close();
"<" и ">" 我做测试(在实际程序中,我使用 Jsoup)
在这个符号的帮助下,我找到了第一个符号和结束符号的坐标轴。这是绘制 canvas 元素(直线、曲线到)所必需的。我还添加了布尔值以绘制两次,第一个字母和第二个字母的坐标。
一行的所有单词,如果我想为两行画下划线,它不会中断。这部分:<PDF that has some text in it>
static class Word25TextRenderer extends TextRenderer {
private boolean isUnderStart;
private boolean isUnderEnd;
public Word25TextRenderer(Text textElement, boolean isUnderStart, boolean isUnderEnd) {
super(textElement);
this.isUnderStart = isUnderStart;
this.isUnderEnd = isUnderEnd;
}
@Override
public IRenderer getNextRenderer() {
return new Word25TextRenderer((Text) modelElement, isUnderStart, isUnderEnd);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle textRect = getOccupiedAreaBBox();
int pageNumber = getOccupiedArea().getPageNumber();
PdfCanvas canvas = drawContext.getCanvas();
if (isUnderStart) {
canvas
.saveState()
.setStrokeColor(DeviceRgb.RED)
.moveTo(textRect.getRight(), textRect.getBottom());
}
if (isUnderEnd) {
canvas.curveTo(textRect.getRight(), textRect.getBottom() + textRect.getHeight() / 2,
textRect.getRight(), textRect.getBottom(),
textRect.getRight(), textRect.getBottom())
.stroke()
.restoreState();
}
}
}
也许你知道其他方法?
这是最后发生的事情
p.s:我在文本中添加了一个元素,因为之后我会单独更改元素(字体、字体大小等)这是必要的!
与其在 Text
元素/渲染器级别添加下划线,不如在 Paragraph
级别添加下划线更方便,其中所有关于行拆分的信息都是已知的,因为您必须在同一 Text
中位于不同行的部分下划线。
我们将创建一个 CustomText
class 来存储有关我们是否仍要为那段文本加下划线的信息(尽管我们可以在常规 [=13] 上使用 setProperty
=]元素):
static class CustomText extends Text {
private boolean isUnderStart;
private boolean isUnderEnd;
public CustomText(String text, boolean isUnderStart, boolean isUnderEnd) {
super(text);
this.isUnderStart = isUnderStart;
this.isUnderEnd = isUnderEnd;
}
public boolean isUnderStart() {
return isUnderStart;
}
public boolean isUnderEnd() {
return isUnderEnd;
}
}
最重要的部分是我们的习惯ParagraphRenderer
- 我们翻过几行,记住最后一个“左括号”,或者文本块开始定义要加下划线的文本的开始,然后一旦我们面对“右括号”,或定义文本结尾的文本块,我们为整个区域进行实际绘图。此外,如果在完成线路检查时我们仍然有“开括号”,我们会通过在线路的剩余部分下划线来处理拆分。这里是代码:
static class CustomParagraphRenderer extends ParagraphRenderer {
public CustomParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new CustomParagraphRenderer((Paragraph) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle lastRectStart = null;
for (int i = 0; i < lines.size(); i++) {
LineRenderer lineRenderer = lines.get(i);
boolean anyEventsThisLine = false;
for (IRenderer renderer : lineRenderer.getChildRenderers()) {
if (renderer.getModelElement() instanceof CustomText &&
(((CustomText) renderer.getModelElement()).isUnderEnd()
|| ((CustomText) renderer.getModelElement()).isUnderStart())) {
anyEventsThisLine = true;
if ((((CustomText) renderer.getModelElement()).isUnderEnd())) {
Rectangle endRect = renderer.getOccupiedArea().getBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lastRectStart.getRight(), lastRectStart.getBottom())
.curveTo(endRect.getRight(), endRect.getBottom() + endRect.getHeight() / 2,
endRect.getRight(), endRect.getBottom(),
endRect.getRight(), endRect.getBottom())
.stroke().restoreState();
lastRectStart = null;
} else {
lastRectStart = renderer.getOccupiedArea().getBBox();
}
}
}
if (lastRectStart != null && !anyEventsThisLine) {
// Underline the whole line
PdfCanvas canvas = drawContext.getCanvas();
Rectangle lineRect = lineRenderer.getOccupiedArea().getBBox();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lineRect.getLeft(), lineRect.getBottom())
.curveTo(lineRect.getRight(), lineRect.getBottom() + lineRect.getHeight() / 2,
lineRect.getRight(), lineRect.getBottom(),
lineRect.getRight(), lineRect.getBottom())
.stroke().restoreState();
}
if (lastRectStart != null) {
// Draw till end of line
Rectangle endRect = lineRenderer.getChildRenderers().get(lineRenderer.getChildRenderers().size() - 1)
.getOccupiedArea().getBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lastRectStart.getRight(), lastRectStart.getBottom())
.curveTo(endRect.getRight(), endRect.getBottom() + endRect.getHeight() / 2,
endRect.getRight(), endRect.getBottom(),
endRect.getRight(), endRect.getBottom())
.stroke().restoreState();
if (i + 1 < lines.size()) {
lastRectStart = lines.get(i + 1).getChildRenderers().get(0).getOccupiedArea().getBBox();
} else {
lastRectStart = null;
}
}
}
}
}
主要入口点代码只有细微的变化:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter("C:/path/to.pdf"));
Document doc = new Document(pdfDocument);
String s = "d < like to filter > RENDER_TEXT events as they are <written> to an output file. I have a <PDF that has some text in it> that I want filtered out. I've found that I can walk the document once and determine the characteristics of the render events that I want to filter. Now I'd like to copy the pages of the source document and skip over some RENDER_TEXT events so that the text does not appear in the destination document. I have an IEventFilter that will accept the correct events. I just need to know how to put this filter on the document writer.";
String[] words = s.split("");
Paragraph paragraph = new Paragraph();
paragraph.setNextRenderer(new CustomParagraphRenderer(paragraph));
Text text = null;
boolean isUnderStart = false;
boolean isUnderEnd = false;
int i = 1;
for (String word : words) {
if (word.equals("<")) {
isUnderStart = true;
}
if (word.equals(">")) {
isUnderEnd = true;
}
text = new CustomText(word, isUnderStart, isUnderEnd);
isUnderStart = false;
isUnderEnd = false;
paragraph.add(text);
i++;
}
doc.add(paragraph);
doc.close();
我需要为自定义下划线扩展 TextRenderer,但在一个元素文本中我有一个字母。 我有大文本并执行此操作:
String s = "d < like to filter > RENDER_TEXT events as they are <written> to an output file. I have a <PDF that has some text in it> that I want filtered out. I've found that I can walk the document once and determine the characteristics of the render events that I want to filter. Now I'd like to copy the pages of the source document and skip over some RENDER_TEXT events so that the text does not appear in the destination document. I have an IEventFilter that will accept the correct events. I just need to know how to put this filter on the document writer.";
String[] words = s.split("");
Paragraph paragraph = new Paragraph();
Text text = null;
boolean isUnderStart = false;
boolean isUnderEnd = false;
int i = 1;
for (String word : words) {
if (word.equals("<")) {
isUnderStart = true;
}
if (word.equals(">")) {
isUnderEnd = true;
}
text = new Text(word);
text.setNextRenderer(new Word25TextRenderer(text, isUnderStart,isUnderEnd));
isUnderStart = false;
isUnderEnd = false;
paragraph.add(text);
i++;
}
doc.add(paragraph);
doc.close();
"<" и ">" 我做测试(在实际程序中,我使用 Jsoup) 在这个符号的帮助下,我找到了第一个符号和结束符号的坐标轴。这是绘制 canvas 元素(直线、曲线到)所必需的。我还添加了布尔值以绘制两次,第一个字母和第二个字母的坐标。
一行的所有单词,如果我想为两行画下划线,它不会中断。这部分:<PDF that has some text in it>
static class Word25TextRenderer extends TextRenderer {
private boolean isUnderStart;
private boolean isUnderEnd;
public Word25TextRenderer(Text textElement, boolean isUnderStart, boolean isUnderEnd) {
super(textElement);
this.isUnderStart = isUnderStart;
this.isUnderEnd = isUnderEnd;
}
@Override
public IRenderer getNextRenderer() {
return new Word25TextRenderer((Text) modelElement, isUnderStart, isUnderEnd);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle textRect = getOccupiedAreaBBox();
int pageNumber = getOccupiedArea().getPageNumber();
PdfCanvas canvas = drawContext.getCanvas();
if (isUnderStart) {
canvas
.saveState()
.setStrokeColor(DeviceRgb.RED)
.moveTo(textRect.getRight(), textRect.getBottom());
}
if (isUnderEnd) {
canvas.curveTo(textRect.getRight(), textRect.getBottom() + textRect.getHeight() / 2,
textRect.getRight(), textRect.getBottom(),
textRect.getRight(), textRect.getBottom())
.stroke()
.restoreState();
}
}
}
也许你知道其他方法? 这是最后发生的事情
p.s:我在文本中添加了一个元素,因为之后我会单独更改元素(字体、字体大小等)这是必要的!
与其在 Text
元素/渲染器级别添加下划线,不如在 Paragraph
级别添加下划线更方便,其中所有关于行拆分的信息都是已知的,因为您必须在同一 Text
中位于不同行的部分下划线。
我们将创建一个 CustomText
class 来存储有关我们是否仍要为那段文本加下划线的信息(尽管我们可以在常规 [=13] 上使用 setProperty
=]元素):
static class CustomText extends Text {
private boolean isUnderStart;
private boolean isUnderEnd;
public CustomText(String text, boolean isUnderStart, boolean isUnderEnd) {
super(text);
this.isUnderStart = isUnderStart;
this.isUnderEnd = isUnderEnd;
}
public boolean isUnderStart() {
return isUnderStart;
}
public boolean isUnderEnd() {
return isUnderEnd;
}
}
最重要的部分是我们的习惯ParagraphRenderer
- 我们翻过几行,记住最后一个“左括号”,或者文本块开始定义要加下划线的文本的开始,然后一旦我们面对“右括号”,或定义文本结尾的文本块,我们为整个区域进行实际绘图。此外,如果在完成线路检查时我们仍然有“开括号”,我们会通过在线路的剩余部分下划线来处理拆分。这里是代码:
static class CustomParagraphRenderer extends ParagraphRenderer {
public CustomParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
return new CustomParagraphRenderer((Paragraph) modelElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle lastRectStart = null;
for (int i = 0; i < lines.size(); i++) {
LineRenderer lineRenderer = lines.get(i);
boolean anyEventsThisLine = false;
for (IRenderer renderer : lineRenderer.getChildRenderers()) {
if (renderer.getModelElement() instanceof CustomText &&
(((CustomText) renderer.getModelElement()).isUnderEnd()
|| ((CustomText) renderer.getModelElement()).isUnderStart())) {
anyEventsThisLine = true;
if ((((CustomText) renderer.getModelElement()).isUnderEnd())) {
Rectangle endRect = renderer.getOccupiedArea().getBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lastRectStart.getRight(), lastRectStart.getBottom())
.curveTo(endRect.getRight(), endRect.getBottom() + endRect.getHeight() / 2,
endRect.getRight(), endRect.getBottom(),
endRect.getRight(), endRect.getBottom())
.stroke().restoreState();
lastRectStart = null;
} else {
lastRectStart = renderer.getOccupiedArea().getBBox();
}
}
}
if (lastRectStart != null && !anyEventsThisLine) {
// Underline the whole line
PdfCanvas canvas = drawContext.getCanvas();
Rectangle lineRect = lineRenderer.getOccupiedArea().getBBox();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lineRect.getLeft(), lineRect.getBottom())
.curveTo(lineRect.getRight(), lineRect.getBottom() + lineRect.getHeight() / 2,
lineRect.getRight(), lineRect.getBottom(),
lineRect.getRight(), lineRect.getBottom())
.stroke().restoreState();
}
if (lastRectStart != null) {
// Draw till end of line
Rectangle endRect = lineRenderer.getChildRenderers().get(lineRenderer.getChildRenderers().size() - 1)
.getOccupiedArea().getBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState().setStrokeColor(ColorConstants.RED)
.moveTo(lastRectStart.getRight(), lastRectStart.getBottom())
.curveTo(endRect.getRight(), endRect.getBottom() + endRect.getHeight() / 2,
endRect.getRight(), endRect.getBottom(),
endRect.getRight(), endRect.getBottom())
.stroke().restoreState();
if (i + 1 < lines.size()) {
lastRectStart = lines.get(i + 1).getChildRenderers().get(0).getOccupiedArea().getBBox();
} else {
lastRectStart = null;
}
}
}
}
}
主要入口点代码只有细微的变化:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter("C:/path/to.pdf"));
Document doc = new Document(pdfDocument);
String s = "d < like to filter > RENDER_TEXT events as they are <written> to an output file. I have a <PDF that has some text in it> that I want filtered out. I've found that I can walk the document once and determine the characteristics of the render events that I want to filter. Now I'd like to copy the pages of the source document and skip over some RENDER_TEXT events so that the text does not appear in the destination document. I have an IEventFilter that will accept the correct events. I just need to know how to put this filter on the document writer.";
String[] words = s.split("");
Paragraph paragraph = new Paragraph();
paragraph.setNextRenderer(new CustomParagraphRenderer(paragraph));
Text text = null;
boolean isUnderStart = false;
boolean isUnderEnd = false;
int i = 1;
for (String word : words) {
if (word.equals("<")) {
isUnderStart = true;
}
if (word.equals(">")) {
isUnderEnd = true;
}
text = new CustomText(word, isUnderStart, isUnderEnd);
isUnderStart = false;
isUnderEnd = false;
paragraph.add(text);
i++;
}
doc.add(paragraph);
doc.close();