mirror of
https://github.com/servo/servo.git
synced 2025-07-30 10:40:27 +01:00
Auto merge of #21711 - servo:webgl, r=jdm
Some fixes to canvas stuff <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21711) <!-- Reviewable:end -->
This commit is contained in:
commit
0ecd671f52
14 changed files with 404 additions and 262 deletions
|
@ -729,7 +729,7 @@ fn crop_image(
|
|||
/// smoothing_enabled: It determines if smoothing is applied to the image result
|
||||
fn write_image(
|
||||
draw_target: &DrawTarget,
|
||||
mut image_data: Vec<u8>,
|
||||
image_data: Vec<u8>,
|
||||
image_size: Size2D<f64>,
|
||||
dest_rect: Rect<f64>,
|
||||
smoothing_enabled: bool,
|
||||
|
@ -740,8 +740,6 @@ fn write_image(
|
|||
return
|
||||
}
|
||||
let image_rect = Rect::new(Point2D::zero(), image_size);
|
||||
// rgba -> bgra
|
||||
byte_swap(&mut image_data);
|
||||
|
||||
// From spec https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
// When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt
|
||||
|
|
|
@ -132,12 +132,13 @@ impl<'a> CanvasPaintThread <'a> {
|
|||
self.canvas(canvas_id).is_point_in_path(x, y, fill_rule, chan)
|
||||
},
|
||||
Canvas2dMsg::DrawImage(
|
||||
imagedata,
|
||||
mut imagedata,
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
) => {
|
||||
byte_swap(&mut imagedata);
|
||||
self.canvas(canvas_id).draw_image(
|
||||
imagedata.into(),
|
||||
image_size,
|
||||
|
@ -169,8 +170,6 @@ impl<'a> CanvasPaintThread <'a> {
|
|||
let mut image_data = self.canvas(canvas_id).read_pixels(
|
||||
source_rect.to_i32(),
|
||||
image_size);
|
||||
// TODO: avoid double byte_swap.
|
||||
byte_swap(&mut image_data);
|
||||
self.canvas(other_canvas_id).draw_image(
|
||||
image_data.into(),
|
||||
source_rect.size,
|
||||
|
|
|
@ -684,7 +684,7 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
|
|||
|
||||
class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||
def __init__(self, location, parentScope, name, parent, members,
|
||||
isKnownNonPartial):
|
||||
isKnownNonPartial, toStringTag):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
assert isinstance(name, IDLUnresolvedIdentifier)
|
||||
assert isKnownNonPartial or not parent
|
||||
|
@ -722,6 +722,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
|||
# interface we're iterating for in order to get its nativeType.
|
||||
self.iterableInterface = None
|
||||
|
||||
self.toStringTag = toStringTag
|
||||
|
||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||
IDLExposureMixins.__init__(self, location)
|
||||
|
||||
|
@ -1017,10 +1019,9 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
|||
[self.location])
|
||||
|
||||
for m in self.members:
|
||||
if ((m.isMethod() and m.isJsonifier()) or
|
||||
m.identifier.name == "toJSON"):
|
||||
if m.identifier.name == "toJSON":
|
||||
raise WebIDLError("Unforgeable interface %s has a "
|
||||
"jsonifier so we won't be able to add "
|
||||
"toJSON so we won't be able to add "
|
||||
"one ourselves" % self.identifier.name,
|
||||
[self.location, m.location])
|
||||
|
||||
|
@ -1044,6 +1045,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
|||
(member.getExtendedAttribute("StoreInSlot") or
|
||||
member.getExtendedAttribute("Cached"))) or
|
||||
member.isMaplikeOrSetlike()):
|
||||
if self.isJSImplemented() and not member.isMaplikeOrSetlike():
|
||||
raise WebIDLError("Interface %s is JS-implemented and we "
|
||||
"don't support [Cached] or [StoreInSlot] "
|
||||
"on JS-implemented interfaces" %
|
||||
self.identifier.name,
|
||||
[self.location, member.location])
|
||||
if member.slotIndices is None:
|
||||
member.slotIndices = dict()
|
||||
member.slotIndices[self.identifier.name] = self.totalMembersInSlots
|
||||
|
@ -1115,15 +1122,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
|||
memberType = "deleters"
|
||||
elif member.isStringifier():
|
||||
memberType = "stringifiers"
|
||||
elif member.isJsonifier():
|
||||
memberType = "jsonifiers"
|
||||
elif member.isLegacycaller():
|
||||
memberType = "legacycallers"
|
||||
else:
|
||||
continue
|
||||
|
||||
if (memberType != "stringifiers" and memberType != "legacycallers" and
|
||||
memberType != "jsonifiers"):
|
||||
if (memberType != "stringifiers" and memberType != "legacycallers"):
|
||||
if member.isNamed():
|
||||
memberType = "named " + memberType
|
||||
else:
|
||||
|
@ -1573,9 +1577,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
|||
|
||||
class IDLInterface(IDLInterfaceOrNamespace):
|
||||
def __init__(self, location, parentScope, name, parent, members,
|
||||
isKnownNonPartial):
|
||||
isKnownNonPartial, classNameOverride=None,
|
||||
toStringTag=None):
|
||||
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
||||
parent, members, isKnownNonPartial)
|
||||
parent, members, isKnownNonPartial,
|
||||
toStringTag)
|
||||
self.classNameOverride = classNameOverride
|
||||
|
||||
def __str__(self):
|
||||
return "Interface '%s'" % self.identifier.name
|
||||
|
@ -1583,6 +1590,11 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
def isInterface(self):
|
||||
return True
|
||||
|
||||
def getClassName(self):
|
||||
if self.classNameOverride:
|
||||
return self.classNameOverride
|
||||
return self.identifier.name
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
for attr in attrs:
|
||||
identifier = attr.identifier()
|
||||
|
@ -1677,14 +1689,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
elif newMethod not in self.namedConstructors:
|
||||
raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
|
||||
[method.location, newMethod.location])
|
||||
elif (identifier == "ArrayClass"):
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[ArrayClass] must take no arguments",
|
||||
[attr.location])
|
||||
if self.parent:
|
||||
raise WebIDLError("[ArrayClass] must not be specified on "
|
||||
"an interface with inherited interfaces",
|
||||
[attr.location, self.location])
|
||||
elif (identifier == "ExceptionClass"):
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[ExceptionClass] must take no arguments",
|
||||
|
@ -1738,6 +1742,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
identifier == "ProbablyShortLivingWrapper" or
|
||||
identifier == "LegacyUnenumerableNamedProperties" or
|
||||
identifier == "RunConstructorInCallerCompartment" or
|
||||
identifier == "WantsEventListenerHooks" or
|
||||
identifier == "NonOrdinaryGetPrototypeOf" or
|
||||
identifier == "Abstract" or
|
||||
identifier == "Inline"):
|
||||
|
@ -1769,7 +1774,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
class IDLNamespace(IDLInterfaceOrNamespace):
|
||||
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
|
||||
IDLInterfaceOrNamespace.__init__(self, location, parentScope, name,
|
||||
None, members, isKnownNonPartial)
|
||||
None, members, isKnownNonPartial,
|
||||
toStringTag=None)
|
||||
|
||||
def __str__(self):
|
||||
return "Namespace '%s'" % self.identifier.name
|
||||
|
@ -2152,7 +2158,7 @@ class IDLType(IDLObject):
|
|||
# Should only call this on float types
|
||||
assert self.isFloat()
|
||||
|
||||
def isSerializable(self):
|
||||
def isJSONType(self):
|
||||
return False
|
||||
|
||||
def tag(self):
|
||||
|
@ -2350,8 +2356,8 @@ class IDLNullableType(IDLParametrizedType):
|
|||
def isUnion(self):
|
||||
return self.inner.isUnion()
|
||||
|
||||
def isSerializable(self):
|
||||
return self.inner.isSerializable()
|
||||
def isJSONType(self):
|
||||
return self.inner.isJSONType()
|
||||
|
||||
def tag(self):
|
||||
return self.inner.tag()
|
||||
|
@ -2430,8 +2436,8 @@ class IDLSequenceType(IDLParametrizedType):
|
|||
def isEnum(self):
|
||||
return False
|
||||
|
||||
def isSerializable(self):
|
||||
return self.inner.isSerializable()
|
||||
def isJSONType(self):
|
||||
return self.inner.isJSONType()
|
||||
|
||||
def tag(self):
|
||||
return IDLType.Tags.sequence
|
||||
|
@ -2476,6 +2482,9 @@ class IDLRecordType(IDLParametrizedType):
|
|||
def isRecord(self):
|
||||
return True
|
||||
|
||||
def isJSONType(self):
|
||||
return self.inner.isJSONType()
|
||||
|
||||
def tag(self):
|
||||
return IDLType.Tags.record
|
||||
|
||||
|
@ -2525,8 +2534,8 @@ class IDLUnionType(IDLType):
|
|||
def isUnion(self):
|
||||
return True
|
||||
|
||||
def isSerializable(self):
|
||||
return all(m.isSerializable() for m in self.memberTypes)
|
||||
def isJSONType(self):
|
||||
return all(m.isJSONType() for m in self.memberTypes)
|
||||
|
||||
def includesRestrictedFloat(self):
|
||||
return any(t.includesRestrictedFloat() for t in self.memberTypes)
|
||||
|
@ -2676,6 +2685,9 @@ class IDLTypedefType(IDLType):
|
|||
def isVoid(self):
|
||||
return self.inner.isVoid()
|
||||
|
||||
def isJSONType(self):
|
||||
return self.inner.isJSONType()
|
||||
|
||||
def isSequence(self):
|
||||
return self.inner.isSequence()
|
||||
|
||||
|
@ -2817,15 +2829,25 @@ class IDLWrapperType(IDLType):
|
|||
def isEnum(self):
|
||||
return isinstance(self.inner, IDLEnum)
|
||||
|
||||
def isSerializable(self):
|
||||
def isJSONType(self):
|
||||
if self.isInterface():
|
||||
if self.inner.isExternal():
|
||||
return False
|
||||
return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
|
||||
iface = self.inner
|
||||
while iface:
|
||||
if any(m.isMethod() and m.isToJSON() for m in iface.members):
|
||||
return True
|
||||
iface = iface.parent
|
||||
return False
|
||||
elif self.isEnum():
|
||||
return True
|
||||
elif self.isDictionary():
|
||||
return all(m.type.isSerializable() for m in self.inner.members)
|
||||
dictionary = self.inner
|
||||
while dictionary:
|
||||
if not all(m.type.isJSONType() for m in dictionary.members):
|
||||
return False
|
||||
dictionary = dictionary.parent
|
||||
return True
|
||||
else:
|
||||
raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
|
||||
"is serializable" % type(self.inner), [self.location])
|
||||
|
@ -3111,8 +3133,8 @@ class IDLBuiltinType(IDLType):
|
|||
return (self._typeTag == IDLBuiltinType.Types.unrestricted_float or
|
||||
self._typeTag == IDLBuiltinType.Types.unrestricted_double)
|
||||
|
||||
def isSerializable(self):
|
||||
return self.isPrimitive() or self.isString() or self.isDate()
|
||||
def isJSONType(self):
|
||||
return self.isPrimitive() or self.isString() or self.isObject()
|
||||
|
||||
def includesRestrictedFloat(self):
|
||||
return self.isFloat() and not self.isUnrestricted()
|
||||
|
@ -4665,7 +4687,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
def __init__(self, location, identifier, returnType, arguments,
|
||||
static=False, getter=False, setter=False,
|
||||
deleter=False, specialType=NamedOrIndexed.Neither,
|
||||
legacycaller=False, stringifier=False, jsonifier=False,
|
||||
legacycaller=False, stringifier=False,
|
||||
maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
|
||||
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
|
@ -4690,8 +4712,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
self._legacycaller = legacycaller
|
||||
assert isinstance(stringifier, bool)
|
||||
self._stringifier = stringifier
|
||||
assert isinstance(jsonifier, bool)
|
||||
self._jsonifier = jsonifier
|
||||
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
|
||||
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
|
||||
assert isinstance(htmlConstructor, bool)
|
||||
|
@ -4739,12 +4759,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
assert len(overload.arguments) == 0
|
||||
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
|
||||
|
||||
if self._jsonifier:
|
||||
assert len(self._overloads) == 1
|
||||
overload = self._overloads[0]
|
||||
assert len(overload.arguments) == 0
|
||||
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
|
||||
|
||||
def isStatic(self):
|
||||
return self._static
|
||||
|
||||
|
@ -4776,8 +4790,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
def isStringifier(self):
|
||||
return self._stringifier
|
||||
|
||||
def isJsonifier(self):
|
||||
return self._jsonifier
|
||||
def isToJSON(self):
|
||||
return self.identifier.name == "toJSON"
|
||||
|
||||
def isDefaultToJSON(self):
|
||||
return self.isToJSON() and self.getExtendedAttribute("Default")
|
||||
|
||||
def isMaplikeOrSetlikeOrIterableMethod(self):
|
||||
"""
|
||||
|
@ -4791,8 +4808,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
self.isSetter() or
|
||||
self.isDeleter() or
|
||||
self.isLegacycaller() or
|
||||
self.isStringifier() or
|
||||
self.isJsonifier())
|
||||
self.isStringifier())
|
||||
|
||||
def isHTMLConstructor(self):
|
||||
return self._htmlConstructor
|
||||
|
@ -4848,8 +4864,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
assert not method.isDeleter()
|
||||
assert not self.isStringifier()
|
||||
assert not method.isStringifier()
|
||||
assert not self.isJsonifier()
|
||||
assert not method.isJsonifier()
|
||||
assert not self.isHTMLConstructor()
|
||||
assert not method.isHTMLConstructor()
|
||||
|
||||
|
@ -4972,6 +4986,19 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
" methods on JS-implemented classes only.",
|
||||
[self.location])
|
||||
|
||||
# Ensure that toJSON methods satisfy the spec constraints on them.
|
||||
if self.identifier.name == "toJSON":
|
||||
if len(self.signatures()) != 1:
|
||||
raise WebIDLError("toJSON method has multiple overloads",
|
||||
[self._overloads[0].location,
|
||||
self._overloads[1].location])
|
||||
if len(self.signatures()[0][1]) != 0:
|
||||
raise WebIDLError("toJSON method has arguments",
|
||||
[self.location])
|
||||
if not self.signatures()[0][0].isJSONType():
|
||||
raise WebIDLError("toJSON method has non-JSON return type",
|
||||
[self.location])
|
||||
|
||||
def overloadsForArgCount(self, argc):
|
||||
return [overload for overload in self._overloads if
|
||||
len(overload.arguments) == argc or
|
||||
|
@ -5105,6 +5132,19 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
raise WebIDLError("[CEReactions] is only allowed on operation, "
|
||||
"attribute, setter, and deleter",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "Default":
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[Default] must take no arguments",
|
||||
[attr.location])
|
||||
|
||||
if not self.isToJSON():
|
||||
raise WebIDLError("[Default] is only allowed on toJSON operations",
|
||||
[attr.location, self.location])
|
||||
|
||||
if self.signatures()[0][0] != BuiltinTypes[IDLBuiltinType.Types.object]:
|
||||
raise WebIDLError("The return type of the default toJSON "
|
||||
"operation must be 'object'",
|
||||
[attr.location, self.location]);
|
||||
elif (identifier == "Throws" or
|
||||
identifier == "CanOOM" or
|
||||
identifier == "NewObject" or
|
||||
|
@ -5292,7 +5332,6 @@ class Tokenizer(object):
|
|||
"false": "FALSE",
|
||||
"serializer": "SERIALIZER",
|
||||
"stringifier": "STRINGIFIER",
|
||||
"jsonifier": "JSONIFIER",
|
||||
"unrestricted": "UNRESTRICTED",
|
||||
"attribute": "ATTRIBUTE",
|
||||
"readonly": "READONLY",
|
||||
|
@ -6123,19 +6162,6 @@ class Parser(Tokenizer):
|
|||
stringifier=True)
|
||||
p[0] = method
|
||||
|
||||
def p_Jsonifier(self, p):
|
||||
"""
|
||||
Operation : JSONIFIER SEMICOLON
|
||||
"""
|
||||
identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"__jsonifier", allowDoubleUnderscore=True)
|
||||
method = IDLMethod(self.getLocation(p, 1),
|
||||
identifier,
|
||||
returnType=BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
arguments=[],
|
||||
jsonifier=True)
|
||||
p[0] = method
|
||||
|
||||
def p_QualifierStatic(self, p):
|
||||
"""
|
||||
Qualifier : STATIC
|
||||
|
@ -6289,7 +6315,6 @@ class Parser(Tokenizer):
|
|||
| SETTER
|
||||
| STATIC
|
||||
| STRINGIFIER
|
||||
| JSONIFIER
|
||||
| TYPEDEF
|
||||
| UNRESTRICTED
|
||||
| NAMESPACE
|
||||
|
@ -6441,7 +6466,6 @@ class Parser(Tokenizer):
|
|||
| SHORT
|
||||
| STATIC
|
||||
| STRINGIFIER
|
||||
| JSONIFIER
|
||||
| TRUE
|
||||
| TYPEDEF
|
||||
| UNSIGNED
|
||||
|
@ -6958,9 +6982,12 @@ class Parser(Tokenizer):
|
|||
nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")])
|
||||
itr_ident = IDLUnresolvedIdentifier(iface.location,
|
||||
iface.identifier.name + "Iterator")
|
||||
toStringTag = iface.identifier.name + " Iterator"
|
||||
itr_iface = IDLInterface(iface.location, self.globalScope(),
|
||||
itr_ident, None, [nextMethod],
|
||||
isKnownNonPartial=True)
|
||||
isKnownNonPartial=True,
|
||||
classNameOverride=toStringTag,
|
||||
toStringTag=toStringTag)
|
||||
itr_iface.addExtendedAttributes([simpleExtendedAttr("NoInterfaceObject")])
|
||||
# Make sure the exposure set for the iterator interface is the
|
||||
# same as the exposure set for the iterable interface, because
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -1744,7 +1744,8 @@
|
||||
identifier == "ProbablyShortLivingWrapper" or
|
||||
identifier == "LegacyUnenumerableNamedProperties" or
|
||||
identifier == "RunConstructorInCallerCompartment" or
|
||||
identifier == "WantsEventListenerHooks" or
|
||||
- identifier == "NonOrdinaryGetPrototypeOf"):
|
||||
+ identifier == "NonOrdinaryGetPrototypeOf" or
|
||||
+ identifier == "Abstract"):
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
+ identifier == "Inline"):
|
||||
# Known extended attributes that do not take values
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||
|
|
|
@ -131,17 +131,3 @@ def WebIDLTest(parser, harness):
|
|||
harness.ok(threw,
|
||||
"Should have thrown for [CEReactions] used on a stringifier")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface Foo {
|
||||
[CEReactions] jsonifier;
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")
|
||||
|
|
|
@ -374,32 +374,3 @@ def WebIDLTest(parser, harness):
|
|||
threw = True
|
||||
harness.ok(threw,
|
||||
"Should not allow unknown extended attributes on interfaces")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface B {};
|
||||
[ArrayClass]
|
||||
interface A : B {
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(threw,
|
||||
"Should not allow [ArrayClass] on interfaces with parents")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
[ArrayClass]
|
||||
interface A {
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(not threw,
|
||||
"Should allow [ArrayClass] on interfaces without parents")
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON();
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow a toJSON method.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON(object arg);
|
||||
object toJSON(long arg);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow overloads of a toJSON method.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
object toJSON(object arg);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow a toJSON method with arguments.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
long toJSON();
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow a toJSON method with 'long' as return type.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
[Default] object toJSON();
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(not threw, "Should allow a default toJSON method with 'object' as return type.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse(
|
||||
"""
|
||||
interface Test {
|
||||
[Default] long toJSON();
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
harness.ok(threw, "Should not allow a default toJSON method with non-'object' as return type.")
|
||||
|
||||
JsonTypes = [ "byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long",
|
||||
"unsigned long long", "float", "unrestricted float", "double", "unrestricted double", "boolean",
|
||||
"DOMString", "ByteString", "USVString", "Enum", "InterfaceWithToJSON", "object" ]
|
||||
|
||||
nonJsonTypes = [ "InterfaceWithoutToJSON", "any", "Int8Array", "Int16Array", "Int32Array","Uint8Array",
|
||||
"Uint16Array", "Uint32Array", "Uint8ClampedArray", "Float32Array", "Float64Array", "ArrayBuffer" ]
|
||||
|
||||
def doTest(testIDL, shouldThrow, description):
|
||||
p = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
p.parse(testIDL +
|
||||
"""
|
||||
enum Enum { "a", "b", "c" };
|
||||
interface InterfaceWithToJSON { long toJSON(); };
|
||||
interface InterfaceWithoutToJSON {};
|
||||
""");
|
||||
p.finish();
|
||||
except Exception as x:
|
||||
threw = True
|
||||
harness.ok(x.message == "toJSON method has non-JSON return type", x)
|
||||
harness.check(threw, shouldThrow, description)
|
||||
|
||||
|
||||
for type in JsonTypes:
|
||||
doTest("interface Test { %s toJSON(); };" % type, False,
|
||||
"%s should be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { sequence<%s> toJSON(); };" % type, False,
|
||||
"sequence<%s> should be a JSON type" % type)
|
||||
|
||||
doTest("dictionary Foo { %s foo; }; "
|
||||
"interface Test { Foo toJSON(); }; " % type, False,
|
||||
"dictionary containing only JSON type (%s) should be a JSON type" % type)
|
||||
|
||||
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||
"interface Test { Bar toJSON(); }; " % type, False,
|
||||
"dictionary whose ancestors only contain JSON types should be a JSON type")
|
||||
|
||||
doTest("dictionary Foo { any foo; }; dictionary Bar : Foo { %s bar; };"
|
||||
"interface Test { Bar toJSON(); };" % type, True,
|
||||
"dictionary whose ancestors contain non-JSON types should not be a JSON type")
|
||||
|
||||
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, False,
|
||||
"record<DOMString, %s> should be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, False,
|
||||
"record<ByteString, %s> should be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, False,
|
||||
"record<USVString, %s> should be a JSON type" % type)
|
||||
|
||||
otherUnionType = "Foo" if type != "object" else "long"
|
||||
doTest("interface Foo { object toJSON(); };"
|
||||
"interface Test { (%s or %s) toJSON(); };" % (otherUnionType, type), False,
|
||||
"union containing only JSON types (%s or %s) should be a JSON type" %(otherUnionType, type))
|
||||
|
||||
doTest("interface test { %s? toJSON(); };" % type, False,
|
||||
"Nullable type (%s) should be a JSON type" % type)
|
||||
|
||||
doTest("interface Foo : InterfaceWithoutToJSON { %s toJSON(); };"
|
||||
"interface Test { Foo toJSON(); };" % type, False,
|
||||
"interface with toJSON should be a JSON type")
|
||||
|
||||
doTest("interface Foo : InterfaceWithToJSON { };"
|
||||
"interface Test { Foo toJSON(); };", False,
|
||||
"inherited interface with toJSON should be a JSON type")
|
||||
|
||||
for type in nonJsonTypes:
|
||||
doTest("interface Test { %s toJSON(); };" % type, True,
|
||||
"%s should not be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { sequence<%s> toJSON(); };" % type, True,
|
||||
"sequence<%s> should not be a JSON type" % type)
|
||||
|
||||
doTest("dictionary Foo { %s foo; }; "
|
||||
"interface Test { Foo toJSON(); }; " % type, True,
|
||||
"Dictionary containing a non-JSON type (%s) should not be a JSON type" % type)
|
||||
|
||||
doTest("dictionary Foo { %s foo; }; dictionary Bar : Foo { }; "
|
||||
"interface Test { Bar toJSON(); }; " % type, True,
|
||||
"dictionary whose ancestors only contain non-JSON types should not be a JSON type")
|
||||
|
||||
doTest("interface Test { record<DOMString, %s> toJSON(); };" % type, True,
|
||||
"record<DOMString, %s> should not be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { record<ByteString, %s> toJSON(); };" % type, True,
|
||||
"record<ByteString, %s> should not be a JSON type" % type)
|
||||
|
||||
doTest("interface Test { record<USVString, %s> toJSON(); };" % type, True,
|
||||
"record<USVString, %s> should not be a JSON type" % type)
|
||||
|
||||
if type != "any":
|
||||
doTest("interface Foo { object toJSON(); }; "
|
||||
"interface Test { (Foo or %s) toJSON(); };" % type, True,
|
||||
"union containing a non-JSON type (%s) should not be a JSON type" % type)
|
||||
|
||||
doTest("interface test { %s? toJSON(); };" % type, True,
|
||||
"Nullable type (%s) should not be a JSON type" % type)
|
||||
|
||||
doTest("dictionary Foo { long foo; any bar; };"
|
||||
"interface Test { Foo toJSON(); };", True,
|
||||
"dictionary containing a non-JSON type should not be a JSON type")
|
||||
|
||||
doTest("interface Foo : InterfaceWithoutToJSON { }; "
|
||||
"interface Test { Foo toJSON(); };", True,
|
||||
"interface without toJSON should not be a JSON type")
|
|
@ -246,8 +246,6 @@ impl CanvasRenderingContext2D {
|
|||
CanvasImageSource::HTMLCanvasElement(canvas) => {
|
||||
canvas.origin_is_clean()
|
||||
}
|
||||
CanvasImageSource::CanvasRenderingContext2D(image) =>
|
||||
image.origin_is_clean(),
|
||||
CanvasImageSource::HTMLImageElement(image) => {
|
||||
let image_origin = image.get_origin().expect("Image's origin is missing");
|
||||
image_origin.same_origin(GlobalScope::entry().origin())
|
||||
|
@ -294,11 +292,6 @@ impl CanvasRenderingContext2D {
|
|||
sx, sy, sw, sh,
|
||||
dx, dy, dw, dh)
|
||||
}
|
||||
CanvasImageSource::CanvasRenderingContext2D(ref image) => {
|
||||
self.draw_html_canvas_element(&image.Canvas(),
|
||||
sx, sy, sw, sh,
|
||||
dx, dy, dw, dh)
|
||||
}
|
||||
CanvasImageSource::HTMLImageElement(ref image) => {
|
||||
// https://html.spec.whatwg.org/multipage/#img-error
|
||||
// If the image argument is an HTMLImageElement object that is in the broken state,
|
||||
|
@ -1216,12 +1209,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
|||
|
||||
canvas.fetch_all_data().ok_or(Error::InvalidState)?
|
||||
},
|
||||
CanvasImageSource::CanvasRenderingContext2D(ref context) => {
|
||||
let canvas = context.Canvas();
|
||||
let _ = canvas.get_or_init_2d_context();
|
||||
|
||||
canvas.fetch_all_data().ok_or(Error::InvalidState)?
|
||||
}
|
||||
CanvasImageSource::CSSStyleValue(ref value) => {
|
||||
value.get_url(self.base_url.clone())
|
||||
.and_then(|url| self.fetch_image_data(url))
|
||||
|
|
|
@ -17,7 +17,7 @@ use dom::bindings::inheritance::Castable;
|
|||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::root::{Dom, DomRoot, LayoutDom};
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::bindings::str::{DOMString, USVString};
|
||||
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
|
||||
|
@ -191,12 +191,12 @@ impl HTMLCanvasElement {
|
|||
pub fn get_or_init_webgl_context(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
attrs: Option<HandleValue>
|
||||
options: HandleValue,
|
||||
) -> Option<DomRoot<WebGLRenderingContext>> {
|
||||
if self.context.borrow().is_none() {
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let attrs = Self::get_gl_attributes(cx, attrs)?;
|
||||
let attrs = Self::get_gl_attributes(cx, options)?;
|
||||
let maybe_ctx = WebGLRenderingContext::new(&window, self, WebGLVersion::WebGL1, size, attrs);
|
||||
|
||||
*self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(Dom::from_ref(&*ctx)));
|
||||
|
@ -212,7 +212,7 @@ impl HTMLCanvasElement {
|
|||
pub fn get_or_init_webgl2_context(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
attrs: Option<HandleValue>
|
||||
options: HandleValue,
|
||||
) -> Option<DomRoot<WebGL2RenderingContext>> {
|
||||
if !PREFS.is_webgl2_enabled() {
|
||||
return None
|
||||
|
@ -220,7 +220,7 @@ impl HTMLCanvasElement {
|
|||
if self.context.borrow().is_none() {
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let attrs = Self::get_gl_attributes(cx, attrs)?;
|
||||
let attrs = Self::get_gl_attributes(cx, options)?;
|
||||
let maybe_ctx = WebGL2RenderingContext::new(&window, self, size, attrs);
|
||||
|
||||
*self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL2(Dom::from_ref(&*ctx)));
|
||||
|
@ -243,12 +243,8 @@ impl HTMLCanvasElement {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_gl_attributes(cx: *mut JSContext, attrs: Option<HandleValue>) -> Option<GLContextAttributes> {
|
||||
let webgl_attributes = match attrs {
|
||||
Some(attrs) => attrs,
|
||||
None => return Some(GLContextAttributes::default()),
|
||||
};
|
||||
match unsafe { WebGLContextAttributes::new(cx, webgl_attributes) } {
|
||||
fn get_gl_attributes(cx: *mut JSContext, options: HandleValue) -> Option<GLContextAttributes> {
|
||||
match unsafe { WebGLContextAttributes::new(cx, options) } {
|
||||
Ok(ConversionResult::Success(ref attrs)) => Some(From::from(attrs)),
|
||||
Ok(ConversionResult::Failure(ref error)) => {
|
||||
unsafe { throw_type_error(cx, &error); }
|
||||
|
@ -310,36 +306,39 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-canvas-height
|
||||
make_uint_setter!(SetHeight, "height", DEFAULT_HEIGHT);
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
|
||||
unsafe fn GetContext(&self,
|
||||
cx: *mut JSContext,
|
||||
id: DOMString,
|
||||
attributes: Vec<HandleValue>)
|
||||
-> Option<RenderingContext> {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn GetContext(
|
||||
&self,
|
||||
cx: *mut JSContext,
|
||||
id: DOMString,
|
||||
options: HandleValue,
|
||||
) -> Option<RenderingContext> {
|
||||
match &*id {
|
||||
"2d" => {
|
||||
self.get_or_init_2d_context()
|
||||
.map(RenderingContext::CanvasRenderingContext2D)
|
||||
}
|
||||
"webgl" | "experimental-webgl" => {
|
||||
self.get_or_init_webgl_context(cx, attributes.get(0).cloned())
|
||||
self.get_or_init_webgl_context(cx, options)
|
||||
.map(RenderingContext::WebGLRenderingContext)
|
||||
}
|
||||
"webgl2" | "experimental-webgl2" => {
|
||||
self.get_or_init_webgl2_context(cx, attributes.get(0).cloned())
|
||||
self.get_or_init_webgl2_context(cx, options)
|
||||
.map(RenderingContext::WebGL2RenderingContext)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl
|
||||
unsafe fn ToDataURL(&self,
|
||||
_context: *mut JSContext,
|
||||
_mime_type: Option<DOMString>,
|
||||
_arguments: Vec<HandleValue>) -> Fallible<DOMString> {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn ToDataURL(
|
||||
&self,
|
||||
_context: *mut JSContext,
|
||||
_mime_type: Option<DOMString>,
|
||||
_quality: HandleValue,
|
||||
) -> Fallible<USVString> {
|
||||
// Step 1.
|
||||
if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() {
|
||||
if !context.origin_is_clean() {
|
||||
|
@ -349,7 +348,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
|
||||
// Step 2.
|
||||
if self.Width() == 0 || self.Height() == 0 {
|
||||
return Ok(DOMString::from("data:,"));
|
||||
return Ok(USVString("data:,".into()));
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
|
@ -363,13 +362,13 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
Some(CanvasContext::WebGL(ref context)) => {
|
||||
match context.get_image_data(self.Width(), self.Height()) {
|
||||
Some(data) => data,
|
||||
None => return Ok("data:,".into()),
|
||||
None => return Ok(USVString("data:,".into())),
|
||||
}
|
||||
}
|
||||
Some(CanvasContext::WebGL2(ref context)) => {
|
||||
match context.base_context().get_image_data(self.Width(), self.Height()) {
|
||||
Some(data) => data,
|
||||
None => return Ok("data:,".into()),
|
||||
None => return Ok(USVString("data:,".into())),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -388,7 +387,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
}
|
||||
|
||||
let encoded = base64::encode(&encoded);
|
||||
Ok(DOMString::from(format!("data:{};base64,{}", mime_type, encoded)))
|
||||
Ok(USVString(format!("data:{};base64,{}", mime_type, encoded)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ use canvas_traits::canvas::CanvasImageData;
|
|||
use canvas_traits::canvas::CanvasMsg;
|
||||
use canvas_traits::canvas::FromLayoutMsg;
|
||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule;
|
||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource;
|
||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap;
|
||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin;
|
||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
|
||||
use dom::bindings::codegen::Bindings::PaintRenderingContext2DBinding;
|
||||
use dom::bindings::codegen::Bindings::PaintRenderingContext2DBinding::PaintRenderingContext2DMethods;
|
||||
use dom::bindings::codegen::UnionTypes::HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2DOrCSSStyleValue;
|
||||
use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
|
||||
use dom::bindings::error::ErrorResult;
|
||||
use dom::bindings::error::Fallible;
|
||||
|
@ -194,37 +194,40 @@ impl PaintRenderingContext2DMethods for PaintRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2DOrCSSStyleValue,
|
||||
dx: f64,
|
||||
dy: f64)
|
||||
-> ErrorResult {
|
||||
fn DrawImage(
|
||||
&self,
|
||||
image: CanvasImageSource,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
) -> ErrorResult {
|
||||
self.context.DrawImage(image, dx, dy)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage_(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2DOrCSSStyleValue,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> ErrorResult {
|
||||
fn DrawImage_(
|
||||
&self,
|
||||
image: CanvasImageSource,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64,
|
||||
) -> ErrorResult {
|
||||
self.context.DrawImage_(image, dx, dy, dw, dh)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
fn DrawImage__(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2DOrCSSStyleValue,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: f64,
|
||||
sh: f64,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64)
|
||||
-> ErrorResult {
|
||||
fn DrawImage__(
|
||||
&self,
|
||||
image: CanvasImageSource,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: f64,
|
||||
sh: f64,
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
dw: f64,
|
||||
dh: f64,
|
||||
) -> ErrorResult {
|
||||
self.context.DrawImage__(image, sx, sy, sw, sh, dx, dy, dw, dh)
|
||||
}
|
||||
|
||||
|
@ -321,10 +324,11 @@ impl PaintRenderingContext2DMethods for PaintRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
|
||||
fn CreatePattern(&self,
|
||||
image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2DOrCSSStyleValue,
|
||||
repetition: DOMString)
|
||||
-> Fallible<DomRoot<CanvasPattern>> {
|
||||
fn CreatePattern(
|
||||
&self,
|
||||
image: CanvasImageSource,
|
||||
repetition: DOMString,
|
||||
) -> Fallible<DomRoot<CanvasPattern>> {
|
||||
self.context.CreatePattern(image, repetition)
|
||||
}
|
||||
|
||||
|
|
|
@ -540,8 +540,10 @@ impl WebGLRenderingContext {
|
|||
return Err(());
|
||||
}
|
||||
},
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLVideoElement(_rooted_video)
|
||||
=> unimplemented!(),
|
||||
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLVideoElement(_) => {
|
||||
// TODO: https://github.com/servo/servo/issues/6711
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
|
||||
return Ok((pixels, size, premultiplied));
|
||||
|
|
|
@ -2,30 +2,25 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#2dcontext
|
||||
|
||||
// typedef (HTMLImageElement or
|
||||
// SVGImageElement) HTMLOrSVGImageElement;
|
||||
typedef HTMLImageElement HTMLOrSVGImageElement;
|
||||
|
||||
typedef (HTMLOrSVGImageElement or
|
||||
/*HTMLVideoElement or*/
|
||||
HTMLCanvasElement or
|
||||
/*ImageBitmap or*/
|
||||
/*OffscreenCanvas or*/
|
||||
/*CSSImageValue*/ CSSStyleValue) CanvasImageSource;
|
||||
|
||||
enum CanvasFillRule { "nonzero", "evenodd" };
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#2dcontext
|
||||
typedef (HTMLImageElement or
|
||||
/* HTMLVideoElement or */
|
||||
HTMLCanvasElement or
|
||||
CanvasRenderingContext2D or
|
||||
/* ImageBitmap or */
|
||||
// This should probably be a CSSImageValue
|
||||
// https://github.com/w3c/css-houdini-drafts/issues/416
|
||||
CSSStyleValue) CanvasImageSource;
|
||||
|
||||
//[Constructor(optional unsigned long width, unsigned long height)]
|
||||
[Exposed=Window]
|
||||
interface CanvasRenderingContext2D {
|
||||
|
||||
// back-reference to the canvas
|
||||
readonly attribute HTMLCanvasElement canvas;
|
||||
|
||||
// canvas dimensions
|
||||
// attribute unsigned long width;
|
||||
// attribute unsigned long height;
|
||||
|
||||
// for contexts that aren't directly fixed to a specific canvas
|
||||
//void commit(); // push the image to the output bitmap
|
||||
};
|
||||
CanvasRenderingContext2D implements CanvasState;
|
||||
CanvasRenderingContext2D implements CanvasTransform;
|
||||
|
@ -33,25 +28,25 @@ CanvasRenderingContext2D implements CanvasCompositing;
|
|||
CanvasRenderingContext2D implements CanvasImageSmoothing;
|
||||
CanvasRenderingContext2D implements CanvasFillStrokeStyles;
|
||||
CanvasRenderingContext2D implements CanvasShadowStyles;
|
||||
CanvasRenderingContext2D implements CanvasFilters;
|
||||
CanvasRenderingContext2D implements CanvasRect;
|
||||
CanvasRenderingContext2D implements CanvasDrawPath;
|
||||
CanvasRenderingContext2D implements CanvasUserInterface;
|
||||
CanvasRenderingContext2D implements CanvasText;
|
||||
CanvasRenderingContext2D implements CanvasDrawImage;
|
||||
CanvasRenderingContext2D implements CanvasHitRegion;
|
||||
CanvasRenderingContext2D implements CanvasImageData;
|
||||
CanvasRenderingContext2D implements CanvasPathDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasTextDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasPath;
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasState {
|
||||
// state
|
||||
void save(); // push state on state stack
|
||||
void restore(); // pop state stack and restore state
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasTransform {
|
||||
// transformations (default transform is the identity matrix)
|
||||
void scale(unrestricted double x, unrestricted double y);
|
||||
|
@ -75,23 +70,22 @@ interface CanvasTransform {
|
|||
void resetTransform();
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasCompositing {
|
||||
// compositing
|
||||
attribute unrestricted double globalAlpha; // (default 1.0)
|
||||
attribute DOMString globalCompositeOperation; // (default source-over)
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasImageSmoothing {
|
||||
// image smoothing
|
||||
attribute boolean imageSmoothingEnabled; // (default true)
|
||||
// attribute ImageSmoothingQuality imageSmoothingQuality; // (default low)
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasFillStrokeStyles {
|
||||
|
||||
// colours and styles (see also the CanvasDrawingStyles interface)
|
||||
attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
|
||||
attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
|
||||
|
@ -102,7 +96,7 @@ interface CanvasFillStrokeStyles {
|
|||
CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasShadowStyles {
|
||||
// shadows
|
||||
attribute unrestricted double shadowOffsetX; // (default 0)
|
||||
|
@ -111,32 +105,30 @@ interface CanvasShadowStyles {
|
|||
attribute DOMString shadowColor; // (default transparent black)
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasFilters {
|
||||
// filters
|
||||
//attribute DOMString filter; // (default "none")
|
||||
};
|
||||
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasRect {
|
||||
// rects
|
||||
//[LenientFloat]
|
||||
void clearRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
|
||||
//[LenientFloat]
|
||||
void fillRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
|
||||
//[LenientFloat]
|
||||
void strokeRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasDrawPath {
|
||||
// path API (see also CanvasPathMethods)
|
||||
// path API (see also CanvasPath)
|
||||
void beginPath();
|
||||
void fill(optional CanvasFillRule fillRule = "nonzero");
|
||||
//void fill(Path2D path, optional CanvasFillRule fillRule = "nonzero");
|
||||
void stroke();
|
||||
//void stroke(Path2D path);
|
||||
//void drawFocusIfNeeded(Element element);
|
||||
//void drawFocusIfNeeded(Path2D path, Element element);
|
||||
//void scrollPathIntoView();
|
||||
//void scrollPathIntoView(Path2D path);
|
||||
void clip(optional CanvasFillRule fillRule = "nonzero");
|
||||
//void clip(Path2D path, optional CanvasFillRule fillRule = "nonzero");
|
||||
//void resetClip();
|
||||
boolean isPointInPath(unrestricted double x, unrestricted double y,
|
||||
optional CanvasFillRule fillRule = "nonzero");
|
||||
//boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y,
|
||||
|
@ -145,14 +137,17 @@ interface CanvasDrawPath {
|
|||
//boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasUserInterface {
|
||||
// TODO?
|
||||
//void drawFocusIfNeeded(Element element);
|
||||
//void drawFocusIfNeeded(Path2D path, Element element);
|
||||
//void scrollPathIntoView();
|
||||
//void scrollPathIntoView(Path2D path);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasText {
|
||||
// text (see also the CanvasDrawingStyles interface)
|
||||
// text (see also the CanvasPathDrawingStyles and CanvasTextDrawingStyles interfaces)
|
||||
[Pref="dom.canvas-text.enabled"]
|
||||
void fillText(DOMString text, unrestricted double x, unrestricted double y,
|
||||
optional unrestricted double maxWidth);
|
||||
|
@ -161,7 +156,7 @@ interface CanvasText {
|
|||
//TextMetrics measureText(DOMString text);
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasDrawImage {
|
||||
// drawing images
|
||||
[Throws]
|
||||
|
@ -176,15 +171,7 @@ interface CanvasDrawImage {
|
|||
unrestricted double dw, unrestricted double dh);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface CanvasHitRegion {
|
||||
// hit regions
|
||||
//void addHitRegion(optional HitRegionOptions options);
|
||||
//void removeHitRegion(DOMString id);
|
||||
//void clearHitRegions();
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
[Exposed=Window, NoInterfaceObject]
|
||||
interface CanvasImageData {
|
||||
// pixel manipulation
|
||||
[Throws]
|
||||
|
@ -199,9 +186,6 @@ interface CanvasImageData {
|
|||
double dirtyX, double dirtyY,
|
||||
double dirtyWidth, double dirtyHeight);
|
||||
};
|
||||
CanvasRenderingContext2D implements CanvasPathDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasTextDrawingStyles;
|
||||
CanvasRenderingContext2D implements CanvasPath;
|
||||
|
||||
enum CanvasLineCap { "butt", "round", "square" };
|
||||
enum CanvasLineJoin { "round", "bevel", "miter"};
|
||||
|
@ -209,12 +193,12 @@ enum CanvasTextAlign { "start", "end", "left", "right", "center" };
|
|||
enum CanvasTextBaseline { "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" };
|
||||
enum CanvasDirection { "ltr", "rtl", "inherit" };
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasPathDrawingStyles {
|
||||
// line caps/joins
|
||||
attribute unrestricted double lineWidth; // (default 1)
|
||||
attribute CanvasLineCap lineCap; // "butt", "round", "square" (default "butt")
|
||||
attribute CanvasLineJoin lineJoin; // "round", "bevel", "miter" (default "miter")
|
||||
attribute CanvasLineCap lineCap; // (default "butt")
|
||||
attribute CanvasLineJoin lineJoin; // (default "miter")
|
||||
attribute unrestricted double miterLimit; // (default 10)
|
||||
|
||||
// dashed lines
|
||||
|
@ -223,7 +207,7 @@ interface CanvasPathDrawingStyles {
|
|||
//attribute unrestricted double lineDashOffset;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasTextDrawingStyles {
|
||||
// text
|
||||
//attribute DOMString font; // (default 10px sans-serif)
|
||||
|
@ -233,7 +217,7 @@ interface CanvasTextDrawingStyles {
|
|||
//attribute CanvasDirection direction; // "ltr", "rtl", "inherit" (default: "inherit")
|
||||
};
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window, Worker, PaintWorklet)]
|
||||
[Exposed=(PaintWorklet, Window), NoInterfaceObject]
|
||||
interface CanvasPath {
|
||||
// shared path API methods
|
||||
void closePath();
|
||||
|
@ -253,17 +237,12 @@ interface CanvasPath {
|
|||
void arcTo(unrestricted double x1, unrestricted double y1,
|
||||
unrestricted double x2, unrestricted double y2,
|
||||
unrestricted double radius);
|
||||
// [LenientFloat] void arcTo(double x1, double y1, double x2, double y2,
|
||||
// double radiusX, double radiusY, double rotation);
|
||||
|
||||
void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
|
||||
|
||||
[Throws]
|
||||
void arc(unrestricted double x, unrestricted double y, unrestricted double radius,
|
||||
unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false);
|
||||
// [LenientFloat] void ellipse(double x, double y, double radiusX, double radiusY,
|
||||
// double rotation, double startAngle, double endAngle,
|
||||
// boolean anticlockwise);
|
||||
|
||||
[Throws]
|
||||
void ellipse(unrestricted double x, unrestricted double y, unrestricted double radius_x,
|
||||
|
|
|
@ -5,20 +5,18 @@
|
|||
// https://html.spec.whatwg.org/multipage/#htmlcanvaselement
|
||||
typedef (CanvasRenderingContext2D or WebGLRenderingContext or WebGL2RenderingContext) RenderingContext;
|
||||
|
||||
[HTMLConstructor]
|
||||
[Exposed=Window,
|
||||
HTMLConstructor]
|
||||
interface HTMLCanvasElement : HTMLElement {
|
||||
[CEReactions, Pure]
|
||||
attribute unsigned long width;
|
||||
[CEReactions, Pure]
|
||||
attribute unsigned long height;
|
||||
[CEReactions, Pure] attribute unsigned long width;
|
||||
[CEReactions, Pure] attribute unsigned long height;
|
||||
|
||||
RenderingContext? getContext(DOMString contextId, any... arguments);
|
||||
//boolean probablySupportsContext(DOMString contextId, any... arguments);
|
||||
|
||||
//void setContext(RenderingContext context);
|
||||
//CanvasProxy transferControlToProxy();
|
||||
RenderingContext? getContext(DOMString contextId, optional any options = null);
|
||||
|
||||
[Throws]
|
||||
DOMString toDataURL(optional DOMString type, any... arguments);
|
||||
//void toBlob(FileCallback? _callback, optional DOMString type, any... arguments);
|
||||
USVString toDataURL(optional DOMString type, optional any quality);
|
||||
//void toBlob(BlobCallback _callback, optional DOMString type, optional any quality);
|
||||
//OffscreenCanvas transferControlToOffscreen();
|
||||
};
|
||||
|
||||
//callback BlobCallback = void (Blob? blob);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue