Issue #220 Improved font changing

This commit is contained in:
Jindra Petk
2013-07-27 07:34:52 +02:00
parent fae061520d
commit 2c2b722c27
17 changed files with 399 additions and 56 deletions

View File

@@ -3020,9 +3020,9 @@ public class SWFInputStream extends InputStream {
for (int i = 0; i < numZoneData; i++) {
ret.zonedata[i] = readZONEDATA();
}
readUB(6);
ret.zoneMaskX = readUB(1) == 1;
readUB(6);
ret.zoneMaskY = readUB(1) == 1;
ret.zoneMaskX = readUB(1) == 1;
return ret;
}

View File

@@ -1592,8 +1592,8 @@ public class SWFOutputStream extends OutputStream {
writeZONEDATA(value.zonedata[i]);
}
writeUB(6, 0);
writeUB(1, value.zoneMaskX ? 1 : 0);
writeUB(1, value.zoneMaskY ? 1 : 0);
writeUB(1, value.zoneMaskX ? 1 : 0);
}
/**

View File

@@ -36,22 +36,36 @@ import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
import com.jpexs.decompiler.flash.helpers.Cache;
import com.jpexs.decompiler.flash.helpers.Helper;
import com.jpexs.decompiler.flash.types.ZONERECORD;
import com.sun.jna.Platform;
import com.sun.jna.WString;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.QuadCurve2D;
import java.io.*;
import java.net.Socket;
import java.net.URLDecoder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.logging.ConsoleHandler;
@@ -63,9 +77,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import static javax.swing.WindowConstants.HIDE_ON_CLOSE;
import javax.swing.filechooser.FileFilter;
/**
@@ -598,6 +615,7 @@ public class Main {
* @throws IOException
*/
public static void main(String[] args) throws IOException {
loadProperties();
Configuration.loadFromFile(getConfigFile(), getReplacementsFile());
int pos = 0;
@@ -613,6 +631,102 @@ public class Main {
View.setLookAndFeel();
/*View.execInEventDispatch(new Runnable() {
@Override
public void run() {
new JFrame() {
private int size = 15*1024;
@Override
public void setVisible(boolean b) {
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
size+=10;
repaint();
}
});
addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
getContentPane().add(new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform t = AffineTransform.getTranslateInstance(0, 0);
t.translate(200, 400);
t.scale((((float)size)/1024)/(2000),(((float)size)/1024)/2000);
g2d.setTransform(t);
Font f = new Font("Cordia New", 0, size);
GlyphVector v = f.createGlyphVector((new JPanel()).getFontMetrics(f).getFontRenderContext(), "C");
Shape shp = v.getOutline();
g2d.setPaint(Color.black);
g.setColor(Color.black);
double points[] = new double[6];
double lastX = 0;
double lastY = 0;
double startX = 0;
double startY = 0;
GeneralPath path=new GeneralPath();
for (PathIterator it = shp.getPathIterator(null); !it.isDone(); it.next()) {
int type = it.currentSegment(points);
switch (type) {
case PathIterator.SEG_MOVETO:
lastX = (points[0]);
lastY = (points[1]);
startX = lastX;
startY = lastY;
path.moveTo(lastX, lastY);
break;
case PathIterator.SEG_LINETO:
//g2d.drawLine((int) lastX, (int) lastY, (int) points[0], (int) points[1]);
lastX = (points[0]);
lastY = (points[1]);
path.lineTo(lastX, lastY);
break;
case PathIterator.SEG_CUBICTO:
throw new RuntimeException("NOCUBIC");
case PathIterator.SEG_QUADTO:
//g2d.draw(new QuadCurve2D.Double(lastX, lastY, points[0], points[1], points[2], points[3]));
path.quadTo(points[0], points[1], points[2], points[3]);
lastX = (points[2]);
lastY = (points[3]);
break;
case PathIterator.SEG_CLOSE: //Closing line back to last SEG_MOVETO
if ((startX == lastX) && (startY == lastY)) {
break;
}
//g2d.drawLine((int) lastX, (int) lastY, (int) points[0], (int) points[1]);
path.lineTo(startX, startY);
lastX = startX;
lastY = startY;
break;
}
}
g2d.draw(path);
}
});
setDefaultCloseOperation(HIDE_ON_CLOSE);
setSize(500, 500);
super.setVisible(b);
}
}.setVisible(true);
}
});
if (true) {
return;
}//*/
if ((Boolean) Configuration.getConfig("cacheOnDisk", Boolean.TRUE)) {
Cache.setStorageType(Cache.STORAGE_FILES);
} else {
@@ -1234,7 +1348,7 @@ public class Main {
if ((!exists) && add) { //add
Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec");
Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec", "", "Open with FFDec");
Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec\\command");
Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec\\ ");
Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec\\command", "", "\"" + appDir + exeName + "\" \"%1\"");
}
if (exists && (!add)) { //remove

View File

@@ -82,6 +82,7 @@ import com.jpexs.decompiler.flash.tags.base.Container;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
@@ -122,6 +123,8 @@ 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;
@@ -139,6 +142,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
@@ -276,6 +280,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
private ErrorLogFrame errorLogFrame;
private ComponentListener fontChangeList;
private JComboBox<String> fontSelection;
private Map<Integer, String> sourceFontsMap = new HashMap<>();
private AbortRetryIgnoreHandler errorHandler = new AbortRetryIgnoreHandler() {
@Override
public int handle(Throwable thrown) {
@@ -1162,6 +1167,15 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
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();
@@ -2147,6 +2161,18 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
if (oldValue instanceof FontTag) {
FontTag f = (FontTag) oldValue;
String oldchars = f.getCharacters(swf.tags);
for (int i = 0; i < newchars.length(); i++) {
char c = newchars.charAt(i);
if (oldchars.indexOf((int) c) == -1) {
Font font=new Font(fontSelection.getSelectedItem().toString(),f.getFontStyle(),1024);
if(!font.canDisplay(c)){
JOptionPane.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", ""+c), translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
}
}
for (int i = 0; i < newchars.length(); i++) {
char c = newchars.charAt(i);
if (oldchars.indexOf((int) c) == -1) {
@@ -2331,8 +2357,35 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
case "SAVETEXT":
if (oldValue instanceof TextTag) {
try {
((TextTag) oldValue).setFormattedText(swf.tags, textValue.getText(), fontSelection.getSelectedItem().toString());
setEditText(false);
if (((TextTag) oldValue).setFormattedText(new MissingCharacterHandler() {
@Override
public boolean handle(FontTag font, List<Tag> tags, char character) {
String fontName = sourceFontsMap.get(font.getFontId());
if (fontName == null) {
fontName = font.getFontName(tags);
}
//
if (!fontNames.contains(fontName)) {
fontName = "Times New Roman";
}
if (!fontNames.contains(fontName)) {
fontName = "Arial";
}
if (!fontNames.contains(fontName)) {
fontName = fontSelection.getItemAt(0);
}
Font f = new Font(fontName, font.getFontStyle(), 18);
if (!f.canDisplay(character)) {
JOptionPane.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", ""+character), translate("error"), JOptionPane.ERROR_MESSAGE);
return false;
}
font.addCharacter(tags, character, fontName);
return true;
}
}, swf.tags, textValue.getText(), fontSelection.getSelectedItem().toString())) {
setEditText(false);
}
} catch (ParseException ex) {
JOptionPane.showMessageDialog(null, translate("error.text.invalid").replace("%text%", ex.text).replace("%line%", "" + ex.line), translate("error"), JOptionPane.ERROR_MESSAGE);
}
@@ -3026,10 +3079,14 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading());
String chars = ft.getCharacters(swf.tags);
fontCharactersTextArea.setText(chars);
fontSelection.setSelectedIndex(0);
fontSelection.setSelectedItem("Times New Roman");
fontSelection.setSelectedItem("Arial");
fontSelection.setSelectedItem(ft.getFontName(swf.tags));
if (sourceFontsMap.containsKey(ft.getFontId())) {
fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId()));
} else {
fontSelection.setSelectedIndex(0);
fontSelection.setSelectedItem("Times New Roman");
fontSelection.setSelectedItem("Arial");
fontSelection.setSelectedItem(ft.getFontName(swf.tags));
}
fontChangeList.componentResized(null);
showDetailWithPreview(CARDFONTPANEL);
} else {

View File

@@ -331,4 +331,6 @@ menu.general = General
menu.language = Language
startup.welcometo = Welcome to
startup.selectopen = Click open icon on the top panel or drag SWF file to this window to start.
startup.selectopen = Click open icon on the top panel or drag SWF file to this window to start.
error.font.nocharacter = Selected source font does not contain character "%char%".

View File

@@ -329,4 +329,6 @@ menu.general = Hlavn\u00ed
menu.language = Jazyk
startup.welcometo = V\u00edtejte v programu
startup.selectopen = Pro za\u010d\u00e1tek klikn\u011bte na otev\u0159\u00edt v horn\u00edm panelu nebo p\u0159et\u00e1hn\u011bte SWF soubor p\u0159\u00edmo do tohoto okna.
startup.selectopen = Pro za\u010d\u00e1tek klikn\u011bte na otev\u0159\u00edt v horn\u00edm panelu nebo p\u0159et\u00e1hn\u011bte SWF soubor p\u0159\u00edmo do tohoto okna.
error.font.nocharacter = Vybran\u00e9 zdrojov\u00e9 p\u00edsmo neobsahuje znak "%char%".

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.tags.text.ParsedSymbol;
@@ -163,7 +164,7 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
}
@Override
public void setFormattedText(List<Tag> tags, String text, String fontName) throws ParseException {
public boolean setFormattedText(MissingCharacterHandler missingCharHandler, List<Tag> tags, String text, String fontName) throws ParseException {
try {
TextLexer lexer = new TextLexer(new InputStreamReader(new ByteArrayInputStream(text.getBytes("UTF-8")), "UTF-8"));
ParsedSymbol s = null;
@@ -336,6 +337,7 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
}
}
this.bounds = bounds;
if (text.length() > 0) {
initialText = text;
this.hasText = true;
@@ -384,8 +386,9 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
} catch (IOException ex) {
Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
return true;
}
@@ -464,6 +467,7 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos

View File

@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import java.awt.Font;
import java.awt.font.GlyphVector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -313,13 +314,28 @@ public class DefineFont2Tag extends FontTag {
int fontStyle = getFontStyle();
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
glyphShapeTable.add(shp);
codeTable.add((int) character);
int code = (int) character;
int pos = -1;
for (int i = 0; i < codeTable.size(); i++) {
if (codeTable.get(i) > code) {
pos = i;
break;
}
}
if (pos == -1) {
pos = codeTable.size();
}
FontTag.shiftGlyphIndices(fontId, pos, tags);
glyphShapeTable.add(pos, shp);
codeTable.add(pos, (int) character);
if (fontFlagsHasLayout) {
fontBoundsTable.add(shp.getBounds());
fontBoundsTable.add(pos, shp.getBounds());
Font fnt = new Font(fontName, fontStyle, getDivider() * 1024);
fontAdvanceTable.add((new JPanel()).getFontMetrics(fnt).charWidth(character));
fontAdvanceTable.add(pos, (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX()));
}
numGlyphs++;
}

View File

@@ -32,8 +32,11 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class DefineFont3Tag extends FontTag {
@@ -301,14 +304,39 @@ public class DefineFont3Tag extends FontTag {
@Override
public void addCharacter(List<Tag> tags, char character, String fontName) {
//Font Align Zones will be removed as adding new character zones is not supported:-(
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
if (t instanceof DefineFontAlignZonesTag) {
DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t;
if (fa.fontID == fontId) {
tags.remove(i);
i--;
}
}
}
int fontStyle = getFontStyle();
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
glyphShapeTable.add(shp);
codeTable.add((int) character);
int code = (int) character;
int pos = -1;
for (int i = 0; i < codeTable.size(); i++) {
if (codeTable.get(i) > code) {
pos = i;
break;
}
}
if (pos == -1) {
pos = codeTable.size();
}
FontTag.shiftGlyphIndices(fontId, pos, tags);
glyphShapeTable.add(pos, shp);
codeTable.add(pos, (int) character);
if (fontFlagsHasLayout) {
fontBoundsTable.add(shp.getBounds());
fontBoundsTable.add(pos, shp.getBounds());
Font fnt = new Font(fontName, fontStyle, getDivider() * 1024);
fontAdvanceTable.add((new JPanel()).getFontMetrics(fnt).charWidth(character));
fontAdvanceTable.add(pos, (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX()));
}
numGlyphs++;
}

View File

@@ -225,14 +225,30 @@ public class DefineFontTag extends FontTag {
@Override
public void addCharacter(List<Tag> tags, char character, String fontName) {
glyphShapeTable.add(SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character));
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character);
List<Integer> codeTable=new ArrayList<>();
ensureFontInfo(tags);
if (fontInfoTag != null) {
fontInfoTag.codeTable.add((int) character);
codeTable =fontInfoTag.codeTable;
}
if (fontInfo2Tag != null) {
fontInfo2Tag.codeTable.add((int) character);
codeTable =fontInfo2Tag.codeTable;
}
int code=(int)character;
int pos=-1;
for(int i=0;i<codeTable.size();i++){
if(codeTable.get(i)>code){
pos = i;
break;
}
}
if(pos==-1){
pos = codeTable.size();
}
FontTag.shiftGlyphIndices(fontId, pos, tags);
glyphShapeTable.add(pos,shp);
codeTable.add(pos,(int)character);
}
@Override

View File

@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.tags.text.ParsedSymbol;
@@ -164,7 +165,7 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag,
}
@Override
public void setFormattedText(List<Tag> tags, String text, String fontName) throws ParseException {
public boolean setFormattedText(MissingCharacterHandler missingCharHandler,List<Tag> tags, String text, String fontName) throws ParseException {
try {
TextLexer lexer = new TextLexer(new InputStreamReader(new ByteArrayInputStream(text.getBytes("UTF-8")), "UTF-8"));
ParsedSymbol s = null;
@@ -336,12 +337,12 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag,
char c = txt.charAt(i);
tr.glyphEntries[i] = new GLYPHENTRY();
if (!font.containsChar(tags, c)) {
font.addCharacter(tags, c, fontName);
if(!missingCharHandler.handle(font, tags, c)){
return false;
}
}
tr.glyphEntries[i].glyphIndex = font.charToGlyph(tags, c);
/*if (tr.glyphEntries[i].glyphIndex == -1) {
throw new ParseException("Font does not contain glyph for character '" + c + "'", lexer.yyline());
}*/
@@ -381,7 +382,9 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag,
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(DefineText2Tag.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
return false;
}
return true;
}
@Override
@@ -423,6 +426,7 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag,
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos

View File

@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.tags.text.ParsedSymbol;
@@ -164,7 +165,7 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag,
}
@Override
public void setFormattedText(List<Tag> tags, String text, String fontName) throws ParseException {
public boolean setFormattedText(MissingCharacterHandler missingCharHandler,List<Tag> tags, String text, String fontName) throws ParseException {
try {
TextLexer lexer = new TextLexer(new InputStreamReader(new ByteArrayInputStream(text.getBytes("UTF-8")), "UTF-8"));
ParsedSymbol s = null;
@@ -335,7 +336,9 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag,
char c = txt.charAt(i);
tr.glyphEntries[i] = new GLYPHENTRY();
if (!font.containsChar(tags, c)) {
font.addCharacter(tags, c, fontName);
if(!missingCharHandler.handle(font, tags, c)){
return false;
}
}
tr.glyphEntries[i].glyphIndex = font.charToGlyph(tags, c);
@@ -381,7 +384,9 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag,
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(DefineTextTag.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
return false;
}
return true;
}
@Override

View File

@@ -17,9 +17,14 @@
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
/**
@@ -94,4 +99,30 @@ public abstract class FontTag extends CharacterTag implements AloneTag {
}
return name + " (" + getCharacterId() + nameAppend + ")";
}
public static void shiftGlyphIndices(int fontId,int startIndex, List<Tag> tags) {
List<TEXTRECORD> textRecords = new ArrayList<>();
for (Tag t : tags) {
if (t instanceof DefineTextTag) {
textRecords.addAll(((DefineTextTag) t).textRecords);
}
if (t instanceof DefineText2Tag) {
textRecords.addAll(((DefineTextTag) t).textRecords);
}
}
int curFontId=0;
for (TEXTRECORD tr : textRecords) {
if(tr.styleFlagsHasFont){
curFontId = tr.fontId;
}
if(curFontId!=fontId){
continue;
}
for (GLYPHENTRY en : tr.glyphEntries) {
if (en.glyphIndex >= startIndex) {
en.glyphIndex++;
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.tags.Tag;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.util.Arrays;
import java.util.List;
/**
*
* @author JPEXS
*/
public class MissingCharacterHandler {
protected static List<String> fontNames = Arrays.asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
public boolean handle(FontTag font,List<Tag> tags,char character){
String fontName = font.getFontName(tags);
if(!fontNames.contains(fontName)){
return false;
}
Font f=new Font(fontName,font.getFontStyle(),18);
if(!f.canDisplay(character)){
return false;
}
font.addCharacter(tags, character, fontName);
return true;
}
}

View File

@@ -34,7 +34,7 @@ public interface TextTag {
public String getFormattedText(List<Tag> tags);
public void setFormattedText(List<Tag> tags, String text, String fontName) throws ParseException;
public boolean setFormattedText(MissingCharacterHandler missingCharHandler,List<Tag> tags, String text, String fontName) throws ParseException;
public int getCharacterId();

View File

@@ -16,6 +16,14 @@
*/
package com.jpexs.decompiler.flash.types;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.LineMetrics;
import javax.swing.JFrame;
/**
* Represents 32-bit alpha, red, green and blue value
*
@@ -26,7 +34,7 @@ public class ZONERECORD {
public ZONEDATA zonedata[] = new ZONEDATA[0];
public boolean zoneMaskX;
public boolean zoneMaskY;
@Override
public String toString() {
String ret = "[ZONERECORD data:";

View File

@@ -35,6 +35,7 @@ import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.LinearGradientPaint;
@@ -48,8 +49,10 @@ import java.awt.TexturePaint;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
@@ -60,6 +63,7 @@ import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
@@ -366,7 +370,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
GeneralPath ret = new GeneralPath();
int x = startX;
int y = startY;
boolean wasMoveTo = false;
boolean wasMoveTo = false;
for (SHAPERECORD rec : edges) {
int nx = rec.changeX(x);
int ny = rec.changeY(y);
@@ -870,7 +874,12 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
}
private static List<String> existingFonts = Arrays.asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
public static SHAPE systemFontCharacterToSHAPE(String fontName, int fontStyle, int fontSize, char character) {
public static SHAPE systemFontCharacterToSHAPE(final String fontName, final int fontStyle, int fontSize, char character) {
int multiplier = 1;
if(fontSize>1024){
multiplier = fontSize/1024;
fontSize = 1024;
}
List<SHAPERECORD> retList = new ArrayList<>();
String defaultFonts[] = new String[]{"Times New Roman", "Arial"};
Font f = null;
@@ -887,7 +896,6 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
if (f == null) {
f = new Font("Dialog", fontStyle, fontSize); //Fallback to DIALOG
}
GlyphVector v = f.createGlyphVector((new JPanel()).getFontMetrics(f).getFontRenderContext(), "" + character);
Shape shp = v.getOutline();
double points[] = new double[6];
@@ -896,13 +904,13 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
int startX = 0;
int startY = 0;
for (PathIterator it = shp.getPathIterator(null); !it.isDone(); it.next()) {
int type = it.currentSegment(points);
int type = it.currentSegment(points);
switch (type) {
case PathIterator.SEG_MOVETO:
StyleChangeRecord scr = new StyleChangeRecord();
scr.stateMoveTo = true;
scr.moveDeltaX = (int) Math.round(points[0]);
scr.moveDeltaY = (int) Math.round(points[1]);
scr.moveDeltaX = multiplier*(int) Math.round(points[0]);
scr.moveDeltaY = multiplier*(int) Math.round(points[1]);
scr.moveBits = SWFOutputStream.getNeededBitsS(scr.moveDeltaX, scr.moveDeltaY);
retList.add(scr);
lastX = (int) Math.round(points[0]);
@@ -911,10 +919,14 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
startY = lastY;
break;
case PathIterator.SEG_LINETO:
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.generalLineFlag = true;
ser.deltaX = ((int) Math.round(points[0])) - lastX;
ser.deltaY = ((int) Math.round(points[1])) - lastY;
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = multiplier*(((int) Math.round(points[0])) - lastX);
ser.deltaY = multiplier*(((int) Math.round(points[1])) - lastY);
ser.generalLineFlag = ser.deltaX!=0 && ser.deltaY!=0;
if(ser.deltaX == 0){
ser.vertLineFlag = true;
}
ser.numBits = SWFOutputStream.getNeededBitsS(ser.deltaX, ser.deltaY) - 2;
if (ser.numBits < 0) {
ser.numBits = 0;
@@ -933,11 +945,11 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
double quadCoords[][] = approximateCubic(cubicCoords);
for (int i = 0; i < quadCoords.length; i++) {
CurvedEdgeRecord cer = new CurvedEdgeRecord();
cer.controlDeltaX = ((int) Math.round(quadCoords[i][0])) - lastX;
cer.controlDeltaY = ((int) Math.round(quadCoords[i][1])) - lastY;
cer.anchorDeltaX = ((int) Math.round(quadCoords[i][2])) - ((int) Math.round(quadCoords[i][0]));
cer.anchorDeltaY = ((int) Math.round(quadCoords[i][3])) - ((int) Math.round(quadCoords[i][1]));
cer.numBits = SWFOutputStream.getNeededBitsS(cer.controlDeltaX, cer.controlDeltaY, cer.anchorDeltaX, cer.anchorDeltaY) - 2;
cer.controlDeltaX = multiplier*(((int) Math.round(quadCoords[i][0])) - lastX);
cer.controlDeltaY = multiplier*(((int) Math.round(quadCoords[i][1])) - lastY);
cer.anchorDeltaX = multiplier*(((int) Math.round(quadCoords[i][2])) - ((int) Math.round(quadCoords[i][0])));
cer.anchorDeltaY = multiplier*(((int) Math.round(quadCoords[i][3])) - ((int) Math.round(quadCoords[i][1])));
cer.numBits = SWFOutputStream.getNeededBitsS(cer.controlDeltaX, cer.controlDeltaY, cer.anchorDeltaX, cer.anchorDeltaY) - 2;
if (cer.numBits < 0) {
cer.numBits = 0;
}
@@ -948,17 +960,17 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
break;
case PathIterator.SEG_QUADTO:
CurvedEdgeRecord cer = new CurvedEdgeRecord();
cer.controlDeltaX = ((int) Math.round(points[0])) - lastX;
cer.controlDeltaY = ((int) Math.round(points[1])) - lastY;
cer.anchorDeltaX = ((int) Math.round(points[2])) - (int) Math.round(points[0]);
cer.anchorDeltaY = ((int) Math.round(points[3])) - (int) Math.round(points[1]);
cer.controlDeltaX = multiplier*(((int) Math.round(points[0])) - lastX);
cer.controlDeltaY = multiplier*(((int) Math.round(points[1])) - lastY);
cer.anchorDeltaX = multiplier*(((int) Math.round(points[2])) - (int) Math.round(points[0]));
cer.anchorDeltaY = multiplier*(((int) Math.round(points[3])) - (int) Math.round(points[1]));
cer.numBits = SWFOutputStream.getNeededBitsS(cer.controlDeltaX, cer.controlDeltaY, cer.anchorDeltaX, cer.anchorDeltaY) - 2;
if (cer.numBits < 0) {
cer.numBits = 0;
}
retList.add(cer);
retList.add(cer);
lastX = (int) Math.round(points[2]);
lastY = (int) Math.round(points[3]);
lastY = (int) Math.round(points[3]);
break;
case PathIterator.SEG_CLOSE: //Closing line back to last SEG_MOVETO
if ((startX == lastX) && (startY == lastY)) {
@@ -966,8 +978,8 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
}
StraightEdgeRecord closeSer = new StraightEdgeRecord();
closeSer.generalLineFlag = true;
closeSer.deltaX = (int) Math.round((startX - lastX));
closeSer.deltaY = (int) Math.round((startY - lastY));
closeSer.deltaX = multiplier*((int) Math.round((startX - lastX)));
closeSer.deltaY = multiplier*((int) Math.round((startY - lastY)));
closeSer.numBits = SWFOutputStream.getNeededBitsS(closeSer.deltaX, closeSer.deltaY) - 2;
if (closeSer.numBits < 0) {
closeSer.numBits = 0;