diff --git a/CHANGELOG.md b/CHANGELOG.md index a81f20d4e..322febf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ All notable changes to this project will be documented in this file. - NullPointer on reload / uncache - [#2076] Auto rename identifiers infinite loop caused by renaming in playerglobal library - Not working "Show in Projector" button for DefineFont4 (hide) +- Proper error message when there is no room for new characters in the font (DefineFont1) +- Synchronization problems when adding characters to the font vs its display ### Changed - [#2070] String values inside SWF to XML export are backslash escaped diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java index a7a0fd164..ae15af1f9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java @@ -244,7 +244,7 @@ public class DefineFont2Tag extends FontTag { * @throws java.io.IOException */ @Override - public void getData(SWFOutputStream sos) throws IOException { + public synchronized void getData(SWFOutputStream sos) throws IOException { checkWideParameters(); sos.writeUI16(fontID); sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); @@ -319,12 +319,12 @@ public class DefineFont2Tag extends FontTag { } @Override - public int getGlyphWidth(int glyphIndex) { + public synchronized int getGlyphWidth(int glyphIndex) { return glyphShapeTable.get(glyphIndex).getBounds(1).getWidth(); } @Override - public RECT getGlyphBounds(int glyphIndex) { + public synchronized RECT getGlyphBounds(int glyphIndex) { if (fontFlagsHasLayout) { return fontBoundsTable.get(glyphIndex); } @@ -332,7 +332,7 @@ public class DefineFont2Tag extends FontTag { } @Override - public double getGlyphAdvance(int glyphIndex) { + public synchronized double getGlyphAdvance(int glyphIndex) { if (fontFlagsHasLayout) { return fontAdvanceTable.get(glyphIndex); } else { @@ -341,7 +341,7 @@ public class DefineFont2Tag extends FontTag { } @Override - public List getGlyphShapeTable() { + public synchronized List getGlyphShapeTable() { return glyphShapeTable; } @@ -356,12 +356,12 @@ public class DefineFont2Tag extends FontTag { } @Override - public char glyphToChar(int glyphIndex) { + public synchronized char glyphToChar(int glyphIndex) { return Utf8Helper.codePointToChar(codeTable.get(glyphIndex), getCodesCharset()); } @Override - public int charToGlyph(char c) { + public synchronized int charToGlyph(char c) { return codeTable.indexOf(Utf8Helper.charToCodePoint(c, getCodesCharset())); } @@ -444,7 +444,7 @@ public class DefineFont2Tag extends FontTag { } @Override - public void addCharacter(char character, Font font) { + public synchronized boolean addCharacter(char character, Font font) { int fontStyle = getFontStyle(); SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); @@ -519,10 +519,11 @@ public class DefineFont2Tag extends FontTag { checkWideParameters(); setModified(true); getSwf().clearImageCache(); + return true; } @Override - public boolean removeCharacter(char character) { + public synchronized boolean removeCharacter(char character) { int code = (int) character; int pos = -1; for (int i = 0; i < codeTable.size(); i++) { @@ -565,7 +566,7 @@ public class DefineFont2Tag extends FontTag { } @Override - public void setAdvanceValues(Font font) { + public synchronized void setAdvanceValues(Font font) { List newFontBoundsTable = new ArrayList<>(); List newFontAdvanceTable = new ArrayList<>(); for (int i = 0; i < codeTable.size(); i++) { @@ -589,12 +590,12 @@ public class DefineFont2Tag extends FontTag { } @Override - public int getCharacterCount() { + public synchronized int getCharacterCount() { return codeTable.size(); } @Override - public String getCharacters() { + public synchronized String getCharacters() { StringBuilder ret = new StringBuilder(codeTable.size()); for (int i : codeTable) { Character c = Utf8Helper.codePointToChar(i, getCodesCharset()); @@ -609,14 +610,14 @@ public class DefineFont2Tag extends FontTag { } @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + public synchronized int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { char c1 = glyphToChar(glyphIndex); char c2 = glyphToChar(nextGlyphIndex); return getCharKerningAdjustment(c1, c2); } @Override - public int getCharKerningAdjustment(char c1, char c2) { + public synchronized int getCharKerningAdjustment(char c1, char c2) { int kerningAdjustment = 0; int c1Code = Utf8Helper.charToCodePoint(c1, getCodesCharset()); int c2Code = Utf8Helper.charToCodePoint(c2, getCodesCharset()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java index 0b574c91b..cfd4201fd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java @@ -231,7 +231,7 @@ public class DefineFont3Tag extends FontTag { * @throws java.io.IOException */ @Override - public void getData(SWFOutputStream sos) throws IOException { + public synchronized void getData(SWFOutputStream sos) throws IOException { checkWideParameters(); List offsetTable = new ArrayList<>(); ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); @@ -307,12 +307,12 @@ public class DefineFont3Tag extends FontTag { } @Override - public int getGlyphWidth(int glyphIndex) { + public synchronized int getGlyphWidth(int glyphIndex) { return glyphShapeTable.get(glyphIndex).getBounds(1).getWidth(); } @Override - public double getGlyphAdvance(int glyphIndex) { + public synchronized double getGlyphAdvance(int glyphIndex) { if (fontFlagsHasLayout && glyphIndex != -1) { return fontAdvanceTable.get(glyphIndex); } else { @@ -321,17 +321,17 @@ public class DefineFont3Tag extends FontTag { } @Override - public char glyphToChar(int glyphIndex) { + public synchronized char glyphToChar(int glyphIndex) { return Utf8Helper.codePointToChar(codeTable.get(glyphIndex), getCodesCharset()); } @Override - public int charToGlyph(char c) { + public synchronized int charToGlyph(char c) { return codeTable.indexOf(Utf8Helper.charToCodePoint(c, getCodesCharset())); } @Override - public List getGlyphShapeTable() { + public synchronized List getGlyphShapeTable() { return glyphShapeTable; } @@ -424,7 +424,7 @@ public class DefineFont3Tag extends FontTag { } @Override - public void addCharacter(char character, Font font) { + public synchronized boolean addCharacter(char character, Font font) { //Font Align Zones will be removed as adding new character zones is not supported:-( for (int i = 0; i < swf.getTags().size(); i++) { @@ -508,10 +508,11 @@ public class DefineFont3Tag extends FontTag { checkWideParameters(); setModified(true); getSwf().clearImageCache(); + return true; } @Override - public boolean removeCharacter(char character) { + public synchronized boolean removeCharacter(char character) { //Font Align Zones will be removed as removing character zones is not supported:-( for (int i = 0; i < swf.getTags().size(); i++) { @@ -566,7 +567,7 @@ public class DefineFont3Tag extends FontTag { } @Override - public void setAdvanceValues(Font font) { + public synchronized void setAdvanceValues(Font font) { List newFontBoundsTable = new ArrayList<>(); List newFontAdvanceTable = new ArrayList<>(); for (int i = 0; i < codeTable.size(); i++) { @@ -590,12 +591,12 @@ public class DefineFont3Tag extends FontTag { } @Override - public int getCharacterCount() { + public synchronized int getCharacterCount() { return codeTable.size(); } @Override - public String getCharacters() { + public synchronized String getCharacters() { StringBuilder ret = new StringBuilder(codeTable.size()); for (int i : codeTable) { Character c = Utf8Helper.codePointToChar(i, getCodesCharset()); @@ -610,7 +611,7 @@ public class DefineFont3Tag extends FontTag { } @Override - public RECT getGlyphBounds(int glyphIndex) { + public synchronized RECT getGlyphBounds(int glyphIndex) { if (fontFlagsHasLayout) { return fontBoundsTable.get(glyphIndex); } @@ -618,7 +619,7 @@ public class DefineFont3Tag extends FontTag { } @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + public synchronized int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { if (glyphIndex == -1 || nextGlyphIndex == -1) { return 0; } @@ -628,7 +629,7 @@ public class DefineFont3Tag extends FontTag { } @Override - public int getCharKerningAdjustment(char c1, char c2) { + public synchronized int getCharKerningAdjustment(char c1, char c2) { int c1Code = Utf8Helper.charToCodePoint(c1, getCodesCharset()); int c2Code = Utf8Helper.charToCodePoint(c2, getCodesCharset()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java index 4e9a4ecc6..08b400df1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.ValueTooLargeException; import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; import com.jpexs.decompiler.flash.tags.base.FontInfoTag; import com.jpexs.decompiler.flash.tags.base.FontTag; @@ -35,6 +36,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -107,7 +110,7 @@ public class DefineFontTag extends FontTag { * @throws java.io.IOException */ @Override - public void getData(SWFOutputStream sos) throws IOException { + public synchronized void getData(SWFOutputStream sos) throws IOException { sos.writeUI16(fontId); ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); List offsetTable = new ArrayList<>(); @@ -133,7 +136,7 @@ public class DefineFontTag extends FontTag { } @Override - public int getGlyphWidth(int glyphIndex) { + public synchronized int getGlyphWidth(int glyphIndex) { return glyphShapeTable.get(glyphIndex).getBounds(1).getWidth(); } @@ -154,7 +157,7 @@ public class DefineFontTag extends FontTag { } @Override - public char glyphToChar(int glyphIndex) { + public synchronized char glyphToChar(int glyphIndex) { ensureFontInfo(); if (fontInfoTag != null) { return Utf8Helper.codePointToChar(fontInfoTag.getCodeTable().get(glyphIndex), getCodesCharset()); @@ -174,7 +177,7 @@ public class DefineFontTag extends FontTag { } @Override - public List getGlyphShapeTable() { + public synchronized List getGlyphShapeTable() { return glyphShapeTable; } @@ -275,9 +278,9 @@ public class DefineFontTag extends FontTag { } - + @Override - public void addCharacter(char character, Font font) { + public synchronized boolean addCharacter(char character, Font font) { SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); ensureFontInfo(); int code = (int) Utf8Helper.charToCodePoint(character, getCodesCharset()); @@ -307,6 +310,31 @@ public class DefineFontTag extends FontTag { pos = 0; } + + //Check whether offset is not too large + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(baos, getVersion(), getCharset()); + for (int s = 0; s <= glyphShapeTable.size(); s++) { + SHAPE shape; + if (s == glyphShapeTable.size() || pos == s) { + if (pos != s) { + break; + } + shape = shp; + } else { + shape = glyphShapeTable.get(s); + } + int offset = glyphShapeTable.size() * 2 + (int) sos2.getPos(); + if (offset > 0xffff) { + return false; + } + try { + sos2.writeSHAPE(shape, 1); + } catch (IOException ex) { + //should not happen + } + } + if (!exists) { shiftGlyphIndices(fontId, pos, true); glyphShapeTable.add(pos, shp); @@ -319,10 +347,11 @@ public class DefineFontTag extends FontTag { setModified(true); getSwf().clearImageCache(); + return true; } @Override - public boolean removeCharacter(char character) { + public synchronized boolean removeCharacter(char character) { ensureFontInfo(); if (fontInfoTag == null) { return false; @@ -362,7 +391,7 @@ public class DefineFontTag extends FontTag { } @Override - public int getCharacterCount() { + public synchronized int getCharacterCount() { ensureFontInfo(); if (fontInfoTag != null) { List codeTable = fontInfoTag.getCodeTable(); @@ -372,7 +401,7 @@ public class DefineFontTag extends FontTag { } @Override - public String getCharacters() { + public synchronized String getCharacters() { ensureFontInfo(); if (fontInfoTag != null) { List codeTable = fontInfoTag.getCodeTable(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index efea03a1e..2be987a56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -65,7 +65,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag { public abstract List getGlyphShapeTable(); - public abstract void addCharacter(char character, Font font); + public abstract boolean addCharacter(char character, Font font); public abstract boolean removeCharacter(char character); @@ -440,7 +440,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) { + public synchronized void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) { SHAPERECORD.shapeListToImage(1, swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java index 05b34b042..3a9acb9f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.tags.base; +import com.jpexs.decompiler.flash.ValueTooLargeException; import java.awt.Font; import java.util.Map; @@ -50,7 +51,6 @@ public class MissingCharacterHandler { if (!f.canDisplay(character)) { return false; } - font.addCharacter(character, f); - return true; + return font.addCharacter(character, f); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index 4ef938445..b657b6713 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -149,7 +149,7 @@ public final class DefineCompactedFont extends FontTag { } @Override - public void addCharacter(char character, Font cfont) { + public boolean addCharacter(char character, Font cfont) { int fontStyle = getFontStyle(); FontType font = fonts.get(0); @@ -217,6 +217,7 @@ public final class DefineCompactedFont extends FontTag { setModified(true); getSwf().clearImageCache(); + return true; } @Override diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index d4756e3ef..34c23df2a 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -4059,9 +4059,7 @@ public class CommandLineArgumentParser { return false; } - font.addCharacter(character, f); - - return true; + return font.addCharacter(character, f); } }, new TextImportErrorHandler() { private String getTextTagInfo(TextTag textTag) { diff --git a/src/com/jpexs/decompiler/flash/gui/FontPanel.java b/src/com/jpexs/decompiler/flash/gui/FontPanel.java index dd65854bc..fb9bdfb54 100644 --- a/src/com/jpexs/decompiler/flash/gui/FontPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FontPanel.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.ValueTooLargeException; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.helpers.TableLayoutHelper; import com.jpexs.decompiler.flash.tags.DefineFontTag; @@ -192,6 +193,7 @@ public class FontPanel extends JPanel implements TagEditorPanel { boolean yestoall = false; boolean notoall = false; boolean replaced = false; + int numAdded = 0; for (int ic : selChars) { char c = (char) ic; if (oldchars.indexOf((int) c) > -1) { @@ -219,7 +221,11 @@ public class FontPanel extends JPanel implements TagEditorPanel { replaced = true; } - f.addCharacter(c, font); + if (!f.addCharacter(c, font)) { + ViewMessages.showMessageDialog(mainPanel,AppStrings.translate("error.font.cannotaddcharacter").replace("%numchars%", "" + numAdded), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + break; + } + numAdded++; oldchars += c; } diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 2dfecd957..53de28950 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -4105,9 +4105,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return false; } - font.addCharacter(character, f); - - return true; + return font.addCharacter(character, f); } }; } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index e2026b2be..497834218 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1147,4 +1147,6 @@ warning.edit.headerframecount = WARNING: Editing frame count in the header does warning.icon = Click to show related warning -button.export = Export \ No newline at end of file +button.export = Export + +error.font.cannotaddcharacter = ERROR: Cannot add more characters to the font.\r\nSuccessfully added characters: %numchars%. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 5ceef3322..9cbcf5bf0 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -1132,4 +1132,7 @@ warning.edit.headerframecount = VAROV\u00c1N\u00cd: Editace po\u010dtu sn\u00edm warning.icon = Klikn\u011bte pro zobrazen\u00ed souvisej\u00edc\u00edho varov\u00e1n\u00ed -button.export = Exportovat \ No newline at end of file +button.export = Exportovat + +error.font.cannotaddcharacter = CHYBA: Do tohoto p\u00edsma nelze ji\u017e p\u0159idat v\u00edce znak\u016f.\r\n\u00dasp\u011b\u0161n\u011b p\u0159idan\u00fdch znak\u016f: %numchars%. +