зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. r=merge a=merge CLOSED TREE
This commit is contained in:
Коммит
130574a8e2
|
@ -3346,12 +3346,18 @@
|
|||
<certItem issuerName="MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey">
|
||||
<serialNumber>frj5jTuqBnQ4fljPvVU3KA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>AzL4tLuklekJ8lSh6VnRMSrk</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==">
|
||||
<serialNumber>AMs=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABFqoAZoI=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A+ly3y1rVP59k/MKfcE3DoEq</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>GN2Hrh9LtnM=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3364,6 +3370,9 @@
|
|||
<certItem issuerName="MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB">
|
||||
<serialNumber>BAAAAAABI54PryQ=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BJDHnthjoDRutxFRJPFnixbU</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CeFU2w==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3376,9 +3385,15 @@
|
|||
<certItem issuerName="MFkxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKjAoBgNVBAMTIVN0YWF0IGRlciBOZWRlcmxhbmRlbiBPdmVyaGVpZCBDQQ==">
|
||||
<serialNumber>ATFEdg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A5oET6WBWx72ColKf0txoWyR</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==">
|
||||
<serialNumber>RnQ3dg5KdDZs0nyFZk4=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BONHqLIx/ibQE08IQIyoGaXg</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=">
|
||||
<serialNumber>NpsJHyt3o1U47AAgw3UNXA==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3418,6 +3433,9 @@
|
|||
<certItem issuerName="MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=">
|
||||
<serialNumber>BYyEX2b5+K+myAIR7eXaRQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A7RCxMe1S9Hb7ENzRxl0mxGP</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=">
|
||||
<serialNumber>BAAAAAABLF5/Gog=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3430,6 +3448,9 @@
|
|||
<certItem issuerName="MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu">
|
||||
<serialNumber>BAAAAAABMYnGRuw=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A/99bZCzSpexYL5y6dSryDn3</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGKMQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEmMCQGA1UECxMdQ29weXJpZ2h0IChjKSAyMDA1IFdJU2VLZXkgU0ExFjAUBgNVBAsTDUludGVybmF0aW9uYWwxKTAnBgNVBAMTIFdJU2VLZXkgQ2VydGlmeUlEIEFkdmFuY2VkIEcxIENB">
|
||||
<serialNumber>WD1AyQAAAAAAJQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3490,6 +3511,9 @@
|
|||
<certItem issuerName="MDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTQ==">
|
||||
<serialNumber>Eg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>AyjNQ4dnGD3FD6WL5gYrYru7</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=">
|
||||
<serialNumber>Cj0=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3541,6 +3565,9 @@
|
|||
<certItem issuerName="MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=">
|
||||
<serialNumber>a12RvBNhznU=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A7uy+rmTav6tDH4dRrsnvXGH</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkGA1UEAxMiQ09NT0RPIFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==">
|
||||
<serialNumber>AKrMYlJmUUin8FOM/0TJrmk=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3688,9 +3715,15 @@
|
|||
<certItem issuerName="MEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0E=">
|
||||
<serialNumber>AjpW</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A8wZnhfuY6VIV1SwGsTGNR7L</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jvb3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==">
|
||||
<serialNumber>DL8=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A+RCQYwhofmXM+/hxdyoUzkI</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR8wHQYDVQQDExZHZW9UcnVzdCBTSEEyNTYgU1NMIENB">
|
||||
<serialNumber>OUvvVscW0/NltofkmV9qmg==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3718,6 +3751,9 @@
|
|||
<certItem issuerName="MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=">
|
||||
<serialNumber>NMpMcEnex3eXx4ohk9glcQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A7T0V6o47rgCKl3oUb7jF2Ph</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>F6QlB/yX+A==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3766,6 +3802,9 @@
|
|||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==">
|
||||
<serialNumber>QAAnEQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A3ZQibPGSZ8nPVbuccaCvUfa</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQKDBBWZXJpem9uIEJ1c2luZXNzMREwDwYDVQQLDAhPbW5pUm9vdDEfMB0GA1UEAwwWVmVyaXpvbiBHbG9iYWwgUm9vdCBDQQ==">
|
||||
<serialNumber>A4g=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3775,6 +3814,9 @@
|
|||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>BycfpA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BHT6CK6B569m/dd5dEluBOEd</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dD">
|
||||
<serialNumber>Ew1ee9Jq7Q/Dig3ACF4V6Q==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3835,6 +3877,9 @@
|
|||
<certItem issuerName="MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=">
|
||||
<serialNumber>APdCebq8ZyZr/T0luxlicNw=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A7GX+szdK8/7Kf0xUuarfyIN</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==">
|
||||
<serialNumber>YUlF+VXF2FWFqCo472HfZlw=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3913,24 +3958,12 @@
|
|||
<certItem issuerName="MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5">
|
||||
<serialNumber>QOu0a5Z9rCkw6Nk7Rg1/AQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=">
|
||||
<serialNumber>PAdKZPiaac2CvPxbOrsHOw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==">
|
||||
<serialNumber>BAAAAAABCFiEp9s=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB">
|
||||
<serialNumber>GuJ0aGBYhChXAOljooJZ3A==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==">
|
||||
<serialNumber>QM1zZ4GZ4gfwpQtUYye3Ne0=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJGaXJzdC1PYmplY3Q=">
|
||||
<serialNumber>a9rf7/BmG9JkKvRuy7J5QA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQKEwVUYWlDQTESMBAGA1UECxMJUG9saWN5IENBMSQwIgYDVQQDExtUYWlDQSBJbmZvcm1hdGlvbiBQb2xpY3kgQ0E=">
|
||||
<serialNumber>UbQGvw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMCREU=">
|
||||
<serialNumber>M0VSOewW3WI=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3943,17 +3976,11 @@
|
|||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CcHC/g==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>AQAAAAU=</serialNumber>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A3TWA5Aylxw0x8bVvrmUSNJd</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>Cfk9lw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy">
|
||||
<serialNumber>AIChpbGNqu4XKp9J70syKEs=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=">
|
||||
<serialNumber>cJ+vg4742XhNgJW2ot9eIg==</serialNumber>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A3UNTBOHUkbq+k999nJeSJdF</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5">
|
||||
<serialNumber>fMTRbGCp280pnyE/u53zbA==</serialNumber>
|
||||
|
@ -3970,12 +3997,6 @@
|
|||
<certItem issuerName="MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey">
|
||||
<serialNumber>RFlmmjulj6Ve7PfBi44nnw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>Cyr1PA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h">
|
||||
<serialNumber>Gg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CqL7CA==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -3985,30 +4006,12 @@
|
|||
<certItem issuerName="MEMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAMTFHRoYXd0ZSBTSEEyNTYgU1NMIENB">
|
||||
<serialNumber>UKKK5ol/rKBZchAAOnZjaA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzQ=">
|
||||
<serialNumber>H08=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABLM/7qjk=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABKB/OGqI=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=">
|
||||
<serialNumber>Rvm2CEw2IC2Mu/ax0A46QQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzM=">
|
||||
<serialNumber>HNo1DR4XCe4mS1iUMsY6Wg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>ByfFnw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>F5BhENPfVw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>GN2Hrh9Ltm4=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTowOAYDVQQDEzFHbG9iYWxTaWduIFBlcnNvbmFsU2lnbiBQYXJ0bmVycyBDQSAtIFNIQTI1NiAtIEcy">
|
||||
<serialNumber>AeNmeF8oVpDp/4GPvA==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4021,9 +4024,6 @@
|
|||
<certItem issuerName="MH8xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEwMC4GA1UEAxMnU3ltYW50ZWMgQ2xhc3MgMyBFQ0MgMjU2IGJpdCBFViBDQSAtIEcy">
|
||||
<serialNumber>OhrtngFwotLcm4i+z00SjA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>ESJJweWBPhoXAaB9c8SHwI4O</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==">
|
||||
<serialNumber>ANU=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4036,36 +4036,21 @@
|
|||
<certItem issuerName="MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu">
|
||||
<serialNumber>BAAAAAABJQcQRNU=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=">
|
||||
<serialNumber>VOcIuNbTqkpOMUyI108FOg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==">
|
||||
<serialNumber>HVRikKXRQ1ouhOpYcOna/A==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp">
|
||||
<serialNumber>TA5iEg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==">
|
||||
<serialNumber>RnQ3dYovwvB0D5q2YGY=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxUaGF3dGUsIEluYy4xGzAZBgNVBAMTElRoYXd0ZSBTR0MgQ0EgLSBHMg==">
|
||||
<serialNumber>e0bEFhI16xx9U1yvlI56rA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=">
|
||||
<serialNumber>JGKKnm00uOQ=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=">
|
||||
<serialNumber>Eg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MCgxCzAJBgNVBAYTAkJFMRkwFwYDVQQDExBCZWxnaXVtIFJvb3QgQ0Ey">
|
||||
<serialNumber>L1fHogsVxmfMBka5q4uzaQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=">
|
||||
<serialNumber>ezdAeCxKH7BFs7vn3byYaw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==">
|
||||
<serialNumber>AZ0=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=">
|
||||
<serialNumber>AJiU+bpWh2Uc4xFRf8GM9yA=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4075,33 +4060,18 @@
|
|||
<certItem issuerName="MFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRydXN0ZWQgUm9vdCBDQSBHMg==">
|
||||
<serialNumber>UV9aaDeNRNtQuXjRYk4Skhg=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CcHC1w==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVzdGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExIjAgBgNVBAMTGVRydXN0ZWQgUm9vdCBDQSBTSEEyNTYgRzI=">
|
||||
<serialNumber>RdHgEmEIjdyRFWDRRlk=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>BEeJFwO0nu759EPo9tKluw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLExZULVRlbGVTZWMgVHJ1c3QgQ2VudGVyMSMwIQYDVQQDExpEZXV0c2NoZSBUZWxla29tIFJvb3QgQ0EgMg==">
|
||||
<serialNumber>AQw=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==">
|
||||
<serialNumber>BAAAAAABK84yjs8=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>FJl6tXgNpSk=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAAA+X/GIyk=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>ESCC9oPNcRdPOox+SjWm9dTX</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>DjIvBkX+ECVbB/C3i6w2Gg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yaw==">
|
||||
<serialNumber>O2Qh+qhbBRuZA11yDhcLGQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4123,6 +4093,9 @@
|
|||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABJ/ufQg8=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A8LV4zckxcwdttbQSk0EPnoA</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==">
|
||||
<serialNumber>QZCrvQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4156,6 +4129,9 @@
|
|||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>GN2Hrh9Ltms=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>AyYMguSo1my449OZq51C3s3Z</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5">
|
||||
<serialNumber>Qh/QbQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4231,12 +4207,18 @@
|
|||
<certItem issuerName="MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=">
|
||||
<serialNumber>A9GPKQ8jv9oIxfwiOy7qxQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BOPwjyn5eqfeoxs7Z0y3vqNN</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>Byd/Ug==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu">
|
||||
<serialNumber>BAAAAAABIg08FMU=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BKobzjrOxa/6kCR0ImKoqaQW</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>AQAAAAA=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4309,6 +4291,9 @@
|
|||
<certItem issuerName="MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=">
|
||||
<serialNumber>MABJTA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BOc11keA9WJ9R20XQY8hO7yi</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>BydCwg==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4378,6 +4363,9 @@
|
|||
<certItem issuerName="MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlvbjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=">
|
||||
<serialNumber>R/j2qA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A/7DHCczBnP5qUVh0jF2pvwB</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CdWFNw==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4420,6 +4408,9 @@
|
|||
<certItem issuerName="MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVzdCBHbG9iYWwgUm9vdA==">
|
||||
<serialNumber>BAAAAAABQaHhNLo=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>AwBGo0Zmp6KRryAguuMvXATI</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEQxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQDExRHZW9UcnVzdCBTU0wgQ0EgLSBHMw==">
|
||||
<serialNumber>bx/XHJqcwxDOptxJ2lh5vw==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4447,6 +4438,9 @@
|
|||
<certItem issuerName="MGgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEiMCAGA1UEAxMZR2VvVHJ1c3QgRFYgU1NMIFNIQTI1NiBDQQ==">
|
||||
<serialNumber>ZgwfEqZnBsUNvNuZ77FbQA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BOIIipysxAz5xHIMmFRvYchY</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMw==">
|
||||
<serialNumber>OgxXyntHYBXnPAHDxY0OXg==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4501,6 +4495,9 @@
|
|||
<certItem issuerName="MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5">
|
||||
<serialNumber>MWzraR3LLhU9m/qKEhvVLQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>Ax6Jm7ajV49tqHgf9nYnzRCI</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEcxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxITAfBgNVBAMTGFN3aXNzU2lnbiBTaWx2ZXIgQ0EgLSBHMg==">
|
||||
<serialNumber>APiyCXmwAUq+95DYa3DmGw==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4531,6 +4528,9 @@
|
|||
<certItem issuerName="MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=">
|
||||
<serialNumber>E77H6yvyFQjO0PcN3x0H+Q==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A3WVy2V+2VFkWtMvA6HFwnhq</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=">
|
||||
<serialNumber>B+U=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4543,6 +4543,12 @@
|
|||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>GN2Hrh9LtnA=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BOncXh7IZp1SNydhtUdyh2O2</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A8aDg1/IA4O8gjMPZHVqPI+w</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MDMxCzAJBgNVBAYTAlBUMQ0wCwYDVQQKDARTQ0VFMRUwEwYDVQQDDAxFQ1JhaXpFc3RhZG8=">
|
||||
<serialNumber>cx0HrIEQg8JHWTP7DzOxSQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4603,6 +4609,9 @@
|
|||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>EAdmaA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BLlQHJ611eOZuedFrFgVAfAs</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UEAxMORFNUIFJvb3QgQ0EgWDM=">
|
||||
<serialNumber>CgFBQQAAATjtdPY5AAAAAg==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4612,6 +4621,9 @@
|
|||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABGMGjftY=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A1V4dX0tTb1rdTZxdWcuZ7YR</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=">
|
||||
<serialNumber>BUrYjru5px1ym4QUN33TOQ==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4627,6 +4639,12 @@
|
|||
<certItem issuerName="MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=">
|
||||
<serialNumber>SurdtfsuPcXXDpY2LkBpYO6BT7o=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>AxW0+uDsfyCSfhECdsGGpVD8</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A9BRwOwbXRRhCe+kcmglgW3z</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHsxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEyMDAGA1UEAxMpVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENBIC0gRzI=">
|
||||
<serialNumber>dhjnNtYx6cojdAE55TgIBA==</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4660,6 +4678,9 @@
|
|||
<certItem issuerName="MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29tMSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMTJFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==">
|
||||
<serialNumber>QZCrvA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>A0BOaf9UbJxzqBudSyes/cEM</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDM=">
|
||||
<serialNumber>NTgf4iwIfeyJPIomw2dwSXEwtxQ=</serialNumber>
|
||||
</certItem>
|
||||
|
@ -4690,8 +4711,98 @@
|
|||
<certItem issuerName="MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=">
|
||||
<serialNumber>BAAAAAABKUXDqA8=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BDV89QWZE9MJYlCpFQUv5Y2W</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJzdC1IYXJkd2FyZQ==">
|
||||
<serialNumber>Xrr31RF0DoIzMKXS6XtD+g==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=">
|
||||
<serialNumber>PAdKZPiaac2CvPxbOrsHOw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xvYmFsU2lnbiBQYXJ0bmVycyBDQQ==">
|
||||
<serialNumber>BAAAAAABCFiEp9s=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHYxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEtMCsGA1UEAxMkVmVyaVNpZ24gQ2xhc3MgMyBTU1AgSW50ZXJtZWRpYXRlIENB">
|
||||
<serialNumber>GuJ0aGBYhChXAOljooJZ3A==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BPVqx4UbKVAbJSFTKwrcFryU</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFcxCzAJBgNVBAYTAlRXMQ4wDAYDVQQKEwVUYWlDQTESMBAGA1UECxMJUG9saWN5IENBMSQwIgYDVQQDExtUYWlDQSBJbmZvcm1hdGlvbiBQb2xpY3kgQ0E=">
|
||||
<serialNumber>UbQGvw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>AQAAAAU=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>Cfk9lw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAy">
|
||||
<serialNumber>AIChpbGNqu4XKp9J70syKEs=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWU=">
|
||||
<serialNumber>cJ+vg4742XhNgJW2ot9eIg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>Cyr1PA==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MDQxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25h">
|
||||
<serialNumber>Gg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMw==">
|
||||
<serialNumber>BKrxi2/1iFxHEFzyZvegxq5C</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGYxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEgMB4GA1UEAxMXR2VvVHJ1c3QgRFYgU1NMIENBIC0gRzQ=">
|
||||
<serialNumber>H08=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==">
|
||||
<serialNumber>BAAAAAABKB/OGqI=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwx0aGF3dGUsIEluYy4xHTAbBgNVBAsTFERvbWFpbiBWYWxpZGF0ZWQgU1NMMR4wHAYDVQQDExV0aGF3dGUgRFYgU1NMIENBIC0gRzI=">
|
||||
<serialNumber>Rvm2CEw2IC2Mu/ax0A46QQ==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>ByfFnw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>F5BhENPfVw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGVMQswCQYDVQQGEwJHUjFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTE=">
|
||||
<serialNumber>GN2Hrh9Ltm4=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>ESJJweWBPhoXAaB9c8SHwI4O</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIG8MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMTYwNAYDVQQDEy1WZXJpU2lnbiBDbGFzcyAzIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gRzM=">
|
||||
<serialNumber>VOcIuNbTqkpOMUyI108FOg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFAxJDAiBgNVBAsTG0dsb2JhbFNpZ24gRUNDIFJvb3QgQ0EgLSBSNDETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbg==">
|
||||
<serialNumber>RnQ3dYovwvB0D5q2YGY=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MGMxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpDZXJ0aW5vbWlzMRcwFQYDVQQLEw4wMDAyIDQzMzk5ODkwMzEmMCQGA1UEAwwdQ2VydGlub21pcyAtIEF1dG9yaXTDqSBSYWNpbmU=">
|
||||
<serialNumber>Eg==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MH4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEfMB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazEvMC0GA1UEAxMmU3ltYW50ZWMgQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzQ=">
|
||||
<serialNumber>ezdAeCxKH7BFs7vn3byYaw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MIGFMQswCQYDVQQGEwJVUzEgMB4GA1UECgwXV2VsbHMgRmFyZ28gV2VsbHNTZWN1cmUxHDAaBgNVBAsME1dlbGxzIEZhcmdvIEJhbmsgTkExNjA0BgNVBAMMLVdlbGxzU2VjdXJlIFB1YmxpYyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eQ==">
|
||||
<serialNumber>AZ0=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAkRFMRMwEQYDVQQKEwpERk4tVmVyZWluMRAwDgYDVQQLEwdERk4tUEtJMSQwIgYDVQQDExtERk4tVmVyZWluIFBDQSBHbG9iYWwgLSBHMDE=">
|
||||
<serialNumber>CcHC1w==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFoxCzAJBgNVBAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxIjAgBgNVBAMTGUJhbHRpbW9yZSBDeWJlclRydXN0IFJvb3Q=">
|
||||
<serialNumber>BEeJFwO0nu759EPo9tKluw==</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MFYxCzAJBgNVBAYTAkpQMQ8wDQYDVQQKEwZKSVBERUMxGjAYBgNVBAsTEUpDQU4gU3ViIFJvb3QgQ0EwMRowGAYDVQQDExFKQ0FOIFN1YiBSb290IENBMA==">
|
||||
<serialNumber>BAAAAAABK84yjs8=</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>ESCC9oPNcRdPOox+SjWm9dTX</serialNumber>
|
||||
</certItem>
|
||||
<certItem issuerName="MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xhc3MgMiBQcmltYXJ5IENB">
|
||||
<serialNumber>DjIvBkX+ECVbB/C3i6w2Gg==</serialNumber>
|
||||
</certItem>
|
||||
</certItems>
|
||||
</blocklist>
|
||||
|
|
|
@ -168,7 +168,7 @@ var TabsInTitlebar = {
|
|||
let fullTabsHeight = rect($("TabsToolbar")).height;
|
||||
|
||||
// Buttons first:
|
||||
let captionButtonsBoxWidth = rect($("titlebar-buttonbox-container")).width;
|
||||
let captionButtonsBoxWidth = rect($("titlebar-buttonbox")).width;
|
||||
|
||||
let secondaryButtonsWidth, menuHeight, fullMenuHeight, menuStyles;
|
||||
if (AppConstants.platform == "macosx") {
|
||||
|
|
|
@ -904,6 +904,12 @@ CustomizeMode.prototype = {
|
|||
let removable = aPlace == "palette" || CustomizableUI.isWidgetRemovable(aNode);
|
||||
wrapper.setAttribute("removable", removable);
|
||||
|
||||
if (AppConstants.platform == "win") {
|
||||
// Allow touch events to initiate dragging in customize mode.
|
||||
// This is only supported on Windows for now.
|
||||
wrapper.setAttribute("touchdownstartsdrag", "true");
|
||||
}
|
||||
|
||||
let contextMenuAttrName = "";
|
||||
if (aNode.getAttribute("context")) {
|
||||
contextMenuAttrName = "context";
|
||||
|
|
|
@ -38,6 +38,9 @@ add_task(async function searchbar_in_panel() {
|
|||
// autocomplete panel and search for suggestions, which would
|
||||
// trigger network requests. Temporarily disable suggestions.
|
||||
await SpecialPowers.pushPrefEnv({set: [["browser.search.suggest.enabled", false]]});
|
||||
let dontShowPopup = e => e.preventDefault();
|
||||
let searchbarPopup = searchbar.textbox.popup;
|
||||
searchbarPopup.addEventListener("popupshowing", dontShowPopup);
|
||||
|
||||
searchbar.value = "foo";
|
||||
searchbar.focus();
|
||||
|
@ -55,9 +58,6 @@ add_task(async function searchbar_in_panel() {
|
|||
EventUtils.synthesizeMouseAtCenter(selectAll, {});
|
||||
await contextMenuHidden;
|
||||
|
||||
// Hide the suggestion panel.
|
||||
searchbar.textbox.popup.hidePopup();
|
||||
|
||||
ok(isOverflowOpen(), "Panel should still be open");
|
||||
|
||||
let hiddenPanelPromise = promiseOverflowHidden(window);
|
||||
|
@ -65,6 +65,9 @@ add_task(async function searchbar_in_panel() {
|
|||
await hiddenPanelPromise;
|
||||
ok(!isOverflowOpen(), "Panel should no longer be open");
|
||||
|
||||
// Allow search bar popup to show again.
|
||||
searchbarPopup.removeEventListener("popupshowing", dontShowPopup);
|
||||
|
||||
// We focused the search bar earlier - ensure we don't keep doing that.
|
||||
gURLBar.select();
|
||||
|
||||
|
|
|
@ -91,7 +91,11 @@ this.pageAction = class extends ExtensionAPI {
|
|||
|
||||
this.tabContext.shutdown();
|
||||
|
||||
if (this.browserPageAction) {
|
||||
// Removing the browser page action causes PageActions to forget about it
|
||||
// across app restarts, so don't remove it on app shutdown, but do remove
|
||||
// it on all other shutdowns since there's no guarantee the action will be
|
||||
// coming back.
|
||||
if (reason != "APP_SHUTDOWN" && this.browserPageAction) {
|
||||
this.browserPageAction.remove();
|
||||
this.browserPageAction = null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource:///modules/PageActions.jsm");
|
||||
Cu.import("resource://testing-common/AddonTestUtils.jsm");
|
||||
|
||||
const {
|
||||
createAppInfo,
|
||||
promiseShutdownManager,
|
||||
promiseStartupManager,
|
||||
} = AddonTestUtils;
|
||||
|
||||
AddonTestUtils.init(this);
|
||||
AddonTestUtils.overrideCertDB();
|
||||
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "58");
|
||||
|
||||
// This is copied and pasted from ExtensionPopups.jsm. It's used as the
|
||||
// PageActions action ID. See ext-pageAction.js.
|
||||
function makeWidgetId(id) {
|
||||
id = id.toLowerCase();
|
||||
// FIXME: This allows for collisions.
|
||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||
}
|
||||
|
||||
// Tests that the shownInUrlbar property of the PageActions.Action object
|
||||
// backing the extension's page action persists across app restarts.
|
||||
add_task(async function testAppShutdown() {
|
||||
let extensionData = {
|
||||
useAddonManager: "permanent",
|
||||
manifest: {
|
||||
page_action: {
|
||||
default_title: "test_ext_pageAction_shutdown.js",
|
||||
browser_style: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Simulate starting up the app.
|
||||
PageActions.init();
|
||||
await promiseStartupManager();
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||
await extension.startup();
|
||||
|
||||
// Get the PageAction.Action object. Its shownInUrlbar should have been
|
||||
// initialized to true in ext-pageAction.js, when it's created.
|
||||
let actionID = makeWidgetId(extension.id);
|
||||
let action = PageActions.actionForID(actionID);
|
||||
Assert.equal(action.shownInUrlbar, true);
|
||||
|
||||
// Simulate restarting the app without first unloading the extension.
|
||||
await promiseShutdownManager();
|
||||
PageActions._reset();
|
||||
await promiseStartupManager();
|
||||
await extension.awaitStartup();
|
||||
|
||||
// Get the action. Its shownInUrlbar should remain true.
|
||||
action = PageActions.actionForID(actionID);
|
||||
Assert.equal(action.shownInUrlbar, true);
|
||||
|
||||
// Now set its shownInUrlbar to false.
|
||||
action.shownInUrlbar = false;
|
||||
|
||||
// Simulate restarting the app again without first unloading the extension.
|
||||
await promiseShutdownManager();
|
||||
PageActions._reset();
|
||||
await promiseStartupManager();
|
||||
await extension.awaitStartup();
|
||||
|
||||
// Get the action. Its shownInUrlbar should remain false.
|
||||
action = PageActions.actionForID(actionID);
|
||||
Assert.equal(action.shownInUrlbar, false);
|
||||
|
||||
// Now unload the extension and quit the app.
|
||||
await extension.unload();
|
||||
await promiseShutdownManager();
|
||||
});
|
|
@ -16,10 +16,11 @@ dupe-manifest =
|
|||
# - xpcshell-remote.ini
|
||||
# For tests which should only run with both remote extensions and remote content.
|
||||
|
||||
[test_ext_geckoProfiler_schema.js]
|
||||
[test_ext_manifest_commands.js]
|
||||
[test_ext_manifest_omnibox.js]
|
||||
[test_ext_manifest_permissions.js]
|
||||
[test_ext_geckoProfiler_schema.js]
|
||||
[test_ext_pageAction_shutdown.js]
|
||||
[test_ext_pkcs11_management.js]
|
||||
|
||||
[include:xpcshell-common.ini]
|
||||
|
|
|
@ -1328,14 +1328,18 @@ PlacesController.prototype = {
|
|||
transactions = [...transactions, ...newTransactions];
|
||||
}
|
||||
|
||||
await PlacesUIUtils.batchUpdatesForNode(this._view.result, transactions.length, async () => {
|
||||
await PlacesTransactions.batch(async () => {
|
||||
for (let transaction of transactions) {
|
||||
let guid = await transaction.transact();
|
||||
itemsToSelect.push(await PlacesUtils.promiseItemId(guid));
|
||||
}
|
||||
// Note: this._view may be a view or the tree element.
|
||||
let resultForBatching = getResultForBatching(this._view);
|
||||
|
||||
await PlacesUIUtils.batchUpdatesForNode(resultForBatching,
|
||||
transactions.length, async () => {
|
||||
await PlacesTransactions.batch(async () => {
|
||||
for (let transaction of transactions) {
|
||||
let guid = await transaction.transact();
|
||||
itemsToSelect.push(await PlacesUtils.promiseItemId(guid));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let transactions = [];
|
||||
|
@ -1609,9 +1613,8 @@ var PlacesControllerDragHelper = {
|
|||
* @param {Object} insertionPoint The insertion point where the items should
|
||||
* be dropped.
|
||||
* @param {Object} dt The dataTransfer information for the drop.
|
||||
* @param {Object} view The tree view where this object is being
|
||||
* dropped to. This allows batching to take
|
||||
* place.
|
||||
* @param {Object} view The view or the tree element. This allows
|
||||
* batching to take place.
|
||||
*/
|
||||
async onDrop(insertionPoint, dt, view) {
|
||||
let doCopy = ["copy", "link"].includes(dt.dropEffect);
|
||||
|
@ -1723,9 +1726,11 @@ var PlacesControllerDragHelper = {
|
|||
return;
|
||||
}
|
||||
if (PlacesUIUtils.useAsyncTransactions) {
|
||||
await PlacesUIUtils.batchUpdatesForNode(view && view.result, transactions.length, async () => {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
});
|
||||
let resultForBatching = getResultForBatching(view);
|
||||
await PlacesUIUtils.batchUpdatesForNode(resultForBatching,
|
||||
transactions.length, async () => {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
});
|
||||
} else {
|
||||
let txn = new PlacesAggregatedTransaction("DropItems", transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
|
@ -1810,6 +1815,30 @@ function goDoPlacesCommand(aCommand) {
|
|||
controller.doCommand(aCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets the most appropriate item for using for batching. In the case of multiple
|
||||
* views being related, the method returns the most expensive result to batch.
|
||||
* For example, if it detects the left-hand library pane, then it will look for
|
||||
* and return the reference to the right-hand pane.
|
||||
*
|
||||
* @param {Object} viewOrElement The item to check.
|
||||
* @return {Object} Will return the best result node to batch, or null
|
||||
* if one could not be found.
|
||||
*/
|
||||
function getResultForBatching(viewOrElement) {
|
||||
if (viewOrElement && viewOrElement instanceof Ci.nsIDOMElement &&
|
||||
viewOrElement.id === "placesList") {
|
||||
// Note: fall back to the existing item if we can't find the right-hane pane.
|
||||
viewOrElement = document.getElementById("placeContent") || viewOrElement;
|
||||
}
|
||||
|
||||
if (viewOrElement && viewOrElement.result) {
|
||||
return viewOrElement.result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a set of transfer items and returns transactions to insert or
|
||||
* move them.
|
||||
|
|
|
@ -121,7 +121,6 @@
|
|||
<hbox flex="1" align="center">
|
||||
<textbox id="editBMPanel_tagsField"
|
||||
type="autocomplete"
|
||||
class="padded"
|
||||
flex="1"
|
||||
autocompletesearch="places-tag-autocomplete"
|
||||
completedefaultindex="true"
|
||||
|
|
|
@ -1453,7 +1453,7 @@ PlacesTreeView.prototype = {
|
|||
// since this information is specific to the tree view.
|
||||
let ip = this._getInsertionPoint(aRow, aOrientation);
|
||||
if (ip) {
|
||||
PlacesControllerDragHelper.onDrop(ip, aDataTransfer, this)
|
||||
PlacesControllerDragHelper.onDrop(ip, aDataTransfer, this._tree.element)
|
||||
.catch(Components.utils.reportError)
|
||||
.then(() => {
|
||||
// We should only clear the drop target once
|
||||
|
|
|
@ -28,8 +28,13 @@ add_task(async function test_click_on_footer() {
|
|||
// Click on the footer
|
||||
const optionButton = itemsBox.querySelector(".autocomplete-richlistitem:last-child")._optionButton;
|
||||
const prefTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, PRIVACY_PREF_URL);
|
||||
// Wait for dropdown animation finished to continue mouse synthesizing.
|
||||
await sleep(1000);
|
||||
await EventUtils.synthesizeMouseAtCenter(optionButton, {});
|
||||
await BrowserTestUtils.removeTab(await prefTabPromise);
|
||||
info(`expecting tab: about:preferences#privacy opened`);
|
||||
const prefTab = await prefTabPromise;
|
||||
info(`expecting tab: about:preferences#privacy removed`);
|
||||
await BrowserTestUtils.removeTab(prefTab);
|
||||
ok(true, "Tab: preferences#privacy was successfully opened by clicking on the footer");
|
||||
|
||||
await closePopup(browser);
|
||||
|
@ -48,7 +53,10 @@ add_task(async function test_press_enter_on_footer() {
|
|||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
}
|
||||
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
|
||||
await BrowserTestUtils.removeTab(await prefTabPromise);
|
||||
info(`expecting tab: about:preferences#privacy opened`);
|
||||
const prefTab = await prefTabPromise;
|
||||
info(`expecting tab: about:preferences#privacy removed`);
|
||||
await BrowserTestUtils.removeTab(prefTab);
|
||||
ok(true, "Tab: preferences#privacy was successfully opened by pressing enter on the footer");
|
||||
|
||||
await closePopup(browser);
|
||||
|
|
|
@ -31,6 +31,7 @@ add_task(async function test_back_forward() {
|
|||
// Now navigate forward and make sure autofill autocomplete results are still attached
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(browser);
|
||||
await BrowserTestUtils.loadURI(browser, `${URL}?load=2`);
|
||||
info("expecting browser loaded");
|
||||
await loadPromise;
|
||||
|
||||
// Check the second page
|
||||
|
@ -40,6 +41,7 @@ add_task(async function test_back_forward() {
|
|||
// Check after hitting back to the first page
|
||||
let stoppedPromise = BrowserTestUtils.browserStopped(browser);
|
||||
browser.goBack();
|
||||
info("expecting browser stopped");
|
||||
await stoppedPromise;
|
||||
await openPopupOn(browser, "#street-address");
|
||||
checkPopup(autoCompletePopup);
|
||||
|
@ -47,6 +49,7 @@ add_task(async function test_back_forward() {
|
|||
// Check after hitting forward to the second page
|
||||
stoppedPromise = BrowserTestUtils.browserStopped(browser);
|
||||
browser.goForward();
|
||||
info("expecting browser stopped");
|
||||
await stoppedPromise;
|
||||
await openPopupOn(browser, "#street-address");
|
||||
checkPopup(autoCompletePopup);
|
||||
|
|
|
@ -30,6 +30,7 @@ add_task(async function test_detach_tab_marked() {
|
|||
await closePopup(browser);
|
||||
|
||||
// Detach the tab to a new window
|
||||
info("expecting tab replaced with new window");
|
||||
let newWin = gBrowser.replaceTabWithWindow(gBrowser.getTabForBrowser(browser));
|
||||
await TestUtils.topicObserved("browser-delayed-startup-finished", subject => {
|
||||
return subject == newWin;
|
||||
|
|
|
@ -53,10 +53,9 @@ add_task(async function test_insecure_form() {
|
|||
expectedResultLength: 1,
|
||||
}];
|
||||
|
||||
await runTest(testSets[0]);
|
||||
await runTest(testSets[1]);
|
||||
await runTest(testSets[2]);
|
||||
await runTest(testSets[3]);
|
||||
for (const test of testSets) {
|
||||
await runTest(test);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_click_on_insecure_warning() {
|
||||
|
|
|
@ -102,6 +102,7 @@ async function sleep(ms = 500) {
|
|||
}
|
||||
|
||||
async function focusAndWaitForFieldsIdentified(browser, selector) {
|
||||
info("expecting the target input being focused and indentified");
|
||||
/* eslint no-shadow: ["error", { "allow": ["selector", "previouslyFocused", "previouslyIdentified"] }] */
|
||||
const {previouslyFocused, previouslyIdentified} = await ContentTask.spawn(browser, {selector}, async function({selector}) {
|
||||
Components.utils.import("resource://gre/modules/FormLikeFactory.jsm");
|
||||
|
@ -176,6 +177,7 @@ async function closePopup(browser) {
|
|||
}
|
||||
|
||||
function getRecords(data) {
|
||||
info(`expecting record retrievals: ${data.collectionName}`);
|
||||
return new Promise(resolve => {
|
||||
Services.cpmm.addMessageListener("FormAutofill:Records", function getResult(result) {
|
||||
Services.cpmm.removeMessageListener("FormAutofill:Records", getResult);
|
||||
|
@ -194,11 +196,13 @@ function getCreditCards() {
|
|||
}
|
||||
|
||||
function saveAddress(address) {
|
||||
info("expecting address saved");
|
||||
Services.cpmm.sendAsyncMessage("FormAutofill:SaveAddress", {address});
|
||||
return TestUtils.topicObserved("formautofill-storage-changed");
|
||||
}
|
||||
|
||||
function saveCreditCard(creditcard) {
|
||||
info("expecting credit card saved");
|
||||
let creditcardClone = Object.assign({}, creditcard);
|
||||
Services.cpmm.sendAsyncMessage("FormAutofill:SaveCreditCard", {
|
||||
creditcard: creditcardClone,
|
||||
|
@ -207,11 +211,13 @@ function saveCreditCard(creditcard) {
|
|||
}
|
||||
|
||||
function removeAddresses(guids) {
|
||||
info("expecting address removed");
|
||||
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveAddresses", {guids});
|
||||
return TestUtils.topicObserved("formautofill-storage-changed");
|
||||
}
|
||||
|
||||
function removeCreditCards(guids) {
|
||||
info("expecting credit card removed");
|
||||
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveCreditCards", {guids});
|
||||
return TestUtils.topicObserved("formautofill-storage-changed");
|
||||
}
|
||||
|
@ -236,6 +242,7 @@ async function clickDoorhangerButton(button, index) {
|
|||
EventUtils.synthesizeMouseAtCenter(getNotification()[button], {});
|
||||
} else if (button == MENU_BUTTON) {
|
||||
// Click the dropmarker arrow and wait for the menu to show up.
|
||||
info("expecting notification menu button present");
|
||||
await BrowserTestUtils.waitForCondition(() => getNotification().menubutton);
|
||||
await sleep(2000); // menubutton needs extra time for binding
|
||||
let notification = getNotification();
|
||||
|
@ -243,11 +250,13 @@ async function clickDoorhangerButton(button, index) {
|
|||
let dropdownPromise =
|
||||
BrowserTestUtils.waitForEvent(notification.menupopup, "popupshown");
|
||||
await EventUtils.synthesizeMouseAtCenter(notification.menubutton, {});
|
||||
info("expecting notification popup show up");
|
||||
await dropdownPromise;
|
||||
|
||||
let actionMenuItem = notification.querySelectorAll("menuitem")[index];
|
||||
await EventUtils.synthesizeMouseAtCenter(actionMenuItem, {});
|
||||
}
|
||||
info("expecting notification popup hidden");
|
||||
await popuphidden;
|
||||
}
|
||||
|
||||
|
@ -264,6 +273,7 @@ function getDoorhangerButton(button) {
|
|||
// Wait for the master password dialog to popup and enter the password to log in
|
||||
// if "login" is "true" or dismiss it directly if otherwise.
|
||||
function waitForMasterPasswordDialog(login = false) {
|
||||
info("expecting master password dialog loaded");
|
||||
let dialogShown = TestUtils.topicObserved("common-dialog-loaded");
|
||||
return dialogShown.then(([subject]) => {
|
||||
let dialog = subject.Dialog;
|
||||
|
|
|
@ -15,6 +15,7 @@ async function sleep(ms = 500, reason = "Intentionally wait for UI ready") {
|
|||
}
|
||||
|
||||
async function focusAndWaitForFieldsIdentified(input, mustBeIdentified = false) {
|
||||
info("expecting the target input being focused and indentified");
|
||||
if (typeof input === "string") {
|
||||
input = document.querySelector(input);
|
||||
}
|
||||
|
@ -66,6 +67,7 @@ function clickOnElement(selector) {
|
|||
}
|
||||
|
||||
async function onStorageChanged(type) {
|
||||
info(`expecting the storage changed: ${type}`);
|
||||
return new Promise(resolve => {
|
||||
formFillChromeScript.addMessageListener("formautofill-storage-changed", function onChanged(data) {
|
||||
formFillChromeScript.removeMessageListener("formautofill-storage-changed", onChanged);
|
||||
|
@ -87,6 +89,7 @@ function checkMenuEntries(expectedValues, isFormAutofillResult = true) {
|
|||
}
|
||||
|
||||
function invokeAsyncChromeTask(message, response, payload = {}) {
|
||||
info(`expecting the chrome task finished: ${message}`);
|
||||
return new Promise(resolve => {
|
||||
formFillChromeScript.sendAsyncMessage(message, payload);
|
||||
formFillChromeScript.addMessageListener(response, function onReceived(data) {
|
||||
|
@ -192,6 +195,7 @@ function formAutoFillCommonSetup() {
|
|||
|
||||
SimpleTest.registerCleanupFunction(async () => {
|
||||
formFillChromeScript.sendAsyncMessage("cleanup");
|
||||
info(`expecting the storage cleanup`);
|
||||
await formFillChromeScript.promiseOneMessage("cleanup-finished");
|
||||
|
||||
formFillChromeScript.destroy();
|
||||
|
|
|
@ -61,6 +61,7 @@ function checkAutoCompleteInputFilled(element, expectedvalue) {
|
|||
}
|
||||
|
||||
function checkFormFilled(address) {
|
||||
info("expecting form filled");
|
||||
let promises = [];
|
||||
for (let prop in address) {
|
||||
let element = document.getElementById(prop);
|
||||
|
|
|
@ -62,6 +62,7 @@ function checkElementFilled(element, expectedvalue) {
|
|||
}
|
||||
|
||||
function checkFormFilled(creditCard) {
|
||||
info("expecting form filled");
|
||||
let promises = [];
|
||||
for (let prop in creditCard) {
|
||||
let element = document.getElementById(prop);
|
||||
|
|
|
@ -47,6 +47,7 @@ function addInputField(form, className) {
|
|||
}
|
||||
|
||||
async function checkFormChangeHappened(formId) {
|
||||
info("expecting form changed");
|
||||
await focusAndWaitForFieldsIdentified(`#${formId} input[name=tel]`);
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
|
|
|
@ -73,6 +73,7 @@ function checkFormFilledFields(address) {
|
|||
}
|
||||
|
||||
function confirmAllFieldsFilled(address) {
|
||||
info("expecting form filled");
|
||||
const pendingPromises = [];
|
||||
|
||||
for (const prop in address) {
|
||||
|
|
|
@ -391,6 +391,14 @@ this.PageActions = {
|
|||
}
|
||||
},
|
||||
|
||||
// For tests. See Bug 1413692.
|
||||
_reset() {
|
||||
PageActions._purgeUnregisteredPersistedActions();
|
||||
PageActions._builtInActions = [];
|
||||
PageActions._nonBuiltInActions = [];
|
||||
PageActions._actionsByID = new Map();
|
||||
},
|
||||
|
||||
_storePersistedActions() {
|
||||
let json = JSON.stringify(this._persistedActions);
|
||||
Services.prefs.setStringPref(PREF_PERSISTED_ACTIONS, json);
|
||||
|
|
|
@ -166,10 +166,6 @@ menuitem.bookmark-item {
|
|||
border-color: Highlight;
|
||||
}
|
||||
|
||||
.urlbar-textbox-container {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
/* ::::: URL Bar Zoom Reset Button ::::: */
|
||||
@keyframes urlbar-zoom-reset-pulse {
|
||||
0% {
|
||||
|
@ -707,3 +703,80 @@ html|span.ac-emphasize-text-url {
|
|||
.restore-tabs-button:hover:active:not([disabled="true"]) {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
/* Hide the titlebar explicitly on versions of GTK+ where
|
||||
* it's rendered by window manager. */
|
||||
@media (-moz-gtk-csd-available: 0) {
|
||||
#titlebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* We draw to titlebar when Gkt+ CSD is available */
|
||||
@media (-moz-gtk-csd-available) {
|
||||
:root[tabsintitlebar] > #titlebar:-moz-lwtheme {
|
||||
visibility: hidden;
|
||||
}
|
||||
:root[tabsintitlebar] > #titlebar-content:-moz-lwtheme {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
:root[tabsintitlebar][sizemode="normal"] > #titlebar {
|
||||
-moz-appearance: -moz-window-titlebar;
|
||||
}
|
||||
:root[tabsintitlebar][sizemode="maximized"] > #titlebar {
|
||||
-moz-appearance: -moz-window-titlebar-maximized;
|
||||
}
|
||||
|
||||
/* The button box must appear on top of the navigator-toolbox in order for
|
||||
* click and hover mouse events to work properly for the button in the restored
|
||||
* window state. Otherwise, elements in the navigator-toolbox, like the menubar,
|
||||
* can swallow those events.
|
||||
*/
|
||||
#titlebar-buttonbox {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Render titlebar command buttons according to system config.
|
||||
* Use full scale icons here as the Gtk+ does.
|
||||
*/
|
||||
@media (-moz-gtk-csd-minimize-button) {
|
||||
#titlebar-min {
|
||||
list-style-image: url("moz-icon://stock/window-minimize-symbolic");
|
||||
-moz-appearance: -moz-window-button-minimize;
|
||||
}
|
||||
}
|
||||
@media (-moz-gtk-csd-minimize-button: 0) {
|
||||
#titlebar-min {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-gtk-csd-maximize-button) {
|
||||
#titlebar-max {
|
||||
list-style-image: url("moz-icon://stock/window-maximize-symbolic");
|
||||
-moz-appearance: -moz-window-button-maximize;
|
||||
}
|
||||
:root[sizemode="maximized"] #titlebar-max {
|
||||
list-style-image: url("moz-icon://stock/window-restore-symbolic");
|
||||
-moz-appearance: -moz-window-button-restore;
|
||||
}
|
||||
}
|
||||
@media (-moz-gtk-csd-maximize-button: 0) {
|
||||
#titlebar-max {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-gtk-csd-close-button) {
|
||||
#titlebar-close {
|
||||
list-style-image: url("moz-icon://stock/window-close-symbolic");
|
||||
-moz-appearance: -moz-window-button-close;
|
||||
}
|
||||
}
|
||||
@media (-moz-gtk-csd-close-button: 0) {
|
||||
#titlebar-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
padding: 0;
|
||||
margin: 3px 5px;
|
||||
min-height: 30px;
|
||||
cursor: default;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
|
@ -72,11 +73,6 @@
|
|||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.urlbar-input-box,
|
||||
.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#urlbar-search-splitter {
|
||||
/* The splitter width should equal the location and search bars' combined
|
||||
neighboring margin and border width. */
|
||||
|
|
|
@ -529,10 +529,6 @@ html|*.urlbar-input:-moz-lwtheme::placeholder,
|
|||
color: #777;
|
||||
}
|
||||
|
||||
.urlbar-textbox-container {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
/* ::::: URL Bar Zoom Reset Button ::::: */
|
||||
@keyframes urlbar-zoom-reset-pulse {
|
||||
0% {
|
||||
|
|
|
@ -57,12 +57,12 @@ def yasm_version(yasm):
|
|||
return Version(version)
|
||||
|
||||
|
||||
@depends(yasm_version)
|
||||
@depends_if(yasm_version)
|
||||
def yasm_major_version(yasm_version):
|
||||
return str(yasm_version.major)
|
||||
|
||||
|
||||
@depends(yasm_version)
|
||||
@depends_if(yasm_version)
|
||||
def yasm_minor_version(yasm_version):
|
||||
return str(yasm_version.minor)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
[browser_jsonview_nojs.js]
|
||||
[browser_jsonview_nul.js]
|
||||
[browser_jsonview_object-type.js]
|
||||
[browser_jsonview_row_selection.js]
|
||||
[browser_jsonview_save_json.js]
|
||||
support-files =
|
||||
!/toolkit/content/tests/browser/common/mockTransfer.js
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
info("Test JSON row selection started");
|
||||
|
||||
// Create a tall JSON so that there is a scrollbar.
|
||||
let numRows = 1e3;
|
||||
let json = JSON.stringify(Array(numRows).fill().map((_, i) => i));
|
||||
let tab = yield addJsonViewTab("data:application/json," + json);
|
||||
|
||||
is(yield getElementCount(".treeRow"), numRows, "Got the expected number of rows.");
|
||||
yield assertRowSelected(null);
|
||||
yield evalInContent("var scroller = $('.jsonPanelBox .panelContent')");
|
||||
ok(yield evalInContent("scroller.clientHeight < scroller.scrollHeight"),
|
||||
"There is a scrollbar.");
|
||||
is(yield evalInContent("scroller.scrollTop"), 0, "Initially scrolled to the top.");
|
||||
|
||||
// Click to select last row.
|
||||
yield evalInContent("$('.treeRow:last-child').click()");
|
||||
yield assertRowSelected(numRows);
|
||||
is(yield evalInContent("scroller.scrollTop + scroller.clientHeight"),
|
||||
yield evalInContent("scroller.scrollHeight"), "Scrolled to the bottom.");
|
||||
|
||||
// Click to select 2nd row.
|
||||
yield evalInContent("$('.treeRow:nth-child(2)').click()");
|
||||
yield assertRowSelected(2);
|
||||
ok(yield evalInContent("scroller.scrollTop > 0"), "Not scrolled to the top.");
|
||||
|
||||
// Synthetize up arrow key to select first row.
|
||||
yield evalInContent("$('.treeTable').focus()");
|
||||
yield BrowserTestUtils.synthesizeKey("VK_UP", {}, tab.linkedBrowser);
|
||||
yield assertRowSelected(1);
|
||||
is(yield evalInContent("scroller.scrollTop"), 0, "Scrolled to the top.");
|
||||
});
|
||||
|
||||
async function assertRowSelected(rowNum) {
|
||||
let idx = evalInContent("[].indexOf.call($$('.treeRow'), $('.treeRow.selected'))");
|
||||
is(await idx + 1, +rowNum, `${rowNum ? "The row #" + rowNum : "No row"} is selected.`);
|
||||
}
|
|
@ -119,3 +119,8 @@ addMessageListener("Test:JsonView:Eval", function (msg) {
|
|||
let result = content.eval(msg.data.code);
|
||||
sendAsyncMessage(msg.name, {result});
|
||||
});
|
||||
|
||||
Components.utils.exportFunction(content.document.querySelector.bind(content.document),
|
||||
content, {defineAs: "$"});
|
||||
Components.utils.exportFunction(content.document.querySelectorAll.bind(content.document),
|
||||
content, {defineAs: "$$"});
|
||||
|
|
|
@ -208,19 +208,16 @@ class StatisticsPanel extends Component {
|
|||
} else if (Filters.media(request)) {
|
||||
// "media"
|
||||
type = 6;
|
||||
} else if (Filters.flash(request)) {
|
||||
// "flash"
|
||||
type = 7;
|
||||
} else if (Filters.ws(request)) {
|
||||
// "ws"
|
||||
type = 8;
|
||||
type = 7;
|
||||
} else if (Filters.xhr(request)) {
|
||||
// Verify XHR last, to categorize other mime types in their own blobs.
|
||||
// "xhr"
|
||||
type = 3;
|
||||
} else {
|
||||
// "other"
|
||||
type = 9;
|
||||
type = 8;
|
||||
}
|
||||
|
||||
if (emptyCache || !this.responseIsFresh(request)) {
|
||||
|
|
|
@ -275,7 +275,6 @@ const FILTER_TAGS = [
|
|||
"fonts",
|
||||
"images",
|
||||
"media",
|
||||
"flash",
|
||||
"ws",
|
||||
"other",
|
||||
];
|
||||
|
|
|
@ -61,15 +61,6 @@ function isMedia({ mimeType }) {
|
|||
mimeType.includes("model/"));
|
||||
}
|
||||
|
||||
function isFlash({ url, mimeType }) {
|
||||
// Flash is a mess.
|
||||
return (mimeType && (
|
||||
mimeType.includes("/x-flv") ||
|
||||
mimeType.includes("/x-shockwave-flash"))) ||
|
||||
url.includes(".swf") ||
|
||||
url.includes(".flv");
|
||||
}
|
||||
|
||||
function isWS({ requestHeaders, responseHeaders }) {
|
||||
// Detect a websocket upgrade if request has an Upgrade header with value 'websocket'
|
||||
if (!requestHeaders || !Array.isArray(requestHeaders.headers)) {
|
||||
|
@ -100,7 +91,7 @@ function isWS({ requestHeaders, responseHeaders }) {
|
|||
}
|
||||
|
||||
function isOther(item) {
|
||||
let tests = [isHtml, isCss, isJs, isXHR, isFont, isImage, isMedia, isFlash, isWS];
|
||||
let tests = [isHtml, isCss, isJs, isXHR, isFont, isImage, isMedia, isWS];
|
||||
return tests.every(is => !is(item));
|
||||
}
|
||||
|
||||
|
@ -114,7 +105,6 @@ module.exports = {
|
|||
fonts: isFont,
|
||||
images: isImage,
|
||||
media: isMedia,
|
||||
flash: isFlash,
|
||||
ws: isWS,
|
||||
other: isOther,
|
||||
},
|
||||
|
|
|
@ -213,13 +213,6 @@ add_task(function* () {
|
|||
testFilterButtons(monitor, "media");
|
||||
yield testContents([0, 0, 0, 0, 0, 1, 1, 0, 0]);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-all-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-flash-button"));
|
||||
testFilterButtons(monitor, "flash");
|
||||
yield testContents([0, 0, 0, 0, 0, 0, 0, 1, 0]);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-all-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
|
@ -265,25 +258,20 @@ add_task(function* () {
|
|||
document.querySelector(".requests-list-filter-html-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-css-button"));
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
yield testContents([1, 1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
// Html and css filter enabled and text filter should show just the html and css match.
|
||||
// Should not show both the items matching the button plus the items matching the text.
|
||||
setFreetextFilter("sample");
|
||||
yield testContents([1, 1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-flash-button"));
|
||||
setFreetextFilter("");
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0]);
|
||||
yield testContents([1, 1, 0, 0, 0, 0, 0, 1, 0]);
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
yield testContents([1, 1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
// Disable some filters. Only one left active.
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-css-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-flash-button"));
|
||||
testFilterButtons(monitor, "html");
|
||||
yield testContents([1, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
|
@ -300,7 +288,7 @@ add_task(function* () {
|
|||
document.querySelector(".requests-list-filter-css-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-ws-button"));
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 0, 1]);
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 0, 0, 0, 0, 0, 1, 0]);
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-all-button"));
|
||||
testFilterButtons(monitor, "all");
|
||||
|
|
|
@ -38,7 +38,7 @@ add_task(function* () {
|
|||
|
||||
testStatus();
|
||||
|
||||
let buttons = ["html", "css", "js", "xhr", "fonts", "images", "media", "flash"];
|
||||
let buttons = ["html", "css", "js", "xhr", "fonts", "images", "media"];
|
||||
for (let button of buttons) {
|
||||
let buttonEl = document.querySelector(`.requests-list-filter-${button}-button`);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, buttonEl);
|
||||
|
|
|
@ -26,7 +26,7 @@ add_task(function* () {
|
|||
document.querySelector(".requests-list-filter-ws-button"));
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector(".requests-list-filter-other-button"));
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1]);
|
||||
testFilterButtonsCustom(monitor, [0, 1, 1, 1, 0, 0, 0, 0, 1, 1]);
|
||||
info("The correct filtering predicates are used before entering perf. analysis mode.");
|
||||
|
||||
store.dispatch(Actions.openStatistics(connector, true));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
define(function (require, exports, module) {
|
||||
const { cloneElement, Component, createFactory, DOM: dom, PropTypes } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
// Reps
|
||||
const { ObjectProvider } = require("./ObjectProvider");
|
||||
|
@ -153,7 +154,7 @@ define(function (require, exports, module) {
|
|||
// TODO: Do better than just selecting the first row again. We want to
|
||||
// select (in order) previous, next or parent in case when selected
|
||||
// row is removed.
|
||||
this.selectRow(this.rows[0].props.member.path);
|
||||
this.selectRow(this.rows[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,13 +256,13 @@ define(function (require, exports, module) {
|
|||
case "ArrowDown":
|
||||
let nextRow = this.rows[index + 1];
|
||||
if (nextRow) {
|
||||
this.selectRow(nextRow.props.member.path);
|
||||
this.selectRow(nextRow);
|
||||
}
|
||||
break;
|
||||
case "ArrowUp":
|
||||
let previousRow = this.rows[index - 1];
|
||||
if (previousRow) {
|
||||
this.selectRow(previousRow.props.member.path);
|
||||
this.selectRow(previousRow);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -277,7 +278,7 @@ define(function (require, exports, module) {
|
|||
if (cell && cell.classList.contains("treeLabelCell")) {
|
||||
this.toggle(nodePath);
|
||||
}
|
||||
this.selectRow(nodePath);
|
||||
this.selectRow(event.currentTarget);
|
||||
}
|
||||
|
||||
getSelectedRow(rows) {
|
||||
|
@ -287,10 +288,12 @@ define(function (require, exports, module) {
|
|||
return rows.find(row => this.isSelected(row.props.member.path));
|
||||
}
|
||||
|
||||
selectRow(nodePath) {
|
||||
selectRow(row) {
|
||||
row = findDOMNode(row);
|
||||
this.setState(Object.assign({}, this.state, {
|
||||
selected: nodePath
|
||||
selected: row.id
|
||||
}));
|
||||
row.scrollIntoView({block: "nearest"});
|
||||
}
|
||||
|
||||
isSelected(nodePath) {
|
||||
|
|
|
@ -494,7 +494,9 @@ checkbox:-moz-focusring {
|
|||
top: 100%;
|
||||
width: 100%;
|
||||
line-height: initial !important;
|
||||
z-index: 999;
|
||||
/* See bug - 1414609. z-index is greater than 1000 so that searchbox's z-index
|
||||
is more than z-index of requests-list-headers-wrapper in netmonitor */
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* Don't add 'double spacing' for inputs that are at beginning / end
|
||||
|
|
|
@ -191,7 +191,7 @@
|
|||
fill: var(--theme-toolbar-selected-color);
|
||||
}
|
||||
|
||||
.devtools-tab:not(.selected).highlighted > img {
|
||||
.devtools-tab.highlighted > img {
|
||||
fill: var(--theme-toolbar-highlighted-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ a {
|
|||
* assertion when loading HTML page with links in XUL iframe */
|
||||
*:visited { }
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
padding: 0 7px;
|
||||
|
|
|
@ -95,7 +95,8 @@ support-files =
|
|||
test-bug-869003-iframe.html
|
||||
test-bug-869003-top-window.html
|
||||
test-bug-952277-highlight-nodes-in-vview.html
|
||||
test-bug-989025-iframe-parent.html
|
||||
test-iframe-child.html
|
||||
test-iframe-parent.html
|
||||
test-certificate-messages.html
|
||||
test-closure-optimized-out.html
|
||||
test-closures.html
|
||||
|
@ -198,8 +199,11 @@ skip-if = true # Bug 1403188
|
|||
[browser_jsterm_add_edited_input_to_history.js]
|
||||
[browser_jsterm_autocomplete_array_no_index.js]
|
||||
[browser_jsterm_autocomplete_cached_results.js]
|
||||
[browser_jsterm_autocomplete_crossdomain_iframe.js]
|
||||
[browser_jsterm_autocomplete_escape_key.js]
|
||||
[browser_jsterm_autocomplete_extraneous_closing_brackets.js]
|
||||
[browser_jsterm_autocomplete_helpers.js]
|
||||
[browser_jsterm_autocomplete_in_debugger_stackframe.js]
|
||||
[browser_jsterm_autocomplete_inside_text.js]
|
||||
[browser_jsterm_autocomplete_nav_and_tab_key.js]
|
||||
[browser_jsterm_autocomplete_return_key_no_selection.js]
|
||||
|
@ -221,17 +225,12 @@ subsuite = clipboard
|
|||
tags = mcb
|
||||
skip-if = true # Bug 1403452
|
||||
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
|
||||
[browser_webconsole_autocomplete_crossdomain_iframe.js]
|
||||
skip-if = true # Bug 1408919
|
||||
[browser_webconsole_autocomplete_in_debugger_stackframe.js]
|
||||
skip-if = true # Bug 1408920
|
||||
[browser_webconsole_batching.js]
|
||||
[browser_webconsole_block_mixedcontent_securityerrors.js]
|
||||
tags = mcb
|
||||
skip-if = true # Bug 1403899
|
||||
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
|
||||
[browser_webconsole_cached_messages.js]
|
||||
skip-if = true # Bug 1406069
|
||||
[browser_webconsole_cd_iframe.js]
|
||||
skip-if = true # Bug 1406030
|
||||
[browser_webconsole_certificate_messages.js]
|
||||
|
@ -246,8 +245,6 @@ skip-if = true # Bug 1406038
|
|||
[browser_webconsole_clickable_urls.js]
|
||||
[browser_webconsole_closing_after_completion.js]
|
||||
skip-if = true # Bug 1408927
|
||||
[browser_webconsole_closing_brackets.js]
|
||||
skip-if = true # Bug 1408928
|
||||
[browser_webconsole_closure_inspection.js]
|
||||
skip-if = true # Bug 1405250
|
||||
[browser_webconsole_completion.js]
|
||||
|
@ -256,7 +253,6 @@ skip-if = true # Bug 1408929
|
|||
skip-if = true # Bug 1408930
|
||||
[browser_webconsole_console_dir.js]
|
||||
[browser_webconsole_console_dir_uninspectable.js]
|
||||
skip-if = true # Bug 1403449
|
||||
[browser_webconsole_console_group.js]
|
||||
[browser_webconsole_console_logging_workers_api.js]
|
||||
skip-if = true # Bug 1405252
|
||||
|
@ -271,10 +267,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
subsuite = clipboard
|
||||
[browser_webconsole_context_menu_open_url.js]
|
||||
[browser_webconsole_context_menu_store_as_global.js]
|
||||
[browser_webconsole_copy_entire_message_context_menu.js]
|
||||
subsuite = clipboard
|
||||
skip-if = true # Bug 1401958
|
||||
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
|
||||
[browser_webconsole_copy_link_location.js]
|
||||
skip-if = true # Bug 1401944
|
||||
[browser_webconsole_csp_ignore_reflected_xss_message.js]
|
||||
|
|
|
@ -18,7 +18,8 @@ add_task(async function () {
|
|||
inputNode: input,
|
||||
} = jsterm;
|
||||
|
||||
const jstermComplete = (value, delta) => complete(jsterm, input, value, delta);
|
||||
const jstermComplete = (value, offset) =>
|
||||
jstermSetValueAndComplete(jsterm, value, offset);
|
||||
|
||||
// Test if 'doc' gives 'document'
|
||||
await jstermComplete("doc");
|
||||
|
@ -65,16 +66,6 @@ add_task(async function () {
|
|||
"autocomplete cached results do not contain docfoobar. list has not been updated");
|
||||
});
|
||||
|
||||
function complete(jsterm, input, value, caretIndexDelta = 0) {
|
||||
input.value = value;
|
||||
let index = value.length + caretIndexDelta;
|
||||
input.setSelectionRange(index, index);
|
||||
|
||||
const updated = jsterm.once("autocomplete-updated");
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
|
||||
return updated;
|
||||
}
|
||||
|
||||
function getPopupLabels(popup) {
|
||||
return popup.getItems().map(item => item.label);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that autocomplete doesn't break when trying to reach into objects from
|
||||
// a different domain. See Bug 989025.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"new-console-output/test/mochitest/test-iframe-parent.html";
|
||||
add_task(async function () {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
const { jsterm } = hud;
|
||||
|
||||
const onParentTitle = waitForMessage(hud, "iframe parent");
|
||||
jsterm.execute("document.title");
|
||||
await onParentTitle;
|
||||
ok(true, "root document's title is accessible");
|
||||
|
||||
// Make sure we don't throw when trying to autocomplete
|
||||
let autocompleteUpdated = hud.jsterm.once("autocomplete-updated");
|
||||
jsterm.setInputValue("window[0].document");
|
||||
EventUtils.synthesizeKey(".", {});
|
||||
await autocompleteUpdated;
|
||||
|
||||
hud.jsterm.setInputValue("window[0].document.title");
|
||||
const onPermissionDeniedMessage = waitForMessage(hud, "Permission denied");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
const permissionDenied = await onPermissionDeniedMessage;
|
||||
ok(permissionDenied.node.classList.contains("error"),
|
||||
"A message error is shown when trying to inspect window[0]");
|
||||
|
||||
const onParentLocation = waitForMessage(hud, "test-iframe-parent.html");
|
||||
hud.jsterm.execute("window.location");
|
||||
await onParentLocation;
|
||||
ok(true, "root document's location is accessible");
|
||||
});
|
|
@ -10,20 +10,13 @@
|
|||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,test for bug 592442";
|
||||
|
||||
add_task(function* () {
|
||||
yield loadTab(TEST_URI);
|
||||
let hud = yield openConsole();
|
||||
hud.jsterm.clearOutput();
|
||||
let jsterm = hud.jsterm;
|
||||
add_task(async function () {
|
||||
let { jsterm } = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
jsterm.setInputValue("document.getElementById)");
|
||||
|
||||
let error = false;
|
||||
try {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
|
||||
await jstermSetValueAndComplete(jsterm, "document.getElementById)");
|
||||
ok(true, "no error was thrown when an extraneous bracket was inserted");
|
||||
} catch (ex) {
|
||||
error = true;
|
||||
ok(false, "an error was thrown when an extraneous bracket was inserted")
|
||||
}
|
||||
|
||||
ok(!error, "no error was thrown when an extraneous bracket was inserted");
|
||||
});
|
|
@ -0,0 +1,116 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that makes sure web console autocomplete happens in the user-selected
|
||||
// stackframe from the js debugger.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"new-console-output/test/mochitest/test-autocomplete-in-stackframe.html";
|
||||
|
||||
add_task(async function () {
|
||||
// Force the old debugger UI since it's directly used (see Bug 1301705)
|
||||
await pushPref("devtools.debugger.new-debugger-frontend", false);
|
||||
|
||||
let { jsterm } = await openNewTabAndConsole(TEST_URI);
|
||||
const {
|
||||
autocompletePopup: popup,
|
||||
} = jsterm;
|
||||
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
const jstermComplete = value => jstermSetValueAndComplete(jsterm, value);
|
||||
|
||||
// Test that document.title gives string methods. Native getters must execute.
|
||||
await jstermComplete("document.title.");
|
||||
|
||||
let newItemsLabels = getPopupLabels(popup);
|
||||
ok(newItemsLabels.length > 0, "'document.title.' gave a list of suggestions");
|
||||
ok(newItemsLabels.includes("substr"), `results do contain "substr"`);
|
||||
ok(newItemsLabels.includes("toLowerCase"), `results do contain "toLowerCase"`);
|
||||
ok(newItemsLabels.includes("strike"), `results do contain "strike"`);
|
||||
|
||||
// Test if 'foo' gives 'foo1' but not 'foo2' or 'foo3'
|
||||
await jstermComplete("foo");
|
||||
is(getPopupLabels(popup).join("-"), "foo1Obj-foo1",
|
||||
`"foo" gave the expected suggestions`);
|
||||
|
||||
// Test if 'foo1Obj.' gives 'prop1' and 'prop2'
|
||||
await jstermComplete("foo1Obj.");
|
||||
is(getPopupLabels(popup).join("-"), "prop2-prop1",
|
||||
`"foo1Obj." gave the expected suggestions`);
|
||||
|
||||
// Test if 'foo1Obj.prop2.' gives 'prop21'
|
||||
await jstermComplete("foo1Obj.prop2.");
|
||||
ok(getPopupLabels(popup).includes("prop21"),
|
||||
`"foo1Obj.prop2." gave the expected suggestions`);
|
||||
|
||||
info("Opening Debugger");
|
||||
let {panel} = await openDebugger();
|
||||
|
||||
info("Waiting for pause");
|
||||
const stackFrames = await pauseDebugger(panel);
|
||||
|
||||
info("Opening Console again");
|
||||
await toolbox.selectTool("webconsole");
|
||||
|
||||
// Test if 'foo' gives 'foo3' and 'foo1' but not 'foo2', since we are paused in
|
||||
// the `secondCall` function (called by `firstCall`, which we call in `pauseDebugger`).
|
||||
await jstermComplete("foo");
|
||||
is(getPopupLabels(popup).join("-"), "foo3Obj-foo3-foo1Obj-foo1",
|
||||
`"foo" gave the expected suggestions`);
|
||||
|
||||
await openDebugger();
|
||||
|
||||
// Select the frame for the `firstCall` function.
|
||||
stackFrames.selectFrame(1);
|
||||
|
||||
info("openConsole");
|
||||
await toolbox.selectTool("webconsole");
|
||||
|
||||
// Test if 'foo' gives 'foo2' and 'foo1' but not 'foo3', since we are now in the
|
||||
// `firstCall` frame.
|
||||
await jstermComplete("foo");
|
||||
is(getPopupLabels(popup).join("-"), "foo2Obj-foo2-foo1Obj-foo1",
|
||||
`"foo" gave the expected suggestions`);
|
||||
|
||||
// Test if 'foo2Obj.' gives 'prop1'
|
||||
await jstermComplete("foo2Obj.");
|
||||
ok(getPopupLabels(popup).includes("prop1"), `"foo2Obj." returns "prop1"`);
|
||||
|
||||
// Test if 'foo2Obj.prop1.' gives 'prop11'
|
||||
await jstermComplete("foo2Obj.prop1.");
|
||||
ok(getPopupLabels(popup).includes("prop11"), `"foo2Obj.prop1" returns "prop11"`);
|
||||
|
||||
// Test if 'foo2Obj.prop1.prop11.' gives suggestions for a string,i.e. 'length'
|
||||
await jstermComplete("foo2Obj.prop1.prop11.");
|
||||
ok(getPopupLabels(popup).includes("length"), `results do contain "length"`);
|
||||
|
||||
// Test if 'foo2Obj[0].' throws no errors.
|
||||
await jstermComplete("foo2Obj[0].");
|
||||
is(getPopupLabels(popup).length, 0, "no items for foo2Obj[0]");
|
||||
});
|
||||
|
||||
function getPopupLabels(popup) {
|
||||
return popup.getItems().map(item => item.label);
|
||||
}
|
||||
|
||||
function pauseDebugger(debuggerPanel) {
|
||||
const debuggerWin = debuggerPanel.panelWin;
|
||||
const debuggerController = debuggerWin.DebuggerController;
|
||||
const thread = debuggerController.activeThread;
|
||||
|
||||
return new Promise(resolve => {
|
||||
thread.addOneTimeListener("framesadded", () =>
|
||||
resolve(debuggerController.StackFrames));
|
||||
|
||||
info("firstCall()");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
|
||||
content.wrappedJSObject.firstCall();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that autocomplete doesn't break when trying to reach into objects from
|
||||
// a different domain, bug 989025.
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let hud;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-bug-989025-iframe-parent.html";
|
||||
|
||||
Task.spawn(function* () {
|
||||
const {tab} = yield loadTab(TEST_URI);
|
||||
hud = yield openConsole(tab);
|
||||
|
||||
hud.jsterm.execute("document.title");
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "989025 - iframe parent",
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
|
||||
let autocompleteUpdated = hud.jsterm.once("autocomplete-updated");
|
||||
|
||||
hud.jsterm.setInputValue("window[0].document");
|
||||
executeSoon(() => {
|
||||
EventUtils.synthesizeKey(".", {});
|
||||
});
|
||||
|
||||
yield autocompleteUpdated;
|
||||
|
||||
hud.jsterm.setInputValue("window[0].document.title");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "Permission denied",
|
||||
category: CATEGORY_OUTPUT,
|
||||
severity: SEVERITY_ERROR,
|
||||
}],
|
||||
});
|
||||
|
||||
hud.jsterm.execute("window.location");
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "test-bug-989025-iframe-parent.html",
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
|
||||
yield closeConsole(tab);
|
||||
}).then(finishTest);
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that makes sure web console autocomplete happens in the user-selected
|
||||
// stackframe from the js debugger.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-autocomplete-in-stackframe.html";
|
||||
|
||||
// Force the old debugger UI since it's directly used (see Bug 1301705)
|
||||
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
|
||||
registerCleanupFunction(function* () {
|
||||
Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
|
||||
});
|
||||
|
||||
var gStackframes;
|
||||
registerCleanupFunction(function () {
|
||||
gStackframes = null;
|
||||
});
|
||||
|
||||
requestLongerTimeout(2);
|
||||
add_task(function* () {
|
||||
yield loadTab(TEST_URI);
|
||||
let hud = yield openConsole();
|
||||
yield testCompletion(hud);
|
||||
});
|
||||
|
||||
function* testCompletion(hud) {
|
||||
let jsterm = hud.jsterm;
|
||||
let input = jsterm.inputNode;
|
||||
let popup = jsterm.autocompletePopup;
|
||||
|
||||
// Test that document.title gives string methods. Native getters must execute.
|
||||
input.value = "document.title.";
|
||||
input.setSelectionRange(input.value.length, input.value.length);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
let newItems = popup.getItems();
|
||||
ok(newItems.length > 0, "'document.title.' gave a list of suggestions");
|
||||
ok(newItems.some(function (item) {
|
||||
return item.label == "substr";
|
||||
}), "autocomplete results do contain substr");
|
||||
ok(newItems.some(function (item) {
|
||||
return item.label == "toLowerCase";
|
||||
}), "autocomplete results do contain toLowerCase");
|
||||
ok(newItems.some(function (item) {
|
||||
return item.label == "strike";
|
||||
}), "autocomplete results do contain strike");
|
||||
|
||||
// Test if 'f' gives 'foo1' but not 'foo2' or 'foo3'
|
||||
input.value = "f";
|
||||
input.setSelectionRange(1, 1);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(newItems.length > 0, "'f' gave a list of suggestions");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1";
|
||||
}), "autocomplete results do contain foo1");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1Obj";
|
||||
}), "autocomplete results do contain foo1Obj");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo2";
|
||||
}), "autocomplete results do not contain foo2");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo2Obj";
|
||||
}), "autocomplete results do not contain foo2Obj");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo3";
|
||||
}), "autocomplete results do not contain foo3");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo3Obj";
|
||||
}), "autocomplete results do not contain foo3Obj");
|
||||
|
||||
// Test if 'foo1Obj.' gives 'prop1' and 'prop2'
|
||||
input.value = "foo1Obj.";
|
||||
input.setSelectionRange(8, 8);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "prop1";
|
||||
}), "autocomplete results do contain prop1");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "prop2";
|
||||
}), "autocomplete results do contain prop2");
|
||||
|
||||
// Test if 'foo1Obj.prop2.' gives 'prop21'
|
||||
input.value = "foo1Obj.prop2.";
|
||||
input.setSelectionRange(14, 14);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "prop21";
|
||||
}), "autocomplete results do contain prop21");
|
||||
|
||||
info("Opening Debugger");
|
||||
let dbg = yield openDebugger();
|
||||
|
||||
info("Waiting for pause");
|
||||
yield pauseDebugger(dbg);
|
||||
|
||||
info("Opening Console again");
|
||||
yield openConsole();
|
||||
|
||||
// From this point on the
|
||||
// Test if 'f' gives 'foo3' and 'foo1' but not 'foo2'
|
||||
input.value = "f";
|
||||
input.setSelectionRange(1, 1);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(newItems.length > 0, "'f' gave a list of suggestions");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo3";
|
||||
}), "autocomplete results do contain foo3");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo3Obj";
|
||||
}), "autocomplete results do contain foo3Obj");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1";
|
||||
}), "autocomplete results do contain foo1");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1Obj";
|
||||
}), "autocomplete results do contain foo1Obj");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo2";
|
||||
}), "autocomplete results do not contain foo2");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo2Obj";
|
||||
}), "autocomplete results do not contain foo2Obj");
|
||||
|
||||
yield openDebugger();
|
||||
|
||||
gStackframes.selectFrame(1);
|
||||
|
||||
info("openConsole");
|
||||
yield openConsole();
|
||||
|
||||
// Test if 'f' gives 'foo2' and 'foo1' but not 'foo3'
|
||||
input.value = "f";
|
||||
input.setSelectionRange(1, 1);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(newItems.length > 0, "'f' gave a list of suggestions");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo2";
|
||||
}), "autocomplete results do contain foo2");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo2Obj";
|
||||
}), "autocomplete results do contain foo2Obj");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1";
|
||||
}), "autocomplete results do contain foo1");
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "foo1Obj";
|
||||
}), "autocomplete results do contain foo1Obj");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo3";
|
||||
}), "autocomplete results do not contain foo3");
|
||||
ok(newItems.every(function (item) {
|
||||
return item.label != "foo3Obj";
|
||||
}), "autocomplete results do not contain foo3Obj");
|
||||
|
||||
// Test if 'foo2Obj.' gives 'prop1'
|
||||
input.value = "foo2Obj.";
|
||||
input.setSelectionRange(8, 8);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "prop1";
|
||||
}), "autocomplete results do contain prop1");
|
||||
|
||||
// Test if 'foo2Obj.prop1.' gives 'prop11'
|
||||
input.value = "foo2Obj.prop1.";
|
||||
input.setSelectionRange(14, 14);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "prop11";
|
||||
}), "autocomplete results do contain prop11");
|
||||
|
||||
// Test if 'foo2Obj.prop1.prop11.' gives suggestions for a string
|
||||
// i.e. 'length'
|
||||
input.value = "foo2Obj.prop1.prop11.";
|
||||
input.setSelectionRange(21, 21);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
ok(!newItems.every(function (item) {
|
||||
return item.label != "length";
|
||||
}), "autocomplete results do contain length");
|
||||
|
||||
// Test if 'foo1Obj[0].' throws no errors.
|
||||
input.value = "foo2Obj[0].";
|
||||
input.setSelectionRange(11, 11);
|
||||
yield new Promise(resolve => {
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
|
||||
});
|
||||
|
||||
newItems = popup.getItems();
|
||||
is(newItems.length, 0, "no items for foo2Obj[0]");
|
||||
}
|
||||
|
||||
function pauseDebugger(aResult) {
|
||||
let debuggerWin = aResult.panelWin;
|
||||
let debuggerController = debuggerWin.DebuggerController;
|
||||
let thread = debuggerController.activeThread;
|
||||
gStackframes = debuggerController.StackFrames;
|
||||
return new Promise(resolve => {
|
||||
thread.addOneTimeListener("framesadded", resolve);
|
||||
|
||||
info("firstCall()");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
|
||||
content.wrappedJSObject.firstCall();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -9,51 +9,41 @@
|
|||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-webconsole-error-observer.html";
|
||||
"new-console-output/test/mochitest/test-webconsole-error-observer.html";
|
||||
|
||||
// On e10s, the exception is triggered in child process
|
||||
// and is ignored by test harness
|
||||
if (!Services.appinfo.browserTabsRemoteAutostart) {
|
||||
expectUncaughtException();
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
loadTab(TEST_URI).then(testOpenUI);
|
||||
}
|
||||
|
||||
function testOpenUI(aTestReopen) {
|
||||
openConsole().then((hud) => {
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
text: "log Bazzle",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "error Bazzle",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
},
|
||||
{
|
||||
text: "bazBug611032",
|
||||
category: CATEGORY_JS,
|
||||
severity: SEVERITY_ERROR,
|
||||
},
|
||||
{
|
||||
text: "cssColorBug611032",
|
||||
category: CATEGORY_CSS,
|
||||
severity: SEVERITY_WARNING,
|
||||
},
|
||||
],
|
||||
}).then(() => {
|
||||
closeConsole(gBrowser.selectedTab).then(() => {
|
||||
aTestReopen && info("will reopen the Web Console");
|
||||
executeSoon(aTestReopen ? testOpenUI : finishTest);
|
||||
});
|
||||
});
|
||||
});
|
||||
add_task(async function() {
|
||||
// On e10s, the exception is triggered in child process
|
||||
// and is ignored by test harness
|
||||
if (!Services.appinfo.browserTabsRemoteAutostart) {
|
||||
expectUncaughtException();
|
||||
}
|
||||
// Enable CSS filter for the test.
|
||||
await pushPref("devtools.webconsole.filter.css", true);
|
||||
|
||||
await addTab(TEST_URI);
|
||||
|
||||
info("Open the console");
|
||||
let hud = await openConsole();
|
||||
testMessagesVisibility(hud);
|
||||
|
||||
info("Close the toolbox");
|
||||
await closeToolbox();
|
||||
|
||||
info("Open the console again");
|
||||
hud = await openConsole();
|
||||
testMessagesVisibility(hud);
|
||||
});
|
||||
|
||||
function testMessagesVisibility(hud) {
|
||||
let message = findMessage(hud, "log Bazzle", ".message.log");
|
||||
ok(message, "console.log message is visible");
|
||||
|
||||
message = findMessage(hud, "error Bazzle", ".message.error");
|
||||
ok(message, "console.error message is visible");
|
||||
|
||||
message = findMessage(hud, "bazBug611032", ".message.error");
|
||||
ok(message, "exception message is visible");
|
||||
|
||||
message = findMessage(hud, "cssColorBug611032", ".message.warn.css");
|
||||
ok(message, "css warning message is visible");
|
||||
}
|
||||
|
|
|
@ -8,40 +8,31 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,test for bug 773466";
|
||||
const TEST_URI = "data:text/html;charset=utf8,test console.dir on uninspectable object";
|
||||
const FIRST_LOG_MESSAGE = "fooBug773466a";
|
||||
const SECOND_LOG_MESSAGE = "fooBug773466b";
|
||||
|
||||
add_task(function* () {
|
||||
yield loadTab(TEST_URI);
|
||||
add_task(async function () {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
const {jsterm} = hud;
|
||||
|
||||
let hud = yield openConsole();
|
||||
info("Logging a first message to make sure everything is working");
|
||||
let onLogMessage = waitForMessage(hud, FIRST_LOG_MESSAGE);
|
||||
jsterm.execute(`console.log("${FIRST_LOG_MESSAGE}")`);
|
||||
await onLogMessage;
|
||||
|
||||
hud.jsterm.clearOutput(true);
|
||||
info("console.dir on an uninspectable object");
|
||||
const onDirMessage = waitForMessage(hud, "Object { }");
|
||||
jsterm.execute("console.dir(Object.create(null))");
|
||||
await onDirMessage;
|
||||
|
||||
hud.jsterm.execute("console.log('fooBug773466a')");
|
||||
hud.jsterm.execute("myObj = Object.create(null)");
|
||||
hud.jsterm.execute("console.dir(myObj)");
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "fooBug773466a",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
name: "console.dir output",
|
||||
consoleDir: "[object Object]",
|
||||
}],
|
||||
info("Logging a second message to make sure the console is not broken");
|
||||
onLogMessage = waitForMessage(hud, SECOND_LOG_MESSAGE);
|
||||
// Logging from content to make sure the console API is working.
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, SECOND_LOG_MESSAGE, (string) => {
|
||||
content.console.log(string);
|
||||
});
|
||||
await onLogMessage;
|
||||
|
||||
content.console.log("fooBug773466b");
|
||||
|
||||
yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "fooBug773466b",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
ok(true, "The console.dir call on an uninspectable object did not break the console");
|
||||
});
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* globals goDoCommand */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test copying of the entire console message when right-clicked
|
||||
// with no other text selected. See Bug 1100562.
|
||||
|
||||
add_task(function* () {
|
||||
let hud;
|
||||
let outputNode;
|
||||
let contextMenu;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console.html";
|
||||
|
||||
const { tab, browser } = yield loadTab(TEST_URI);
|
||||
hud = yield openConsole(tab);
|
||||
outputNode = hud.outputNode;
|
||||
contextMenu = hud.iframeWindow.document.getElementById("output-contextmenu");
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
hud = outputNode = contextMenu = null;
|
||||
});
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
yield ContentTask.spawn(browser, {}, function* () {
|
||||
let button = content.document.getElementById("testTrace");
|
||||
button.click();
|
||||
});
|
||||
|
||||
let results = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
text: "bug 1100562",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
lines: 1,
|
||||
},
|
||||
{
|
||||
name: "console.trace output",
|
||||
consoleTrace: true,
|
||||
lines: 3,
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
outputNode.focus();
|
||||
|
||||
for (let result of results) {
|
||||
let message = [...result.matched][0];
|
||||
|
||||
yield waitForContextMenu(contextMenu, message, () => {
|
||||
let copyItem = contextMenu.querySelector("#cMenu_copy");
|
||||
copyItem.doCommand();
|
||||
|
||||
let controller = top.document.commandDispatcher
|
||||
.getControllerForCommand("cmd_copy");
|
||||
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
|
||||
});
|
||||
|
||||
let clipboardText;
|
||||
|
||||
yield waitForClipboardPromise(
|
||||
() => goDoCommand("cmd_copy"),
|
||||
(str) => {
|
||||
clipboardText = str;
|
||||
return message.textContent == clipboardText;
|
||||
}
|
||||
);
|
||||
|
||||
ok(clipboardText, "Clipboard text was found and saved");
|
||||
|
||||
let lines = clipboardText.split("\n");
|
||||
ok(lines.length > 0, "There is at least one newline in the message");
|
||||
is(lines.pop(), "", "There is a newline at the end");
|
||||
is(lines.length, result.lines, `There are ${result.lines} lines in the message`);
|
||||
|
||||
// Test the first line for "timestamp message repeat file:line"
|
||||
let firstLine = lines.shift();
|
||||
ok(/^[\d:.]+ .+ \d+ .+:\d+$/.test(firstLine),
|
||||
"The message's first line has the right format");
|
||||
|
||||
// Test the remaining lines (stack trace) for "TABfunctionName sourceURL:line:col"
|
||||
for (let line of lines) {
|
||||
ok(/^\t.+ .+:\d+:\d+$/.test(line), "The stack trace line has the right format");
|
||||
}
|
||||
}
|
||||
|
||||
yield closeConsole(tab);
|
||||
yield finishTest();
|
||||
});
|
|
@ -3,9 +3,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from ../../../../framework/test/shared-head.js */
|
||||
/* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitFor, findMessage,
|
||||
openContextMenu, hideContextMenu, loadDocument, hasFocus,
|
||||
waitForNodeMutation, testOpenInDebugger, checkClickOnNode */
|
||||
/* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitForMessage, waitFor,
|
||||
findMessage, openContextMenu, hideContextMenu, loadDocument, hasFocus,
|
||||
waitForNodeMutation, testOpenInDebugger, checkClickOnNode, jstermSetValueAndComplete,
|
||||
openDebugger, openConsole */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -69,12 +70,12 @@ async function openNewTabAndConsole(url, clearJstermHistory = true) {
|
|||
* - hud: the webconsole
|
||||
* - messages: Array[Object]. An array of messages to match.
|
||||
Current supported options:
|
||||
* - text: Exact text match in .message-body
|
||||
* - text: Partial text match in .message-body
|
||||
*/
|
||||
function waitForMessages({ hud, messages }) {
|
||||
return new Promise(resolve => {
|
||||
let numMatched = 0;
|
||||
let receivedLog = hud.ui.on("new-messages",
|
||||
const matchedMessages = [];
|
||||
hud.ui.on("new-messages",
|
||||
function messagesReceived(e, newMessages) {
|
||||
for (let message of messages) {
|
||||
if (message.matched) {
|
||||
|
@ -84,17 +85,20 @@ function waitForMessages({ hud, messages }) {
|
|||
for (let newMessage of newMessages) {
|
||||
let messageBody = newMessage.node.querySelector(".message-body");
|
||||
if (messageBody.textContent.includes(message.text)) {
|
||||
numMatched++;
|
||||
matchedMessages.push(newMessage);
|
||||
message.matched = true;
|
||||
info("Matched a message with text: " + message.text +
|
||||
", still waiting for " + (messages.length - numMatched) + " messages");
|
||||
const messagesLeft = messages.length - matchedMessages.length;
|
||||
info(`Matched a message with text: "${message.text}", ` + (messagesLeft > 0
|
||||
? `still waiting for ${messagesLeft} messages.`
|
||||
: `all messages received.`)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numMatched === messages.length) {
|
||||
if (matchedMessages.length === messages.length) {
|
||||
hud.ui.off("new-messages", messagesReceived);
|
||||
resolve(receivedLog);
|
||||
resolve(matchedMessages);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +106,17 @@ function waitForMessages({ hud, messages }) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a single message in the web console output, resolving once it is received.
|
||||
*
|
||||
* @param {Object} hud : the webconsole
|
||||
* @param {String} text : text included in .message-body
|
||||
*/
|
||||
async function waitForMessage(hud, text) {
|
||||
const messages = await waitForMessages({hud, messages: [{text}]});
|
||||
return messages[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a predicate to return a result.
|
||||
*
|
||||
|
@ -271,3 +286,81 @@ function hasFocus(node) {
|
|||
return node.ownerDocument.activeElement == node
|
||||
&& node.ownerDocument.hasFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the JsTerm and its caret position, and fire a completion request.
|
||||
*
|
||||
* @param {JsTerm} jsterm
|
||||
* @param {String} value : The value to set the jsterm to.
|
||||
* @param {Integer} caretIndexOffset : A number that will be added to value.length
|
||||
* when setting the caret. A negative number will place the caret
|
||||
* in (end - offset) position. Default to 0 (caret set at the end)
|
||||
* @returns {Promise} resolves when the jsterm is completed.
|
||||
*/
|
||||
function jstermSetValueAndComplete(jsterm, value, caretIndexOffset = 0) {
|
||||
const {inputNode} = jsterm;
|
||||
inputNode.value = value;
|
||||
let index = value.length + caretIndexOffset;
|
||||
inputNode.setSelectionRange(index, index);
|
||||
|
||||
const updated = jsterm.once("autocomplete-updated");
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the JavaScript debugger.
|
||||
*
|
||||
* @param object options
|
||||
* Options for opening the debugger:
|
||||
* - tab: the tab you want to open the debugger for.
|
||||
* @return object
|
||||
* A promise that is resolved once the debugger opens, or rejected if
|
||||
* the open fails. The resolution callback is given one argument, an
|
||||
* object that holds the following properties:
|
||||
* - target: the Target object for the Tab.
|
||||
* - toolbox: the Toolbox instance.
|
||||
* - panel: the jsdebugger panel instance.
|
||||
*/
|
||||
async function openDebugger(options = {}) {
|
||||
if (!options.tab) {
|
||||
options.tab = gBrowser.selectedTab;
|
||||
}
|
||||
|
||||
let target = TargetFactory.forTab(options.tab);
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
let dbgPanelAlreadyOpen = toolbox && toolbox.getPanel("jsdebugger");
|
||||
if (dbgPanelAlreadyOpen) {
|
||||
await toolbox.selectTool("jsdebugger");
|
||||
|
||||
return {
|
||||
target,
|
||||
toolbox,
|
||||
panel: toolbox.getCurrentPanel()
|
||||
};
|
||||
}
|
||||
|
||||
toolbox = await gDevTools.showToolbox(target, "jsdebugger");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
// Do not clear VariableView lazily so it doesn't disturb test ending.
|
||||
panel._view.Variables.lazyEmpty = false;
|
||||
|
||||
await panel.panelWin.DebuggerController.waitForSourcesLoaded();
|
||||
return {target, toolbox, panel};
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Web Console for the given tab, or the current one if none given.
|
||||
*
|
||||
* @param nsIDOMElement tab
|
||||
* Optional tab element for which you want open the Web Console.
|
||||
* Defaults to current selected tab.
|
||||
* @return Promise
|
||||
* A promise that is resolved with the console hud once the web console is open.
|
||||
*/
|
||||
async function openConsole(tab) {
|
||||
let target = TargetFactory.forTab(tab || gBrowser.selectedTab);
|
||||
const toolbox = await gDevTools.showToolbox(target, "webconsole");
|
||||
return toolbox.getCurrentPanel().hud;
|
||||
};
|
||||
|
|
|
@ -10,35 +10,33 @@
|
|||
<script>
|
||||
var foo1 = "globalFoo";
|
||||
|
||||
var foo1Obj = {
|
||||
var foo1Obj = Object.assign(Object.create(null), {
|
||||
prop1: "111",
|
||||
prop2: {
|
||||
prop21: "212121"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
function firstCall()
|
||||
{
|
||||
function firstCall() {
|
||||
var foo2 = "fooFirstCall";
|
||||
|
||||
var foo2Obj = {
|
||||
prop1: {
|
||||
var foo2Obj = Object.assign(Object.create(null), {
|
||||
prop1: Object.assign(Object.create(null), {
|
||||
prop11: "111111"
|
||||
}
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
secondCall();
|
||||
}
|
||||
|
||||
function secondCall()
|
||||
{
|
||||
function secondCall() {
|
||||
var foo3 = "fooSecondCall";
|
||||
|
||||
var foo3Obj = {
|
||||
prop1: {
|
||||
var foo3Obj = Object.assign(Object.create(null), {
|
||||
prop1: Object.assign(Object.create(null), {
|
||||
prop11: "313131"
|
||||
}
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
debugger;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>test for bug 989025 - iframe child</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>test for bug 989025 - iframe child</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,13 +1,13 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>test for bug 989025 - iframe parent</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>test for bug 989025 - iframe parent</p>
|
||||
<iframe src="http://mochi.test:8888/browser/devtools/client/webconsole/test/test-bug-609872-cd-iframe-child.html"></iframe>
|
||||
<iframe src="http://mochi.test:8888/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-iframe-child.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -203,6 +203,11 @@ public:
|
|||
return mOffset.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set() sets a point to aOffset or aChild.
|
||||
* If it's set with offset, mRef is invalidated. If it's set with aChild,
|
||||
* mOffset may be invalidated unless the offset can be computed simply.
|
||||
*/
|
||||
void
|
||||
Set(nsINode* aContainer, int32_t aOffset)
|
||||
{
|
||||
|
@ -210,6 +215,29 @@ public:
|
|||
mRef = nullptr;
|
||||
mOffset = mozilla::Some(aOffset);
|
||||
}
|
||||
void
|
||||
Set(const nsIContent* aChild)
|
||||
{
|
||||
MOZ_ASSERT(aChild);
|
||||
mParent = aChild->GetParentNode();
|
||||
mRef = aChild->GetPreviousSibling();
|
||||
if (!mRef) {
|
||||
mOffset = mozilla::Some(0);
|
||||
} else {
|
||||
mOffset.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear() makes the instance not point anywhere.
|
||||
*/
|
||||
void
|
||||
Clear()
|
||||
{
|
||||
mParent = nullptr;
|
||||
mRef = nullptr;
|
||||
mOffset.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* AdvanceOffset() tries to reference next sibling of mRef if its container
|
||||
|
|
|
@ -51,6 +51,7 @@ TextTrackRegion::TextTrackRegion(nsISupports* aGlobal)
|
|||
void
|
||||
TextTrackRegion::CopyValues(TextTrackRegion& aRegion)
|
||||
{
|
||||
mId = aRegion.Id();
|
||||
mWidth = aRegion.Width();
|
||||
mLines = aRegion.Lines();
|
||||
mRegionAnchorX = aRegion.RegionAnchorX();
|
||||
|
|
|
@ -127,6 +127,16 @@ public:
|
|||
mScroll = aScroll;
|
||||
}
|
||||
|
||||
void GetId(nsAString& aId) const
|
||||
{
|
||||
aId = mId;
|
||||
}
|
||||
|
||||
void SetId(const nsAString& aId)
|
||||
{
|
||||
mId = aId;
|
||||
}
|
||||
|
||||
/** end WebIDL Methods. */
|
||||
|
||||
|
||||
|
@ -139,11 +149,16 @@ public:
|
|||
{
|
||||
return mScroll;
|
||||
}
|
||||
const nsAString& Id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
private:
|
||||
~TextTrackRegion() {}
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
nsString mId;
|
||||
double mWidth;
|
||||
long mLines;
|
||||
double mRegionAnchorX;
|
||||
|
|
|
@ -120,11 +120,12 @@ H264Converter::Decode(MediaRawData* aSample)
|
|||
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
|
||||
}
|
||||
|
||||
if (!*mNeedAVCC &&
|
||||
mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe).isErr()) {
|
||||
auto res = !*mNeedAVCC
|
||||
? mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)
|
||||
: Ok();
|
||||
if (res.isErr()) {
|
||||
return DecodePromise::CreateAndReject(
|
||||
MediaResult(NS_ERROR_OUT_OF_MEMORY,
|
||||
RESULT_DETAIL("ConvertSampleToAnnexB")),
|
||||
MediaResult(res.unwrapErr(), RESULT_DETAIL("ConvertSampleToAnnexB")),
|
||||
__func__);
|
||||
}
|
||||
|
||||
|
@ -374,11 +375,13 @@ H264Converter::DecodeFirstSample(MediaRawData* aSample)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!*mNeedAVCC &&
|
||||
mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe).isErr()) {
|
||||
mDecodePromise.Reject(MediaResult(NS_ERROR_OUT_OF_MEMORY,
|
||||
RESULT_DETAIL("ConvertSampleToAnnexB")),
|
||||
__func__);
|
||||
auto res = !*mNeedAVCC
|
||||
? mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)
|
||||
: Ok();
|
||||
if (res.isErr()) {
|
||||
mDecodePromise.Reject(
|
||||
MediaResult(res.unwrapErr(), RESULT_DETAIL("ConvertSampleToAnnexB")),
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,14 +113,11 @@
|
|||
Promise.all(test.track.fragments.map(fragment => DownloadMedia(fragment, test.track.type, ms)))
|
||||
.then(() => {
|
||||
ms.endOfStream();
|
||||
LoadEME();
|
||||
})
|
||||
.then(() => {
|
||||
video.play();
|
||||
});
|
||||
});
|
||||
|
||||
video.addEventListener("ended", SimpleTest.finish);
|
||||
once(video, "ended", SimpleTest.finish);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1116,6 +1116,7 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
|||
if (settings.has("id")) {
|
||||
try {
|
||||
var region = new self.window.VTTRegion();
|
||||
region.id = settings.get("id", "");
|
||||
region.width = settings.get("width", 100);
|
||||
region.lines = settings.get("lines", 3);
|
||||
region.regionAnchorX = settings.get("regionanchorX", 0);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
[Constructor, Pref="media.webvtt.regions.enabled"]
|
||||
interface VTTRegion {
|
||||
attribute DOMString id;
|
||||
[SetterThrows]
|
||||
attribute double width;
|
||||
|
||||
|
|
|
@ -3969,7 +3969,7 @@ EditorBase::SplitNodeDeep(nsIContent& aNode,
|
|||
nsCOMPtr<nsIContent>* ioChildAtSplitPointOffset)
|
||||
{
|
||||
MOZ_ASSERT(&aSplitPointParent == &aNode ||
|
||||
EditorUtils::IsDescendantOf(&aSplitPointParent, &aNode));
|
||||
EditorUtils::IsDescendantOf(aSplitPointParent, aNode));
|
||||
int32_t offset = aSplitPointOffset;
|
||||
|
||||
nsCOMPtr<nsIContent> leftNode, rightNode;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "mozilla/EditorUtils.h"
|
||||
|
||||
#include "mozilla/EditorDOMPoint.h"
|
||||
#include "mozilla/OwningNonNull.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
@ -135,19 +136,23 @@ DOMSubtreeIterator::~DOMSubtreeIterator()
|
|||
*****************************************************************************/
|
||||
|
||||
bool
|
||||
EditorUtils::IsDescendantOf(nsINode* aNode,
|
||||
nsINode* aParent,
|
||||
int32_t* aOffset)
|
||||
EditorUtils::IsDescendantOf(const nsINode& aNode,
|
||||
const nsINode& aParent,
|
||||
EditorRawDOMPoint* aOutPoint /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(aNode && aParent);
|
||||
if (aNode == aParent) {
|
||||
if (aOutPoint) {
|
||||
aOutPoint->Clear();
|
||||
}
|
||||
|
||||
if (&aNode == &aParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
|
||||
if (node->GetParentNode() == aParent) {
|
||||
if (aOffset) {
|
||||
*aOffset = aParent->IndexOf(node);
|
||||
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
|
||||
if (node->GetParentNode() == &aParent) {
|
||||
if (aOutPoint) {
|
||||
MOZ_ASSERT(node->IsContent());
|
||||
aOutPoint->Set(node->AsContent());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -157,19 +162,20 @@ EditorUtils::IsDescendantOf(nsINode* aNode,
|
|||
}
|
||||
|
||||
bool
|
||||
EditorUtils::IsDescendantOf(nsINode* aNode,
|
||||
nsINode* aParent,
|
||||
nsIContent** aChild)
|
||||
EditorUtils::IsDescendantOf(const nsINode& aNode,
|
||||
const nsINode& aParent,
|
||||
EditorDOMPoint* aOutPoint)
|
||||
{
|
||||
MOZ_ASSERT(aNode && aParent && aChild);
|
||||
*aChild = nullptr;
|
||||
if (aNode == aParent) {
|
||||
MOZ_ASSERT(aOutPoint);
|
||||
aOutPoint->Clear();
|
||||
if (&aNode == &aParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
|
||||
if (node->GetParentNode() == aParent) {
|
||||
*aChild = node->AsContent();
|
||||
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
|
||||
if (node->GetParentNode() == &aParent) {
|
||||
MOZ_ASSERT(node->IsContent());
|
||||
aOutPoint->Set(node->AsContent());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -177,17 +183,6 @@ EditorUtils::IsDescendantOf(nsINode* aNode,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EditorUtils::IsDescendantOf(nsIDOMNode* aNode,
|
||||
nsIDOMNode* aParent,
|
||||
int32_t* aOffset)
|
||||
{
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
|
||||
NS_ENSURE_TRUE(node && parent, false);
|
||||
return IsDescendantOf(node, parent, aOffset);
|
||||
}
|
||||
|
||||
bool
|
||||
EditorUtils::IsLeafNode(nsIDOMNode* aNode)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/EditorBase.h"
|
||||
#include "mozilla/EditorDOMPoint.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -378,13 +379,19 @@ public:
|
|||
class EditorUtils final
|
||||
{
|
||||
public:
|
||||
// Note that aChild isn't a normal XPCOM outparam and won't get AddRef'ed.
|
||||
static bool IsDescendantOf(nsINode* aNode, nsINode* aParent,
|
||||
nsIContent** aChild);
|
||||
static bool IsDescendantOf(nsINode* aNode, nsINode* aParent,
|
||||
int32_t* aOffset = nullptr);
|
||||
static bool IsDescendantOf(nsIDOMNode* aNode, nsIDOMNode* aParent,
|
||||
int32_t* aOffset = nullptr);
|
||||
/**
|
||||
* IsDescendantOf() checks if aNode is a child or a descendant of aParent.
|
||||
* aOutPoint is set to the child of aParent.
|
||||
*
|
||||
* @return true if aNode is a child or a descendant of aParent.
|
||||
*/
|
||||
static bool IsDescendantOf(const nsINode& aNode,
|
||||
const nsINode& aParent,
|
||||
EditorRawDOMPoint* aOutPoint = nullptr);
|
||||
static bool IsDescendantOf(const nsINode& aNode,
|
||||
const nsINode& aParent,
|
||||
EditorDOMPoint* aOutPoint);
|
||||
|
||||
static bool IsLeafNode(nsIDOMNode* aNode);
|
||||
};
|
||||
|
||||
|
|
|
@ -2858,19 +2858,20 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
// different lists, join the lists instead.
|
||||
bool mergeLists = false;
|
||||
nsAtom* existingList = nsGkAtoms::_empty;
|
||||
nsIContent* childInBlock = nullptr;
|
||||
EditorDOMPoint childInBlock;
|
||||
nsCOMPtr<Element> leftList, rightList;
|
||||
if (HTMLEditUtils::IsListItem(leftBlock) &&
|
||||
HTMLEditUtils::IsListItem(rightBlock)) {
|
||||
leftList = leftBlock->GetParentElement();
|
||||
rightList = rightBlock->GetParentElement();
|
||||
if (leftList && rightList && leftList != rightList &&
|
||||
!EditorUtils::IsDescendantOf(leftList, rightBlock, &childInBlock) &&
|
||||
!EditorUtils::IsDescendantOf(rightList, leftBlock, &childInBlock)) {
|
||||
!EditorUtils::IsDescendantOf(*leftList, *rightBlock, &childInBlock) &&
|
||||
!EditorUtils::IsDescendantOf(*rightList, *leftBlock, &childInBlock)) {
|
||||
// There are some special complications if the lists are descendants of
|
||||
// the other lists' items. Note that it is okay for them to be
|
||||
// descendants of the other lists themselves, which is the usual case for
|
||||
// sublists in our implementation.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!childInBlock.IsSet());
|
||||
leftBlock = leftList;
|
||||
rightBlock = rightList;
|
||||
mergeLists = true;
|
||||
|
@ -2880,15 +2881,13 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
|
||||
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
|
||||
|
||||
int32_t rightOffset = 0;
|
||||
int32_t leftOffset = -1;
|
||||
|
||||
// offset below is where you find yourself in rightBlock when you traverse
|
||||
// upwards from leftBlock
|
||||
if (EditorUtils::IsDescendantOf(leftBlock, rightBlock, &rightOffset)) {
|
||||
EditorDOMPoint rightBlockChild;
|
||||
if (EditorUtils::IsDescendantOf(*leftBlock, *rightBlock, &rightBlockChild)) {
|
||||
// Tricky case. Left block is inside right block. Do ws adjustment. This
|
||||
// just destroys non-visible ws at boundaries we will be joining.
|
||||
rightOffset++;
|
||||
rightBlockChild.AdvanceOffset();
|
||||
nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
|
||||
WSRunObject::kBlockEnd,
|
||||
leftBlock);
|
||||
|
@ -2898,23 +2897,25 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
|
||||
{
|
||||
// We can't just track rightBlock because it's an Element.
|
||||
nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
|
||||
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
|
||||
address_of(trackingRightBlock), &rightOffset);
|
||||
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &rightBlockChild);
|
||||
rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
|
||||
WSRunObject::kAfterBlock,
|
||||
rightBlock, rightOffset);
|
||||
rightBlock,
|
||||
rightBlockChild.Offset());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditActionIgnored(rv);
|
||||
}
|
||||
|
||||
if (trackingRightBlock->IsElement()) {
|
||||
rightBlock = trackingRightBlock->AsElement();
|
||||
// XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
|
||||
// Do we really need to do update rightBlock here??
|
||||
MOZ_ASSERT(rightBlock == rightBlockChild.Container());
|
||||
if (rightBlockChild.Container()->IsElement()) {
|
||||
rightBlock = rightBlockChild.Container()->AsElement();
|
||||
} else {
|
||||
if (NS_WARN_IF(!trackingRightBlock->GetParentElement())) {
|
||||
if (NS_WARN_IF(!rightBlockChild.Container()->GetParentElement())) {
|
||||
return EditActionIgnored(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
rightBlock = trackingRightBlock->GetParentElement();
|
||||
rightBlock = rightBlockChild.Container()->GetParentElement();
|
||||
}
|
||||
}
|
||||
// Do br adjustment.
|
||||
|
@ -2924,8 +2925,12 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
if (mergeLists) {
|
||||
// The idea here is to take all children in rightList that are past
|
||||
// offset, and pull them into leftlist.
|
||||
for (nsCOMPtr<nsIContent> child = childInBlock;
|
||||
child; child = rightList->GetChildAt(rightOffset)) {
|
||||
// XXX Looks like that when mergeLists is true, childInBlock has never
|
||||
// been set. So, this block must be dead code.
|
||||
MOZ_DIAGNOSTIC_ASSERT(childInBlock.IsSet());
|
||||
uint32_t offset = rightBlockChild.Offset();
|
||||
for (nsCOMPtr<nsIContent> child = childInBlock.GetChildAtOffset();
|
||||
child; child = rightList->GetChildAt(offset)) {
|
||||
rv = htmlEditor->MoveNode(child, leftList, -1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditActionIgnored(rv);
|
||||
|
@ -2933,13 +2938,21 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
}
|
||||
// XXX Should this set to true only when above for loop moves the node?
|
||||
ret.MarkAsHandled();
|
||||
// childInBlock and rightBlockChild were moved to leftList. So, they
|
||||
// are now invalid.
|
||||
rightBlockChild.Clear();
|
||||
childInBlock.Clear();
|
||||
} else {
|
||||
// XXX Why do we ignore the result of MoveBlock()?
|
||||
EditActionResult retMoveBlock =
|
||||
MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
|
||||
MoveBlock(*leftBlock, *rightBlock,
|
||||
-1, rightBlockChild.Offset());
|
||||
if (retMoveBlock.Handled()) {
|
||||
ret.MarkAsHandled();
|
||||
}
|
||||
// Now, all children of rightBlock were moved to leftBlock. So,
|
||||
// rightBlockChild is now invalid.
|
||||
rightBlockChild.Clear();
|
||||
}
|
||||
if (brNode && NS_SUCCEEDED(htmlEditor->DeleteNode(brNode))) {
|
||||
ret.MarkAsHandled();
|
||||
|
@ -2947,9 +2960,12 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!rightBlockChild.IsSet());
|
||||
|
||||
// Offset below is where you find yourself in leftBlock when you traverse
|
||||
// upwards from rightBlock
|
||||
if (EditorUtils::IsDescendantOf(rightBlock, leftBlock, &leftOffset)) {
|
||||
EditorDOMPoint leftBlockChild;
|
||||
if (EditorUtils::IsDescendantOf(*rightBlock, *leftBlock, &leftBlockChild)) {
|
||||
// Tricky case. Right block is inside left block. Do ws adjustment. This
|
||||
// just destroys non-visible ws at boundaries we will be joining.
|
||||
nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
|
||||
|
@ -2962,50 +2978,51 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
{
|
||||
// We can't just track leftBlock because it's an Element, so track
|
||||
// something else.
|
||||
nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
|
||||
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
|
||||
address_of(trackingLeftBlock), &leftOffset);
|
||||
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &leftBlockChild);
|
||||
rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
|
||||
WSRunObject::kBeforeBlock,
|
||||
leftBlock, leftOffset);
|
||||
leftBlock, leftBlockChild.Offset());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditActionIgnored(rv);
|
||||
}
|
||||
|
||||
if (trackingLeftBlock->IsElement()) {
|
||||
leftBlock = trackingLeftBlock->AsElement();
|
||||
// XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
|
||||
// Do we really need to do update rightBlock here??
|
||||
MOZ_DIAGNOSTIC_ASSERT(leftBlock == leftBlockChild.Container());
|
||||
if (leftBlockChild.Container()->IsElement()) {
|
||||
leftBlock = leftBlockChild.Container()->AsElement();
|
||||
} else {
|
||||
if (NS_WARN_IF(!trackingLeftBlock->GetParentElement())) {
|
||||
if (NS_WARN_IF(!leftBlockChild.Container()->GetParentElement())) {
|
||||
return EditActionIgnored(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
leftBlock = trackingLeftBlock->GetParentElement();
|
||||
leftBlock = leftBlockChild.Container()->GetParentElement();
|
||||
}
|
||||
}
|
||||
// Do br adjustment.
|
||||
nsCOMPtr<Element> brNode =
|
||||
CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock, leftOffset);
|
||||
CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock,
|
||||
leftBlockChild.Offset());
|
||||
EditActionResult ret(NS_OK);
|
||||
if (mergeLists) {
|
||||
// XXX Why do we ignore the result of MoveContents()?
|
||||
int32_t offset = leftBlockChild.Offset();
|
||||
EditActionResult retMoveContents =
|
||||
MoveContents(*rightList, *leftList, &leftOffset);
|
||||
MoveContents(*rightList, *leftList, &offset);
|
||||
if (retMoveContents.Handled()) {
|
||||
ret.MarkAsHandled();
|
||||
}
|
||||
// leftBlockChild was moved to rightList. So, it's invalid now.
|
||||
leftBlockChild.Clear();
|
||||
} else {
|
||||
// Left block is a parent of right block, and the parent of the previous
|
||||
// visible content. Right block is a child and contains the contents we
|
||||
// want to move.
|
||||
|
||||
int32_t previousContentOffset;
|
||||
nsCOMPtr<nsINode> previousContentParent;
|
||||
|
||||
EditorDOMPoint previousContent;
|
||||
if (&aLeftNode == leftBlock) {
|
||||
// We are working with valid HTML, aLeftNode is a block node, and is
|
||||
// therefore allowed to contain rightBlock. This is the simple case,
|
||||
// we will simply move the content in rightBlock out of its block.
|
||||
previousContentParent = leftBlock;
|
||||
previousContentOffset = leftOffset;
|
||||
previousContent = leftBlockChild;
|
||||
} else {
|
||||
// We try to work as well as possible with HTML that's already invalid.
|
||||
// Although "right block" is a block, and a block must not be contained
|
||||
|
@ -3016,13 +3033,10 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
// However, in some situations this strategy moves the content to an
|
||||
// unexpected position. (see bug 200416) The new idea is to make the
|
||||
// moving content a sibling, next to the previous visible content.
|
||||
|
||||
previousContentParent = aLeftNode.GetParentNode();
|
||||
previousContentOffset = previousContentParent ?
|
||||
previousContentParent->IndexOf(&aLeftNode) : -1;
|
||||
previousContent.Set(&aLeftNode);
|
||||
|
||||
// We want to move our content just after the previous visible node.
|
||||
previousContentOffset++;
|
||||
previousContent.AdvanceOffset();
|
||||
}
|
||||
|
||||
// Because we don't want the moving content to receive the style of the
|
||||
|
@ -3031,6 +3045,8 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
nsCOMPtr<Element> editorRoot = htmlEditor->GetEditorRoot();
|
||||
if (!editorRoot || &aLeftNode != editorRoot) {
|
||||
nsCOMPtr<nsIContent> splittedPreviousContent;
|
||||
nsCOMPtr<nsINode> previousContentParent = previousContent.Container();
|
||||
int32_t previousContentOffset = previousContent.Offset();
|
||||
rv = htmlEditor->SplitStyleAbovePoint(
|
||||
address_of(previousContentParent),
|
||||
&previousContentOffset,
|
||||
|
@ -3041,18 +3057,18 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
}
|
||||
|
||||
if (splittedPreviousContent) {
|
||||
previousContentParent = splittedPreviousContent->GetParentNode();
|
||||
previousContentOffset = previousContentParent ?
|
||||
previousContentParent->IndexOf(splittedPreviousContent) : -1;
|
||||
previousContent.Set(splittedPreviousContent);
|
||||
} else {
|
||||
previousContent.Set(previousContentParent, previousContentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!previousContentParent)) {
|
||||
if (NS_WARN_IF(!previousContent.IsSet())) {
|
||||
return EditActionIgnored(NS_ERROR_NULL_POINTER);
|
||||
}
|
||||
|
||||
ret |= MoveBlock(*previousContentParent->AsElement(), *rightBlock,
|
||||
previousContentOffset, rightOffset);
|
||||
ret |= MoveBlock(*previousContent.Container()->AsElement(), *rightBlock,
|
||||
previousContent.Offset(), 0);
|
||||
if (NS_WARN_IF(ret.Failed())) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -3063,6 +3079,9 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!rightBlockChild.IsSet());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!leftBlockChild.IsSet());
|
||||
|
||||
// Normal case. Blocks are siblings, or at least close enough. An example
|
||||
// of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>. The
|
||||
// first li and the p are not true siblings, but we still want to join them
|
||||
|
@ -3089,7 +3108,7 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
|
|||
ret.MarkAsHandled();
|
||||
} else {
|
||||
// Nodes are dissimilar types.
|
||||
ret |= MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
|
||||
ret |= MoveBlock(*leftBlock, *rightBlock, -1, 0);
|
||||
if (NS_WARN_IF(ret.Failed())) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -3438,7 +3457,7 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
|
|||
|
||||
if (HTMLEditUtils::IsList(curNode)) {
|
||||
// do we have a curList already?
|
||||
if (curList && !EditorUtils::IsDescendantOf(curNode, curList)) {
|
||||
if (curList && !EditorUtils::IsDescendantOf(*curNode, *curList)) {
|
||||
// move all of our children into curList. cheezy way to do it: move
|
||||
// whole list and then RemoveContainer() on the list. ConvertListType
|
||||
// first: that routine handles converting the list item types, if
|
||||
|
@ -3469,7 +3488,7 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
|
|||
if (!curParent->IsHTMLElement(listType)) {
|
||||
// list item is in wrong type of list. if we don't have a curList,
|
||||
// split the old list and make a new list of correct type.
|
||||
if (!curList || EditorUtils::IsDescendantOf(curNode, curList)) {
|
||||
if (!curList || EditorUtils::IsDescendantOf(*curNode, *curList)) {
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
NS_ENSURE_STATE(curParent->IsContent());
|
||||
ErrorResult rv;
|
||||
|
@ -4405,7 +4424,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
|
|||
// Do we have a blockquote that we are already committed to removing?
|
||||
if (curBlockQuote) {
|
||||
// If so, is this node a descendant?
|
||||
if (EditorUtils::IsDescendantOf(curNode, curBlockQuote)) {
|
||||
if (EditorUtils::IsDescendantOf(*curNode, *curBlockQuote)) {
|
||||
lastBQChild = curNode;
|
||||
// Then we don't need to do anything different for this node
|
||||
continue;
|
||||
|
@ -4532,7 +4551,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
|
|||
int32_t startOffset = aSelection.GetRangeAt(0)->StartOffset();
|
||||
if (rememberedLeftBQ &&
|
||||
(startNode == rememberedLeftBQ ||
|
||||
EditorUtils::IsDescendantOf(startNode, rememberedLeftBQ))) {
|
||||
EditorUtils::IsDescendantOf(*startNode, *rememberedLeftBQ))) {
|
||||
// Selection is inside rememberedLeftBQ - push it past it.
|
||||
startNode = rememberedLeftBQ->GetParentNode();
|
||||
startOffset = startNode ? 1 + startNode->IndexOf(rememberedLeftBQ) : 0;
|
||||
|
@ -4543,7 +4562,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
|
|||
startOffset = aSelection.GetRangeAt(0)->StartOffset();
|
||||
if (rememberedRightBQ &&
|
||||
(startNode == rememberedRightBQ ||
|
||||
EditorUtils::IsDescendantOf(startNode, rememberedRightBQ))) {
|
||||
EditorUtils::IsDescendantOf(*startNode, *rememberedRightBQ))) {
|
||||
// Selection is inside rememberedRightBQ - push it before it.
|
||||
startNode = rememberedRightBQ->GetParentNode();
|
||||
startOffset = startNode ? startNode->IndexOf(rememberedRightBQ) : -1;
|
||||
|
@ -4584,8 +4603,8 @@ HTMLEditRules::SplitBlock(Element& aBlock,
|
|||
nsIContent** aOutMiddleNode)
|
||||
{
|
||||
// aStartChild and aEndChild must be exclusive descendants of aBlock
|
||||
MOZ_ASSERT(EditorUtils::IsDescendantOf(&aStartChild, &aBlock) &&
|
||||
EditorUtils::IsDescendantOf(&aEndChild, &aBlock));
|
||||
MOZ_ASSERT(EditorUtils::IsDescendantOf(aStartChild, aBlock) &&
|
||||
EditorUtils::IsDescendantOf(aEndChild, aBlock));
|
||||
NS_ENSURE_TRUE_VOID(mHTMLEditor);
|
||||
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
||||
|
||||
|
@ -6396,7 +6415,7 @@ HTMLEditRules::GetHighestInlineParent(nsINode& aNode)
|
|||
// such elements for now.
|
||||
// XXX This should be MOZ_ASSERT after fixing bug 1413131 for avoiding
|
||||
// calling this expensive method.
|
||||
if (NS_WARN_IF(!EditorUtils::IsDescendantOf(&aNode, host))) {
|
||||
if (NS_WARN_IF(!EditorUtils::IsDescendantOf(aNode, *host))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -7088,7 +7107,7 @@ HTMLEditRules::RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
|
|||
} else if (IsInlineNode(curNode)) {
|
||||
if (curBlock) {
|
||||
// If so, is this node a descendant?
|
||||
if (EditorUtils::IsDescendantOf(curNode, curBlock)) {
|
||||
if (EditorUtils::IsDescendantOf(*curNode, *curBlock)) {
|
||||
// Then we don't need to do anything different for this node
|
||||
lastNode = curNode->AsContent();
|
||||
continue;
|
||||
|
@ -8160,7 +8179,7 @@ HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
|
|||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
if (EditorUtils::IsDescendantOf(startContainer, aNode)) {
|
||||
if (EditorUtils::IsDescendantOf(*startContainer, *aNode)) {
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -8174,7 +8193,7 @@ HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
|
|||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
if (EditorUtils::IsDescendantOf(endContainer, aNode)) {
|
||||
if (EditorUtils::IsDescendantOf(*endContainer, *aNode)) {
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -758,7 +758,7 @@ HTMLEditor::GetBlockNodeParent(nsINode* aNode,
|
|||
MOZ_ASSERT(aNode);
|
||||
MOZ_ASSERT(!aAncestorLimiter ||
|
||||
aNode == aAncestorLimiter ||
|
||||
EditorUtils::IsDescendantOf(aNode, aAncestorLimiter),
|
||||
EditorUtils::IsDescendantOf(*aNode, *aAncestorLimiter),
|
||||
"aNode isn't in aAncestorLimiter");
|
||||
|
||||
// The caller has already reached the limiter.
|
||||
|
@ -791,7 +791,7 @@ HTMLEditor::GetBlock(nsINode& aNode,
|
|||
{
|
||||
MOZ_ASSERT(!aAncestorLimiter ||
|
||||
&aNode == aAncestorLimiter ||
|
||||
EditorUtils::IsDescendantOf(&aNode, aAncestorLimiter),
|
||||
EditorUtils::IsDescendantOf(aNode, *aAncestorLimiter),
|
||||
"aNode isn't in aAncestorLimiter");
|
||||
|
||||
if (NodeIsBlockStatic(&aNode)) {
|
||||
|
|
|
@ -442,7 +442,11 @@ HTMLEditor::DoInsertHTMLWithContext(const nsAString& aInputString,
|
|||
if (insertedContextParent) {
|
||||
// if we had to insert something higher up in the paste hierarchy, we want to
|
||||
// skip any further paste nodes that descend from that. Else we will paste twice.
|
||||
if (EditorUtils::IsDescendantOf(curNode, insertedContextParent)) {
|
||||
nsCOMPtr<nsINode> insertedContextParentNode =
|
||||
do_QueryInterface(insertedContextParent);
|
||||
if (NS_WARN_IF(!insertedContextParentNode) ||
|
||||
EditorUtils::IsDescendantOf(*nodeList[j],
|
||||
*insertedContextParentNode)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -2380,7 +2384,7 @@ HTMLEditor::ReplaceOrphanedStructure(
|
|||
(i - removedCount) : (originalLength - i - 1);
|
||||
OwningNonNull<nsINode> endpoint = aNodeArray[idx];
|
||||
if (endpoint == replaceNode ||
|
||||
EditorUtils::IsDescendantOf(endpoint, replaceNode)) {
|
||||
EditorUtils::IsDescendantOf(*endpoint, *replaceNode)) {
|
||||
aNodeArray.RemoveElementAt(idx);
|
||||
removedCount++;
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@ RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
|
|||
|
||||
// check for range endpoints that are in descendants of aNode
|
||||
nsCOMPtr<nsINode> oldStart;
|
||||
if (EditorUtils::IsDescendantOf(item->mStartContainer, aNode)) {
|
||||
if (EditorUtils::IsDescendantOf(*item->mStartContainer, *aNode)) {
|
||||
oldStart = item->mStartContainer; // save for efficiency hack below.
|
||||
item->mStartContainer = parent;
|
||||
item->mStartOffset = offset;
|
||||
|
@ -295,7 +295,7 @@ RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
|
|||
|
||||
// avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
|
||||
if (item->mEndContainer == oldStart ||
|
||||
EditorUtils::IsDescendantOf(item->mEndContainer, aNode)) {
|
||||
EditorUtils::IsDescendantOf(*item->mEndContainer, *aNode)) {
|
||||
item->mEndContainer = parent;
|
||||
item->mEndOffset = offset;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef mozilla_SelectionState_h
|
||||
#define mozilla_SelectionState_h
|
||||
|
||||
#include "mozilla/EditorDOMPoint.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsINode.h"
|
||||
|
@ -180,6 +181,7 @@ private:
|
|||
nsCOMPtr<nsINode>* mNode;
|
||||
nsCOMPtr<nsIDOMNode>* mDOMNode;
|
||||
int32_t* mOffset;
|
||||
EditorDOMPoint* mPoint;
|
||||
RefPtr<RangeItem> mRangeItem;
|
||||
|
||||
public:
|
||||
|
@ -189,6 +191,7 @@ public:
|
|||
, mNode(aNode)
|
||||
, mDOMNode(nullptr)
|
||||
, mOffset(aOffset)
|
||||
, mPoint(nullptr)
|
||||
{
|
||||
mRangeItem = new RangeItem();
|
||||
mRangeItem->mStartContainer = *mNode;
|
||||
|
@ -204,6 +207,7 @@ public:
|
|||
, mNode(nullptr)
|
||||
, mDOMNode(aNode)
|
||||
, mOffset(aOffset)
|
||||
, mPoint(nullptr)
|
||||
{
|
||||
mRangeItem = new RangeItem();
|
||||
mRangeItem->mStartContainer = do_QueryInterface(*mDOMNode);
|
||||
|
@ -213,9 +217,29 @@ public:
|
|||
mRangeUpdater.RegisterRangeItem(mRangeItem);
|
||||
}
|
||||
|
||||
AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
|
||||
EditorDOMPoint* aPoint)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mNode(nullptr)
|
||||
, mDOMNode(nullptr)
|
||||
, mOffset(nullptr)
|
||||
, mPoint(aPoint)
|
||||
{
|
||||
mRangeItem = new RangeItem();
|
||||
mRangeItem->mStartContainer = mPoint->Container();
|
||||
mRangeItem->mEndContainer = mPoint->Container();
|
||||
mRangeItem->mStartOffset = mPoint->Offset();
|
||||
mRangeItem->mEndOffset = mPoint->Offset();
|
||||
mRangeUpdater.RegisterRangeItem(mRangeItem);
|
||||
}
|
||||
|
||||
~AutoTrackDOMPoint()
|
||||
{
|
||||
mRangeUpdater.DropRangeItem(mRangeItem);
|
||||
if (mPoint) {
|
||||
mPoint->Set(mRangeItem->mStartContainer, mRangeItem->mStartOffset);
|
||||
return;
|
||||
}
|
||||
if (mNode) {
|
||||
*mNode = mRangeItem->mStartContainer;
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="autocomplete.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.textbox-input {
|
||||
border-style: none;
|
||||
}
|
|
@ -1,29 +1,18 @@
|
|||
@namespace url('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul');
|
||||
@namespace html url('http://www.w3.org/1999/xhtml');
|
||||
|
||||
:root > html|input,
|
||||
:root > html|textarea {
|
||||
margin: 2px 4px;
|
||||
padding: 2px 2px 3px;
|
||||
padding-inline-start: 5px;
|
||||
}
|
||||
|
||||
#mac html|input, #mac html|textarea {
|
||||
margin: 4px;
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
#win html|input, #win html|textarea {
|
||||
margin: 2px 4px;
|
||||
padding: 2px 3px 3px;
|
||||
padding-inline-start: 5px;
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) {
|
||||
#win html|input {
|
||||
padding: 1px 2px 2px;
|
||||
padding-inline-start: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
#linux html|input, #linux html|textarea {
|
||||
margin: 2px 4px;
|
||||
padding: 2px 5px 3px;
|
||||
}
|
||||
|
||||
textbox[multiline="true"], html|textarea {
|
||||
border: none !important;
|
||||
-moz-appearance: none !important;
|
||||
|
@ -36,10 +25,6 @@ html|input, html|textarea {
|
|||
font: inherit;
|
||||
}
|
||||
|
||||
html|input.ac {
|
||||
padding: 0 4px !important;
|
||||
}
|
||||
|
||||
html|input.empty {
|
||||
color: graytext;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == empty-1.xul empty-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == empty-1.xul empty-ref.xul # Windows: bug 1239170
|
||||
!= empty-2.xul empty-ref.xul
|
||||
# There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
|
||||
# Therefore, the equlity tests below should be marked as failing.
|
||||
|
@ -6,11 +6,11 @@ fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[
|
|||
fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
|
||||
!= emptymultiline-1.xul emptymultiline-ref.xul
|
||||
fails-if(Android) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-1.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == emptytextbox-1.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
!= emptytextbox-3.xul emptytextbox-ref.xul
|
||||
!= emptytextbox-4.xul emptytextbox-ref.xul
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-5.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == emptytextbox-5.xul emptytextbox-ref.xul # Windows: bug 1239170
|
||||
# There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
|
||||
# Therefore, the equlity tests below should be marked as failing.
|
||||
!= number-1.xul number-ref.xul
|
||||
|
@ -19,11 +19,11 @@ fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[
|
|||
!= number-4.xul number-ref.xul
|
||||
fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-5.xul number-ref.xul # bug 783658
|
||||
fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == passwd-1.xul passwd-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == passwd-2.xul passwd-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == passwd-1.xul passwd-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == passwd-2.xul passwd-ref.xul # Windows: bug 1239170
|
||||
!= passwd-3.xul passwd-ref.xul
|
||||
fails-if(Android) == plain-1.xul plain-ref.xul # bug 783658
|
||||
fails-if(Android) skip-if(browserIsRemote&&winWidget) == textbox-1.xul textbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(Android) skip-if(winWidget) == textbox-1.xul textbox-ref.xul # Windows: bug 1239170
|
||||
!= textbox-disabled.xul textbox-ref.xul
|
||||
# Read-only textboxes look like normal textboxes in windows Vista/7 default theme
|
||||
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if(browserIsRemote&&winWidget) != textbox-readonly.xul textbox-ref.xul # Windows: bug 1239170
|
||||
fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if(winWidget) != textbox-readonly.xul textbox-ref.xul # Windows: bug 1239170
|
||||
|
|
|
@ -175,4 +175,4 @@ Troubleshooting tips:
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
The version of WebRender currently in the tree is:
|
||||
fae962bfd6e1997f4b921ee93c3c1cc5abca3256
|
||||
34f1e8ed19a19cb950deef89ee31c1cf3d442d22
|
||||
|
|
|
@ -111,7 +111,8 @@ impl Example for App {
|
|||
(50, 350).by(50, 50),
|
||||
SideOffsets2D::new(Some(10.0), None, Some(10.0), None),
|
||||
StickyOffsetBounds::new(-40.0, 60.0),
|
||||
StickyOffsetBounds::new(0.0, 0.0)
|
||||
StickyOffsetBounds::new(0.0, 0.0),
|
||||
LayoutVector2D::new(0.0, 0.0)
|
||||
);
|
||||
|
||||
builder.push_clip_id(sticky_id);
|
||||
|
|
|
@ -19,7 +19,8 @@ void brush_vs(
|
|||
struct BrushInstance {
|
||||
int picture_address;
|
||||
int prim_address;
|
||||
int layer_address;
|
||||
int clip_node_id;
|
||||
int scroll_node_id;
|
||||
int clip_address;
|
||||
int z;
|
||||
int flags;
|
||||
|
@ -31,7 +32,8 @@ BrushInstance load_brush() {
|
|||
|
||||
bi.picture_address = aData0.x;
|
||||
bi.prim_address = aData0.y;
|
||||
bi.layer_address = aData0.z;
|
||||
bi.clip_node_id = aData0.z / 65536;
|
||||
bi.scroll_node_id = aData0.z % 65536;
|
||||
bi.clip_address = aData0.w;
|
||||
bi.z = aData1.x;
|
||||
bi.flags = aData1.y;
|
||||
|
@ -66,7 +68,7 @@ void main(void) {
|
|||
gl_Position = uTransform * vec4(device_pos, 0.0, 1.0);
|
||||
} else {
|
||||
AlphaBatchTask alpha_task = fetch_alpha_batch_task(brush.picture_address);
|
||||
Layer layer = fetch_layer(brush.layer_address);
|
||||
Layer layer = fetch_layer(brush.clip_node_id, brush.scroll_node_id);
|
||||
ClipArea clip_area = fetch_clip_area(brush.clip_address);
|
||||
|
||||
// Write the normal vertex information out.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
varying vec3 vUv;
|
||||
flat varying int vImageKind;
|
||||
flat varying vec4 vUvBounds;
|
||||
flat varying vec4 vUvBounds_NoClamp;
|
||||
flat varying vec4 vParams;
|
||||
|
||||
#if defined WR_FEATURE_ALPHA_TARGET
|
||||
|
@ -42,8 +43,8 @@ void brush_vs(
|
|||
#endif
|
||||
|
||||
vec2 uv0 = task.target_rect.p0;
|
||||
vec2 src_size = task.target_rect.size;
|
||||
vec2 uv1 = uv0 + src_size;
|
||||
vec2 src_size = task.target_rect.size * task.scale_factor;
|
||||
vec2 uv1 = uv0 + task.target_rect.size;
|
||||
|
||||
// TODO(gw): In the future we'll probably draw these as segments
|
||||
// with the brush shader. When that occurs, we can
|
||||
|
@ -74,6 +75,7 @@ void brush_vs(
|
|||
}
|
||||
|
||||
vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
|
||||
vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -89,7 +91,8 @@ vec4 brush_fs() {
|
|||
case BRUSH_IMAGE_NINEPATCH: {
|
||||
uv = clamp(vUv.xy, vec2(0.0), vParams.xy);
|
||||
uv += max(vec2(0.0), vUv.xy - vParams.zw);
|
||||
uv = mix(vUvBounds.xy, vUvBounds.zw, uv);
|
||||
uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
|
||||
uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
|
||||
break;
|
||||
}
|
||||
case BRUSH_IMAGE_MIRROR: {
|
||||
|
@ -101,7 +104,8 @@ vec4 brush_fs() {
|
|||
// shadow corner. This can happen, for example, when
|
||||
// drawing the outer parts of an inset box shadow.
|
||||
uv = clamp(uv, vec2(0.0), vec2(1.0));
|
||||
uv = mix(vUvBounds.xy, vUvBounds.zw, uv);
|
||||
uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
|
||||
uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,10 +52,6 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
|
|||
Layer layer,
|
||||
ClipArea area,
|
||||
int segment) {
|
||||
|
||||
RectWithSize clipped_local_rect = intersect_rect(local_clip_rect,
|
||||
layer.local_clip_rect);
|
||||
|
||||
vec2 outer_p0 = area.screen_origin_target_index.xy;
|
||||
vec2 outer_p1 = outer_p0 + area.task_bounds.zw - area.task_bounds.xy;
|
||||
vec2 inner_p0 = area.inner_rect.xy;
|
||||
|
@ -94,9 +90,9 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
|
|||
|
||||
gl_Position = uTransform * vec4(vertex_pos, 0.0, 1);
|
||||
|
||||
vLocalBounds = vec4(clipped_local_rect.p0, clipped_local_rect.p0 + clipped_local_rect.size);
|
||||
vLocalBounds = vec4(local_clip_rect.p0, local_clip_rect.p0 + local_clip_rect.size);
|
||||
|
||||
ClipVertexInfo vi = ClipVertexInfo(layer_pos.xyw, actual_pos, clipped_local_rect);
|
||||
ClipVertexInfo vi = ClipVertexInfo(layer_pos.xyw, actual_pos, local_clip_rect);
|
||||
return vi;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ BorderClipDot fetch_border_clip_dot(ivec2 address, int segment) {
|
|||
void main(void) {
|
||||
ClipMaskInstance cmi = fetch_clip_item();
|
||||
ClipArea area = fetch_clip_area(cmi.render_task_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address);
|
||||
|
||||
// Fetch the header information for this corner clip.
|
||||
BorderCorner corner = fetch_border_corner(cmi.clip_data_address);
|
||||
|
|
|
@ -24,7 +24,7 @@ ImageMaskData fetch_mask_data(ivec2 address) {
|
|||
void main(void) {
|
||||
ClipMaskInstance cmi = fetch_clip_item();
|
||||
ClipArea area = fetch_clip_area(cmi.render_task_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address);
|
||||
ImageMaskData mask = fetch_mask_data(cmi.clip_data_address);
|
||||
RectWithSize local_rect = mask.local_rect;
|
||||
ImageResource res = fetch_image_resource_direct(cmi.resource_address);
|
||||
|
|
|
@ -58,7 +58,7 @@ ClipData fetch_clip(ivec2 address) {
|
|||
void main(void) {
|
||||
ClipMaskInstance cmi = fetch_clip_item();
|
||||
ClipArea area = fetch_clip_area(cmi.render_task_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address);
|
||||
Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address);
|
||||
ClipData clip = fetch_clip(cmi.clip_data_address);
|
||||
RectWithSize local_rect = clip.rect.rect;
|
||||
|
||||
|
|
|
@ -71,14 +71,14 @@ vec4[2] fetch_from_resource_cache_2(int address) {
|
|||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
#define VECS_PER_LAYER 9
|
||||
#define VECS_PER_LAYER 10
|
||||
#define VECS_PER_RENDER_TASK 3
|
||||
#define VECS_PER_PRIM_HEADER 2
|
||||
#define VECS_PER_TEXT_RUN 3
|
||||
#define VECS_PER_GRADIENT 3
|
||||
#define VECS_PER_GRADIENT_STOP 2
|
||||
|
||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sLayers;
|
||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
|
||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks;
|
||||
|
||||
// Instanced attributes
|
||||
|
@ -143,14 +143,16 @@ vec4 fetch_from_resource_cache_1(int address) {
|
|||
return texelFetch(sResourceCache, uv, 0);
|
||||
}
|
||||
|
||||
struct Layer {
|
||||
struct ClipScrollNode {
|
||||
mat4 transform;
|
||||
mat4 inv_transform;
|
||||
RectWithSize local_clip_rect;
|
||||
vec4 local_clip_rect;
|
||||
vec2 reference_frame_relative_scroll_offset;
|
||||
vec2 scroll_offset;
|
||||
};
|
||||
|
||||
Layer fetch_layer(int index) {
|
||||
Layer layer;
|
||||
ClipScrollNode fetch_clip_scroll_node(int index) {
|
||||
ClipScrollNode node;
|
||||
|
||||
// Create a UV base coord for each 8 texels.
|
||||
// This is required because trying to use an offset
|
||||
|
@ -160,18 +162,46 @@ Layer fetch_layer(int index) {
|
|||
ivec2 uv0 = ivec2(uv.x + 0, uv.y);
|
||||
ivec2 uv1 = ivec2(uv.x + 8, uv.y);
|
||||
|
||||
layer.transform[0] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(0, 0));
|
||||
layer.transform[1] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(1, 0));
|
||||
layer.transform[2] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(2, 0));
|
||||
layer.transform[3] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(3, 0));
|
||||
node.transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(0, 0));
|
||||
node.transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(1, 0));
|
||||
node.transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(2, 0));
|
||||
node.transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(3, 0));
|
||||
|
||||
layer.inv_transform[0] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(4, 0));
|
||||
layer.inv_transform[1] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(5, 0));
|
||||
layer.inv_transform[2] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(6, 0));
|
||||
layer.inv_transform[3] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(7, 0));
|
||||
node.inv_transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(4, 0));
|
||||
node.inv_transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(5, 0));
|
||||
node.inv_transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(6, 0));
|
||||
node.inv_transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(7, 0));
|
||||
|
||||
vec4 clip_rect = TEXEL_FETCH(sLayers, uv1, 0, ivec2(0, 0));
|
||||
layer.local_clip_rect = RectWithSize(clip_rect.xy, clip_rect.zw);
|
||||
vec4 clip_rect = TEXEL_FETCH(sClipScrollNodes, uv1, 0, ivec2(0, 0));
|
||||
node.local_clip_rect = clip_rect;
|
||||
|
||||
vec4 offsets = TEXEL_FETCH(sClipScrollNodes, uv1, 0, ivec2(1, 0));
|
||||
node.reference_frame_relative_scroll_offset = offsets.xy;
|
||||
node.scroll_offset = offsets.zw;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
struct Layer {
|
||||
mat4 transform;
|
||||
mat4 inv_transform;
|
||||
RectWithSize local_clip_rect;
|
||||
};
|
||||
|
||||
Layer fetch_layer(int clip_node_id, int scroll_node_id) {
|
||||
ClipScrollNode clip_node = fetch_clip_scroll_node(clip_node_id);
|
||||
ClipScrollNode scroll_node = fetch_clip_scroll_node(scroll_node_id);
|
||||
|
||||
Layer layer;
|
||||
layer.transform = scroll_node.transform;
|
||||
layer.inv_transform = scroll_node.inv_transform;
|
||||
|
||||
vec4 local_clip_rect = clip_node.local_clip_rect;
|
||||
local_clip_rect.xy += clip_node.reference_frame_relative_scroll_offset;
|
||||
local_clip_rect.xy -= scroll_node.reference_frame_relative_scroll_offset;
|
||||
local_clip_rect.xy -= scroll_node.scroll_offset;
|
||||
|
||||
layer.local_clip_rect = RectWithSize(local_clip_rect.xy, local_clip_rect.zw);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
@ -228,6 +258,7 @@ struct BlurTask {
|
|||
RectWithSize target_rect;
|
||||
float render_target_layer_index;
|
||||
float blur_radius;
|
||||
float scale_factor;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
|
@ -238,6 +269,7 @@ BlurTask fetch_blur_task(int address) {
|
|||
RectWithSize(task_data.data0.xy, task_data.data0.zw),
|
||||
task_data.data1.x,
|
||||
task_data.data1.y,
|
||||
task_data.data1.z,
|
||||
task_data.data2
|
||||
);
|
||||
}
|
||||
|
@ -358,7 +390,8 @@ struct PrimitiveInstance {
|
|||
int specific_prim_address;
|
||||
int render_task_index;
|
||||
int clip_task_index;
|
||||
int layer_index;
|
||||
int scroll_node_id;
|
||||
int clip_node_id;
|
||||
int z;
|
||||
int user_data0;
|
||||
int user_data1;
|
||||
|
@ -372,7 +405,8 @@ PrimitiveInstance fetch_prim_instance() {
|
|||
pi.specific_prim_address = pi.prim_address + VECS_PER_PRIM_HEADER;
|
||||
pi.render_task_index = aData0.y;
|
||||
pi.clip_task_index = aData0.z;
|
||||
pi.layer_index = aData0.w;
|
||||
pi.clip_node_id = aData0.w / 65536;
|
||||
pi.scroll_node_id = aData0.w % 65536;
|
||||
pi.z = aData1.x;
|
||||
pi.user_data0 = aData1.y;
|
||||
pi.user_data1 = aData1.z;
|
||||
|
@ -388,6 +422,8 @@ struct CompositeInstance {
|
|||
int user_data0;
|
||||
int user_data1;
|
||||
float z;
|
||||
int user_data2;
|
||||
int user_data3;
|
||||
};
|
||||
|
||||
CompositeInstance fetch_composite_instance() {
|
||||
|
@ -400,6 +436,8 @@ CompositeInstance fetch_composite_instance() {
|
|||
|
||||
ci.user_data0 = aData1.x;
|
||||
ci.user_data1 = aData1.y;
|
||||
ci.user_data2 = aData1.z;
|
||||
ci.user_data3 = aData1.w;
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
@ -437,7 +475,7 @@ Primitive load_primitive() {
|
|||
|
||||
Primitive prim;
|
||||
|
||||
prim.layer = fetch_layer(pi.layer_index);
|
||||
prim.layer = fetch_layer(pi.clip_node_id, pi.scroll_node_id);
|
||||
prim.clip_area = fetch_clip_area(pi.clip_task_index);
|
||||
#ifdef PRIMITIVE_HAS_PICTURE_TASK
|
||||
prim.task = fetch_picture_task(pi.render_task_index);
|
||||
|
@ -546,8 +584,7 @@ VertexInfo write_vertex(RectWithSize instance_rect,
|
|||
vec2 local_pos = instance_rect.p0 + instance_rect.size * aPosition.xy;
|
||||
|
||||
// Clamp to the two local clip rects.
|
||||
vec2 clamped_local_pos = clamp_rect(clamp_rect(local_pos, local_clip_rect),
|
||||
layer.local_clip_rect);
|
||||
vec2 clamped_local_pos = clamp_rect(clamp_rect(local_pos, local_clip_rect), layer.local_clip_rect);
|
||||
|
||||
/// Compute the snapping offset.
|
||||
vec2 snap_offset = compute_snap_offset(clamped_local_pos, local_clip_rect, layer, snap_rect);
|
||||
|
@ -739,10 +776,9 @@ Image fetch_image(int address) {
|
|||
}
|
||||
|
||||
void write_clip(vec2 global_pos, ClipArea area) {
|
||||
vec2 texture_size = vec2(textureSize(sSharedCacheA8, 0).xy);
|
||||
vec2 uv = global_pos + area.task_bounds.xy - area.screen_origin_target_index.xy;
|
||||
vClipMaskUvBounds = area.task_bounds / texture_size.xyxy;
|
||||
vClipMaskUv = vec3(uv / texture_size, area.screen_origin_target_index.z);
|
||||
vClipMaskUvBounds = area.task_bounds;
|
||||
vClipMaskUv = vec3(uv, area.screen_origin_target_index.z);
|
||||
}
|
||||
#endif //WR_VERTEX_SHADER
|
||||
|
||||
|
@ -807,7 +843,7 @@ float do_clip() {
|
|||
vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
|
||||
// check for the dummy bounds, which are given to the opaque objects
|
||||
return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
|
||||
all(inside) ? textureLod(sSharedCacheA8, vClipMaskUv, 0.0).r : 0.0;
|
||||
all(inside) ? texelFetch(sSharedCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_DITHERING
|
||||
|
|
|
@ -18,7 +18,7 @@ void main(void) {
|
|||
vec2(ci.user_data0, ci.user_data1);
|
||||
|
||||
vec2 local_pos = mix(dest_origin,
|
||||
dest_origin + src_task.size,
|
||||
dest_origin + vec2(ci.user_data2, ci.user_data3),
|
||||
aPosition.xy);
|
||||
|
||||
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
|
||||
|
|
|
@ -15,12 +15,13 @@ varying vec3 vLocalPos;
|
|||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
#define MODE_ALPHA 0
|
||||
#define MODE_SUBPX_PASS0 1
|
||||
#define MODE_SUBPX_PASS1 2
|
||||
#define MODE_SUBPX_BG_PASS0 3
|
||||
#define MODE_SUBPX_BG_PASS1 4
|
||||
#define MODE_SUBPX_BG_PASS2 5
|
||||
#define MODE_COLOR_BITMAP 6
|
||||
#define MODE_SUBPX_OPAQUE 1
|
||||
#define MODE_SUBPX_PASS0 2
|
||||
#define MODE_SUBPX_PASS1 3
|
||||
#define MODE_SUBPX_BG_PASS0 4
|
||||
#define MODE_SUBPX_BG_PASS1 5
|
||||
#define MODE_SUBPX_BG_PASS2 6
|
||||
#define MODE_COLOR_BITMAP 7
|
||||
|
||||
void main(void) {
|
||||
Primitive prim = load_primitive();
|
||||
|
@ -76,6 +77,11 @@ void main(void) {
|
|||
case MODE_COLOR_BITMAP:
|
||||
vColor = vec4(text.color.a);
|
||||
break;
|
||||
case MODE_SUBPX_OPAQUE:
|
||||
// The text foreground color is handled by the constant
|
||||
// color blend mode.
|
||||
vColor = vec4(1.0);
|
||||
break;
|
||||
case MODE_SUBPX_BG_PASS1:
|
||||
// This should never be reached.
|
||||
break;
|
||||
|
|
|
@ -170,7 +170,6 @@ impl FrameBuilder {
|
|||
LayerSize::new(width, height));
|
||||
let brush_info = LayerPrimitiveInfo::new(brush_rect);
|
||||
let brush_prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
&brush_info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
|
@ -239,7 +238,6 @@ impl FrameBuilder {
|
|||
};
|
||||
let brush_info = LayerPrimitiveInfo::new(brush_rect);
|
||||
let brush_prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
&brush_info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
|
|
|
@ -21,7 +21,6 @@ pub type ClipSourcesWeakHandle = WeakFreeListHandle<ClipSources>;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipRegion {
|
||||
pub origin: LayerPoint,
|
||||
pub main: LayerRect,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
pub complex_clips: Vec<ComplexClipRegion>,
|
||||
|
@ -32,32 +31,39 @@ impl ClipRegion {
|
|||
rect: LayerRect,
|
||||
mut complex_clips: Vec<ComplexClipRegion>,
|
||||
mut image_mask: Option<ImageMask>,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) -> ClipRegion {
|
||||
// All the coordinates we receive are relative to the stacking context, but we want
|
||||
// to convert them to something relative to the origin of the clip.
|
||||
let negative_origin = -rect.origin.to_vector();
|
||||
let rect = rect.translate(reference_frame_relative_offset);
|
||||
|
||||
if let Some(ref mut image_mask) = image_mask {
|
||||
image_mask.rect = image_mask.rect.translate(&negative_origin);
|
||||
image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
|
||||
}
|
||||
|
||||
for complex_clip in complex_clips.iter_mut() {
|
||||
complex_clip.rect = complex_clip.rect.translate(&negative_origin);
|
||||
complex_clip.rect = complex_clip.rect.translate(reference_frame_relative_offset);
|
||||
}
|
||||
|
||||
ClipRegion {
|
||||
origin: rect.origin,
|
||||
main: LayerRect::new(LayerPoint::zero(), rect.size),
|
||||
main: rect,
|
||||
image_mask,
|
||||
complex_clips,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_for_clip_node_with_local_clip(local_clip: &LocalClip) -> ClipRegion {
|
||||
pub fn create_for_clip_node_with_local_clip(
|
||||
local_clip: &LocalClip,
|
||||
reference_frame_relative_offset: &LayoutVector2D
|
||||
) -> ClipRegion {
|
||||
let complex_clips = match local_clip {
|
||||
&LocalClip::Rect(_) => Vec::new(),
|
||||
&LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
|
||||
};
|
||||
ClipRegion::create_for_clip_node(*local_clip.clip_rect(), complex_clips, None)
|
||||
ClipRegion::create_for_clip_node(
|
||||
*local_clip.clip_rect(),
|
||||
complex_clips,
|
||||
None,
|
||||
reference_frame_relative_offset
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize};
|
||||
use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId};
|
||||
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
|
||||
use api::WorldPoint;
|
||||
use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, LayoutVector2D, PipelineId};
|
||||
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity};
|
||||
use api::{StickyOffsetBounds, WorldPoint};
|
||||
use clip::{ClipRegion, ClipSources, ClipSourcesHandle, ClipStore};
|
||||
use clip_scroll_tree::{CoordinateSystemId, TransformUpdateState};
|
||||
use euclid::SideOffsets2D;
|
||||
use geometry::ray_intersects_rect;
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
|
||||
use render_task::{ClipChain, ClipChainNode, ClipWorkItem};
|
||||
use resource_cache::ResourceCache;
|
||||
use spring::{DAMPING, STIFFNESS, Spring};
|
||||
use std::rc::Rc;
|
||||
use tiling::{PackedLayer, PackedLayerIndex};
|
||||
use util::{MatrixHelpers, MaxRect};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -24,15 +24,13 @@ const CAN_OVERSCROLL: bool = true;
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
const CAN_OVERSCROLL: bool = false;
|
||||
|
||||
const MAX_LOCAL_VIEWPORT: f32 = 1000000.0;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipInfo {
|
||||
/// The clips for this node.
|
||||
pub clip_sources: ClipSourcesHandle,
|
||||
|
||||
/// The packed layer index for this node, which is used to render a clip mask
|
||||
/// for it, if necessary.
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
|
||||
/// Whether or not this clip node automatically creates a mask.
|
||||
pub is_masking: bool,
|
||||
}
|
||||
|
@ -40,7 +38,6 @@ pub struct ClipInfo {
|
|||
impl ClipInfo {
|
||||
pub fn new(
|
||||
clip_region: ClipRegion,
|
||||
packed_layer_index: PackedLayerIndex,
|
||||
clip_store: &mut ClipStore,
|
||||
) -> ClipInfo {
|
||||
let clip_sources = ClipSources::from(clip_region);
|
||||
|
@ -48,7 +45,6 @@ impl ClipInfo {
|
|||
|
||||
ClipInfo {
|
||||
clip_sources: clip_store.insert(clip_sources),
|
||||
packed_layer_index,
|
||||
is_masking,
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +55,7 @@ pub struct StickyFrameInfo {
|
|||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
pub previously_applied_offset: LayoutVector2D,
|
||||
pub current_offset: LayerVector2D,
|
||||
}
|
||||
|
||||
|
@ -66,12 +63,14 @@ impl StickyFrameInfo {
|
|||
pub fn new(
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D
|
||||
) -> StickyFrameInfo {
|
||||
StickyFrameInfo {
|
||||
margins,
|
||||
vertical_offset_bounds,
|
||||
horizontal_offset_bounds,
|
||||
previously_applied_offset,
|
||||
current_offset: LayerVector2D::zero(),
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +109,8 @@ pub struct ClipScrollNode {
|
|||
/// This is in the coordinate system of the node origin.
|
||||
/// Precisely, it combines the local clipping rectangles of all the parent
|
||||
/// nodes on the way to the root, including those of `ClipRegion` rectangles.
|
||||
/// The combined clip is lossy/concervative on `ReferenceFrame` nodes.
|
||||
/// The combined clip is reset to maximum when an incompatible coordinate
|
||||
/// system is encountered.
|
||||
pub combined_local_viewport_rect: LayerRect,
|
||||
|
||||
/// World transform for the viewport rect itself. This is the parent
|
||||
|
@ -148,6 +148,10 @@ pub struct ClipScrollNode {
|
|||
|
||||
/// The axis-aligned coordinate system id of this node.
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
|
||||
/// A linear ID / index of this clip-scroll node. Used as a reference to
|
||||
/// pass to shaders, to allow them to fetch a given clip-scroll node.
|
||||
pub id: ClipScrollNodeIndex,
|
||||
}
|
||||
|
||||
impl ClipScrollNode {
|
||||
|
@ -171,6 +175,7 @@ impl ClipScrollNode {
|
|||
clip_chain_node: None,
|
||||
combined_clip_outer_bounds: DeviceIntRect::max_rect(),
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
id: ClipScrollNodeIndex(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,15 +292,11 @@ impl ClipScrollNode {
|
|||
pub fn update_clip_work_item(
|
||||
&mut self,
|
||||
state: &mut TransformUpdateState,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32,
|
||||
packed_layers: &mut Vec<PackedLayer>,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
) {
|
||||
self.coordinate_system_id = state.current_coordinate_system_id;
|
||||
|
||||
let current_clip_chain = state.parent_clip_chain.clone();
|
||||
let clip_info = match self.node_type {
|
||||
NodeType::Clip(ref mut info) if info.is_masking => info,
|
||||
|
@ -306,29 +307,9 @@ impl ClipScrollNode {
|
|||
}
|
||||
};
|
||||
|
||||
// The coordinates of the mask are relative to the origin of the node itself,
|
||||
// so we need to account for that origin in the transformation we assign to
|
||||
// the packed layer.
|
||||
let transform = self.world_viewport_transform
|
||||
.pre_translate(self.local_viewport_rect.origin.to_vector().to_3d());
|
||||
|
||||
let packed_layer = &mut packed_layers[clip_info.packed_layer_index.0];
|
||||
if packed_layer.set_transform(transform) {
|
||||
// Meanwhile, the combined viewport rect is relative to the reference frame, so
|
||||
// we move it into the local coordinate system of the node.
|
||||
let local_viewport_rect = self.combined_local_viewport_rect
|
||||
.translate(&-self.local_viewport_rect.origin.to_vector());
|
||||
|
||||
packed_layer.set_rect(
|
||||
&local_viewport_rect,
|
||||
screen_rect,
|
||||
device_pixel_ratio,
|
||||
);
|
||||
}
|
||||
|
||||
let clip_sources = clip_store.get_mut(&clip_info.clip_sources);
|
||||
clip_sources.update(
|
||||
&transform,
|
||||
&self.world_viewport_transform,
|
||||
gpu_cache,
|
||||
resource_cache,
|
||||
device_pixel_ratio,
|
||||
|
@ -345,7 +326,7 @@ impl ClipScrollNode {
|
|||
// TODO: Combine rectangles in the same axis-aligned clip space here?
|
||||
self.clip_chain_node = Some(Rc::new(ClipChainNode {
|
||||
work_item: ClipWorkItem {
|
||||
layer_index: clip_info.packed_layer_index,
|
||||
scroll_node_id: self.id,
|
||||
clip_sources: clip_info.clip_sources.weak(),
|
||||
coordinate_system_id: state.current_coordinate_system_id,
|
||||
},
|
||||
|
@ -356,7 +337,11 @@ impl ClipScrollNode {
|
|||
state.parent_clip_chain = self.clip_chain_node.clone();
|
||||
}
|
||||
|
||||
pub fn update_transform(&mut self, state: &mut TransformUpdateState) {
|
||||
pub fn update_transform(
|
||||
&mut self,
|
||||
state: &mut TransformUpdateState,
|
||||
node_data: &mut Vec<ClipScrollNodeData>,
|
||||
) {
|
||||
// We calculate this here to avoid a double-borrow later.
|
||||
let sticky_offset = self.calculate_sticky_offset(
|
||||
&state.nearest_scrolling_ancestor_offset,
|
||||
|
@ -452,6 +437,39 @@ impl ClipScrollNode {
|
|||
info.current_offset + state.parent_accumulated_scroll_offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Store coord system ID, and also the ID used for shaders to reference this node.
|
||||
self.coordinate_system_id = state.current_coordinate_system_id;
|
||||
self.id = ClipScrollNodeIndex(node_data.len() as u32);
|
||||
|
||||
let local_clip_rect = if self.world_content_transform.has_perspective_component() {
|
||||
LayerRect::new(
|
||||
LayerPoint::new(-MAX_LOCAL_VIEWPORT, -MAX_LOCAL_VIEWPORT),
|
||||
LayerSize::new(2.0 * MAX_LOCAL_VIEWPORT, 2.0 * MAX_LOCAL_VIEWPORT)
|
||||
)
|
||||
} else {
|
||||
self.combined_local_viewport_rect
|
||||
};
|
||||
|
||||
let data = match self.world_content_transform.inverse() {
|
||||
Some(inverse) => {
|
||||
ClipScrollNodeData {
|
||||
transform: self.world_content_transform,
|
||||
inv_transform: inverse,
|
||||
local_clip_rect,
|
||||
reference_frame_relative_scroll_offset: self.reference_frame_relative_scroll_offset,
|
||||
scroll_offset: self.scroll_offset(),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
state.combined_outer_clip_bounds = DeviceIntRect::zero();
|
||||
|
||||
ClipScrollNodeData::invalid()
|
||||
}
|
||||
};
|
||||
|
||||
// Write the data that will be made available to the GPU for this node.
|
||||
node_data.push(data);
|
||||
}
|
||||
|
||||
fn calculate_sticky_offset(
|
||||
|
@ -478,54 +496,87 @@ impl ClipScrollNode {
|
|||
|
||||
let mut sticky_offset = LayerVector2D::zero();
|
||||
if let Some(margin) = info.margins.top {
|
||||
// If the sticky rect is positioned above the top edge of the viewport (plus margin)
|
||||
// we move it down so that it is fully inside the viewport.
|
||||
let top_viewport_edge = viewport_rect.min_y() + margin;
|
||||
if sticky_rect.min_y() < top_viewport_edge {
|
||||
sticky_offset.y = top_viewport_edge - sticky_rect.min_y();
|
||||
// If the sticky rect is positioned above the top edge of the viewport (plus margin)
|
||||
// we move it down so that it is fully inside the viewport.
|
||||
sticky_offset.y = top_viewport_edge - sticky_rect.min_y();
|
||||
} else if info.previously_applied_offset.y > 0.0 &&
|
||||
sticky_rect.min_y() > top_viewport_edge {
|
||||
// However, if the sticky rect is positioned *below* the top edge of the viewport
|
||||
// and there is already some offset applied to the sticky rect's position, then
|
||||
// we need to move it up so that it remains at the correct position. This
|
||||
// makes sticky_offset.y negative and effectively reduces the amount of the
|
||||
// offset that was already applied. We limit the reduction so that it can, at most,
|
||||
// cancel out the already-applied offset, but should never end up adjusting the
|
||||
// position the other way.
|
||||
sticky_offset.y = top_viewport_edge - sticky_rect.min_y();
|
||||
sticky_offset.y = sticky_offset.y.max(-info.previously_applied_offset.y);
|
||||
}
|
||||
debug_assert!(sticky_offset.y >= 0.0);
|
||||
debug_assert!(sticky_offset.y + info.previously_applied_offset.y >= 0.0);
|
||||
}
|
||||
|
||||
if sticky_offset.y == 0.0 {
|
||||
// If we don't have a sticky-top offset (sticky_offset.y + info.previously_applied_offset.y
|
||||
// == 0), or if we have a previously-applied bottom offset (previously_applied_offset.y < 0)
|
||||
// then we check for handling the bottom margin case.
|
||||
if sticky_offset.y + info.previously_applied_offset.y <= 0.0 {
|
||||
if let Some(margin) = info.margins.bottom {
|
||||
// If the bottom of the sticky rect is positioned below the bottom viewport edge
|
||||
// (accounting for margin), we move it up so that it is fully inside the viewport.
|
||||
// Same as the above case, but inverted for bottom-sticky items. Here
|
||||
// we adjust items upwards, resulting in a negative sticky_offset.y,
|
||||
// or reduce the already-present upward adjustment, resulting in a positive
|
||||
// sticky_offset.y.
|
||||
let bottom_viewport_edge = viewport_rect.max_y() - margin;
|
||||
if sticky_rect.max_y() > bottom_viewport_edge {
|
||||
sticky_offset.y = bottom_viewport_edge - sticky_rect.max_y();
|
||||
sticky_offset.y = bottom_viewport_edge - sticky_rect.max_y();
|
||||
} else if info.previously_applied_offset.y < 0.0 &&
|
||||
sticky_rect.max_y() < bottom_viewport_edge {
|
||||
sticky_offset.y = bottom_viewport_edge - sticky_rect.max_y();
|
||||
sticky_offset.y = sticky_offset.y.min(-info.previously_applied_offset.y);
|
||||
}
|
||||
debug_assert!(sticky_offset.y <= 0.0);
|
||||
debug_assert!(sticky_offset.y + info.previously_applied_offset.y <= 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, but for the x-axis.
|
||||
if let Some(margin) = info.margins.left {
|
||||
// If the sticky rect is positioned left of the left edge of the viewport (plus margin)
|
||||
// we move it right so that it is fully inside the viewport.
|
||||
let left_viewport_edge = viewport_rect.min_x() + margin;
|
||||
if sticky_rect.min_x() < left_viewport_edge {
|
||||
sticky_offset.x = left_viewport_edge - sticky_rect.min_x();
|
||||
sticky_offset.x = left_viewport_edge - sticky_rect.min_x();
|
||||
} else if info.previously_applied_offset.x > 0.0 &&
|
||||
sticky_rect.min_x() > left_viewport_edge {
|
||||
sticky_offset.x = left_viewport_edge - sticky_rect.min_x();
|
||||
sticky_offset.x = sticky_offset.x.max(-info.previously_applied_offset.x);
|
||||
}
|
||||
debug_assert!(sticky_offset.x >= 0.0);
|
||||
debug_assert!(sticky_offset.x + info.previously_applied_offset.x >= 0.0);
|
||||
}
|
||||
|
||||
if sticky_offset.x == 0.0 {
|
||||
if sticky_offset.x + info.previously_applied_offset.x <= 0.0 {
|
||||
if let Some(margin) = info.margins.right {
|
||||
// If the right edge of the sticky rect is positioned right of the right viewport
|
||||
// edge (accounting for margin), we move it left so that it is fully inside the
|
||||
// viewport.
|
||||
let right_viewport_edge = viewport_rect.max_x() - margin;
|
||||
if sticky_rect.max_x() > right_viewport_edge {
|
||||
sticky_offset.x = right_viewport_edge - sticky_rect.max_x();
|
||||
sticky_offset.x = right_viewport_edge - sticky_rect.max_x();
|
||||
} else if info.previously_applied_offset.x < 0.0 &&
|
||||
sticky_rect.max_x() < right_viewport_edge {
|
||||
sticky_offset.x = right_viewport_edge - sticky_rect.max_x();
|
||||
sticky_offset.x = sticky_offset.x.min(-info.previously_applied_offset.x);
|
||||
}
|
||||
debug_assert!(sticky_offset.x <= 0.0);
|
||||
debug_assert!(sticky_offset.x + info.previously_applied_offset.x <= 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
sticky_offset.y = sticky_offset.y.max(info.vertical_offset_bounds.min);
|
||||
sticky_offset.y = sticky_offset.y.min(info.vertical_offset_bounds.max);
|
||||
sticky_offset.x = sticky_offset.x.max(info.horizontal_offset_bounds.min);
|
||||
sticky_offset.x = sticky_offset.x.min(info.horizontal_offset_bounds.max);
|
||||
// The total "sticky offset" (which is the sum that was already applied by
|
||||
// the calling code, stored in info.previously_applied_offset, and the extra amount we
|
||||
// computed as a result of scrolling, stored in sticky_offset) needs to be
|
||||
// clamped to the provided bounds.
|
||||
let clamp_adjusted = |value: f32, adjust: f32, bounds: &StickyOffsetBounds| {
|
||||
(value + adjust).max(bounds.min).min(bounds.max) - adjust
|
||||
};
|
||||
sticky_offset.y = clamp_adjusted(sticky_offset.y,
|
||||
info.previously_applied_offset.y,
|
||||
&info.vertical_offset_bounds);
|
||||
sticky_offset.x = clamp_adjusted(sticky_offset.x,
|
||||
info.previously_applied_offset.x,
|
||||
&info.horizontal_offset_bounds);
|
||||
|
||||
sticky_offset
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ use api::{ScrollLayerState, ScrollLocation, WorldPoint};
|
|||
use clip::ClipStore;
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollingState, StickyFrameInfo};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::ClipScrollNodeData;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
use render_task::ClipChain;
|
||||
use resource_cache::ResourceCache;
|
||||
use tiling::PackedLayer;
|
||||
|
||||
pub type ScrollStates = FastHashMap<ClipId, ScrollingState>;
|
||||
|
||||
|
@ -329,11 +329,11 @@ impl ClipScrollTree {
|
|||
&mut self,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32,
|
||||
packed_layers: &mut Vec<PackedLayer>,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
pan: LayerPoint,
|
||||
node_data: &mut Vec<ClipScrollNodeData>,
|
||||
) {
|
||||
if self.nodes.is_empty() {
|
||||
return;
|
||||
|
@ -360,12 +360,11 @@ impl ClipScrollTree {
|
|||
self.update_node_transform(
|
||||
root_reference_frame_id,
|
||||
&mut state,
|
||||
&screen_rect,
|
||||
device_pixel_ratio,
|
||||
packed_layers,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
node_data,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -373,12 +372,11 @@ impl ClipScrollTree {
|
|||
&mut self,
|
||||
layer_id: ClipId,
|
||||
state: &mut TransformUpdateState,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32,
|
||||
packed_layers: &mut Vec<PackedLayer>,
|
||||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
node_data: &mut Vec<ClipScrollNodeData>,
|
||||
) {
|
||||
// TODO(gw): This is an ugly borrow check workaround to clone these.
|
||||
// Restructure this to avoid the clones!
|
||||
|
@ -389,12 +387,13 @@ impl ClipScrollTree {
|
|||
None => return,
|
||||
};
|
||||
|
||||
node.update_transform(&mut state);
|
||||
node.update_transform(
|
||||
&mut state,
|
||||
node_data
|
||||
);
|
||||
node.update_clip_work_item(
|
||||
&mut state,
|
||||
screen_rect,
|
||||
device_pixel_ratio,
|
||||
packed_layers,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
|
@ -407,12 +406,11 @@ impl ClipScrollTree {
|
|||
self.update_node_transform(
|
||||
child_layer_id,
|
||||
&mut state,
|
||||
screen_rect,
|
||||
device_pixel_ratio,
|
||||
packed_layers,
|
||||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
node_data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use super::shader_source;
|
||||
use api::ImageFormat;
|
||||
use api::{ColorF, ImageFormat};
|
||||
use api::{DeviceIntRect, DeviceUintSize};
|
||||
use euclid::Transform3D;
|
||||
use gleam::gl;
|
||||
|
@ -1925,6 +1925,12 @@ impl Device {
|
|||
self.gl.blend_func_separate(gl::ONE, gl::ONE, gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
|
||||
self.gl.blend_equation(gl::FUNC_ADD);
|
||||
}
|
||||
pub fn set_blend_mode_subpixel_opaque(&self, color: ColorF) {
|
||||
self.gl.blend_color(color.r, color.g, color.b, color.a);
|
||||
self.gl
|
||||
.blend_func(gl::CONSTANT_COLOR, gl::ONE_MINUS_SRC_COLOR);
|
||||
self.gl.blend_equation(gl::FUNC_ADD);
|
||||
}
|
||||
}
|
||||
|
||||
/// return (gl_internal_format, gl_format)
|
||||
|
|
|
@ -322,8 +322,10 @@ impl<'a> FlattenContext<'a> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let mut clip_region = ClipRegion::create_for_clip_node_with_local_clip(local_clip);
|
||||
clip_region.origin += reference_frame_relative_offset;
|
||||
let clip_region = ClipRegion::create_for_clip_node_with_local_clip(
|
||||
local_clip,
|
||||
&reference_frame_relative_offset
|
||||
);
|
||||
let parent_pipeline_id = parent_id.pipeline_id();
|
||||
let clip_id = self.clip_scroll_tree
|
||||
.generate_new_clip_id(parent_pipeline_id);
|
||||
|
@ -552,13 +554,12 @@ impl<'a> FlattenContext<'a> {
|
|||
}
|
||||
SpecificDisplayItem::Clip(ref info) => {
|
||||
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
|
||||
let mut clip_region = ClipRegion::create_for_clip_node(
|
||||
let clip_region = ClipRegion::create_for_clip_node(
|
||||
*item.local_clip().clip_rect(),
|
||||
complex_clips,
|
||||
info.image_mask,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
clip_region.origin += reference_frame_relative_offset;
|
||||
|
||||
self.flatten_clip(
|
||||
pipeline_id,
|
||||
&clip_and_scroll.scroll_node_id,
|
||||
|
@ -568,13 +569,12 @@ impl<'a> FlattenContext<'a> {
|
|||
}
|
||||
SpecificDisplayItem::ScrollFrame(ref info) => {
|
||||
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
|
||||
let mut clip_region = ClipRegion::create_for_clip_node(
|
||||
let clip_region = ClipRegion::create_for_clip_node(
|
||||
*item.local_clip().clip_rect(),
|
||||
complex_clips,
|
||||
info.image_mask,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
clip_region.origin += reference_frame_relative_offset;
|
||||
|
||||
// Just use clip rectangle as the frame rect for this scroll frame.
|
||||
// This is useful when calculating scroll extents for the
|
||||
// ClipScrollNode::scroll(..) API as well as for properly setting sticky
|
||||
|
@ -599,6 +599,7 @@ impl<'a> FlattenContext<'a> {
|
|||
info.margins,
|
||||
info.vertical_offset_bounds,
|
||||
info.horizontal_offset_bounds,
|
||||
info.previously_applied_offset,
|
||||
);
|
||||
self.clip_scroll_tree.add_sticky_frame(
|
||||
info.id,
|
||||
|
|
|
@ -16,7 +16,7 @@ use app_units::Au;
|
|||
use border::ImageBorderSegment;
|
||||
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
|
||||
use clip_scroll_node::{ClipInfo, ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId};
|
||||
use clip_scroll_tree::{ClipScrollTree};
|
||||
use euclid::{SideOffsets2D, TypedTransform3D, vec2, vec3};
|
||||
use frame::FrameId;
|
||||
use gpu_cache::GpuCache;
|
||||
|
@ -29,14 +29,14 @@ use prim_store::{PrimitiveContainer, PrimitiveIndex};
|
|||
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
|
||||
use prim_store::{RectangleContent, RectanglePrimitive, TextRunPrimitiveCpu};
|
||||
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use render_task::{AlphaRenderItem, ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
|
||||
use render_task::{AlphaRenderItem, ClearMode, RenderTask, RenderTaskId, RenderTaskLocation};
|
||||
use render_task::RenderTaskTree;
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::ScenePipeline;
|
||||
use std::{mem, usize, f32, i32};
|
||||
use tiling::{ClipScrollGroup, ClipScrollGroupIndex, CompositeOps, Frame};
|
||||
use tiling::{CompositeOps, Frame};
|
||||
use tiling::{ContextIsolation, RenderTargetKind, StackingContextIndex};
|
||||
use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, RenderPass};
|
||||
use tiling::{PrimitiveFlags, PrimitiveRunCmd, RenderPass};
|
||||
use tiling::{RenderTargetContext, ScrollbarPrimitive, StackingContext};
|
||||
use util::{self, pack_as_float, RectHelpers, recycle_vec};
|
||||
use box_shadow::BLUR_SAMPLE_SCALE;
|
||||
|
@ -113,11 +113,6 @@ pub struct FrameBuilder {
|
|||
pub config: FrameBuilderConfig,
|
||||
|
||||
stacking_context_store: Vec<StackingContext>,
|
||||
clip_scroll_group_store: Vec<ClipScrollGroup>,
|
||||
// Note: value here is meant to be `ClipScrollGroupIndex`,
|
||||
// but we already have `ClipAndScrollInfo` in the key
|
||||
clip_scroll_group_indices: FastHashMap<ClipAndScrollInfo, usize>,
|
||||
packed_layers: Vec<PackedLayer>,
|
||||
|
||||
// A stack of the current shadow primitives.
|
||||
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
|
||||
|
@ -141,36 +136,24 @@ pub struct FrameBuilder {
|
|||
}
|
||||
|
||||
pub struct PrimitiveContext<'a> {
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
pub packed_layer: &'a PackedLayer,
|
||||
pub device_pixel_ratio: f32,
|
||||
pub clip_chain: ClipChain,
|
||||
pub clip_bounds: DeviceIntRect,
|
||||
pub clip_id: ClipId,
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
pub display_list: &'a BuiltDisplayList,
|
||||
pub clip_node: &'a ClipScrollNode,
|
||||
pub scroll_node: &'a ClipScrollNode,
|
||||
}
|
||||
|
||||
impl<'a> PrimitiveContext<'a> {
|
||||
fn new(
|
||||
packed_layer_index: PackedLayerIndex,
|
||||
packed_layer: &'a PackedLayer,
|
||||
clip_id: ClipId,
|
||||
clip_chain: ClipChain,
|
||||
clip_bounds: DeviceIntRect,
|
||||
coordinate_system_id: CoordinateSystemId,
|
||||
device_pixel_ratio: f32,
|
||||
display_list: &'a BuiltDisplayList,
|
||||
clip_node: &'a ClipScrollNode,
|
||||
scroll_node: &'a ClipScrollNode,
|
||||
) -> Self {
|
||||
PrimitiveContext {
|
||||
packed_layer_index,
|
||||
packed_layer,
|
||||
clip_chain,
|
||||
clip_bounds,
|
||||
coordinate_system_id,
|
||||
device_pixel_ratio,
|
||||
clip_id,
|
||||
display_list,
|
||||
clip_node,
|
||||
scroll_node,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,11 +168,8 @@ impl FrameBuilder {
|
|||
match previous {
|
||||
Some(prev) => FrameBuilder {
|
||||
stacking_context_store: recycle_vec(prev.stacking_context_store),
|
||||
clip_scroll_group_store: recycle_vec(prev.clip_scroll_group_store),
|
||||
clip_scroll_group_indices: FastHashMap::default(),
|
||||
cmds: recycle_vec(prev.cmds),
|
||||
hit_testing_runs: recycle_vec(prev.hit_testing_runs),
|
||||
packed_layers: recycle_vec(prev.packed_layers),
|
||||
shadow_prim_stack: recycle_vec(prev.shadow_prim_stack),
|
||||
pending_shadow_contents: recycle_vec(prev.pending_shadow_contents),
|
||||
scrollbar_prims: recycle_vec(prev.scrollbar_prims),
|
||||
|
@ -204,11 +184,8 @@ impl FrameBuilder {
|
|||
},
|
||||
None => FrameBuilder {
|
||||
stacking_context_store: Vec::new(),
|
||||
clip_scroll_group_store: Vec::new(),
|
||||
clip_scroll_group_indices: FastHashMap::default(),
|
||||
cmds: Vec::new(),
|
||||
hit_testing_runs: Vec::new(),
|
||||
packed_layers: Vec::new(),
|
||||
shadow_prim_stack: Vec::new(),
|
||||
pending_shadow_contents: Vec::new(),
|
||||
scrollbar_prims: Vec::new(),
|
||||
|
@ -229,16 +206,10 @@ impl FrameBuilder {
|
|||
/// sub-primitives.
|
||||
pub fn create_primitive(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
info: &LayerPrimitiveInfo,
|
||||
mut clip_sources: Vec<ClipSource>,
|
||||
container: PrimitiveContainer,
|
||||
) -> PrimitiveIndex {
|
||||
if !self.clip_scroll_group_indices.contains_key(&clip_and_scroll) {
|
||||
let group_id = self.create_clip_scroll_group(&clip_and_scroll);
|
||||
self.clip_scroll_group_indices.insert(clip_and_scroll, group_id);
|
||||
}
|
||||
|
||||
if let &LocalClip::RoundedRect(main, region) = &info.local_clip {
|
||||
clip_sources.push(ClipSource::Rectangle(main));
|
||||
clip_sources.push(ClipSource::RoundedRectangle(
|
||||
|
@ -322,28 +293,12 @@ impl FrameBuilder {
|
|||
container: PrimitiveContainer,
|
||||
) -> PrimitiveIndex {
|
||||
self.add_primitive_to_hit_testing_list(info, clip_and_scroll);
|
||||
let prim_index = self.create_primitive(clip_and_scroll, info, clip_sources, container);
|
||||
let prim_index = self.create_primitive(info, clip_sources, container);
|
||||
|
||||
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
|
||||
prim_index
|
||||
}
|
||||
|
||||
fn create_clip_scroll_group(&mut self, info: &ClipAndScrollInfo) -> usize {
|
||||
let packed_layer_index = PackedLayerIndex(self.packed_layers.len());
|
||||
self.packed_layers.push(PackedLayer::empty());
|
||||
|
||||
let group_id = self.clip_scroll_group_store.len();
|
||||
self.clip_scroll_group_store.push(ClipScrollGroup {
|
||||
scroll_node_id: info.scroll_node_id,
|
||||
clip_node_id: info.clip_node_id(),
|
||||
packed_layer_index,
|
||||
screen_bounding_rect: None,
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
});
|
||||
|
||||
group_id
|
||||
}
|
||||
|
||||
pub fn notify_waiting_for_root_stacking_context(&mut self) {
|
||||
self.has_root_stacking_context = false;
|
||||
}
|
||||
|
@ -517,15 +472,13 @@ impl FrameBuilder {
|
|||
clip_region: ClipRegion,
|
||||
clip_scroll_tree: &mut ClipScrollTree,
|
||||
) {
|
||||
let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size);
|
||||
let clip_rect = clip_region.main;
|
||||
let clip_info = ClipInfo::new(
|
||||
clip_region,
|
||||
PackedLayerIndex(self.packed_layers.len()),
|
||||
&mut self.clip_store,
|
||||
);
|
||||
let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, clip_info, clip_rect);
|
||||
clip_scroll_tree.add_node(node, new_node_id);
|
||||
self.packed_layers.push(PackedLayer::empty());
|
||||
}
|
||||
|
||||
pub fn add_scroll_frame(
|
||||
|
@ -566,7 +519,6 @@ impl FrameBuilder {
|
|||
// before any visual text elements that are added as
|
||||
// part of this shadow context.
|
||||
let prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Picture(prim),
|
||||
|
@ -676,7 +628,6 @@ impl FrameBuilder {
|
|||
let mut info = info.clone();
|
||||
info.rect = info.rect.translate(&shadow.offset);
|
||||
let prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
&info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Line(line),
|
||||
|
@ -685,7 +636,6 @@ impl FrameBuilder {
|
|||
}
|
||||
|
||||
let prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
&info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Line(line),
|
||||
|
@ -1183,7 +1133,6 @@ impl FrameBuilder {
|
|||
let mut info = info.clone();
|
||||
info.rect = rect.translate(&text_prim.offset);
|
||||
let prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
&info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::TextRun(text_prim),
|
||||
|
@ -1194,7 +1143,6 @@ impl FrameBuilder {
|
|||
// Create (and add to primitive store) the primitive that will be
|
||||
// used for both the visual element and also the shadow(s).
|
||||
let prim_index = self.create_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::TextRun(prim),
|
||||
|
@ -1317,19 +1265,6 @@ impl FrameBuilder {
|
|||
stacking_context.isolated_items_bounds = LayerRect::zero();
|
||||
}
|
||||
|
||||
pub fn get_packed_layer_index_if_visible(
|
||||
&self,
|
||||
clip_and_scroll: &ClipAndScrollInfo
|
||||
) -> Option<PackedLayerIndex> {
|
||||
let group_id = self.clip_scroll_group_indices[&clip_and_scroll];
|
||||
let clip_scroll_group = &self.clip_scroll_group_store[group_id];
|
||||
if clip_scroll_group.is_visible() {
|
||||
Some(clip_scroll_group.packed_layer_index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hit_test(
|
||||
&self,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
|
@ -1414,33 +1349,13 @@ impl FrameBuilder {
|
|||
profile_counters: &mut FrameProfileCounters,
|
||||
) -> bool {
|
||||
let stacking_context_index = *self.stacking_context_stack.last().unwrap();
|
||||
let packed_layer_index =
|
||||
match self.get_packed_layer_index_if_visible(&clip_and_scroll) {
|
||||
Some(index) => index,
|
||||
None => {
|
||||
debug!("{:?} of invisible {:?}", base_prim_index, stacking_context_index);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let scroll_node = &clip_scroll_tree.nodes[&clip_and_scroll.scroll_node_id];
|
||||
let clip_node = &clip_scroll_tree.nodes[&clip_and_scroll.clip_node_id()];
|
||||
|
||||
let (clip_chain, clip_bounds, coordinate_system_id) =
|
||||
match clip_scroll_tree.nodes.get(&clip_and_scroll.clip_node_id()) {
|
||||
Some(node) if node.combined_clip_outer_bounds != DeviceIntRect::zero() => {
|
||||
let group_id = self.clip_scroll_group_indices[&clip_and_scroll];
|
||||
(
|
||||
node.clip_chain_node.clone(),
|
||||
node.combined_clip_outer_bounds,
|
||||
self.clip_scroll_group_store[group_id].coordinate_system_id,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let group_id = self.clip_scroll_group_indices[&clip_and_scroll];
|
||||
self.clip_scroll_group_store[group_id].screen_bounding_rect = None;
|
||||
|
||||
debug!("{:?} of clipped out {:?}", base_prim_index, stacking_context_index);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if clip_node.combined_clip_outer_bounds == DeviceIntRect::zero() {
|
||||
debug!("{:?} of clipped out {:?}", base_prim_index, stacking_context_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
let stacking_context = &mut self.stacking_context_store[stacking_context_index.0];
|
||||
let pipeline_id = {
|
||||
|
@ -1455,37 +1370,25 @@ impl FrameBuilder {
|
|||
};
|
||||
|
||||
debug!(
|
||||
"\t{:?} of {:?} at {:?}",
|
||||
"\t{:?} of {:?}",
|
||||
base_prim_index,
|
||||
stacking_context_index,
|
||||
packed_layer_index
|
||||
);
|
||||
|
||||
let packed_layer = &self.packed_layers[packed_layer_index.0];
|
||||
let display_list = &pipelines
|
||||
.get(&pipeline_id)
|
||||
.expect("No display list?")
|
||||
.display_list;
|
||||
|
||||
if !stacking_context.is_backface_visible && packed_layer.transform.is_backface_visible() {
|
||||
if !stacking_context.is_backface_visible && scroll_node.world_content_transform.is_backface_visible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let prim_context = PrimitiveContext::new(
|
||||
packed_layer_index,
|
||||
packed_layer,
|
||||
clip_and_scroll.clip_node_id(),
|
||||
clip_chain,
|
||||
clip_bounds,
|
||||
coordinate_system_id,
|
||||
device_pixel_ratio,
|
||||
display_list,
|
||||
);
|
||||
|
||||
debug!(
|
||||
"\tclip_bounds {:?}, layer_local_clip {:?}",
|
||||
prim_context.clip_bounds,
|
||||
packed_layer.local_clip_rect
|
||||
clip_node,
|
||||
scroll_node,
|
||||
);
|
||||
|
||||
for i in 0 .. prim_count {
|
||||
|
@ -1571,55 +1474,6 @@ impl FrameBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn recalculate_clip_scroll_groups(
|
||||
&mut self,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32
|
||||
) {
|
||||
debug!("recalculate_clip_scroll_groups");
|
||||
for ref mut group in &mut self.clip_scroll_group_store {
|
||||
let scroll_node = &clip_scroll_tree.nodes[&group.scroll_node_id];
|
||||
let clip_node = &clip_scroll_tree.nodes[&group.clip_node_id];
|
||||
let packed_layer = &mut self.packed_layers[group.packed_layer_index.0];
|
||||
|
||||
debug!(
|
||||
"\tProcessing group scroll={:?}, clip={:?}",
|
||||
group.scroll_node_id,
|
||||
group.clip_node_id
|
||||
);
|
||||
|
||||
let transform = scroll_node.world_content_transform;
|
||||
if !packed_layer.set_transform(transform) {
|
||||
group.screen_bounding_rect = None;
|
||||
debug!("\t\tUnable to set transform {:?}", transform);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Here we move the viewport rectangle into the coordinate system
|
||||
// of the stacking context content.
|
||||
let local_viewport_rect = clip_node
|
||||
.combined_local_viewport_rect
|
||||
.translate(&clip_node.reference_frame_relative_scroll_offset)
|
||||
.translate(&-scroll_node.reference_frame_relative_scroll_offset)
|
||||
.translate(&-scroll_node.scroll_offset());
|
||||
|
||||
group.screen_bounding_rect = packed_layer.set_rect(
|
||||
&local_viewport_rect,
|
||||
screen_rect,
|
||||
device_pixel_ratio,
|
||||
);
|
||||
|
||||
group.coordinate_system_id = scroll_node.coordinate_system_id;
|
||||
|
||||
debug!(
|
||||
"\t\tlocal viewport {:?} screen bound {:?}",
|
||||
local_viewport_rect,
|
||||
group.screen_bounding_rect
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the contribution (bounding rectangles, and resources) of layers and their
|
||||
/// primitives in screen space.
|
||||
fn build_layer_screen_rects_and_cull_layers(
|
||||
|
@ -1635,12 +1489,6 @@ impl FrameBuilder {
|
|||
) {
|
||||
profile_scope!("cull");
|
||||
|
||||
self.recalculate_clip_scroll_groups(
|
||||
clip_scroll_tree,
|
||||
screen_rect,
|
||||
device_pixel_ratio
|
||||
);
|
||||
|
||||
debug!("processing commands...");
|
||||
let commands = mem::replace(&mut self.cmds, Vec::new());
|
||||
for cmd in &commands {
|
||||
|
@ -1839,6 +1687,7 @@ impl FrameBuilder {
|
|||
{
|
||||
let mut prev_task = alpha_task_stack.pop().unwrap();
|
||||
let screen_origin = current_task.as_alpha_batch().screen_origin;
|
||||
let current_task_size = current_task.get_dynamic_size();
|
||||
let current_task_id = render_tasks.add(current_task);
|
||||
let item = AlphaRenderItem::HardwareComposite(
|
||||
stacking_context_index,
|
||||
|
@ -1846,6 +1695,7 @@ impl FrameBuilder {
|
|||
HardwareCompositeOp::PremultipliedAlpha,
|
||||
screen_origin,
|
||||
next_z,
|
||||
current_task_size,
|
||||
);
|
||||
next_z += 1;
|
||||
prev_task.as_alpha_batch_mut().items.push(item);
|
||||
|
@ -1883,6 +1733,7 @@ impl FrameBuilder {
|
|||
screen_origin.y - inflate_size as i32,
|
||||
),
|
||||
next_z,
|
||||
render_tasks.get(current_task_id).get_dynamic_size(),
|
||||
);
|
||||
prev_task.as_alpha_batch_mut().items.push(item);
|
||||
prev_task.children.push(blur_render_task_id);
|
||||
|
@ -1973,6 +1824,7 @@ impl FrameBuilder {
|
|||
{
|
||||
let mut prev_task = alpha_task_stack.pop().unwrap();
|
||||
let screen_origin = current_task.as_alpha_batch().screen_origin;
|
||||
let current_task_size = current_task.get_dynamic_size();
|
||||
let current_task_id = render_tasks.add(current_task);
|
||||
let item = AlphaRenderItem::HardwareComposite(
|
||||
stacking_context_index,
|
||||
|
@ -1980,6 +1832,7 @@ impl FrameBuilder {
|
|||
HardwareCompositeOp::PremultipliedAlpha,
|
||||
screen_origin,
|
||||
next_z,
|
||||
current_task_size,
|
||||
);
|
||||
next_z += 1;
|
||||
prev_task.as_alpha_batch_mut().items.push(item);
|
||||
|
@ -1993,19 +1846,11 @@ impl FrameBuilder {
|
|||
continue;
|
||||
}
|
||||
|
||||
let group_id = self.clip_scroll_group_indices[&clip_and_scroll];
|
||||
let group_index = ClipScrollGroupIndex(group_id, clip_and_scroll);
|
||||
|
||||
if self.clip_scroll_group_store[group_id]
|
||||
.screen_bounding_rect
|
||||
.is_none()
|
||||
{
|
||||
debug!("\tcs-group {:?} screen rect is None", group_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
debug!("\trun of {} items", prim_count);
|
||||
|
||||
let scroll_node = &clip_scroll_tree.nodes[&clip_and_scroll.scroll_node_id];
|
||||
let clip_node = &clip_scroll_tree.nodes[&clip_and_scroll.clip_node_id()];
|
||||
|
||||
for i in 0 .. prim_count {
|
||||
let prim_index = PrimitiveIndex(first_prim_index.0 + i);
|
||||
|
||||
|
@ -2013,7 +1858,7 @@ impl FrameBuilder {
|
|||
self.prim_store
|
||||
.add_render_tasks_for_prim(prim_index, &mut current_task);
|
||||
let item =
|
||||
AlphaRenderItem::Primitive(Some(group_index), prim_index, next_z);
|
||||
AlphaRenderItem::Primitive(clip_node.id, scroll_node.id, prim_index, next_z);
|
||||
current_task.as_alpha_batch_mut().items.push(item);
|
||||
next_z += 1;
|
||||
}
|
||||
|
@ -2058,14 +1903,16 @@ impl FrameBuilder {
|
|||
),
|
||||
);
|
||||
|
||||
let mut node_data = Vec::new();
|
||||
|
||||
clip_scroll_tree.update_all_node_transforms(
|
||||
&screen_rect,
|
||||
device_pixel_ratio,
|
||||
&mut self.packed_layers,
|
||||
&mut self.clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
pan
|
||||
pan,
|
||||
&mut node_data,
|
||||
);
|
||||
|
||||
self.update_scroll_bars(clip_scroll_tree, gpu_cache);
|
||||
|
@ -2112,9 +1959,9 @@ impl FrameBuilder {
|
|||
let ctx = RenderTargetContext {
|
||||
device_pixel_ratio,
|
||||
stacking_context_store: &self.stacking_context_store,
|
||||
clip_scroll_group_store: &self.clip_scroll_group_store,
|
||||
prim_store: &self.prim_store,
|
||||
resource_cache,
|
||||
node_data: &node_data,
|
||||
};
|
||||
|
||||
pass.build(
|
||||
|
@ -2146,7 +1993,7 @@ impl FrameBuilder {
|
|||
window_size: self.screen_size,
|
||||
profile_counters,
|
||||
passes,
|
||||
layer_texture_data: self.packed_layers.clone(),
|
||||
node_data,
|
||||
render_tasks,
|
||||
deferred_resolves,
|
||||
gpu_cache_updates: Some(gpu_cache_updates),
|
||||
|
|
|
@ -2,22 +2,12 @@
|
|||
* 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/. */
|
||||
|
||||
use api::LayerRect;
|
||||
use api::{LayerVector2D, LayerRect, LayerToWorldTransform, WorldToLayerTransform};
|
||||
use gpu_cache::GpuCacheAddress;
|
||||
use render_task::RenderTaskAddress;
|
||||
use tiling::PackedLayerIndex;
|
||||
|
||||
// Contains type that must exactly match the same structures declared in GLSL.
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PackedLayerAddress(i32);
|
||||
|
||||
impl From<PackedLayerIndex> for PackedLayerAddress {
|
||||
fn from(index: PackedLayerIndex) -> PackedLayerAddress {
|
||||
PackedLayerAddress(index.0 as i32)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum BlurDirection {
|
||||
|
@ -41,7 +31,7 @@ pub struct BlurInstance {
|
|||
#[repr(C)]
|
||||
pub struct ClipMaskInstance {
|
||||
pub render_task_address: RenderTaskAddress,
|
||||
pub layer_address: PackedLayerAddress,
|
||||
pub scroll_node_id: ClipScrollNodeIndex,
|
||||
pub segment: i32,
|
||||
pub clip_data_address: GpuCacheAddress,
|
||||
pub resource_address: GpuCacheAddress,
|
||||
|
@ -57,7 +47,8 @@ pub struct SimplePrimitiveInstance {
|
|||
pub specific_prim_address: GpuCacheAddress,
|
||||
pub task_address: RenderTaskAddress,
|
||||
pub clip_task_address: RenderTaskAddress,
|
||||
pub layer_address: PackedLayerAddress,
|
||||
pub clip_id: ClipScrollNodeIndex,
|
||||
pub scroll_id: ClipScrollNodeIndex,
|
||||
pub z_sort_index: i32,
|
||||
}
|
||||
|
||||
|
@ -66,14 +57,16 @@ impl SimplePrimitiveInstance {
|
|||
specific_prim_address: GpuCacheAddress,
|
||||
task_address: RenderTaskAddress,
|
||||
clip_task_address: RenderTaskAddress,
|
||||
layer_address: PackedLayerAddress,
|
||||
clip_id: ClipScrollNodeIndex,
|
||||
scroll_id: ClipScrollNodeIndex,
|
||||
z_sort_index: i32,
|
||||
) -> SimplePrimitiveInstance {
|
||||
SimplePrimitiveInstance {
|
||||
specific_prim_address,
|
||||
task_address,
|
||||
clip_task_address,
|
||||
layer_address,
|
||||
clip_id,
|
||||
scroll_id,
|
||||
z_sort_index,
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +77,7 @@ impl SimplePrimitiveInstance {
|
|||
self.specific_prim_address.as_int(),
|
||||
self.task_address.0 as i32,
|
||||
self.clip_task_address.0 as i32,
|
||||
self.layer_address.0,
|
||||
((self.clip_id.0 as i32) << 16) | self.scroll_id.0 as i32,
|
||||
self.z_sort_index,
|
||||
data0,
|
||||
data1,
|
||||
|
@ -101,6 +94,8 @@ pub struct CompositePrimitiveInstance {
|
|||
pub data0: i32,
|
||||
pub data1: i32,
|
||||
pub z: i32,
|
||||
pub data2: i32,
|
||||
pub data3: i32,
|
||||
}
|
||||
|
||||
impl CompositePrimitiveInstance {
|
||||
|
@ -111,6 +106,8 @@ impl CompositePrimitiveInstance {
|
|||
data0: i32,
|
||||
data1: i32,
|
||||
z: i32,
|
||||
data2: i32,
|
||||
data3: i32,
|
||||
) -> CompositePrimitiveInstance {
|
||||
CompositePrimitiveInstance {
|
||||
task_address,
|
||||
|
@ -119,6 +116,8 @@ impl CompositePrimitiveInstance {
|
|||
data0,
|
||||
data1,
|
||||
z,
|
||||
data2,
|
||||
data3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,8 +132,8 @@ impl From<CompositePrimitiveInstance> for PrimitiveInstance {
|
|||
instance.z,
|
||||
instance.data0,
|
||||
instance.data1,
|
||||
0,
|
||||
0,
|
||||
instance.data2,
|
||||
instance.data3,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,8 @@ pub const BRUSH_FLAG_USES_PICTURE: i32 = (1 << 0);
|
|||
pub struct BrushInstance {
|
||||
pub picture_address: RenderTaskAddress,
|
||||
pub prim_address: GpuCacheAddress,
|
||||
pub layer_address: PackedLayerAddress,
|
||||
pub clip_id: ClipScrollNodeIndex,
|
||||
pub scroll_id: ClipScrollNodeIndex,
|
||||
pub clip_task_address: RenderTaskAddress,
|
||||
pub z: i32,
|
||||
pub flags: i32,
|
||||
|
@ -170,7 +170,7 @@ impl From<BrushInstance> for PrimitiveInstance {
|
|||
data: [
|
||||
instance.picture_address.0 as i32,
|
||||
instance.prim_address.as_int(),
|
||||
instance.layer_address.0,
|
||||
((instance.clip_id.0 as i32) << 16) | instance.scroll_id.0 as i32,
|
||||
instance.clip_task_address.0 as i32,
|
||||
instance.z,
|
||||
instance.flags,
|
||||
|
@ -190,3 +190,29 @@ pub enum BrushImageKind {
|
|||
NinePatch = 1, // A nine-patch image (stretch inside segments)
|
||||
Mirror = 2, // A top left corner only (mirror across x/y axes)
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ClipScrollNodeIndex(pub u32);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct ClipScrollNodeData {
|
||||
pub transform: LayerToWorldTransform,
|
||||
pub inv_transform: WorldToLayerTransform,
|
||||
pub local_clip_rect: LayerRect,
|
||||
pub reference_frame_relative_scroll_offset: LayerVector2D,
|
||||
pub scroll_offset: LayerVector2D,
|
||||
}
|
||||
|
||||
impl ClipScrollNodeData {
|
||||
pub fn invalid() -> ClipScrollNodeData {
|
||||
ClipScrollNodeData {
|
||||
transform: LayerToWorldTransform::identity(),
|
||||
inv_transform: WorldToLayerTransform::identity(),
|
||||
local_clip_rect: LayerRect::zero(),
|
||||
reference_frame_relative_scroll_offset: LayerVector2D::zero(),
|
||||
scroll_offset: LayerVector2D::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,9 +287,9 @@ impl FontContext {
|
|||
let length = pixels.len() / 3;
|
||||
let mut bgra_pixels: Vec<u8> = vec![0; length * 4];
|
||||
for i in 0 .. length {
|
||||
bgra_pixels[i * 4 + 0] = pixels[i * 3 + 0];
|
||||
bgra_pixels[i * 4 + 0] = pixels[i * 3 + 2];
|
||||
bgra_pixels[i * 4 + 1] = pixels[i * 3 + 1];
|
||||
bgra_pixels[i * 4 + 2] = pixels[i * 3 + 2];
|
||||
bgra_pixels[i * 4 + 2] = pixels[i * 3 + 0];
|
||||
bgra_pixels[i * 4 + 3] = 0xff;
|
||||
}
|
||||
bgra_pixels
|
||||
|
|
|
@ -18,7 +18,7 @@ use renderer::MAX_VERTEX_TEXTURE_WIDTH;
|
|||
use resource_cache::{ImageProperties, ResourceCache};
|
||||
use std::{mem, usize};
|
||||
use std::rc::Rc;
|
||||
use util::{MatrixHelpers, pack_as_float, recycle_vec, TransformedRect};
|
||||
use util::{pack_as_float, recycle_vec, MatrixHelpers, TransformedRect, TransformedRectKind};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PrimitiveOpacity {
|
||||
|
@ -1209,8 +1209,10 @@ impl PrimitiveStore {
|
|||
clip_store: &mut ClipStore,
|
||||
) -> bool {
|
||||
let metadata = &mut self.cpu_metadata[prim_index.0];
|
||||
let transform = &prim_context.scroll_node.world_content_transform;
|
||||
|
||||
clip_store.get_mut(&metadata.clip_sources).update(
|
||||
&prim_context.packed_layer.transform,
|
||||
transform,
|
||||
gpu_cache,
|
||||
resource_cache,
|
||||
prim_context.device_pixel_ratio,
|
||||
|
@ -1218,8 +1220,9 @@ impl PrimitiveStore {
|
|||
|
||||
// Try to create a mask if we may need to.
|
||||
let prim_clips = clip_store.get(&metadata.clip_sources);
|
||||
let is_axis_aligned = prim_context.packed_layer.transform.preserves_2d_axis_alignment();
|
||||
let clip_task = if prim_context.clip_chain.is_some() || prim_clips.is_masking() {
|
||||
let is_axis_aligned = transform.transform_kind() == TransformedRectKind::AxisAligned;
|
||||
|
||||
let clip_task = if prim_context.clip_node.clip_chain_node.is_some() || prim_clips.is_masking() {
|
||||
// Take into account the actual clip info of the primitive, and
|
||||
// mutate the current bounds accordingly.
|
||||
let mask_rect = match prim_clips.bounds.outer {
|
||||
|
@ -1236,9 +1239,9 @@ impl PrimitiveStore {
|
|||
let extra_clip = if prim_clips.is_masking() {
|
||||
Some(Rc::new(ClipChainNode {
|
||||
work_item: ClipWorkItem {
|
||||
layer_index: prim_context.packed_layer_index,
|
||||
scroll_node_id: prim_context.scroll_node.id,
|
||||
clip_sources: metadata.clip_sources.weak(),
|
||||
coordinate_system_id: prim_context.coordinate_system_id,
|
||||
coordinate_system_id: prim_context.scroll_node.coordinate_system_id,
|
||||
},
|
||||
prev: None,
|
||||
}))
|
||||
|
@ -1249,12 +1252,12 @@ impl PrimitiveStore {
|
|||
RenderTask::new_mask(
|
||||
None,
|
||||
mask_rect,
|
||||
prim_context.clip_chain.clone(),
|
||||
prim_context.clip_node.clip_chain_node.clone(),
|
||||
extra_clip,
|
||||
prim_screen_rect,
|
||||
clip_store,
|
||||
is_axis_aligned,
|
||||
prim_context.coordinate_system_id,
|
||||
prim_context.scroll_node.coordinate_system_id,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
@ -1284,14 +1287,13 @@ impl PrimitiveStore {
|
|||
}
|
||||
|
||||
if !metadata.is_backface_visible &&
|
||||
prim_context.packed_layer.transform.is_backface_visible() {
|
||||
prim_context.scroll_node.world_content_transform.is_backface_visible() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let local_rect = metadata
|
||||
.local_rect
|
||||
.intersection(&metadata.local_clip_rect)
|
||||
.and_then(|rect| rect.intersection(&prim_context.packed_layer.local_clip_rect));
|
||||
.intersection(&metadata.local_clip_rect);
|
||||
|
||||
let local_rect = match local_rect {
|
||||
Some(local_rect) => local_rect,
|
||||
|
@ -1300,13 +1302,13 @@ impl PrimitiveStore {
|
|||
|
||||
let xf_rect = TransformedRect::new(
|
||||
&local_rect,
|
||||
&prim_context.packed_layer.transform,
|
||||
&prim_context.scroll_node.world_content_transform,
|
||||
prim_context.device_pixel_ratio
|
||||
);
|
||||
|
||||
metadata.screen_rect = xf_rect
|
||||
.bounding_rect
|
||||
.intersection(&prim_context.clip_bounds);
|
||||
let clip_bounds = &prim_context.clip_node.combined_clip_outer_bounds;
|
||||
metadata.screen_rect = xf_rect.bounding_rect
|
||||
.intersection(clip_bounds);
|
||||
|
||||
let geometry = match metadata.screen_rect {
|
||||
Some(device_rect) => Geometry {
|
||||
|
|
|
@ -326,19 +326,21 @@ impl FrameProfileCounters {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct TextureCacheProfileCounters {
|
||||
pub pages_a8: ResourceProfileCounter,
|
||||
pub pages_rgb8: ResourceProfileCounter,
|
||||
pub pages_rgba8: ResourceProfileCounter,
|
||||
pub pages_rg8: ResourceProfileCounter,
|
||||
pub pages_a8_linear: ResourceProfileCounter,
|
||||
pub pages_rgb8_linear: ResourceProfileCounter,
|
||||
pub pages_rgba8_linear: ResourceProfileCounter,
|
||||
pub pages_rgba8_nearest: ResourceProfileCounter,
|
||||
pub pages_rg8_linear: ResourceProfileCounter,
|
||||
}
|
||||
|
||||
impl TextureCacheProfileCounters {
|
||||
pub fn new() -> Self {
|
||||
TextureCacheProfileCounters {
|
||||
pages_a8: ResourceProfileCounter::new("Texture A8 cached pages"),
|
||||
pages_rgb8: ResourceProfileCounter::new("Texture RGB8 cached pages"),
|
||||
pages_rgba8: ResourceProfileCounter::new("Texture RGBA8 cached pages"),
|
||||
pages_rg8: ResourceProfileCounter::new("Texture RG8 cached pages"),
|
||||
pages_a8_linear: ResourceProfileCounter::new("Texture A8 cached pages"),
|
||||
pages_rgb8_linear: ResourceProfileCounter::new("Texture RGB8 cached pages"),
|
||||
pages_rgba8_linear: ResourceProfileCounter::new("Texture RGBA8 cached pages (L)"),
|
||||
pages_rgba8_nearest: ResourceProfileCounter::new("Texture RGBA8 cached pages (N)"),
|
||||
pages_rg8_linear: ResourceProfileCounter::new("Texture RG8 cached pages"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -842,10 +844,11 @@ impl Profiler {
|
|||
|
||||
self.draw_counters(
|
||||
&[
|
||||
&backend_profile.resources.texture_cache.pages_a8,
|
||||
&backend_profile.resources.texture_cache.pages_rgb8,
|
||||
&backend_profile.resources.texture_cache.pages_rgba8,
|
||||
&backend_profile.resources.texture_cache.pages_rg8,
|
||||
&backend_profile.resources.texture_cache.pages_a8_linear,
|
||||
&backend_profile.resources.texture_cache.pages_rgb8_linear,
|
||||
&backend_profile.resources.texture_cache.pages_rgba8_linear,
|
||||
&backend_profile.resources.texture_cache.pages_rgba8_nearest,
|
||||
&backend_profile.resources.texture_cache.pages_rg8_linear,
|
||||
&backend_profile.ipc.display_lists,
|
||||
],
|
||||
debug_renderer,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
use api::ApiMsg;
|
||||
use api::{ApiMsg, DocumentMsg};
|
||||
use bincode::{serialize, Infinite};
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use std::any::TypeId;
|
||||
|
@ -65,8 +65,14 @@ pub fn should_record_msg(msg: &ApiMsg) -> bool {
|
|||
match *msg {
|
||||
ApiMsg::UpdateResources(..) |
|
||||
ApiMsg::AddDocument { .. } |
|
||||
ApiMsg::UpdateDocument(..) |
|
||||
ApiMsg::DeleteDocument(..) => true,
|
||||
ApiMsg::UpdateDocument(_, ref msg) => {
|
||||
match *msg {
|
||||
DocumentMsg::GetScrollNodeState(..) |
|
||||
DocumentMsg::HitTest(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@ use api::{LayerRect, PipelineId};
|
|||
use clip::{ClipSource, ClipSourcesWeakHandle, ClipStore};
|
||||
use clip_scroll_tree::CoordinateSystemId;
|
||||
use gpu_cache::GpuCacheHandle;
|
||||
use gpu_types::{ClipScrollNodeIndex};
|
||||
use internal_types::HardwareCompositeOp;
|
||||
use prim_store::PrimitiveIndex;
|
||||
use std::{cmp, usize, f32, i32};
|
||||
use std::rc::Rc;
|
||||
use tiling::{ClipScrollGroupIndex, PackedLayerIndex, RenderPass, RenderTargetIndex};
|
||||
use tiling::{RenderPass, RenderTargetIndex};
|
||||
use tiling::{RenderTargetKind, StackingContextIndex};
|
||||
|
||||
const FLOATS_PER_RENDER_TASK_INFO: usize = 12;
|
||||
|
@ -151,7 +152,7 @@ pub enum RenderTaskLocation {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum AlphaRenderItem {
|
||||
Primitive(Option<ClipScrollGroupIndex>, PrimitiveIndex, i32),
|
||||
Primitive(ClipScrollNodeIndex, ClipScrollNodeIndex, PrimitiveIndex, i32),
|
||||
Blend(StackingContextIndex, RenderTaskId, FilterOp, i32),
|
||||
Composite(
|
||||
StackingContextIndex,
|
||||
|
@ -167,6 +168,7 @@ pub enum AlphaRenderItem {
|
|||
HardwareCompositeOp,
|
||||
DeviceIntPoint,
|
||||
i32,
|
||||
DeviceIntSize,
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -200,7 +202,7 @@ pub enum MaskGeometryKind {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClipWorkItem {
|
||||
pub layer_index: PackedLayerIndex,
|
||||
pub scroll_node_id: ClipScrollNodeIndex,
|
||||
pub clip_sources: ClipSourcesWeakHandle,
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
}
|
||||
|
@ -268,6 +270,7 @@ pub struct BlurTask {
|
|||
pub target_kind: RenderTargetKind,
|
||||
pub regions: Vec<LayerRect>,
|
||||
pub color: ColorF,
|
||||
pub scale_factor: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -284,6 +287,7 @@ pub enum RenderTaskKind {
|
|||
HorizontalBlur(BlurTask),
|
||||
Readback(DeviceIntRect),
|
||||
Alias(RenderTaskId),
|
||||
Scaling(RenderTargetKind),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -447,14 +451,17 @@ impl RenderTask {
|
|||
})
|
||||
}
|
||||
|
||||
// Construct a render task to apply a blur to a primitive. For now,
|
||||
// this is only used for text runs, but we can probably extend this
|
||||
// to handle general blurs to any render task in the future.
|
||||
// Construct a render task to apply a blur to a primitive.
|
||||
// The render task chain that is constructed looks like:
|
||||
//
|
||||
// PrimitiveCacheTask: Draw the text run.
|
||||
// PrimitiveCacheTask: Draw the primitives.
|
||||
// ^
|
||||
// |
|
||||
// DownscalingTask(s): Each downscaling task reduces the size of render target to
|
||||
// ^ half. Also reduce the std deviation to half until the std
|
||||
// | deviation less than 4.0.
|
||||
// |
|
||||
// |
|
||||
// VerticalBlurTask: Apply the separable vertical blur to the primitive.
|
||||
// ^
|
||||
// |
|
||||
|
@ -471,17 +478,41 @@ impl RenderTask {
|
|||
clear_mode: ClearMode,
|
||||
color: ColorF,
|
||||
) -> RenderTask {
|
||||
// Adjust large std deviation value.
|
||||
const MAX_BLUR_STD_DEVIATION: f32 = 4.0;
|
||||
const MIN_DOWNSCALING_RT_SIZE: i32 = 128;
|
||||
let mut adjusted_blur_std_deviation = blur_std_deviation;
|
||||
let blur_target_size = render_tasks.get(src_task_id).get_dynamic_size();
|
||||
let mut adjusted_blur_target_size = blur_target_size;
|
||||
let mut downscaling_src_task_id = src_task_id;
|
||||
let mut scale_factor = 1.0;
|
||||
while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
|
||||
if adjusted_blur_target_size.width < MIN_DOWNSCALING_RT_SIZE ||
|
||||
adjusted_blur_target_size.height < MIN_DOWNSCALING_RT_SIZE {
|
||||
break;
|
||||
}
|
||||
adjusted_blur_std_deviation *= 0.5;
|
||||
scale_factor *= 2.0;
|
||||
adjusted_blur_target_size = (blur_target_size.to_f32() / scale_factor).to_i32();
|
||||
let downscaling_task = RenderTask::new_scaling(
|
||||
target_kind,
|
||||
downscaling_src_task_id,
|
||||
adjusted_blur_target_size
|
||||
);
|
||||
downscaling_src_task_id = render_tasks.add(downscaling_task);
|
||||
}
|
||||
scale_factor = blur_target_size.width as f32 / adjusted_blur_target_size.width as f32;
|
||||
|
||||
let blur_task_v = RenderTask {
|
||||
cache_key: None,
|
||||
children: vec![src_task_id],
|
||||
location: RenderTaskLocation::Dynamic(None, blur_target_size),
|
||||
children: vec![downscaling_src_task_id],
|
||||
location: RenderTaskLocation::Dynamic(None, adjusted_blur_target_size),
|
||||
kind: RenderTaskKind::VerticalBlur(BlurTask {
|
||||
blur_std_deviation,
|
||||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
regions: regions.to_vec(),
|
||||
color,
|
||||
scale_factor,
|
||||
}),
|
||||
clear_mode,
|
||||
};
|
||||
|
@ -491,12 +522,13 @@ impl RenderTask {
|
|||
let blur_task_h = RenderTask {
|
||||
cache_key: None,
|
||||
children: vec![blur_task_v_id],
|
||||
location: RenderTaskLocation::Dynamic(None, blur_target_size),
|
||||
location: RenderTaskLocation::Dynamic(None, adjusted_blur_target_size),
|
||||
kind: RenderTaskKind::HorizontalBlur(BlurTask {
|
||||
blur_std_deviation,
|
||||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
regions: regions.to_vec(),
|
||||
color,
|
||||
scale_factor,
|
||||
}),
|
||||
clear_mode,
|
||||
};
|
||||
|
@ -504,6 +536,23 @@ impl RenderTask {
|
|||
blur_task_h
|
||||
}
|
||||
|
||||
pub fn new_scaling(
|
||||
target_kind: RenderTargetKind,
|
||||
src_task_id: RenderTaskId,
|
||||
target_size: DeviceIntSize,
|
||||
) -> RenderTask {
|
||||
RenderTask {
|
||||
cache_key: None,
|
||||
children: vec![src_task_id],
|
||||
location: RenderTaskLocation::Dynamic(None, target_size),
|
||||
kind: RenderTaskKind::Scaling(target_kind),
|
||||
clear_mode: match target_kind {
|
||||
RenderTargetKind::Color => ClearMode::Transparent,
|
||||
RenderTargetKind::Alpha => ClearMode::One,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_alpha_batch_mut<'a>(&'a mut self) -> &'a mut AlphaRenderTask {
|
||||
match self.kind {
|
||||
RenderTaskKind::Alpha(ref mut task) => task,
|
||||
|
@ -512,7 +561,8 @@ impl RenderTask {
|
|||
RenderTaskKind::VerticalBlur(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Alias(..) => unreachable!(),
|
||||
RenderTaskKind::Alias(..) |
|
||||
RenderTaskKind::Scaling(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,7 +574,8 @@ impl RenderTask {
|
|||
RenderTaskKind::VerticalBlur(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Alias(..) => unreachable!(),
|
||||
RenderTaskKind::Alias(..) |
|
||||
RenderTaskKind::Scaling(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,7 +660,7 @@ impl RenderTask {
|
|||
target_rect.size.height as f32,
|
||||
target_index.0 as f32,
|
||||
task_info.blur_std_deviation,
|
||||
0.0,
|
||||
task_info.scale_factor,
|
||||
0.0,
|
||||
task_info.color.r,
|
||||
task_info.color.g,
|
||||
|
@ -618,7 +669,8 @@ impl RenderTask {
|
|||
],
|
||||
}
|
||||
}
|
||||
RenderTaskKind::Readback(..) => {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
let (target_rect, target_index) = self.get_target_rect();
|
||||
RenderTaskData {
|
||||
data: [
|
||||
|
@ -662,7 +714,8 @@ impl RenderTask {
|
|||
RenderTaskKind::VerticalBlur(..) |
|
||||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::Alias(..) => {
|
||||
RenderTaskKind::Alias(..) |
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
panic!("bug: inflate only supported for alpha tasks");
|
||||
}
|
||||
}
|
||||
|
@ -700,6 +753,10 @@ impl RenderTask {
|
|||
task_info.target_kind
|
||||
}
|
||||
|
||||
RenderTaskKind::Scaling(target_kind) => {
|
||||
target_kind
|
||||
}
|
||||
|
||||
RenderTaskKind::Picture(ref task_info) => {
|
||||
task_info.target_kind
|
||||
}
|
||||
|
@ -722,7 +779,8 @@ impl RenderTask {
|
|||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::VerticalBlur(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::HorizontalBlur(..) => false,
|
||||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Scaling(..) => false,
|
||||
|
||||
RenderTaskKind::CacheMask(..) => true,
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//! [renderer]: struct.Renderer.html
|
||||
|
||||
use api::{channel, BlobImageRenderer, FontRenderMode};
|
||||
use api::{ColorF, Epoch, PipelineId, RenderApiSender, RenderNotifier};
|
||||
use api::{ColorF, ColorU, Epoch, PipelineId, RenderApiSender, RenderNotifier};
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
|
||||
use api::{ExternalImageId, ExternalImageType, ImageFormat};
|
||||
use api::{YUV_COLOR_SPACES, YUV_FORMATS};
|
||||
|
@ -62,7 +62,7 @@ use std::thread;
|
|||
use texture_cache::TextureCache;
|
||||
use thread_profiler::{register_thread_with_profiler, write_profile};
|
||||
use tiling::{AlphaRenderTarget, ColorRenderTarget, RenderTargetKind};
|
||||
use tiling::{BatchKey, BatchKind, BrushBatchKind, Frame, RenderTarget, TransformBatchKind};
|
||||
use tiling::{BatchKey, BatchKind, BrushBatchKind, Frame, RenderTarget, ScalingInfo, TransformBatchKind};
|
||||
use time::precise_time_ns;
|
||||
use util::TransformedRectKind;
|
||||
|
||||
|
@ -221,12 +221,13 @@ type ShaderMode = i32;
|
|||
#[repr(C)]
|
||||
enum TextShaderMode {
|
||||
Alpha = 0,
|
||||
SubpixelPass0 = 1,
|
||||
SubpixelPass1 = 2,
|
||||
SubpixelWithBgColorPass0 = 3,
|
||||
SubpixelWithBgColorPass1 = 4,
|
||||
SubpixelWithBgColorPass2 = 5,
|
||||
ColorBitmap = 6,
|
||||
SubpixelOpaque = 1,
|
||||
SubpixelPass0 = 2,
|
||||
SubpixelPass1 = 3,
|
||||
SubpixelWithBgColorPass0 = 4,
|
||||
SubpixelWithBgColorPass1 = 5,
|
||||
SubpixelWithBgColorPass2 = 6,
|
||||
ColorBitmap = 7,
|
||||
}
|
||||
|
||||
impl Into<ShaderMode> for TextShaderMode {
|
||||
|
@ -255,7 +256,7 @@ enum TextureSampler {
|
|||
CacheA8,
|
||||
CacheRGBA8,
|
||||
ResourceCache,
|
||||
Layers,
|
||||
ClipScrollNodes,
|
||||
RenderTasks,
|
||||
Dither,
|
||||
// A special sampler that is bound to the A8 output of
|
||||
|
@ -286,7 +287,7 @@ impl Into<TextureSlot> for TextureSampler {
|
|||
TextureSampler::CacheA8 => TextureSlot(3),
|
||||
TextureSampler::CacheRGBA8 => TextureSlot(4),
|
||||
TextureSampler::ResourceCache => TextureSlot(5),
|
||||
TextureSampler::Layers => TextureSlot(6),
|
||||
TextureSampler::ClipScrollNodes => TextureSlot(6),
|
||||
TextureSampler::RenderTasks => TextureSlot(7),
|
||||
TextureSampler::Dither => TextureSlot(8),
|
||||
TextureSampler::SharedCacheA8 => TextureSlot(9),
|
||||
|
@ -640,7 +641,8 @@ pub enum BlendMode {
|
|||
Alpha,
|
||||
PremultipliedAlpha,
|
||||
PremultipliedDestOut,
|
||||
Subpixel,
|
||||
SubpixelOpaque(ColorU),
|
||||
SubpixelWithAlpha,
|
||||
SubpixelWithBgColor,
|
||||
}
|
||||
|
||||
|
@ -1013,7 +1015,8 @@ impl BrushShader {
|
|||
BlendMode::Alpha |
|
||||
BlendMode::PremultipliedAlpha |
|
||||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::Subpixel |
|
||||
BlendMode::SubpixelOpaque(..) |
|
||||
BlendMode::SubpixelWithAlpha |
|
||||
BlendMode::SubpixelWithBgColor => {
|
||||
self.alpha.bind(device, projection, mode, renderer_errors)
|
||||
}
|
||||
|
@ -1126,7 +1129,7 @@ fn create_prim_shader(
|
|||
("sDither", TextureSampler::Dither),
|
||||
("sCacheA8", TextureSampler::CacheA8),
|
||||
("sCacheRGBA8", TextureSampler::CacheRGBA8),
|
||||
("sLayers", TextureSampler::Layers),
|
||||
("sClipScrollNodes", TextureSampler::ClipScrollNodes),
|
||||
("sRenderTasks", TextureSampler::RenderTasks),
|
||||
("sResourceCache", TextureSampler::ResourceCache),
|
||||
("sSharedCacheA8", TextureSampler::SharedCacheA8),
|
||||
|
@ -1153,7 +1156,7 @@ fn create_clip_shader(name: &'static str, device: &mut Device) -> Result<Program
|
|||
program,
|
||||
&[
|
||||
("sColor0", TextureSampler::Color0),
|
||||
("sLayers", TextureSampler::Layers),
|
||||
("sClipScrollNodes", TextureSampler::ClipScrollNodes),
|
||||
("sRenderTasks", TextureSampler::RenderTasks),
|
||||
("sResourceCache", TextureSampler::ResourceCache),
|
||||
("sSharedCacheA8", TextureSampler::SharedCacheA8),
|
||||
|
@ -1254,7 +1257,7 @@ pub struct Renderer {
|
|||
blur_vao: VAO,
|
||||
clip_vao: VAO,
|
||||
|
||||
layer_texture: VertexDataTexture,
|
||||
node_data_texture: VertexDataTexture,
|
||||
render_task_texture: VertexDataTexture,
|
||||
gpu_cache_texture: CacheTexture,
|
||||
|
||||
|
@ -1760,7 +1763,7 @@ impl Renderer {
|
|||
|
||||
let texture_resolver = SourceTextureResolver::new(&mut device);
|
||||
|
||||
let layer_texture = VertexDataTexture::new(&mut device);
|
||||
let node_data_texture = VertexDataTexture::new(&mut device);
|
||||
let render_task_texture = VertexDataTexture::new(&mut device);
|
||||
|
||||
device.end_frame();
|
||||
|
@ -1868,7 +1871,7 @@ impl Renderer {
|
|||
prim_vao,
|
||||
blur_vao,
|
||||
clip_vao,
|
||||
layer_texture,
|
||||
node_data_texture,
|
||||
render_task_texture,
|
||||
pipeline_epoch_map: FastHashMap::default(),
|
||||
dither_matrix_texture,
|
||||
|
@ -2492,7 +2495,8 @@ impl Renderer {
|
|||
BlendMode::Alpha |
|
||||
BlendMode::PremultipliedAlpha |
|
||||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::Subpixel |
|
||||
BlendMode::SubpixelOpaque(..) |
|
||||
BlendMode::SubpixelWithAlpha |
|
||||
BlendMode::SubpixelWithBgColor => true,
|
||||
BlendMode::None => false,
|
||||
}
|
||||
|
@ -2689,6 +2693,30 @@ impl Renderer {
|
|||
self.draw_instanced_batch(instances, VertexArrayKind::Primitive, &key.textures);
|
||||
}
|
||||
|
||||
fn handle_scaling(
|
||||
&mut self,
|
||||
render_tasks: &RenderTaskTree,
|
||||
scalings: &Vec<ScalingInfo>,
|
||||
source: SourceTexture,
|
||||
) {
|
||||
let cache_texture = self.texture_resolver
|
||||
.resolve(&source)
|
||||
.unwrap();
|
||||
for scaling in scalings {
|
||||
let source = render_tasks.get(scaling.src_task_id);
|
||||
let dest = render_tasks.get(scaling.dest_task_id);
|
||||
|
||||
let (source_rect, source_layer) = source.get_target_rect();
|
||||
let (dest_rect, _) = dest.get_target_rect();
|
||||
|
||||
let cache_draw_target = (cache_texture, source_layer.0 as i32);
|
||||
self.device
|
||||
.bind_read_target(Some(cache_draw_target));
|
||||
|
||||
self.device.blit_render_target(source_rect, dest_rect);
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_color_target(
|
||||
&mut self,
|
||||
render_target: Option<(&Texture, i32)>,
|
||||
|
@ -2755,6 +2783,8 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
self.handle_scaling(render_tasks, &target.scalings, SourceTexture::CacheRGBA8);
|
||||
|
||||
// Draw any textrun caches for this target. For now, this
|
||||
// is only used to cache text runs that are to be blurred
|
||||
// for shadow support. In the future it may be worth
|
||||
|
@ -2832,12 +2862,13 @@ impl Renderer {
|
|||
for batch in &target.alpha_batcher.batch_list.alpha_batch_list.batches {
|
||||
if self.debug_flags.contains(DebugFlags::ALPHA_PRIM_DBG) {
|
||||
let color = match batch.key.blend_mode {
|
||||
BlendMode::None => ColorF::new(0.3, 0.3, 0.3, 1.0),
|
||||
BlendMode::Alpha => ColorF::new(0.0, 0.9, 0.1, 1.0),
|
||||
BlendMode::PremultipliedAlpha => ColorF::new(0.0, 0.3, 0.7, 1.0),
|
||||
BlendMode::PremultipliedDestOut => ColorF::new(0.6, 0.2, 0.0, 1.0),
|
||||
BlendMode::Subpixel => ColorF::new(0.5, 0.0, 0.4, 1.0),
|
||||
BlendMode::SubpixelWithBgColor => ColorF::new(0.6, 0.0, 0.5, 1.0),
|
||||
BlendMode::None => debug_colors::BLACK,
|
||||
BlendMode::Alpha => debug_colors::YELLOW,
|
||||
BlendMode::PremultipliedAlpha => debug_colors::GREY,
|
||||
BlendMode::PremultipliedDestOut => debug_colors::SALMON,
|
||||
BlendMode::SubpixelOpaque(..) => debug_colors::GREEN,
|
||||
BlendMode::SubpixelWithAlpha => debug_colors::RED,
|
||||
BlendMode::SubpixelWithBgColor => debug_colors::BLUE,
|
||||
}.into();
|
||||
for item_rect in &batch.item_rects {
|
||||
self.debug.add_rect(item_rect, color);
|
||||
|
@ -2875,7 +2906,24 @@ impl Renderer {
|
|||
&batch.key.textures
|
||||
);
|
||||
}
|
||||
BlendMode::Subpixel => {
|
||||
BlendMode::SubpixelOpaque(color) => {
|
||||
self.device.set_blend_mode_subpixel_opaque(color.into());
|
||||
|
||||
self.ps_text_run.bind(
|
||||
&mut self.device,
|
||||
transform_kind,
|
||||
projection,
|
||||
TextShaderMode::SubpixelOpaque,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
|
||||
self.draw_instanced_batch(
|
||||
&batch.instances,
|
||||
VertexArrayKind::Primitive,
|
||||
&batch.key.textures
|
||||
);
|
||||
}
|
||||
BlendMode::SubpixelWithAlpha => {
|
||||
// Using the two pass component alpha rendering technique:
|
||||
//
|
||||
// http://anholt.livejournal.com/32058.html
|
||||
|
@ -2991,7 +3039,9 @@ impl Renderer {
|
|||
self.device.set_blend(true);
|
||||
self.device.set_blend_mode_premultiplied_dest_out();
|
||||
}
|
||||
BlendMode::Subpixel | BlendMode::SubpixelWithBgColor => {
|
||||
BlendMode::SubpixelOpaque(..) |
|
||||
BlendMode::SubpixelWithAlpha |
|
||||
BlendMode::SubpixelWithBgColor => {
|
||||
unreachable!("bug: subpx text handled earlier");
|
||||
}
|
||||
}
|
||||
|
@ -3114,6 +3164,8 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
self.handle_scaling(render_tasks, &target.scalings, SourceTexture::CacheA8);
|
||||
|
||||
if !target.brush_mask_corners.is_empty() {
|
||||
self.device.set_blend(false);
|
||||
|
||||
|
@ -3349,7 +3401,7 @@ impl Renderer {
|
|||
pass.max_alpha_target_size.width,
|
||||
pass.max_alpha_target_size.height,
|
||||
ImageFormat::A8,
|
||||
TextureFilter::Nearest,
|
||||
TextureFilter::Linear,
|
||||
RenderTargetMode::RenderTarget,
|
||||
alpha_target_count as i32,
|
||||
None,
|
||||
|
@ -3357,13 +3409,13 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
self.layer_texture
|
||||
.update(&mut self.device, &mut frame.layer_texture_data);
|
||||
self.node_data_texture
|
||||
.update(&mut self.device, &mut frame.node_data);
|
||||
self.device
|
||||
.bind_texture(TextureSampler::ClipScrollNodes, &self.node_data_texture.texture);
|
||||
|
||||
self.render_task_texture
|
||||
.update(&mut self.device, &mut frame.render_tasks.task_data);
|
||||
|
||||
self.device
|
||||
.bind_texture(TextureSampler::Layers, &self.layer_texture.texture);
|
||||
self.device.bind_texture(
|
||||
TextureSampler::RenderTasks,
|
||||
&self.render_task_texture.texture,
|
||||
|
@ -3669,7 +3721,7 @@ impl Renderer {
|
|||
if let Some(dither_matrix_texture) = self.dither_matrix_texture {
|
||||
self.device.delete_texture(dither_matrix_texture);
|
||||
}
|
||||
self.layer_texture.deinit(&mut self.device);
|
||||
self.node_data_texture.deinit(&mut self.device);
|
||||
self.render_task_texture.deinit(&mut self.device);
|
||||
for texture in self.alpha_render_targets {
|
||||
self.device.delete_texture(texture);
|
||||
|
|
|
@ -18,7 +18,8 @@ use std::mem;
|
|||
|
||||
// The fixed number of layers for the shared texture cache.
|
||||
// There is one array texture per image format, allocated lazily.
|
||||
const TEXTURE_ARRAY_LAYERS: i32 = 4;
|
||||
const TEXTURE_ARRAY_LAYERS_LINEAR: usize = 4;
|
||||
const TEXTURE_ARRAY_LAYERS_NEAREST: usize = 1;
|
||||
|
||||
// The dimensions of each layer in the texture cache.
|
||||
const TEXTURE_LAYER_DIMENSIONS: u32 = 2048;
|
||||
|
@ -91,6 +92,7 @@ struct CacheEntry {
|
|||
uv_rect_handle: GpuCacheHandle,
|
||||
// Image format of the item.
|
||||
format: ImageFormat,
|
||||
filter: TextureFilter,
|
||||
// The actual device texture ID this is part of.
|
||||
texture_id: CacheTextureId,
|
||||
}
|
||||
|
@ -101,6 +103,7 @@ impl CacheEntry {
|
|||
texture_id: CacheTextureId,
|
||||
size: DeviceUintSize,
|
||||
format: ImageFormat,
|
||||
filter: TextureFilter,
|
||||
user_data: [f32; 3],
|
||||
last_access: FrameId,
|
||||
) -> CacheEntry {
|
||||
|
@ -111,6 +114,7 @@ impl CacheEntry {
|
|||
kind: EntryKind::Standalone,
|
||||
texture_id,
|
||||
format,
|
||||
filter,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
}
|
||||
}
|
||||
|
@ -164,10 +168,11 @@ pub struct TextureCache {
|
|||
// each format the texture cache supports.
|
||||
// TODO(gw): Do we actually need RG8 and RGB8 or
|
||||
// are they only used by external textures?
|
||||
array_a8: TextureArray,
|
||||
array_rgba8: TextureArray,
|
||||
array_rg8: TextureArray,
|
||||
array_rgb8: TextureArray,
|
||||
array_rgba8_nearest: TextureArray,
|
||||
array_a8_linear: TextureArray,
|
||||
array_rgba8_linear: TextureArray,
|
||||
array_rg8_linear: TextureArray,
|
||||
array_rgb8_linear: TextureArray,
|
||||
|
||||
// Maximum texture size supported by hardware.
|
||||
max_texture_size: u32,
|
||||
|
@ -204,10 +209,31 @@ impl TextureCache {
|
|||
pub fn new(max_texture_size: u32) -> TextureCache {
|
||||
TextureCache {
|
||||
max_texture_size,
|
||||
array_a8: TextureArray::new(ImageFormat::A8),
|
||||
array_rgba8: TextureArray::new(ImageFormat::BGRA8),
|
||||
array_rg8: TextureArray::new(ImageFormat::RG8),
|
||||
array_rgb8: TextureArray::new(ImageFormat::RGB8),
|
||||
array_a8_linear: TextureArray::new(
|
||||
ImageFormat::A8,
|
||||
TextureFilter::Linear,
|
||||
TEXTURE_ARRAY_LAYERS_LINEAR,
|
||||
),
|
||||
array_rgba8_linear: TextureArray::new(
|
||||
ImageFormat::BGRA8,
|
||||
TextureFilter::Linear,
|
||||
TEXTURE_ARRAY_LAYERS_LINEAR,
|
||||
),
|
||||
array_rg8_linear: TextureArray::new(
|
||||
ImageFormat::RG8,
|
||||
TextureFilter::Linear,
|
||||
TEXTURE_ARRAY_LAYERS_LINEAR,
|
||||
),
|
||||
array_rgb8_linear: TextureArray::new(
|
||||
ImageFormat::RGB8,
|
||||
TextureFilter::Linear,
|
||||
TEXTURE_ARRAY_LAYERS_LINEAR,
|
||||
),
|
||||
array_rgba8_nearest: TextureArray::new(
|
||||
ImageFormat::BGRA8,
|
||||
TextureFilter::Nearest,
|
||||
TEXTURE_ARRAY_LAYERS_NEAREST
|
||||
),
|
||||
cache_textures: CacheTextureIdList::new(),
|
||||
pending_updates: TextureUpdateList::new(),
|
||||
frame_id: FrameId(0),
|
||||
|
@ -224,14 +250,16 @@ impl TextureCache {
|
|||
pub fn end_frame(&mut self, texture_cache_profile: &mut TextureCacheProfileCounters) {
|
||||
self.expire_old_standalone_entries();
|
||||
|
||||
self.array_a8
|
||||
.update_profile(&mut texture_cache_profile.pages_a8);
|
||||
self.array_rg8
|
||||
.update_profile(&mut texture_cache_profile.pages_rg8);
|
||||
self.array_rgb8
|
||||
.update_profile(&mut texture_cache_profile.pages_rgb8);
|
||||
self.array_rgba8
|
||||
.update_profile(&mut texture_cache_profile.pages_rgba8);
|
||||
self.array_a8_linear
|
||||
.update_profile(&mut texture_cache_profile.pages_a8_linear);
|
||||
self.array_rg8_linear
|
||||
.update_profile(&mut texture_cache_profile.pages_rg8_linear);
|
||||
self.array_rgb8_linear
|
||||
.update_profile(&mut texture_cache_profile.pages_rgb8_linear);
|
||||
self.array_rgba8_linear
|
||||
.update_profile(&mut texture_cache_profile.pages_rgba8_linear);
|
||||
self.array_rgba8_nearest
|
||||
.update_profile(&mut texture_cache_profile.pages_rgba8_nearest);
|
||||
}
|
||||
|
||||
// Request an item in the texture cache. All images that will
|
||||
|
@ -349,13 +377,22 @@ impl TextureCache {
|
|||
}
|
||||
|
||||
// Get a specific region by index from a shared texture array.
|
||||
fn get_region_mut(&mut self, format: ImageFormat, region_index: u16) -> &mut TextureRegion {
|
||||
let texture_array = match format {
|
||||
ImageFormat::A8 => &mut self.array_a8,
|
||||
ImageFormat::BGRA8 => &mut self.array_rgba8,
|
||||
ImageFormat::RGB8 => &mut self.array_rgb8,
|
||||
ImageFormat::RG8 => &mut self.array_rg8,
|
||||
ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
|
||||
fn get_region_mut(&mut self,
|
||||
format: ImageFormat,
|
||||
filter: TextureFilter,
|
||||
region_index: u16
|
||||
) -> &mut TextureRegion {
|
||||
let texture_array = match (format, filter) {
|
||||
(ImageFormat::A8, TextureFilter::Linear) => &mut self.array_a8_linear,
|
||||
(ImageFormat::BGRA8, TextureFilter::Linear) => &mut self.array_rgba8_linear,
|
||||
(ImageFormat::BGRA8, TextureFilter::Nearest) => &mut self.array_rgba8_nearest,
|
||||
(ImageFormat::RGB8, TextureFilter::Linear) => &mut self.array_rgb8_linear,
|
||||
(ImageFormat::RG8, TextureFilter::Linear) => &mut self.array_rg8_linear,
|
||||
(ImageFormat::Invalid, _) |
|
||||
(ImageFormat::RGBAF32, _) |
|
||||
(ImageFormat::A8, TextureFilter::Nearest) |
|
||||
(ImageFormat::RG8, TextureFilter::Nearest) |
|
||||
(ImageFormat::RGB8, TextureFilter::Nearest) => unreachable!(),
|
||||
};
|
||||
|
||||
&mut texture_array.regions[region_index as usize]
|
||||
|
@ -501,7 +538,11 @@ impl TextureCache {
|
|||
..
|
||||
} => {
|
||||
// Free the block in the given region.
|
||||
let region = self.get_region_mut(entry.format, region_index);
|
||||
let region = self.get_region_mut(
|
||||
entry.format,
|
||||
entry.filter,
|
||||
region_index
|
||||
);
|
||||
region.free(origin);
|
||||
Some(region)
|
||||
}
|
||||
|
@ -512,15 +553,21 @@ impl TextureCache {
|
|||
fn allocate_from_shared_cache(
|
||||
&mut self,
|
||||
descriptor: &ImageDescriptor,
|
||||
filter: TextureFilter,
|
||||
user_data: [f32; 3],
|
||||
) -> Option<CacheEntry> {
|
||||
// Work out which cache it goes in, based on format.
|
||||
let texture_array = match descriptor.format {
|
||||
ImageFormat::A8 => &mut self.array_a8,
|
||||
ImageFormat::BGRA8 => &mut self.array_rgba8,
|
||||
ImageFormat::RGB8 => &mut self.array_rgb8,
|
||||
ImageFormat::RG8 => &mut self.array_rg8,
|
||||
ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
|
||||
let texture_array = match (descriptor.format, filter) {
|
||||
(ImageFormat::A8, TextureFilter::Linear) => &mut self.array_a8_linear,
|
||||
(ImageFormat::BGRA8, TextureFilter::Linear) => &mut self.array_rgba8_linear,
|
||||
(ImageFormat::BGRA8, TextureFilter::Nearest) => &mut self.array_rgba8_nearest,
|
||||
(ImageFormat::RGB8, TextureFilter::Linear) => &mut self.array_rgb8_linear,
|
||||
(ImageFormat::RG8, TextureFilter::Linear) => &mut self.array_rg8_linear,
|
||||
(ImageFormat::Invalid, _) |
|
||||
(ImageFormat::RGBAF32, _) |
|
||||
(ImageFormat::A8, TextureFilter::Nearest) |
|
||||
(ImageFormat::RG8, TextureFilter::Nearest) |
|
||||
(ImageFormat::RGB8, TextureFilter::Nearest) => unreachable!(),
|
||||
};
|
||||
|
||||
// Lazy initialize this texture array if required.
|
||||
|
@ -533,8 +580,8 @@ impl TextureCache {
|
|||
width: TEXTURE_LAYER_DIMENSIONS,
|
||||
height: TEXTURE_LAYER_DIMENSIONS,
|
||||
format: descriptor.format,
|
||||
filter: TextureFilter::Linear,
|
||||
layer_count: TEXTURE_ARRAY_LAYERS,
|
||||
filter: texture_array.filter,
|
||||
layer_count: texture_array.layer_count as i32,
|
||||
mode: RenderTargetMode::RenderTarget, // todo: !!!! remove me!?
|
||||
},
|
||||
};
|
||||
|
@ -572,12 +619,10 @@ impl TextureCache {
|
|||
let size = DeviceUintSize::new(descriptor.width, descriptor.height);
|
||||
let frame_id = self.frame_id;
|
||||
|
||||
// TODO(gw): For now, anything that requests nearest filtering
|
||||
// TODO(gw): For now, anything that requests nearest filtering and isn't BGRA8
|
||||
// just fails to allocate in a texture page, and gets a standalone
|
||||
// texture. This isn't ideal, as it causes lots of batch breaks,
|
||||
// but is probably rare enough that it can be fixed up later (it's also
|
||||
// fairly trivial to implement, just tedious).
|
||||
if filter == TextureFilter::Nearest {
|
||||
// texture. This is probably rare enough that it can be fixed up later.
|
||||
if filter == TextureFilter::Nearest && descriptor.format != ImageFormat::BGRA8 {
|
||||
allowed_in_shared_cache = false;
|
||||
}
|
||||
|
||||
|
@ -591,14 +636,22 @@ impl TextureCache {
|
|||
|
||||
// If it's allowed in the cache, see if there is a spot for it.
|
||||
if allowed_in_shared_cache {
|
||||
new_cache_entry = self.allocate_from_shared_cache(&descriptor, user_data);
|
||||
new_cache_entry = self.allocate_from_shared_cache(
|
||||
&descriptor,
|
||||
filter,
|
||||
user_data
|
||||
);
|
||||
|
||||
// If we failed to allocate in the shared cache, run an
|
||||
// eviction cycle, and then try to allocate again.
|
||||
if new_cache_entry.is_none() {
|
||||
self.expire_old_shared_entries(&descriptor);
|
||||
|
||||
new_cache_entry = self.allocate_from_shared_cache(&descriptor, user_data);
|
||||
new_cache_entry = self.allocate_from_shared_cache(
|
||||
&descriptor,
|
||||
filter,
|
||||
user_data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,6 +680,7 @@ impl TextureCache {
|
|||
texture_id,
|
||||
size,
|
||||
descriptor.format,
|
||||
filter,
|
||||
user_data,
|
||||
frame_id,
|
||||
));
|
||||
|
@ -824,6 +878,8 @@ impl TextureRegion {
|
|||
// each layer contains one or more regions that can act
|
||||
// as slab allocators.
|
||||
struct TextureArray {
|
||||
filter: TextureFilter,
|
||||
layer_count: usize,
|
||||
format: ImageFormat,
|
||||
is_allocated: bool,
|
||||
regions: Vec<TextureRegion>,
|
||||
|
@ -831,9 +887,15 @@ struct TextureArray {
|
|||
}
|
||||
|
||||
impl TextureArray {
|
||||
fn new(format: ImageFormat) -> TextureArray {
|
||||
fn new(
|
||||
format: ImageFormat,
|
||||
filter: TextureFilter,
|
||||
layer_count: usize
|
||||
) -> TextureArray {
|
||||
TextureArray {
|
||||
format,
|
||||
filter,
|
||||
layer_count,
|
||||
is_allocated: false,
|
||||
regions: Vec::new(),
|
||||
texture_id: None,
|
||||
|
@ -842,9 +904,9 @@ impl TextureArray {
|
|||
|
||||
fn update_profile(&self, counter: &mut ResourceProfileCounter) {
|
||||
if self.is_allocated {
|
||||
let size = TEXTURE_ARRAY_LAYERS as u32 * TEXTURE_LAYER_DIMENSIONS *
|
||||
let size = self.layer_count as u32 * TEXTURE_LAYER_DIMENSIONS *
|
||||
TEXTURE_LAYER_DIMENSIONS * self.format.bytes_per_pixel();
|
||||
counter.set(TEXTURE_ARRAY_LAYERS as usize, size as usize);
|
||||
counter.set(self.layer_count as usize, size as usize);
|
||||
} else {
|
||||
counter.set(0, 0);
|
||||
}
|
||||
|
@ -864,15 +926,18 @@ impl TextureArray {
|
|||
if !self.is_allocated {
|
||||
debug_assert!(TEXTURE_LAYER_DIMENSIONS % TEXTURE_REGION_DIMENSIONS == 0);
|
||||
let regions_per_axis = TEXTURE_LAYER_DIMENSIONS / TEXTURE_REGION_DIMENSIONS;
|
||||
for layer_index in 0 .. TEXTURE_ARRAY_LAYERS {
|
||||
for layer_index in 0 .. self.layer_count {
|
||||
for y in 0 .. regions_per_axis {
|
||||
for x in 0 .. regions_per_axis {
|
||||
let origin = DeviceUintPoint::new(
|
||||
x * TEXTURE_REGION_DIMENSIONS,
|
||||
y * TEXTURE_REGION_DIMENSIONS,
|
||||
);
|
||||
let region =
|
||||
TextureRegion::new(TEXTURE_REGION_DIMENSIONS, layer_index, origin);
|
||||
let region = TextureRegion::new(
|
||||
TEXTURE_REGION_DIMENSIONS,
|
||||
layer_index as i32,
|
||||
origin
|
||||
);
|
||||
self.regions.push(region);
|
||||
}
|
||||
}
|
||||
|
@ -936,6 +1001,7 @@ impl TextureArray {
|
|||
kind,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
format: self.format,
|
||||
filter: self.filter,
|
||||
texture_id: self.texture_id.unwrap(),
|
||||
}
|
||||
})
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
use api::{BorderRadiusKind, ClipAndScrollInfo, ClipId, ColorF, DeviceIntPoint, ImageKey};
|
||||
use api::{DeviceIntRect, DeviceIntSize, DeviceUintPoint, DeviceUintSize};
|
||||
use api::{ExternalImageType, FilterOp, FontRenderMode, ImageRendering, LayerRect};
|
||||
use api::{LayerToWorldTransform, MixBlendMode, PipelineId, PropertyBinding, TransformStyle};
|
||||
use api::{LayerVector2D, TileOffset, WorldToLayerTransform, YuvColorSpace, YuvFormat};
|
||||
use api::{MixBlendMode, PipelineId, PropertyBinding, TransformStyle};
|
||||
use api::{LayerVector2D, TileOffset, YuvColorSpace, YuvFormat};
|
||||
use border::{BorderCornerInstance, BorderCornerSide};
|
||||
use clip::{ClipSource, ClipStore};
|
||||
use clip_scroll_tree::CoordinateSystemId;
|
||||
|
@ -15,7 +15,7 @@ use glyph_rasterizer::GlyphFormat;
|
|||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuCacheUpdateList};
|
||||
use gpu_types::{BlurDirection, BlurInstance, BrushInstance, BrushImageKind, ClipMaskInstance};
|
||||
use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveInstance};
|
||||
use gpu_types::{BRUSH_FLAG_USES_PICTURE};
|
||||
use gpu_types::{BRUSH_FLAG_USES_PICTURE, ClipScrollNodeIndex, ClipScrollNodeData};
|
||||
use internal_types::{FastHashMap, SourceTexture};
|
||||
use internal_types::BatchTextures;
|
||||
use picture::PictureKind;
|
||||
|
@ -30,8 +30,7 @@ use renderer::ImageBufferKind;
|
|||
use resource_cache::{GlyphFetchResult, ResourceCache};
|
||||
use std::{cmp, usize, f32, i32};
|
||||
use texture_allocator::GuillotineAllocator;
|
||||
use util::{MatrixHelpers, TransformedRect, TransformedRectKind};
|
||||
use euclid::rect;
|
||||
use util::{MatrixHelpers, TransformedRectKind};
|
||||
|
||||
// Special sentinel value recognized by the shader. It is considered to be
|
||||
// a dummy task that doesn't mask out anything.
|
||||
|
@ -59,11 +58,15 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
PrimitiveKind::TextRun => {
|
||||
let font = &self.cpu_text_runs[metadata.cpu_prim_index.0].font;
|
||||
match font.render_mode {
|
||||
FontRenderMode::Subpixel => if font.bg_color.a != 0 {
|
||||
BlendMode::SubpixelWithBgColor
|
||||
} else {
|
||||
BlendMode::Subpixel
|
||||
},
|
||||
FontRenderMode::Subpixel => {
|
||||
if font.bg_color.a != 0 {
|
||||
BlendMode::SubpixelWithBgColor
|
||||
} else if font.color.a != 255 || metadata.clip_task_id.is_some() {
|
||||
BlendMode::SubpixelWithAlpha
|
||||
} else {
|
||||
BlendMode::SubpixelOpaque(font.color)
|
||||
}
|
||||
}
|
||||
FontRenderMode::Alpha |
|
||||
FontRenderMode::Mono |
|
||||
FontRenderMode::Bitmap => BlendMode::PremultipliedAlpha,
|
||||
|
@ -157,14 +160,15 @@ impl AlphaBatchList {
|
|||
) -> &mut Vec<PrimitiveInstance> {
|
||||
let mut selected_batch_index = None;
|
||||
|
||||
match key.kind {
|
||||
BatchKind::Composite { .. } => {
|
||||
match (key.kind, key.blend_mode) {
|
||||
(BatchKind::Composite { .. }, _) => {
|
||||
// Composites always get added to their own batch.
|
||||
// This is because the result of a composite can affect
|
||||
// the input to the next composite. Perhaps we can
|
||||
// optimize this in the future.
|
||||
}
|
||||
BatchKind::Transformable(_, TransformBatchKind::TextRun(_)) => {
|
||||
(BatchKind::Transformable(_, TransformBatchKind::TextRun(_)), BlendMode::SubpixelWithBgColor) |
|
||||
(BatchKind::Transformable(_, TransformBatchKind::TextRun(_)), BlendMode::SubpixelWithAlpha) => {
|
||||
'outer_text: for (batch_index, batch) in self.batches.iter().enumerate().rev().take(10) {
|
||||
// Subpixel text is drawn in two passes. Because of this, we need
|
||||
// to check for overlaps with every batch (which is a bit different
|
||||
|
@ -281,7 +285,9 @@ impl BatchList {
|
|||
match key.blend_mode {
|
||||
BlendMode::None => self.opaque_batch_list.get_suitable_batch(key),
|
||||
BlendMode::Alpha | BlendMode::PremultipliedAlpha |
|
||||
BlendMode::PremultipliedDestOut | BlendMode::Subpixel |
|
||||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::SubpixelOpaque(..) |
|
||||
BlendMode::SubpixelWithAlpha |
|
||||
BlendMode::SubpixelWithBgColor => {
|
||||
self.alpha_batch_list
|
||||
.get_suitable_batch(key, item_bounding_rect)
|
||||
|
@ -346,6 +352,8 @@ impl AlphaRenderItem {
|
|||
filter_mode,
|
||||
amount,
|
||||
z,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
|
@ -356,6 +364,7 @@ impl AlphaRenderItem {
|
|||
composite_op,
|
||||
screen_origin,
|
||||
z,
|
||||
dest_rect,
|
||||
) => {
|
||||
let stacking_context = &ctx.stacking_context_store[stacking_context_index.0];
|
||||
let src_task_address = render_tasks.get_task_address(src_id);
|
||||
|
@ -365,6 +374,11 @@ impl AlphaRenderItem {
|
|||
BatchTextures::no_texture(),
|
||||
);
|
||||
let batch = batch_list.get_suitable_batch(key, &stacking_context.screen_bounds);
|
||||
let dest_rect = if dest_rect.width > 0 && dest_rect.height > 0 {
|
||||
dest_rect
|
||||
} else {
|
||||
render_tasks.get(src_id).get_dynamic_size()
|
||||
};
|
||||
|
||||
let instance = CompositePrimitiveInstance::new(
|
||||
task_address,
|
||||
|
@ -373,6 +387,8 @@ impl AlphaRenderItem {
|
|||
screen_origin.x,
|
||||
screen_origin.y,
|
||||
z,
|
||||
dest_rect.width,
|
||||
dest_rect.height,
|
||||
);
|
||||
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
|
@ -399,20 +415,19 @@ impl AlphaRenderItem {
|
|||
mode as u32 as i32,
|
||||
0,
|
||||
z,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
}
|
||||
AlphaRenderItem::Primitive(clip_scroll_group_index_opt, prim_index, z) => {
|
||||
AlphaRenderItem::Primitive(clip_id, scroll_id, prim_index, z) => {
|
||||
let prim_metadata = ctx.prim_store.get_metadata(prim_index);
|
||||
let (transform_kind, packed_layer_index) = match clip_scroll_group_index_opt {
|
||||
Some(group_index) => {
|
||||
let group = &ctx.clip_scroll_group_store[group_index.0];
|
||||
let bounding_rect = group.screen_bounding_rect.as_ref().unwrap();
|
||||
(bounding_rect.0, group.packed_layer_index)
|
||||
}
|
||||
None => (TransformedRectKind::AxisAligned, PackedLayerIndex(0)),
|
||||
};
|
||||
let scroll_node = &ctx.node_data[scroll_id.0 as usize];
|
||||
// TODO(gw): Calculating this for every primitive is a bit
|
||||
// wasteful. We should probably cache this in
|
||||
// the scroll node...
|
||||
let transform_kind = scroll_node.transform.transform_kind();
|
||||
let item_bounding_rect = prim_metadata.screen_rect.as_ref().unwrap();
|
||||
let prim_cache_address = gpu_cache.get_address(&prim_metadata.gpu_location);
|
||||
let no_textures = BatchTextures::no_texture();
|
||||
|
@ -423,7 +438,8 @@ impl AlphaRenderItem {
|
|||
prim_cache_address,
|
||||
task_address,
|
||||
clip_task_address,
|
||||
packed_layer_index.into(),
|
||||
clip_id,
|
||||
scroll_id,
|
||||
z,
|
||||
);
|
||||
|
||||
|
@ -631,7 +647,8 @@ impl AlphaRenderItem {
|
|||
let instance = BrushInstance {
|
||||
picture_address: task_address,
|
||||
prim_address: prim_cache_address,
|
||||
layer_address: packed_layer_index.into(),
|
||||
clip_id,
|
||||
scroll_id,
|
||||
clip_task_address,
|
||||
z,
|
||||
flags: 0,
|
||||
|
@ -773,6 +790,8 @@ impl AlphaRenderItem {
|
|||
gpu_address,
|
||||
0,
|
||||
z,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
|
@ -864,7 +883,7 @@ impl ClipBatcher {
|
|||
for work_item in clips.iter() {
|
||||
let instance = ClipMaskInstance {
|
||||
render_task_address: task_address,
|
||||
layer_address: work_item.layer_index.into(),
|
||||
scroll_node_id: work_item.scroll_node_id,
|
||||
segment: 0,
|
||||
clip_data_address: GpuCacheAddress::invalid(),
|
||||
resource_address: GpuCacheAddress::invalid(),
|
||||
|
@ -956,9 +975,9 @@ impl ClipBatcher {
|
|||
pub struct RenderTargetContext<'a> {
|
||||
pub device_pixel_ratio: f32,
|
||||
pub stacking_context_store: &'a [StackingContext],
|
||||
pub clip_scroll_group_store: &'a [ClipScrollGroup],
|
||||
pub prim_store: &'a PrimitiveStore,
|
||||
pub resource_cache: &'a ResourceCache,
|
||||
pub node_data: &'a [ClipScrollNodeData],
|
||||
}
|
||||
|
||||
struct TextureAllocator {
|
||||
|
@ -1109,6 +1128,11 @@ pub struct FrameOutput {
|
|||
pub pipeline_id: PipelineId,
|
||||
}
|
||||
|
||||
pub struct ScalingInfo {
|
||||
pub src_task_id: RenderTaskId,
|
||||
pub dest_task_id: RenderTaskId,
|
||||
}
|
||||
|
||||
/// A render target represents a number of rendering operations on a surface.
|
||||
pub struct ColorRenderTarget {
|
||||
pub alpha_batcher: AlphaBatcher,
|
||||
|
@ -1119,6 +1143,7 @@ pub struct ColorRenderTarget {
|
|||
pub vertical_blurs: Vec<BlurInstance>,
|
||||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
pub readbacks: Vec<DeviceIntRect>,
|
||||
pub scalings: Vec<ScalingInfo>,
|
||||
// List of frame buffer outputs for this render target.
|
||||
pub outputs: Vec<FrameOutput>,
|
||||
allocator: Option<TextureAllocator>,
|
||||
|
@ -1141,6 +1166,7 @@ impl RenderTarget for ColorRenderTarget {
|
|||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
readbacks: Vec::new(),
|
||||
scalings: Vec::new(),
|
||||
allocator: size.map(|size| TextureAllocator::new(size)),
|
||||
glyph_fetch_buffer: Vec::new(),
|
||||
outputs: Vec::new(),
|
||||
|
@ -1228,7 +1254,8 @@ impl RenderTarget for ColorRenderTarget {
|
|||
sub_prim_address,
|
||||
task_index,
|
||||
RenderTaskAddress(0),
|
||||
PackedLayerIndex(0).into(),
|
||||
ClipScrollNodeIndex(0),
|
||||
ClipScrollNodeIndex(0),
|
||||
0,
|
||||
); // z is disabled for rendering cache primitives
|
||||
|
||||
|
@ -1286,6 +1313,12 @@ impl RenderTarget for ColorRenderTarget {
|
|||
RenderTaskKind::Readback(device_rect) => {
|
||||
self.readbacks.push(device_rect);
|
||||
}
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
self.scalings.push(ScalingInfo {
|
||||
src_task_id: task.children[0],
|
||||
dest_task_id: task_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1297,6 +1330,7 @@ pub struct AlphaRenderTarget {
|
|||
// List of blur operations to apply for this render target.
|
||||
pub vertical_blurs: Vec<BlurInstance>,
|
||||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
pub scalings: Vec<ScalingInfo>,
|
||||
pub zero_clears: Vec<RenderTaskId>,
|
||||
allocator: TextureAllocator,
|
||||
}
|
||||
|
@ -1313,6 +1347,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
brush_mask_rounded_rects: Vec::new(),
|
||||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
scalings: Vec::new(),
|
||||
zero_clears: Vec::new(),
|
||||
allocator: TextureAllocator::new(size.expect("bug: alpha targets need size")),
|
||||
}
|
||||
|
@ -1395,7 +1430,8 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
// tasks support clip masks and
|
||||
// transform primitives, these
|
||||
// will need to be filled out!
|
||||
layer_address: PackedLayerIndex(0).into(),
|
||||
clip_id: ClipScrollNodeIndex(0),
|
||||
scroll_id: ClipScrollNodeIndex(0),
|
||||
clip_task_address: RenderTaskAddress(0),
|
||||
z: 0,
|
||||
flags: BRUSH_FLAG_USES_PICTURE,
|
||||
|
@ -1438,6 +1474,12 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
clip_store,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
self.scalings.push(ScalingInfo {
|
||||
src_task_id: task.children[0],
|
||||
dest_task_id: task_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1700,9 +1742,6 @@ impl OpaquePrimitiveBatch {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct PackedLayerIndex(pub usize);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct StackingContextIndex(pub usize);
|
||||
|
||||
|
@ -1808,73 +1847,6 @@ impl StackingContext {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct ClipScrollGroupIndex(pub usize, pub ClipAndScrollInfo);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipScrollGroup {
|
||||
pub scroll_node_id: ClipId,
|
||||
pub clip_node_id: ClipId,
|
||||
pub packed_layer_index: PackedLayerIndex,
|
||||
pub screen_bounding_rect: Option<(TransformedRectKind, DeviceIntRect)>,
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
}
|
||||
|
||||
impl ClipScrollGroup {
|
||||
pub fn is_visible(&self) -> bool {
|
||||
self.screen_bounding_rect.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct PackedLayer {
|
||||
pub transform: LayerToWorldTransform,
|
||||
pub inv_transform: WorldToLayerTransform,
|
||||
pub local_clip_rect: LayerRect,
|
||||
}
|
||||
|
||||
impl PackedLayer {
|
||||
pub fn empty() -> PackedLayer {
|
||||
PackedLayer {
|
||||
transform: LayerToWorldTransform::identity(),
|
||||
inv_transform: WorldToLayerTransform::identity(),
|
||||
local_clip_rect: LayerRect::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_transform(&mut self, transform: LayerToWorldTransform) -> bool {
|
||||
self.transform = transform;
|
||||
match self.transform.inverse() {
|
||||
Some(inv) => {
|
||||
self.inv_transform = inv;
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_rect(
|
||||
&mut self,
|
||||
local_rect: &LayerRect,
|
||||
screen_rect: &DeviceIntRect,
|
||||
device_pixel_ratio: f32,
|
||||
) -> Option<(TransformedRectKind, DeviceIntRect)> {
|
||||
self.local_clip_rect = if self.transform.has_perspective_component() {
|
||||
// Given a very large rect which means any rect would be inside this rect.
|
||||
// That is, nothing would be clipped.
|
||||
rect(f32::MIN / 2.0, f32::MIN / 2.0, f32::MAX, f32::MAX)
|
||||
} else {
|
||||
*local_rect
|
||||
};
|
||||
let xf_rect = TransformedRect::new(local_rect, &self.transform, device_pixel_ratio);
|
||||
xf_rect
|
||||
.bounding_rect
|
||||
.intersection(screen_rect)
|
||||
.map(|rect| (xf_rect.kind, rect))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct CompositeOps {
|
||||
// Requires only a single texture as input (e.g. most filters)
|
||||
|
@ -1915,8 +1887,7 @@ pub struct Frame {
|
|||
pub passes: Vec<RenderPass>,
|
||||
pub profile_counters: FrameProfileCounters,
|
||||
|
||||
pub layer_texture_data: Vec<PackedLayer>,
|
||||
|
||||
pub node_data: Vec<ClipScrollNodeData>,
|
||||
pub render_tasks: RenderTaskTree,
|
||||
|
||||
// List of updates that need to be pushed to the
|
||||
|
|
|
@ -22,6 +22,7 @@ pub trait MatrixHelpers<Src, Dst> {
|
|||
fn has_perspective_component(&self) -> bool;
|
||||
fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>>;
|
||||
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>;
|
||||
fn transform_kind(&self) -> TransformedRectKind;
|
||||
}
|
||||
|
||||
impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
||||
|
@ -98,6 +99,14 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
|||
.unwrap_or(TypedPoint2D::zero()),
|
||||
])
|
||||
}
|
||||
|
||||
fn transform_kind(&self) -> TransformedRectKind {
|
||||
if self.preserves_2d_axis_alignment() {
|
||||
TransformedRectKind::AxisAligned
|
||||
} else {
|
||||
TransformedRectKind::Complex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RectHelpers<U>
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче