shape parsing

This commit is contained in:
2016-03-15 20:56:10 +06:00
parent 2ed2198eb7
commit 72f4d69c3e
14 changed files with 414 additions and 31 deletions

View File

@@ -79,6 +79,7 @@
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfColorTransformRGB.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfColorTransformRGBA.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfControlTags.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfFillStyleType.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfLongHeaderType.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfMatrix.cs" />
<Compile Include="Assets\FlashTools\Scripts\Internal\Editor\SwfTools\SwfTypes\SwfRGB.cs" />

View File

@@ -52,12 +52,12 @@ namespace FlashTools.Internal.SwfTools {
}
public bool ReadBit() {
var bitIndex = _bitContext.BitIndex & 0x07;
if ( bitIndex == 0 ) {
var bit_index = _bitContext.BitIndex & 0x07;
if ( bit_index == 0 ) {
_bitContext.CachedByte = ReadByte();
}
++_bitContext.BitIndex;
return ((_bitContext.CachedByte << bitIndex) & 0x80) != 0;
return ((_bitContext.CachedByte << bit_index) & 0x80) != 0;
}
public byte ReadByte() {
@@ -140,30 +140,29 @@ namespace FlashTools.Internal.SwfTools {
}
public uint ReadEncodedU32() {
AlignToByte();
uint val = 0;
var bt = ReadByte();
val |= bt & 0x7fu;
val |= bt & 0x7Fu;
if ( (bt & 0x80) == 0 ) {
return val;
}
bt = ReadByte();
val |= (bt & 0x7fu) << 7;
val |= (bt & 0x7Fu) << 7;
if ( (bt & 0x80) == 0 ) {
return val;
}
bt = ReadByte();
val |= (bt & 0x7fu) << 14;
val |= (bt & 0x7Fu) << 14;
if ( (bt & 0x80) == 0 ) {
return val;
}
bt = ReadByte();
val |= (bt & 0x7fu) << 21;
val |= (bt & 0x7Fu) << 21;
if ( (bt & 0x80) == 0 ) {
return val;
}
bt = ReadByte();
val |= (bt & 0x7fu) << 28;
val |= (bt & 0x7Fu) << 28;
return val;
}
}

View File

@@ -21,7 +21,7 @@ namespace FlashTools.Internal.SwfTools.SwfTags {
var tag = new DefineShape2Tag();
tag.ShapeId = reader.ReadUInt16();
tag.ShapeBounds = SwfRect.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader, SwfShapesWithStyle.ShapeStyleType.Shape2);
return tag;
}
}

View File

@@ -21,7 +21,7 @@ namespace FlashTools.Internal.SwfTools.SwfTags {
var tag = new DefineShape3Tag();
tag.ShapeId = reader.ReadUInt16();
tag.ShapeBounds = SwfRect.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader, SwfShapesWithStyle.ShapeStyleType.Shape3);
return tag;
}
}

View File

@@ -23,8 +23,8 @@ namespace FlashTools.Internal.SwfTools.SwfTags {
tag.ShapeId = reader.ReadUInt16();
tag.ShapeBounds = SwfRect.Read(reader);
tag.EdgeBounds = SwfRect.Read(reader);
reader.ReadByte(); // Skip flags
tag.Shapes = SwfShapesWithStyle.Read(reader);
reader.ReadByte(); // Flags
tag.Shapes = SwfShapesWithStyle.Read(reader, SwfShapesWithStyle.ShapeStyleType.Shape4);
return tag;
}
}

View File

@@ -21,7 +21,7 @@ namespace FlashTools.Internal.SwfTools.SwfTags {
var tag = new DefineShapeTag();
tag.ShapeId = reader.ReadUInt16();
tag.ShapeBounds = SwfRect.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader);
tag.Shapes = SwfShapesWithStyle.Read(reader, SwfShapesWithStyle.ShapeStyleType.Shape);
return tag;
}
}

View File

@@ -18,18 +18,18 @@ namespace FlashTools.Internal.SwfTools.SwfTypes {
Overlay,
Hardlight
}
public Mode Type;
public Mode Value;
public static SwfBlendMode Read(SwfStreamReader reader) {
var mode_id = reader.ReadByte();
var mode = ModeFromByte(mode_id);
return new SwfBlendMode{Type = mode};
return new SwfBlendMode{Value = mode};
}
public override string ToString() {
return string.Format(
"SwfBlendMode. Type: {0}",
Type.ToString());
"SwfBlendMode. Mode: {0}",
Value);
}
static Mode ModeFromByte(byte mode_id) {

View File

@@ -0,0 +1,45 @@
using UnityEngine;
namespace FlashTools.Internal.SwfTools.SwfTypes {
struct SwfFillStyleType {
public enum Type {
SolidColor,
LinearGradient,
RadialGradient,
FocalGradient,
RepeatingBitmap,
ClippedBitmap,
NonSmoothedRepeatingBitmap,
NonSmoothedClippedBitmap
}
public Type Value;
public static SwfFillStyleType Read(SwfStreamReader reader) {
var type_id = reader.ReadByte();
var type = TypeFromByte(type_id);
return new SwfFillStyleType{Value = type};
}
public override string ToString() {
return string.Format(
"SwfFillStyleType. Type: {0}",
Value);
}
static Type TypeFromByte(byte type_id) {
switch ( type_id ) {
case 0x00: return Type.SolidColor;
case 0x10: return Type.LinearGradient;
case 0x12: return Type.RadialGradient;
case 0x13: return Type.FocalGradient;
case 0x40: return Type.RepeatingBitmap;
case 0x41: return Type.ClippedBitmap;
case 0x42: return Type.NonSmoothedRepeatingBitmap;
case 0x43: return Type.NonSmoothedClippedBitmap;
default:
Debug.LogWarningFormat("Incorrect FillStyleType Id: {0}", type_id);
return Type.SolidColor;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 392129356a8e143989e89d24bb52060e
timeCreated: 1457976003
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,14 +12,14 @@
var has_scale = reader.ReadBit();
if ( has_scale ) {
var bits = (byte)reader.ReadUnsignedBits(5);
matrix.ScaleX = reader.ReadFixedPoint16(bits);
matrix.ScaleY = reader.ReadFixedPoint16(bits);
matrix.ScaleX = reader.ReadFixedPoint16(bits) / 20.0f;
matrix.ScaleY = reader.ReadFixedPoint16(bits) / 20.0f;
}
var has_rotate = reader.ReadBit();
if ( has_rotate ) {
var bits = (byte)reader.ReadUnsignedBits(5);
matrix.RotateSkew0 = reader.ReadFixedPoint16(bits);
matrix.RotateSkew1 = reader.ReadFixedPoint16(bits);
matrix.RotateSkew0 = reader.ReadFixedPoint16(bits) / 20.0f;
matrix.RotateSkew1 = reader.ReadFixedPoint16(bits) / 20.0f;
}
var translate_bits = (byte)reader.ReadUnsignedBits(5);
matrix.TranslateX = reader.ReadSignedBits(translate_bits) / 20.0f;

View File

@@ -17,5 +17,13 @@
"SwfRGB. R: {0}, G: {1}, B: {2}",
R, G, B);
}
public SwfRGBA ToRGBA(byte alpha) {
return new SwfRGBA{
R = R,
G = G,
B = B,
A = alpha};
}
}
}

View File

@@ -19,5 +19,12 @@
"SwfRGBA. R: {0}, G: {1}, B: {2}, A: {3}",
R, G, B, A);
}
public SwfRGB ToRGB() {
return new SwfRGB{
R = R,
G = G,
B = B};
}
}
}

View File

