зеркало из https://github.com/mozilla/shumway.git
Move player/timeline.ts to flash/symbol.ts and move most SymbolFoo classes to the Foo class they represent
This commit is contained in:
Родитель
900c42275f
Коммит
a5a8c71386
|
@ -41,7 +41,7 @@ module Shumway.AVM2.AS.avm1lib {
|
|||
static loadBitmap(symbolId: string): flash.display.BitmapData {
|
||||
symbolId = asCoerceString(symbolId);
|
||||
var symbol = AVM1Context.instance.getAsset(symbolId);
|
||||
if (symbol && symbol.symbolProps instanceof Shumway.Timeline.BitmapSymbol) {
|
||||
if (symbol && symbol.symbolProps instanceof flash.display.BitmapSymbol) {
|
||||
var bitmap = AVM1BitmapData.initializeFrom(symbol);
|
||||
bitmap.class.instanceConstructorNoInitialize.call(bitmap);
|
||||
return bitmap;
|
||||
|
|
|
@ -185,7 +185,7 @@ module Shumway.AVM2.AS.avm1lib {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
var props: Timeline.SpriteSymbol = Object.create(symbol.symbolProps);
|
||||
var props: flash.display.SpriteSymbol = Object.create(symbol.symbolProps);
|
||||
props.avm1Name = name;
|
||||
props.avm1SymbolClass = symbol.theClass;
|
||||
|
||||
|
|
|
@ -61,6 +61,12 @@ declare module Shumway.AVM2.AS.flash {
|
|||
data: {buttonActions: Shumway.Timeline.AVM1ButtonAction[]}
|
||||
}
|
||||
}
|
||||
|
||||
class BitmapSymbol {}
|
||||
class SpriteSymbol {
|
||||
avm1Name: string;
|
||||
avm1SymbolClass;
|
||||
}
|
||||
}
|
||||
module events {
|
||||
class EventDispatcher extends ASNative {
|
||||
|
@ -100,9 +106,4 @@ declare module Shumway.Timeline {
|
|||
actionsData: Uint8Array;
|
||||
actionsBlock: AVM1.AVM1ActionsData;
|
||||
}
|
||||
class BitmapSymbol {}
|
||||
class SpriteSymbol {
|
||||
avm1Name: string;
|
||||
avm1SymbolClass;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
static classInitializer: any = null;
|
||||
|
||||
// Called whenever an instance of the class is initialized.
|
||||
static initializer: any = function (symbol: Shumway.Timeline.BitmapSymbol) {
|
||||
static initializer: any = function (symbol: flash.display.BitmapSymbol) {
|
||||
var self: Bitmap = this;
|
||||
|
||||
self._bitmapData = null;
|
||||
|
|
|
@ -43,8 +43,8 @@ module Shumway.AVM2.AS.flash.display {
|
|||
// ...
|
||||
};
|
||||
|
||||
_symbol: Shumway.Timeline.BitmapSymbol;
|
||||
static initializer: any = function (symbol: Shumway.Timeline.BitmapSymbol) {
|
||||
_symbol: BitmapSymbol;
|
||||
static initializer: any = function (symbol: BitmapSymbol) {
|
||||
this._symbol = symbol;
|
||||
};
|
||||
|
||||
|
@ -908,4 +908,52 @@ module Shumway.AVM2.AS.flash.display {
|
|||
matrix: flash.geom.Matrix, colorTransform: flash.geom.ColorTransform,
|
||||
blendMode: string, clipRect: flash.geom.Rectangle, smoothing: boolean);
|
||||
}
|
||||
|
||||
export class BitmapSymbol extends Timeline.DisplaySymbol {
|
||||
width: number;
|
||||
height: number;
|
||||
image: any; // Image, but tsc doesn't like that.
|
||||
data: Uint8Array;
|
||||
type: ImageType;
|
||||
|
||||
private sharedInstance: flash.display.BitmapData;
|
||||
|
||||
constructor(data: Timeline.SymbolData) {
|
||||
super(data, flash.display.BitmapData, false);
|
||||
}
|
||||
|
||||
static FromData(data: any): BitmapSymbol {
|
||||
var symbol = new BitmapSymbol(data);
|
||||
symbol.width = data.width;
|
||||
symbol.height = data.height;
|
||||
symbol.image = data.image;
|
||||
symbol.data = data.data;
|
||||
switch (data.mimeType) {
|
||||
case "application/octet-stream":
|
||||
symbol.type = data.dataType;
|
||||
break;
|
||||
case "image/jpeg":
|
||||
symbol.type = ImageType.JPEG;
|
||||
break;
|
||||
case "image/png":
|
||||
symbol.type = ImageType.PNG;
|
||||
break;
|
||||
case "image/gif":
|
||||
symbol.type = ImageType.GIF;
|
||||
break;
|
||||
default:
|
||||
notImplemented(data.mimeType);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
getSharedInstance() {
|
||||
return this.sharedInstance || this.createSharedInstance();
|
||||
}
|
||||
createSharedInstance() {
|
||||
this.sharedInstance = this.symbolClass.initializeFrom(this);
|
||||
this.symbolClass.instanceConstructorNoInitialize.call(this.sharedInstance);
|
||||
return this.sharedInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
callConstructor: boolean): DisplayObject {
|
||||
var symbol = state.symbol;
|
||||
if (!symbol) {
|
||||
var ownSymbol = <Timeline.SpriteSymbol>this._symbol;
|
||||
var ownSymbol = <flash.display.SpriteSymbol>this._symbol;
|
||||
symbol = <Timeline.DisplaySymbol>ownSymbol.loaderInfo.getSymbolById(state.symbolId);
|
||||
state.symbol = symbol;
|
||||
}
|
||||
|
@ -1650,12 +1650,12 @@ module Shumway.AVM2.AS.flash.display {
|
|||
_setStaticContentFromSymbol(symbol: Shumway.Timeline.DisplaySymbol) {
|
||||
release || assert(!symbol.dynamic);
|
||||
if (this._canHaveGraphics()) {
|
||||
release || assert(symbol instanceof Shumway.Timeline.ShapeSymbol);
|
||||
this._graphics = (<Shumway.Timeline.ShapeSymbol>symbol).graphics;
|
||||
release || assert(symbol instanceof flash.display.ShapeSymbol);
|
||||
this._graphics = (<flash.display.ShapeSymbol>symbol).graphics;
|
||||
this._setDirtyFlags(DisplayObjectFlags.DirtyGraphics);
|
||||
} else if (flash.text.StaticText.isType(this)) {
|
||||
release || assert(symbol instanceof Shumway.Timeline.TextSymbol);
|
||||
var textSymbol = <Shumway.Timeline.TextSymbol>symbol;
|
||||
release || assert(symbol instanceof flash.text.TextSymbol);
|
||||
var textSymbol = <flash.text.TextSymbol>symbol;
|
||||
(<flash.text.StaticText>this)._textContent = textSymbol.textContent;
|
||||
this._setDirtyFlags(DisplayObjectFlags.DirtyTextContent);
|
||||
}
|
||||
|
|
|
@ -468,7 +468,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
this._applyLoadUpdate(this._queuedLoadUpdates.shift());
|
||||
}
|
||||
|
||||
private createContentRoot(symbol: Timeline.SpriteSymbol, sceneData) {
|
||||
private createContentRoot(symbol: flash.display.SpriteSymbol, sceneData) {
|
||||
var root = symbol.symbolClass.initializeFrom(symbol);
|
||||
// The root object gets a default of 'rootN', which doesn't use up a DisplayObject instance
|
||||
// ID.
|
||||
|
|
|
@ -281,37 +281,37 @@ module Shumway.AVM2.AS.flash.display {
|
|||
// TODO: replace this switch with a table lookup.
|
||||
switch (data.type) {
|
||||
case 'shape':
|
||||
symbol = Timeline.ShapeSymbol.FromData(data, this);
|
||||
symbol = flash.display.ShapeSymbol.FromData(data, this);
|
||||
break;
|
||||
case 'morphshape':
|
||||
symbol = Timeline.MorphShapeSymbol.FromData(data, this);
|
||||
symbol = flash.display.MorphShapeSymbol.FromData(data, this);
|
||||
break;
|
||||
case 'image':
|
||||
symbol = Timeline.BitmapSymbol.FromData(data.definition);
|
||||
symbol = flash.display.BitmapSymbol.FromData(data.definition);
|
||||
break;
|
||||
case 'label':
|
||||
symbol = Timeline.TextSymbol.FromLabelData(data, this);
|
||||
symbol = flash.text.TextSymbol.FromLabelData(data, this);
|
||||
break;
|
||||
case 'text':
|
||||
symbol = Timeline.TextSymbol.FromTextData(data, this);
|
||||
symbol = flash.text.TextSymbol.FromTextData(data, this);
|
||||
break;
|
||||
case 'button':
|
||||
symbol = Timeline.ButtonSymbol.FromData(data, this);
|
||||
symbol = flash.display.ButtonSymbol.FromData(data, this);
|
||||
break;
|
||||
case 'sprite':
|
||||
symbol = Timeline.SpriteSymbol.FromData(data, this);
|
||||
symbol = flash.display.SpriteSymbol.FromData(data, this);
|
||||
break;
|
||||
case 'font':
|
||||
// Fonts are eagerly parsed and have their data in `definition`.
|
||||
if (data.definition) {
|
||||
data = data.definition;
|
||||
}
|
||||
symbol = Timeline.FontSymbol.FromData(data);
|
||||
symbol = flash.text.FontSymbol.FromData(data);
|
||||
var font = flash.text.Font.initializeFrom(symbol);
|
||||
flash.text.Font.instanceConstructorNoInitialize.call(font);
|
||||
break;
|
||||
case 'sound':
|
||||
symbol = Timeline.SoundSymbol.FromData(data);
|
||||
symbol = flash.media.SoundSymbol.FromData(data);
|
||||
break;
|
||||
case 'binary':
|
||||
symbol = Timeline.BinarySymbol.FromData(data);
|
||||
|
@ -322,10 +322,11 @@ module Shumway.AVM2.AS.flash.display {
|
|||
return symbol;
|
||||
}
|
||||
|
||||
getRootSymbol(): Timeline.SpriteSymbol {
|
||||
var symbol = <Timeline.SpriteSymbol>this._dictionary[0];
|
||||
getRootSymbol(): flash.display.SpriteSymbol {
|
||||
var symbol = <flash.display.SpriteSymbol>this._dictionary[0];
|
||||
if (!symbol) {
|
||||
symbol = new Timeline.SpriteSymbol({id: 0, className: this._file.symbolClassesMap[0]}, this);
|
||||
symbol = new flash.display.SpriteSymbol({id: 0, className: this._file.symbolClassesMap[0]},
|
||||
this);
|
||||
symbol.isRoot = true;
|
||||
if (this._actionScriptVersion === ActionScriptVersion.ACTIONSCRIPT2) {
|
||||
symbol.isAVM1Object = true;
|
||||
|
|
|
@ -15,14 +15,12 @@
|
|||
*/
|
||||
// Class: MorphShape
|
||||
module Shumway.AVM2.AS.flash.display {
|
||||
import assert = Shumway.Debug.assert;
|
||||
|
||||
export class MorphShape extends flash.display.DisplayObject {
|
||||
static classSymbols: string [] = null; // [];
|
||||
static instanceSymbols: string [] = null; // [];
|
||||
|
||||
static classInitializer: any = null;
|
||||
static initializer: any = function (symbol: Shumway.Timeline.MorphShapeSymbol) {
|
||||
static initializer: any = function (symbol: flash.display.MorphShapeSymbol) {
|
||||
var self: MorphShape = this;
|
||||
self._graphics = null;
|
||||
if (symbol) {
|
||||
|
@ -56,4 +54,22 @@ module Shumway.AVM2.AS.flash.display {
|
|||
return !!graphics && graphics._containsPoint(localX, localY, true, this._ratio / 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
export class MorphShapeSymbol extends flash.display.ShapeSymbol {
|
||||
morphFillBounds: Bounds;
|
||||
morphLineBounds: Bounds;
|
||||
constructor(data: Timeline.SymbolData) {
|
||||
super(data, flash.display.MorphShape);
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): MorphShapeSymbol {
|
||||
var symbol = new MorphShapeSymbol(data);
|
||||
symbol._setBoundsFromData(data);
|
||||
symbol.graphics = flash.display.Graphics.FromData(data);
|
||||
symbol.processRequires(data.require, loaderInfo);
|
||||
symbol.morphFillBounds = data.morphFillBounds;
|
||||
symbol.morphLineBounds = data.morphLineBounds;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
var info = start.soundInfo;
|
||||
var sound: SoundClip = sounds[symbolId];
|
||||
if (!sound) {
|
||||
var symbolInfo: Timeline.SoundSymbol = <Timeline.SoundSymbol>loaderInfo.getSymbolById(symbolId);
|
||||
var symbolInfo = <flash.media.SoundSymbol>loaderInfo.getSymbolById(symbolId);
|
||||
if (!symbolInfo) {
|
||||
continue;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
}
|
||||
|
||||
// Called whenever an instance of the class is initialized.
|
||||
static initializer: any = function (symbol: Shumway.Timeline.SpriteSymbol) {
|
||||
static initializer: any = function (symbol: flash.display.SpriteSymbol) {
|
||||
var self: MovieClip = this;
|
||||
|
||||
DisplayObject._advancableInstances.push(self);
|
||||
|
@ -225,7 +225,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
}
|
||||
|
||||
_addFrame(frameInfo: any) {
|
||||
var spriteSymbol = <Timeline.SpriteSymbol><any>this._symbol;
|
||||
var spriteSymbol = <flash.display.SpriteSymbol><any>this._symbol;
|
||||
var frames = spriteSymbol.frames;
|
||||
frames.push(frameInfo.frameDelta);
|
||||
if (frameInfo.labelName) {
|
||||
|
@ -523,7 +523,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
var state = stateAtDepth[depth];
|
||||
// Eagerly create the symbol here, because it's needed in the canBeAnimated check below.
|
||||
if (state && state.symbolId > -1 && !state.symbol) {
|
||||
var ownSymbol = <Timeline.SpriteSymbol>this._symbol;
|
||||
var ownSymbol = <flash.display.SpriteSymbol>this._symbol;
|
||||
state.symbol = <Timeline.DisplaySymbol>ownSymbol.loaderInfo.getSymbolById(state.symbolId);
|
||||
}
|
||||
if (child) {
|
||||
|
@ -710,7 +710,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
|
||||
get _avm1SymbolClass(): any {
|
||||
return (this._symbol &&
|
||||
(<Timeline.SpriteSymbol>this._symbol).avm1SymbolClass) || null;
|
||||
(<flash.display.SpriteSymbol>this._symbol).avm1SymbolClass) || null;
|
||||
}
|
||||
|
||||
get _isFullyLoaded(): boolean {
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
// Class: Shape
|
||||
module Shumway.AVM2.AS.flash.display {
|
||||
import notImplemented = Shumway.Debug.notImplemented;
|
||||
import warning = Shumway.Debug.warning;
|
||||
|
||||
export class Shape extends flash.display.DisplayObject {
|
||||
static classSymbols: string [] = null; // [];
|
||||
static instanceSymbols: string [] = null; // [];
|
||||
|
||||
static classInitializer: any = null;
|
||||
static initializer: any = function (symbol: Shumway.Timeline.ShapeSymbol) {
|
||||
static initializer: any = function (symbol: ShapeSymbol) {
|
||||
var self: Shape = this;
|
||||
self._graphics = null;
|
||||
if (symbol) {
|
||||
|
@ -55,4 +55,37 @@ module Shumway.AVM2.AS.flash.display {
|
|||
return !!graphics && graphics._containsPoint(localX, localY, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShapeSymbol extends Timeline.DisplaySymbol {
|
||||
graphics: flash.display.Graphics = null;
|
||||
|
||||
constructor(data: Timeline.SymbolData, symbolClass: Shumway.AVM2.AS.ASClass) {
|
||||
super(data, symbolClass, false);
|
||||
}
|
||||
|
||||
static FromData(data: Timeline.SymbolData, loaderInfo: flash.display.LoaderInfo): ShapeSymbol {
|
||||
var symbol = new ShapeSymbol(data, flash.display.Shape);
|
||||
symbol._setBoundsFromData(data);
|
||||
symbol.graphics = flash.display.Graphics.FromData(data);
|
||||
symbol.processRequires((<any>data).require, loaderInfo);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
processRequires(dependencies: any[], loaderInfo: flash.display.LoaderInfo): void {
|
||||
if (!dependencies) {
|
||||
return;
|
||||
}
|
||||
var textures = this.graphics.getUsedTextures();
|
||||
for (var i = 0; i < dependencies.length; i++) {
|
||||
var symbol = <flash.display.BitmapSymbol>loaderInfo.getSymbolById(dependencies[i]);
|
||||
if (!symbol) {
|
||||
warning("Bitmap symbol " + dependencies[i] + " required by shape, but not defined.");
|
||||
textures.push(null);
|
||||
// TODO: handle null-textures from invalid SWFs correctly.
|
||||
continue;
|
||||
}
|
||||
textures.push(symbol.getSharedInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ module Shumway.AVM2.AS.flash.display {
|
|||
import notImplemented = Shumway.Debug.notImplemented;
|
||||
import asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
|
||||
import assert = Shumway.Debug.assert;
|
||||
import ButtonSymbol = Shumway.Timeline.ButtonSymbol;
|
||||
|
||||
export class SimpleButton extends flash.display.InteractiveObject {
|
||||
|
||||
|
@ -275,4 +274,46 @@ module Shumway.AVM2.AS.flash.display {
|
|||
this._invalidateFillAndLineBounds(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
export class ButtonSymbol extends Timeline.DisplaySymbol {
|
||||
upState: Timeline.AnimationState = null;
|
||||
overState: Timeline.AnimationState = null;
|
||||
downState: Timeline.AnimationState = null;
|
||||
hitTestState: Timeline.AnimationState = null;
|
||||
loaderInfo: flash.display.LoaderInfo;
|
||||
|
||||
constructor(data: Timeline.SymbolData, loaderInfo: flash.display.LoaderInfo) {
|
||||
super(data, flash.display.SimpleButton, false);
|
||||
this.loaderInfo = loaderInfo;
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): ButtonSymbol {
|
||||
var symbol = new ButtonSymbol(data, loaderInfo);
|
||||
if (loaderInfo.actionScriptVersion === ActionScriptVersion.ACTIONSCRIPT2) {
|
||||
symbol.isAVM1Object = true;
|
||||
}
|
||||
var states = data.states;
|
||||
var character: flash.display.SpriteSymbol = null;
|
||||
var matrix: flash.geom.Matrix = null;
|
||||
var colorTransform: flash.geom.ColorTransform = null;
|
||||
var cmd;
|
||||
for (var stateName in states) {
|
||||
var commands = states[stateName];
|
||||
if (commands.length === 1) {
|
||||
cmd = commands[0];
|
||||
matrix = flash.geom.Matrix.FromUntyped(cmd.matrix);
|
||||
if (cmd.cxform) {
|
||||
colorTransform = flash.geom.ColorTransform.FromCXForm(cmd.cxform);
|
||||
}
|
||||
} else {
|
||||
cmd = {symbolId: -1};
|
||||
character = new flash.display.SpriteSymbol({id: -1, className: null}, loaderInfo);
|
||||
character.frames.push(new Timeline.FrameDelta(loaderInfo, commands));
|
||||
}
|
||||
symbol[stateName + 'State'] = new Timeline.AnimationState(cmd.symbolId, character, 0,
|
||||
matrix, colorTransform);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
static classInitializer: any = null;
|
||||
|
||||
// Called whenever an instance of the class is initialized.
|
||||
static initializer: any = function (symbol: Timeline.SpriteSymbol) {
|
||||
static initializer: any = function (symbol: SpriteSymbol) {
|
||||
var self: Sprite = this;
|
||||
|
||||
self._graphics = null;
|
||||
|
@ -75,7 +75,7 @@ module Shumway.AVM2.AS.flash.display {
|
|||
_hitTarget: flash.display.Sprite;
|
||||
|
||||
_addFrame(frameInfo: any) {
|
||||
var frames = (<Timeline.SpriteSymbol><any>this._symbol).frames;
|
||||
var frames = (<SpriteSymbol><any>this._symbol).frames;
|
||||
frames.push(frameInfo.frameDelta);
|
||||
if (frames.length === 1) {
|
||||
this._initializeChildren(frames[0]);
|
||||
|
@ -199,4 +199,48 @@ module Shumway.AVM2.AS.flash.display {
|
|||
return !!graphics && graphics._containsPoint(localX, localY, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
export class SpriteSymbol extends Timeline.DisplaySymbol {
|
||||
numFrames: number = 1;
|
||||
frames: Timeline.FrameDelta[] = [];
|
||||
labels: flash.display.FrameLabel[] = [];
|
||||
frameScripts: any[] = [];
|
||||
isRoot: boolean;
|
||||
avm1Name: string;
|
||||
avm1SymbolClass;
|
||||
loaderInfo: flash.display.LoaderInfo;
|
||||
|
||||
constructor(data: Timeline.SymbolData, loaderInfo: flash.display.LoaderInfo) {
|
||||
super(data, flash.display.MovieClip, true);
|
||||
this.loaderInfo = loaderInfo;
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): SpriteSymbol {
|
||||
var symbol = new SpriteSymbol(data, loaderInfo);
|
||||
symbol.numFrames = data.frameCount;
|
||||
if (loaderInfo.actionScriptVersion === ActionScriptVersion.ACTIONSCRIPT2) {
|
||||
symbol.isAVM1Object = true;
|
||||
symbol.avm1Context = loaderInfo._avm1Context;
|
||||
}
|
||||
symbol.frameScripts = [];
|
||||
var frames = data.frames;
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
var frameInfo;
|
||||
frameInfo = loaderInfo.getFrame(data, i);
|
||||
if (frameInfo.actionBlocks) {
|
||||
symbol.frameScripts.push(i);
|
||||
symbol.frameScripts.push.apply(symbol.frameScripts, frameInfo.actionBlocks);
|
||||
}
|
||||
if (frameInfo.labelName) {
|
||||
symbol.labels.push(new flash.display.FrameLabel(frameInfo.labelName, i + 1));
|
||||
}
|
||||
var frame = frameInfo.frameDelta;
|
||||
var repeat = frameInfo.repeat || 1;
|
||||
while (repeat--) {
|
||||
symbol.frames.push(frame);
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ module Shumway.AVM2.AS.flash.media {
|
|||
static classInitializer: any = null;
|
||||
|
||||
// Called whenever an instance of the class is initialized.
|
||||
static initializer: any = function (symbol: Timeline.SoundSymbol) {
|
||||
static initializer: any = function (symbol: SoundSymbol) {
|
||||
this._playQueue = [];
|
||||
this._url = null;
|
||||
this._length = 0;
|
||||
|
@ -253,4 +253,24 @@ module Shumway.AVM2.AS.flash.media {
|
|||
stream.load(request);
|
||||
}
|
||||
}
|
||||
|
||||
export class SoundSymbol extends Timeline.Symbol {
|
||||
channels: number;
|
||||
sampleRate: number;
|
||||
pcm: Float32Array;
|
||||
packaged;
|
||||
|
||||
constructor(data: Timeline.SymbolData) {
|
||||
super(data, flash.media.Sound);
|
||||
}
|
||||
|
||||
static FromData(data: any): SoundSymbol {
|
||||
var symbol = new SoundSymbol(data);
|
||||
symbol.channels = data.channels;
|
||||
symbol.sampleRate = data.sampleRate;
|
||||
symbol.pcm = data.pcm;
|
||||
symbol.packaged = data.packaged;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
///<reference path='../TextContent.ts' />
|
||||
///<reference path='options.ts' />
|
||||
|
||||
///<reference path='symbol.ts' />
|
||||
|
||||
///<reference path='geom/Matrix.ts' />
|
||||
///<reference path='geom/Matrix3D.ts' />
|
||||
///<reference path='geom/Orientation3D.ts' />
|
||||
|
@ -412,6 +414,4 @@
|
|||
|
||||
///<reference path='avm1.d.ts' />
|
||||
|
||||
///<reference path='../player/timeline.ts' />
|
||||
|
||||
///<reference path='linker.ts' />
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
/**
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
module Shumway.Timeline {
|
||||
import notImplemented = Shumway.Debug.notImplemented;
|
||||
import isInteger = Shumway.isInteger;
|
||||
import assert = Shumway.Debug.assert;
|
||||
import warning = Shumway.Debug.warning;
|
||||
import abstractMethod = Shumway.Debug.abstractMethod;
|
||||
import Bounds = Shumway.Bounds;
|
||||
import ColorUtilities = Shumway.ColorUtilities;
|
||||
import flash = Shumway.AVM2.AS.flash;
|
||||
import SwfTag = Shumway.SWF.Parser.SwfTag;
|
||||
import PlaceObjectFlags = Shumway.SWF.Parser.PlaceObjectFlags;
|
||||
import SoundStream = Shumway.SWF.Parser.SoundStream;
|
||||
|
||||
import ActionScriptVersion = flash.display.ActionScriptVersion;
|
||||
|
||||
export interface SymbolData {id: number; className: string}
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class Symbol {
|
||||
data: any;
|
||||
isAVM1Object: boolean;
|
||||
avm1Context: Shumway.AVM1.AVM1Context;
|
||||
symbolClass: Shumway.AVM2.AS.ASClass;
|
||||
|
||||
constructor(data: SymbolData, symbolDefaultClass: Shumway.AVM2.AS.ASClass) {
|
||||
release || assert (isInteger(data.id));
|
||||
this.data = data;
|
||||
if (data.className) {
|
||||
var appDomain = Shumway.AVM2.Runtime.AVM2.instance.applicationDomain;
|
||||
try {
|
||||
var symbolClass = appDomain.getClass(data.className);
|
||||
this.symbolClass = symbolClass;
|
||||
} catch (e) {
|
||||
warning ("Symbol " + data.id + " bound to non-existing class " + data.className);
|
||||
this.symbolClass = symbolDefaultClass;
|
||||
}
|
||||
} else {
|
||||
this.symbolClass = symbolDefaultClass;
|
||||
}
|
||||
this.isAVM1Object = false;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this.data.id;
|
||||
}
|
||||
}
|
||||
|
||||
export class DisplaySymbol extends Symbol {
|
||||
fillBounds: Bounds;
|
||||
lineBounds: Bounds;
|
||||
scale9Grid: Bounds;
|
||||
dynamic: boolean;
|
||||
|
||||
constructor(data: SymbolData, symbolClass: Shumway.AVM2.AS.ASClass, dynamic: boolean) {
|
||||
super(data, symbolClass);
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
_setBoundsFromData(data: any) {
|
||||
this.fillBounds = data.fillBounds ? Bounds.FromUntyped(data.fillBounds) : null;
|
||||
this.lineBounds = data.lineBounds ? Bounds.FromUntyped(data.lineBounds) : null;
|
||||
if (!this.lineBounds && this.fillBounds) {
|
||||
this.lineBounds = this.fillBounds.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BinarySymbol extends Symbol {
|
||||
buffer: Uint8Array;
|
||||
byteLength: number;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.utils.ByteArray);
|
||||
}
|
||||
|
||||
static FromData(data: any): BinarySymbol {
|
||||
var symbol = new BinarySymbol(data);
|
||||
symbol.buffer = data.data;
|
||||
symbol.byteLength = data.data.byteLength;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class AnimationState {
|
||||
constructor(public symbolId: number,
|
||||
public symbol: DisplaySymbol = null,
|
||||
public depth: number = 0,
|
||||
public matrix: flash.geom.Matrix = null,
|
||||
public colorTransform: flash.geom.ColorTransform = null,
|
||||
public ratio: number = 0,
|
||||
public name: string = null,
|
||||
public clipDepth: number = -1,
|
||||
public filters: any [] = null,
|
||||
public blendMode: string = null,
|
||||
public cacheAsBitmap: boolean = false,
|
||||
public visible: boolean = true,
|
||||
public events: any [] = null,
|
||||
public variableName: string = null) {
|
||||
|
||||
}
|
||||
|
||||
canBeAnimated(obj: flash.display.DisplayObject): boolean {
|
||||
if (!obj._hasFlags(flash.display.DisplayObjectFlags.AnimatedByTimeline)) {
|
||||
return false;
|
||||
}
|
||||
if (obj._depth !== this.depth) {
|
||||
return false;
|
||||
}
|
||||
var symbol = this.symbol;
|
||||
if (symbol) {
|
||||
if (symbol.dynamic) {
|
||||
return false;
|
||||
}
|
||||
if (obj._clipDepth !== this.clipDepth) {
|
||||
return false;
|
||||
}
|
||||
if (!symbol.symbolClass.isType(obj)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
canBeReused(obj: flash.display.DisplayObject): boolean {
|
||||
var symbol = this.symbol;
|
||||
if (symbol && symbol === obj._symbol &&
|
||||
obj._hasFlags(flash.display.DisplayObjectFlags.OwnedByTimeline)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class SoundStart {
|
||||
constructor(public soundId: number, public soundInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class FrameDelta {
|
||||
private _stateAtDepth: Shumway.Map<AnimationState>;
|
||||
private _soundStarts: SoundStart[];
|
||||
private _soundStreamHead: SoundStream;
|
||||
private _soundStreamBlock: {data: Uint8Array};
|
||||
|
||||
get stateAtDepth() {
|
||||
return this._stateAtDepth || this._initialize();
|
||||
}
|
||||
|
||||
get soundStarts() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStarts;
|
||||
}
|
||||
|
||||
// TODO: refactor streaming sound support to delay sound parsing until needed.
|
||||
// These two fields aren't used for now, but will perhaps be helpful in the above.
|
||||
get soundStreamHead() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStreamHead;
|
||||
}
|
||||
|
||||
get soundStreamBlock() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStreamBlock;
|
||||
}
|
||||
|
||||
constructor(private loaderInfo: flash.display.LoaderInfo, private commands: any []) {
|
||||
this._stateAtDepth = null;
|
||||
this._soundStarts = null;
|
||||
this._soundStreamHead = null;
|
||||
this._soundStreamBlock = null;
|
||||
}
|
||||
|
||||
private _initialize(): Shumway.Map<AnimationState> {
|
||||
var states: Shumway.Map<AnimationState> = this._stateAtDepth = Object.create(null);
|
||||
var commands = this.commands;
|
||||
if (!commands) {
|
||||
return states;
|
||||
}
|
||||
var loaderInfo = this.loaderInfo;
|
||||
for (var i = 0; i < commands.length; i++) {
|
||||
var cmd = 'depth' in commands[i] ?
|
||||
commands[i] :
|
||||
<any>loaderInfo._file.getParsedTag(commands[i]);
|
||||
var depth = cmd.depth;
|
||||
switch (cmd.code) {
|
||||
case SwfTag.CODE_REMOVE_OBJECT:
|
||||
case SwfTag.CODE_REMOVE_OBJECT2:
|
||||
states[depth] = null;
|
||||
break;
|
||||
case SwfTag.CODE_START_SOUND:
|
||||
var soundStarts = this._soundStarts || (this._soundStarts = []);
|
||||
soundStarts.push(new SoundStart(cmd.soundId, cmd.soundInfo));
|
||||
break;
|
||||
case SwfTag.CODE_SOUND_STREAM_HEAD:
|
||||
case SwfTag.CODE_SOUND_STREAM_HEAD2:
|
||||
this._soundStreamHead = SoundStream.FromTag(cmd);
|
||||
break;
|
||||
case SwfTag.CODE_SOUND_STREAM_BLOCK:
|
||||
this._soundStreamBlock = cmd;
|
||||
break;
|
||||
case SwfTag.CODE_PLACE_OBJECT:
|
||||
case SwfTag.CODE_PLACE_OBJECT2:
|
||||
case SwfTag.CODE_PLACE_OBJECT3:
|
||||
var symbol: DisplaySymbol = null;
|
||||
var matrix: flash.geom.Matrix = null;
|
||||
var colorTransform: flash.geom.ColorTransform = null;
|
||||
var filters: flash.filters.BitmapFilter[] = null;
|
||||
var events: any[] = loaderInfo._allowCodeExecution ? cmd.events : 0;
|
||||
if (cmd.symbolId) {
|
||||
symbol = <DisplaySymbol>loaderInfo.getSymbolById(cmd.symbolId);
|
||||
if (!symbol) {
|
||||
warning("Symbol " + cmd.symbolId + " is not defined.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasMatrix) {
|
||||
matrix = flash.geom.Matrix.FromUntyped(cmd.matrix);
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasColorTransform) {
|
||||
colorTransform = flash.geom.ColorTransform.FromCXForm(cmd.cxform);
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasFilterList) {
|
||||
filters = [];
|
||||
var swfFilters = cmd.filters;
|
||||
for (var j = 0; j < swfFilters.length; j++) {
|
||||
var obj = swfFilters[j];
|
||||
var filter: flash.filters.BitmapFilter;
|
||||
switch (obj.type) {
|
||||
case 0: filter = flash.filters.DropShadowFilter.FromUntyped(obj); break;
|
||||
case 1: filter = flash.filters.BlurFilter.FromUntyped(obj); break;
|
||||
case 2: filter = flash.filters.GlowFilter.FromUntyped(obj); break;
|
||||
case 3: filter = flash.filters.BevelFilter.FromUntyped(obj); break;
|
||||
case 4: filter = flash.filters.GradientGlowFilter.FromUntyped(obj); break;
|
||||
case 5: filter = flash.filters.ConvolutionFilter.FromUntyped(obj); break;
|
||||
case 6: filter = flash.filters.ColorMatrixFilter.FromUntyped(obj); break;
|
||||
case 7: filter = flash.filters.GradientBevelFilter.FromUntyped(obj); break;
|
||||
}
|
||||
release || assert (filter, "Unknown filter type.");
|
||||
filters.push(filter);
|
||||
}
|
||||
}
|
||||
var state = new Timeline.AnimationState (
|
||||
cmd.symbolId,
|
||||
symbol,
|
||||
depth,
|
||||
matrix,
|
||||
colorTransform,
|
||||
cmd.ratio,
|
||||
cmd.name,
|
||||
cmd.clipDepth,
|
||||
filters,
|
||||
flash.display.BlendMode.fromNumber(cmd.blendMode),
|
||||
!!(cmd.flags & PlaceObjectFlags.HasCacheAsBitmap),
|
||||
cmd.flags & PlaceObjectFlags.HasVisible ? !!cmd.visibility : true,
|
||||
events,
|
||||
cmd.variableName
|
||||
);
|
||||
states[depth] = state;
|
||||
break;
|
||||
default:
|
||||
console.warn("Unhandled timeline control tag: " + cmd.code + ": " + SwfTag[cmd.code]);
|
||||
}
|
||||
|
||||
}
|
||||
this.commands = null;
|
||||
return states;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -845,7 +845,7 @@ module Shumway.AVM2.AS.flash.text {
|
|||
static classSymbols: string [] = null;
|
||||
static instanceSymbols: string [] = null;
|
||||
|
||||
static initializer: any = function (symbol: Shumway.Timeline.FontSymbol) {
|
||||
static initializer: any = function (symbol: FontSymbol) {
|
||||
var self: Font = this;
|
||||
|
||||
// TODO: give fonts proper inter-SWF IDs, so multiple SWFs' fonts don't collide.
|
||||
|
@ -962,7 +962,7 @@ module Shumway.AVM2.AS.flash.text {
|
|||
private _fontType: string;
|
||||
|
||||
_id: number;
|
||||
_symbol: Shumway.Timeline.FontSymbol;
|
||||
_symbol: FontSymbol;
|
||||
|
||||
ascent: number;
|
||||
descent: number;
|
||||
|
@ -1017,4 +1017,31 @@ module Shumway.AVM2.AS.flash.text {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class FontSymbol extends Timeline.Symbol {
|
||||
name: string;
|
||||
id: number;
|
||||
bold: boolean;
|
||||
italic: boolean;
|
||||
codes: number[];
|
||||
originalSize: boolean;
|
||||
metrics: any;
|
||||
|
||||
constructor(data: Timeline.SymbolData) {
|
||||
super(data, Font);
|
||||
}
|
||||
|
||||
static FromData(data: any): FontSymbol {
|
||||
var symbol = new FontSymbol(data);
|
||||
symbol.name = data.name;
|
||||
// No need to keep the original data baggage around.
|
||||
symbol.data = {id: data.id};
|
||||
symbol.bold = data.bold;
|
||||
symbol.italic = data.italic;
|
||||
symbol.originalSize = data.originalSize;
|
||||
symbol.codes = data.codes;
|
||||
symbol.metrics = data.metrics;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ module Shumway.AVM2.AS.flash.text {
|
|||
static classSymbols: string [] = null;
|
||||
static instanceSymbols: string [] = null;
|
||||
|
||||
static initializer: any = function (symbol: Shumway.Timeline.TextSymbol) {
|
||||
static initializer: any = function (symbol: flash.text.TextSymbol) {
|
||||
var self: StaticText = this;
|
||||
self._textContent = null;
|
||||
if (symbol) {
|
||||
|
|
|
@ -18,6 +18,7 @@ module Shumway.AVM2.AS.flash.text {
|
|||
import notImplemented = Shumway.Debug.notImplemented;
|
||||
import dummyConstructor = Shumway.Debug.dummyConstructor;
|
||||
import assert = Shumway.Debug.assert;
|
||||
import warning = Shumway.Debug.warning;
|
||||
import somewhatImplemented = Shumway.Debug.somewhatImplemented;
|
||||
import throwError = Shumway.AVM2.Runtime.throwError;
|
||||
import asCoerceString = Shumway.AVM2.Runtime.asCoerceString;
|
||||
|
@ -33,7 +34,7 @@ module Shumway.AVM2.AS.flash.text {
|
|||
|
||||
static classInitializer: any = null;
|
||||
|
||||
static initializer: any = function (symbol: Shumway.Timeline.TextSymbol) {
|
||||
static initializer: any = function (symbol: TextSymbol) {
|
||||
var self: TextField = this;
|
||||
|
||||
self._alwaysShowSelection = false;
|
||||
|
@ -797,4 +798,165 @@ module Shumway.AVM2.AS.flash.text {
|
|||
notImplemented("public flash.text.TextField::getImageReference"); return;
|
||||
}
|
||||
}
|
||||
|
||||
export class TextSymbol extends Timeline.DisplaySymbol {
|
||||
color: number = 0;
|
||||
size: number = 0;
|
||||
font: string = "";
|
||||
fontClass: flash.text.Font = null;
|
||||
align: string = flash.text.TextFormatAlign.LEFT;
|
||||
leftMargin: number = 0;
|
||||
rightMargin: number = 0;
|
||||
indent: number = 0;
|
||||
leading: number = 0;
|
||||
multiline: boolean = false;
|
||||
wordWrap: boolean = false;
|
||||
embedFonts: boolean = false;
|
||||
selectable: boolean = true;
|
||||
border: boolean = false;
|
||||
initialText: string = "";
|
||||
html: boolean = false;
|
||||
displayAsPassword: boolean = false;
|
||||
type: string = flash.text.TextFieldType.DYNAMIC;
|
||||
maxChars: number = 0;
|
||||
autoSize: string = flash.text.TextFieldAutoSize.NONE;
|
||||
variableName: string = null;
|
||||
textContent: Shumway.TextContent = null;
|
||||
|
||||
constructor(data: Timeline.SymbolData) {
|
||||
super(data, flash.text.TextField, true);
|
||||
}
|
||||
|
||||
static FromTextData(data: any, loaderInfo: flash.display.LoaderInfo): TextSymbol {
|
||||
var symbol = new TextSymbol(data);
|
||||
symbol._setBoundsFromData(data);
|
||||
var tag = data.tag;
|
||||
if (data.static) {
|
||||
symbol.dynamic = false;
|
||||
symbol.symbolClass = flash.text.StaticText;
|
||||
if (tag.initialText) {
|
||||
var textContent = new Shumway.TextContent();
|
||||
textContent.bounds = symbol.lineBounds;
|
||||
textContent.parseHtml(tag.initialText);
|
||||
textContent.matrix = flash.geom.Matrix.FromUntyped(data.matrix);
|
||||
textContent.coords = data.coords;
|
||||
symbol.textContent = textContent;
|
||||
}
|
||||
}
|
||||
if (tag.hasColor) {
|
||||
symbol.color = tag.color >>> 8;
|
||||
}
|
||||
if (tag.hasFont) {
|
||||
symbol.size = tag.fontHeight;
|
||||
// Requesting the font symbol guarantees that it's loaded and initialized.
|
||||
var fontSymbol = loaderInfo.getSymbolById(tag.fontId);
|
||||
var font = flash.text.Font.getBySymbolId(tag.fontId);
|
||||
if (fontSymbol && font) {
|
||||
symbol.font = font.fontName;
|
||||
if (tag.fontClass) {
|
||||
var appDomain = Shumway.AVM2.Runtime.AVM2.instance.applicationDomain;
|
||||
symbol.fontClass = <flash.text.Font><any>appDomain.getClass(tag.fontClass);
|
||||
}
|
||||
} else {
|
||||
warning("Font " + tag.fontId + " is not defined.");
|
||||
}
|
||||
}
|
||||
if (tag.hasLayout) {
|
||||
symbol.align = flash.text.TextFormatAlign.fromNumber(tag.align);
|
||||
symbol.leftMargin = tag.leftMargin;
|
||||
symbol.rightMargin = tag.rightMargin;
|
||||
symbol.indent = tag.indent;
|
||||
symbol.leading = tag.leading;
|
||||
}
|
||||
symbol.multiline = !!tag.multiline;
|
||||
symbol.wordWrap = !!tag.wordWrap;
|
||||
symbol.embedFonts = !!tag.useOutlines;
|
||||
symbol.selectable = !tag.noSelect;
|
||||
symbol.border = !!tag.border;
|
||||
if (tag.hasText) {
|
||||
symbol.initialText = tag.initialText;
|
||||
}
|
||||
symbol.html = !!tag.html;
|
||||
symbol.displayAsPassword = !!tag.password;
|
||||
symbol.type = tag.readonly ? flash.text.TextFieldType.DYNAMIC :
|
||||
flash.text.TextFieldType.INPUT;
|
||||
if (tag.hasMaxLength) {
|
||||
symbol.maxChars = tag.maxLength;
|
||||
}
|
||||
symbol.autoSize = tag.autoSize ? flash.text.TextFieldAutoSize.LEFT : flash.text.TextFieldAutoSize.NONE;
|
||||
symbol.variableName = tag.variableName;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns raw DefineLabel tag data into an object that's consumable as a text symbol and then
|
||||
* passes that into `FromTextData`, returning the resulting TextSymbol.
|
||||
*
|
||||
* This has to be done outside the SWF parser because it relies on any used fonts being
|
||||
* available as symbols, which isn't the case in the SWF parser.
|
||||
*/
|
||||
static FromLabelData(data: any, loaderInfo: flash.display.LoaderInfo): TextSymbol {
|
||||
var bounds = data.fillBounds;
|
||||
var records = data.records;
|
||||
var coords = data.coords = [];
|
||||
var htmlText = '';
|
||||
var size = 12;
|
||||
var face = 'Times Roman';
|
||||
var color = 0;
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var codes: number[];
|
||||
for (var i = 0; i < records.length; i++) {
|
||||
var record = records[i];
|
||||
if (record.eot) {
|
||||
break;
|
||||
}
|
||||
if (record.hasFont) {
|
||||
var font = <flash.text.FontSymbol>loaderInfo.getSymbolById(record.fontId);
|
||||
font || Debug.warning('Label ' + data.id + 'refers to undefined font symbol ' +
|
||||
record.fontId);
|
||||
codes = font.codes;
|
||||
size = record.fontHeight;
|
||||
if (!font.originalSize) {
|
||||
size /= 20;
|
||||
}
|
||||
face = 'swffont' + record.fontId;
|
||||
}
|
||||
if (record.hasColor) {
|
||||
color = record.color >>> 8;
|
||||
}
|
||||
if (record.hasMoveX) {
|
||||
x = record.moveX;
|
||||
if (x < bounds.xMin) {
|
||||
bounds.xMin = x;
|
||||
}
|
||||
}
|
||||
if (record.hasMoveY) {
|
||||
y = record.moveY;
|
||||
if (y < bounds.yMin) {
|
||||
bounds.yMin = y;
|
||||
}
|
||||
}
|
||||
var text = '';
|
||||
var entries = record.entries;
|
||||
var j = 0;
|
||||
var entry;
|
||||
while ((entry = entries[j++])) {
|
||||
var code = codes[entry.glyphIndex];
|
||||
release || assert(code, 'undefined label glyph');
|
||||
var char = String.fromCharCode(code);
|
||||
text += charEscapeMap[char] || char;
|
||||
coords.push(x, y);
|
||||
x += entry.advance;
|
||||
}
|
||||
htmlText += '<font size="' + size + '" face="' + face + '"' + ' color="#' +
|
||||
('000000' + color.toString(16)).slice(-6) + '">' + text + '</font>';
|
||||
}
|
||||
data.tag.initialText = htmlText;
|
||||
return TextSymbol.FromTextData(data, loaderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
var charEscapeMap = {'<': '<', '>': '>', '&' : '&'};
|
||||
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ module Shumway.Player {
|
|||
*
|
||||
* TODO: Make sure we get called back if an error occurs while decoding the image.
|
||||
*/
|
||||
public decodeImage(bitmapSymbol: Shumway.Timeline.BitmapSymbol, resolve: (result) => void) {
|
||||
public decodeImage(bitmapSymbol: flash.display.BitmapSymbol, resolve: (result) => void) {
|
||||
release || assert (bitmapSymbol.type === ImageType.PNG ||
|
||||
bitmapSymbol.type === ImageType.GIF ||
|
||||
bitmapSymbol.type === ImageType.JPEG, "No need to decode any other image formats.");
|
||||
|
@ -532,7 +532,7 @@ module Shumway.Player {
|
|||
flash.display.MovieClip.reset();
|
||||
var symbolInstance = symbol.symbolClass.initializeFrom(symbol);
|
||||
symbol.symbolClass.instanceConstructorNoInitialize.call(symbolInstance);
|
||||
if (symbol instanceof Shumway.Timeline.BitmapSymbol) {
|
||||
if (symbol instanceof flash.display.BitmapSymbol) {
|
||||
symbolInstance = new flash.display.Bitmap(symbolInstance);
|
||||
}
|
||||
while (stage.numChildren > 0) {
|
||||
|
@ -564,8 +564,8 @@ module Shumway.Player {
|
|||
var frames = 1;
|
||||
if (symbol && symbol.id > 0) {
|
||||
show(symbol);
|
||||
if (symbol instanceof Shumway.Timeline.SpriteSymbol) {
|
||||
frames = (<Shumway.Timeline.SpriteSymbol>symbol).numFrames;
|
||||
if (symbol instanceof flash.display.SpriteSymbol) {
|
||||
frames = (<flash.display.SpriteSymbol>symbol).numFrames;
|
||||
}
|
||||
}
|
||||
if (playSymbolFrameDurationOption.value > 0) {
|
||||
|
|
|
@ -1,691 +0,0 @@
|
|||
/**
|
||||
* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
module Shumway.Timeline {
|
||||
import notImplemented = Shumway.Debug.notImplemented;
|
||||
import isInteger = Shumway.isInteger;
|
||||
import assert = Shumway.Debug.assert;
|
||||
import warning = Shumway.Debug.warning;
|
||||
import abstractMethod = Shumway.Debug.abstractMethod;
|
||||
import Bounds = Shumway.Bounds;
|
||||
import ColorUtilities = Shumway.ColorUtilities;
|
||||
import flash = Shumway.AVM2.AS.flash;
|
||||
import SwfTag = Shumway.SWF.Parser.SwfTag;
|
||||
import PlaceObjectFlags = Shumway.SWF.Parser.PlaceObjectFlags;
|
||||
import SoundStream = Shumway.SWF.Parser.SoundStream;
|
||||
|
||||
import ActionScriptVersion = flash.display.ActionScriptVersion;
|
||||
|
||||
export interface SymbolData {id: number; className: string}
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class Symbol {
|
||||
data: any;
|
||||
isAVM1Object: boolean;
|
||||
avm1Context: Shumway.AVM1.AVM1Context;
|
||||
symbolClass: Shumway.AVM2.AS.ASClass;
|
||||
|
||||
constructor(data: SymbolData, symbolDefaultClass: Shumway.AVM2.AS.ASClass) {
|
||||
release || assert (isInteger(data.id));
|
||||
this.data = data;
|
||||
if (data.className) {
|
||||
var appDomain = Shumway.AVM2.Runtime.AVM2.instance.applicationDomain;
|
||||
try {
|
||||
var symbolClass = appDomain.getClass(data.className);
|
||||
this.symbolClass = symbolClass;
|
||||
} catch (e) {
|
||||
warning ("Symbol " + data.id + " bound to non-existing class " + data.className);
|
||||
this.symbolClass = symbolDefaultClass;
|
||||
}
|
||||
} else {
|
||||
this.symbolClass = symbolDefaultClass;
|
||||
}
|
||||
this.isAVM1Object = false;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this.data.id;
|
||||
}
|
||||
}
|
||||
|
||||
export class DisplaySymbol extends Symbol {
|
||||
fillBounds: Bounds;
|
||||
lineBounds: Bounds;
|
||||
scale9Grid: Bounds;
|
||||
dynamic: boolean;
|
||||
|
||||
constructor(data: SymbolData, symbolClass: Shumway.AVM2.AS.ASClass, dynamic: boolean) {
|
||||
super(data, symbolClass);
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
_setBoundsFromData(data: any) {
|
||||
this.fillBounds = data.fillBounds ? Bounds.FromUntyped(data.fillBounds) : null;
|
||||
this.lineBounds = data.lineBounds ? Bounds.FromUntyped(data.lineBounds) : null;
|
||||
if (!this.lineBounds && this.fillBounds) {
|
||||
this.lineBounds = this.fillBounds.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ShapeSymbol extends DisplaySymbol {
|
||||
graphics: flash.display.Graphics = null;
|
||||
|
||||
constructor(data: SymbolData, symbolClass: Shumway.AVM2.AS.ASClass) {
|
||||
super(data, symbolClass, false);
|
||||
}
|
||||
|
||||
static FromData(data: SymbolData, loaderInfo: flash.display.LoaderInfo): ShapeSymbol {
|
||||
var symbol = new ShapeSymbol(data, flash.display.Shape);
|
||||
symbol._setBoundsFromData(data);
|
||||
symbol.graphics = flash.display.Graphics.FromData(data);
|
||||
symbol.processRequires((<any>data).require, loaderInfo);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
processRequires(dependencies: any[], loaderInfo: flash.display.LoaderInfo): void {
|
||||
if (!dependencies) {
|
||||
return;
|
||||
}
|
||||
var textures = this.graphics.getUsedTextures();
|
||||
for (var i = 0; i < dependencies.length; i++) {
|
||||
var symbol = <BitmapSymbol>loaderInfo.getSymbolById(dependencies[i]);
|
||||
if (!symbol) {
|
||||
warning("Bitmap symbol " + dependencies[i] + " required by shape, but not defined.");
|
||||
textures.push(null);
|
||||
// TODO: handle null-textures from invalid SWFs correctly.
|
||||
continue;
|
||||
}
|
||||
textures.push(symbol.getSharedInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class MorphShapeSymbol extends ShapeSymbol {
|
||||
morphFillBounds: Bounds;
|
||||
morphLineBounds: Bounds;
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.display.MorphShape);
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): MorphShapeSymbol {
|
||||
var symbol = new MorphShapeSymbol(data);
|
||||
symbol._setBoundsFromData(data);
|
||||
symbol.graphics = flash.display.Graphics.FromData(data);
|
||||
symbol.processRequires(data.require, loaderInfo);
|
||||
symbol.morphFillBounds = data.morphFillBounds;
|
||||
symbol.morphLineBounds = data.morphLineBounds;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
export class BitmapSymbol extends DisplaySymbol {
|
||||
width: number;
|
||||
height: number;
|
||||
image: any; // Image, but tsc doesn't like that.
|
||||
data: Uint8Array;
|
||||
type: ImageType;
|
||||
|
||||
private sharedInstance: flash.display.BitmapData;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.display.BitmapData, false);
|
||||
}
|
||||
|
||||
static FromData(data: any): BitmapSymbol {
|
||||
var symbol = new BitmapSymbol(data);
|
||||
symbol.width = data.width;
|
||||
symbol.height = data.height;
|
||||
symbol.image = data.image;
|
||||
symbol.data = data.data;
|
||||
switch (data.mimeType) {
|
||||
case "application/octet-stream":
|
||||
symbol.type = data.dataType;
|
||||
break;
|
||||
case "image/jpeg":
|
||||
symbol.type = ImageType.JPEG;
|
||||
break;
|
||||
case "image/png":
|
||||
symbol.type = ImageType.PNG;
|
||||
break;
|
||||
case "image/gif":
|
||||
symbol.type = ImageType.GIF;
|
||||
break;
|
||||
default:
|
||||
notImplemented(data.mimeType);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
getSharedInstance() {
|
||||
return this.sharedInstance || this.createSharedInstance();
|
||||
}
|
||||
createSharedInstance() {
|
||||
this.sharedInstance = this.symbolClass.initializeFrom(this);
|
||||
this.symbolClass.instanceConstructorNoInitialize.call(this.sharedInstance);
|
||||
return this.sharedInstance;
|
||||
}
|
||||
}
|
||||
|
||||
export class TextSymbol extends DisplaySymbol {
|
||||
color: number = 0;
|
||||
size: number = 0;
|
||||
font: string = "";
|
||||
fontClass: flash.text.Font = null;
|
||||
align: string = flash.text.TextFormatAlign.LEFT;
|
||||
leftMargin: number = 0;
|
||||
rightMargin: number = 0;
|
||||
indent: number = 0;
|
||||
leading: number = 0;
|
||||
multiline: boolean = false;
|
||||
wordWrap: boolean = false;
|
||||
embedFonts: boolean = false;
|
||||
selectable: boolean = true;
|
||||
border: boolean = false;
|
||||
initialText: string = "";
|
||||
html: boolean = false;
|
||||
displayAsPassword: boolean = false;
|
||||
type: string = flash.text.TextFieldType.DYNAMIC;
|
||||
maxChars: number = 0;
|
||||
autoSize: string = flash.text.TextFieldAutoSize.NONE;
|
||||
variableName: string = null;
|
||||
textContent: Shumway.TextContent = null;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.text.TextField, true);
|
||||
}
|
||||
|
||||
static FromTextData(data: any, loaderInfo: flash.display.LoaderInfo): TextSymbol {
|
||||
var symbol = new TextSymbol(data);
|
||||
symbol._setBoundsFromData(data);
|
||||
var tag = data.tag;
|
||||
if (data.static) {
|
||||
symbol.dynamic = false;
|
||||
symbol.symbolClass = flash.text.StaticText;
|
||||
if (tag.initialText) {
|
||||
var textContent = new Shumway.TextContent();
|
||||
textContent.bounds = symbol.lineBounds;
|
||||
textContent.parseHtml(tag.initialText);
|
||||
textContent.matrix = flash.geom.Matrix.FromUntyped(data.matrix);
|
||||
textContent.coords = data.coords;
|
||||
symbol.textContent = textContent;
|
||||
}
|
||||
}
|
||||
if (tag.hasColor) {
|
||||
symbol.color = tag.color >>> 8;
|
||||
}
|
||||
if (tag.hasFont) {
|
||||
symbol.size = tag.fontHeight;
|
||||
// Requesting the font symbol guarantees that it's loaded and initialized.
|
||||
var fontSymbol = loaderInfo.getSymbolById(tag.fontId);
|
||||
var font = flash.text.Font.getBySymbolId(tag.fontId);
|
||||
if (fontSymbol && font) {
|
||||
symbol.font = font.fontName;
|
||||
if (tag.fontClass) {
|
||||
var appDomain = Shumway.AVM2.Runtime.AVM2.instance.applicationDomain;
|
||||
symbol.fontClass = <flash.text.Font><any>appDomain.getClass(tag.fontClass);
|
||||
}
|
||||
} else {
|
||||
warning("Font " + tag.fontId + " is not defined.");
|
||||
}
|
||||
}
|
||||
if (tag.hasLayout) {
|
||||
symbol.align = flash.text.TextFormatAlign.fromNumber(tag.align);
|
||||
symbol.leftMargin = tag.leftMargin;
|
||||
symbol.rightMargin = tag.rightMargin;
|
||||
symbol.indent = tag.indent;
|
||||
symbol.leading = tag.leading;
|
||||
}
|
||||
symbol.multiline = !!tag.multiline;
|
||||
symbol.wordWrap = !!tag.wordWrap;
|
||||
symbol.embedFonts = !!tag.useOutlines;
|
||||
symbol.selectable = !tag.noSelect;
|
||||
symbol.border = !!tag.border;
|
||||
if (tag.hasText) {
|
||||
symbol.initialText = tag.initialText;
|
||||
}
|
||||
symbol.html = !!tag.html;
|
||||
symbol.displayAsPassword = !!tag.password;
|
||||
symbol.type = tag.readonly ? flash.text.TextFieldType.DYNAMIC :
|
||||
flash.text.TextFieldType.INPUT;
|
||||
if (tag.hasMaxLength) {
|
||||
symbol.maxChars = tag.maxLength;
|
||||
}
|
||||
symbol.autoSize = tag.autoSize ? flash.text.TextFieldAutoSize.LEFT : flash.text.TextFieldAutoSize.NONE;
|
||||
symbol.variableName = tag.variableName;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns raw DefineLabel tag data into an object that's consumable as a text symbol and then
|
||||
* passes that into `FromTextData`, returning the resulting TextSymbol.
|
||||
*
|
||||
* This has to be done outside the SWF parser because it relies on any used fonts being
|
||||
* available as symbols, which isn't the case in the SWF parser.
|
||||
*/
|
||||
static FromLabelData(data: any, loaderInfo: flash.display.LoaderInfo): TextSymbol {
|
||||
var bounds = data.fillBounds;
|
||||
var records = data.records;
|
||||
var coords = data.coords = [];
|
||||
var htmlText = '';
|
||||
var size = 12;
|
||||
var face = 'Times Roman';
|
||||
var color = 0;
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var codes: number[];
|
||||
for (var i = 0; i < records.length; i++) {
|
||||
var record = records[i];
|
||||
if (record.eot) {
|
||||
break;
|
||||
}
|
||||
if (record.hasFont) {
|
||||
var font = <FontSymbol>loaderInfo.getSymbolById(record.fontId);
|
||||
font || Debug.warning('Label ' + data.id + 'refers to undefined font symbol ' +
|
||||
record.fontId);
|
||||
codes = font.codes;
|
||||
size = record.fontHeight;
|
||||
if (!font.originalSize) {
|
||||
size /= 20;
|
||||
}
|
||||
face = 'swffont' + record.fontId;
|
||||
}
|
||||
if (record.hasColor) {
|
||||
color = record.color >>> 8;
|
||||
}
|
||||
if (record.hasMoveX) {
|
||||
x = record.moveX;
|
||||
if (x < bounds.xMin) {
|
||||
bounds.xMin = x;
|
||||
}
|
||||
}
|
||||
if (record.hasMoveY) {
|
||||
y = record.moveY;
|
||||
if (y < bounds.yMin) {
|
||||
bounds.yMin = y;
|
||||
}
|
||||
}
|
||||
var text = '';
|
||||
var entries = record.entries;
|
||||
var j = 0;
|
||||
var entry;
|
||||
while ((entry = entries[j++])) {
|
||||
var code = codes[entry.glyphIndex];
|
||||
release || assert(code, 'undefined label glyph');
|
||||
var char = String.fromCharCode(code);
|
||||
text += charEscapeMap[char] || char;
|
||||
coords.push(x, y);
|
||||
x += entry.advance;
|
||||
}
|
||||
htmlText += '<font size="' + size + '" face="' + face + '"' + ' color="#' +
|
||||
('000000' + color.toString(16)).slice(-6) + '">' + text + '</font>';
|
||||
}
|
||||
data.tag.initialText = htmlText;
|
||||
return TextSymbol.FromTextData(data, loaderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
var charEscapeMap = {'<': '<', '>': '>', '&' : '&'};
|
||||
|
||||
export class ButtonSymbol extends DisplaySymbol {
|
||||
upState: AnimationState = null;
|
||||
overState: AnimationState = null;
|
||||
downState: AnimationState = null;
|
||||
hitTestState: AnimationState = null;
|
||||
loaderInfo: flash.display.LoaderInfo;
|
||||
|
||||
constructor(data: SymbolData, loaderInfo: flash.display.LoaderInfo) {
|
||||
super(data, flash.display.SimpleButton, false);
|
||||
this.loaderInfo = loaderInfo;
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): ButtonSymbol {
|
||||
var symbol = new ButtonSymbol(data, loaderInfo);
|
||||
if (loaderInfo.actionScriptVersion === ActionScriptVersion.ACTIONSCRIPT2) {
|
||||
symbol.isAVM1Object = true;
|
||||
}
|
||||
var states = data.states;
|
||||
var character: SpriteSymbol = null;
|
||||
var matrix: flash.geom.Matrix = null;
|
||||
var colorTransform: flash.geom.ColorTransform = null;
|
||||
var cmd;
|
||||
for (var stateName in states) {
|
||||
var commands = states[stateName];
|
||||
if (commands.length === 1) {
|
||||
cmd = commands[0];
|
||||
matrix = flash.geom.Matrix.FromUntyped(cmd.matrix);
|
||||
if (cmd.cxform) {
|
||||
colorTransform = flash.geom.ColorTransform.FromCXForm(cmd.cxform);
|
||||
}
|
||||
} else {
|
||||
cmd = {symbolId: -1};
|
||||
character = new Timeline.SpriteSymbol({id: -1, className: null}, loaderInfo);
|
||||
character.frames.push(new FrameDelta(loaderInfo, commands));
|
||||
}
|
||||
symbol[stateName + 'State'] = new Timeline.AnimationState(cmd.symbolId, character, 0,
|
||||
matrix, colorTransform);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
export class SpriteSymbol extends DisplaySymbol {
|
||||
numFrames: number = 1;
|
||||
frames: FrameDelta[] = [];
|
||||
labels: flash.display.FrameLabel[] = [];
|
||||
frameScripts: any[] = [];
|
||||
isRoot: boolean;
|
||||
avm1Name: string;
|
||||
avm1SymbolClass;
|
||||
loaderInfo: flash.display.LoaderInfo;
|
||||
|
||||
constructor(data: SymbolData, loaderInfo: flash.display.LoaderInfo) {
|
||||
super(data, flash.display.MovieClip, true);
|
||||
this.loaderInfo = loaderInfo;
|
||||
}
|
||||
|
||||
static FromData(data: any, loaderInfo: flash.display.LoaderInfo): SpriteSymbol {
|
||||
var symbol = new SpriteSymbol(data, loaderInfo);
|
||||
symbol.numFrames = data.frameCount;
|
||||
if (loaderInfo.actionScriptVersion === ActionScriptVersion.ACTIONSCRIPT2) {
|
||||
symbol.isAVM1Object = true;
|
||||
symbol.avm1Context = loaderInfo._avm1Context;
|
||||
}
|
||||
symbol.frameScripts = [];
|
||||
var frames = data.frames;
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
var frameInfo;
|
||||
frameInfo = loaderInfo.getFrame(data, i);
|
||||
if (frameInfo.actionBlocks) {
|
||||
symbol.frameScripts.push(i);
|
||||
symbol.frameScripts.push.apply(symbol.frameScripts, frameInfo.actionBlocks);
|
||||
}
|
||||
if (frameInfo.labelName) {
|
||||
symbol.labels.push(new flash.display.FrameLabel(frameInfo.labelName, i + 1));
|
||||
}
|
||||
var frame = frameInfo.frameDelta;
|
||||
var repeat = frameInfo.repeat || 1;
|
||||
while (repeat--) {
|
||||
symbol.frames.push(frame);
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move this, and the other symbol classes, into better-suited files.
|
||||
export class FontSymbol extends Symbol {
|
||||
name: string;
|
||||
id: number;
|
||||
bold: boolean;
|
||||
italic: boolean;
|
||||
codes: number[];
|
||||
originalSize: boolean;
|
||||
metrics: any;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.text.Font);
|
||||
}
|
||||
|
||||
static FromData(data: any): FontSymbol {
|
||||
var symbol = new FontSymbol(data);
|
||||
symbol.name = data.name;
|
||||
// No need to keep the original data baggage around.
|
||||
symbol.data = {id: data.id};
|
||||
symbol.bold = data.bold;
|
||||
symbol.italic = data.italic;
|
||||
symbol.originalSize = data.originalSize;
|
||||
symbol.codes = data.codes;
|
||||
symbol.metrics = data.metrics;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
export class SoundSymbol extends Symbol {
|
||||
channels: number;
|
||||
sampleRate: number;
|
||||
pcm: Float32Array;
|
||||
packaged;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.media.Sound);
|
||||
}
|
||||
|
||||
static FromData(data: any): SoundSymbol {
|
||||
var symbol = new SoundSymbol(data);
|
||||
symbol.channels = data.channels;
|
||||
symbol.sampleRate = data.sampleRate;
|
||||
symbol.pcm = data.pcm;
|
||||
symbol.packaged = data.packaged;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
export class BinarySymbol extends Symbol {
|
||||
buffer: Uint8Array;
|
||||
byteLength: number;
|
||||
|
||||
constructor(data: SymbolData) {
|
||||
super(data, flash.utils.ByteArray);
|
||||
}
|
||||
|
||||
static FromData(data: any): BinarySymbol {
|
||||
var symbol = new BinarySymbol(data);
|
||||
symbol.buffer = data.data;
|
||||
symbol.byteLength = data.data.byteLength;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class AnimationState {
|
||||
constructor(public symbolId: number,
|
||||
public symbol: DisplaySymbol = null,
|
||||
public depth: number = 0,
|
||||
public matrix: flash.geom.Matrix = null,
|
||||
public colorTransform: flash.geom.ColorTransform = null,
|
||||
public ratio: number = 0,
|
||||
public name: string = null,
|
||||
public clipDepth: number = -1,
|
||||
public filters: any [] = null,
|
||||
public blendMode: string = null,
|
||||
public cacheAsBitmap: boolean = false,
|
||||
public visible: boolean = true,
|
||||
public events: any [] = null,
|
||||
public variableName: string = null) {
|
||||
|
||||
}
|
||||
|
||||
canBeAnimated(obj: flash.display.DisplayObject): boolean {
|
||||
if (!obj._hasFlags(flash.display.DisplayObjectFlags.AnimatedByTimeline)) {
|
||||
return false;
|
||||
}
|
||||
if (obj._depth !== this.depth) {
|
||||
return false;
|
||||
}
|
||||
var symbol = this.symbol;
|
||||
if (symbol) {
|
||||
if (symbol.dynamic) {
|
||||
return false;
|
||||
}
|
||||
if (obj._clipDepth !== this.clipDepth) {
|
||||
return false;
|
||||
}
|
||||
if (!symbol.symbolClass.isType(obj)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
canBeReused(obj: flash.display.DisplayObject): boolean {
|
||||
var symbol = this.symbol;
|
||||
if (symbol && symbol === obj._symbol &&
|
||||
obj._hasFlags(flash.display.DisplayObjectFlags.OwnedByTimeline)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class SoundStart {
|
||||
constructor(public soundId: number, public soundInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO document
|
||||
*/
|
||||
export class FrameDelta {
|
||||
private _stateAtDepth: Shumway.Map<AnimationState>;
|
||||
private _soundStarts: SoundStart[];
|
||||
private _soundStreamHead: SoundStream;
|
||||
private _soundStreamBlock: {data: Uint8Array};
|
||||
|
||||
get stateAtDepth() {
|
||||
return this._stateAtDepth || this._initialize();
|
||||
}
|
||||
|
||||
get soundStarts() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStarts;
|
||||
}
|
||||
|
||||
// TODO: refactor streaming sound support to delay sound parsing until needed.
|
||||
// These two fields aren't used for now, but will perhaps be helpful in the above.
|
||||
get soundStreamHead() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStreamHead;
|
||||
}
|
||||
|
||||
get soundStreamBlock() {
|
||||
if (this.commands) {
|
||||
this._initialize();
|
||||
}
|
||||
return this._soundStreamBlock;
|
||||
}
|
||||
|
||||
constructor(private loaderInfo: flash.display.LoaderInfo, private commands: any []) {
|
||||
this._stateAtDepth = null;
|
||||
this._soundStarts = null;
|
||||
this._soundStreamHead = null;
|
||||
this._soundStreamBlock = null;
|
||||
}
|
||||
|
||||
private _initialize(): Shumway.Map<AnimationState> {
|
||||
var states: Shumway.Map<AnimationState> = this._stateAtDepth = Object.create(null);
|
||||
var commands = this.commands;
|
||||
if (!commands) {
|
||||
return states;
|
||||
}
|
||||
var loaderInfo = this.loaderInfo;
|
||||
for (var i = 0; i < commands.length; i++) {
|
||||
var cmd = 'depth' in commands[i] ?
|
||||
commands[i] :
|
||||
<any>loaderInfo._file.getParsedTag(commands[i]);
|
||||
var depth = cmd.depth;
|
||||
switch (cmd.code) {
|
||||
case SwfTag.CODE_REMOVE_OBJECT:
|
||||
case SwfTag.CODE_REMOVE_OBJECT2:
|
||||
states[depth] = null;
|
||||
break;
|
||||
case SwfTag.CODE_START_SOUND:
|
||||
var soundStarts = this._soundStarts || (this._soundStarts = []);
|
||||
soundStarts.push(new SoundStart(cmd.soundId, cmd.soundInfo));
|
||||
break;
|
||||
case SwfTag.CODE_SOUND_STREAM_HEAD:
|
||||
case SwfTag.CODE_SOUND_STREAM_HEAD2:
|
||||
this._soundStreamHead = SoundStream.FromTag(cmd);
|
||||
break;
|
||||
case SwfTag.CODE_SOUND_STREAM_BLOCK:
|
||||
this._soundStreamBlock = cmd;
|
||||
break;
|
||||
case SwfTag.CODE_PLACE_OBJECT:
|
||||
case SwfTag.CODE_PLACE_OBJECT2:
|
||||
case SwfTag.CODE_PLACE_OBJECT3:
|
||||
var symbol: DisplaySymbol = null;
|
||||
var matrix: flash.geom.Matrix = null;
|
||||
var colorTransform: flash.geom.ColorTransform = null;
|
||||
var filters: flash.filters.BitmapFilter[] = null;
|
||||
var events: any[] = loaderInfo._allowCodeExecution ? cmd.events : 0;
|
||||
if (cmd.symbolId) {
|
||||
symbol = <DisplaySymbol>loaderInfo.getSymbolById(cmd.symbolId);
|
||||
if (!symbol) {
|
||||
warning("Symbol " + cmd.symbolId + " is not defined.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasMatrix) {
|
||||
matrix = flash.geom.Matrix.FromUntyped(cmd.matrix);
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasColorTransform) {
|
||||
colorTransform = flash.geom.ColorTransform.FromCXForm(cmd.cxform);
|
||||
}
|
||||
if (cmd.flags & PlaceObjectFlags.HasFilterList) {
|
||||
filters = [];
|
||||
var swfFilters = cmd.filters;
|
||||
for (var j = 0; j < swfFilters.length; j++) {
|
||||
var obj = swfFilters[j];
|
||||
var filter: flash.filters.BitmapFilter;
|
||||
switch (obj.type) {
|
||||
case 0: filter = flash.filters.DropShadowFilter.FromUntyped(obj); break;
|
||||
case 1: filter = flash.filters.BlurFilter.FromUntyped(obj); break;
|
||||
case 2: filter = flash.filters.GlowFilter.FromUntyped(obj); break;
|
||||
case 3: filter = flash.filters.BevelFilter.FromUntyped(obj); break;
|
||||
case 4: filter = flash.filters.GradientGlowFilter.FromUntyped(obj); break;
|
||||
case 5: filter = flash.filters.ConvolutionFilter.FromUntyped(obj); break;
|
||||
case 6: filter = flash.filters.ColorMatrixFilter.FromUntyped(obj); break;
|
||||
case 7: filter = flash.filters.GradientBevelFilter.FromUntyped(obj); break;
|
||||
}
|
||||
release || assert (filter, "Unknown filter type.");
|
||||
filters.push(filter);
|
||||
}
|
||||
}
|
||||
var state = new Timeline.AnimationState (
|
||||
cmd.symbolId,
|
||||
symbol,
|
||||
depth,
|
||||
matrix,
|
||||
colorTransform,
|
||||
cmd.ratio,
|
||||
cmd.name,
|
||||
cmd.clipDepth,
|
||||
filters,
|
||||
flash.display.BlendMode.fromNumber(cmd.blendMode),
|
||||
!!(cmd.flags & PlaceObjectFlags.HasCacheAsBitmap),
|
||||
cmd.flags & PlaceObjectFlags.HasVisible ? !!cmd.visibility : true,
|
||||
events,
|
||||
cmd.variableName
|
||||
);
|
||||
states[depth] = state;
|
||||
break;
|
||||
default:
|
||||
console.warn("Unhandled timeline control tag: " + cmd.code + ": " + SwfTag[cmd.code]);
|
||||
}
|
||||
|
||||
}
|
||||
this.commands = null;
|
||||
return states;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
var Loader = flash.display.Loader;
|
||||
var Sprite = flash.display.Sprite;
|
||||
var MovieClip = flash.display.MovieClip;
|
||||
var SpriteSymbol = Shumway.Timeline.SpriteSymbol;
|
||||
var SpriteSymbol = flash.display.SpriteSymbol;
|
||||
var FrameDelta = Shumway.Timeline.FrameDelta;
|
||||
var Event = flash.events.Event;
|
||||
var URLRequest = flash.net.URLRequest;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
var DisplayObjectContainer = flash.display.DisplayObjectContainer;
|
||||
var Stage = flash.display.Stage;
|
||||
var MovieClip = flash.display.MovieClip;
|
||||
var SpriteSymbol = Shumway.Timeline.SpriteSymbol;
|
||||
var SpriteSymbol = flash.display.SpriteSymbol;
|
||||
var FrameDelta = Shumway.Timeline.FrameDelta;
|
||||
|
||||
var MC_NAME_SUFFIX = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче