Merge pull request #2239 from yurydelendik/avm1-misc

Misc AVM1 fixes: filters and loading
This commit is contained in:
Yury Delendik 2015-05-09 17:10:50 -05:00
Родитель 0a44ee31b4 539c2fdfe2
Коммит e81c24367a
19 изменённых файлов: 264 добавлений и 44 удалений

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

@ -57,6 +57,7 @@ interface ISecurityDomain {
net: {
URLRequest: typeof flashPackage.net.URLRequest;
URLLoader: typeof flashPackage.net.URLLoader;
URLVariables: typeof flashPackage.net.URLVariables;
SharedObject: typeof flashPackage.net.SharedObject;
}
system: {
@ -425,6 +426,8 @@ declare module Shumway.AVMX.AS.flash {
class URLRequest extends ASObject {
constructor(url: string);
method: string;
contentType: string;
data: any;
}
class URLLoader extends events.EventDispatcher {
dataFormat;
@ -434,6 +437,10 @@ declare module Shumway.AVMX.AS.flash {
constructor(request?: URLRequest);
_ignoreDecodeErrors: boolean;
}
class URLVariables extends ASObject {
_ignoreDecodingErrors: boolean;
decode(queryString: string): void;
}
class SharedObject extends ASObject {
static axClass: typeof SharedObject;
size: number;

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

@ -19,6 +19,13 @@
module Shumway.AVM1.Lib {
import flash = Shumway.AVMX.AS.flash;
export function toAS3BitmapData(as2Object: AVM1BitmapData): flash.display.BitmapData {
if (!(as2Object instanceof AVM1BitmapData)) {
return null;
}
return as2Object.as3BitmapData;
}
export class AVM1BitmapData extends AVM1Object {
static createAVM1Class(context: AVM1Context): AVM1Object {
return wrapAVM1NativeClass(context, true, AVM1BitmapData,
@ -48,6 +55,13 @@ module Shumway.AVM1.Lib {
this._as3Object = as3Object;
}
static fromAS3BitmapData(context: AVM1Context, as3Object: flash.display.BitmapData): AVM1Object {
var as2Object = new AVM1BitmapData(context);
as2Object.alPrototype = context.globals.alGet('flash').alGet('display').alGet('BitmapData').alGetPrototypeProperty();
as2Object._as3Object = as3Object;
return as2Object;
}
static loadBitmap(context: AVM1Context, symbolId: string): AVM1BitmapData {
symbolId = alToString(context, symbolId);
var symbol = context.getAsset(symbolId);

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

@ -207,8 +207,7 @@ module Shumway.AVM1.Lib {
}
return context.sec.createArray(arr);
case 'BitmapData':
// TODO implement BitmapData conversion
return undefined;
return toAS3BitmapData(value);
case 'Point':
return toAS3Point(value);
default:
@ -231,8 +230,7 @@ module Shumway.AVM1.Lib {
}
return new Natives.AVM1ArrayNative(context, arr);
case 'BitmapData':
// TODO implement BitmapData conversion
return undefined;
return AVM1BitmapData.fromAS3BitmapData(context, value);
case 'Point':
return AVM1Point.fromAS3Point(context, value);
default:

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

@ -37,7 +37,7 @@ module Shumway.AVM1.Lib {
'NaN', 'Infinity', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined',
'Object', 'Function','Array', 'Number', 'Math', 'Boolean', 'Date', 'String', 'Error',
'MovieClip', 'AsBroadcaster', 'System', 'Stage', 'Button',
'TextField', 'Color', 'Key', 'Mouse', 'MovieClipLoader', 'XML', 'XMLNode',
'TextField', 'Color', 'Key', 'Mouse', 'MovieClipLoader', 'XML', 'XMLNode', 'LoadVars',
'Sound', 'SharedObject', 'ContextMenu', 'ContextMenuItem', 'TextFormat'], false);
return globals;
}
@ -211,6 +211,7 @@ module Shumway.AVM1.Lib {
public Key: AVM1Object;
public Mouse: AVM1Object;
public MovieClipLoader: AVM1Object;
public LoadVars: AVM1Object;
public Sound: AVM1Object;
public SharedObject: AVM1Object;
@ -244,6 +245,7 @@ module Shumway.AVM1.Lib {
this.Key = AVM1Key.createAVM1Class(context);
this.Mouse = AVM1Mouse.createAVM1Class(context);
this.MovieClipLoader = AVM1MovieClipLoader.createAVM1Class(context);
this.LoadVars = new AVM1LoadVarsFunction(context);
this.Sound = AVM1Sound.createAVM1Class(context);
this.SharedObject = new AVM1SharedObjectFunction(context);

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

@ -0,0 +1,189 @@
/**
* Copyright 2015 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.
*/
///<reference path='../references.ts' />
module Shumway.AVM1.Lib {
import ASObject = Shumway.AVMX.AS.ASObject;
import flash = Shumway.AVMX.AS.flash;
import axCoerceString = Shumway.AVMX.axCoerceString;
export interface IAVM1DataObject {
isAVM1DataObject: boolean;
_as3Loader: flash.net.URLLoader;
getBytesLoaded(): number;
getBytesTotal(): number;
}
export function loadAVM1DataObject(context: AVM1Context, url: string,
method: string, contentType: string,
data: any, target: IAVM1DataObject): void {
var request = new context.sec.flash.net.URLRequest(url);
if (method) {
request.method = method;
}
if (contentType) {
request.contentType = contentType;
}
if (data) {
release || Debug.assert(typeof data === 'string');
request.data = data;
}
var loader = new context.sec.flash.net.URLLoader(request);
loader.dataFormat = 'text'; // flash.net.URLLoaderDataFormat.TEXT;
var completeHandler = context.sec.boxFunction(function (event: flash.events.Event): void {
loader.removeEventListener(flash.events.Event.COMPLETE, completeHandler);
release || Debug.assert(typeof loader.data === 'string');
avm1BroadcastEvent(context, target, 'onData', [loader.data]);
});
loader.addEventListener(flash.events.Event.COMPLETE, completeHandler);
target._as3Loader = loader;
}
export class AVM1LoadVarsFunction extends AVM1Function {
constructor(context: AVM1Context) {
super(context);
this.alSetOwnPrototypeProperty(new AVM1LoadVarsPrototype(context, this));
}
alConstruct(args?: any[]): AVM1Object {
var obj = new AVM1Object(this.context);
obj.alPrototype = this.alGetPrototypeProperty();
(<IAVM1DataObject><any>obj).isAVM1DataObject = true;
return obj;
}
alCall(thisArg: any, args?: any[]): any {
return this.alConstruct(args);
}
}
export class AVM1LoadVarsPrototype extends AVM1Object implements IAVM1DataObject {
constructor(context: AVM1Context, fn: AVM1LoadVarsFunction) {
super(context);
alDefineObjectProperties(this, {
constructor: {
value: fn,
writable: true
},
toString: {
value: this._toString
},
load: {
value: this.load
},
onData: {
value: this.defaultOnData
},
decode: {
value: this.decode
},
send: {
value: this.load
},
sendAndload: {
value: this.load
}
});
}
isAVM1DataObject: boolean;
_as3Loader: flash.net.URLLoader;
getBytesLoaded(): number {
if (!this._as3Loader) {
return undefined;
}
return this._as3Loader.bytesLoaded;
}
getBytesTotal(): number {
if (!this._as3Loader) {
return undefined;
}
return this._as3Loader.bytesTotal;
}
load(url: string): boolean {
url = alCoerceString(this.context, url);
if (!url) {
return false;
}
loadAVM1DataObject(this.context, url, null, null, null, this);
return true;
}
defaultOnData(src: string) {
if (isNullOrUndefined(src)) {
avm1BroadcastEvent(this.context, this, 'onLoad', [false]);
return;
}
AVM1LoadVarsPrototype.prototype.decode.call(this, src);
this.alPut('loaded', true);
avm1BroadcastEvent(this.context, this, 'onLoad', [true]);
}
decode(queryString: string): void {
queryString = alCoerceString(this.context, queryString);
var as3Variables = new this.context.sec.flash.net.URLVariables();
as3Variables._ignoreDecodingErrors = true;
as3Variables.decode(queryString);
AVMX.forEachPublicProperty(as3Variables, function (name, value) {
// TODO Are we leaking some AS3 properties/fields here?
if (typeof value === 'string') {
this.alPut(name, value);
}
}, this);
}
_toString(): string {
var context = this.context;
var as3Variables = new context.sec.flash.net.URLVariables();
alForEachProperty(this, function (name) {
if (this.alHasOwnProperty(name)) {
as3Variables.axSetPublicProperty(name, alToString(context, this.alGet(name)));
}
}, this);
return as3Variables.axCallPublicProperty('toString', null);
}
send(url: string, target: string, method?: string): boolean {
url = alCoerceString(this.context, url);
method = isNullOrUndefined(method) ? 'POST' : alCoerceString(this.context, method);
Debug.notImplemented('AVM1LoadVarsPrototype.send');
return false;
}
sendAndLoad(url: string, target: AVM1Object, method?: string): boolean {
url = alCoerceString(this.context, url);
method = isNullOrUndefined(method) ? 'POST' : alCoerceString(this.context, method);
if (!url || !(target instanceof AVM1Object)) {
return false;
}
if (!(<IAVM1DataObject><any>target).isAVM1DataObject) {
return false;
}
var contentType = this.alGet('contentType');
contentType = isNullOrUndefined(contentType) ?
'application/x-www-form-urlencoded' :
alCoerceString(this.context, contentType);
var data = alToString(this.context, this);
loadAVM1DataObject(this.context, url, method, contentType, data, <IAVM1DataObject><any>target);
return true;
}
}
}

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

@ -32,6 +32,7 @@ module Shumway.AVM1.Lib {
public avm1Constructor() {
this._loader = new this.context.sec.flash.display.Loader();
AVM1Broadcaster.initialize(this.context, this);
}
public loadClip(url: string, target):Boolean {

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

@ -407,6 +407,7 @@ module Shumway.AVM1.Lib {
var text = args && alCoerceString(this.context, args[0]);
var obj = new AVM1Object(this.context);
obj.alPrototype = this.alGetPrototypeProperty();
(<IAVM1DataObject><any>obj).isAVM1DataObject = true;
AVM1XMLPrototype.prototype.initializeDocument.call(obj, text);
return obj;
}
@ -416,7 +417,7 @@ module Shumway.AVM1.Lib {
}
}
class AVM1XMLPrototype extends AVM1Object {
class AVM1XMLPrototype extends AVM1Object implements IAVM1DataObject {
constructor(context: AVM1Context, fn: AVM1Function, xmlNodeClass: AVM1XMLNodeFunction) {
super(context);
this.alPrototype = xmlNodeClass.alGetPrototypeProperty();
@ -464,7 +465,8 @@ module Shumway.AVM1.Lib {
}
as3XMLDocument: flash.xml.XMLDocument;
private _as3Loader: flash.net.URLLoader;
isAVM1DataObject: boolean;
_as3Loader: flash.net.URLLoader;
initializeDocument(text: string) {
text = alCoerceString(this.context, text) || null;
@ -508,25 +510,15 @@ module Shumway.AVM1.Lib {
if (!url) {
return false;
}
var context = this.context;
var request = new context.sec.flash.net.URLRequest(url);
var loader = new context.sec.flash.net.URLLoader(request);
loader._ignoreDecodeErrors = true;
loader.dataFormat = 'text'; // flash.net.URLLoaderDataFormat.TEXT;
var eventTarget = this;
var completeHandler = context.sec.boxFunction(function (event: flash.events.Event): void {
loader.removeEventListener(flash.events.Event.COMPLETE, completeHandler);
release || Debug.assert(typeof loader.data === 'string');
avm1BroadcastEvent(context, eventTarget, 'onData', [loader.data]);
});
loader.addEventListener(flash.events.Event.COMPLETE, completeHandler);
this._as3Loader = loader;
loadAVM1DataObject(this.context, url, null, null, null, <IAVM1DataObject><any>this);
return true;
}
defaultOnData(src: string) {
// TODO handle failure
if (isNullOrUndefined(src)) {
avm1BroadcastEvent(this.context, this, 'onLoad', [false]);
return;
}
AVM1XMLPrototype.prototype.parseXML.call(this, src);
this.alPut('loaded', true);
avm1BroadcastEvent(this.context, this, 'onLoad', [true]);
@ -541,13 +533,26 @@ module Shumway.AVM1.Lib {
send(url: string, target?: string, method?: string): boolean {
url = alCoerceString(this.context, url);
target = isNullOrUndefined(target) ? undefined : alCoerceString(this.context, target);
method = isNullOrUndefined(method) ? undefined : alCoerceString(this.context, method);
Debug.notImplemented('AVM1XMLPrototype.send');
return false;
}
sendAndLoad(url: string, resultXML: AVM1Object): void {
url = alCoerceString(this.context, url);
Debug.notImplemented('AVM1XMLPrototype.sendAndLoad');
if (!url) {
return;
}
if (!(<IAVM1DataObject><any>resultXML).isAVM1DataObject) {
return;
}
Debug.somewhatImplemented('AVM1XMLPrototype.send');
// TODO check content types and test
var contentType = this.alGet('contentType');
contentType = isNullOrUndefined(contentType) ? undefined : alCoerceString(this.context, contentType);
var data = alToString(this.context, this);
loadAVM1DataObject(this.context, url, 'POST', contentType, data, <IAVM1DataObject><any>resultXML);
}
}
}

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

@ -49,4 +49,5 @@
///<reference path='lib/AVM1SharedObject.ts' />
///<reference path='lib/AVM1MovieClipLoader.ts' />
///<reference path='lib/AVM1Filters.ts' />
///<reference path='lib/AVM1LoadVars.ts' />
///<reference path='lib/AVM1XML.ts' />

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

@ -34,14 +34,15 @@ module Shumway.AVMX.AS.flash.filters {
static instanceSymbols: string [] = null;
public static FromUntyped(obj: any) {
// obj.highlightColor is an RGBA color.
var highlightColor: number = obj.highlightColor >>> 8;
var highlightAlpha: number = (obj.highlightColor & 0xff) / 0xff;
// obj.colors is an array of RGBA colors.
// Here it contains exactly one color object, which maps to shadowColor and shadowAlpha.
release || assert(obj.colors && obj.colors.length === 1, "colors must be Array of length 1");
var shadowColor: number = obj.colors[0] >>> 8;
var shadowAlpha: number = (obj.colors[0] & 0xff) / 0xff;
// Here it contains exactly two color objects (spec might state it differently):
// - first maps to highlightColor and highlightAlpha;
// - second maps to shadowColor and shadowAlpha;
release || assert(obj.colors && obj.colors.length === 2, "colors must be Array of length 2");
var highlightColor: number = obj.colors[0] >>> 8;
var highlightAlpha: number = (obj.colors[0] & 0xff) / 0xff;
var shadowColor: number = obj.colors[1] >>> 8;
var shadowAlpha: number = (obj.colors[1] & 0xff) / 0xff;
// type is derived from obj.onTop and obj.innerShadow
// obj.onTop true: type is FULL
// obj.inner true: type is INNER

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

@ -963,21 +963,18 @@ module Shumway.SWF.Parser.LowLevel {
}
function filterGlow($bytes, $stream, $, type) {
// type: 0 - drop shadow, 2 - glow, 3 - bevel, 4 - gradient glow, 7 - gradient bevel
var count;
if (type === 4 || type === 7) {
count = readUi8($bytes, $stream);
}
else {
count = 1;
} else {
count = type === 3 ? 2 : 1;
}
var $5 = $.colors = [];
var $6 = count;
while ($6--) {
$5.push(rgba($bytes, $stream));
}
if (type === 3) {
$.hightlightColor = rgba($bytes, $stream);
}
if (type === 4 || type === 7) {
var $9 = $.ratios = [];
var $10 = count;

Двоичные данные
test/swfs/avm1/filters/filtersdump.fla

Двоичный файл не отображается.

Двоичные данные
test/swfs/avm1/filters/filtersdump.swf

Двоичный файл не отображается.

Двоичные данные
test/swfs/avm1/loadvariables/loadvars.fla Normal file

Двоичный файл не отображается.

Двоичные данные
test/swfs/avm1/loadvariables/loadvars.swf Normal file

Двоичный файл не отображается.

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

@ -0,0 +1,2 @@
loaded true
var1: test

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

@ -0,0 +1 @@
var1=test&var2=test2

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

@ -267,13 +267,6 @@
],
"type": "stas"
},
{ "id": "avm1 loadVariables trace",
"stas": "swfs/trace.stas",
"filenames": [
"swfs/avm1/loadvariables/loadvariables.swf"
],
"type": "stas"
},
{ "id": "button",
"stas": "swfs/button.stas",
"filenames": [

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

@ -9,7 +9,6 @@
{ "id": "avm1core",
"stas": "swfs/trace.stas",
"filenames": [
"swfs/avm1/filters/filtersdump.swf",
"swfs/avm1/doactionorder/doactionorder.swf"
],
"type": "stas"

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

@ -7,6 +7,7 @@
"swfs/local2global.swf",
"swfs/movieinfo1.swf",
"swfs/stream1.swf",
"swfs/avm1/filters/filtersdump.swf",
"swfs/stroke1.swf"
],
"type": "stas"
@ -99,6 +100,14 @@
],
"type": "stas"
},
{ "id": "avm1 loadvariables",
"stas": "swfs/trace.stas",
"filenames": [
"swfs/avm1/loadvariables/loadvariables.swf",
"swfs/avm1/loadvariables/loadvars.swf"
],
"type": "stas"
},
{ "id": "flash_utils_Timer",
"stas": "swfs/trace.stas",
"filenames": [
@ -196,6 +205,7 @@
"filenames": [
"swfs/avm1/xml/xmlbuild.swf",
"swfs/avm1/xml/xmlload.swf",
"swfs/avm1/xml/xmlload.swf",
"swfs/avm1/xml/xmlstring.swf"
],
"type": "stas"