@@ -1,12 +1,323 @@
namespace FlashTools.Internal.SwfTools.SwfTypes {
using UnityEngine;
using System.Collections.Generic;
namespace FlashTools.Internal.SwfTools.SwfTypes {
struct SwfShapesWithStyle {
public static SwfShapesWithStyle Read(SwfStreamReader reader) {
//TODO: IMPLME
return new SwfShapesWithStyle();
public enum ShapeStyleType {
Shape,
Shape2,
Shape3,
Shape4
}
public struct FillStyle {
public SwfFillStyleType Type;
public ushort BitmapId;
public SwfMatrix BitmapMatrix;
public override string ToString() {
return string.Format(
"FillStyle. Type: {0}, BitmapId: {1}, BitmapMatrix: {2}",
Type, BitmapId, BitmapMatrix);
}
}
public List<FillStyle> FillStyles;
public static SwfShapesWithStyle Read(SwfStreamReader reader, ShapeStyleType style_type) {
var shapes = new SwfShapesWithStyle();
switch ( style_type ) {
case ShapeStyleType.Shape:
shapes.FillStyles = ReadFillStyles(reader, false, false);
SkipLineStyles(reader, false, false, false);
SkipShapeRecords(reader, false, false, false);
break;
case ShapeStyleType.Shape2:
shapes.FillStyles = ReadFillStyles(reader, true, false);
SkipLineStyles(reader, true, false, false);
SkipShapeRecords(reader, true, false, false);
break;
case ShapeStyleType.Shape3:
shapes.FillStyles = ReadFillStyles(reader, true, true);
SkipLineStyles(reader, true, true, false);
SkipShapeRecords(reader, true, true, false);
break;
case ShapeStyleType.Shape4:
shapes.FillStyles = ReadFillStyles(reader, true, true);
SkipLineStyles(reader, true, true, true);
SkipShapeRecords(reader, true, true, true);
break;
default:
throw new UnityException(string.Format(
"Unsupported ShapeStyleType: {0}", style_type));
}
return shapes;
}
public override string ToString() {
return "SwfShapesWithStyle.";
return string.Format(
"SwfShapesWithStyle. FillStyles: {0}",
FillStyles.Count);
}
// ------------------------------------------------------------------------
//
// FillStyles
//
// ------------------------------------------------------------------------
static List<FillStyle> ReadFillStyles(
SwfStreamReader reader, bool allow_big_array, bool with_alpha)
{
ushort count = reader.ReadByte();
if ( allow_big_array && count == 255 ) {
count = reader.ReadUInt16();
}
var styles = new List<FillStyle>(count);
for ( var i = 0; i < count; ++i ) {
styles.Add(ReadFillStyle(reader, with_alpha));
}
return styles;
}
// -----------------------------
// FillStyle
// -----------------------------
static FillStyle ReadFillStyle(SwfStreamReader reader, bool with_alpha) {
var fill_style = new FillStyle();
fill_style.Type = SwfFillStyleType.Read(reader);
switch ( fill_style.Type.Value ) {
case SwfFillStyleType.Type.SolidColor:
if ( with_alpha ) {
SwfRGBA.Read(reader);
} else {
SwfRGB.Read(reader);
} // Color
break;
}
switch ( fill_style.Type.Value ) {
case SwfFillStyleType.Type.LinearGradient:
case SwfFillStyleType.Type.RadialGradient:
case SwfFillStyleType.Type.FocalGradient:
SwfMatrix.Read(reader); // GradientMatrix
break;
}
switch ( fill_style.Type.Value ) {
case SwfFillStyleType.Type.LinearGradient:
case SwfFillStyleType.Type.RadialGradient:
SkipGradient(reader, with_alpha); // Gradient
break;
case SwfFillStyleType.Type.FocalGradient:
SkipFocalGradient(reader, with_alpha); // FocalGradient
break;
}
switch ( fill_style.Type.Value ) {
case SwfFillStyleType.Type.RepeatingBitmap:
case SwfFillStyleType.Type.ClippedBitmap:
case SwfFillStyleType.Type.NonSmoothedRepeatingBitmap:
case SwfFillStyleType.Type.NonSmoothedClippedBitmap:
fill_style.BitmapId = reader.ReadUInt16();
fill_style.BitmapMatrix = SwfMatrix.Read(reader);
break;
default:
fill_style.BitmapId = 0;
fill_style.BitmapMatrix = SwfMatrix.Identity;
break;
}
Debug.LogErrorFormat("ReadFillStyle: {0}", fill_style);
return fill_style;
}
// -----------------------------
// Gradient
// -----------------------------
static void SkipGradient(SwfStreamReader reader, bool with_alpha) {
reader.ReadUnsignedBits(2); // SpreadMode
reader.ReadUnsignedBits(2); // InterpolationMode
var count = reader.ReadUnsignedBits(4);
for ( var i = 0; i < count; ++i ) {
reader.ReadByte(); // Ratio
if ( with_alpha ) {
SwfRGBA.Read(reader);
} else {
SwfRGB.Read(reader);
} // Color
}
}
// -----------------------------
// FocalGradient
// -----------------------------
static void SkipFocalGradient(SwfStreamReader reader, bool with_alpha) {
reader.ReadUnsignedBits(2); // SpreadMode
reader.ReadUnsignedBits(2); // InterpolationMode
var count = reader.ReadUnsignedBits(4);
for ( var i = 0; i < count; ++i ) {
reader.ReadByte(); // Ratio
if ( with_alpha ) {
SwfRGBA.Read(reader);
} else {
SwfRGB.Read(reader);
} // Color
}
reader.ReadFixedPoint8(); // FocalPoint
}
// ------------------------------------------------------------------------
//
// LineStyles
//
// ------------------------------------------------------------------------
static void SkipLineStyles(
SwfStreamReader reader, bool allow_big_array, bool with_alpha, bool line2_type)
{
ushort count = reader.ReadByte();
if ( allow_big_array && count == 255 ) {
count = reader.ReadUInt16();
}
for ( var i = 0; i < count; ++i ) {
if ( line2_type ) {
SkipLine2Style(reader);
} else {
SkipLineStyle(reader, with_alpha);
}
}
}
// -----------------------------
// LineStyles
// -----------------------------
static void SkipLineStyle(SwfStreamReader reader, bool with_alpha) {
reader.ReadUInt16(); // Width
if ( with_alpha ) {
SwfRGBA.Read(reader);
} else {
SwfRGB.Read(reader);
} // Color
}
static void SkipLine2Style(SwfStreamReader reader) {
reader.ReadUInt16(); // Width
reader.ReadUnsignedBits(2); // StartCapStyle
var join_style = reader.ReadUnsignedBits(2);
var has_fill_flag = reader.ReadBit();
reader.ReadBit(); // NoHScaleFlag
reader.ReadBit(); // NoVScaleFlag
reader.ReadBit(); // PixelHintingFlag
reader.ReadUnsignedBits(5); // Reserved
reader.ReadBit(); // NoClose
reader.ReadUnsignedBits(2); // EndCapStyle
if ( join_style == 2 ) {
reader.ReadFixedPoint8(); // MiterLimitFactor
}
if ( has_fill_flag ) {
ReadFillStyle(reader, true); // FillStyle
} else {
SwfRGBA.Read(reader); // Color
}
}
// ------------------------------------------------------------------------
//
// ShapeRecords
//
// ------------------------------------------------------------------------
public enum ShapeRecordType {
EndRecord,
StyleChangeRecord,
StraightEdge,
CurvedEdgeRecord
}
static void SkipShapeRecords(
SwfStreamReader reader,
bool allow_big_array, bool with_alpha, bool line2_type)
{
var fill_style_bits = reader.ReadUnsignedBits(4);
var line_style_bits = reader.ReadUnsignedBits(4);
while ( !SkipShapeRecord(
reader, ref fill_style_bits, ref line_style_bits,
allow_big_array, with_alpha, line2_type) )
{
continue;
}
}
static bool SkipShapeRecord(
SwfStreamReader reader,
ref uint fill_style_bits, ref uint line_style_bits,
bool allow_big_array, bool with_alpha, bool line2_type)
{
var is_edge = reader.ReadBit();
if ( is_edge ) {
var straight = reader.ReadBit();
if ( straight ) {
SkipStraigtEdgeShapeRecord(reader);
} else {
SkipCurvedEdgeShapeRecord(reader);
}
return false;
} else {
var state_new_styles = reader.ReadBit();
var state_line_style = reader.ReadBit();
var state_fill_style1 = reader.ReadBit();
var state_fill_style0 = reader.ReadBit();
var state_move_to = reader.ReadBit();
var is_end_shape_record =
!state_new_styles && !state_line_style &&
!state_fill_style0 && !state_fill_style1 && !state_move_to;
if ( is_end_shape_record ) {
return true;
} else {
if ( state_move_to ) {
var move_bits = reader.ReadUnsignedBits(5);
reader.ReadSignedBits(move_bits); // move_delta_x
reader.ReadSignedBits(move_bits); // move_delta_y
}
if ( state_fill_style0 ) {
reader.ReadUnsignedBits(fill_style_bits); // fill_style_0
}
if ( state_fill_style1 ) {
reader.ReadUnsignedBits(fill_style_bits); // fill_style_1
}
if ( state_line_style ) {
reader.ReadUnsignedBits(line_style_bits); // line_style
}
if ( state_new_styles ) {
ReadFillStyles(reader, allow_big_array, with_alpha);
SkipLineStyles(reader, allow_big_array, with_alpha, line2_type);
fill_style_bits = reader.ReadUnsignedBits(4);
line_style_bits = reader.ReadUnsignedBits(4);
}
return false;
}
}
}
static void SkipStraigtEdgeShapeRecord(SwfStreamReader reader) {
var num_bits = reader.ReadUnsignedBits(4) + 2;
var general_line_flag = reader.ReadBit();
var vert_line_flag = general_line_flag ? false : reader.ReadBit();
if ( general_line_flag || !vert_line_flag ) {
reader.ReadSignedBits(num_bits); // delta_x
}
if ( general_line_flag || vert_line_flag ) {
reader.ReadSignedBits(num_bits); // delta_y
}
}
static void SkipCurvedEdgeShapeRecord(SwfStreamReader reader) {
var num_bits = reader.ReadUnsignedBits(4) + 2;
reader.ReadSignedBits(num_bits); // control_delta_x
reader.ReadSignedBits(num_bits); // control_delta_y
reader.ReadSignedBits(num_bits); // anchor_delta_x
reader.ReadSignedBits(num_bits); // anchor_delta_y
}
}
}

View File

@@ -26,10 +26,10 @@ namespace FlashTools.Internal.SwfTools.SwfTypes {
stream.WriteByte((byte)Format[1]);
stream.WriteByte((byte)Format[2]);
stream.WriteByte(Version);
stream.WriteByte((byte)((FileLength >> 0) & 0xff));
stream.WriteByte((byte)((FileLength >> 8) & 0xff));
stream.WriteByte((byte)((FileLength >> 16) & 0xff));
stream.WriteByte((byte)((FileLength >> 24) & 0xff));
stream.WriteByte((byte)((FileLength >> 0) & 0xFF));
stream.WriteByte((byte)((FileLength >> 8) & 0xFF));
stream.WriteByte((byte)((FileLength >> 16) & 0xFF));
stream.WriteByte((byte)((FileLength >> 24) & 0xFF));
}
public override string ToString() {