зеркало из https://github.com/mozilla/shumway.git
Merge pull request #2239 from yurydelendik/avm1-misc
Misc AVM1 fixes: filters and loading
This commit is contained in:
Коммит
e81c24367a
|
@ -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.fla
Двоичный файл не отображается.
Двоичные данные
test/swfs/avm1/filters/filtersdump.swf
Двоичные данные
test/swfs/avm1/filters/filtersdump.swf
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -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"
|
||||
|
|
Загрузка…
Ссылка в новой задаче