From 1516c7d0addcd67e1e32f5232ee843e97422f2b0 Mon Sep 17 00:00:00 2001 From: Honfika Date: Fri, 20 Dec 2013 12:37:28 +0100 Subject: [PATCH] font panel separated --- .../jpexs/decompiler/flash/gui/FontPanel.java | 312 +++++++++ .../jpexs/decompiler/flash/gui/MainFrame.java | 645 +++++++++++------- 2 files changed, 693 insertions(+), 264 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/FontPanel.java diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/FontPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/FontPanel.java new file mode 100644 index 000000000..bd74e9806 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/FontPanel.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2010-2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +/** + * + * @author JPEXS + */ +public class FontPanel extends JPanel implements ActionListener { + + static final String ACTION_FONT_EMBED = "FONTEMBED"; + static final String ACTION_FONT_ADD_CHARS = "FONTADDCHARS"; + + private MainFrame mainFrame; + private SWF swf; + + public Map sourceFontsMap = new HashMap<>(); + + private JLabel fontNameLabel; + private JLabel fontIsBoldLabel; + private JLabel fontIsItalicLabel; + private JLabel fontAscentLabel; + private JLabel fontDescentLabel; + private JLabel fontLeadingLabel; + private JTextArea fontCharactersTextArea; + private JTextField fontAddCharactersField; + private ComponentListener fontChangeList; + private JComboBox fontSelection; + + public FontPanel(MainFrame mainFrame, SWF swf) { + this.mainFrame = mainFrame; + this.swf = swf; + createFontPanel(); + } + + private JPanel createFontPanel() { + //TODO: This layout SUCKS! If you know something better, please fix it! + final JPanel fontPanel = new JPanel(); + final JPanel fontParams2 = new JPanel(); + fontParams2.setLayout(null); + final Component[][] ctable = new Component[][]{ + {new JLabel(translate("font.name")), fontNameLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.isbold")), fontIsBoldLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.isitalic")), fontIsItalicLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.ascent")), fontAscentLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.descent")), fontDescentLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.leading")), fontLeadingLabel = new JLabel(translate("value.unknown"))}, + {new JLabel(translate("font.characters")), fontCharactersTextArea = new JTextArea("")} + }; + fontCharactersTextArea.setLineWrap(true); + fontCharactersTextArea.setWrapStyleWord(true); + fontCharactersTextArea.setOpaque(false); + fontCharactersTextArea.setEditable(false); + fontCharactersTextArea.setFont(new JLabel().getFont()); + + final int borderLeft = 10; + + final int[] maxws = new int[ctable[0].length]; + for (int x = 0; x < ctable[0].length; x++) { + int maxw = 0; + for (int y = 0; y < ctable.length; y++) { + Dimension d = ctable[y][x].getPreferredSize(); + if (d.width > maxw) { + maxw = d.width; + } + } + maxws[x] = maxw; + } + + for (int i = 0; i < ctable.length; i++) { + fontParams2.add(ctable[i][0]); + fontParams2.add(ctable[i][1]); + } + + //fontParams2.setPreferredSize(new Dimension(600, ctable.length * 25)); + fontChangeList = new ComponentListener() { + @Override + public void componentResized(ComponentEvent e) { + int h = 0; + Insets is = fontPanel.getInsets(); + Insets is2 = fontParams2.getInsets(); + for (int i = 0; i < ctable.length; i++) { + Dimension d = ctable[i][0].getPreferredSize(); + Dimension d2 = ctable[i][1].getPreferredSize(); + ctable[i][0].setBounds(borderLeft, h, maxws[0], d2.height); + + int w2 = fontPanel.getWidth() - 3 * borderLeft - maxws[0] - is.left - is.right - 10; + ctable[i][1].setBounds(borderLeft + maxws[0] + borderLeft, h, w2, d2.height); + h += Math.max(d.height, d2.height); + } + + fontParams2.setPreferredSize(new Dimension(fontPanel.getWidth() - 20, h)); + fontPanel.revalidate(); + } + + @Override + public void componentMoved(ComponentEvent e) { + componentResized(null); + } + + @Override + public void componentShown(ComponentEvent e) { + componentResized(null); + } + + @Override + public void componentHidden(ComponentEvent e) { + componentResized(null); + } + }; + final JPanel fontParams1 = new JPanel(); + fontPanel.addComponentListener(fontChangeList); + + fontChangeList.componentResized(null); + fontParams1.setLayout(new BoxLayout(fontParams1, BoxLayout.Y_AXIS)); + fontParams1.add(fontParams2); + + JPanel fontAddCharsPanel = new JPanel(new FlowLayout()); + fontAddCharsPanel.add(new JLabel(translate("font.characters.add"))); + fontAddCharactersField = new MyTextField(); + fontAddCharactersField.setPreferredSize(new Dimension(150, fontAddCharactersField.getPreferredSize().height)); + fontAddCharsPanel.add(fontAddCharactersField); + JButton fontAddCharsButton = new JButton(translate("button.ok")); + fontAddCharsButton.setActionCommand(ACTION_FONT_ADD_CHARS); + fontAddCharsButton.addActionListener(this); + fontAddCharsPanel.add(fontAddCharsButton); + + JButton fontEmbedButton = new JButton(translate("button.font.embed")); + fontEmbedButton.setActionCommand(ACTION_FONT_EMBED); + fontEmbedButton.addActionListener(this); + //fontAddCharsPanel.add(fontEmbedButton); + + fontParams1.add(fontAddCharsPanel); + JPanel fontSelectionPanel = new JPanel(new FlowLayout()); + fontSelectionPanel.add(new JLabel(translate("font.source"))); + fontSelection = new JComboBox<>(FontTag.fontNames.toArray(new String[FontTag.fontNames.size()])); + fontSelection.setSelectedIndex(0); + fontSelection.setSelectedItem("Times New Roman"); + fontSelection.setSelectedItem("Arial"); + fontSelection.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (mainFrame.oldValue instanceof FontTag) { + FontTag f = (FontTag) mainFrame.oldValue; + sourceFontsMap.put(f.getFontId(), (String) fontSelection.getSelectedItem()); + } + } + }); + fontSelectionPanel.add(fontSelection); + + JPanel fontCharPanel = new JPanel(); + fontCharPanel.setLayout(new ListLayout()); + fontCharPanel.add(fontAddCharsPanel); + fontCharPanel.add(fontSelectionPanel); + fontParams1.add(fontCharPanel); + fontParams1.add(fontEmbedButton); + fontPanel.setLayout(new BorderLayout()); + fontParams1.add(Box.createVerticalGlue()); + fontPanel.add(new JScrollPane(fontParams1), BorderLayout.CENTER); + + return fontPanel; + } + + public String getSelectedFont() { + return fontSelection.getSelectedItem().toString(); + } + + private String translate(String key) { + return mainFrame.translate(key); + } + + private void fontAddChars(FontTag ft, Set selChars, String selFont) { + FontTag f = (FontTag) mainFrame.oldValue; + String oldchars = f.getCharacters(swf.tags); + for (int ic : selChars) { + char c = (char) ic; + if (oldchars.indexOf((int) c) == -1) { + Font font = new Font(selFont, f.getFontStyle(), 1024); + if (!font.canDisplay(c)) { + View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE); + return; + } + } + } + + String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")}; + boolean yestoall = false; + boolean notoall = false; + for (int ic : selChars) { + char c = (char) ic; + if (oldchars.indexOf((int) c) > -1) { + int opt; //yes + if (!(yestoall || notoall)) { + opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); + if (opt == 2) { + yestoall = true; + } + if (opt == 3) { + notoall = true; + } + } + if (yestoall) { + opt = 0; //yes + } else if (notoall) { + opt = 1; //no + } else { + opt = 1; + } + + if (opt == 1) { + continue; + } + } + f.addCharacter(swf.tags, c, fontSelection.getSelectedItem().toString()); + oldchars += c; + } + } + + public void showFontTag(FontTag ft) { + fontNameLabel.setText(ft.getFontName(swf.tags)); + fontIsBoldLabel.setText(ft.isBold() ? translate("yes") : translate("no")); + fontIsItalicLabel.setText(ft.isItalic() ? translate("yes") : translate("no")); + fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent()); + fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent()); + fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading()); + String chars = ft.getCharacters(swf.tags); + fontCharactersTextArea.setText(chars); + if (sourceFontsMap.containsKey(ft.getFontId())) { + fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId())); + } else { + fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName(swf.tags))); + } + fontChangeList.componentResized(null); + } + + @Override + public void actionPerformed(ActionEvent e) { + switch (e.getActionCommand()) { + case ACTION_FONT_EMBED: + if (mainFrame.oldValue instanceof FontTag) { + FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ((FontTag) mainFrame.oldValue).getFontStyle()); + if (fed.display()) { + Set selChars = fed.getSelectedChars(); + if (!selChars.isEmpty()) { + String selFont = fed.getSelectedFont(); + fontSelection.setSelectedItem(selFont); + fontAddChars((FontTag) mainFrame.oldValue, selChars, selFont); + fontAddCharactersField.setText(""); + mainFrame.reload(true); + } + } + } + break; + case ACTION_FONT_ADD_CHARS: + String newchars = fontAddCharactersField.getText(); + if (mainFrame.oldValue instanceof FontTag) { + Set selChars = new TreeSet<>(); + for (int c = 0; c < newchars.length(); c++) { + selChars.add(newchars.codePointAt(c)); + } + fontAddChars((FontTag) mainFrame.oldValue, selChars, fontSelection.getSelectedItem().toString()); + fontAddCharactersField.setText(""); + mainFrame.reload(true); + } + break; + } + } + +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 7e4923407..d03ed52bf 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -100,10 +100,8 @@ import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.graph.ExportMode; -import com.jpexs.helpers.Cache; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; -import com.jpexs.process.ProcessTools; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; @@ -132,9 +130,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; @@ -150,20 +145,15 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Stack; -import java.util.Timer; -import java.util.TimerTask; -import java.util.TreeSet; import java.util.concurrent.CancellationException; import java.util.logging.Level; import java.util.logging.Logger; @@ -171,16 +161,11 @@ import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JCheckBoxMenuItem; import javax.swing.JColorChooser; -import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -189,7 +174,6 @@ import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; -import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.SwingConstants; @@ -210,23 +194,7 @@ import javax.swing.tree.TreeSelectionModel; import org.pushingpixels.flamingo.api.common.AbstractCommandButton; import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState; import org.pushingpixels.flamingo.api.common.CommandButtonLayoutManager; -import org.pushingpixels.flamingo.api.common.JCommandButton; -import org.pushingpixels.flamingo.api.common.JCommandButton.CommandButtonKind; -import org.pushingpixels.flamingo.api.common.JCommandButtonPanel; import org.pushingpixels.flamingo.api.common.icon.ResizableIcon; -import org.pushingpixels.flamingo.api.ribbon.JRibbon; -import org.pushingpixels.flamingo.api.ribbon.JRibbonBand; -import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent; -import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenu; -import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryFooter; -import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryPrimary; -import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority; -import org.pushingpixels.flamingo.api.ribbon.RibbonTask; -import org.pushingpixels.flamingo.api.ribbon.resize.BaseRibbonBandResizePolicy; -import org.pushingpixels.flamingo.api.ribbon.resize.CoreRibbonResizePolicies; -import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy; -import org.pushingpixels.flamingo.api.ribbon.resize.RibbonBandResizePolicy; -import org.pushingpixels.flamingo.internal.ui.ribbon.AbstractBandControlPanel; import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton; /** @@ -240,6 +208,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T public ActionPanel actionPanel; private MainFrameStatusPanel statusPanel; private MainFrameRibbon mainRibbon; + private FontPanel fontPanel; public JProgressBar progressBar = new JProgressBar(0, 100); private DeobfuscationDialog deobfuscationDialog; public JTree tagTree; @@ -276,28 +245,15 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T private JSplitPane previewSplitPane; private JButton imageReplaceButton; private JPanel imageButtonsPanel; - private JLabel fontNameLabel; - private JLabel fontIsBoldLabel; - private JLabel fontIsItalicLabel; - private JLabel fontAscentLabel; - private JLabel fontDescentLabel; - private JLabel fontLeadingLabel; - private JTextArea fontCharactersTextArea; - private JTextField fontAddCharactersField; - private ComponentListener fontChangeList; - private JComboBox fontSelection; private PlayerControls flashControls; private ImagePanel internelViewerPanel; private JPanel viewerCards; public static final String FLASH_VIEWER_CARD = "FLASHVIEWER"; public static final String INTERNAL_VIEWER_CARD = "INTERNALVIEWER"; - private Map sourceFontsMap = new HashMap<>(); private AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); private CancellableWorker setSourceWorker; - static final String ACTION_FONT_EMBED = "FONTEMBED"; static final String ACTION_SELECT_COLOR = "SELECTCOLOR"; - static final String ACTION_FONT_ADD_CHARS = "FONTADDCHARS"; static final String ACTION_REPLACE_IMAGE = "REPLACEIMAGE"; static final String ACTION_REPLACE_BINARY = "REPLACEBINARY"; static final String ACTION_REMOVE_ITEM = "REMOVEITEM"; @@ -791,132 +747,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T displayWithPreview.add(textTopPanel, CARDTEXTPANEL); - - - //TODO: This layout SUCKS! If you know something better, please fix it! - final JPanel fontPanel = new JPanel(); - final JPanel fontParams2 = new JPanel(); - fontParams2.setLayout(null); - final Component[][] ctable = new Component[][]{ - {new JLabel(translate("font.name")), fontNameLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.isbold")), fontIsBoldLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.isitalic")), fontIsItalicLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.ascent")), fontAscentLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.descent")), fontDescentLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.leading")), fontLeadingLabel = new JLabel(translate("value.unknown"))}, - {new JLabel(translate("font.characters")), fontCharactersTextArea = new JTextArea("")} - }; - fontCharactersTextArea.setLineWrap(true); - fontCharactersTextArea.setWrapStyleWord(true); - fontCharactersTextArea.setOpaque(false); - fontCharactersTextArea.setEditable(false); - fontCharactersTextArea.setFont(new JLabel().getFont()); - - final int borderLeft = 10; - - final int[] maxws = new int[ctable[0].length]; - for (int x = 0; x < ctable[0].length; x++) { - int maxw = 0; - for (int y = 0; y < ctable.length; y++) { - Dimension d = ctable[y][x].getPreferredSize(); - if (d.width > maxw) { - maxw = d.width; - } - } - maxws[x] = maxw; - } - - for (int i = 0; i < ctable.length; i++) { - fontParams2.add(ctable[i][0]); - fontParams2.add(ctable[i][1]); - } - - //fontParams2.setPreferredSize(new Dimension(600, ctable.length * 25)); - fontChangeList = new ComponentListener() { - @Override - public void componentResized(ComponentEvent e) { - int h = 0; - Insets is = fontPanel.getInsets(); - Insets is2 = fontParams2.getInsets(); - for (int i = 0; i < ctable.length; i++) { - Dimension d = ctable[i][0].getPreferredSize(); - Dimension d2 = ctable[i][1].getPreferredSize(); - ctable[i][0].setBounds(borderLeft, h, maxws[0], d2.height); - - int w2 = fontPanel.getWidth() - 3 * borderLeft - maxws[0] - is.left - is.right - 10; - ctable[i][1].setBounds(borderLeft + maxws[0] + borderLeft, h, w2, d2.height); - h += Math.max(d.height, d2.height); - } - - fontParams2.setPreferredSize(new Dimension(fontPanel.getWidth() - 20, h)); - fontPanel.revalidate(); - } - - @Override - public void componentMoved(ComponentEvent e) { - componentResized(null); - } - - @Override - public void componentShown(ComponentEvent e) { - componentResized(null); - } - - @Override - public void componentHidden(ComponentEvent e) { - componentResized(null); - } - }; - final JPanel fontParams1 = new JPanel(); - fontPanel.addComponentListener(fontChangeList); - - fontChangeList.componentResized(null); - fontParams1.setLayout(new BoxLayout(fontParams1, BoxLayout.Y_AXIS)); - fontParams1.add(fontParams2); - - JPanel fontAddCharsPanel = new JPanel(new FlowLayout()); - fontAddCharsPanel.add(new JLabel(translate("font.characters.add"))); - fontAddCharactersField = new MyTextField(); - fontAddCharactersField.setPreferredSize(new Dimension(150, fontAddCharactersField.getPreferredSize().height)); - fontAddCharsPanel.add(fontAddCharactersField); - JButton fontAddCharsButton = new JButton(translate("button.ok")); - fontAddCharsButton.setActionCommand(ACTION_FONT_ADD_CHARS); - fontAddCharsButton.addActionListener(this); - fontAddCharsPanel.add(fontAddCharsButton); - - JButton fontEmbedButton = new JButton(translate("button.font.embed")); - fontEmbedButton.setActionCommand(ACTION_FONT_EMBED); - fontEmbedButton.addActionListener(this); - //fontAddCharsPanel.add(fontEmbedButton); - - fontParams1.add(fontAddCharsPanel); - JPanel fontSelectionPanel = new JPanel(new FlowLayout()); - fontSelectionPanel.add(new JLabel(translate("font.source"))); - fontSelection = new JComboBox<>(FontTag.fontNames.toArray(new String[FontTag.fontNames.size()])); - fontSelection.setSelectedIndex(0); - fontSelection.setSelectedItem("Times New Roman"); - fontSelection.setSelectedItem("Arial"); - fontSelection.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (oldValue instanceof FontTag) { - FontTag f = (FontTag) oldValue; - sourceFontsMap.put(f.getFontId(), (String) fontSelection.getSelectedItem()); - } - } - }); - fontSelectionPanel.add(fontSelection); - - JPanel fontCharPanel = new JPanel(); - fontCharPanel.setLayout(new ListLayout()); - fontCharPanel.add(fontAddCharsPanel); - fontCharPanel.add(fontSelectionPanel); - fontParams1.add(fontCharPanel); - fontParams1.add(fontEmbedButton); - fontPanel.setLayout(new BorderLayout()); - fontParams1.add(Box.createVerticalGlue()); - fontPanel.add(new JScrollPane(fontParams1), BorderLayout.CENTER); - + fontPanel = new FontPanel(this, swf); displayWithPreview.add(fontPanel, CARDFONTPANEL); @@ -1184,8 +1015,8 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T mbutton.setDisplayState(new CommandButtonDisplayState( "My Ribbon Application Menu Button", mbutton.getSize().width) { @Override - public org.pushingpixels.flamingo.api.common.CommandButtonLayoutManager createLayoutManager( - org.pushingpixels.flamingo.api.common.AbstractCommandButton commandButton) { + public CommandButtonLayoutManager createLayoutManager( + AbstractCommandButton commandButton) { return new CommandButtonLayoutManager() { @Override public int getPreferredIconSize() { @@ -1844,53 +1675,6 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T } } - private void fontAddChars(FontTag ft, Set selChars, String selFont) { - FontTag f = (FontTag) oldValue; - String oldchars = f.getCharacters(swf.tags); - for (int ic : selChars) { - char c = (char) ic; - if (oldchars.indexOf((int) c) == -1) { - Font font = new Font(selFont, f.getFontStyle(), 1024); - if (!font.canDisplay(c)) { - View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE); - return; - } - } - } - - String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")}; - boolean yestoall = false; - boolean notoall = false; - for (int ic : selChars) { - char c = (char) ic; - if (oldchars.indexOf((int) c) > -1) { - int opt; //yes - if (!(yestoall || notoall)) { - opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); - if (opt == 2) { - yestoall = true; - } - if (opt == 3) { - notoall = true; - } - } - if (yestoall) { - opt = 0; //yes - } else if (notoall) { - opt = 1; //no - } else { - opt = 1; - } - - if (opt == 1) { - continue; - } - } - f.addCharacter(swf.tags, c, fontSelection.getSelectedItem().toString()); - oldchars += c; - } - } - public void disableDecompilationChanged() { clearCache(); if (abcPanel != null) { @@ -2305,21 +2089,6 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { - case ACTION_FONT_EMBED: - if (oldValue instanceof FontTag) { - FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ((FontTag) oldValue).getFontStyle()); - if (fed.display()) { - Set selChars = fed.getSelectedChars(); - if (!selChars.isEmpty()) { - String selFont = fed.getSelectedFont(); - fontSelection.setSelectedItem(selFont); - fontAddChars((FontTag) oldValue, selChars, selFont); - fontAddCharactersField.setText(""); - reload(true); - } - } - } - break; case ACTION_SELECT_COLOR: Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectcolor.title"), View.swfBackgroundColor); if (newColor != null) { @@ -2327,18 +2096,6 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T reload(true); } break; - case ACTION_FONT_ADD_CHARS: - String newchars = fontAddCharactersField.getText(); - if (oldValue instanceof FontTag) { - Set selChars = new TreeSet<>(); - for (int c = 0; c < newchars.length(); c++) { - selChars.add(newchars.codePointAt(c)); - } - fontAddChars((FontTag) oldValue, selChars, fontSelection.getSelectedItem().toString()); - fontAddCharactersField.setText(""); - reload(true); - } - break; case ACTION_REPLACE_IMAGE: { Object tagObj = tagTree.getLastSelectedPathComponent(); @@ -2459,7 +2216,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T if (((TextTag) oldValue).setFormattedText(new MissingCharacterHandler() { @Override public boolean handle(FontTag font, List tags, char character) { - String fontName = sourceFontsMap.get(font.getFontId()); + String fontName = fontPanel.sourceFontsMap.get(font.getFontId()); if (fontName == null) { fontName = font.getFontName(tags); } @@ -2473,7 +2230,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T return true; } - }, swf.tags, textValue.getText(), fontSelection.getSelectedItem().toString())) { + }, swf.tags, textValue.getText(), fontPanel.getSelectedFont())) { setEditText(false); } } catch (ParseException ex) { @@ -2523,7 +2280,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T CardLayout cl = (CardLayout) (displayPanel.getLayout()); cl.show(displayPanel, card); } - private Object oldValue; + public Object oldValue; private File tempFile; @Override @@ -2696,6 +2453,8 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T previewImagePanel.setImage(SWF.frameToImage(containerId, ((FrameNode) tagObj).getFrame() - 1, swf.tags, controlTags, rect, totalFrameCount, new Stack())); } else if (((tagObj instanceof FrameNode) && ((FrameNode) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); + createAndShowTempSwf(tagObj); + try { if (tempFile != null) { tempFile.delete(); @@ -3079,6 +2838,376 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T showCard(CARDEMPTYPANEL); } } + + private void createAndShowTempSwf(Object tagObj) { + try { + if (tempFile != null) { + tempFile.delete(); + } + tempFile = File.createTempFile("temp", ".swf"); + tempFile.deleteOnExit(); + + Color backgroundColor = View.swfBackgroundColor; + if (tagObj instanceof FontTag) { //Fonts are always black on white + backgroundColor = View.DEFAULT_BACKGROUND_COLOR; + } + int frameCount = 1; + int frameRate = swf.frameRate; + HashMap videoFrames = new HashMap<>(); + DefineVideoStreamTag vs = null; + if (tagObj instanceof DefineVideoStreamTag) { + vs = (DefineVideoStreamTag) tagObj; + swf.populateVideoFrames(vs.getCharacterId(), swf.tags, videoFrames); + frameCount = videoFrames.size(); + } + + List soundFrames = new ArrayList<>(); + if (tagObj instanceof SoundStreamHeadTypeTag) { + SWF.populateSoundStreamBlocks(swf.tags, (Tag) tagObj, soundFrames); + frameCount = soundFrames.size(); + } + + if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) { + frameCount = 100; + frameRate = 50; + } + + if (tagObj instanceof DefineSoundTag) { + frameCount = 1; + } + + byte[] data; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + SWFOutputStream sos2 = new SWFOutputStream(baos, 10); + int width = swf.displayRect.Xmax - swf.displayRect.Xmin; + int height = swf.displayRect.Ymax - swf.displayRect.Ymin; + sos2.writeRECT(swf.displayRect); + sos2.writeUI8(0); + sos2.writeUI8(frameRate); + sos2.writeUI16(frameCount); //framecnt + + /*FileAttributesTag fa = new FileAttributesTag(); + sos2.writeTag(fa); + */ + if (tagObj instanceof FrameNode) { + FrameNode fn = (FrameNode) tagObj; + if (fn.getParent() == null) { + for (Tag t : swf.tags) { + if (t instanceof SetBackgroundColorTag) { + backgroundColor = ((SetBackgroundColorTag) t).backgroundColor.toColor(); + break; + } + } + } + } + + sos2.writeTag(new SetBackgroundColorTag(null, new RGB(backgroundColor))); + + if (tagObj instanceof FrameNode) { + FrameNode fn = (FrameNode) tagObj; + Object parent = fn.getParent(); + List subs = new ArrayList<>(); + if (parent == null) { + subs.addAll(swf.tags); + } else { + if (parent instanceof Container) { + subs = ((Container) parent).getSubItems(); + } + } + List doneCharacters = new ArrayList<>(); + int frameCnt = 1; + for (Object o : subs) { + if (o instanceof ShowFrameTag) { + frameCnt++; + continue; + } + if (frameCnt > fn.getFrame()) { + break; + } + Tag t = (Tag) o; + Set needed = t.getDeepNeededCharacters(characters, new ArrayList()); + for (int n : needed) { + if (!doneCharacters.contains(n)) { + sos2.writeTag(classicTag(characters.get(n))); + doneCharacters.add(n); + } + } + if (t instanceof CharacterTag) { + doneCharacters.add(((CharacterTag) t).getCharacterId()); + } + sos2.writeTag(classicTag(t)); + + if (parent != null) { + if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t; + int chid = pot.getCharacterId(); + int depth = pot.getDepth(); + MATRIX mat = pot.getMatrix(); + if (mat == null) { + mat = new MATRIX(); + } + mat = (MATRIX) Helper.deepCopy(mat); + if (parent instanceof BoundedTag) { + RECT r = ((BoundedTag) parent).getRect(characters, new Stack()); + mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2; + mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2; + } else { + mat.translateX += width / 2; + mat.translateY += height / 2; + } + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, false, false, true, false, true, depth, chid, mat, null, 0, null, 0, null)); + + } + } + } + sos2.writeTag(new ShowFrameTag(null)); + } else { + + if (tagObj instanceof DefineBitsTag) { + if (jtt != null) { + sos2.writeTag(jtt); + } + } else if (tagObj instanceof AloneTag) { + } else { + Set needed = ((Tag) tagObj).getDeepNeededCharacters(characters, new ArrayList()); + for (int n : needed) { + sos2.writeTag(classicTag(characters.get(n))); + } + } + + sos2.writeTag(classicTag((Tag) tagObj)); + + int chtId = 0; + if (tagObj instanceof CharacterTag) { + chtId = ((CharacterTag) tagObj).getCharacterId(); + } + + MATRIX mat = new MATRIX(); + mat.hasRotate = false; + mat.hasScale = false; + mat.translateX = 0; + mat.translateY = 0; + if (tagObj instanceof BoundedTag) { + RECT r = ((BoundedTag) tagObj).getRect(characters, new Stack()); + mat.translateX = -r.Xmin; + mat.translateY = -r.Ymin; + mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2; + mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2; + } else { + mat.translateX = width / 4; + mat.translateY = height / 4; + } + if (tagObj instanceof FontTag) { + + int countGlyphs = ((FontTag) tagObj).getGlyphShapeTable().size(); + int fontId = ((FontTag) tagObj).getFontId(); + int sloupcu = (int) Math.ceil(Math.sqrt(countGlyphs)); + int radku = (int) Math.ceil(((float) countGlyphs) / ((float) sloupcu)); + int x = 0; + int y = 1; + for (int f = 0; f < countGlyphs; f++) { + if (x >= sloupcu) { + x = 0; + y++; + } + List rec = new ArrayList<>(); + TEXTRECORD tr = new TEXTRECORD(); + int textHeight = height / radku; + tr.fontId = fontId; + tr.styleFlagsHasFont = true; + tr.textHeight = textHeight; + tr.glyphEntries = new GLYPHENTRY[1]; + tr.styleFlagsHasColor = true; + tr.textColor = new RGB(0, 0, 0); + tr.glyphEntries[0] = new GLYPHENTRY(); + tr.glyphEntries[0].glyphAdvance = 0; + tr.glyphEntries[0].glyphIndex = f; + rec.add(tr); + mat.translateX = x * width / sloupcu; + mat.translateY = y * height / radku; + sos2.writeTag(new DefineTextTag(null, 999 + f, new RECT(0, width, 0, height), new MATRIX(), rec)); + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1 + f, 999 + f, mat, null, 0, null, 0, null)); + x++; + } + sos2.writeTag(new ShowFrameTag(null)); + } else if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) { + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); + sos2.writeTag(new ShowFrameTag(null)); + int numFrames = 100; + for (int ratio = 0; ratio < 65536; ratio += 65536 / numFrames) { + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, false, true, 1, chtId, mat, null, ratio, null, 0, null)); + sos2.writeTag(new ShowFrameTag(null)); + } + } else if (tagObj instanceof SoundStreamHeadTypeTag) { + for (SoundStreamBlockTag blk : soundFrames) { + sos2.writeTag(blk); + sos2.writeTag(new ShowFrameTag(null)); + } + } else if (tagObj instanceof DefineSoundTag) { + ExportAssetsTag ea = new ExportAssetsTag(); + DefineSoundTag ds = (DefineSoundTag) tagObj; + ea.tags.add(ds.soundId); + ea.names.add("my_define_sound"); + sos2.writeTag(ea); + List actions; + DoActionTag doa; + + + doa = new DoActionTag(null, new byte[]{}, SWF.DEFAULT_VERSION, 0); + actions = ASMParser.parse(0, 0, false, + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n" + + "Push \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\" 0.0 \"Sound\"\n" + + "NewObject\n" + + "SetMember\n" + + "Push \"my_define_sound\" 1 \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"attachSound\"\n" + + "CallMethod\n" + + "Pop\n" + + "Stop", SWF.DEFAULT_VERSION, false); + doa.setActions(actions, SWF.DEFAULT_VERSION); + sos2.writeTag(doa); + sos2.writeTag(new ShowFrameTag(null)); + + + actions = ASMParser.parse(0, 0, false, + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n" + + "StopSounds\n" + + "Push \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\" 0.0 \"Sound\"\n" + + "NewObject\n" + + "SetMember\n" + + "Push \"my_define_sound\" 1 \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"attachSound\"\n" + + "CallMethod\n" + + "Pop\n" + + "Push 9999 0.0 2 \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"start\"\n" + + "CallMethod\n" + + "Pop\n" + + "Stop", SWF.DEFAULT_VERSION, false); + doa.setActions(actions, SWF.DEFAULT_VERSION); + sos2.writeTag(doa); + sos2.writeTag(new ShowFrameTag(null)); + + actions = ASMParser.parse(0, 0, false, + "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n" + + "StopSounds\n" + + "Push \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\" 0.0 \"Sound\"\n" + + "NewObject\n" + + "SetMember\n" + + "Push \"my_define_sound\" 1 \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"attachSound\"\n" + + "CallMethod\n" + + "Pop\n" + + "Push \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"onSoundComplete\"\n" + + "DefineFunction2 \"\" 0 2 false true true false true false true false false {\n" + + "Push 0.0 register1 \"my_sound\"\n" + + "GetMember\n" + + "Push \"start\"\n" + + "CallMethod\n" + + "Pop\n" + + "}\n" + + "SetMember\n" + + "Push \"_root\"\n" + + "GetVariable\n" + + "Push \"execParam\"\n" + + "GetMember\n" + + "Push 1 \"_root\"\n" + + "GetVariable\n" + + "Push \"my_sound\"\n" + + "GetMember\n" + + "Push \"start\"\n" + + "CallMethod\n" + + "Pop\n" + + "Stop", SWF.DEFAULT_VERSION, false); + doa.setActions(actions, SWF.DEFAULT_VERSION); + sos2.writeTag(doa); + sos2.writeTag(new ShowFrameTag(null)); + + + actions = ASMParser.parse(0, 0, false, + "StopSounds\n" + + "Stop", SWF.DEFAULT_VERSION, false); + doa.setActions(actions, SWF.DEFAULT_VERSION); + sos2.writeTag(doa); + sos2.writeTag(new ShowFrameTag(null)); + + + sos2.writeTag(new ShowFrameTag(null)); + if (flashPanel != null) { + flashPanel.specialPlayback = true; + } + } else if (tagObj instanceof DefineVideoStreamTag) { + + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, false, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); + List frs = new ArrayList<>(videoFrames.values()); + Collections.sort(frs, new Comparator() { + @Override + public int compare(VideoFrameTag o1, VideoFrameTag o2) { + return o1.frameNum - o2.frameNum; + } + }); + boolean first = true; + int ratio = 0; + for (VideoFrameTag f : frs) { + if (!first) { + ratio++; + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, false, false, true, 1, 0, null, null, ratio, null, 0, null)); + } + sos2.writeTag(f); + sos2.writeTag(new ShowFrameTag(null)); + first = false; + } + } else { + sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); + sos2.writeTag(new ShowFrameTag(null)); + } + + + }//not showframe + + sos2.writeTag(new EndTag(null)); + data = baos.toByteArray(); + } + + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile))) { + SWFOutputStream sos = new SWFOutputStream(fos, 10); + sos.write("FWS".getBytes()); + sos.write(swf.version); + sos.writeUI32(sos.getPos() + data.length + 4); + sos.write(data); + fos.flush(); + } + + showCard(CARDFLASHPANEL); + if (flashPanel != null) { + flashPanel.displaySWF(tempFile.getAbsolutePath(), backgroundColor, frameRate); + } + } catch (IOException | com.jpexs.decompiler.flash.action.parser.ParseException ex) { + Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); + } + } private void showFontTag(FontTag ft) { if (mainRibbon.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { @@ -3090,20 +3219,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T parametersPanel.setVisible(true); previewSplitPane.setDividerLocation(previewSplitPane.getWidth() / 2); - fontNameLabel.setText(ft.getFontName(swf.tags)); - fontIsBoldLabel.setText(ft.isBold() ? translate("yes") : translate("no")); - fontIsItalicLabel.setText(ft.isItalic() ? translate("yes") : translate("no")); - fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent()); - fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent()); - fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading()); - String chars = ft.getCharacters(swf.tags); - fontCharactersTextArea.setText(chars); - if (sourceFontsMap.containsKey(ft.getFontId())) { - fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId())); - } else { - fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName(swf.tags))); - } - fontChangeList.componentResized(null); + fontPanel.showFontTag(ft); showDetailWithPreview(CARDFONTPANEL); } @@ -3183,6 +3299,7 @@ public final class MainFrame extends AppRibbonFrame implements ActionListener, T @Override public void free() { + Helper.emptyObject(mainRibbon); Helper.emptyObject(statusPanel); Helper.emptyObject(this); }