From 23404f85b6607f68efe8132f6c38ab5719a8ec8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 22 Dec 2022 20:55:16 +0100 Subject: [PATCH] Added #583 FlashPaper SWF to PDF with selectable text (commandline) --- CHANGELOG.md | 7 +- .../console/CommandLineArgumentParser.java | 86 ++++++++++++++++--- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7f4a5029..a86ea860a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - [#1910] Copy/paste transform matrix to/from the clipboard - [#1912] Persist selected item in the tree upon quick search (Ctrl+F) - [#1901] Editor mode and autosave feature for header, raw editor, transform +- [#583] FlashPaper SWF to PDF with selectable text (commandline) ### Fixed - [#1904] NullPointerException when renaming invalid identifiers in AS1/2 files caused by missing charset @@ -2782,10 +2783,12 @@ All notable changes to this project will be documented in this file. [#1460]: https://www.free-decompiler.com/flash/issues/1460 [#1909]: https://www.free-decompiler.com/flash/issues/1909 [#1910]: https://www.free-decompiler.com/flash/issues/1910 +[#1912]: https://www.free-decompiler.com/flash/issues/1912 +[#1901]: https://www.free-decompiler.com/flash/issues/1901 +[#583]: https://www.free-decompiler.com/flash/issues/583 [#1904]: https://www.free-decompiler.com/flash/issues/1904 [#595]: https://www.free-decompiler.com/flash/issues/595 [#1908]: https://www.free-decompiler.com/flash/issues/1908 -[#1912]: https://www.free-decompiler.com/flash/issues/1912 [#1898]: https://www.free-decompiler.com/flash/issues/1898 [#1511]: https://www.free-decompiler.com/flash/issues/1511 [#1765]: https://www.free-decompiler.com/flash/issues/1765 @@ -2796,7 +2799,6 @@ All notable changes to this project will be documented in this file. [#1893]: https://www.free-decompiler.com/flash/issues/1893 [#1181]: https://www.free-decompiler.com/flash/issues/1181 [#1900]: https://www.free-decompiler.com/flash/issues/1900 -[#1901]: https://www.free-decompiler.com/flash/issues/1901 [#1897]: https://www.free-decompiler.com/flash/issues/1897 [#1006]: https://www.free-decompiler.com/flash/issues/1006 [#1828]: https://www.free-decompiler.com/flash/issues/1828 @@ -2979,7 +2981,6 @@ All notable changes to this project will be documented in this file. [#1573]: https://www.free-decompiler.com/flash/issues/1573 [#1598]: https://www.free-decompiler.com/flash/issues/1598 [#428]: https://www.free-decompiler.com/flash/issues/428 -[#583]: https://www.free-decompiler.com/flash/issues/583 [#1373]: https://www.free-decompiler.com/flash/issues/1373 [#1595]: https://www.free-decompiler.com/flash/issues/1595 [#1611]: https://www.free-decompiler.com/flash/issues/1611 diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 3f9530d72..704823773 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -216,10 +216,20 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import com.jpexs.decompiler.flash.Bundle; +import com.jpexs.decompiler.flash.exporters.DualPdfGraphics2D; +import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.gui.translator.Translator; import com.jpexs.decompiler.flash.importers.SymbolClassImporter; import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel; +import com.jpexs.decompiler.flash.tags.base.RenderContext; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.helpers.SerializableImage; +import gnu.jpdf.PDFGraphics; +import java.awt.AlphaComposite; import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; import java.util.Comparator; /** @@ -2968,14 +2978,19 @@ public class CommandLineArgumentParser { for (Tag t : swf.getTags()) { if (t instanceof DefineSpriteTag) { DefineSpriteTag ds = (DefineSpriteTag) t; - if ("page1".equals(ds.getExportName())) { - totalPages = 1; - } else if (totalPages > 0) { - totalPages++; + String exportName = ds.getExportName(); + if (exportName != null && exportName.matches("^page[0-9]+$")) { + int pageNum = Integer.parseInt(exportName.substring(4)); + if (pageNum > totalPages) { + totalPages = pageNum; + } } } } + PageFormat pf = new PageFormat(); + pf.setOrientation(PageFormat.PORTRAIT); + Paper p = new Paper(); int page = 0; for (Tag t : swf.getTags()) { @@ -2992,18 +3007,61 @@ public class CommandLineArgumentParser { continue; } System.out.print("Page " + page + "/" + totalPages + "..."); - RECT displayRect = new RECT(ds.getTimeline().displayRect); - BufferedImage img = SWF.frameToImageGet(ds.getTimeline(), 0, 0, null, 0, displayRect, new Matrix(), null, Color.white, zoom).getBufferedImage(); - PageFormat pf = new PageFormat(); - pf.setOrientation(PageFormat.PORTRAIT); - Paper p = new Paper(); - p.setSize(img.getWidth(), img.getHeight()); + Timeline tim = ds.getTimeline(); + RECT rect = tim.displayRect; + + double w = (rect.getWidth() * zoom / SWF.unitDivisor); + double h = (rect.getHeight() * zoom / SWF.unitDivisor); + p.setSize(w, h); pf.setPaper(p); - if (job != null) { - Graphics g = job.getGraphics(pf); - g.drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null); - g.dispose(); + Matrix m = new Matrix(); + m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); + m.scale(zoom); + Matrix transformation = m; + Map existingFonts = new HashMap<>(); + + int fframe = 0; + final Graphics2D g = (Graphics2D) job.getGraphics(pf); + + SerializableImage image = new SerializableImage((int) w + 1, (int) h + 1, SerializableImage.TYPE_INT_ARGB_PRE) { + + private Graphics2D compositeGraphics; + + @Override + public Graphics getGraphics() { + if (compositeGraphics != null) { + return compositeGraphics; + } + final Graphics2D parentGraphics = (Graphics2D) super.getGraphics(); + compositeGraphics = new DualPdfGraphics2D(parentGraphics, (PDFGraphics) g, existingFonts); + return compositeGraphics; + } + + @Override + public void fillTransparent() { + + } + + }; + int imgWidth = (int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1; + int imgHeight = (int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1; + + RenderContext renderContext = new RenderContext(); + renderContext.cursorPosition = new Point(-1, -1); + renderContext.mouseButton = 0; + renderContext.stateUnderCursor = new ArrayList<>(); + + try { + tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0); + } catch (Exception ex) { + ex.printStackTrace(); } + g.dispose(); + + if (Thread.currentThread().isInterrupted()) { + return; + } + System.out.println("OK"); }