mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-28 06:46:31 +00:00
better Flash player integration using JavactiveX library
Issue #701 TTF file import/replace - still needs locales, better integration Issue #702 Fixed GFX font export size
This commit is contained in:
Binary file not shown.
BIN
lib/JavactiveX.jar
Normal file
BIN
lib/JavactiveX.jar
Normal file
Binary file not shown.
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.ApplicationInfo;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.RunnableIOEx;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.PathExporter;
|
||||
@@ -108,9 +109,12 @@ public class FontExporter {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public void exportFont(final FontTag t, FontExportMode mode, File file) throws IOException {
|
||||
public void exportFont(FontTag ft, FontExportMode mode, File file) throws IOException {
|
||||
final FontTag t = ft.toClassicFont();
|
||||
List<SHAPE> shapes = t.getGlyphShapeTable();
|
||||
|
||||
final double divider = t.getDivider();
|
||||
|
||||
File ttfFile = file;
|
||||
|
||||
if (mode == FontExportMode.WOFF) {
|
||||
@@ -122,9 +126,10 @@ public class FontExporter {
|
||||
|
||||
f.getEngine().setCopyrightYear(cop == null ? "" : cop);
|
||||
f.setAuthor(ApplicationInfo.shortApplicationVerName);
|
||||
f.setVersion("1.0");
|
||||
f.setAscender(t.getAscent() / t.getDivider());
|
||||
f.setDescender(t.getDescent() / t.getDivider());
|
||||
f.setVersion("1.0");
|
||||
|
||||
f.setAscender(Math.round(t.getAscent() / divider));
|
||||
f.setDescender(Math.round(t.getDescent() / divider));
|
||||
|
||||
for (int i = 0; i < shapes.size(); i++) {
|
||||
SHAPE s = shapes.get(i);
|
||||
@@ -132,11 +137,11 @@ public class FontExporter {
|
||||
PathExporter seb = new PathExporter(s, new ColorTransform()) {
|
||||
|
||||
private double transformX(double x) {
|
||||
return Math.ceil((double) (x / t.getDivider()));
|
||||
return Math.ceil((double) (x / divider));
|
||||
}
|
||||
|
||||
private double transformY(double y) {
|
||||
return -Math.ceil((double) (y / t.getDivider()));
|
||||
return -Math.ceil((double) (y / divider));
|
||||
}
|
||||
|
||||
List<FPoint> path = new ArrayList<>();
|
||||
@@ -178,9 +183,9 @@ public class FontExporter {
|
||||
final FGlyph g = f.addGlyph(c);
|
||||
double adv = t.getGlyphAdvance(i);
|
||||
if (adv != -1) {
|
||||
g.setAdvanceWidth((int) adv);
|
||||
g.setAdvanceWidth((int) Math.round(adv / divider));
|
||||
} else {
|
||||
g.setAdvanceWidth(t.getGlyphWidth(i) / t.getDivider() + 100);
|
||||
g.setAdvanceWidth((int)Math.round(t.getGlyphWidth(i) / divider + 100));
|
||||
}
|
||||
for (FPoint[] cnt : contours) {
|
||||
if (cnt.length == 0) {
|
||||
|
||||
@@ -260,7 +260,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
char firstChar = size.charAt(0);
|
||||
if (firstChar != '+' && firstChar != '-') {
|
||||
int fontSize = Integer.parseInt(size);
|
||||
style.fontHeight = fontSize * (style.font == null ? 1 : style.font.getDivider());
|
||||
style.fontHeight = (int)Math.round(fontSize * (style.font == null ? 1 : style.font.getDivider()));
|
||||
style.fontLeading = leading;
|
||||
} else {
|
||||
// todo: parse relative sizes
|
||||
@@ -824,7 +824,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
kerningAdjustment = font.getGlyphKerningAdjustment(ge.glyphIndex, font.charToGlyph(nextChar));
|
||||
kerningAdjustment /= font.getDivider();
|
||||
}
|
||||
advance = (int) Math.round(font.getDivider() * Math.round((double) lastStyle.fontHeight * (font.getGlyphAdvance(ge.glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0)));
|
||||
advance = (int) Math.round(Math.round((double) lastStyle.fontHeight * (font.getGlyphAdvance(ge.glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0)));
|
||||
} else {
|
||||
String fontName = FontTag.defaultFontName;
|
||||
int fontStyle = font == null ? 0 : font.getFontStyle();
|
||||
|
||||
@@ -97,6 +97,14 @@ public class DefineFont2Tag extends FontTag {
|
||||
return glyphShapeTable.get(glyphIndex).getBounds().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getGlyphBounds(int glyphIndex) {
|
||||
return fontBoundsTable.get(glyphIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double getGlyphAdvance(int glyphIndex) {
|
||||
if (fontFlagsHasLayout) {
|
||||
@@ -340,7 +348,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDivider() {
|
||||
public double getDivider() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -369,10 +377,10 @@ public class DefineFont2Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCharacter(char character, String fontName) {
|
||||
public void addCharacter(char character, Font font) {
|
||||
int fontStyle = getFontStyle();
|
||||
|
||||
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
|
||||
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, fontStyle, (int)Math.round(getDivider() * 1024), character);
|
||||
|
||||
int code = (int) character;
|
||||
int pos = -1;
|
||||
|
||||
@@ -95,7 +95,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
@Override
|
||||
public double getGlyphAdvance(int glyphIndex) {
|
||||
if (fontFlagsHasLayout && glyphIndex != -1) {
|
||||
return fontAdvanceTable.get(glyphIndex) / SWF.unitDivisor;
|
||||
return fontAdvanceTable.get(glyphIndex);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -334,7 +334,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDivider() {
|
||||
public double getDivider() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCharacter(char character, String fontName) {
|
||||
public void 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.tags.size(); i++) {
|
||||
@@ -377,7 +377,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
}
|
||||
int fontStyle = getFontStyle();
|
||||
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
|
||||
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, fontStyle, (int)Math.round(getDivider() * 1024), character);
|
||||
int code = (int) character;
|
||||
int pos = -1;
|
||||
boolean exists = false;
|
||||
@@ -433,6 +433,13 @@ public class DefineFont3Tag extends FontTag {
|
||||
return fontFlagsHasLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getGlyphBounds(int glyphIndex) {
|
||||
return fontBoundsTable.get(glyphIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
|
||||
if (glyphIndex == -1 || nextGlyphIndex == -1) {
|
||||
|
||||
@@ -20,11 +20,13 @@ import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.awt.Font;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -260,13 +262,13 @@ public class DefineFontTag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDivider() {
|
||||
public double getDivider() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCharacter(char character, String fontName) {
|
||||
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character);
|
||||
public void addCharacter(char character, Font font) {
|
||||
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, getFontStyle(), (int)Math.round(getDivider() * 1024), character);
|
||||
List<Integer> codeTable = new ArrayList<>();
|
||||
ensureFontInfo();
|
||||
if (fontInfoTag != null) {
|
||||
@@ -322,4 +324,5 @@ public class DefineFontTag extends FontTag {
|
||||
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ public class DefineText2Tag extends TextTag {
|
||||
if (nextChar != null) {
|
||||
kerningAdjustment = font.getGlyphKerningAdjustment(tr.glyphEntries[i].glyphIndex, font.charToGlyph(nextChar));
|
||||
}
|
||||
advance = (int) Math.round(font.getDivider() * ((double) textHeight * font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0));
|
||||
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment)) / (font.getDivider() * 1024.0));
|
||||
} else {
|
||||
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ public class DefineTextTag extends TextTag {
|
||||
if (nextChar != null) {
|
||||
kerningAdjustment = font.getGlyphKerningAdjustment(tr.glyphEntries[i].glyphIndex, font.charToGlyph(nextChar));
|
||||
}
|
||||
advance = (int) Math.round(font.getDivider() * ((double) textHeight * font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0));
|
||||
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex + kerningAdjustment))) / (font.getDivider() * 1024.0));
|
||||
} else {
|
||||
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
|
||||
}
|
||||
|
||||
@@ -22,18 +22,29 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
|
||||
import com.jpexs.decompiler.flash.helpers.FontHelper;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFontNameTag;
|
||||
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.tags.gfx.DefineCompactedFont;
|
||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.LANGCODE;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.TEXTRECORD;
|
||||
import com.jpexs.decompiler.flash.types.gfx.FontType;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GlyphType;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
@@ -43,11 +54,15 @@ import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.Area;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -65,7 +80,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
|
||||
public abstract List<SHAPE> getGlyphShapeTable();
|
||||
|
||||
public abstract void addCharacter(char character, String fontName);
|
||||
public abstract void addCharacter(char character, Font font);
|
||||
|
||||
public abstract char glyphToChar(int glyphIndex);
|
||||
|
||||
@@ -97,7 +112,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
|
||||
public abstract void setItalic(boolean value);
|
||||
|
||||
public abstract int getDivider();
|
||||
public abstract double getDivider();
|
||||
|
||||
public abstract int getAscent();
|
||||
|
||||
@@ -338,4 +353,16 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
sb.append("\t}\r\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public RECT getGlyphBounds(int glyphIndex) {
|
||||
return getGlyphShapeTable().get(glyphIndex).getBounds();
|
||||
}
|
||||
|
||||
public FontTag toClassicFont() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import java.awt.Font;
|
||||
@@ -32,7 +33,7 @@ public class MissingCharacterHandler {
|
||||
if (!f.canDisplay(character)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
font.addCharacter(character, f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,10 +144,12 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCharacter(char character, String fontName) {
|
||||
public void addCharacter(char character, Font cfont) {
|
||||
int fontStyle = getFontStyle();
|
||||
FontType font = fonts.get(0);
|
||||
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, (int) (SWF.unitDivisor * font.nominalSize), character);
|
||||
|
||||
double d = 1; //1024/font.nominalSize;
|
||||
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, fontStyle, (int) (SWF.unitDivisor * font.nominalSize * d), character);
|
||||
|
||||
int code = (int) character;
|
||||
int pos = -1;
|
||||
@@ -169,7 +171,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
|
||||
shiftGlyphIndices(fontId, pos);
|
||||
}
|
||||
|
||||
Font fnt = new Font(fontName, fontStyle, font.nominalSize);
|
||||
Font fnt = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d));
|
||||
int advance = (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX());
|
||||
if (!exists) {
|
||||
font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0));
|
||||
@@ -278,7 +280,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDivider() {
|
||||
public double getDivider() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -307,17 +309,13 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int resizemultiplier() {
|
||||
FontType ft = fonts.get(0);
|
||||
return (int) Math.round(1024.0 / ft.nominalSize);
|
||||
@Override
|
||||
public RECT getGlyphBounds(int glyphIndex) {
|
||||
GlyphType gt = fonts.get(0).glyphs.get(glyphIndex);
|
||||
return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]));
|
||||
}
|
||||
|
||||
private int resize(int val) {
|
||||
int ret = val * resizemultiplier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SHAPE resize(SHAPE shp) {
|
||||
public SHAPE resizeShape(SHAPE shp) {
|
||||
SHAPE ret = new SHAPE();
|
||||
ret.numFillBits = 1;
|
||||
ret.numLineBits = 0;
|
||||
@@ -350,36 +348,39 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected int resize(double val) {
|
||||
FontType ft = fonts.get(0);
|
||||
return (int) Math.round(val * 1024.0 / ft.nominalSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontTag toClassicFont() {
|
||||
try {
|
||||
DefineFont2Tag ret = new DefineFont2Tag(swf);
|
||||
ret.fontId = fontId;
|
||||
ret.fontId = getFontId();
|
||||
ret.fontFlagsBold = isBold();
|
||||
ret.fontFlagsItalic = isItalic();
|
||||
ret.fontFlagsWideOffsets = true;
|
||||
ret.fontFlagsWideCodes = true;
|
||||
ret.fontFlagsHasLayout = true;
|
||||
FontType ft = fonts.get(0);
|
||||
ret.fontAscent = resize(ft.ascent);
|
||||
ret.fontDescent = resize(ft.descent);
|
||||
ret.fontLeading = resize(ft.leading);
|
||||
ret.fontAscent = (getAscent());
|
||||
ret.fontDescent = (getDescent());
|
||||
ret.fontLeading = (getLeading());
|
||||
ret.fontAdvanceTable = new ArrayList<>();
|
||||
ret.fontBoundsTable = new ArrayList<>();
|
||||
ret.codeTable = new ArrayList<>();
|
||||
ret.glyphShapeTable = new ArrayList<>();
|
||||
ret.numGlyphs = ft.glyphInfo.size();
|
||||
SHAPE shpA = SHAPERECORD.systemFontCharacterToSHAPE("Times New Roman", 0, getDivider() * 1024, 'A');
|
||||
for (GlyphInfoType gi : ft.glyphInfo) {
|
||||
ret.fontAdvanceTable.add(resize(gi.advanceX));
|
||||
ret.codeTable.add(gi.glyphCode);
|
||||
}
|
||||
List<SHAPE> shp = getGlyphShapeTable();
|
||||
ret.numGlyphs = shp.size();
|
||||
for (int g = 0; g < shp.size(); g++) {
|
||||
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
|
||||
ret.codeTable.add((int) glyphToChar(g));
|
||||
|
||||
for (GlyphType gt : ft.glyphs) {
|
||||
SHAPE shpX = resize(gt.toSHAPE());
|
||||
ret.glyphShapeTable.add(shpX); //
|
||||
ret.fontBoundsTable.add(new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3])));
|
||||
SHAPE shpX = resizeShape(shp.get(g));
|
||||
ret.glyphShapeTable.add(shpX);
|
||||
ret.fontBoundsTable.add(getGlyphBounds(g));
|
||||
}
|
||||
ret.fontName = ft.fontName;
|
||||
ret.fontName = getFontName();
|
||||
ret.languageCode = new LANGCODE(1);
|
||||
ret.fontKerningTable = new KERNINGRECORD[0];/*new KERNINGRECORD[ft.kerning.size()];
|
||||
for(int i=0;i<ft.kerning.size();i++){
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.shaperecords;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -233,13 +234,17 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
|
||||
}
|
||||
|
||||
public static SHAPE systemFontCharacterToSHAPE(final String fontName, final int fontStyle, int fontSize, char character) {
|
||||
return fontCharacterToSHAPE(new Font(FontTag.getFontNameWithFallback(fontName),Font.PLAIN,10), fontStyle, fontSize, character);
|
||||
}
|
||||
|
||||
public static SHAPE fontCharacterToSHAPE(final Font font, final int fontStyle, int fontSize, char character) {
|
||||
int multiplier = 1;
|
||||
if (fontSize > 1024) {
|
||||
multiplier = fontSize / 1024;
|
||||
fontSize = 1024;
|
||||
}
|
||||
List<SHAPERECORD> retList = new ArrayList<>();
|
||||
List<SHAPERECORD> retList = new ArrayList<>();
|
||||
Font f = font.deriveFont(fontStyle, fontSize);
|
||||
GlyphVector v = f.createGlyphVector((new JPanel()).getFontMetrics(f).getFontRenderContext(), "" + character);
|
||||
Shape shp = v.getOutline();
|
||||
double[] points = new double[6];
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
|
||||
<compilation-unit>
|
||||
<package-root>src</package-root>
|
||||
<classpath mode="compile">lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/jsyntaxpane-0.9.5.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src</classpath>
|
||||
<classpath mode="compile">lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/jsyntaxpane-0.9.5.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src;lib/JavactiveX.jar</classpath>
|
||||
<built-to>build</built-to>
|
||||
<built-to>javadoc</built-to>
|
||||
<built-to>reports</built-to>
|
||||
|
||||
@@ -41,7 +41,11 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="463" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="importTTFButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="387" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@@ -91,7 +95,11 @@
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="415" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="341" max="32767" attributes="0"/>
|
||||
<Component id="importTTFButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="85" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@@ -583,6 +591,14 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonPreviewFontActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="importTTFButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Import TTF"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importTTFButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
||||
@@ -23,13 +23,25 @@ import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -86,14 +98,14 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
return mainPanel.translate(key);
|
||||
}
|
||||
|
||||
private void fontAddChars(FontTag ft, Set<Integer> selChars, String selFont) {
|
||||
private void fontAddChars(FontTag ft, Set<Integer> selChars, Font font) {
|
||||
FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem();
|
||||
SWF swf = ft.getSwf();
|
||||
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);
|
||||
font = font.deriveFont(f.getFontStyle(), 1024);
|
||||
if (!font.canDisplay(c)) {
|
||||
View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
@@ -129,7 +141,7 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
f.addCharacter(c, fontSelection.getSelectedItem().toString());
|
||||
f.addCharacter(c, font);
|
||||
oldchars += c;
|
||||
}
|
||||
|
||||
@@ -233,6 +245,7 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
buttonSave = new javax.swing.JButton();
|
||||
buttonCancel = new javax.swing.JButton();
|
||||
buttonPreviewFont = new javax.swing.JButton();
|
||||
importTTFButton = new javax.swing.JButton();
|
||||
|
||||
addComponentListener(new java.awt.event.ComponentAdapter() {
|
||||
public void componentResized(java.awt.event.ComponentEvent evt) {
|
||||
@@ -494,11 +507,21 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
importTTFButton.setText("Import TTF");
|
||||
importTTFButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
importTTFButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
|
||||
jPanel2.setLayout(jPanel2Layout);
|
||||
jPanel2Layout.setHorizontalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 463, Short.MAX_VALUE)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(importTTFButton)
|
||||
.addContainerGap(387, Short.MAX_VALUE))
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
@@ -536,7 +559,10 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
);
|
||||
jPanel2Layout.setVerticalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 415, Short.MAX_VALUE)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap(341, Short.MAX_VALUE)
|
||||
.addComponent(importTTFButton)
|
||||
.addGap(85, 85, 85))
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
@@ -588,25 +614,26 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
for (int c = 0; c < newchars.length(); c++) {
|
||||
selChars.add(newchars.codePointAt(c));
|
||||
}
|
||||
fontAddChars((FontTag) item, selChars, fontSelection.getSelectedItem().toString());
|
||||
fontAddChars((FontTag) item, selChars, new Font(fontSelection.getSelectedItem().toString(),Font.PLAIN,12));
|
||||
fontAddCharactersField.setText("");
|
||||
mainPanel.reload(true);
|
||||
}
|
||||
}//GEN-LAST:event_fontAddCharsButtonActionPerformed
|
||||
|
||||
|
||||
|
||||
private void fontEmbedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontEmbedButtonActionPerformed
|
||||
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
|
||||
if (item instanceof FontTag) {
|
||||
FontTag fontTag = (FontTag) item;
|
||||
FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), fontTag.getFontStyle());
|
||||
if (fed.display()) {
|
||||
FontTag ft = (FontTag) item;
|
||||
FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ft.getFontStyle());
|
||||
if (fed.display()) {
|
||||
Set<Integer> selChars = fed.getSelectedChars();
|
||||
if (!selChars.isEmpty()) {
|
||||
String selFont = fed.getSelectedFont();
|
||||
fontSelection.setSelectedItem(selFont);
|
||||
fontAddChars(fontTag, selChars, selFont);
|
||||
fontAddCharactersField.setText("");
|
||||
mainPanel.reload(true);
|
||||
String selFont = fed.getSelectedFont();
|
||||
fontSelection.setSelectedItem(selFont);
|
||||
fontAddChars(ft, selChars, new Font(selFont,Font.PLAIN,10));
|
||||
fontAddCharactersField.setText("");
|
||||
mainPanel.reload(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -651,6 +678,59 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
jPanel1.updateUI();
|
||||
}//GEN-LAST:event_formComponentResized
|
||||
|
||||
private void importTTFButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importTTFButtonActionPerformed
|
||||
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
|
||||
if (item instanceof FontTag) {
|
||||
FontTag ft = (FontTag) item;
|
||||
|
||||
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
|
||||
FileFilter ttfFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "TTF files";
|
||||
}
|
||||
};
|
||||
fc.setFileFilter(ttfFilter);
|
||||
|
||||
fc.setAcceptAllFileFilterUsed(false);
|
||||
JFrame fr = new JFrame();
|
||||
View.setWindowIcon(fr);
|
||||
int returnVal = fc.showOpenDialog(fr);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
|
||||
File selfile = Helper.fixDialogFile(fc.getSelectedFile());
|
||||
Set<Integer> selChars = new HashSet<>();
|
||||
try {
|
||||
Font f = Font.createFont(Font.TRUETYPE_FONT, selfile);
|
||||
int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020};
|
||||
loopi:for(char i=0;i<Character.MAX_VALUE;i++){
|
||||
for(int r:required){
|
||||
if(r==i){
|
||||
continue loopi;
|
||||
}
|
||||
}
|
||||
if(f.canDisplay((int)i)){
|
||||
selChars.add((int)i);
|
||||
}
|
||||
}
|
||||
fontAddChars(ft,selChars, f);
|
||||
mainPanel.reload(true);
|
||||
} catch (FontFormatException ex) {
|
||||
JOptionPane.showMessageDialog(mainPanel, "Invalid TTF font");
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_importTTFButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton buttonCancel;
|
||||
private javax.swing.JButton buttonEdit;
|
||||
@@ -670,6 +750,7 @@ public class FontPanel extends javax.swing.JPanel {
|
||||
private javax.swing.JLabel fontLeadingLabel;
|
||||
private javax.swing.JLabel fontNameLabel;
|
||||
private javax.swing.JComboBox fontSelection;
|
||||
private javax.swing.JButton importTTFButton;
|
||||
private javax.swing.JLabel jLabel11;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
|
||||
@@ -1916,7 +1916,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
|
||||
View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + character), translate("error"), JOptionPane.ERROR_MESSAGE);
|
||||
return false;
|
||||
}
|
||||
font.addCharacter(character, fontName);
|
||||
font.addCharacter(character, f);
|
||||
return true;
|
||||
|
||||
}
|
||||
@@ -2269,7 +2269,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
|
||||
TreeItem tagObj = treeNode.getItem();
|
||||
|
||||
if (flashPanel != null) {
|
||||
flashPanel.specialPlayback = false;
|
||||
//flashPanel.specialPlayback = false;
|
||||
}
|
||||
previewPanel.clear();
|
||||
if (soundThread != null) {
|
||||
|
||||
@@ -781,7 +781,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
|
||||
|
||||
new ShowFrameTag(swf).writeTag(sos2);
|
||||
if (flashPanel != null) {
|
||||
flashPanel.specialPlayback = true;
|
||||
//flashPanel.specialPlayback = true;
|
||||
}
|
||||
} else if (tagObj instanceof DefineVideoStreamTag) {
|
||||
|
||||
|
||||
@@ -17,43 +17,19 @@
|
||||
package com.jpexs.decompiler.flash.gui.player;
|
||||
|
||||
import com.jpexs.decompiler.flash.gui.FlashUnsupportedException;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import com.sun.jna.Native;
|
||||
import com.jpexs.javactivex.ActiveX;
|
||||
import com.jpexs.javactivex.example.controls.flash.ShockwaveFlash;
|
||||
import com.sun.jna.Platform;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.platform.win32.Kernel32;
|
||||
import com.sun.jna.platform.win32.SHELLEXECUTEINFO;
|
||||
import com.sun.jna.platform.win32.Shell32;
|
||||
import com.sun.jna.platform.win32.WinDef;
|
||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
||||
import com.sun.jna.platform.win32.WinUser;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JPopupMenu;
|
||||
import org.pushingpixels.substance.internal.contrib.jgoodies.looks.common.ShadowPopupFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -61,37 +37,10 @@ import org.pushingpixels.substance.internal.contrib.jgoodies.looks.common.Shadow
|
||||
*/
|
||||
public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
|
||||
|
||||
private boolean executed = false;
|
||||
private String flash;
|
||||
private HANDLE pipe;
|
||||
private HANDLE process;
|
||||
private WinDef.HWND hwnd;
|
||||
private WinDef.HWND hwndFrame;
|
||||
private Component frame;
|
||||
private ShockwaveFlash flash;
|
||||
|
||||
private boolean stopped = true;
|
||||
private static final int CMD_PLAY = 1;
|
||||
private static final int CMD_RESIZE = 2;
|
||||
private static final int CMD_BGCOLOR = 3;
|
||||
private static final int CMD_CURRENT_FRAME = 4;
|
||||
private static final int CMD_TOTAL_FRAMES = 5;
|
||||
private static final int CMD_PAUSE = 6;
|
||||
private static final int CMD_RESUME = 7;
|
||||
private static final int CMD_PLAYING = 8;
|
||||
private static final int CMD_REWIND = 9;
|
||||
private static final int CMD_GOTO = 10;
|
||||
private static final int CMD_CALL = 11;
|
||||
private static final int CMD_GETVARIABLE = 12;
|
||||
private static final int CMD_SETVARIABLE = 13;
|
||||
private static final int CMD_CHECKCLICK = 14;
|
||||
private static final int CMD_ZOOM = 15;
|
||||
|
||||
private static final int PIPE_TIMEOUT_MS = 1000;
|
||||
private int frameRate;
|
||||
public boolean specialPlayback = false;
|
||||
private boolean specialPlaying = false;
|
||||
private JPopupMenu rightClickMenu = null;
|
||||
|
||||
private Timer rightClickTimer;
|
||||
|
||||
@Override
|
||||
public boolean screenAvailable() {
|
||||
@@ -113,238 +62,54 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private synchronized int checkClick(Point ret) throws IOException {
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_CHECKCLICK});
|
||||
byte res[] = new byte[1];
|
||||
readFromPipe(res);
|
||||
int button = res[0];
|
||||
if (button > 0) {
|
||||
res = new byte[4];
|
||||
readFromPipe(res);
|
||||
ret.x = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
|
||||
ret.y = ((res[2] & 0xff) << 8) + (res[3] & 0xff);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private double zoom = 1.0;
|
||||
|
||||
@Override
|
||||
public synchronized void zoom(double zoom) {
|
||||
if (pipe != null) {
|
||||
try {
|
||||
long zoomint = Math.round(100 / (zoom / this.zoom));
|
||||
if (zoom == 1.0) {
|
||||
zoomint = 0;
|
||||
}
|
||||
this.zoom = zoom;
|
||||
writeToPipe(new byte[]{CMD_ZOOM});
|
||||
writeToPipe(new byte[]{(byte) ((zoomint >> 8) & 0xff), (byte) (zoomint & 0xff)});
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
int zoomint = (int) Math.round(100 / (zoom / this.zoom));
|
||||
if (zoom == 1.0) {
|
||||
zoomint = 0;
|
||||
}
|
||||
flash.Zoom(zoomint);
|
||||
|
||||
}
|
||||
|
||||
public synchronized String getVariable(String name) throws IOException {
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_GETVARIABLE});
|
||||
int nameLen = name.getBytes().length;
|
||||
writeToPipe(new byte[]{(byte) ((nameLen >> 8) & 0xff), (byte) (nameLen & 0xff)});
|
||||
writeToPipe(name.getBytes());
|
||||
byte res[] = new byte[2];
|
||||
readFromPipe(res);
|
||||
int retLen = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
|
||||
res = new byte[retLen];
|
||||
readFromPipe(res);
|
||||
String ret = new String(res, 0, retLen);
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
return flash.GetVariable(name);
|
||||
}
|
||||
|
||||
public synchronized void setVariable(String name, String value) throws IOException {
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_SETVARIABLE});
|
||||
int nameLen = name.getBytes().length;
|
||||
writeToPipe(new byte[]{(byte) ((nameLen >> 8) & 0xff), (byte) (nameLen & 0xff)});
|
||||
writeToPipe(name.getBytes());
|
||||
|
||||
int valLen = value.getBytes().length;
|
||||
writeToPipe(new byte[]{(byte) ((valLen >> 8) & 0xff), (byte) (valLen & 0xff)});
|
||||
writeToPipe(value.getBytes());
|
||||
}
|
||||
flash.SetVariable(name, value);
|
||||
}
|
||||
|
||||
public synchronized String call(String callString) throws IOException {
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_CALL});
|
||||
int callLen = callString.getBytes().length;
|
||||
writeToPipe(new byte[]{(byte) ((callLen >> 8) & 0xff), (byte) (callLen & 0xff)});
|
||||
writeToPipe(callString.getBytes());
|
||||
|
||||
byte res[] = new byte[2];
|
||||
readFromPipe(res);
|
||||
int retLen = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
|
||||
res = new byte[retLen];
|
||||
readFromPipe(res);
|
||||
String ret = new String(res, 0, retLen);
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized void resize() throws IOException {
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_RESIZE});
|
||||
writeToPipe(new byte[]{
|
||||
(byte) (getWidth() / 256), (byte) (getWidth() % 256),
|
||||
(byte) (getHeight() / 256), (byte) (getHeight() % 256),});
|
||||
}
|
||||
}
|
||||
|
||||
private int __getCurrentFrame() throws IOException {
|
||||
byte[] res = new byte[2];
|
||||
writeToPipe(new byte[]{CMD_CURRENT_FRAME});
|
||||
readFromPipe(res);
|
||||
return ((res[0] & 0xff) << 8) + (res[1] & 0xff);
|
||||
return flash.CallFunction(callString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getCurrentFrame() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
if (!specialPlaying) {
|
||||
return specialPosition;
|
||||
}
|
||||
String posStr = getVariable("_root.my_sound.position");
|
||||
if (posStr != null) {
|
||||
return Integer.parseInt(posStr);
|
||||
}
|
||||
}
|
||||
return __getCurrentFrame();
|
||||
} catch (IOException ex) {
|
||||
return 0;
|
||||
}
|
||||
return flash.getFrameNum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getTotalFrames() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
String durStr = getVariable("_root.my_sound.duration");
|
||||
if (durStr != null) {
|
||||
return Integer.parseInt(durStr);
|
||||
}
|
||||
}
|
||||
byte[] res = new byte[2];
|
||||
writeToPipe(new byte[]{CMD_TOTAL_FRAMES});
|
||||
readFromPipe(res);
|
||||
return ((res[0] & 0xff) << 8) + (res[1] & 0xff);
|
||||
} catch (IOException ex) {
|
||||
return 0;
|
||||
}
|
||||
return flash.getTotalFrames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setBackground(Color color) {
|
||||
try {
|
||||
writeToPipe(new byte[]{CMD_BGCOLOR});
|
||||
writeToPipe(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setRightClickMenu(JPopupMenu menu) {
|
||||
rightClickMenu = menu;
|
||||
flash.setBackgroundColor((color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue());
|
||||
}
|
||||
|
||||
public FlashPlayerPanel(Component frame) {
|
||||
if (!Platform.isWindows()) {
|
||||
throw new FlashUnsupportedException();
|
||||
}
|
||||
this.frame = frame;
|
||||
//this.add(rightClickMenu);
|
||||
addComponentListener(new ComponentListener() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
try {
|
||||
resize();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
componentResized(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized void execute() {
|
||||
if (!executed) {
|
||||
hwnd = new WinDef.HWND();
|
||||
hwnd.setPointer(Native.getComponentPointer(this));
|
||||
|
||||
hwndFrame = new WinDef.HWND();
|
||||
hwndFrame.setPointer(Native.getComponentPointer(frame));
|
||||
|
||||
startFlashPlayer();
|
||||
|
||||
executed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void restartFlashPlayer() {
|
||||
Kernel32.INSTANCE.TerminateProcess(process, 0);
|
||||
Kernel32.INSTANCE.CloseHandle(pipe);
|
||||
startFlashPlayer();
|
||||
}
|
||||
|
||||
private void startFlashPlayer() {
|
||||
String path = Utf8Helper.urlDecode(FlashPlayerPanel.class.getProtectionDomain().getCodeSource().getLocation().getPath());
|
||||
String appDir = new File(path).getParentFile().getAbsolutePath();
|
||||
if (!appDir.endsWith("\\")) {
|
||||
appDir += "\\";
|
||||
}
|
||||
String exePath = appDir + "lib\\FlashPlayer.exe";
|
||||
File f = new File(exePath);
|
||||
if (!f.exists()) {
|
||||
Logger.getLogger(FlashPlayerPanel.class.getName()).log(Level.SEVERE, "FlashPlayer.exe not found: " + f.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
String pipeName = "\\\\.\\pipe\\ffdec_flashplayer_" + hwnd.getPointer().hashCode();
|
||||
pipe = Kernel32.INSTANCE.CreateNamedPipe(pipeName, Kernel32.PIPE_ACCESS_DUPLEX, Kernel32.PIPE_TYPE_BYTE, 1, 4096, 4096, 0, null);
|
||||
|
||||
SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO();
|
||||
sei.fMask = 0x00000040;
|
||||
sei.lpFile = new WString(exePath);
|
||||
sei.lpParameters = new WString(hwnd.getPointer().hashCode() + " " + hwndFrame.getPointer().hashCode());
|
||||
sei.nShow = WinUser.SW_NORMAL;
|
||||
Shell32.INSTANCE.ShellExecuteEx(sei);
|
||||
process = sei.hProcess;
|
||||
|
||||
Kernel32.INSTANCE.ConnectNamedPipe(pipe, null);
|
||||
flash = ActiveX.createObject(ShockwaveFlash.class, this);
|
||||
}
|
||||
|
||||
public synchronized void stopSWF() {
|
||||
if (rightClickTimer != null) {
|
||||
rightClickTimer.cancel();
|
||||
rightClickTimer = null;
|
||||
}
|
||||
displaySWF("-", null, 1);
|
||||
stopped = true;
|
||||
}
|
||||
@@ -363,183 +128,51 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void displaySWF(String flash, Color bgColor, int frameRate) {
|
||||
try {
|
||||
zoom = 1.0;
|
||||
this.flash = flash;
|
||||
repaint();
|
||||
this.frameRate = frameRate;
|
||||
execute();
|
||||
if (bgColor != null) {
|
||||
setBackground(bgColor);
|
||||
}
|
||||
resize();
|
||||
if (pipe != null) {
|
||||
writeToPipe(new byte[]{CMD_PLAY});
|
||||
writeToPipe(new byte[]{(byte) flash.getBytes().length});
|
||||
writeToPipe(flash.getBytes());
|
||||
}
|
||||
stopped = false;
|
||||
specialPlaying = false;
|
||||
specialPosition = 0;
|
||||
if (specialPlayback) {
|
||||
play();
|
||||
}
|
||||
if (rightClickTimer != null) {
|
||||
rightClickTimer.cancel();
|
||||
}
|
||||
rightClickTimer = new Timer();
|
||||
rightClickTimer.schedule(new TimerTask() {
|
||||
public synchronized void displaySWF(String flashName, Color bgColor, int frameRate) {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final Point pt = new Point();
|
||||
final int button = checkClick(pt);
|
||||
View.execInEventDispatch(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (rightClickMenu != null) {
|
||||
if (button == 2) {
|
||||
ShadowPopupFactory.uninstall();
|
||||
rightClickMenu.show(FlashPlayerPanel.this, pt.x, pt.y);
|
||||
ShadowPopupFactory.install();
|
||||
}
|
||||
if (button == 1) {
|
||||
rightClickMenu.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}, 100, 100);
|
||||
} catch (IOException ex) {
|
||||
zoom = 1.0;
|
||||
//this.frameRate = frameRate;
|
||||
if (bgColor != null) {
|
||||
setBackground(bgColor);
|
||||
}
|
||||
flash.setMovie(flashName);
|
||||
//play
|
||||
stopped = false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (rightClickTimer != null) {
|
||||
rightClickTimer.cancel();
|
||||
rightClickTimer = null;
|
||||
}
|
||||
Kernel32.INSTANCE.CloseHandle(pipe);
|
||||
Kernel32.INSTANCE.TerminateProcess(process, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if (flash != null) {
|
||||
execute();
|
||||
}
|
||||
super.paint(g);
|
||||
}
|
||||
private int specialPosition = 0;
|
||||
|
||||
private synchronized void __pause() throws IOException {
|
||||
writeToPipe(new byte[]{CMD_PAUSE});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
specialPosition = getCurrentFrame();
|
||||
__gotoFrame(3);
|
||||
__play();
|
||||
specialPlaying = false;
|
||||
return;
|
||||
}
|
||||
__pause();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
flash.Stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rewind() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
boolean plays = specialPlaying;
|
||||
pause();
|
||||
specialPosition = 0;
|
||||
if (plays) {
|
||||
play();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
writeToPipe(new byte[]{CMD_REWIND});
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void __play() throws IOException {
|
||||
writeToPipe(new byte[]{CMD_RESUME});
|
||||
flash.Rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
double p = (((double) specialPosition) / 1000.0);
|
||||
setVariable("_root.execParam", "" + p);
|
||||
__gotoFrame(1);
|
||||
__play();
|
||||
specialPlaying = true;
|
||||
return;
|
||||
}
|
||||
__play();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
flash.Play();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
return specialPlaying;
|
||||
}
|
||||
writeToPipe(new byte[]{CMD_PLAYING});
|
||||
byte[] res = new byte[1];
|
||||
readFromPipe(res);
|
||||
return res[0] == 1;
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void __gotoFrame(int frame) throws IOException {
|
||||
writeToPipe(new byte[]{CMD_GOTO});
|
||||
writeToPipe(new byte[]{(byte) ((frame >> 8) & 0xff), (byte) (frame & 0xff)});
|
||||
return flash.IsPlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoFrame(int frame) {
|
||||
try {
|
||||
if (specialPlayback) {
|
||||
if (specialPlaying) {
|
||||
pause();
|
||||
specialPosition = frame;
|
||||
play();
|
||||
} else {
|
||||
specialPosition = frame;
|
||||
}
|
||||
return;
|
||||
}
|
||||
__gotoFrame(frame);
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
flash.GotoFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFrameRate() {
|
||||
if (specialPlayback) {
|
||||
return 1000;
|
||||
}
|
||||
return frameRate;
|
||||
}
|
||||
|
||||
@@ -548,69 +181,4 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
|
||||
return !isStopped();
|
||||
}
|
||||
|
||||
private synchronized boolean writeToPipe(final byte[] data) throws IOException {
|
||||
final IntByReference ibr = new IntByReference();
|
||||
int result = -1;
|
||||
try {
|
||||
result = CancellableWorker.call(new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
boolean result = Kernel32.INSTANCE.WriteFile(pipe, data, data.length, ibr, null);
|
||||
if (!result) {
|
||||
return Kernel32.INSTANCE.GetLastError();
|
||||
}
|
||||
if (ibr.getValue() != data.length) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}, PIPE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
|
||||
// ignore
|
||||
}
|
||||
if (result != 0) {
|
||||
if (result == Kernel32.ERROR_NO_DATA || result == -1) {
|
||||
restartFlashPlayer();
|
||||
throw new IOException("Pipe write error.");
|
||||
} else {
|
||||
// System.out.println("pipe write failed. datalength: " + data.length + " error:" + result);
|
||||
}
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
private synchronized boolean readFromPipe(final byte[] res) throws IOException {
|
||||
final IntByReference ibr = new IntByReference();
|
||||
int result = -1;
|
||||
try {
|
||||
result = CancellableWorker.call(new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
int read = 0;
|
||||
while (read < res.length) {
|
||||
byte[] data = new byte[res.length - read];
|
||||
boolean result = Kernel32.INSTANCE.ReadFile(pipe, data, data.length, ibr, null);
|
||||
if (!result) {
|
||||
return Kernel32.INSTANCE.GetLastError();
|
||||
}
|
||||
int readNow = ibr.getValue();
|
||||
System.arraycopy(data, 0, res, read, readNow);
|
||||
read += readNow;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}, PIPE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
|
||||
// ignore
|
||||
}
|
||||
if (result != 0) {
|
||||
if (result == Kernel32.ERROR_BROKEN_PIPE || result == -1) {
|
||||
restartFlashPlayer();
|
||||
throw new IOException("Pipe read error.");
|
||||
} else {
|
||||
// System.out.println("pipe read failed. result: " + result + " datalength: " + res.length + " received: " + ibr.getValue() + " error: " + result);
|
||||
}
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user