/* * Copyright (C) 2010-2016 JPEXS, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.jpexs.decompiler.flash.types.gfx; 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.IOException; import java.io.Serializable; /** * * @author JPEXS */ public class EdgeType implements Serializable { private static final int[] sizes = new int[]{1, 2, 1, 2, 1, 2, 3, 4, 2, 3, 4, 5, 6, 7, 8, 9}; private static final int Edge_H12 = 0; // 2 bytes private static final int Edge_H20 = 1; // 3 bytes private static final int Edge_V12 = 2; // 2 bytes private static final int Edge_V20 = 3; // 3 bytes private static final int Edge_L6 = 4; // 2 bytes private static final int Edge_L10 = 5; // 3 bytes private static final int Edge_L14 = 6; // 4 bytes private static final int Edge_L18 = 7; // 5 bytes private static final int Edge_C5 = 8; // 3 bytes private static final int Edge_C7 = 9; // 4 bytes private static final int Edge_C9 = 10; // 5 bytes private static final int Edge_C11 = 11; // 6 bytes private static final int Edge_C13 = 12; // 7 bytes private static final int Edge_C15 = 13; // 8 bytes private static final int Edge_C17 = 14; // 9 bytes private static final int Edge_C19 = 15; // 10 bytes private static final int Edge_HLine = 0; private static final int Edge_VLine = 1; private static final int Edge_Line = 2; private static final int Edge_Quad = 3; public int[] data; public EdgeType(boolean vertical, int v) { data = new int[]{vertical ? Edge_VLine : Edge_HLine, v}; } public EdgeType(int x, int y) { data = new int[]{Edge_Line, x, y}; } public EdgeType(int cx, int cy, int ax, int ay) { data = new int[]{Edge_Quad, cx, cy, ax, ay}; } @Override public String toString() { String ret = "[Edge data:"; for (int i = 0; i < data.length; i++) { if (i > 0) { ret += ", "; } ret += "" + data[i]; } ret += "]"; return ret; } public EdgeType(GFxInputStream sis) throws IOException { data = readEdge(sis); /*if((raw[0]&0xf) == Edge_V20){ data[1] = 0; } if((raw[0]&0xf) == Edge_C17){ //System.out.println("========== 17 : "+toString()) ; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 0; }*/ } private static int SInt8(int val) { /*boolean sign = (val & 0x80) == 0x80; val = val & 0x7F; if (sign) { val = -val; } return val;*/ return (byte) val; } public SHAPERECORD toSHAPERECORD() { int multiplier = 1; StraightEdgeRecord ser; CurvedEdgeRecord cer; switch (data[0]) { case Edge_HLine: 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(); cer.controlDeltaX = data[1] * multiplier; cer.controlDeltaY = data[2] * multiplier; cer.anchorDeltaX = data[3] * multiplier; cer.anchorDeltaY = data[4] * multiplier; cer.calculateBits(); return cer; } return null; } private int[] readEdge(GFxInputStream sis) throws IOException { byte firstByte = (byte) sis.readUI8("firstByte"); byte raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8, raw9; raw1 = (byte) sis.readUI8("byte1"); int[] data = new int[5]; switch (firstByte & 0xF) { case Edge_H12: data[0] = Edge_HLine; data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); break; case Edge_H20: raw2 = (byte) sis.readUI8("byte2"); data[0] = Edge_HLine; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); break; case Edge_V12: data[0] = Edge_VLine; data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); break; case Edge_V20: data[0] = Edge_VLine; raw2 = (byte) sis.readUI8("byte2"); data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); break; case Edge_L6: data[0] = Edge_Line; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 6) >> 2); data[2] = SInt8(raw1 & 0xff) >> 2; break; case Edge_L10: raw2 = (byte) sis.readUI8("byte2"); data[0] = Edge_Line; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 2) << 2); data[2] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff)) << 2); break; case Edge_L14: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); data[0] = Edge_Line; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 6) << 6); data[2] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff)) << 6); break; case Edge_L18: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); data[0] = Edge_Line; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 2) << 10); data[2] = ((raw2 & 0xff) >> 6) | ((raw3 & 0xff) << 2) | (SInt8((raw4 & 0xff)) << 10); break; case Edge_C5: raw2 = (byte) sis.readUI8("byte2"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 7) >> 3); data[2] = SInt8((raw1 & 0xff) << 2) >> 3; data[3] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff) << 5) >> 3); data[4] = SInt8((raw2 & 0xff)) >> 3; break; case Edge_C7: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 5) >> 1); data[2] = ((raw1 & 0xff) >> 3) | (SInt8((raw2 & 0xff) << 6) >> 1); data[3] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff) << 7) >> 1); data[4] = SInt8(raw3) >> 1; break; case Edge_C9: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 3) << 1); data[2] = ((raw1 & 0xff) >> 5) | (SInt8((raw2 & 0xff) << 2) << 1); data[3] = ((raw2 & 0xff) >> 6) | (SInt8((raw3 & 0xff) << 1) << 1); data[4] = ((raw3 & 0xff) >> 7) | (SInt8(raw4 & 0xff) << 1); break; case Edge_C11: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); raw5 = (byte) sis.readUI8("byte5"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 1) << 3); data[2] = (raw1 >> 7) | ((raw2 & 0xff) << 1) | (SInt8((raw3 & 0xff) << 6) << 3); data[3] = ((raw3 & 0xff) >> 2) | (SInt8((raw4 & 0xff) << 3) << 3); data[4] = ((raw4 & 0xff) >> 5) | (SInt8(raw5 & 0xff) << 3); break; case Edge_C13: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); raw5 = (byte) sis.readUI8("byte5"); raw6 = (byte) sis.readUI8("byte6"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 7) << 5); data[2] = ((raw2 & 0xff) >> 1) | (SInt8((raw3 & 0xff) << 2) << 5); data[3] = ((raw3 & 0xff) >> 6) | ((raw4 & 0xff) << 2) | (SInt8((raw5 & 0xff) << 5) << 5); data[4] = ((raw5 & 0xff) >> 3) | (SInt8(raw6 & 0xff) << 5); break; case Edge_C15: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); raw5 = (byte) sis.readUI8("byte5"); raw6 = (byte) sis.readUI8("byte6"); raw7 = (byte) sis.readUI8("byte7"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 5) << 7); data[2] = ((raw2 & 0xff) >> 3) | ((raw3 & 0xff) << 5) | (SInt8((raw4 & 0xff) << 6) << 7); data[3] = ((raw4 & 0xff) >> 2) | ((raw5 & 0xff) << 6) | (SInt8((raw6 & 0xff) << 7) << 7); data[4] = ((raw6 & 0xff) >> 1) | (SInt8((raw7 & 0xff)) << 7); break; case Edge_C17: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); raw5 = (byte) sis.readUI8("byte5"); raw6 = (byte) sis.readUI8("byte6"); raw7 = (byte) sis.readUI8("byte7"); raw8 = (byte) sis.readUI8("byte8"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 3) << 9); data[2] = ((raw2 & 0xff) >> 5) | ((raw3 & 0xff) << 3) | (SInt8((raw4 & 0xff) << 2) << 9); data[3] = ((raw4 & 0xff) >> 6) | ((raw5 & 0xff) << 2) | (SInt8((raw6 & 0xff) << 1) << 9); data[4] = ((raw6 & 0xff) >> 7) | ((raw7 & 0xff) << 1) | (SInt8(raw8 & 0xff) << 9); break; case Edge_C19: raw2 = (byte) sis.readUI8("byte2"); raw3 = (byte) sis.readUI8("byte3"); raw4 = (byte) sis.readUI8("byte4"); raw5 = (byte) sis.readUI8("byte5"); raw6 = (byte) sis.readUI8("byte6"); raw7 = (byte) sis.readUI8("byte7"); raw8 = (byte) sis.readUI8("byte8"); raw9 = (byte) sis.readUI8("byte9"); data[0] = Edge_Quad; data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 << 1) << 11); data[2] = ((raw2 & 0xff) >> 7) | ((raw3 & 0xff) << 1) | ((raw4 & 0xff) << 9) | (SInt8(raw5 << 6) << 11); data[3] = ((raw5 & 0xff) >> 2) | ((raw6 & 0xff) << 6) | (SInt8(raw7 << 3) << 11); data[4] = ((raw7 & 0xff) >> 5) | ((raw8 & 0xff) << 3) | (SInt8(raw9) << 11); break; } return data; } 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))); } } }