From f29a2a801dffb55f4bfc59acb45f170554995833 Mon Sep 17 00:00:00 2001 From: SKNG Date: Wed, 23 Oct 2019 21:23:44 +0800 Subject: [PATCH] - fix style text issue. underline, superscript, subscript, strikethrough, and justified sentence. --- .../src/org/oss/pdfreporter/pdf/Page.java | 4 + .../engine/export/JRPdfExporter.java | 17 +- .../engine/export/PdfTextRenderer.java | 3 + .../pdfreporter/font/text/ITextLayout.java | 1 + .../src/org/oss/pdfreporter/pdf/IPage.java | 2 + .../pdfreporter/pdf/ParagraphRenderer.java | 157 +++++++++++++++++- .../oss/pdfreporter/font/text/TextLayout.java | 6 + .../src/org/oss/pdfreporter/pdf/Page.java | 4 + .../oss/pdfreporter/font/text/TextLayout.java | 7 + 9 files changed, 192 insertions(+), 9 deletions(-) diff --git a/pdfreporter-android/src/org/oss/pdfreporter/pdf/Page.java b/pdfreporter-android/src/org/oss/pdfreporter/pdf/Page.java index 61d51258..3b5c2927 100644 --- a/pdfreporter-android/src/org/oss/pdfreporter/pdf/Page.java +++ b/pdfreporter-android/src/org/oss/pdfreporter/pdf/Page.java @@ -253,5 +253,9 @@ public void setCharacterSpacing(float spacing) { delegate.setCharacterSpacing(spacing); } + @Override + public void setTextRise(float rise) { + delegate.setTextRise(rise); + } } diff --git a/pdfreporter-core/src/org/oss/pdfreporter/engine/export/JRPdfExporter.java b/pdfreporter-core/src/org/oss/pdfreporter/engine/export/JRPdfExporter.java index 1b6a486d..b2eee7d3 100644 --- a/pdfreporter-core/src/org/oss/pdfreporter/engine/export/JRPdfExporter.java +++ b/pdfreporter-core/src/org/oss/pdfreporter/engine/export/JRPdfExporter.java @@ -71,10 +71,11 @@ import org.oss.pdfreporter.engine.type.RotationEnum; import org.oss.pdfreporter.engine.util.JRPdfaIccProfileNotFoundException; import org.oss.pdfreporter.engine.util.JRStyledText; -import org.oss.pdfreporter.font.IFontManager; import org.oss.pdfreporter.font.IFont.FontDecoration; import org.oss.pdfreporter.font.IFont.FontStyle; +import org.oss.pdfreporter.font.IFontManager; import org.oss.pdfreporter.font.factory.IFontFactory; +import org.oss.pdfreporter.font.text.ITextLayout; import org.oss.pdfreporter.font.text.TextAttribute; import org.oss.pdfreporter.geometry.IAffineTransformMatrix; import org.oss.pdfreporter.geometry.IColor; @@ -84,13 +85,13 @@ import org.oss.pdfreporter.image.IImage; import org.oss.pdfreporter.pdf.DocumentException; import org.oss.pdfreporter.pdf.IDocument; -import org.oss.pdfreporter.pdf.IEncryption; -import org.oss.pdfreporter.pdf.IPage; -import org.oss.pdfreporter.pdf.ParagraphRenderer; import org.oss.pdfreporter.pdf.IDocument.ConformanceLevel; import org.oss.pdfreporter.pdf.IDocument.PageOrientation; +import org.oss.pdfreporter.pdf.IEncryption; +import org.oss.pdfreporter.pdf.IPage; import org.oss.pdfreporter.pdf.IPage.LineCap; import org.oss.pdfreporter.pdf.IPage.ScaleMode; +import org.oss.pdfreporter.pdf.ParagraphRenderer; import org.oss.pdfreporter.registry.ApiRegistry; import org.oss.pdfreporter.text.HorizontalAlignment; import org.oss.pdfreporter.text.IPositionedLine; @@ -1909,12 +1910,16 @@ private static org.oss.pdfreporter.font.IFont toPdfFont(JRFont font, boolean und return fontManager.getModifiedFont(pdfFont, font.getFontSize() * fontSizeScale, decoration); } - static void drawParagraph(IPage aPdfPage, Paragraph paragraph, float llx, float lly, float urx, float ury, float leading, HorizontalAlignment alignment) { + static void drawParagraph(IPage aPdfPage, Paragraph paragraph, float llx, float lly, float urx, float ury, float leading, HorizontalAlignment alignment) { + drawParagraph(aPdfPage, paragraph, llx, lly, urx, ury, leading, null, alignment); + } + + static void drawParagraph(IPage aPdfPage, Paragraph paragraph, float llx, float lly, float urx, float ury, float leading, ITextLayout textLayout, HorizontalAlignment alignment) { logger.finest("drawParagraph('" + paragraph.getText() + "', " + llx + ", " + lly + ", " + urx + ", " + ury + ", " + leading + ", " + alignment); logger.finest("Pos(x=" + (int)llx + ", y=" + (int)lly + ", width=" + (int)(urx - llx) + ", height=" + (int)(lly - ury)); float verticalAlignmentHack = paragraph.getFirstParagraphText().getFont().getSize(); IRectangle rect = ApiRegistry.getGeometryFactory().newRectangle((int)llx, (int)(lly - verticalAlignmentHack), (int)(urx - llx), (int)(lly - ury)); - ParagraphRenderer renderer = new ParagraphRenderer(paragraph, alignment, rect); + ParagraphRenderer renderer = new ParagraphRenderer(paragraph, alignment, rect, textLayout); renderer.render(aPdfPage, true); } diff --git a/pdfreporter-core/src/org/oss/pdfreporter/engine/export/PdfTextRenderer.java b/pdfreporter-core/src/org/oss/pdfreporter/engine/export/PdfTextRenderer.java index 2892b577..bc871264 100644 --- a/pdfreporter-core/src/org/oss/pdfreporter/engine/export/PdfTextRenderer.java +++ b/pdfreporter-core/src/org/oss/pdfreporter/engine/export/PdfTextRenderer.java @@ -27,6 +27,7 @@ import org.oss.pdfreporter.engine.JRPropertiesUtil; import org.oss.pdfreporter.engine.JasperReportsContext; import org.oss.pdfreporter.engine.util.JRStyledText; +import org.oss.pdfreporter.font.text.ITextLayout; /** @@ -74,6 +75,7 @@ public void draw() TabSegment segment = segments.get(segmentIndex); float advance = segment.layout.getAdvance(); + ITextLayout textLayout = segment.layout; JRPdfExporter.drawParagraph(pdfPage, pdfExporter.getParagraph(segment.as, segment.text, text), @@ -94,6 +96,7 @@ public void draw() -400//+ lineHeight//FIXMETAB - drawPosY, 0,//text.getLineSpacingFactor(),// * text.getFont().getSize(), + textLayout, horizontalAlignment ); diff --git a/pdfreporter-core/src/org/oss/pdfreporter/font/text/ITextLayout.java b/pdfreporter-core/src/org/oss/pdfreporter/font/text/ITextLayout.java index 1b56f3ca..e62e1568 100644 --- a/pdfreporter-core/src/org/oss/pdfreporter/font/text/ITextLayout.java +++ b/pdfreporter-core/src/org/oss/pdfreporter/font/text/ITextLayout.java @@ -71,4 +71,5 @@ public interface ITextLayout { */ Paragraph getParagraph(); + float getAvailableWidth(); } diff --git a/pdfreporter-core/src/org/oss/pdfreporter/pdf/IPage.java b/pdfreporter-core/src/org/oss/pdfreporter/pdf/IPage.java index 1b23e489..82474f37 100644 --- a/pdfreporter-core/src/org/oss/pdfreporter/pdf/IPage.java +++ b/pdfreporter-core/src/org/oss/pdfreporter/pdf/IPage.java @@ -250,4 +250,6 @@ public enum ScaleMode { */ void drawCropped(IImage image, float xoffset, float yoffset, float x, float y, float width, float height) throws DocumentException; + void setTextRise(float rise); + } diff --git a/pdfreporter-core/src/org/oss/pdfreporter/pdf/ParagraphRenderer.java b/pdfreporter-core/src/org/oss/pdfreporter/pdf/ParagraphRenderer.java index a0d74da0..295bc4b6 100644 --- a/pdfreporter-core/src/org/oss/pdfreporter/pdf/ParagraphRenderer.java +++ b/pdfreporter-core/src/org/oss/pdfreporter/pdf/ParagraphRenderer.java @@ -12,13 +12,17 @@ import java.util.ArrayList; import java.util.List; +import java.util.StringTokenizer; +import org.oss.pdfreporter.font.IFont; +import org.oss.pdfreporter.font.IFont.FontDecoration; +import org.oss.pdfreporter.font.text.ITextLayout; import org.oss.pdfreporter.geometry.IRectangle; import org.oss.pdfreporter.text.HorizontalAlignment; +import org.oss.pdfreporter.text.IPositionedLine; import org.oss.pdfreporter.text.Paragraph; import org.oss.pdfreporter.text.ParagraphText; - public class ParagraphRenderer { private static float LEADING_FACTOR = 1.25f; private final Paragraph paragraph; @@ -27,6 +31,7 @@ public class ParagraphRenderer { private final List textLine; private float leading; private float y, widthLeft; + private ITextLayout textLayout; public ParagraphRenderer(Paragraph paragraph, HorizontalAlignment alignment, IRectangle bounding) { @@ -37,6 +42,16 @@ public ParagraphRenderer(Paragraph paragraph, this.textLine = new ArrayList(); } + public ParagraphRenderer(Paragraph paragraph, + HorizontalAlignment alignment, IRectangle bounding, ITextLayout textLayout) { + super(); + this.paragraph = paragraph; + this.alignment = alignment; + this.bounding = bounding; + this.textLine = new ArrayList(); + this.textLayout = textLayout; + } + public void render(IPage page, boolean wordwrap) { page.beginText(); leading = 0; @@ -76,6 +91,8 @@ private void add(ParagraphText text) { private void renderLine(IPage page) { float x; + int spaceToAdd = 0; + float textLineLengthJustify = 0f; switch (alignment) { case ALIGN_LEFT: x = bounding.getX(); @@ -87,16 +104,150 @@ private void renderLine(IPage page) { x = bounding.getX() + widthLeft / 2; break; case ALIGN_JUSTIFY: - // TODO adjust word and character spacing to consume widthLeft + // adjust word and character spacing to consume widthLeft // How is this done best with different fonts and sizes ? + x = bounding.getX(); + if (textLayout != null) { + try { + float spaceSize = textLayout.getAdvance()-textLayout.getVisibleAdvance(); +// System.out.println("spaceSize:"+spaceSize); + float extraWidthToOffSet = textLayout.getAvailableWidth()-bounding.getWidth(); + /** SKNG : calculate the extra space to add to fill up the blank **/ + spaceToAdd = (int) (extraWidthToOffSet/spaceSize); + if (extraWidthToOffSet%spaceSize > spaceSize*0.75) { + // System.out.println("remaining : "+extraWidthToOffSet%spaceWidthConstantForCarlito+", spaceWidthConstantForCarlito*0.75 : "+spaceWidthConstantForCarlito*0.75); + spaceToAdd++; + } + } catch (Exception e) { + // anything happen, no justify. + System.out.println("Error in calculating spaceToAdd!!! "+e.toString()); + spaceToAdd = 0; + } + textLineLengthJustify = textLayout.getAvailableWidth(); + } + break; default: x = bounding.getX(); } for (ParagraphText text : textLine) { + // TODO render background + float textLineLength = text.getWidth(); + if (textLineLengthJustify > 0f) { + textLineLength = textLineLengthJustify; + } page.setFont(text.getFont()); page.setRGBColorFill(text.getForeground()); page.setTextPos(x, y); - page.textOut(text.getText()); + /** SKNG : reset the text rose for supsubscript **/ + page.setTextRise(0f); + StringBuilder sb = new StringBuilder(); + /** SKNG : add some space to fill the gap **/ + if (spaceToAdd > 0) { + // if the last char is a space. + if (text.getText().endsWith(" ")) { + spaceToAdd++; + } +// System.out.println("text : "+text.getText()); + StringTokenizer st = new StringTokenizer(text.getText()); + int tokens = st.countTokens()-1; +// System.out.println("space tokens found:"+tokens); + int multiplier = 1; + int spaceToAddWithMultiplier = spaceToAdd; + if (spaceToAdd > tokens) { + multiplier += (int) spaceToAdd/tokens; + spaceToAddWithMultiplier = spaceToAdd % tokens; + } + for (char c : text.getText().toCharArray()) { + sb.append(c); + if (' ' == c && spaceToAdd > 0) { + if (multiplier>1 && spaceToAddWithMultiplier>0) { +// System.out.println("[adding space] multiplier:"+multiplier); + for (int times=0; times1) { + int remainderMultiplier = multiplier -1; + for (int times=0; times