Move player/timeline.ts to flash/symbol.ts and move most SymbolFoo classes to the Foo class they represent

This commit is contained in:
Till Schneidereit 2014-11-21 01:35:02 +01:00
Родитель 900c42275f
Коммит a5a8c71386
23 изменённых файлов: 745 добавлений и 745 удалений

Просмотреть файл

@ -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;

11
src/avm1lib/flash.d.ts поставляемый
Просмотреть файл

@ -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' />

298
src/flash/symbol.ts Normal file
Просмотреть файл

@ -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 = {'<': '&lt;', '>': '&gt;', '&' : '&amp;'};
}

Просмотреть файл

@ -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 = {'<': '&lt;', '>': '&gt;', '&' : '&amp;'};
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;