mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 07:28:09 +00:00
GFx fonts: Adding characters
GFx fonts: Displaying text fields Fonts display in internal viewer
This commit is contained in:
@@ -292,6 +292,10 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
private JComboBox<String> fontSelection;
|
||||
private JCommandButton saveCommandButton;
|
||||
private PlayerControls flashControls;
|
||||
private ImagePanel internelViewerPanel;
|
||||
private JPanel viewerCards;
|
||||
public static final String FLASH_VIEWER_CARD = "FLASHVIEWER";
|
||||
public static final String INTERNAL_VIEWER_CARD = "INTERNALVIEWER";
|
||||
private Map<Integer, String> sourceFontsMap = new HashMap<>();
|
||||
private AbortRetryIgnoreHandler errorHandler = new AbortRetryIgnoreHandler() {
|
||||
@Override
|
||||
@@ -1273,7 +1277,19 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
paramsLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
//paramsLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
pan.add(prevLabel, BorderLayout.NORTH);
|
||||
pan.add(leftComponent, BorderLayout.CENTER);
|
||||
|
||||
viewerCards = new JPanel();
|
||||
viewerCards.setLayout(new CardLayout());
|
||||
//viewerCards.add(leftComponent,FLASH_VIEWER_CARD);
|
||||
|
||||
internelViewerPanel = new ImagePanel();
|
||||
JPanel ivPanel = new JPanel(new BorderLayout());
|
||||
ivPanel.add(new HeaderLabel(translate("swfpreview.internal")), BorderLayout.NORTH);
|
||||
ivPanel.add(internelViewerPanel, BorderLayout.CENTER);
|
||||
viewerCards.add(ivPanel, INTERNAL_VIEWER_CARD);
|
||||
|
||||
((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD);
|
||||
|
||||
if (flashPanel != null) {
|
||||
JPanel bottomPanel = new JPanel(new BorderLayout());
|
||||
JPanel buttonsPanel = new JPanel(new FlowLayout());
|
||||
@@ -1285,7 +1301,9 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
bottomPanel.add(buttonsPanel, BorderLayout.EAST);
|
||||
pan.add(bottomPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
previewSplitPane.setLeftComponent(pan);
|
||||
pan.add(leftComponent, BorderLayout.CENTER);
|
||||
viewerCards.add(pan, FLASH_VIEWER_CARD);
|
||||
previewSplitPane.setLeftComponent(viewerCards);
|
||||
|
||||
parametersPanel = new JPanel(new BorderLayout());
|
||||
parametersPanel.add(paramsLabel, BorderLayout.NORTH);
|
||||
@@ -2941,6 +2959,13 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
}
|
||||
}
|
||||
|
||||
private static Tag classicTag(Tag t) {
|
||||
if (t instanceof GFxDefineCompactedFont) {
|
||||
return ((GFxDefineCompactedFont) t).toClassicFont();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public void reload(boolean forceReload) {
|
||||
Object tagObj = tagTree.getLastSelectedPathComponent();
|
||||
if (tagObj == null) {
|
||||
@@ -3047,9 +3072,13 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
imageButtonsPanel.setVisible(((ImageTag) tagObj).importSupported());
|
||||
showCard(CARDIMAGEPANEL);
|
||||
imagePanel.setImage(((ImageTag) tagObj).getImage(swf.tags));
|
||||
} else if ((tagObj instanceof DrawableTag) && (!(tagObj instanceof TextTag)) && (miInternalViewer.isSelected())) {
|
||||
} else if ((tagObj instanceof DrawableTag) && (!(tagObj instanceof TextTag)) && (!(tagObj instanceof FontTag)) && (miInternalViewer.isSelected())) {
|
||||
showCard(CARDDRAWPREVIEWPANEL);
|
||||
previewImagePanel.setDrawable((DrawableTag) tagObj, swf, characters, 50/*FIXME*/);
|
||||
} else if ((tagObj instanceof FontTag) && (miInternalViewer.isSelected() || (tagObj instanceof GFxDefineCompactedFont))) {
|
||||
showCard(CARDFLASHPANEL);
|
||||
previewImagePanel.setDrawable((DrawableTag) tagObj, swf, characters, 50/*FIXME*/);
|
||||
showFontTag((FontTag) tagObj);
|
||||
} else if (tagObj instanceof FrameNode && ((FrameNode) tagObj).isDisplayed() && (miInternalViewer.isSelected())) {
|
||||
showCard(CARDDRAWPREVIEWPANEL);
|
||||
FrameNode fn = (FrameNode) tagObj;
|
||||
@@ -3065,6 +3094,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
}
|
||||
previewImagePanel.setImage(SWF.frameToImage(containerId, ((FrameNode) tagObj).getFrame() - 1, swf.tags, controlTags, rect, totalFrameCount, new Stack<Integer>()));
|
||||
} else if (((tagObj instanceof FrameNode) && ((FrameNode) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) {
|
||||
((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD);
|
||||
try {
|
||||
|
||||
if (tempFile != null) {
|
||||
@@ -3158,14 +3188,14 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
Set<Integer> needed = t.getDeepNeededCharacters(characters, new ArrayList<Integer>());
|
||||
for (int n : needed) {
|
||||
if (!doneCharacters.contains(n)) {
|
||||
sos2.writeTag(characters.get(n));
|
||||
sos2.writeTag(classicTag(characters.get(n)));
|
||||
doneCharacters.add(n);
|
||||
}
|
||||
}
|
||||
if (t instanceof CharacterTag) {
|
||||
doneCharacters.add(((CharacterTag) t).getCharacterId());
|
||||
}
|
||||
sos2.writeTag(t);
|
||||
sos2.writeTag(classicTag(t));
|
||||
|
||||
if (parent != null) {
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
@@ -3201,11 +3231,11 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
} else {
|
||||
Set<Integer> needed = ((Tag) tagObj).getDeepNeededCharacters(characters, new ArrayList<Integer>());
|
||||
for (int n : needed) {
|
||||
sos2.writeTag(characters.get(n));
|
||||
sos2.writeTag(classicTag(characters.get(n)));
|
||||
}
|
||||
}
|
||||
|
||||
sos2.writeTag(((Tag) tagObj));
|
||||
sos2.writeTag(classicTag((Tag) tagObj));
|
||||
|
||||
int chtId = 0;
|
||||
if (tagObj instanceof CharacterTag) {
|
||||
@@ -3441,24 +3471,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
showDetailWithPreview(CARDTEXTPANEL);
|
||||
textValue.setText(((TextTag) tagObj).getFormattedText(swf.tags));
|
||||
} else if (tagObj instanceof FontTag) {
|
||||
parametersPanel.setVisible(true);
|
||||
previewSplitPane.setDividerLocation(previewSplitPane.getWidth() / 2);
|
||||
FontTag ft = (FontTag) tagObj;
|
||||
fontNameLabel.setText(ft.getFontName(swf.tags));
|
||||
fontIsBoldLabel.setText(ft.isBold() ? translate("yes") : translate("no"));
|
||||
fontIsItalicLabel.setText(ft.isItalic() ? translate("yes") : translate("no"));
|
||||
fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent());
|
||||
fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent());
|
||||
fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading());
|
||||
String chars = ft.getCharacters(swf.tags);
|
||||
fontCharactersTextArea.setText(chars);
|
||||
if (sourceFontsMap.containsKey(ft.getFontId())) {
|
||||
fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId()));
|
||||
} else {
|
||||
fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName(swf.tags)));
|
||||
}
|
||||
fontChangeList.componentResized(null);
|
||||
showDetailWithPreview(CARDFONTPANEL);
|
||||
showFontTag((FontTag) tagObj);
|
||||
} else {
|
||||
parametersPanel.setVisible(false);
|
||||
}
|
||||
@@ -3468,6 +3481,33 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
}
|
||||
}
|
||||
|
||||
private void showFontTag(FontTag ft) {
|
||||
if (miInternalViewer.isSelected() || ft instanceof GFxDefineCompactedFont) {
|
||||
((CardLayout) viewerCards.getLayout()).show(viewerCards, INTERNAL_VIEWER_CARD);
|
||||
internelViewerPanel.setDrawable(ft, swf, characters, 1);
|
||||
} else {
|
||||
((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD);
|
||||
}
|
||||
|
||||
parametersPanel.setVisible(true);
|
||||
previewSplitPane.setDividerLocation(previewSplitPane.getWidth() / 2);
|
||||
fontNameLabel.setText(ft.getFontName(swf.tags));
|
||||
fontIsBoldLabel.setText(ft.isBold() ? translate("yes") : translate("no"));
|
||||
fontIsItalicLabel.setText(ft.isItalic() ? translate("yes") : translate("no"));
|
||||
fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent());
|
||||
fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent());
|
||||
fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading());
|
||||
String chars = ft.getCharacters(swf.tags);
|
||||
fontCharactersTextArea.setText(chars);
|
||||
if (sourceFontsMap.containsKey(ft.getFontId())) {
|
||||
fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId()));
|
||||
} else {
|
||||
fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName(swf.tags)));
|
||||
}
|
||||
fontChangeList.componentResized(null);
|
||||
showDetailWithPreview(CARDFONTPANEL);
|
||||
}
|
||||
|
||||
public void refreshTree() {
|
||||
List<ContainerItem> objs = new ArrayList<>();
|
||||
objs.addAll(swf.tags);
|
||||
|
||||
@@ -161,6 +161,10 @@ public class DefineFont2Tag extends FontTag {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public DefineFont2Tag(SWF swf) throws IOException {
|
||||
super(swf, ID, "DefineFont2", new byte[0], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
||||
@@ -18,29 +18,47 @@ 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.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
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.gfx.FontType;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GFxInputStream;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GlyphType;
|
||||
import com.jpexs.decompiler.flash.types.gfx.KerningPairType;
|
||||
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.Helper;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag {
|
||||
public class GFxDefineCompactedFont extends FontTag implements DrawableTag {
|
||||
|
||||
public static final int ID = 1005;
|
||||
public int fontId;
|
||||
@@ -54,15 +72,17 @@ public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag
|
||||
*/
|
||||
@Override
|
||||
public byte[] getData(int version) {
|
||||
return super.getData(version);
|
||||
/*ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
OutputStream os = baos;
|
||||
SWFOutputStream sos = new SWFOutputStream(os, version);
|
||||
try {
|
||||
//sos.write
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return baos.toByteArray();*/
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
OutputStream os = baos;
|
||||
SWFOutputStream sos = new SWFOutputStream(os, version);
|
||||
try {
|
||||
sos.writeUI16(fontId);
|
||||
for (FontType ft : fonts) {
|
||||
ft.write(new GFxOutputStream(sos));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +112,9 @@ public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag
|
||||
for (FontType f : fonts) {
|
||||
shapes.addAll(f.getGlyphShapes());
|
||||
}
|
||||
for (int i = 0; i < shapes.size(); i++) {
|
||||
shapes.set(i, SHAPERECORD.resizeSHAPE(shapes.get(i), 20));
|
||||
}
|
||||
return SHAPERECORD.shapeListToImage(shapes, 500, 500, Color.black);
|
||||
}
|
||||
|
||||
@@ -105,6 +128,7 @@ public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFontName(List<Tag> tags) {
|
||||
String ret = "";
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
@@ -116,18 +140,217 @@ public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(List<Tag> tags) {
|
||||
String nameAppend = "";
|
||||
String fontName = getFontName(tags);
|
||||
if (fontName != null) {
|
||||
nameAppend = ": " + fontName;
|
||||
}
|
||||
return name + " (" + getCharacterId() + nameAppend + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFontId() {
|
||||
return fontId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SHAPE> getGlyphShapeTable() {
|
||||
return fonts.get(0).getGlyphShapes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCharacter(List<Tag> tags, char character, String fontName) {
|
||||
int fontStyle = getFontStyle();
|
||||
FontType font = fonts.get(0);
|
||||
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, 20 * font.nominalSize, character);
|
||||
|
||||
|
||||
int code = (int) character;
|
||||
int pos = -1;
|
||||
for (int i = 0; i < font.glyphInfo.size(); i++) {
|
||||
if (font.glyphInfo.get(i).glyphCode > code) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos == -1) {
|
||||
pos = font.glyphInfo.size();
|
||||
}
|
||||
|
||||
FontTag.shiftGlyphIndices(fontId, pos, tags);
|
||||
|
||||
Font fnt = new Font(fontName, fontStyle, 20 * font.nominalSize);
|
||||
int advance = (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX());
|
||||
font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0));
|
||||
font.glyphs.add(pos, new GlyphType(shp.shapeRecords));
|
||||
}
|
||||
|
||||
@Override
|
||||
public char glyphToChar(List<Tag> tags, int glyphIndex) {
|
||||
return (char) fonts.get(0).glyphInfo.get(glyphIndex).glyphCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int charToGlyph(List<Tag> tags, char c) {
|
||||
FontType ft = fonts.get(0);
|
||||
for (int i = 0; i < ft.glyphInfo.size(); i++) {
|
||||
if (ft.glyphInfo.get(i).glyphCode == c) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGlyphAdvance(int glyphIndex) {
|
||||
return fonts.get(0).glyphInfo.get(glyphIndex).advanceX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGlyphKerningAdjustment(List<Tag> tags, int glyphIndex, int nextGlyphIndex) {
|
||||
int char1 = glyphToChar(tags, glyphIndex);
|
||||
int char2 = glyphToChar(tags, nextGlyphIndex);
|
||||
for (KerningPairType kp : fonts.get(0).kerning) {
|
||||
if (kp.char1 == char1 && kp.char2 == char2) {
|
||||
return kp.advance;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGlyphWidth(int glyphIndex) {
|
||||
return getGlyphShapeTable().get(glyphIndex).getBounds().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSmall() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBold() {
|
||||
return (fonts.get(0).flags & FontType.FF_Bold) == FontType.FF_Bold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItalic() {
|
||||
return (fonts.get(0).flags & FontType.FF_Italic) == FontType.FF_Italic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDivider() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAscent() {
|
||||
return fonts.get(0).ascent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDescent() {
|
||||
return fonts.get(0).descent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLeading() {
|
||||
return fonts.get(0).leading;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacters(List<Tag> tags) {
|
||||
FontType ft = fonts.get(0);
|
||||
String ret = "";
|
||||
for (GlyphInfoType gi : ft.glyphInfo) {
|
||||
ret += (char) gi.glyphCode;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int resizemultiplier() {
|
||||
FontType ft = fonts.get(0);
|
||||
return (int) Math.round(1024.0 / ft.nominalSize);
|
||||
}
|
||||
|
||||
private int resize(int val) {
|
||||
int ret = val * resizemultiplier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SHAPE resize(SHAPE shp) {
|
||||
SHAPE ret = new SHAPE();
|
||||
ret.numFillBits = 1;
|
||||
ret.numLineBits = 0;
|
||||
List<SHAPERECORD> recs = new ArrayList<>();
|
||||
for (SHAPERECORD r : shp.shapeRecords) {
|
||||
SHAPERECORD c = (SHAPERECORD) Helper.deepCopy(r);
|
||||
if (c instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr = (StyleChangeRecord) c;
|
||||
scr.moveDeltaX = resize(scr.moveDeltaX);
|
||||
scr.moveDeltaY = resize(scr.moveDeltaY);
|
||||
scr.calculateBits();
|
||||
}
|
||||
if (c instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer = (CurvedEdgeRecord) c;
|
||||
cer.controlDeltaX = resize(cer.controlDeltaX);
|
||||
cer.controlDeltaY = resize(cer.controlDeltaY);
|
||||
cer.anchorDeltaX = resize(cer.anchorDeltaX);
|
||||
cer.anchorDeltaY = resize(cer.anchorDeltaY);
|
||||
cer.calculateBits();
|
||||
}
|
||||
if (c instanceof StraightEdgeRecord) {
|
||||
StraightEdgeRecord ser = (StraightEdgeRecord) c;
|
||||
ser.deltaX = resize(ser.deltaX);
|
||||
ser.deltaY = resize(ser.deltaY);
|
||||
ser.calculateBits();
|
||||
}
|
||||
recs.add(c);
|
||||
}
|
||||
ret.shapeRecords = recs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public FontTag toClassicFont() {
|
||||
try {
|
||||
DefineFont2Tag ret = new DefineFont2Tag(swf);
|
||||
ret.fontId = fontId;
|
||||
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.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);
|
||||
}
|
||||
|
||||
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])));
|
||||
}
|
||||
ret.fontName = ft.fontName;
|
||||
ret.languageCode = new LANGCODE(1);
|
||||
ret.fontKerningTable = new KERNINGRECORD[0];/*new KERNINGRECORD[ft.kerning.size()];
|
||||
for(int i=0;i<ft.kerning.size();i++){
|
||||
KERNINGRECORD kr=new KERNINGRECORD();
|
||||
kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance);
|
||||
kr.fontKerningCode1 = ft.kerning.get(i).char1;
|
||||
kr.fontKerningCode2 = ft.kerning.get(i).char2;
|
||||
ret.fontKerningTable[i] = kr;
|
||||
}*/
|
||||
return ret;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(GFxDefineCompactedFont.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.gfx.FONTINFO;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GFxInputStream;
|
||||
import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.gfx.TEXGLYPH;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -71,11 +72,11 @@ public class GFxFontTextureInfo extends Tag {
|
||||
sos.writeUI16(nominalGlyphSz);
|
||||
sos.writeUI16(texGlyphs.length);
|
||||
for (int i = 0; i < texGlyphs.length; i++) {
|
||||
texGlyphs[i].write(sos);
|
||||
texGlyphs[i].write(new GFxOutputStream(sos));
|
||||
}
|
||||
sos.writeUI16(fonts.length);
|
||||
for (int i = 0; i < fonts.length; i++) {
|
||||
fonts[i].write(sos);
|
||||
fonts[i].write(new GFxOutputStream(sos));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
@@ -21,22 +21,29 @@ 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.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.TEXTRECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Point;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class FontTag extends CharacterTag implements AloneTag {
|
||||
public abstract class FontTag extends CharacterTag implements AloneTag, DrawableTag {
|
||||
|
||||
public FontTag(SWF swf, int id, String name, byte[] data, long pos) {
|
||||
super(swf, id, name, data, pos);
|
||||
@@ -184,4 +191,19 @@ public abstract class FontTag extends CharacterTag implements AloneTag {
|
||||
}
|
||||
return fontNames.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage toImage(int frame, List<Tag> tags, RECT displayRect, HashMap<Integer, CharacterTag> characters, Stack<Integer> visited) {
|
||||
return SHAPERECORD.shapeListToImage(getGlyphShapeTable(), 500, 500, Color.black);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getImagePos(int frame, HashMap<Integer, CharacterTag> characters, Stack<Integer> visited) {
|
||||
return new Point(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,11 @@ package com.jpexs.decompiler.flash.types;
|
||||
public class LANGCODE {
|
||||
|
||||
public int languageCode;
|
||||
|
||||
public LANGCODE() {
|
||||
}
|
||||
|
||||
public LANGCODE(int languageCode) {
|
||||
this.languageCode = languageCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
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 java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -35,6 +36,39 @@ public class ContourType {
|
||||
public boolean isReference;
|
||||
public long reference;
|
||||
|
||||
public ContourType(List<SHAPERECORD> records) {
|
||||
int i = 0;
|
||||
int divider = 20;
|
||||
for (; i < records.size(); i++) {
|
||||
if (records.get(i) instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr = (StyleChangeRecord) records.get(i);
|
||||
if (scr.stateMoveTo) {
|
||||
moveToX = scr.moveDeltaX / divider;
|
||||
moveToY = scr.moveDeltaY / divider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<EdgeType> edgesList = new ArrayList<>();
|
||||
for (; i < records.size(); i++) {
|
||||
SHAPERECORD rec = records.get(i);
|
||||
if (rec instanceof StraightEdgeRecord) {
|
||||
StraightEdgeRecord ser = (StraightEdgeRecord) rec;
|
||||
if (ser.generalLineFlag) {
|
||||
edgesList.add(new EdgeType(ser.deltaX / divider, ser.deltaY / divider));
|
||||
} else if (ser.vertLineFlag) {
|
||||
edgesList.add(new EdgeType(true, ser.deltaY / divider));
|
||||
} else {
|
||||
edgesList.add(new EdgeType(false, ser.deltaX / divider));
|
||||
}
|
||||
} else if (rec instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer = (CurvedEdgeRecord) rec;
|
||||
edgesList.add(new EdgeType(cer.controlDeltaX / divider, cer.controlDeltaY / divider, cer.anchorDeltaX / divider, cer.anchorDeltaY / divider));
|
||||
}
|
||||
}
|
||||
edges = edgesList.toArray(new EdgeType[edgesList.size()]);
|
||||
}
|
||||
|
||||
public ContourType(GFxInputStream sis) throws IOException {
|
||||
moveToX = sis.readSI15();
|
||||
moveToY = sis.readSI15();
|
||||
@@ -59,19 +93,39 @@ public class ContourType {
|
||||
}
|
||||
|
||||
public List<SHAPERECORD> toSHAPERECORDS() {
|
||||
int multiplier = 20;
|
||||
int multiplier = 1;
|
||||
List<SHAPERECORD> recs = new ArrayList<>();
|
||||
StyleChangeRecord src = new StyleChangeRecord();
|
||||
src.stateMoveTo = true;
|
||||
src.moveDeltaX = moveToX * multiplier;
|
||||
src.moveDeltaY = moveToY * multiplier;
|
||||
src.calculateBits();
|
||||
recs.add(src);
|
||||
for (EdgeType e : edges) {
|
||||
recs.add(e.toSHAPERECORD());
|
||||
}
|
||||
int x = src.moveDeltaX;
|
||||
int y = src.moveDeltaY;
|
||||
for (SHAPERECORD rec : recs) {
|
||||
x = rec.changeX(x);
|
||||
y = rec.changeY(y);
|
||||
}
|
||||
StraightEdgeRecord closeSer = new StraightEdgeRecord();
|
||||
closeSer.generalLineFlag = true;
|
||||
closeSer.deltaX = (src.moveDeltaX - x);
|
||||
closeSer.deltaY = (src.moveDeltaY - y);
|
||||
closeSer.calculateBits();
|
||||
recs.add(closeSer);
|
||||
|
||||
return recs;
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeSI15(moveToX);
|
||||
sos.writeSI15(moveToY);
|
||||
sos.writeUI30(edges.length << 1);
|
||||
for (int i = 0; i < edges.length; i++) {
|
||||
edges[i].write(sos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
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 java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -52,6 +54,32 @@ public class EdgeType {
|
||||
public int data[];
|
||||
public byte raw[];
|
||||
|
||||
public EdgeType(boolean vertical, int v) {
|
||||
data = new int[]{vertical ? Edge_VLine : Edge_HLine, v};
|
||||
calcRaw();
|
||||
}
|
||||
|
||||
public EdgeType(int x, int y) {
|
||||
data = new int[]{Edge_Line, x, y};
|
||||
calcRaw();
|
||||
}
|
||||
|
||||
public EdgeType(int cx, int cy, int ax, int ay) {
|
||||
data = new int[]{Edge_Quad, cx, cy, ax, ay};
|
||||
calcRaw();
|
||||
}
|
||||
|
||||
private void calcRaw() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
GFxOutputStream sos = new GFxOutputStream(baos);
|
||||
try {
|
||||
write(sos);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(EdgeType.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
raw = baos.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String ret = "[Edge " + (raw[0] & 0xf) + " data:";
|
||||
@@ -114,7 +142,7 @@ public class EdgeType {
|
||||
}
|
||||
|
||||
public SHAPERECORD toSHAPERECORD() {
|
||||
int multiplier = 20;
|
||||
int multiplier = 1;
|
||||
StraightEdgeRecord ser;
|
||||
CurvedEdgeRecord cer;
|
||||
switch (data[0]) {
|
||||
@@ -122,18 +150,21 @@ public class EdgeType {
|
||||
ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = false;
|
||||
ser.deltaX = data[1] * multiplier;
|
||||
ser.calculateBits();
|
||||
return ser;
|
||||
case Edge_VLine:
|
||||
ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = false;
|
||||
ser.vertLineFlag = true;
|
||||
ser.deltaY = data[1] * multiplier;
|
||||
ser.calculateBits();
|
||||
return ser;
|
||||
case Edge_Line:
|
||||
ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = true;
|
||||
ser.deltaX = data[1] * multiplier;
|
||||
ser.deltaY = data[2] * multiplier;
|
||||
ser.calculateBits();
|
||||
return ser;
|
||||
case Edge_Quad:
|
||||
cer = new CurvedEdgeRecord();
|
||||
@@ -141,6 +172,7 @@ public class EdgeType {
|
||||
cer.controlDeltaY = data[2] * multiplier;
|
||||
cer.anchorDeltaX = data[3] * multiplier;
|
||||
cer.anchorDeltaY = data[4] * multiplier;
|
||||
cer.calculateBits();
|
||||
return cer;
|
||||
}
|
||||
return null;
|
||||
@@ -262,6 +294,168 @@ public class EdgeType {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
int x;
|
||||
int y;
|
||||
int m1 = 1;
|
||||
int m2 = 3;
|
||||
int m3 = 7;
|
||||
int m4 = 0xF;
|
||||
int m5 = 0x1F;
|
||||
int m6 = 0x3F;
|
||||
int m7 = 0x7F;
|
||||
switch (data[0]) {
|
||||
case Edge_HLine:
|
||||
x = data[1];
|
||||
if (x >= GFxOutputStream.MinSInt12 && x <= GFxOutputStream.MaxSInt12) {
|
||||
sos.writeUI8((x << 4) | Edge_H12);
|
||||
sos.writeUI8(x >> 4);
|
||||
return;
|
||||
}
|
||||
sos.writeUI8((x << 4) | Edge_H20);
|
||||
sos.writeUI8(x >> 4);
|
||||
sos.writeUI8(x >> 12);
|
||||
break;
|
||||
case Edge_VLine:
|
||||
y = data[1];
|
||||
if (y >= GFxOutputStream.MinSInt12 && y <= GFxOutputStream.MaxSInt12) {
|
||||
sos.writeUI8((y << 4) | Edge_V12);
|
||||
sos.writeUI8(y >> 4);
|
||||
return;
|
||||
}
|
||||
sos.writeUI8((y << 4) | Edge_V20);
|
||||
sos.writeUI8(y >> 4);
|
||||
sos.writeUI8(y >> 12);
|
||||
return;
|
||||
case Edge_Line:
|
||||
x = data[1];
|
||||
y = data[2];
|
||||
if (x >= GFxOutputStream.MinSInt6 && x <= GFxOutputStream.MaxSInt6 && y >= GFxOutputStream.MinSInt6 && y <= GFxOutputStream.MaxSInt6) {
|
||||
sos.writeUI8((x << 4) | Edge_L6);
|
||||
sos.writeUI8(((x >> 4) & m2) | (y << 2));
|
||||
return;
|
||||
}
|
||||
if (x >= GFxOutputStream.MinSInt10 && x <= GFxOutputStream.MaxSInt10 && y >= GFxOutputStream.MinSInt10 && y <= GFxOutputStream.MaxSInt10) {
|
||||
sos.writeUI8((x << 4) | Edge_L10);
|
||||
sos.writeUI8(((x >> 4) & m6) | (y << 6));
|
||||
sos.writeUI8(y >> 2);
|
||||
return;
|
||||
}
|
||||
if (x >= GFxOutputStream.MinSInt14 && x <= GFxOutputStream.MaxSInt14 && y >= GFxOutputStream.MinSInt14 && y <= GFxOutputStream.MaxSInt14) {
|
||||
sos.writeUI8((x << 4) | Edge_L14);
|
||||
sos.writeUI8(x >> 4);
|
||||
sos.writeUI8(((x >> 12) & m2) | (y << 2));
|
||||
sos.writeUI8(y >> 6);
|
||||
return;
|
||||
}
|
||||
sos.writeUI8((x << 4) | Edge_L18);
|
||||
sos.writeUI8(x >> 4);
|
||||
sos.writeUI8(((x >> 12) & m6) | (y << 6));
|
||||
sos.writeUI8(y >> 2);
|
||||
sos.writeUI8(y >> 10);
|
||||
return;
|
||||
case Edge_Quad:
|
||||
int cx = data[1];
|
||||
int cy = data[2];
|
||||
int ax = data[3];
|
||||
int ay = data[4];
|
||||
int minV = cx;
|
||||
int maxV = cx;
|
||||
if (cy < minV) {
|
||||
minV = cy;
|
||||
}
|
||||
if (cy > maxV) {
|
||||
maxV = cy;
|
||||
}
|
||||
if (ax < minV) {
|
||||
minV = ax;
|
||||
}
|
||||
if (ax > maxV) {
|
||||
maxV = ax;
|
||||
}
|
||||
if (ay < minV) {
|
||||
minV = ay;
|
||||
}
|
||||
if (ay > maxV) {
|
||||
maxV = ay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (minV >= GFxOutputStream.MinSInt5 && maxV <= GFxOutputStream.MaxSInt5) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C5));
|
||||
sos.writeUI8((((cx >> 4) & m1) | ((cy << 1) & m6) | (ax << 6)));
|
||||
sos.writeUI8((((ax >> 2) & m3) | (ay << 3)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt7 && maxV <= GFxOutputStream.MaxSInt7) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C7));
|
||||
sos.writeUI8((((cx >> 4) & m3) | (cy << 3)));
|
||||
sos.writeUI8((((cy >> 5) & m2) | (ax << 2)));
|
||||
sos.writeUI8((((ax >> 6) & m1) | (ay << 1)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt9 && maxV <= GFxOutputStream.MaxSInt9) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C9));
|
||||
sos.writeUI8((((cx >> 4) & m5) | (cy << 5)));
|
||||
sos.writeUI8((((cy >> 3) & m6) | (ax << 6)));
|
||||
sos.writeUI8((((ax >> 2) & m7) | (ay << 7)));
|
||||
sos.writeUI8(((ay >> 1)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt11 && maxV <= GFxOutputStream.MaxSInt11) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C11));
|
||||
sos.writeUI8((((cx >> 4) & m7) | (cy << 7)));
|
||||
sos.writeUI8(((cy >> 1)));
|
||||
sos.writeUI8((((cy >> 9) & m2) | (ax << 2)));
|
||||
sos.writeUI8((((ax >> 6) & m5) | (ay << 5)));
|
||||
sos.writeUI8(((ay >> 3)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt13 && maxV <= GFxOutputStream.MaxSInt13) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C13));
|
||||
sos.writeUI8(((cx >> 4)));
|
||||
sos.writeUI8((((cx >> 12) & m1) | (cy << 1)));
|
||||
sos.writeUI8((((cy >> 7) & m6) | (ax << 6)));
|
||||
sos.writeUI8(((ax >> 2)));
|
||||
sos.writeUI8((((ax >> 10) & m3) | (ay << 3)));
|
||||
sos.writeUI8(((ay >> 5)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt15 && maxV <= GFxOutputStream.MaxSInt15) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C15));
|
||||
sos.writeUI8(((cx >> 4)));
|
||||
sos.writeUI8((((cx >> 12) & m3) | (cy << 3)));
|
||||
sos.writeUI8(((cy >> 5)));
|
||||
sos.writeUI8((((cy >> 13) & m2) | (ax << 2)));
|
||||
sos.writeUI8(((ax >> 6)));
|
||||
sos.writeUI8((((ax >> 14) & m1) | (ay << 1)));
|
||||
sos.writeUI8(((ay >> 7)));
|
||||
return;
|
||||
}
|
||||
if (minV >= GFxOutputStream.MinSInt17 && maxV <= GFxOutputStream.MaxSInt17) {
|
||||
sos.writeUI8(((cx << 4) | Edge_C17));
|
||||
sos.writeUI8(((cx >> 4)));
|
||||
sos.writeUI8((((cx >> 12) & m5) | (cy << 5)));
|
||||
sos.writeUI8(((cy >> 3)));
|
||||
sos.writeUI8((((cy >> 11) & m6) | (ax << 6)));
|
||||
sos.writeUI8(((ax >> 2)));
|
||||
sos.writeUI8((((ax >> 10) & m7) | (ay << 7)));
|
||||
sos.writeUI8(((ay >> 1)));
|
||||
sos.writeUI8(((ay >> 9)));
|
||||
return;
|
||||
}
|
||||
sos.writeUI8(((cx << 4) | Edge_C19));
|
||||
sos.writeUI8(((cx >> 4)));
|
||||
sos.writeUI8((((cx >> 12) & m7) | (cy << 7)));
|
||||
sos.writeUI8(((cy >> 1)));
|
||||
sos.writeUI8(((cy >> 9)));
|
||||
sos.writeUI8((((cy >> 17) & m2) | (ax << 2)));
|
||||
sos.writeUI8(((ax >> 6)));
|
||||
sos.writeUI8((((ax >> 14) & m5) | (ay << 5)));
|
||||
sos.writeUI8(((ay >> 3)));
|
||||
sos.writeUI8(((ay >> 11)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -42,7 +41,7 @@ public class FONTINFO {
|
||||
}
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeUI16(fontId);
|
||||
sos.writeUI16(glyphIndices.length);
|
||||
for (int i = 0; i < glyphIndices.length; i++) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -37,14 +36,13 @@ public class FontType {
|
||||
public int ascent;
|
||||
public int descent;
|
||||
public int leading;
|
||||
public GlyphType[] glyphs;
|
||||
public GlyphInfoType[] glyphInfo;
|
||||
public KerningPairType[] kerning;
|
||||
public List<GlyphType> glyphs;
|
||||
public List<GlyphInfoType> glyphInfo;
|
||||
public List<KerningPairType> kerning;
|
||||
|
||||
public FontType(GFxInputStream sis) throws IOException {
|
||||
sis = new GFxInputStream(sis);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
//fontId = sis.readUI16();
|
||||
int val;
|
||||
while ((val = sis.readUI8()) > 0) {
|
||||
baos.write(val);
|
||||
@@ -59,21 +57,21 @@ public class FontType {
|
||||
long glyphBytesLen = sis.readUI32();
|
||||
byte glyphBytes[] = new byte[(int) glyphBytesLen];
|
||||
sis.read(glyphBytes);
|
||||
glyphInfo = new GlyphInfoType[(int) numGlyphs];
|
||||
glyphInfo = new ArrayList<>();
|
||||
for (int i = 0; i < numGlyphs; i++) {
|
||||
glyphInfo[i] = new GlyphInfoType(sis);
|
||||
glyphInfo.add(new GlyphInfoType(sis));
|
||||
}
|
||||
|
||||
long kerningTableSize = sis.readUI30();
|
||||
kerning = new KerningPairType[((int) kerningTableSize)];
|
||||
kerning = new ArrayList<>();
|
||||
for (int i = 0; i < kerningTableSize; i++) {
|
||||
kerning[i] = new KerningPairType(sis);
|
||||
kerning.add(new KerningPairType(sis));
|
||||
}
|
||||
|
||||
glyphs = new GlyphType[glyphInfo.length];
|
||||
for (int i = 0; i < glyphInfo.length; i++) {
|
||||
sis.setPos(glyphInfo[i].globalOffset);
|
||||
glyphs[i] = new GlyphType(sis);
|
||||
glyphs = new ArrayList<>();
|
||||
for (int i = 0; i < glyphInfo.size(); i++) {
|
||||
sis.setPos(glyphInfo.get(i).globalOffset);
|
||||
glyphs.add(new GlyphType(sis));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +83,32 @@ public class FontType {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos = new GFxOutputStream(sos);
|
||||
sos.write(fontName.getBytes());
|
||||
sos.writeUI8(0);
|
||||
sos.writeUI16(flags);
|
||||
sos.writeUI16(nominalSize);
|
||||
sos.writeUI16(ascent);
|
||||
sos.writeUI16(descent);
|
||||
sos.writeUI16(leading);
|
||||
sos.writeUI32(glyphInfo.size()); //numGlyphs
|
||||
long headerLen = sos.getPos() + 4;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
GFxOutputStream sos2 = new GFxOutputStream(baos);
|
||||
for (int i = 0; i < glyphs.size(); i++) {
|
||||
glyphInfo.get(i).globalOffset = headerLen + sos2.getPos();
|
||||
glyphs.get(i).write(sos2);
|
||||
}
|
||||
byte[] glyphBytes = baos.toByteArray();
|
||||
sos.writeUI32(glyphBytes.length);
|
||||
sos.write(glyphBytes);
|
||||
for (int i = 0; i < glyphInfo.size(); i++) {
|
||||
glyphInfo.get(i).write(sos);
|
||||
}
|
||||
sos.writeUI30(kerning.size());
|
||||
for (KerningPairType kp : kerning) {
|
||||
kp.write(sos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.types.gfx;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GFxOutputStream extends OutputStream {
|
||||
|
||||
public static final int MaxUInt6 = (1 << 6) - 1;
|
||||
public static final int MaxUInt7 = (1 << 7) - 1;
|
||||
public static final int MaxUInt14 = (1 << 14) - 1;
|
||||
public static final int MaxUInt22 = (1 << 22) - 1;
|
||||
public static final int MaxUInt30 = (1 << 30) - 1;
|
||||
public static final int MinSInt5 = -(1 << 4);
|
||||
public static final int MaxSInt5 = (1 << 4) - 1;
|
||||
public static final int MinSInt6 = -(1 << 5);
|
||||
public static final int MaxSInt6 = (1 << 5) - 1;
|
||||
public static final int MinSInt7 = -(1 << 6);
|
||||
public static final int MaxSInt7 = (1 << 6) - 1;
|
||||
public static final int MinSInt8 = -(1 << 7);
|
||||
public static final int MaxSInt8 = (1 << 7) - 1;
|
||||
public static final int MinSInt9 = -(1 << 8);
|
||||
public static final int MaxSInt9 = (1 << 8) - 1;
|
||||
public static final int MinSInt10 = -(1 << 9);
|
||||
public static final int MaxSInt10 = (1 << 9) - 1;
|
||||
public static final int MinSInt11 = -(1 << 10);
|
||||
public static final int MaxSInt11 = (1 << 10) - 1;
|
||||
public static final int MinSInt12 = -(1 << 11);
|
||||
public static final int MaxSInt12 = (1 << 11) - 1;
|
||||
public static final int MinSInt13 = -(1 << 12);
|
||||
public static final int MaxSInt13 = (1 << 12) - 1;
|
||||
public static final int MinSInt14 = -(1 << 13);
|
||||
public static final int MaxSInt14 = (1 << 13) - 1;
|
||||
public static final int MinSInt15 = -(1 << 14);
|
||||
public static final int MaxSInt15 = (1 << 14) - 1;
|
||||
public static final int MinSInt17 = -(1 << 16);
|
||||
public static final int MaxSInt17 = (1 << 16) - 1;
|
||||
public static final int MinSInt18 = -(1 << 17);
|
||||
public static final int MaxSInt18 = (1 << 17) - 1;
|
||||
public static final int MinSInt19 = -(1 << 18);
|
||||
public static final int MaxSInt19 = (1 << 18) - 1;
|
||||
public static final int MinSInt20 = -(1 << 19);
|
||||
public static final int MaxSInt20 = (1 << 19) - 1;
|
||||
public static final int MinSInt22 = -(1 << 21);
|
||||
public static final int MaxSInt22 = (1 << 21) - 1;
|
||||
private OutputStream os;
|
||||
private long pos = 0;
|
||||
|
||||
public GFxOutputStream(OutputStream os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public long getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
os.write(b);
|
||||
pos++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes SI32 (Signed 32bit integer) value to the stream
|
||||
*
|
||||
* @param value SI32 value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeSI32(long value) throws IOException {
|
||||
writeUI32(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes SI16 (Signed 16bit integer) value to the stream
|
||||
*
|
||||
* @param value SI16 value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeSI16(int value) throws IOException {
|
||||
writeUI16(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes SI8 (Signed 8bit integer) value to the stream
|
||||
*
|
||||
* @param value SI8 value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeSI8(int value) throws IOException {
|
||||
writeUI8(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes UI32 (Unsigned 32bit integer) value to the stream
|
||||
*
|
||||
* @param value UI32 value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeUI32(long value) throws IOException {
|
||||
write((int) (value & 0xff));
|
||||
write((int) ((value >> 8) & 0xff));
|
||||
write((int) ((value >> 16) & 0xff));
|
||||
write((int) ((value >> 24) & 0xff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes UI16 (Unsigned 16bit integer) value to the stream
|
||||
*
|
||||
* @param value UI16 value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeUI16(int value) throws IOException {
|
||||
write((int) (value & 0xff));
|
||||
write((int) ((value >> 8) & 0xff));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes UI8 (Unsigned 8bit integer) value to the stream
|
||||
*
|
||||
* @param val UI8 value to write
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeUI8(int val) throws IOException {
|
||||
write(val & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes FLOAT (single precision floating point value) value to the stream
|
||||
*
|
||||
* @param value FLOAT value
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeFLOAT(float value) throws IOException {
|
||||
writeUI32(Float.floatToIntBits(value));
|
||||
}
|
||||
|
||||
public void writeSI15(int v) throws IOException {
|
||||
if (v >= MinSInt7 && v <= MaxSInt7) {
|
||||
writeUI8(v << 1);
|
||||
return;
|
||||
}
|
||||
writeUI8((v << 1) | 1);
|
||||
writeUI8(v >> 7);
|
||||
}
|
||||
|
||||
public void writeUI15(int v) throws IOException {
|
||||
if (v <= MaxUInt7) {
|
||||
writeUI8(v << 1);
|
||||
return;
|
||||
}
|
||||
writeUI8((v << 1) | 1);
|
||||
writeUI8(v >> 7);
|
||||
}
|
||||
|
||||
public void writeUI30(int v) throws IOException {
|
||||
if (v <= MaxUInt6) {
|
||||
writeUI8(v << 2);
|
||||
return;
|
||||
}
|
||||
if (v <= MaxUInt14) {
|
||||
writeUI8((v << 2) | 1);
|
||||
writeUI8(v >> 6);
|
||||
return;
|
||||
}
|
||||
if (v <= MaxUInt22) {
|
||||
writeUI8((v << 2) | 2);
|
||||
writeUI8(v >> 6);
|
||||
writeUI8(v >> 14);
|
||||
return;
|
||||
}
|
||||
writeUI8((v << 2) | 3);
|
||||
writeUI8(v >> 6);
|
||||
writeUI8(v >> 14);
|
||||
writeUI8(v >> 22);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -38,7 +37,7 @@ public class GLYPHIDX {
|
||||
this.indexInTexture = sis.readUI16();
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeUI16(indexInFont);
|
||||
sos.writeUI16(indexInTexture);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -41,7 +40,7 @@ public class GlyphInfoType {
|
||||
this.globalOffset = sis.readUI32();
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeUI16(glyphCode);
|
||||
sos.writeSI16(advanceX);
|
||||
sos.writeUI32(globalOffset);
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import java.io.IOException;
|
||||
@@ -33,6 +34,32 @@ public class GlyphType {
|
||||
public int[] boundingBox;
|
||||
public ContourType[] contours;
|
||||
|
||||
public GlyphType(List<SHAPERECORD> records) {
|
||||
RECT bounds = SHAPERECORD.getBounds(records);
|
||||
boundingBox = new int[4];
|
||||
boundingBox[0] = bounds.Xmin;
|
||||
boundingBox[1] = bounds.Ymin;
|
||||
boundingBox[2] = bounds.Xmax;
|
||||
boundingBox[3] = bounds.Ymax;
|
||||
List<SHAPERECORD> cont = new ArrayList<>();
|
||||
List<ContourType> contoursList = new ArrayList<>();
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
SHAPERECORD r = records.get(i);
|
||||
if ((r instanceof StyleChangeRecord) && ((StyleChangeRecord) r).stateMoveTo) {
|
||||
if (!cont.isEmpty()) {
|
||||
contoursList.add(new ContourType(cont));
|
||||
cont.clear();
|
||||
}
|
||||
}
|
||||
cont.add(r);
|
||||
}
|
||||
if (!cont.isEmpty()) {
|
||||
contoursList.add(new ContourType(cont));
|
||||
cont.clear();
|
||||
}
|
||||
contours = contoursList.toArray(new ContourType[contoursList.size()]);
|
||||
}
|
||||
|
||||
public GlyphType(GFxInputStream sis) throws IOException {
|
||||
boundingBox = new int[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -48,19 +75,29 @@ public class GlyphType {
|
||||
public SHAPE toSHAPE() {
|
||||
SHAPE shp = new SHAPE();
|
||||
shp.numFillBits = 1;
|
||||
shp.numLineBits = 1;
|
||||
shp.numLineBits = 0;
|
||||
List<SHAPERECORD> recs = new ArrayList<>();
|
||||
StyleChangeRecord scr = new StyleChangeRecord();
|
||||
scr.fillStyle0 = 1;
|
||||
scr.stateFillStyle0 = true;
|
||||
scr.fillStyle0 = 0;
|
||||
scr.fillStyle1 = 1;
|
||||
scr.stateFillStyle1 = true;
|
||||
scr.stateFillStyle0 = false;
|
||||
recs.add(scr);
|
||||
for (ContourType cnt : contours) {
|
||||
recs.addAll(cnt.toSHAPERECORDS());
|
||||
}
|
||||
recs.add(new EndShapeRecord());
|
||||
shp.shapeRecords = recs;
|
||||
return shp;
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
for (int b : boundingBox) {
|
||||
sos.writeSI15(b);
|
||||
}
|
||||
sos.writeUI15(contours.length);
|
||||
for (ContourType cnt : contours) {
|
||||
cnt.write(sos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -41,7 +40,7 @@ public class KerningPairType {
|
||||
this.advance = sis.readSI16();
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeUI16(char1);
|
||||
sos.writeUI16(char2);
|
||||
sos.writeSI16(advance);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.gfx;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -50,7 +49,7 @@ public class TEXGLYPH {
|
||||
this.uvOriginY = sis.readFLOAT();
|
||||
}
|
||||
|
||||
public void write(SWFOutputStream sos) throws IOException {
|
||||
public void write(GFxOutputStream sos) throws IOException {
|
||||
sos.writeFLOAT(uvBoundsLeft);
|
||||
sos.writeFLOAT(uvBoundsTop);
|
||||
sos.writeFLOAT(uvBoundsRight);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.types.shaperecords;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -68,4 +69,12 @@ public class CurvedEdgeRecord extends SHAPERECORD {
|
||||
public boolean isMove() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateBits() {
|
||||
numBits = SWFOutputStream.getNeededBitsS(controlDeltaX, controlDeltaY, anchorDeltaX, anchorDeltaY) - 2;
|
||||
if (numBits < 0) {
|
||||
numBits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,4 +53,8 @@ public class EndShapeRecord extends SHAPERECORD {
|
||||
public boolean isMove() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateBits() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.helpers.Cache;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
@@ -73,10 +74,12 @@ import javax.swing.JPanel;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
|
||||
public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Serializable {
|
||||
|
||||
private static final float DESCALE = 20;
|
||||
|
||||
public abstract void calculateBits();
|
||||
|
||||
@Override
|
||||
public Set<Integer> getNeededCharacters() {
|
||||
HashSet<Integer> ret = new HashSet<>();
|
||||
@@ -847,10 +850,33 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
|
||||
for (SHAPE s : shapes) {
|
||||
images.add(s.toImage(1, new ArrayList<Tag>(), color));
|
||||
}
|
||||
int maxw = 0;
|
||||
int maxh = 0;
|
||||
for (BufferedImage im : images) {
|
||||
if (im.getWidth() > maxw) {
|
||||
maxw = im.getWidth();
|
||||
}
|
||||
if (im.getHeight() > maxh) {
|
||||
maxh = im.getHeight();
|
||||
}
|
||||
}
|
||||
int cols = (int) Math.ceil(Math.sqrt(images.size()));
|
||||
int pos = 0;
|
||||
int w2 = prevWidth / cols;
|
||||
int h2 = prevHeight / cols;
|
||||
|
||||
|
||||
int mh = maxh * w2 / maxw;
|
||||
int mw;
|
||||
if (mh > h2) {
|
||||
mw = maxw * h2 / maxh;
|
||||
mh = h2;
|
||||
} else {
|
||||
mw = w2;
|
||||
}
|
||||
|
||||
float ratio = (float) mw / (float) maxw;
|
||||
|
||||
loopy:
|
||||
for (int y = 0; y < cols; y++) {
|
||||
for (int x = 0; x < cols; x++) {
|
||||
@@ -861,16 +887,18 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
|
||||
int h1 = images.get(pos).getHeight();
|
||||
|
||||
|
||||
int h = h1 * w2 / w1;
|
||||
int w;
|
||||
if (h > h2) {
|
||||
w = w1 * h2 / h1;
|
||||
h = h2;
|
||||
} else {
|
||||
w = w2;
|
||||
}
|
||||
int px = x * w2 + w2 / 2 - w / 2;
|
||||
int py = y * h2 + h2 / 2 - h / 2;
|
||||
/*int h = h1 * mw / w1;
|
||||
int w;
|
||||
if (h > mh) {
|
||||
w = w1 * mh / h1;
|
||||
h = mh;
|
||||
} else {
|
||||
w = mw;
|
||||
}*/
|
||||
int w = Math.round(ratio * w1);
|
||||
int h = Math.round(ratio * h1);
|
||||
int px = x * mw + mw / 2 - w / 2;
|
||||
int py = y * mh + mh - h;
|
||||
g.drawImage(images.get(pos), px, py, px + w, py + h, 0, 0, w1, h1, null);
|
||||
pos++;
|
||||
}
|
||||
@@ -1139,4 +1167,37 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
|
||||
image = ImageIO.read(in);
|
||||
}
|
||||
}
|
||||
|
||||
public static SHAPE resizeSHAPE(SHAPE shp, int multiplier) {
|
||||
SHAPE ret = new SHAPE();
|
||||
ret.numFillBits = shp.numFillBits;
|
||||
ret.numLineBits = shp.numLineBits;
|
||||
List<SHAPERECORD> recs = new ArrayList<>();
|
||||
for (SHAPERECORD r : shp.shapeRecords) {
|
||||
SHAPERECORD c = (SHAPERECORD) Helper.deepCopy(r);
|
||||
if (c instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr = (StyleChangeRecord) c;
|
||||
scr.moveDeltaX = (multiplier * scr.moveDeltaX);
|
||||
scr.moveDeltaY = (multiplier * scr.moveDeltaY);
|
||||
scr.calculateBits();
|
||||
}
|
||||
if (c instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer = (CurvedEdgeRecord) c;
|
||||
cer.controlDeltaX = (multiplier * cer.controlDeltaX);
|
||||
cer.controlDeltaY = (multiplier * cer.controlDeltaY);
|
||||
cer.anchorDeltaX = (multiplier * cer.anchorDeltaX);
|
||||
cer.anchorDeltaY = (multiplier * cer.anchorDeltaY);
|
||||
cer.calculateBits();
|
||||
}
|
||||
if (c instanceof StraightEdgeRecord) {
|
||||
StraightEdgeRecord ser = (StraightEdgeRecord) c;
|
||||
ser.deltaX = (multiplier * ser.deltaX);
|
||||
ser.deltaY = (multiplier * ser.deltaY);
|
||||
ser.calculateBits();
|
||||
}
|
||||
recs.add(c);
|
||||
}
|
||||
ret.shapeRecords = recs;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.types.shaperecords;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -80,4 +81,12 @@ public class StraightEdgeRecord extends SHAPERECORD {
|
||||
public boolean isMove() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateBits() {
|
||||
numBits = SWFOutputStream.getNeededBitsS(deltaX, deltaY) - 2;
|
||||
if (numBits < 0) {
|
||||
numBits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.types.shaperecords;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import java.util.Set;
|
||||
@@ -105,4 +106,9 @@ public class StyleChangeRecord extends SHAPERECORD implements Cloneable {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateBits() {
|
||||
moveBits = SWFOutputStream.getNeededBitsS(moveDeltaX, moveDeltaY);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user