Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-07-23 16:03:48 -04:00
commit 8b5cd2c641
189 changed files with 3201 additions and 3257 deletions

View File

@ -29,22 +29,27 @@ endif
AB_CD = $(MOZ_UI_LOCALE)
AB := $(firstword $(subst -, ,$(AB_CD)))
ifeq (zh-TW,$(AB_CD))
LPROJ_ROOT := $(subst -,_,$(AB_CD))
else
LPROJ_ROOT := $(firstword $(subst -, ,$(AB_CD)))
endif
LPROJ := Contents/Resources/$(LPROJ_ROOT).lproj
clean clobber repackage::
rm -rf $(DIST)/$(APP_NAME).app
libs-preqs = \
$(call mkdir_deps,$(DIST)/$(APP_NAME).app/Contents/MacOS) \
$(call mkdir_deps,$(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj) \
$(call mkdir_deps,$(DIST)/$(APP_NAME).app/$(LPROJ)) \
$(NULL)
.PHONY: repackage
tools repackage:: $(libs-preqs)
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/$(LPROJ)
sed -e 's/%MOZ_APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MOZ_APP_NAME%/$(MOZ_APP_NAME)/' -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' -e 's/%APP_BINARY%/$(APP_BINARY)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
sed -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
sed -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/$(LPROJ)/InfoPlist.strings
rsync -a --exclude 'mangle' --exclude 'shlibsign' --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/Resources
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/MacOS
ifdef LIBXUL_SDK

View File

@ -1,44 +0,0 @@
{
"config_version": 2,
"tooltool_manifest": "releng-hamachi.tt",
"mock_target": "mozilla-centos6-x86_64",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel", "git", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel"],
"mock_files": [
["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"],
["/builds/crash-stats-api.token", "/builds/crash-stats-api.token"]
],
"build_targets": [],
"upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml"
],
"public_upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml",
"{workdir}/out/target/product/hamachi/*.mar"
],
"zip_files": [
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"MOZ_TELEMETRY_REPORTING": "1",
"B2G_UPDATE_CHANNEL": "nightly"
},
"b2g_manifest": "hamachi.xml",
"b2g_manifest_intree": true,
"additional_source_tarballs": ["backup-hamachi.tar.xz"],
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "https://hg.mozilla.org/gaia-l10n"
}
}
}

View File

@ -1,37 +0,0 @@
{
"config_version": 2,
"tooltool_manifest": "releng-limited-memory.tt",
"tooltool_bootstrap_cmd": ["bash", "-xe", "tt_setup.sh"],
"mock_target": "mozilla-centos6-x86_64",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel", "git", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel"],
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
"build_targets": [],
"upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml"
],
"zip_files": [
["{workdir}/out/target/product/hamachi/*.img", "out/target/product/hamachi/"],
["{workdir}/boot.2knand.img", "out/target/product/hamachi/boot.img"],
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"MOZ_TELEMETRY_REPORTING": "1"
},
"b2g_manifest": "hamachi.xml",
"b2g_manifest_branch": "master",
"additional_source_tarballs": ["backup-hamachi.tar.xz"],
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "https://hg.mozilla.org/gaia-l10n"
}
}
}

View File

@ -1,21 +0,0 @@
[
{
"size": 55276112,
"digest": "035efc2064a88bdb6f60fd126f17ee0e35de708f4666837cbeb0f3381024044a6ec3a05c244c553f9c2d852d94706f5263edde3d7dbff33872bd05db0215f5e6",
"algorithm": "sha512",
"filename": "backup-hamachi.tar.xz"
},
{
"size": 1570553,
"digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7",
"algorithm": "sha512",
"filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip"
},
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": "True"
}
]

View File

@ -1,39 +0,0 @@
[
{
"size": 55276112,
"digest": "035efc2064a88bdb6f60fd126f17ee0e35de708f4666837cbeb0f3381024044a6ec3a05c244c553f9c2d852d94706f5263edde3d7dbff33872bd05db0215f5e6",
"algorithm": "sha512",
"filename": "backup-hamachi.tar.xz"
},
{
"size": 1570553,
"digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7",
"algorithm": "sha512",
"filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip"
},
{
"size": 4632576,
"digest": "27d149a804d6cfaf387d7cced7078b5fe5227681d407f9258cf07ac61fcb35ee17a414b3c108eee6720293bd3e1d9e9c911eaf57059ad7d2361f9b93e9ee815b",
"algorithm": "sha512",
"filename": "boot.2knand.img"
},
{
"size": 9452,
"digest": "d4b919947dfb3f90d6645df31c92d795d6cf68e67f3679bbd80f8bb1920310dd69c8f6d3c0dcd697000b4691cbfddd17d60667a5a9ef933ba78d9a54a86503f0",
"algorithm": "sha512",
"filename": "patches.tgz"
},
{
"size": 302,
"digest": "d6a969fad4e53b617a21026062767f4b89d301464c38e9c9d04ba7dc7dcad72f1b337c284243a81e74de713171af5dd9a13aaaa7efd10109a0847ed23bf6e539",
"algorithm": "sha512",
"filename": "tt_setup.sh"
},
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": "True"
}
]

View File

@ -1,112 +0,0 @@
<?xml version="1.0" ?><manifest>
<!--original fetch url was https://android.googlesource.com/-->
<remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
<!--original fetch url was git://github.com/mozilla-b2g/-->
<remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
<!--original fetch url was git://github.com/mozilla/-->
<remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
<!--original fetch url was git://codeaurora.org/-->
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7205eca829290a2b5c312ddade7416dff41051cd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a536a1fec54b9e2a9ae4fd2e69c2336f12559730"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform_bionic" path="bionic" remote="b2g" revision="1a2a32eda22ef2cd18f57f423a5e7b22a105a6f8"/>
<project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
<project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
<project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
<project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
<project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
<project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="eb469e89d6ec6ec7ff1633a7f1b567a3787888f8"/>
<project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/>
<project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="05c760f3cca674e868cd35fefbacfb8d67745ce8"/>
<project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
<project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
<project name="platform/external/dbus" path="external/dbus" revision="878ed6cf21207e36956253a9013932c819053ee4"/>
<project name="platform/external/dhcpcd" path="external/dhcpcd" revision="638e6ed58cb734c178f1dfb251d3769e1b8ef410"/>
<project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
<project name="platform_external_elfcopy" path="external/elfcopy" remote="b2g" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/>
<project name="platform_external_elfutils" path="external/elfutils" remote="b2g" revision="72940dec691fa3255e13df01f8c53b620e446066"/>
<project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/>
<project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
<project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
<project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
<project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
<project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
<project name="platform/external/gtest" path="external/gtest" revision="8c212ebe53bb2baab3575f03069016f1fb11e449"/>
<project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/>
<project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
<project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
<project name="platform/external/jpeg" path="external/jpeg" revision="ef8288e4a75360236d69c5860b0d18ea101f0c1d"/>
<project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
<project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/>
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
<project name="platform/external/libpng" path="external/libpng" revision="1353a869289ec205209e594c5804e17fa4787e04"/>
<project name="platform/external/libvpx" path="external/libvpx" revision="2618c324e2ecd1fa5dbfb8cc0ba0911f4fd255d9"/>
<project name="platform/external/llvm" path="external/llvm" revision="d9527968ba7078ee6ce99dda8d8f555342032b91"/>
<project name="platform/external/mksh" path="external/mksh" revision="8380dd0a75783fc5e4a3e3b0f07f7e25bade3c8c"/>
<project name="platform/external/openssl" path="external/openssl" revision="c63c712a6a20e2c1b6085601c2d48e3f3ef32f73"/>
<project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/>
<project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/>
<project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/>
<project name="platform/external/skia" path="external/skia" revision="098dff2ef5d35b30bc79fdfdeae74e186919dcfe"/>
<project name="platform/external/sonivox" path="external/sonivox" revision="f5f46e68585c690436956f552994910f5e33bef5"/>
<project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/>
<project name="platform/external/sqlite" path="external/sqlite" revision="fb30e613139b8836fdc8e81e166cf3a76e5fa17f"/>
<project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
<project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
<project name="platform/external/svox" path="external/svox" revision="02dadb2ae0a5c31b9451ab169f1383dd0ff0948f"/>
<project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="b3a40ef1402b782553e1f3798d17e75636f16e3b"/>
<project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
<project name="unbootimg" path="external/unbootimg" remote="b2g" revision="9464623d92eb8668544916dc5a8f4f6337d0bc08"/>
<project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
<project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/>
<project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/>
<project name="platform/external/hostap" path="external/hostap" revision="611194f9ea6a2851171663dd59fae2fbfb39e246"/>
<project name="platform/external/zlib" path="external/zlib" revision="cb8dbfb25f8f0b111d0c8270ac49455cac4fd5b3"/>
<project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/>
<project name="platform/frameworks/base" path="frameworks/base" revision="e353565bea6e7c8382219190afefcced4b50b7d0"/>
<project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/>
<project name="platform/frameworks/support" path="frameworks/support" revision="90ffd236fe7f1e2bec74bd8624284ea017b41e64"/>
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="300ccfa39e003383d746d6a404be48c9194b19e1"/>
<project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="f197f55362dea6b9fc338a4f6d89bc009900f41f"/>
<project name="platform/libcore" path="libcore" revision="6d924abb26a30abb24d98378fac6bdc405f2a398"/>
<project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/>
<project name="platform/prebuilt" path="prebuilt" revision="248d92592df169569c387a91db56b1fedd6e5d29"/>
<project name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="d9735fc81434f2af2c44d86ca57740c673c8d9bc"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="395aff045276107a285daf0392d0884a98b9f538"/>
<project name="platform/system/core" path="system/core" revision="70229cf62037cfb70ec2257f7c78b5550628fb53"/>
<project name="platform/system/extras" path="system/extras" revision="a5dd0ea60ce973c2c762b41835a43316fb4ff9e3"/>
<project name="platform/system/media" path="system/media" revision="fbb3d9b4c5bf59071424e820e872e3f64f0a244a"/>
<project name="platform/system/netd" path="system/netd" revision="2e226e6e636ca0a8cc4c51093e46f4baba1ffcce"/>
<project name="platform/system/vold" path="system/vold" revision="8ac5eef8ea3a456b96d52ce2091bf6d814782d8c"/>
<!-- hamachi specific things -->
<project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="ccd8b858242c099cb4bc725daf22896ab4a4b325"/>
<project name="quic/lf/b2g/external/jsmin" path="external/jsmin" revision="cec896f0affaa0226c02605ad28d42df1bc0e393"/>
<project name="device/qcom/common" path="device/qcom/common" revision="d13aaf080177b7c48f243d51827db5c7a7873cd0"/>
<project name="platform/vendor/qcom/msm7627a" path="device/qcom/msm7627a" revision="f06bcacc6f13cec895dc5d4c2385c076396194ec"/>
<project name="android-device-hamachi" path="device/qcom/hamachi" remote="b2g" revision="7a67afcef2846ad7938059111e1d0bc4de9f0445"/>
<project name="kernel/msm" path="kernel" revision="a6578b9cacf9079f2dcf5bfe77c31b1be18809e3"/>
<project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="19933e5d182a4799c6217b19a18562193a419298"/>
<project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="5a58382180c70d0c446badc9c9837918ab69ec60"/>
<project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="20d83ab382a1f813702421e76c2f9f994585990e"/>
<project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="1698e6e9ed7cf1d543508845fa05ed86c7e5e241"/>
<project name="platform/hardware/msm7k" path="hardware/msm7k" revision="693e65da9905d88c23653b45800e6509143f6a78"/>
<project name="platform/vendor/qcom-opensource/omx/mm-core" path="vendor/qcom/opensource/omx/mm-core" revision="0365db6af2d4df11184a421f97c5043db47a0c0d"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="ec40c0aee736052fc4fe01c1b8dc16929da5dc45"/>
</manifest>

View File

@ -1,50 +0,0 @@
{
"config_version": 2,
"tooltool_manifest": "releng-helix.tt",
"mock_target": "mozilla-centos6-x86_64",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel", "git", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel"],
"mock_files": [
["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"],
["/builds/crash-stats-api.token", "/builds/crash-stats-api.token"]
],
"build_targets": [],
"upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml"
],
"public_upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml",
"{objdir}/dist/b2g-update/*.mar"
],
"zip_files": [
["{workdir}/out/target/product/helix/*.img", "out/target/product/helix/"],
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"MOZ_TELEMETRY_REPORTING": "1",
"ANDROIDFS_DIR": "{workdir}/helix-ics",
"B2G_UPDATE_CHANNEL": "nightly"
},
"b2g_manifest": "helix.xml",
"b2g_manifest_intree": true,
"additional_source_tarballs": ["helix-ics.tar.xz"],
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "https://hg.mozilla.org/gaia-l10n"
}
}
}

View File

@ -1,21 +0,0 @@
[
{
"size": 58958768,
"digest": "a1c7727075b481259ee1835d0f016834f52b8a20dd18be6e0dbf265421671e2fc5203ff01891588ab712f5033103350574528dae866ea795460518afa78b0c4b",
"algorithm": "sha512",
"filename": "helix-ics.tar.xz"
},
{
"size": 1570553,
"digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7",
"algorithm": "sha512",
"filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip"
},
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": "True"
}
]

View File

@ -1,109 +0,0 @@
<?xml version="1.0" ?><manifest>
<!--original fetch url was https://android.googlesource.com/-->
<remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
<!--original fetch url was git://github.com/mozilla-b2g/-->
<remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
<!--original fetch url was git://github.com/mozilla/-->
<remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
<!--original fetch url was git://codeaurora.org/-->
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b33a1afb538e8c7e12f6fb792c454da34f9f5b76"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform_bionic" path="bionic" remote="b2g" revision="1a2a32eda22ef2cd18f57f423a5e7b22a105a6f8"/>
<project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
<project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
<project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
<project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
<project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
<project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="eb469e89d6ec6ec7ff1633a7f1b567a3787888f8"/>
<project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/>
<project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="05c760f3cca674e868cd35fefbacfb8d67745ce8"/>
<project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
<project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
<project name="platform/external/dbus" path="external/dbus" revision="878ed6cf21207e36956253a9013932c819053ee4"/>
<project name="platform/external/dhcpcd" path="external/dhcpcd" revision="638e6ed58cb734c178f1dfb251d3769e1b8ef410"/>
<project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
<project name="platform_external_elfcopy" path="external/elfcopy" remote="b2g" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/>
<project name="platform_external_elfutils" path="external/elfutils" remote="b2g" revision="72940dec691fa3255e13df01f8c53b620e446066"/>
<project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/>
<project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
<project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
<project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
<project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
<project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
<project name="platform/external/gtest" path="external/gtest" revision="8c212ebe53bb2baab3575f03069016f1fb11e449" upstream="aosp-new/master"/>
<project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/>
<project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
<project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
<project name="platform/external/jpeg" path="external/jpeg" revision="ef8288e4a75360236d69c5860b0d18ea101f0c1d"/>
<project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
<project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/>
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
<project name="platform/external/libpng" path="external/libpng" revision="1353a869289ec205209e594c5804e17fa4787e04"/>
<project name="platform/external/libvpx" path="external/libvpx" revision="2618c324e2ecd1fa5dbfb8cc0ba0911f4fd255d9"/>
<project name="platform/external/llvm" path="external/llvm" revision="d9527968ba7078ee6ce99dda8d8f555342032b91"/>
<project name="platform/external/mksh" path="external/mksh" revision="8380dd0a75783fc5e4a3e3b0f07f7e25bade3c8c"/>
<project name="platform/external/openssl" path="external/openssl" revision="c63c712a6a20e2c1b6085601c2d48e3f3ef32f73"/>
<project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/>
<project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/>
<project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/>
<project name="platform/external/skia" path="external/skia" revision="098dff2ef5d35b30bc79fdfdeae74e186919dcfe"/>
<project name="platform/external/sonivox" path="external/sonivox" revision="f5f46e68585c690436956f552994910f5e33bef5"/>
<project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/>
<project name="platform/external/sqlite" path="external/sqlite" revision="537b409287fe6c28b71c5500a42f5fd7724f900d"/>
<project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
<project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
<project name="platform/external/svox" path="external/svox" revision="02dadb2ae0a5c31b9451ab169f1383dd0ff0948f"/>
<project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="b3a40ef1402b782553e1f3798d17e75636f16e3b"/>
<project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
<project name="unbootimg" path="external/unbootimg" remote="b2g" revision="9464623d92eb8668544916dc5a8f4f6337d0bc08"/>
<project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
<project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/>
<project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/>
<project name="platform/external/hostap" path="external/hostap" revision="611194f9ea6a2851171663dd59fae2fbfb39e246"/>
<project name="platform/external/zlib" path="external/zlib" revision="cb8dbfb25f8f0b111d0c8270ac49455cac4fd5b3"/>
<project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/>
<project name="platform/frameworks/base" path="frameworks/base" revision="bb9f8618ff7a1dfb5627b3c13219f6583a16e470"/>
<project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/>
<project name="platform/frameworks/support" path="frameworks/support" revision="90ffd236fe7f1e2bec74bd8624284ea017b41e64"/>
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="93226241c35eea5ae139c8370a6d8ad837c8106e"/>
<project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="f197f55362dea6b9fc338a4f6d89bc009900f41f"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="7dc9ff3e8de3fbf36fa89bf2909959a0070fc75d"/>
<project name="platform/libcore" path="libcore" revision="6d924abb26a30abb24d98378fac6bdc405f2a398"/>
<project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/>
<project name="platform/prebuilt" path="prebuilt" revision="248d92592df169569c387a91db56b1fedd6e5d29"/>
<project name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="d9735fc81434f2af2c44d86ca57740c673c8d9bc"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="395aff045276107a285daf0392d0884a98b9f538"/>
<project name="platform/system/core" path="system/core" revision="e4e910457913d521e1773e059a94891bde2cfeeb"/>
<project name="platform/system/extras" path="system/extras" revision="a5dd0ea60ce973c2c762b41835a43316fb4ff9e3"/>
<project name="platform/system/media" path="system/media" revision="fbb3d9b4c5bf59071424e820e872e3f64f0a244a"/>
<project name="platform/system/netd" path="system/netd" revision="a947ed754bb0cd0db992579d9a3a00ae4484c59c"/>
<project name="platform/system/vold" path="system/vold" revision="3f87f19bf8bdf3a7cb3c01ef2b2c5810633e78ef"/>
<!-- helix specific things -->
<project name="device/qcom/common" path="device/qcom/common" revision="d13aaf080177b7c48f243d51827db5c7a7873cd0"/>
<project name="platform/vendor/qcom/msm7627a" path="device/qcom/msm7627a" revision="9019e1c750f427785148c7512a183531f7675679"/>
<project name="device-helix" path="device/qcom/helix" remote="b2g" revision="47f22c59edb13379a6995554cb4a473558929653"/>
<project name="kernel/msm" path="kernel" revision="e9c1e0c6a0ca33f5741a48288de4b46453031210"/>
<project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="c4e3e6cf938f1bdde78bc39f38350f72b6fc3a21"/>
<project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="32905dde6a66296c7e5843e9664c5c6444deb38c"/>
<project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="b2ac43193f3d3a44171bdb50ea3c2aeb558511d3"/>
<project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="1698e6e9ed7cf1d543508845fa05ed86c7e5e241"/>
<project name="platform/hardware/msm7k" path="hardware/msm7k" revision="669815aaca47afee95b4a95908dc87bff267a815"/>
<project name="platform/vendor/qcom-opensource/omx/mm-core" path="vendor/qcom/opensource/omx/mm-core" revision="0365db6af2d4df11184a421f97c5043db47a0c0d"/>
</manifest>

View File

@ -1,43 +0,0 @@
{
"config_version": 2,
"tooltool_manifest": "releng-wasabi.tt",
"mock_target": "mozilla-centos6-x86_64",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel", "git", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel"],
"mock_files": [
["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"],
["/builds/crash-stats-api.token", "/builds/crash-stats-api.token"]
],
"build_targets": [],
"upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml"
],
"zip_files": [
["{workdir}/out/target/product/wasabi/*.img", "out/target/product/wasabi/"],
["{workdir}/boot.img", "out/target/product/wasabi/"],
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",
"MOZ_TELEMETRY_REPORTING": "1"
},
"b2g_manifest": "wasabi.xml",
"b2g_manifest_intree": true,
"additional_source_tarballs": ["backup-wasabi.tar.gz"],
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "https://hg.mozilla.org/gaia-l10n"
}
}
}

View File

@ -1,27 +0,0 @@
[
{
"size": 311696844,
"digest": "110d6a8a275fb8427816e748448930bb5e6fc45eaba88ac5be824d2873d2d41e1b5c0252d68a1d3b197ec209a7d6dcd1b5e83322702667c8e1b89f3db2ff0bc6",
"algorithm": "sha512",
"filename": "backup-wasabi.tar.gz"
},
{
"size": 1570553,
"digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7",
"algorithm": "sha512",
"filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip"
},
{
"size": 5730304,
"digest": "709a281438607f10c9f55683303d5cc1d8720520e26a8ae45f48b7ccb9265ba8939c4a077ae3368afc891bbd7426013edfbbbb3dbdeab5b1f06e60901b141de6",
"algorithm": "sha512",
"filename": "boot.img"
},
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": "True"
}
]

View File

@ -1,112 +0,0 @@
<?xml version="1.0" ?><manifest>
<!--original fetch url was https://android.googlesource.com/-->
<remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
<!--original fetch url was git://github.com/mozilla-b2g/-->
<remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
<!--original fetch url was git://github.com/mozilla/-->
<remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
<!--original fetch url was git://codeaurora.org/-->
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
<!--original fetch url was https://git.mozilla.org/releases-->
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
<!--original fetch url was git://github.com/apitrace/-->
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
<default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
<!-- Gonk specific things and forks -->
<project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="b33a1afb538e8c7e12f6fb792c454da34f9f5b76"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5d482e320548e7ef0a44f62fd7ad51778cca4b3a"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
<project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
<project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
<project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
<project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
<project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
<project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="1023c91c66e9c3bd1132480051993bf7827770f6"/>
<project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/>
<project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="02b1eb24fbb3d0135a81edb4a2175b1397308d7d"/>
<project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
<project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
<project name="platform/external/dbus" path="external/dbus" revision="c7517b6195dc6926728352113e6cc335da3f9c9e"/>
<project name="platform/external/dhcpcd" path="external/dhcpcd" revision="1e00fb67022d0921af0fead263f81762781b9ffa"/>
<project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
<project name="platform_external_elfcopy" path="external/elfcopy" remote="b2g" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/>
<project name="platform_external_elfutils" path="external/elfutils" remote="b2g" revision="72940dec691fa3255e13df01f8c53b620e446066"/>
<project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/>
<project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
<project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
<project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
<project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
<project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
<project name="platform/external/gtest" path="external/gtest" revision="8c212ebe53bb2baab3575f03069016f1fb11e449"/>
<project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/>
<project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
<project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
<project name="platform/external/jpeg" path="external/jpeg" revision="a62e464d672a4623233180e4023034bf825f066e"/>
<project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
<project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
<project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/>
<project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
<project name="platform/external/libpng" path="external/libpng" revision="9c3730f0efa69f580f03463c237cd928f3196404"/>
<project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/>
<project name="platform/external/llvm" path="external/llvm" revision="bff5923831940309f7d8ddbff5826ca6ed2dc050"/>
<project name="platform/external/mksh" path="external/mksh" revision="ec646e8f5e7dac9a77d1de549c6ed92c04d0cd4b"/>
<project name="platform_external_opensans" path="external/opensans" remote="b2g" revision="b5b4c226ca1d71e936153cf679dda6d3d60e2354"/>
<project name="platform/external/openssl" path="external/openssl" revision="27d333cce9a31c806b4bfa042925f045c727aecd"/>
<project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/>
<project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/>
<project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/>
<project name="platform/external/skia" path="external/skia" revision="7d90c85f2c0e3b747f7c7eff8bc9253b0063b439"/>
<project name="platform/external/sonivox" path="external/sonivox" revision="7c967779dfc61ac1f346e972de91d4bfce7dccbb"/>
<project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/>
<project name="platform/external/sqlite" path="external/sqlite" revision="fb30e613139b8836fdc8e81e166cf3a76e5fa17f"/>
<project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
<project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
<project name="platform/external/svox" path="external/svox" revision="bd1c06681030164268172ead2eb39b86425624bf"/>
<project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
<project name="platform/external/tinyalsa" path="external/tinyalsa" revision="06cc244ee512c1352215e543615738bc8ac82814"/>
<project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
<project name="unbootimg" path="external/unbootimg" remote="b2g" revision="9464623d92eb8668544916dc5a8f4f6337d0bc08"/>
<project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
<project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/>
<project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/>
<project name="platform/external/hostap" path="external/hostap" revision="bf04b0faadbdeb4b7943f2e2c4c5aa59df872bb1"/>
<project name="platform/external/zlib" path="external/zlib" revision="f96a1d1ebfdf1cd582210fd09c23d8f59e0ae094"/>
<project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/>
<project name="platform/frameworks/base" path="frameworks/base" revision="eb2bc75803ca179353c24c364a9c8a8ce23e8b78"/>
<project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/>
<project name="platform/frameworks/support" path="frameworks/support" revision="27208692b001981f1806f4f396434f4eac78b909"/>
<project name="platform/hardware/libhardware" path="hardware/libhardware" revision="4a619901847621f8a7305edf42dd07347a140484"/>
<project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="87b4d7afa8f854b445e2d0d95091f6f6069f2b30"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="d65f556f96bf5421f1f8db36b81706c8c3cb53c3"/>
<project name="platform/libcore" path="libcore" revision="30841f9fba9ccd5c54f4f079f495994db97f283e"/>
<project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/>
<project name="platform/prebuilt" path="prebuilt" revision="447ea790fcc957dde59730ecc2a65ca263bdc733"/>
<project name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="d9735fc81434f2af2c44d86ca57740c673c8d9bc"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="7772cad4823f1f427ce1d4df84a55982386d6d18"/>
<project name="platform/system/core" path="system/core" revision="bf1970408676ce570b8f4dc3efa038e47552137f"/>
<project name="platform/system/extras" path="system/extras" revision="01db6c1254e1407740a543f24317fc540fc4c049"/>
<project name="platform/system/media" path="system/media" revision="7f71c7fd362bbd992ff2e0e80f7af5859ad116ad"/>
<project name="platform/system/netd" path="system/netd" revision="306e765248e3900041bf2737e9f57b1b5694a4ce"/>
<project name="platform/system/vold" path="system/vold" revision="99fff257d53cc045d1460841edca5d901dacfcf5"/>
<!-- Wasabi specific things -->
<project name="device/qcom/common" path="device/qcom/common" revision="b9cdab8e1e1a215a8c65b8d5816f666bec7be205"/>
<project name="platform/vendor/qcom/msm8960" path="device/qcom/msm8960" revision="58786a6a6f16384a7770f92081a5d8f7b1a067ae"/>
<project name="device-wasabi" path="device/qcom/wasabi" remote="b2g" revision="75c4cf201326edcd909502aa52febc96bf553104"/>
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="0a01247e4b0880f93424b27251cd3a1f6b19dbb2"/>
<project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="1acf77a75e30f3fc8b1eed2057c97adf1cb1633f"/>
<project name="hardware_qcom_display" path="hardware/qcom/display" remote="b2g" revision="6405d30f2fac7d8a1f2cb17b99fb7dd0a8bcfdac"/>
<project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="552c3ddb7174a01f3508782d40c4d8c845ab441a"/>
<project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="23d5707b320d7fc69f8ba3b7d84d78a1c5681708"/>
<project name="platform/vendor/qcom-opensource/omx/mm-core" path="vendor/qcom/opensource/omx/mm-core" revision="ab17ac9a074b4bb69986a8436336bdfbbaf9cd39"/>
</manifest>

View File

@ -79,7 +79,12 @@ endif
AB_CD = $(MOZ_UI_LOCALE)
AB := $(firstword $(subst -, ,$(AB_CD)))
ifeq (zh-TW,$(AB_CD))
LPROJ_ROOT := $(subst -,_,$(AB_CD))
else
LPROJ_ROOT := $(firstword $(subst -, ,$(AB_CD)))
endif
LPROJ := Contents/Resources/$(LPROJ_ROOT).lproj
clean clobber repackage::
$(RM) -r $(dist_dest)
@ -89,11 +94,11 @@ MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_A
.PHONY: repackage
tools repackage:: $(PROGRAM)
$(MKDIR) -p $(dist_dest)/Contents/MacOS
$(MKDIR) -p $(dist_dest)/Contents/Resources/$(AB).lproj
$(MKDIR) -p $(dist_dest)/$(LPROJ)
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/$(LPROJ)
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/$(LPROJ)/InfoPlist.strings
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)

View File

@ -295,6 +295,7 @@ skip-if = true # browser_drag.js is disabled, as it needs to be updated for the
[browser_favicon_change.js]
[browser_favicon_change_not_in_document.js]
[browser_findbarClose.js]
[browser_focusonkeydown.js]
[browser_fullscreen-window-open.js]
skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
[browser_fxa_migrate.js]

View File

@ -0,0 +1,26 @@
add_task(function *()
{
let keyUps = 0;
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/html,<body>");
gURLBar.focus();
window.addEventListener("keyup", function countKeyUps(event) {
window.removeEventListener("keyup", countKeyUps, true);
if (event.originalTarget == gURLBar.inputField) {
keyUps++;
}
}, true);
gURLBar.addEventListener("keydown", function redirectFocus(event) {
gURLBar.removeEventListener("keydown", redirectFocus, true);
gBrowser.selectedBrowser.focus();
}, true);
EventUtils.synthesizeKey("v", { });
is(keyUps, 1, "Key up fired at url bar");
gBrowser.removeCurrentTab();
});

View File

@ -1,220 +1,200 @@
Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html";
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
/**
* Frame script that will be injected into the test browser
* to cause plugin crashes, and then manipulate the crashed plugin
* UI. The specific actions and checks that occur in the frame
* script for the crashed plugin UI are set in the
* test:crash-plugin message object sent from the parent. The actions
* and checks that the parent can specify are:
*
* pleaseSubmitStyle: the display style that the pleaseSubmit anonymous element
* should have - example "block", "none".
* submitComment: the comment that should be put into the crash report
* urlOptIn: true if the submitURLOptIn element should be checked.
* sendCrashMessage: if true, the frame script will send a
* test:crash-plugin:crashed message when the plugin has
* crashed. This is used for the last test case, and
* causes the frame script to skip any of the crashed
* plugin UI manipulation, since the last test shows
* no crashed plugin UI.
*/
function frameScript() {
function fail(reason) {
sendAsyncMessage("test:crash-plugin:fail", {
reason: `Failure from frameScript: ${reason}`,
});
}
addMessageListener("test:crash-plugin", (message) => {
addEventListener("PluginCrashed", function onPluginCrashed(event) {
removeEventListener("PluginCrashed", onPluginCrashed);
let doc = content.document;
let plugin = doc.getElementById("plugin");
if (!plugin) {
fail("Could not find plugin element");
return;
}
let getUI = (anonid) => {
return doc.getAnonymousElementByAttribute(plugin, "anonid", anonid);
};
let style = content.getComputedStyle(getUI("pleaseSubmit"));
if (style.display != message.data.pleaseSubmitStyle) {
fail("Submission UI visibility is not correct. Expected " +
`${message.data.pleaseSubmitStyle} and got ${style.display}`);
return;
}
if (message.data.sendCrashMessage) {
sendAsyncMessage("test:crash-plugin:crashed", {
crashID: event.pluginDumpID,
});
return;
}
if (message.data.submitComment) {
getUI("submitComment").value = message.data.submitComment;
}
getUI("submitURLOptIn").checked = message.data.urlOptIn;
getUI("submitButton").click();
});
let plugin = content.document.getElementById("test");
try {
plugin.crash()
} catch(e) {
}
});
}
function test() {
// Crashing the plugin takes up a lot of time, so extend the test timeout.
requestLongerTimeout(runs.length);
waitForExplicitFinish();
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
let gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
let gTestBrowser = null;
let config = {};
add_task(function* () {
// The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin
// crash reports. This test needs them enabled. The test also needs a mock
// report server, and fortunately one is already set up by toolkit/
// crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL,
// which CrashSubmit.jsm uses as a server override.
let env = Cc["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
let env = Components.classes["@mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment);
let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT");
let serverURL = env.get("MOZ_CRASHREPORTER_URL");
let serverUrl = env.get("MOZ_CRASHREPORTER_URL");
env.set("MOZ_CRASHREPORTER_NO_REPORT", "");
env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
let browser = gBrowser.getBrowserForTab(tab);
let mm = browser.messageManager;
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", true);
gBrowser.selectedTab = gBrowser.addTab();
gTestBrowser = gBrowser.selectedBrowser;
mm.addMessageListener("test:crash-plugin:fail", (message) => {
ok(false, message.data.reason);
});
// Crash immediately
Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", 0);
Services.obs.addObserver(onSubmitStatus, "crash-report-status", false);
registerCleanupFunction(function cleanUp() {
registerCleanupFunction(Task.async(function*() {
Services.prefs.clearUserPref("dom.ipc.plugins.timeoutSecs");
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
env.set("MOZ_CRASHREPORTER_URL", serverURL);
Services.obs.removeObserver(onSubmitStatus, "crash-report-status");
env.set("MOZ_CRASHREPORTER_URL", serverUrl);
env = null;
config = null;
gTestBrowser = null;
gBrowser.removeCurrentTab();
});
window.focus();
}));
});
doNextRun();
}
let runs = [
{
add_task(function* () {
config = {
shouldSubmissionUIBeVisible: true,
comment: "",
urlOptIn: false,
},
{
urlOptIn: false
};
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
let pluginCrashed = promisePluginCrashed();
yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html");
// Work around for delayed PluginBindingAttached
yield promiseUpdatePluginBindings(gTestBrowser);
// Wait for the plugin to crash
yield pluginCrashed;
let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus);
// Test that the crash submission UI is actually visible and submit the crash report.
let crashUiVisible = yield ContentTask.spawn(gTestBrowser, config, function* (aConfig) {
let doc = content.document;
let plugin = doc.getElementById("plugin");
let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton");
// Test that we don't send the URL when urlOptIn is false.
doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn;
submitButton.click();
return content.getComputedStyle(pleaseSubmit).display == "block";
});
yield crashReportStatus;
is(crashUiVisible, config.shouldSubmissionUIBeVisible, "The crash UI should be visible");
});
add_task(function* () {
config = {
shouldSubmissionUIBeVisible: true,
comment: "a test comment",
urlOptIn: true,
},
{
width: 300,
height: 300,
urlOptIn: true
};
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
let pluginCrashed = promisePluginCrashed();
yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html");
// Work around for delayed PluginBindingAttached
yield promiseUpdatePluginBindings(gTestBrowser);
// Wait for the plugin to crash
yield pluginCrashed;
let crashReportStatus = TestUtils.topicObserved("crash-report-status", onSubmitStatus);
// Test that the crash submission UI is actually visible and submit the crash report.
let crashUiVisible = yield ContentTask.spawn(gTestBrowser, config, function* (aConfig) {
let doc = content.document;
let plugin = doc.getElementById("plugin");
let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
let submitButton = doc.getAnonymousElementByAttribute(plugin, "anonid", "submitButton");
// Test that we send the URL when urlOptIn is true.
doc.getAnonymousElementByAttribute(plugin, "anonid", "submitURLOptIn").checked = aConfig.urlOptIn;
doc.getAnonymousElementByAttribute(plugin, "anonid", "submitComment").value = aConfig.comment;
submitButton.click();
return content.getComputedStyle(pleaseSubmit).display == "block";
});
yield crashReportStatus;
is(crashUiVisible, config.shouldSubmissionUIBeVisible, "The crash UI should be visible");
});
add_task(function* () {
config = {
shouldSubmissionUIBeVisible: false,
},
];
comment: "",
urlOptIn: true
};
let currentRun = null;
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
function doNextRun() {
try {
if (!runs.length) {
finish();
return;
}
currentRun = runs.shift();
let args = ["width", "height"].reduce(function (memo, arg) {
if (arg in currentRun)
memo[arg] = currentRun[arg];
return memo;
}, {});
let mm = gBrowser.selectedBrowser.messageManager;
let pluginCrashed = promisePluginCrashed();
if (!currentRun.shouldSubmittionUIBeVisible) {
mm.addMessageListener("test:crash-plugin:crash", function onCrash(message) {
mm.removeMessageListener("test:crash-plugin:crash", onCrash);
// Make sure that the plugin container is too small to display the crash submission UI
yield promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_crashCommentAndURL.html?" +
encodeURIComponent(JSON.stringify({width: 300, height: 300})));
ok(!!message.data.crashID, "pluginDumpID should be set");
CrashSubmit.delete(message.data.crashID);
doNextRun();
// Work around for delayed PluginBindingAttached
yield promiseUpdatePluginBindings(gTestBrowser);
// Wait for the plugin to crash
yield pluginCrashed;
// Test that the crash submission UI is not visible and do not submit a crash report.
let crashUiVisible = yield ContentTask.spawn(gTestBrowser, {}, function* () {
let doc = content.document;
let plugin = doc.getElementById("plugin");
let pleaseSubmit = doc.getAnonymousElementByAttribute(plugin, "anonid", "pleaseSubmit");
return !!pleaseSubmit && content.getComputedStyle(pleaseSubmit).display == "block";
});
is(crashUiVisible, config.shouldSubmissionUIBeVisible, "Plugin crash UI should not be visible");
});
function promisePluginCrashed() {
return new ContentTask.spawn(gTestBrowser, {}, function* () {
yield new Promise((resolve) => {
addEventListener("PluginCrashed", function onPluginCrashed() {
removeEventListener("PluginCrashed", onPluginCrashed);
resolve();
});
}
mm.sendAsyncMessage("test:crash-plugin", {
pleaseSubmitStyle: currentRun.shouldSubmissionUIBeVisible ? "block" : "none",
submitComment: currentRun.comment,
urlOptIn: currentRun.urlOptIn,
sendOnCrashMessage: !currentRun.shouldSubmissionUIBeVisible,
});
gBrowser.loadURI(CRASH_URL + "?" +
encodeURIComponent(JSON.stringify(args)));
// And now wait for the crash.
}
catch (err) {
failWithException(err);
finish();
}
})
}
function onSubmitStatus(subj, topic, data) {
try {
// Wait for success or failed, doesn't matter which.
if (data != "success" && data != "failed")
return;
function onSubmitStatus(aSubject, aData) {
// Wait for success or failed, doesn't matter which.
if (aData != "success" && aData != "failed")
return false;
let propBag = subj.QueryInterface(Ci.nsIPropertyBag);
if (data == "success") {
let remoteID = getPropertyBagValue(propBag, "serverCrashID");
ok(!!remoteID, "serverCrashID should be set");
let propBag = aSubject.QueryInterface(Ci.nsIPropertyBag);
if (aData == "success") {
let remoteID = getPropertyBagValue(propBag, "serverCrashID");
ok(!!remoteID, "serverCrashID should be set");
// Remove the submitted report file.
let file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
file.initWithPath(Services.crashmanager._submittedDumpsDir);
file.append(remoteID + ".txt");
ok(file.exists(), "Submitted report file should exist");
file.remove(false);
}
let extra = getPropertyBagValue(propBag, "extra");
ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag");
let val = getPropertyBagValue(extra, "PluginUserComment");
if (currentRun.comment)
is(val, currentRun.comment,
"Comment in extra data should match comment in textbox");
else
ok(val === undefined,
"Comment should be absent from extra data when textbox is empty");
val = getPropertyBagValue(extra, "PluginContentURL");
if (currentRun.urlOptIn)
is(val, gBrowser.currentURI.spec,
"URL in extra data should match browser URL when opt-in checked");
else
ok(val === undefined,
"URL should be absent from extra data when opt-in not checked");
// Remove the submitted report file.
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(Services.crashmanager._submittedDumpsDir);
file.append(remoteID + ".txt");
ok(file.exists(), "Submitted report file should exist");
file.remove(false);
}
catch (err) {
failWithException(err);
}
doNextRun();
let extra = getPropertyBagValue(propBag, "extra");
ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag");
let val = getPropertyBagValue(extra, "PluginUserComment");
if (config.comment)
is(val, config.comment,
"Comment in extra data should match comment in textbox");
else
ok(val === undefined,
"Comment should be absent from extra data when textbox is empty");
val = getPropertyBagValue(extra, "PluginContentURL");
if (config.urlOptIn)
is(val, gBrowser.currentURI.spec,
"URL in extra data should match browser URL when opt-in checked");
else
ok(val === undefined,
"URL should be absent from extra data when opt-in not checked");
return true;
}
function getPropertyBagValue(bag, key) {
@ -224,7 +204,3 @@ function getPropertyBagValue(bag, key) {
catch (e if e.result == Cr.NS_ERROR_FAILURE) {}
return val;
}
function failWithException(err) {
ok(false, "Uncaught exception: " + err + "\n" + err.stack);
}

View File

@ -126,8 +126,13 @@ RESPATH = $(BINPATH)
endif
DEFINES += -DRESPATH=$(RESPATH)
AB = $(firstword $(subst -, ,$(AB_CD)))
DEFINES += -DAB=$(AB)
LPROJ_ROOT = $(firstword $(subst -, ,$(AB_CD)))
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
ifeq (zh-TW,$(AB_CD))
LPROJ_ROOT := $(subst -,_,$(AB_CD))
endif
endif
DEFINES += -DLPROJ_ROOT=$(LPROJ_ROOT)
DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_VERSION)
ifdef MOZ_NATIVE_ICU

View File

@ -38,7 +38,7 @@
@APPNAME@/Contents/PkgInfo
@RESPATH@/firefox.icns
@RESPATH@/document.icns
@RESPATH@/@AB@.lproj/*
@RESPATH@/@LPROJ_ROOT@.lproj/*
#endif
[@AB_CD@]

View File

@ -349,6 +349,7 @@ CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
endif # MOZ_OPTIMIZE == 1
LDFLAGS += $(MOZ_OPTIMIZE_LDFLAGS)
RUSTFLAGS += $(MOZ_OPTIMIZE_RUSTFLAGS)
endif # MOZ_OPTIMIZE
ifdef CROSS_COMPILE

View File

@ -888,7 +888,8 @@ $(basename $2$(notdir $1)).$(OBJ_SUFFIX): $1 $$(call mkdir_deps,$$(MDDEPDIR))
endef
$(foreach f,$(CSRCS) $(SSRCS) $(CPPSRCS) $(CMSRCS) $(CMMSRCS) $(ASFILES),$(eval $(call src_objdep,$(f))))
$(foreach f,$(HOST_CSRCS) $(HOST_CPPSRCS) $(HOST_CMSRCS) $(HOST_CMMSRCS),$(eval $(call src_objdep,$(f),host_)))
# The rust compiler only outputs library objects, and so we need different
# The Rust compiler only outputs library objects, and so we need different
# mangling to generate dependency rules for it.
mk_libname = $(basename lib$(notdir $1)).$(LIB_SUFFIX)
src_libdep = $(call mk_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
@ -946,7 +947,7 @@ ifdef MOZ_RUST
# in the target's LIBS.
$(RSOBJS):
$(REPORT_BUILD)
$(RUSTC) --crate-type staticlib -o $(call mk_libname,$<) $(_VPATH_SRCS)
$(RUSTC) $(RUSTFLAGS) --crate-type staticlib -o $(call mk_libname,$<) $(_VPATH_SRCS)
endif
$(SOBJS):

View File

@ -29,6 +29,7 @@ LDFLAGS="${LDFLAGS=}"
HOST_CFLAGS="${HOST_CFLAGS=}"
HOST_CXXFLAGS="${HOST_CXXFLAGS=}"
HOST_LDFLAGS="${HOST_LDFLAGS=}"
RUSTFLAGS="${RUSTFLAGS=}"
dnl ========================================================
dnl = Preserve certain environment flags passed to configure
@ -429,7 +430,7 @@ if test -n "$RUSTC"; then
AC_MSG_RESULT([$RUSTC_VERSION (v${_RUSTC_MAJOR_VERSION}.${_RUSTC_MINOR_VERSION}.${_RUSTC_PATCH_VERSION})])
fi
MOZ_ARG_ENABLE_BOOL([rust],
[ --enable-rust Include rust language sources],
[ --enable-rust Include Rust language sources],
[MOZ_RUST=1],
[MOZ_RUST= ])
if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
@ -440,7 +441,7 @@ fi
if test -n "$MOZ_RUST" && test -z "$_RUSTC_MAJOR_VERSION" -o \
"$_RUSTC_MAJOR_VERSION" -lt 1; then
AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old.
To compile rust language sources please install at least
To compile Rust language sources please install at least
version 1.0 of the 'rustc' toolchain and make sure it is
first in your path.
You can verify this by typing 'rustc --version'.])
@ -505,7 +506,7 @@ EOF
if test -z "$MOZ_RUST"; then
AC_MSG_ERROR([rustc does not support MacOS X $MACOSX_DEPLOYMENT_TARGET
Add 'ac_add_options --enable-macos-target=10.7' (or later)
to mozconfig, disable rust support, or use an alternate toolchain.])
to mozconfig, disable Rust support, or use an alternate toolchain.])
fi
fi
@ -7054,6 +7055,10 @@ if test -z "$MOZ_OPTIMIZE_FLAGS"; then
MOZ_OPTIMIZE_FLAGS="-O"
fi
if test -z "$MOZ_OPTIMIZE_RUSTFLAGS"; then
MOZ_OPTIMIZE_RUSTFLAGS="-O"
fi
MOZ_ARG_ENABLE_STRING(optimize,
[ --disable-optimize Disable compiler optimization
--enable-optimize=[OPT] Specify compiler optimization flags [OPT=-O]],
@ -7071,7 +7076,7 @@ MOZ_SET_FRAMEPTR_FLAGS
if test "$COMPILE_ENVIRONMENT"; then
if test -n "$MOZ_OPTIMIZE"; then
AC_MSG_CHECKING([for valid optimization flags])
AC_MSG_CHECKING([for valid C compiler optimization flags])
_SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $MOZ_OPTIMIZE_FLAGS"
AC_TRY_COMPILE([#include <stdio.h>],
@ -7080,7 +7085,7 @@ if test -n "$MOZ_OPTIMIZE"; then
_results=no)
AC_MSG_RESULT([$_results])
if test "$_results" = "no"; then
AC_MSG_ERROR([These compiler flags are invalid: $MOZ_OPTIMIZE_FLAGS])
AC_MSG_ERROR([These compiler flags for C are invalid: $MOZ_OPTIMIZE_FLAGS])
fi
CFLAGS=$_SAVE_CFLAGS
fi
@ -7089,6 +7094,7 @@ fi # COMPILE_ENVIRONMENT
AC_SUBST(MOZ_OPTIMIZE)
AC_SUBST(MOZ_FRAMEPTR_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_FLAGS)
AC_SUBST(MOZ_OPTIMIZE_RUSTFLAGS)
AC_SUBST(MOZ_OPTIMIZE_LDFLAGS)
AC_SUBST(MOZ_ALLOW_HEAP_EXECUTE_FLAGS)
AC_SUBST(MOZ_PGO)

View File

@ -158,9 +158,7 @@ Animation::SetPlaybackRate(double aPlaybackRate)
Nullable<TimeDuration> previousTime = GetCurrentTime();
mPlaybackRate = aPlaybackRate;
if (!previousTime.IsNull()) {
ErrorResult rv;
SetCurrentTime(previousTime.Value());
MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time");
}
}
@ -449,9 +447,7 @@ Animation::SilentlySetPlaybackRate(double aPlaybackRate)
Nullable<TimeDuration> previousTime = GetCurrentTime();
mPlaybackRate = aPlaybackRate;
if (!previousTime.IsNull()) {
ErrorResult rv;
SilentlySetCurrentTime(previousTime.Value());
MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time");
}
}

View File

@ -348,6 +348,12 @@ this.PermissionsTable = { geolocation: {
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"audio-channel-system": {
app: DENY_ACTION,
trusted: DENY_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"audio-channel-telephony": {
app: DENY_ACTION,
trusted: DENY_ACTION,

View File

@ -93,6 +93,7 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
int(AUDIO_AGENT_CHANNEL_ALARM) == int(AudioChannel::Alarm) &&
int(AUDIO_AGENT_CHANNEL_TELEPHONY) == int(AudioChannel::Telephony) &&
int(AUDIO_AGENT_CHANNEL_RINGER) == int(AudioChannel::Ringer) &&
int(AUDIO_AGENT_CHANNEL_SYSTEM) == int(AudioChannel::System) &&
int(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) == int(AudioChannel::Publicnotification),
"Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelBinding.h");

View File

@ -29,7 +29,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
* 1. Changes to the playable status of this channel.
*/
[uuid(e28e1569-2a44-4f71-9cd0-216874b05d57)]
[uuid(ee39a34b-a5c7-4b30-b1ac-cd64ceedef67)]
interface nsIAudioChannelAgent : nsISupports
{
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
@ -39,6 +39,7 @@ interface nsIAudioChannelAgent : nsISupports
const long AUDIO_AGENT_CHANNEL_TELEPHONY = 4;
const long AUDIO_AGENT_CHANNEL_RINGER = 5;
const long AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION = 6;
const long AUDIO_AGENT_CHANNEL_SYSTEM = 7;
const long AUDIO_AGENT_CHANNEL_ERROR = 1000;

View File

@ -3619,7 +3619,7 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
forwarder->GetShadowManager()->SendGetAnimationTransform(
layer->AsShadowableLayer()->GetShadow(), &transform);
if (transform.type() == MaybeTransform::TMatrix4x4) {
gfx3DMatrix matrix = To3DMatrix(transform.get_Matrix4x4());
Matrix4x4 matrix = transform.get_Matrix4x4();
cssValue = nsComputedDOMStyle::MatrixToCSSValue(matrix);
}
}

View File

@ -2983,20 +2983,20 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
return NS_OK;
}
// If this is a remote child browser, call NavigateDocument to have
// the child process continue the navigation. Return a special error
// code to have the caller return early. If the child ends up not
// being focusable in some way, the child process will call back
// into document navigation again by calling MoveFocus.
TabParent* remote = TabParent::GetFrom(currentContent);
if (remote) {
remote->NavigateByKey(aForward, aForDocumentNavigation);
return NS_SUCCESS_DOM_NO_OPERATION;
}
// Next, for document navigation, check if this a non-remote child document.
bool checkSubDocument = true;
if (aForDocumentNavigation) {
// If this is a remote child browser, call NavigateDocument to have
// the child process continue the navigation. Return a special error
// code to have the caller return early. If the child ends up not
// being focusable in some way, the child process will call back
// into document navigation again by calling MoveFocus.
TabParent* remote = TabParent::GetFrom(currentContent);
if (remote) {
remote->NavigateDocument(aForward);
return NS_SUCCESS_DOM_NO_OPERATION;
}
// Next, check if this a non-remote child document.
nsIContent* docRoot = GetRootForChildDocument(currentContent);
if (docRoot) {
// If GetRootForChildDocument returned something then call

View File

@ -2079,6 +2079,7 @@ GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
GK_ATOM(baseURIProperty, "baseURIProperty")
GK_ATOM(lockedStyleStates, "lockedStyleStates")
GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
// Languages for lang-specific transforms
GK_ATOM(Japanese, "ja")

View File

@ -759,6 +759,9 @@ nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
}
// else fall through to js::Wrapper
// When we change this to always claim the property is configurable (bug
// 1178639), update the comments in nsOuterWindowProxy::defineProperty
// accordingly.
return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
}
@ -777,14 +780,29 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
return result.failCantDefineWindowElement();
}
#ifndef RELEASE_BUILD // To be turned on in bug 1178638.
// For now, allow chrome code to define non-configurable properties
// on windows, until we sort out what exactly the addon SDK is
// doing. In the meantime, this still allows us to test web compat
// behavior.
if (false && !desc.configurable() && !nsContentUtils::IsCallerChrome()) {
if (desc.hasConfigurable() && !desc.configurable() &&
!nsContentUtils::IsCallerChrome()) {
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
}
// Note that if hasConfigurable() is false we do NOT want to
// setConfigurable(true). That would make this code:
//
// var x;
// window.x = 5;
//
// fail, because the JS engine ends up converting the assignment into a define
// with !hasConfigurable(), but the var actually declared a non-configurable
// property on our underlying Window object, so the set would fail if we
// forced setConfigurable(true) here. What we want to do instead is change
// getOwnPropertyDescriptor to always claim configurable. See bug 1178639.
#endif
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
}

View File

@ -790,7 +790,6 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
[test_bug1081686.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
[test_window_define_nonconfigurable.html]
skip-if = true # bug 1107443 - code for newly-added test was disabled
[test_root_iframe.html]
[test_performance_user_timing.html]
[test_bug1126851.html]

View File

@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
/** Test for Bug 1107443 **/
try {
Object.defineProperty(window, "nosuchprop", { value: 5 });
Object.defineProperty(window, "nosuchprop", { value: 5, configurable: false });
throw "didn't throw";
} catch (e) {
is(e instanceof TypeError, true,
@ -22,9 +22,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
'Window should not have property after an attempt to define it failed');
}
Object.defineProperty(window, "nosuchprop", { value: 7, configurable: true });
Object.defineProperty(window, "nosuchprop", { value: 6 });
var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
is(typeof(desc), "object", "Should have a property now");
todo_is(desc.configurable, true, "Property should be configurable");
is(desc.writable, false, "Property should be readonly");
is(desc.value, 6, "Property should have the right value");
Object.defineProperty(window, "nosuchprop2", { value: 7, configurable: true });
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop2");
is(typeof(desc), "object", "Should have a property now");
is(desc.configurable, true, "Property should be configurable");
is(desc.writable, false, "Property should be readonly");
is(desc.value, 7, "Property should have the right value");

View File

@ -23,11 +23,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607464
* Pixel scrolling shouldn't scroll smoothly, even if general.smoothScroll is on.
**/
function scrollDown15PxWithPixelScrolling(scrollbox) {
function scrollDown150PxWithPixelScrolling(scrollbox) {
var win = scrollbox.ownerDocument.defaultView;
let event = {
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaY: 3.0,
deltaY: 30.0,
lineOrPageDeltaY: 1
};
// A pixel scroll with lineOrPageDeltaY.
@ -52,20 +52,18 @@ function runTest() {
var scrollbox = win.document.getElementById("scrollbox");
let scrollTopBefore = scrollbox.scrollTop;
scrollDown15PxWithPixelScrolling(scrollbox);
// wait for the next refresh driver run
win.requestAnimationFrame(function() {
// actually, wait for the next one before checking results, since
// scrolling might not be flushed until after this code has run
win.requestAnimationFrame(function() {
is(scrollbox.scrollTop, scrollTopBefore + 15,
"Pixel scrolling should have finished after one refresh driver iteration. " +
"We shouldn't be scrolling smoothly, even though the pref is set.");
win.addEventListener("scroll", function(e) {
is(scrollbox.scrollTop % 30, 0,
"Pixel scrolling should happen instantly, not smoothly. The " +
"scroll position " + scrollbox.scrollTop + " in this sequence of wheel " +
"events should be a multiple of 30.");
if (scrollbox.scrollTop == 150) {
win.close();
SimpleTest.finish();
});
});
}
}, true);
scrollDown150PxWithPixelScrolling(scrollbox);
}, win);
}
@ -77,6 +75,7 @@ window.onload = function() {
}
SimpleTest.waitForExplicitFinish();
SimpleTest.testInChaosMode();
</script>
</pre>

View File

@ -1211,6 +1211,7 @@ nsresult HTMLMediaElement::LoadResource()
// TODO: Handle failure: run "If the media data cannot be fetched at
// all, due to network errors, causing the user agent to give up
// trying to fetch the resource" section of resource fetch algorithm.
decoder->Shutdown();
return NS_ERROR_FAILURE;
}
nsRefPtr<MediaResource> resource =

View File

@ -5,7 +5,7 @@
#include "domstubs.idl"
[scriptable, uuid(A10D887D-7FC2-48A2-ABC6-A2027423860C)]
[scriptable, uuid(CE6F563B-BD77-4EF2-9D7C-A94C587353E4)]
interface nsITabParent : nsISupports
{
void injectTouchEvent(in AString aType,
@ -28,10 +28,13 @@ interface nsITabParent : nsISupports
readonly attribute uint64_t tabId;
/**
* If aForward is true, navigate to the first focusable document.
* If aForward is false, navigate to the last focusable document.
* Navigate by key. If aForDocumentNavigation is true, navigate by document.
* If aForDocumentNavigation is false, navigate by element.
*
* If aForward is true, navigate to the first focusable element or document.
* If aForward is false, navigate to the last focusable element or document.
*/
void navigateDocument(in bool aForward);
void navigateByKey(in bool aForward, in bool aForDocumentNavigation);
readonly attribute boolean hasContentOpener;
};

View File

@ -698,9 +698,9 @@ child:
SetIsDocShellActive(bool aIsActive);
/**
* Navigate by document.
* Navigate by key (Tab/Shift+Tab/F6/Shift+f6).
*/
NavigateDocument(bool aForward);
NavigateByKey(bool aForward, bool aForDocumentNavigation);
/**
* The parent (chrome thread) requests that the child inform it when

View File

@ -2512,7 +2512,7 @@ TabChild::RecvSetIsDocShellActive(const bool& aIsActive)
}
bool
TabChild::RecvNavigateDocument(const bool& aForward)
TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
{
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
@ -2520,9 +2520,20 @@ TabChild::RecvNavigateDocument(const bool& aForward)
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
// Move to the first or last document.
fm->MoveFocus(window, nullptr, aForward ? nsIFocusManager::MOVEFOCUS_FIRSTDOC :
nsIFocusManager::MOVEFOCUS_LASTDOC,
uint32_t type = aForward ?
(aForDocumentNavigation ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC) :
static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT)) :
(aForDocumentNavigation ? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC) :
static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LAST));
fm->MoveFocus(window, nullptr, type,
nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
// No valid root element was found, so move to the first focusable element.
if (!result && aForward && !aForDocumentNavigation) {
fm->MoveFocus(window, nullptr, nsIFocusManager::MOVEFOCUS_FIRST,
nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
}
SendRequestFocus(false);
}

View File

@ -502,7 +502,7 @@ protected:
virtual bool RecvDestroy() override;
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) override;
virtual bool RecvSetIsDocShellActive(const bool& aIsActive) override;
virtual bool RecvNavigateDocument(const bool& aForward) override;
virtual bool RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation) override;
virtual bool RecvRequestNotifyAfterRemotePaint() override;

View File

@ -2950,9 +2950,9 @@ TabParent::SetHasContentOpener(bool aHasContentOpener)
}
NS_IMETHODIMP
TabParent::NavigateDocument(bool aForward)
TabParent::NavigateByKey(bool aForward, bool aForDocumentNavigation)
{
unused << SendNavigateDocument(aForward);
unused << SendNavigateByKey(aForward, aForDocumentNavigation);
return NS_OK;
}

View File

@ -3,10 +3,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "AudioSink.h"
#include "MediaDecoderStateMachine.h"
#include "AudioStream.h"
#include "prenv.h"
#include "MediaQueue.h"
#include "VideoUtils.h"
#include "mozilla/CheckedInt.h"
namespace mozilla {
@ -19,9 +22,13 @@ extern PRLogModuleInfo* gMediaDecoderLog;
// The amount of audio frames that is used to fuzz rounding errors.
static const int64_t AUDIO_FUZZ_FRAMES = 1;
AudioSink::AudioSink(MediaDecoderStateMachine* aStateMachine,
int64_t aStartTime, AudioInfo aInfo, dom::AudioChannel aChannel)
: mStateMachine(aStateMachine)
AudioSink::AudioSink(MediaQueue<AudioData>& aAudioQueue,
ReentrantMonitor& aMonitor,
int64_t aStartTime,
const AudioInfo& aInfo,
dom::AudioChannel aChannel)
: mAudioQueue(aAudioQueue)
, mDecoderMonitor(aMonitor)
, mStartTime(aStartTime)
, mWritten(0)
, mLastGoodPosition(0)
@ -318,9 +325,6 @@ AudioSink::PlayFromAudioQueue()
StartAudioStreamPlaybackIfNeeded();
if (audio->mOffset != -1) {
mStateMachine->DispatchOnPlaybackOffsetUpdate(audio->mOffset);
}
return audio->mFrames;
}
@ -394,28 +398,10 @@ AudioSink::GetEndTime() const
return playedUsecs.value();
}
MediaQueue<AudioData>&
AudioSink::AudioQueue()
{
return mStateMachine->AudioQueue();
}
ReentrantMonitor&
AudioSink::GetReentrantMonitor()
{
return mStateMachine->mDecoder->GetReentrantMonitor();
}
void
AudioSink::AssertCurrentThreadInMonitor()
{
return mStateMachine->AssertCurrentThreadInMonitor();
}
void
AudioSink::AssertOnAudioThread()
{
MOZ_ASSERT(IsCurrentThread(mThread));
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
}
} // namespace mozilla

View File

@ -6,23 +6,30 @@
#if !defined(AudioSink_h__)
#define AudioSink_h__
#include "MediaInfo.h"
#include "nsRefPtr.h"
#include "nsISupportsImpl.h"
#include "MediaDecoderReader.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/Atomics.h"
#include "mozilla/MozPromise.h"
#include "mozilla/ReentrantMonitor.h"
namespace mozilla {
class AudioData;
class AudioStream;
class MediaDecoderStateMachine;
template <class T> class MediaQueue;
class AudioSink {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioSink)
AudioSink(MediaDecoderStateMachine* aStateMachine,
int64_t aStartTime, AudioInfo aInfo, dom::AudioChannel aChannel);
AudioSink(MediaQueue<AudioData>& aAudioQueue,
ReentrantMonitor& aMonitor,
int64_t aStartTime,
const AudioInfo& aInfo,
dom::AudioChannel aChannel);
// Return a promise which will be resolved when AudioSink finishes playing,
// or rejected if any error.
@ -92,13 +99,22 @@ private:
void StartAudioStreamPlaybackIfNeeded();
void WriteSilence(uint32_t aFrames);
MediaQueue<AudioData>& AudioQueue();
MediaQueue<AudioData>& AudioQueue() const {
return mAudioQueue;
}
ReentrantMonitor& GetReentrantMonitor() const {
return mDecoderMonitor;
}
void AssertCurrentThreadInMonitor() const {
GetReentrantMonitor().AssertCurrentThreadIn();
}
ReentrantMonitor& GetReentrantMonitor();
void AssertCurrentThreadInMonitor();
void AssertOnAudioThread();
nsRefPtr<MediaDecoderStateMachine> mStateMachine;
MediaQueue<AudioData>& mAudioQueue;
ReentrantMonitor& mDecoderMonitor;
// Thread for pushing audio onto the audio hardware.
// The "audio push thread".

View File

@ -181,6 +181,8 @@ cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel)
return CUBEB_STREAM_TYPE_VOICE_CALL;
case dom::AudioChannel::Ringer:
return CUBEB_STREAM_TYPE_RING;
case dom::AudioChannel::System:
return CUBEB_STREAM_TYPE_SYSTEM;
case dom::AudioChannel::Publicnotification:
return CUBEB_STREAM_TYPE_SYSTEM_ENFORCED;
default:

View File

@ -558,12 +558,11 @@ void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts()
nsresult MediaDecoder::ScheduleStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERTION(mDecoderStateMachine,
"Must have state machine to start state machine thread");
NS_ENSURE_STATE(mDecoderStateMachine);
if (mShuttingDown)
return NS_OK;
MOZ_ASSERT(mDecoderStateMachine);
NS_ENSURE_STATE(mDecoderStateMachine);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mDecoderStateMachine->ScheduleStateMachineCrossThread();
return NS_OK;

View File

@ -283,13 +283,17 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
timeBeginPeriod(1);
#endif
nsRefPtr<MediaDecoderStateMachine> self = this;
AudioQueue().AddPopListener(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnAudioPopped),
mTaskQueue);
[self] (const AudioData* aSample) {
self->OnAudioPopped(aSample);
}, mTaskQueue);
VideoQueue().AddPopListener(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::OnVideoPopped),
mTaskQueue);
[self] (const VideoData* aSample) {
self->OnVideoPopped(aSample);
}, mTaskQueue);
}
MediaDecoderStateMachine::~MediaDecoderStateMachine()
@ -681,19 +685,21 @@ MediaDecoderStateMachine::PushFront(VideoData* aSample)
}
void
MediaDecoderStateMachine::OnAudioPopped()
MediaDecoderStateMachine::OnAudioPopped(const AudioData* aSample)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->UpdatePlaybackOffset(std::max<int64_t>(0, aSample->mOffset));
UpdateNextFrameStatus();
DispatchAudioDecodeTaskIfNeeded();
}
void
MediaDecoderStateMachine::OnVideoPopped()
MediaDecoderStateMachine::OnVideoPopped(const VideoData* aSample)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->UpdatePlaybackOffset(aSample->mOffset);
UpdateNextFrameStatus();
DispatchVideoDecodeTaskIfNeeded();
// Notify the decode thread that the video queue's buffers may have
@ -1788,8 +1794,9 @@ MediaDecoderStateMachine::StartAudioThread()
if (HasAudio() && !mAudioSink) {
mAudioCompleted = false;
mAudioSink = new AudioSink(this, GetMediaTime(),
mInfo.mAudio, mDecoder->GetAudioChannel());
mAudioSink = new AudioSink(mAudioQueue, mDecoder->GetReentrantMonitor(),
GetMediaTime(), mInfo.mAudio,
mDecoder->GetAudioChannel());
mAudioSinkPromise.Begin(
mAudioSink->Init()->Then(
@ -2714,7 +2721,6 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames()
}
VideoQueue().PushFront(currentFrame);
if (framesRemoved > 0) {
OnPlaybackOffsetUpdate(currentFrame->mOffset);
mVideoFrameEndTime = currentFrame->GetEndTime();
MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
frameStats.NotifyPresentedFrame();
@ -3104,13 +3110,6 @@ MediaDecoderStateMachine::AudioEndTime() const
return -1;
}
void MediaDecoderStateMachine::OnPlaybackOffsetUpdate(int64_t aPlaybackOffset)
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecoder->UpdatePlaybackOffset(aPlaybackOffset);
}
void MediaDecoderStateMachine::OnAudioSinkComplete()
{
MOZ_ASSERT(OnTaskQueue());

View File

@ -119,7 +119,6 @@ extern PRLogModuleInfo* gMediaSampleLog;
*/
class MediaDecoderStateMachine
{
friend class AudioSink;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderStateMachine)
public:
typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
@ -398,8 +397,8 @@ protected:
void PushFront(AudioData* aSample);
void PushFront(VideoData* aSample);
void OnAudioPopped();
void OnVideoPopped();
void OnAudioPopped(const AudioData* aSample);
void OnVideoPopped(const VideoData* aSample);
void VolumeChanged();
void LogicalPlaybackRateChanged();
@ -667,17 +666,6 @@ protected:
// Can only be called on the state machine thread.
void SetPlayStartTime(const TimeStamp& aTimeStamp);
private:
// Update mDecoder's playback offset.
void OnPlaybackOffsetUpdate(int64_t aPlaybackOffset);
public:
void DispatchOnPlaybackOffsetUpdate(int64_t aPlaybackOffset)
{
RefPtr<nsRunnable> r =
NS_NewRunnableMethodWithArg<int64_t>(this, &MediaDecoderStateMachine::OnPlaybackOffsetUpdate, aPlaybackOffset);
OwnerThread()->Dispatch(r.forget());
}
private:
// Resolved by the AudioSink to signal that all outstanding work is complete
// and the sink is shutting down.

View File

@ -52,31 +52,34 @@ public:
OnSuccess(nsIVariant* aDevices) override
{
// Cribbed from MediaPermissionGonk.cpp
nsIID elementIID;
uint16_t elementType;
// Create array for nsIMediaDevice
nsTArray<nsCOMPtr<nsIMediaDevice>> devices;
// Contain the fumes
{
void* rawArray;
uint32_t arrayLen;
nsresult rv;
rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
uint16_t vtype;
nsresult rv = aDevices->GetDataType(&vtype);
NS_ENSURE_SUCCESS(rv, rv);
if (vtype != nsIDataType::VTYPE_EMPTY_ARRAY) {
nsIID elementIID;
uint16_t elementType;
void* rawArray;
uint32_t arrayLen;
rv = aDevices->GetAsArray(&elementType, &elementIID, &arrayLen, &rawArray);
NS_ENSURE_SUCCESS(rv, rv);
if (elementType != nsIDataType::VTYPE_INTERFACE) {
free(rawArray);
return NS_ERROR_FAILURE;
}
if (elementType != nsIDataType::VTYPE_INTERFACE) {
free(rawArray);
return NS_ERROR_FAILURE;
nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
for (uint32_t i = 0; i < arrayLen; ++i) {
nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
devices.AppendElement(device);
NS_IF_RELEASE(supportsArray[i]); // explicitly decrease refcount for rawptr
}
free(rawArray); // explicitly free memory from nsIVariant::GetAsArray
}
nsISupports **supportsArray = reinterpret_cast<nsISupports **>(rawArray);
for (uint32_t i = 0; i < arrayLen; ++i) {
nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supportsArray[i]));
devices.AppendElement(device);
NS_IF_RELEASE(supportsArray[i]); // explicitly decrease refcount for rawptr
}
free(rawArray); // explicitly free memory from nsIVariant::GetAsArray
}
nsTArray<nsRefPtr<MediaDeviceInfo>> infos;
for (auto& device : devices) {

View File

@ -1683,12 +1683,12 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
if (!privileged) {
// only allow privileged content to set the window id
if (vc.mBrowserWindow.WasPassed()) {
vc.mBrowserWindow.Construct(-1);
vc.mBrowserWindow.Value() = -1;
}
if (vc.mAdvanced.WasPassed()) {
for (MediaTrackConstraintSet& cs : vc.mAdvanced.Value()) {
if (cs.mBrowserWindow.WasPassed()) {
cs.mBrowserWindow.Construct(-1);
cs.mBrowserWindow.Value() = -1;
}
}
}

View File

@ -7,8 +7,8 @@
#define MediaQueue_h_
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/UniquePtr.h"
#include "nsDeque.h"
#include "nsTArray.h"
@ -24,14 +24,44 @@ class MediaQueueDeallocator : public nsDequeFunctor {
}
};
template <class T> class MediaQueue : private nsDeque {
public:
template <class T>
class MediaQueue : private nsDeque {
struct Listener {
virtual ~Listener() {}
virtual void Dispatch(T* aItem) = 0;
};
MediaQueue()
: nsDeque(new MediaQueueDeallocator<T>()),
mReentrantMonitor("mediaqueue"),
mEndOfStream(false)
{}
template<typename Function>
class PopListener : public Listener {
public:
explicit PopListener(const Function& aFunction, TaskQueue* aTarget)
: mFunction(aFunction), mTarget(aTarget) {}
void Dispatch(T* aItem) override {
nsRefPtr<T> item = aItem;
Function function = mFunction;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
function(item);
});
mTarget->Dispatch(r.forget());
}
private:
Function mFunction;
nsRefPtr<TaskQueue> mTarget;
};
void NotifyPopListeners(T* aItem) {
for (auto&& l : mPopListeners) {
l->Dispatch(aItem);
}
}
public:
MediaQueue()
: nsDeque(new MediaQueueDeallocator<T>()),
mReentrantMonitor("mediaqueue"),
mEndOfStream(false)
{}
~MediaQueue() {
Reset();
@ -60,7 +90,7 @@ template <class T> class MediaQueue : private nsDeque {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsRefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
if (rv) {
NotifyPopListeners();
NotifyPopListeners(rv);
}
return rv.forget();
}
@ -160,39 +190,16 @@ template <class T> class MediaQueue : private nsDeque {
mPopListeners.Clear();
}
void AddPopListener(nsIRunnable* aRunnable, TaskQueue* aTarget) {
template<typename Function>
void AddPopListener(const Function& aFunction, TaskQueue* aTarget) {
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mPopListeners.AppendElement(Listener(aRunnable, aTarget));
mPopListeners.AppendElement()->reset(
new PopListener<Function>(aFunction, aTarget));
}
private:
mutable ReentrantMonitor mReentrantMonitor;
struct Listener {
Listener(nsIRunnable* aRunnable, TaskQueue* aTarget)
: mRunnable(aRunnable)
, mTarget(aTarget)
{
}
Listener(const Listener& aOther)
: mRunnable(aOther.mRunnable)
, mTarget(aOther.mTarget)
{
}
nsCOMPtr<nsIRunnable> mRunnable;
RefPtr<TaskQueue> mTarget;
};
nsTArray<Listener> mPopListeners;
void NotifyPopListeners() {
for (uint32_t i = 0; i < mPopListeners.Length(); i++) {
Listener& l = mPopListeners[i];
nsCOMPtr<nsIRunnable> r = l.mRunnable;
l.mTarget->Dispatch(r.forget());
}
}
nsTArray<UniquePtr<Listener>> mPopListeners;
// True when we've decoded the last frame of data in the
// bitstream for which we're queueing frame data.
bool mEndOfStream;

View File

@ -21,10 +21,10 @@ function mustFailWith(msg, reason, f) {
e => is(e.name, reason, msg + " must fail: " + e.message));
}
var pushPrefs = dict => new Promise(res => SpecialPowers.pushPrefEnv(dict, res));
var pushPrefs = (...p) => new Promise(r => SpecialPowers.pushPrefEnv({set: p}, r));
runTest(() =>
pushPrefs({ set : [["media.navigator.streams.fake", true]] })
pushPrefs(["media.navigator.streams.fake", true])
.then(() => navigator.mediaDevices.enumerateDevices())
.then(devices => {
ok(devices.length > 0, "At least one device found");
@ -58,7 +58,12 @@ runTest(() =>
() => navigator.mediaDevices.getUserMedia({
audio: { deviceId: { exact: "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=" } },
fake: true,
}))));
})))
// Check the special case of no devices found (these prefs override fake).
.then(() => pushPrefs(["media.audio_loopback_dev", "none"],
["media.video_loopback_dev", "none"]))
.then(() => navigator.mediaDevices.enumerateDevices())
.then(devices => ok(devices.length === 0, "No devices found")));
</script>
</pre>

View File

@ -95,7 +95,7 @@ runTest(function() {
var unexpected = supported.filter(key => !mustSupport.includes(key));
is(unexpected.length, 0,
"Unexpected support (please update test): " + unexpected);
"Unanticipated support (please update test): " + unexpected);
// Run constraint tests

View File

@ -41,7 +41,9 @@ if CONFIG['MOZ_WEBSPEECH']:
'test/nsFakeSynthServices.cpp'
]
if CONFIG['MOZ_SYNTH_PICO']:
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DIRS = ['windows']
elif CONFIG['MOZ_SYNTH_PICO']:
DIRS = ['pico']
IPDL_SOURCES += [

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "mozilla/ModuleUtils.h"
#include "nsIClassInfoImpl.h"
#include "SapiService.h"
using namespace mozilla::dom;
#define SAPISERVICE_CID \
{0x21b4a45b, 0x9806, 0x4021, {0xa7, 0x06, 0xd7, 0x68, 0xab, 0x05, 0x48, 0xf9}}
#define SAPISERVICE_CONTRACTID "@mozilla.org/synthsapi;1"
// Defines SapiServiceConstructor
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SapiService,
SapiService::GetInstanceForService)
// Defines kSAPISERVICE_CID
NS_DEFINE_NAMED_CID(SAPISERVICE_CID);
static const mozilla::Module::CIDEntry kCIDs[] = {
{ &kSAPISERVICE_CID, true, nullptr, SapiServiceConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kContracts[] = {
{ SAPISERVICE_CONTRACTID, &kSAPISERVICE_CID },
{ nullptr }
};
static const mozilla::Module::CategoryEntry kCategories[] = {
{ "profile-after-change", "Sapi Speech Synth", SAPISERVICE_CONTRACTID },
{ nullptr }
};
static void
UnloadSapiModule()
{
SapiService::Shutdown();
}
static const mozilla::Module kModule = {
mozilla::Module::kVersion,
kCIDs,
kContracts,
kCategories,
nullptr,
nullptr,
UnloadSapiModule
};
NSMODULE_DEFN(synthsapi) = &kModule;

View File

@ -0,0 +1,381 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "nsISupports.h"
#include "SapiService.h"
#include "nsServiceManagerUtils.h"
#include "nsWin32Locale.h"
#include "mozilla/dom/nsSynthVoiceRegistry.h"
#include "mozilla/dom/nsSpeechTask.h"
#include "mozilla/Preferences.h"
#include <sphelper.h>
namespace mozilla {
namespace dom {
StaticRefPtr<SapiService> SapiService::sSingleton;
class SapiCallback final : public nsISpeechTaskCallback
{
public:
SapiCallback(nsISpeechTask* aTask, ISpVoice* aSapiClient,
uint32_t aTextOffset, uint32_t aSpeakTextLen)
: mTask(aTask)
, mSapiClient(aSapiClient)
, mTextOffset(aTextOffset)
, mSpeakTextLen(aSpeakTextLen)
, mCurrentIndex(0)
, mStreamNum(0)
{
mStartingTime = GetTickCount();
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(SapiCallback, nsISpeechTaskCallback)
NS_DECL_NSISPEECHTASKCALLBACK
ULONG GetStreamNum() const { return mStreamNum; }
void SetStreamNum(ULONG aValue) { mStreamNum = aValue; }
void OnSpeechEvent(const SPEVENT& speechEvent);
private:
~SapiCallback() { }
// This pointer is used to dispatch events
nsCOMPtr<nsISpeechTask> mTask;
nsRefPtr<ISpVoice> mSapiClient;
uint32_t mTextOffset;
uint32_t mSpeakTextLen;
// Used for calculating the time taken to speak the utterance
double mStartingTime;
uint32_t mCurrentIndex;
ULONG mStreamNum;
};
NS_IMPL_CYCLE_COLLECTION(SapiCallback, mTask);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SapiCallback)
NS_INTERFACE_MAP_ENTRY(nsISpeechTaskCallback)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechTaskCallback)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(SapiCallback)
NS_IMPL_CYCLE_COLLECTING_RELEASE(SapiCallback)
NS_IMETHODIMP
SapiCallback::OnPause()
{
if (FAILED(mSapiClient->Pause())) {
return NS_ERROR_FAILURE;
}
mTask->DispatchPause(GetTickCount() - mStartingTime, mCurrentIndex);
return NS_OK;
}
NS_IMETHODIMP
SapiCallback::OnResume()
{
if (FAILED(mSapiClient->Resume())) {
return NS_ERROR_FAILURE;
}
mTask->DispatchResume(GetTickCount() - mStartingTime, mCurrentIndex);
return NS_OK;
}
NS_IMETHODIMP
SapiCallback::OnCancel()
{
// After cancel, mCurrentIndex may be updated.
// At cancel case, use mCurrentIndex for DispatchEnd.
mSpeakTextLen = 0;
// Purge all the previous utterances and speak an empty string
if (FAILED(mSapiClient->Speak(nullptr, SPF_PURGEBEFORESPEAK, nullptr))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
void
SapiCallback::OnSpeechEvent(const SPEVENT& speechEvent)
{
switch (speechEvent.eEventId) {
case SPEI_START_INPUT_STREAM:
mTask->DispatchStart();
break;
case SPEI_END_INPUT_STREAM:
if (mSpeakTextLen) {
mCurrentIndex = mSpeakTextLen;
}
mTask->DispatchEnd(GetTickCount() - mStartingTime, mCurrentIndex);
mTask = nullptr;
break;
case SPEI_TTS_BOOKMARK:
mCurrentIndex = static_cast<ULONG>(speechEvent.lParam) - mTextOffset;
mTask->DispatchBoundary(NS_LITERAL_STRING("mark"),
GetTickCount() - mStartingTime, mCurrentIndex);
break;
case SPEI_WORD_BOUNDARY:
mCurrentIndex = static_cast<ULONG>(speechEvent.lParam) - mTextOffset;
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
GetTickCount() - mStartingTime, mCurrentIndex);
break;
case SPEI_SENTENCE_BOUNDARY:
mCurrentIndex = static_cast<ULONG>(speechEvent.lParam) - mTextOffset;
mTask->DispatchBoundary(NS_LITERAL_STRING("sentence"),
GetTickCount() - mStartingTime, mCurrentIndex);
break;
}
}
// static
void __stdcall
SapiService::SpeechEventCallback(WPARAM aWParam, LPARAM aLParam)
{
nsRefPtr<SapiService> service = (SapiService*) aWParam;
SPEVENT speechEvent;
while (service->mSapiClient->GetEvents(1, &speechEvent, nullptr) == S_OK) {
for (size_t i = 0; i < service->mCallbacks.Length(); i++) {
nsRefPtr<SapiCallback> callback = service->mCallbacks[i];
if (callback->GetStreamNum() == speechEvent.ulStreamNum) {
callback->OnSpeechEvent(speechEvent);
if (speechEvent.eEventId == SPEI_END_INPUT_STREAM) {
service->mCallbacks.RemoveElementAt(i);
}
break;
}
}
}
}
NS_INTERFACE_MAP_BEGIN(SapiService)
NS_INTERFACE_MAP_ENTRY(nsISpeechService)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechService)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(SapiService)
NS_IMPL_RELEASE(SapiService)
SapiService::SapiService()
: mInitialized(false)
{
}
SapiService::~SapiService()
{
}
bool
SapiService::Init()
{
MOZ_ASSERT(!mInitialized);
if (Preferences::GetBool("media.webspeech.synth.test")) {
// When enabled, we shouldn't add OS backend (Bug 1160844)
return nullptr;
}
if (FAILED(CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL, IID_ISpVoice,
getter_AddRefs(mSapiClient)))) {
return false;
}
// Set interest for all the events we are interested in
ULONGLONG eventMask =
SPFEI(SPEI_START_INPUT_STREAM) |
SPFEI(SPEI_TTS_BOOKMARK) |
SPFEI(SPEI_WORD_BOUNDARY) |
SPFEI(SPEI_SENTENCE_BOUNDARY) |
SPFEI(SPEI_END_INPUT_STREAM);
if (FAILED(mSapiClient->SetInterest(eventMask, eventMask))) {
return false;
}
// Get all the voices from sapi and register in the SynthVoiceRegistry
if (!RegisterVoices()) {
return false;
}
// Set the callback function for receiving the events
mSapiClient->SetNotifyCallbackFunction(
(SPNOTIFYCALLBACK*) SapiService::SpeechEventCallback, (WPARAM) this, 0);
mInitialized = true;
return true;
}
bool
SapiService::RegisterVoices()
{
nsresult rv;
nsCOMPtr<nsISynthVoiceRegistry> registry =
do_GetService(NS_SYNTHVOICEREGISTRY_CONTRACTID);
if (!registry) {
return false;
}
nsRefPtr<IEnumSpObjectTokens> voiceTokens;
if (FAILED(SpEnumTokens(SPCAT_VOICES, nullptr, nullptr,
getter_AddRefs(voiceTokens)))) {
return false;
}
while (true) {
nsRefPtr<ISpObjectToken> voiceToken;
if (voiceTokens->Next(1, getter_AddRefs(voiceToken), nullptr) != S_OK) {
break;
}
WCHAR* description = nullptr;
if (FAILED(SpGetDescription(voiceToken, &description))) {
continue;
}
nsRefPtr<ISpDataKey> attributes;
if (FAILED(voiceToken->OpenKey(L"Attributes",
getter_AddRefs(attributes)))) {
continue;
}
WCHAR* language = nullptr;
if (FAILED(attributes->GetStringValue(L"Language", &language))) {
continue;
}
// Language attribute is LCID by hex. So we need convert to locale
// name.
nsAutoString hexLcid;
LCID lcid = wcstol(language, nullptr, 16);
nsAutoString locale;
nsWin32Locale::GetXPLocale(lcid, locale);
nsAutoString uri;
uri.AssignLiteral("urn:moz-tts:sapi:");
uri.Append(description);
uri.AppendLiteral("?");
uri.Append(locale);
rv = registry->AddVoice(this, uri, nsDependentString(description), locale,
true);
if (NS_FAILED(rv)) {
continue;
}
mVoices.Put(uri, voiceToken);
}
return true;
}
NS_IMETHODIMP
SapiService::Speak(const nsAString& aText, const nsAString& aUri,
float aVolume, float aRate, float aPitch,
nsISpeechTask* aTask)
{
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_AVAILABLE);
nsRefPtr<ISpObjectToken> voiceToken;
if (!mVoices.Get(aUri, getter_AddRefs(voiceToken))) {
return NS_ERROR_NOT_AVAILABLE;
}
if (FAILED(mSapiClient->SetVoice(voiceToken))) {
return NS_ERROR_FAILURE;
}
if (FAILED(mSapiClient->SetVolume(static_cast<USHORT>(aVolume * 100)))) {
return NS_ERROR_FAILURE;
}
if (FAILED(mSapiClient->SetRate(static_cast<long>(10 * log10(aRate))))) {
return NS_ERROR_FAILURE;
}
// Set the pitch using xml
nsAutoString xml;
xml.AssignLiteral("<pitch absmiddle=\"");
xml.AppendFloat(aPitch * 10.0f - 10.0f);
xml.AppendLiteral("\">");
uint32_t textOffset = xml.Length();
xml.Append(aText);
xml.AppendLiteral("</pitch>");
nsRefPtr<SapiCallback> callback =
new SapiCallback(aTask, mSapiClient, textOffset, aText.Length());
// The last three parameters doesn't matter for an indirect service
nsresult rv = aTask->Setup(callback, 0, 0, 0);
if (NS_FAILED(rv)) {
return rv;
}
ULONG streamNum;
if (FAILED(mSapiClient->Speak(xml.get(), SPF_ASYNC, &streamNum))) {
aTask->Setup(nullptr, 0, 0, 0);
return NS_ERROR_FAILURE;
}
callback->SetStreamNum(streamNum);
// streamNum reassigns same value when last stream is finished even if
// callback for stream end isn't called
// So we cannot use data hashtable and has to add it to vector at last.
mCallbacks.AppendElement(callback);
return NS_OK;
}
NS_IMETHODIMP
SapiService::GetServiceType(SpeechServiceType* aServiceType)
{
*aServiceType = nsISpeechService::SERVICETYPE_INDIRECT_AUDIO;
return NS_OK;
}
SapiService*
SapiService::GetInstance()
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
MOZ_ASSERT(false,
"SapiService can only be started on main gecko process");
return nullptr;
}
if (!sSingleton) {
nsRefPtr<SapiService> service = new SapiService();
if (service->Init()) {
sSingleton = service;
}
}
return sSingleton;
}
already_AddRefed<SapiService>
SapiService::GetInstanceForService()
{
nsRefPtr<SapiService> sapiService = GetInstance();
return sapiService.forget();
}
void
SapiService::Shutdown()
{
if (!sSingleton) {
return;
}
sSingleton = nullptr;
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef mozilla_dom_SapiService_h
#define mozilla_dom_SapiService_h
#include "nsAutoPtr.h"
#include "nsISpeechService.h"
#include "nsRefPtrHashtable.h"
#include "nsTArray.h"
#include "mozilla/StaticPtr.h"
#include <windows.h>
#include <sapi.h>
namespace mozilla {
namespace dom {
class SapiCallback;
class SapiService final : public nsISpeechService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISPEECHSERVICE
SapiService();
bool Init();
static SapiService* GetInstance();
static already_AddRefed<SapiService> GetInstanceForService();
static void Shutdown();
static void __stdcall SpeechEventCallback(WPARAM aWParam, LPARAM aLParam);
private:
virtual ~SapiService();
bool RegisterVoices();
nsRefPtrHashtable<nsStringHashKey, ISpObjectToken> mVoices;
nsTArray<nsRefPtr<SapiCallback>> mCallbacks;
nsRefPtr<ISpVoice> mSapiClient;
bool mInitialized;
static StaticRefPtr<SapiService> sSingleton;
};
} // namespace dom
} // namespace mozilla
#endif

View File

@ -0,0 +1,13 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
UNIFIED_SOURCES += [
'SapiModule.cpp',
'SapiService.cpp'
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -1311,6 +1311,12 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel,
rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
NS_ENSURE_SUCCESS(rv, rv);
// Preflight requests should never be intercepted by service workers.
nsCOMPtr<nsIHttpChannelInternal> preInternal = do_QueryInterface(preflightChannel);
if (preInternal) {
preInternal->ForceNoIntercept();
}
// Set up listener which will start the original channel
nsCOMPtr<nsIStreamListener> preflightListener =

View File

@ -268,6 +268,16 @@ SVGUseElement::CreateAnonymousContent()
if (!newcontent)
return nullptr;
#ifdef DEBUG
// Our anonymous clone can get restyled by various things
// (e.g. SMIL). Reconstructing its frame is OK, though, because
// it's going to be our _only_ child in the frame tree, so can't get
// mis-ordered with anything.
newcontent->SetProperty(nsGkAtoms::restylableAnonymousNode,
reinterpret_cast<void*>(true));
#endif // DEBUG
if (newcontent->IsSVGElement(nsGkAtoms::symbol)) {
nsIDocument *document = GetComposedDoc();
if (!document)

View File

@ -783,10 +783,6 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex)
}
}
status = SetStreamVolumeIndex(AUDIO_STREAM_MUSIC, aIndex);
if (NS_WARN_IF(NS_FAILED(status))) {
return status;
}
status = SetStreamVolumeIndex(AUDIO_STREAM_SYSTEM, aIndex);
break;
case VOLUME_NOTIFICATION:
status = SetStreamVolumeIndex(AUDIO_STREAM_NOTIFICATION, aIndex);
@ -794,6 +790,10 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex)
return status;
}
status = SetStreamVolumeIndex(AUDIO_STREAM_RING, aIndex);
if (NS_WARN_IF(NS_FAILED(status))) {
return status;
}
status = SetStreamVolumeIndex(AUDIO_STREAM_SYSTEM, aIndex);
break;
case VOLUME_ALARM:
status = SetStreamVolumeIndex(AUDIO_STREAM_ALARM, aIndex);
@ -814,12 +814,12 @@ AudioManager::GetVolumeByCategory(uint32_t aCategory) const
{
switch (static_cast<AudioVolumeCategories>(aCategory)) {
case VOLUME_MEDIA:
MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
mCurrentStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
return mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC];
case VOLUME_NOTIFICATION:
MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
mCurrentStreamVolumeTbl[AUDIO_STREAM_RING]);
MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
mCurrentStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
return mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION];
case VOLUME_ALARM:
return mCurrentStreamVolumeTbl[AUDIO_STREAM_ALARM];
@ -838,12 +838,12 @@ AudioManager::GetMaxVolumeByCategory(uint32_t aCategory) const
{
switch (static_cast<AudioVolumeCategories>(aCategory)) {
case VOLUME_MEDIA:
MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
sMaxStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
return sMaxStreamVolumeTbl[AUDIO_STREAM_MUSIC];
case VOLUME_NOTIFICATION:
MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
sMaxStreamVolumeTbl[AUDIO_STREAM_RING]);
MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
sMaxStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
return sMaxStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION];
case VOLUME_ALARM:
return sMaxStreamVolumeTbl[AUDIO_STREAM_ALARM];
@ -871,6 +871,7 @@ AudioManager::SetAudioChannelVolume(uint32_t aChannel, uint32_t aIndex)
case AudioChannel::Notification:
case AudioChannel::Ringer:
case AudioChannel::Publicnotification:
case AudioChannel::System:
status = SetVolumeByCategory(VOLUME_NOTIFICATION, aIndex);
break;
case AudioChannel::Alarm:
@ -901,6 +902,7 @@ AudioManager::GetAudioChannelVolume(uint32_t aChannel, uint32_t* aIndex)
case AudioChannel::Notification:
case AudioChannel::Ringer:
case AudioChannel::Publicnotification:
case AudioChannel::System:
*aIndex = GetVolumeByCategory(VOLUME_NOTIFICATION);
break;
case AudioChannel::Alarm:
@ -931,6 +933,7 @@ AudioManager::GetMaxAudioChannelVolume(uint32_t aChannel, uint32_t* aMaxIndex)
case AudioChannel::Notification:
case AudioChannel::Ringer:
case AudioChannel::Publicnotification:
case AudioChannel::System:
*aMaxIndex = GetMaxVolumeByCategory(VOLUME_NOTIFICATION);
break;
case AudioChannel::Alarm:

View File

@ -46,4 +46,5 @@ enum AudioChannel {
"telephony",
"ringer",
"publicnotification",
"system"
};

View File

@ -140,6 +140,12 @@ fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_serv
finish();
});
// Test that CORS preflight requests cannot be intercepted
fetchXHR('http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*', null, function(xhr) {
my_ok(xhr.status == 0, "cross origin load with incorrect headers should be a failure");
finish();
}, [["X-Unsafe", "unsafe"]]);
// Test that when the page fetches a url the controlling SW forces a redirect to
// another location. This other location fetch should also be intercepted by
// the SW.

View File

@ -7,6 +7,16 @@ onfetch = function(ev) {
));
}
else if (ev.request.url.includes('file_CrossSiteXHR_server.sjs')) {
// N.B. this response would break the rules of CORS if it were allowed, but
// this test relies upon the preflight request not being intercepted and
// thus this response should not be used.
if (ev.request.method == 'OPTIONS') {
ev.respondWith(new Response('', {headers: {'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'X-Unsafe'}}))
}
}
else if (ev.request.url.includes("synthesized-404.txt")) {
ev.respondWith(Promise.resolve(
new Response("synthesized response body", { status: 404 })

View File

@ -188,6 +188,15 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aPare
parentContent->AddMutationObserver(observer);
newContent->AddMutationObserver(observer);
#ifdef DEBUG
// Editor anonymous content gets passed to RecreateFramesFor... which can't
// _really_ deal with anonymous content (because it can't get the frame tree
// ordering right). But for us the ordering doesn't matter so this is sort of
// ok.
newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
reinterpret_cast<void*>(true));
#endif // DEBUG
// display the element
ps->RecreateFramesFor(newContent);

View File

@ -9,11 +9,56 @@
#include <algorithm>
#include <ostream>
#include <math.h>
#include <float.h> // for FLT_EPSILON
#include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
using namespace std;
namespace {
/* Force small values to zero. We do this to avoid having sin(360deg)
* evaluate to a tiny but nonzero value.
*/
double
FlushToZero(double aVal)
{
// XXX Is double precision really necessary here
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON) {
return 0.0f;
} else {
return aVal;
}
}
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
* undefined or very large, SafeTangent returns a manageably large value
* of the correct sign.
*/
double
SafeTangent(double aTheta)
{
// XXX Is double precision really necessary here
const double kEpsilon = 0.0001;
/* tan(theta) = sin(theta)/cos(theta); problems arise when
* cos(theta) is too close to zero. Limit cos(theta) to the
* range [-1, -epsilon] U [epsilon, 1].
*/
double sinTheta = sin(aTheta);
double cosTheta = cos(aTheta);
if (cosTheta >= 0 && cosTheta < kEpsilon) {
cosTheta = kEpsilon;
} else if (cosTheta < 0 && cosTheta >= -kEpsilon) {
cosTheta = -kEpsilon;
}
return FlushToZero(sinTheta / cosTheta);
}
} // namespace
namespace mozilla {
namespace gfx {
@ -397,5 +442,134 @@ Matrix4x4::SetRotationFromQuaternion(const Quaternion& q)
_44 = 1.0f;
}
void
Matrix4x4::SkewXY(double aXSkew, double aYSkew)
{
// XXX Is double precision really necessary here
float tanX = SafeTangent(aXSkew);
float tanY = SafeTangent(aYSkew);
float temp;
temp = _11;
_11 += tanY * _21;
_21 += tanX * temp;
temp = _12;
_12 += tanY * _22;
_22 += tanX * temp;
temp = _13;
_13 += tanY * _23;
_23 += tanX * temp;
temp = _14;
_14 += tanY * _24;
_24 += tanX * temp;
}
void
Matrix4x4::RotateX(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _21;
_21 = cosTheta * _21 + sinTheta * _31;
_31 = -sinTheta * temp + cosTheta * _31;
temp = _22;
_22 = cosTheta * _22 + sinTheta * _32;
_32 = -sinTheta * temp + cosTheta * _32;
temp = _23;
_23 = cosTheta * _23 + sinTheta * _33;
_33 = -sinTheta * temp + cosTheta * _33;
temp = _24;
_24 = cosTheta * _24 + sinTheta * _34;
_34 = -sinTheta * temp + cosTheta * _34;
}
void
Matrix4x4::RotateY(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + -sinTheta * _31;
_31 = sinTheta * temp + cosTheta * _31;
temp = _12;
_12 = cosTheta * _12 + -sinTheta * _32;
_32 = sinTheta * temp + cosTheta * _32;
temp = _13;
_13 = cosTheta * _13 + -sinTheta * _33;
_33 = sinTheta * temp + cosTheta * _33;
temp = _14;
_14 = cosTheta * _14 + -sinTheta * _34;
_34 = sinTheta * temp + cosTheta * _34;
}
void
Matrix4x4::RotateZ(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + sinTheta * _21;
_21 = -sinTheta * temp + cosTheta * _21;
temp = _12;
_12 = cosTheta * _12 + sinTheta * _22;
_22 = -sinTheta * temp + cosTheta * _22;
temp = _13;
_13 = cosTheta * _13 + sinTheta * _23;
_23 = -sinTheta * temp + cosTheta * _23;
temp = _14;
_14 = cosTheta * _14 + sinTheta * _24;
_24 = -sinTheta * temp + cosTheta * _24;
}
void
Matrix4x4::Perspective(float aDepth)
{
MOZ_ASSERT(aDepth > 0.0f, "Perspective must be positive!");
_31 += -1.0/aDepth * _41;
_32 += -1.0/aDepth * _42;
_33 += -1.0/aDepth * _43;
_34 += -1.0/aDepth * _44;
}
Point3D
Matrix4x4::GetNormalVector() const
{
// Define a plane in transformed space as the transformations
// of 3 points on the z=0 screen plane.
Point3D a = *this * Point3D(0, 0, 0);
Point3D b = *this * Point3D(0, 1, 0);
Point3D c = *this * Point3D(1, 0, 0);
// Convert to two vectors on the surface of the plane.
Point3D ab = b - a;
Point3D ac = c - a;
return ac.CrossProduct(ab);
}
} // namespace gfx
} // namespace mozilla

View File

@ -716,6 +716,11 @@ public:
(*this)[2] += (*this)[1] * aSkew;
}
Matrix4x4 &ChangeBasis(const Point3D& aOrigin)
{
return ChangeBasis(aOrigin.x, aOrigin.y, aOrigin.z);
}
Matrix4x4 &ChangeBasis(Float aX, Float aY, Float aZ)
{
// Translate to the origin before applying this matrix
@ -950,6 +955,18 @@ public:
// Set all the members of the matrix to NaN
void SetNAN();
void SkewXY(double aXSkew, double aYSkew);
void RotateX(double aTheta);
void RotateY(double aTheta);
void RotateZ(double aTheta);
void Perspective(float aDepth);
Point3D GetNormalVector() const;
};
class Matrix5x4

View File

@ -337,7 +337,7 @@ public:
return mLayer->GetVisibleRegion();
}
nsIntRegion region = mLayer->GetVisibleRegion();
region.Transform(gfx::To3DMatrix(mLayer->GetTransform()));
region.Transform(mLayer->GetTransform());
return region;
}

View File

@ -10,7 +10,6 @@
#include <stdlib.h> // for getenv
#include "DirectedGraph.h" // for DirectedGraph
#include "Layers.h" // for Layer
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxLineSegment.h" // for gfxLineSegment
#include "gfxPoint.h" // for gfxPoint
#include "gfxQuad.h" // for gfxQuad
@ -41,11 +40,11 @@ enum LayerSortOrder {
*
* point = normal . (p0 - l0) / normal . l
*/
static gfxFloat RecoverZDepth(const gfx3DMatrix& aTransform, const gfxPoint& aPoint)
static gfxFloat RecoverZDepth(const Matrix4x4& aTransform, const gfxPoint& aPoint)
{
const Point3D l(0, 0, 1);
Point3D l0 = Point3D(aPoint.x, aPoint.y, 0);
Point3D p0 = aTransform.Transform3D(Point3D(0, 0, 0));
Point3D p0 = aTransform * Point3D(0, 0, 0);
Point3D normal = aTransform.GetNormalVector();
gfxFloat n = normal.DotProduct(p0 - l0);
@ -79,12 +78,12 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
gfxRect ourRect = aOne->GetEffectiveVisibleRegion().GetBounds();
gfxRect otherRect = aTwo->GetEffectiveVisibleRegion().GetBounds();
gfx3DMatrix ourTransform = To3DMatrix(aOne->GetTransform());
gfx3DMatrix otherTransform = To3DMatrix(aTwo->GetTransform());
Matrix4x4 ourTransform = aOne->GetTransform();
Matrix4x4 otherTransform = aTwo->GetTransform();
// Transform both rectangles and project into 2d space.
gfxQuad ourTransformedRect = ourTransform.TransformRect(ourRect);
gfxQuad otherTransformedRect = otherTransform.TransformRect(otherRect);
gfxQuad ourTransformedRect = ourRect.TransformToQuad(ourTransform);
gfxQuad otherTransformedRect = otherRect.TransformToQuad(otherTransform);
gfxRect ourBounds = ourTransformedRect.GetBounds();
gfxRect otherBounds = otherTransformedRect.GetBounds();

View File

@ -344,7 +344,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
container->SetChildrenChanged(true);
}
result.Transform(gfx::To3DMatrix(mLayer->GetLocalTransform()));
result.Transform(mLayer->GetLocalTransform());
return result;
}

View File

@ -214,7 +214,7 @@ struct EventRegions {
mVerticalPanRegion.MoveBy(aXTrans, aYTrans);
}
void Transform(const gfx3DMatrix& aTransform)
void Transform(const gfx::Matrix4x4& aTransform)
{
mHitRegion.Transform(aTransform);
mDispatchToContentHitRegion.Transform(aTransform);

View File

@ -188,7 +188,7 @@ DrawSurfaceWithTextureCoords(DrawTarget *aDest,
#ifdef MOZ_ENABLE_SKIA
static SkMatrix
Matrix3DToSkia(const gfx3DMatrix& aMatrix)
Matrix3DToSkia(const Matrix4x4& aMatrix)
{
SkMatrix transform;
transform.setAll(aMatrix._11,
@ -207,7 +207,7 @@ Matrix3DToSkia(const gfx3DMatrix& aMatrix)
static void
Transform(DataSourceSurface* aDest,
DataSourceSurface* aSource,
const gfx3DMatrix& aTransform,
const Matrix4x4& aTransform,
const Point& aDestOffset)
{
if (aTransform.IsSingular()) {
@ -233,8 +233,8 @@ Transform(DataSourceSurface* aDest,
src.setInfo(srcInfo, aSource->Stride());
src.setPixels((uint32_t*)aSource->GetData());
gfx3DMatrix transform = aTransform;
transform.TranslatePost(Point3D(-aDestOffset.x, -aDestOffset.y, 0));
Matrix4x4 transform = aTransform;
transform.PostTranslate(Point3D(-aDestOffset.x, -aDestOffset.y, 0));
destCanvas.setMatrix(Matrix3DToSkia(transform));
SkPaint paint;
@ -246,7 +246,7 @@ Transform(DataSourceSurface* aDest,
}
#else
static pixman_transform
Matrix3DToPixman(const gfx3DMatrix& aMatrix)
Matrix3DToPixman(const Matrix4x4& aMatrix)
{
pixman_f_transform transform;
@ -269,7 +269,7 @@ Matrix3DToPixman(const gfx3DMatrix& aMatrix)
static void
Transform(DataSourceSurface* aDest,
DataSourceSurface* aSource,
const gfx3DMatrix& aTransform,
const Matrix4x4& aTransform,
const Point& aDestOffset)
{
IntSize destSize = aDest->GetSize();
@ -343,7 +343,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
Matrix newTransform;
Rect transformBounds;
gfx3DMatrix new3DTransform;
Matrix4x4 new3DTransform;
IntPoint offset = mRenderTarget->GetOrigin();
if (aTransform.Is2D()) {
@ -358,8 +358,9 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
dest->SetTransform(Matrix::Translation(-aRect.x, -aRect.y));
// Get the bounds post-transform.
new3DTransform = To3DMatrix(aTransform);
gfxRect bounds = new3DTransform.TransformBounds(ThebesRect(aRect));
new3DTransform = aTransform;
gfxRect bounds = ThebesRect(aRect);
bounds.TransformBounds(new3DTransform);
bounds.IntersectRect(bounds, gfxRect(offset.x, offset.y, buffer->GetSize().width, buffer->GetSize().height));
transformBounds = ToRect(bounds);
@ -370,7 +371,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
// When we apply the 3D transformation, we do it against a temporary
// surface, so undo the coordinate offset.
new3DTransform = gfx3DMatrix::Translation(aRect.x, aRect.y, 0) * new3DTransform;
new3DTransform = Matrix4x4::Translation(aRect.x, aRect.y, 0) * new3DTransform;
}
newTransform.PostTranslate(-offset.x, -offset.y);

View File

@ -16,7 +16,6 @@
#include "RenderTrace.h" // for RenderTraceLayers, etc
#include "basic/BasicImplData.h" // for BasicImplData
#include "basic/BasicLayers.h" // for BasicLayerManager, etc
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxASurface.h" // for gfxASurface, etc
#include "gfxColor.h" // for gfxRGBA
#include "gfxContext.h" // for gfxContext, etc
@ -613,7 +612,7 @@ BasicLayerManager::SetRoot(Layer* aLayer)
#ifdef MOZ_ENABLE_SKIA
static SkMatrix
BasicLayerManager_Matrix3DToSkia(const gfx3DMatrix& aMatrix)
BasicLayerManager_Matrix3DToSkia(const Matrix4x4& aMatrix)
{
SkMatrix transform;
transform.setAll(aMatrix._11,
@ -632,7 +631,7 @@ BasicLayerManager_Matrix3DToSkia(const gfx3DMatrix& aMatrix)
static void
Transform(const gfxImageSurface* aDest,
RefPtr<DataSourceSurface> aSrc,
const gfx3DMatrix& aTransform,
const Matrix4x4& aTransform,
gfxPoint aDestOffset)
{
if (aTransform.IsSingular()) {
@ -658,8 +657,8 @@ Transform(const gfxImageSurface* aDest,
src.setInfo(srcInfo, aSrc->Stride());
src.setPixels((uint32_t*)aSrc->GetData());
gfx3DMatrix transform = aTransform;
transform.TranslatePost(Point3D(-aDestOffset.x, -aDestOffset.y, 0));
Matrix4x4 transform = aTransform;
transform.PostTranslate(Point3D(-aDestOffset.x, -aDestOffset.y, 0));
destCanvas.setMatrix(BasicLayerManager_Matrix3DToSkia(transform));
SkPaint paint;
@ -671,7 +670,7 @@ Transform(const gfxImageSurface* aDest,
}
#else
static pixman_transform
BasicLayerManager_Matrix3DToPixman(const gfx3DMatrix& aMatrix)
BasicLayerManager_Matrix3DToPixman(const Matrix4x4& aMatrix)
{
pixman_f_transform transform;
@ -694,7 +693,7 @@ BasicLayerManager_Matrix3DToPixman(const gfx3DMatrix& aMatrix)
static void
Transform(const gfxImageSurface* aDest,
RefPtr<DataSourceSurface> aSrc,
const gfx3DMatrix& aTransform,
const Matrix4x4& aTransform,
gfxPoint aDestOffset)
{
IntSize destSize = aDest->GetSize();
@ -743,7 +742,7 @@ Transform(const gfxImageSurface* aDest,
#endif
/**
* Transform a surface using a gfx3DMatrix and blit to the destination if
* Transform a surface using a Matrix4x4 and blit to the destination if
* it is efficient to do so.
*
* @param aSource Source surface.
@ -759,11 +758,12 @@ static already_AddRefed<gfxASurface>
Transform3D(RefPtr<SourceSurface> aSource,
gfxContext* aDest,
const gfxRect& aBounds,
const gfx3DMatrix& aTransform,
const Matrix4x4& aTransform,
gfxRect& aDestRect)
{
// Find the transformed rectangle of our layer.
gfxRect offsetRect = aTransform.TransformBounds(aBounds);
gfxRect offsetRect = aBounds;
offsetRect.TransformBounds(aTransform);
// Intersect the transformed layer with the destination rectangle.
// This is in device space since we have an identity transform set on aTarget.
@ -779,7 +779,7 @@ Transform3D(RefPtr<SourceSurface> aSource,
gfxPoint offset = aDestRect.TopLeft();
// Include a translation to the correct origin.
gfx3DMatrix translation = gfx3DMatrix::Translation(aBounds.x, aBounds.y, 0);
Matrix4x4 translation = Matrix4x4::Translation(aBounds.x, aBounds.y, 0);
// Transform the content and offset it such that the content begins at the origin.
Transform(destImage, aSource->GetDataSurface(), translation * aTransform, offset);
@ -961,8 +961,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
temp->Paint();
}
#endif
gfx3DMatrix effectiveTransform;
effectiveTransform = gfx::To3DMatrix(aLayer->GetEffectiveTransform());
Matrix4x4 effectiveTransform = aLayer->GetEffectiveTransform();
nsRefPtr<gfxASurface> result =
Transform3D(untransformedDT->Snapshot(), aTarget, bounds,
effectiveTransform, destRect);

View File

@ -408,7 +408,7 @@ SampleValue(float aPortion, Animation& aAnimation, StyleAnimationValue& aStart,
transformOrigin,
perspectiveOrigin,
data.perspective());
gfx3DMatrix transform =
Matrix4x4 transform =
nsDisplayTransform::GetResultingTransformMatrix(props, origin,
data.appUnitsPerDevPixel(),
&data.bounds());
@ -417,10 +417,10 @@ SampleValue(float aPortion, Animation& aAnimation, StyleAnimationValue& aStart,
NS_round(NSAppUnitsToFloatPixels(origin.y, data.appUnitsPerDevPixel())),
0.0f);
transform.Translate(scaledOrigin);
transform.PreTranslate(scaledOrigin);
InfallibleTArray<TransformFunction> functions;
functions.AppendElement(TransformMatrix(ToMatrix4x4(transform)));
functions.AppendElement(TransformMatrix(transform));
*aValue = functions;
}

View File

@ -5,7 +5,7 @@
#include "CanvasLayerComposite.h"
#include "composite/CompositableHost.h" // for CompositableHost
#include "gfx2DGlue.h" // for ToFilter, ToMatrix4x4
#include "gfx2DGlue.h" // for ToFilter
#include "GraphicsFilter.h" // for GraphicsFilter
#include "gfxUtils.h" // for gfxUtils, etc
#include "mozilla/gfx/Matrix.h" // for Matrix4x4

View File

@ -8,7 +8,6 @@
#include "apz/src/AsyncPanZoomController.h" // for AsyncPanZoomController
#include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for LayerRect, LayerPixel, etc
#include "gfx2DGlue.h" // for ToMatrix4x4
#include "gfxPrefs.h" // for gfxPrefs
#include "gfxUtils.h" // for gfxUtils, etc
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc

View File

@ -6,7 +6,7 @@
#include "ImageLayerComposite.h"
#include "CompositableHost.h" // for CompositableHost
#include "Layers.h" // for WriteSnapshotToDumpFile, etc
#include "gfx2DGlue.h" // for ToFilter, ToMatrix4x4
#include "gfx2DGlue.h" // for ToFilter
#include "gfxRect.h" // for gfxRect
#include "gfxUtils.h" // for gfxUtils, etc
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc

View File

@ -22,7 +22,6 @@
#include "TiledContentHost.h"
#include "Units.h" // for ScreenIntRect
#include "UnitTransforms.h" // for ViewAs
#include "gfx2DGlue.h" // for ToMatrix4x4
#include "gfxPrefs.h" // for gfxPrefs
#ifdef XP_MACOSX
#include "gfxPlatformMac.h"

View File

@ -7,7 +7,6 @@
#include "CompositableHost.h" // for TiledLayerProperties, etc
#include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for CSSRect, LayerPixel, etc
#include "gfx2DGlue.h" // for ToMatrix4x4
#include "gfxUtils.h" // for gfxUtils, etc
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/gfx/Matrix.h" // for Matrix4x4

View File

@ -19,7 +19,6 @@
#include "Layers.h" // for WriteSnapshotToDumpFile
#include "LayerScope.h" // for LayerScope
#include "gfx2DGlue.h" // for ThebesFilter
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxCrashReporterUtils.h" // for ScopedGfxFeatureReporter
#include "gfxMatrix.h" // for gfxMatrix
#include "GraphicsFilter.h" // for GraphicsFilter

View File

@ -6,7 +6,6 @@
#include "nsRegion.h"
#include "nsPrintfCString.h"
#include "nsTArray.h"
#include "gfx3DMatrix.h"
#include "gfxUtils.h"
bool nsRegion::Contains(const nsRegion& aRgn) const
@ -607,14 +606,14 @@ nsRegion& nsRegion::ScaleInverseRoundOut (float aXScale, float aYScale)
}
static mozilla::gfx::IntRect
TransformRect(const mozilla::gfx::IntRect& aRect, const gfx3DMatrix& aTransform)
TransformRect(const mozilla::gfx::IntRect& aRect, const mozilla::gfx::Matrix4x4& aTransform)
{
if (aRect.IsEmpty()) {
return mozilla::gfx::IntRect();
}
gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
rect = aTransform.TransformBounds(rect);
rect.TransformBounds(aTransform);
rect.RoundOut();
mozilla::gfx::IntRect intRect;
@ -625,7 +624,7 @@ TransformRect(const mozilla::gfx::IntRect& aRect, const gfx3DMatrix& aTransform)
return intRect;
}
nsRegion& nsRegion::Transform (const gfx3DMatrix &aTransform)
nsRegion& nsRegion::Transform (const mozilla::gfx::Matrix4x4 &aTransform)
{
int n;
pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n);

View File

@ -21,7 +21,11 @@
#include "mozilla/Move.h" // for mozilla::Move
class nsIntRegion;
class gfx3DMatrix;
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
} // namespace mozilla
#include "pixman.h"
@ -299,7 +303,7 @@ public:
ScaleToOtherAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const;
nsRegion& ScaleRoundOut(float aXScale, float aYScale);
nsRegion& ScaleInverseRoundOut(float aXScale, float aYScale);
nsRegion& Transform (const gfx3DMatrix &aTransform);
nsRegion& Transform (const mozilla::gfx::Matrix4x4 &aTransform);
nsIntRegion ScaleToOutsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
nsIntRegion ScaleToInsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
nsIntRegion ScaleToNearestPixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
@ -721,7 +725,7 @@ public:
return This();
}
Derived& Transform (const gfx3DMatrix &aTransform)
Derived& Transform (const mozilla::gfx::Matrix4x4 &aTransform)
{
mImpl.Transform(aTransform);
return This();

View File

@ -9,7 +9,6 @@
#include "gfxPlatform.h"
#include "gfxRect.h"
#include "gfxMatrix.h"
#include "gfx3DMatrix.h"
#include "gfxContext.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/Rect.h"
@ -310,52 +309,6 @@ inline gfxContext::GraphicsOperator ThebesOp(CompositionOp aOp)
}
}
inline Matrix4x4
ToMatrix4x4(const gfx3DMatrix& aIn)
{
Matrix4x4 m;
m._11 = aIn._11;
m._12 = aIn._12;
m._13 = aIn._13;
m._14 = aIn._14;
m._21 = aIn._21;
m._22 = aIn._22;
m._23 = aIn._23;
m._24 = aIn._24;
m._31 = aIn._31;
m._32 = aIn._32;
m._33 = aIn._33;
m._34 = aIn._34;
m._41 = aIn._41;
m._42 = aIn._42;
m._43 = aIn._43;
m._44 = aIn._44;
return m;
}
inline gfx3DMatrix
To3DMatrix(const Matrix4x4& aIn)
{
gfx3DMatrix m;
m._11 = aIn._11;
m._12 = aIn._12;
m._13 = aIn._13;
m._14 = aIn._14;
m._21 = aIn._21;
m._22 = aIn._22;
m._23 = aIn._23;
m._24 = aIn._24;
m._31 = aIn._31;
m._32 = aIn._32;
m._33 = aIn._33;
m._34 = aIn._34;
m._41 = aIn._41;
m._42 = aIn._42;
m._43 = aIn._43;
m._44 = aIn._44;
return m;
}
} // namespace gfx
} // namespace mozilla

View File

@ -1,798 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "gfxMatrix.h"
#include "gfx3DMatrix.h"
#include "gfx2DGlue.h"
#include "mozilla/gfx/Tools.h"
#include <math.h>
#include <algorithm>
using namespace std;
using namespace mozilla;
using namespace mozilla::gfx;
/* Force small values to zero. We do this to avoid having sin(360deg)
* evaluate to a tiny but nonzero value.
*/
static double FlushToZero(double aVal)
{
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
return 0.0f;
else
return aVal;
}
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
* undefined or very large, SafeTangent returns a manageably large value
* of the correct sign.
*/
static double SafeTangent(double aTheta)
{
const double kEpsilon = 0.0001;
/* tan(theta) = sin(theta)/cos(theta); problems arise when
* cos(theta) is too close to zero. Limit cos(theta) to the
* range [-1, -epsilon] U [epsilon, 1].
*/
double sinTheta = sin(aTheta);
double cosTheta = cos(aTheta);
if (cosTheta >= 0 && cosTheta < kEpsilon)
cosTheta = kEpsilon;
else if (cosTheta < 0 && cosTheta >= -kEpsilon)
cosTheta = -kEpsilon;
return FlushToZero(sinTheta / cosTheta);
}
gfx3DMatrix::gfx3DMatrix(void)
{
_11 = _22 = _33 = _44 = 1.0f;
_12 = _13 = _14 = 0.0f;
_21 = _23 = _24 = 0.0f;
_31 = _32 = _34 = 0.0f;
_41 = _42 = _43 = 0.0f;
}
gfx3DMatrix
gfx3DMatrix::operator*(const gfx3DMatrix &aMatrix) const
{
if (Is2D() && aMatrix.Is2D()) {
return Multiply2D(aMatrix);
}
gfx3DMatrix matrix;
matrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21 + _13 * aMatrix._31 + _14 * aMatrix._41;
matrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21 + _23 * aMatrix._31 + _24 * aMatrix._41;
matrix._31 = _31 * aMatrix._11 + _32 * aMatrix._21 + _33 * aMatrix._31 + _34 * aMatrix._41;
matrix._41 = _41 * aMatrix._11 + _42 * aMatrix._21 + _43 * aMatrix._31 + _44 * aMatrix._41;
matrix._12 = _11 * aMatrix._12 + _12 * aMatrix._22 + _13 * aMatrix._32 + _14 * aMatrix._42;
matrix._22 = _21 * aMatrix._12 + _22 * aMatrix._22 + _23 * aMatrix._32 + _24 * aMatrix._42;
matrix._32 = _31 * aMatrix._12 + _32 * aMatrix._22 + _33 * aMatrix._32 + _34 * aMatrix._42;
matrix._42 = _41 * aMatrix._12 + _42 * aMatrix._22 + _43 * aMatrix._32 + _44 * aMatrix._42;
matrix._13 = _11 * aMatrix._13 + _12 * aMatrix._23 + _13 * aMatrix._33 + _14 * aMatrix._43;
matrix._23 = _21 * aMatrix._13 + _22 * aMatrix._23 + _23 * aMatrix._33 + _24 * aMatrix._43;
matrix._33 = _31 * aMatrix._13 + _32 * aMatrix._23 + _33 * aMatrix._33 + _34 * aMatrix._43;
matrix._43 = _41 * aMatrix._13 + _42 * aMatrix._23 + _43 * aMatrix._33 + _44 * aMatrix._43;
matrix._14 = _11 * aMatrix._14 + _12 * aMatrix._24 + _13 * aMatrix._34 + _14 * aMatrix._44;
matrix._24 = _21 * aMatrix._14 + _22 * aMatrix._24 + _23 * aMatrix._34 + _24 * aMatrix._44;
matrix._34 = _31 * aMatrix._14 + _32 * aMatrix._24 + _33 * aMatrix._34 + _34 * aMatrix._44;
matrix._44 = _41 * aMatrix._14 + _42 * aMatrix._24 + _43 * aMatrix._34 + _44 * aMatrix._44;
return matrix;
}
gfx3DMatrix&
gfx3DMatrix::operator*=(const gfx3DMatrix &aMatrix)
{
return *this = *this * aMatrix;
}
gfx3DMatrix
gfx3DMatrix::Multiply2D(const gfx3DMatrix &aMatrix) const
{
gfx3DMatrix matrix;
matrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21;
matrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21;
matrix._41 = _41 * aMatrix._11 + _42 * aMatrix._21 + aMatrix._41;
matrix._12 = _11 * aMatrix._12 + _12 * aMatrix._22;
matrix._22 = _21 * aMatrix._12 + _22 * aMatrix._22;
matrix._42 = _41 * aMatrix._12 + _42 * aMatrix._22 + aMatrix._42;
return matrix;
}
bool
gfx3DMatrix::operator==(const gfx3DMatrix& o) const
{
// XXX would be nice to memcmp here, but that breaks IEEE 754 semantics
return _11 == o._11 && _12 == o._12 && _13 == o._13 && _14 == o._14 &&
_21 == o._21 && _22 == o._22 && _23 == o._23 && _24 == o._24 &&
_31 == o._31 && _32 == o._32 && _33 == o._33 && _34 == o._34 &&
_41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44;
}
bool
gfx3DMatrix::operator!=(const gfx3DMatrix& o) const
{
return !((*this) == o);
}
bool
gfx3DMatrix::FuzzyEqual(const gfx3DMatrix& o) const
{
static const float error = 1e-4;
return gfx::FuzzyEqual(_11, o._11, error) && gfx::FuzzyEqual(_12, o._12, error) &&
gfx::FuzzyEqual(_13, o._13, error) && gfx::FuzzyEqual(_14, o._14, error) &&
gfx::FuzzyEqual(_21, o._21, error) && gfx::FuzzyEqual(_22, o._22, error) &&
gfx::FuzzyEqual(_23, o._23, error) && gfx::FuzzyEqual(_24, o._24, error) &&
gfx::FuzzyEqual(_31, o._31, error) && gfx::FuzzyEqual(_32, o._32, error) &&
gfx::FuzzyEqual(_33, o._33, error) && gfx::FuzzyEqual(_34, o._34, error) &&
gfx::FuzzyEqual(_41, o._41, error) && gfx::FuzzyEqual(_42, o._42, error) &&
gfx::FuzzyEqual(_43, o._43, error) && gfx::FuzzyEqual(_44, o._44, error);
}
gfx3DMatrix&
gfx3DMatrix::operator/=(const gfxFloat scalar)
{
_11 /= scalar;
_12 /= scalar;
_13 /= scalar;
_14 /= scalar;
_21 /= scalar;
_22 /= scalar;
_23 /= scalar;
_24 /= scalar;
_31 /= scalar;
_32 /= scalar;
_33 /= scalar;
_34 /= scalar;
_41 /= scalar;
_42 /= scalar;
_43 /= scalar;
_44 /= scalar;
return *this;
}
gfx3DMatrix
gfx3DMatrix::From2D(const gfxMatrix &aMatrix)
{
gfx3DMatrix matrix;
matrix._11 = (float)aMatrix._11;
matrix._12 = (float)aMatrix._12;
matrix._21 = (float)aMatrix._21;
matrix._22 = (float)aMatrix._22;
matrix._41 = (float)aMatrix._31;
matrix._42 = (float)aMatrix._32;
return matrix;
}
bool
gfx3DMatrix::IsIdentity() const
{
return _11 == 1.0f && _12 == 0.0f && _13 == 0.0f && _14 == 0.0f &&
_21 == 0.0f && _22 == 1.0f && _23 == 0.0f && _24 == 0.0f &&
_31 == 0.0f && _32 == 0.0f && _33 == 1.0f && _34 == 0.0f &&
_41 == 0.0f && _42 == 0.0f && _43 == 0.0f && _44 == 1.0f;
}
void
gfx3DMatrix::Translate(const Point3D& aPoint)
{
_41 += aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31;
_42 += aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32;
_43 += aPoint.x * _13 + aPoint.y * _23 + aPoint.z * _33;
_44 += aPoint.x * _14 + aPoint.y * _24 + aPoint.z * _34;
}
void
gfx3DMatrix::TranslatePost(const Point3D& aPoint)
{
_11 += _14 * aPoint.x;
_21 += _24 * aPoint.x;
_31 += _34 * aPoint.x;
_41 += _44 * aPoint.x;
_12 += _14 * aPoint.y;
_22 += _24 * aPoint.y;
_32 += _34 * aPoint.y;
_42 += _44 * aPoint.y;
_13 += _14 * aPoint.z;
_23 += _24 * aPoint.z;
_33 += _34 * aPoint.z;
_43 += _44 * aPoint.z;
}
void
gfx3DMatrix::ScalePost(float aX, float aY, float aZ)
{
_11 *= aX;
_21 *= aX;
_31 *= aX;
_41 *= aX;
_12 *= aY;
_22 *= aY;
_32 *= aY;
_42 *= aY;
_13 *= aZ;
_23 *= aZ;
_33 *= aZ;
_43 *= aZ;
}
void
gfx3DMatrix::ChangeBasis(const Point3D& aOrigin)
{
// Translate to the origin before applying this matrix.
Translate(-aOrigin);
// Translate back into position after applying this matrix.
TranslatePost(aOrigin);
}
void
gfx3DMatrix::Scale(float aX, float aY, float aZ)
{
(*this)[0] *= aX;
(*this)[1] *= aY;
(*this)[2] *= aZ;
}
void
gfx3DMatrix::Perspective(float aDepth)
{
NS_ASSERTION(aDepth > 0.0f, "Perspective must be positive!");
_31 += -1.0/aDepth * _41;
_32 += -1.0/aDepth * _42;
_33 += -1.0/aDepth * _43;
_34 += -1.0/aDepth * _44;
}
void gfx3DMatrix::SkewXY(double aXSkew, double aYSkew)
{
float tanX = SafeTangent(aXSkew);
float tanY = SafeTangent(aYSkew);
float temp;
temp = _11;
_11 += tanY * _21;
_21 += tanX * temp;
temp = _12;
_12 += tanY * _22;
_22 += tanX * temp;
temp = _13;
_13 += tanY * _23;
_23 += tanX * temp;
temp = _14;
_14 += tanY * _24;
_24 += tanX * temp;
}
void
gfx3DMatrix::RotateX(double aTheta)
{
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _21;
_21 = cosTheta * _21 + sinTheta * _31;
_31 = -sinTheta * temp + cosTheta * _31;
temp = _22;
_22 = cosTheta * _22 + sinTheta * _32;
_32 = -sinTheta * temp + cosTheta * _32;
temp = _23;
_23 = cosTheta * _23 + sinTheta * _33;
_33 = -sinTheta * temp + cosTheta * _33;
temp = _24;
_24 = cosTheta * _24 + sinTheta * _34;
_34 = -sinTheta * temp + cosTheta * _34;
}
void
gfx3DMatrix::RotateY(double aTheta)
{
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + -sinTheta * _31;
_31 = sinTheta * temp + cosTheta * _31;
temp = _12;
_12 = cosTheta * _12 + -sinTheta * _32;
_32 = sinTheta * temp + cosTheta * _32;
temp = _13;
_13 = cosTheta * _13 + -sinTheta * _33;
_33 = sinTheta * temp + cosTheta * _33;
temp = _14;
_14 = cosTheta * _14 + -sinTheta * _34;
_34 = sinTheta * temp + cosTheta * _34;
}
void
gfx3DMatrix::RotateZ(double aTheta)
{
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + sinTheta * _21;
_21 = -sinTheta * temp + cosTheta * _21;
temp = _12;
_12 = cosTheta * _12 + sinTheta * _22;
_22 = -sinTheta * temp + cosTheta * _22;
temp = _13;
_13 = cosTheta * _13 + sinTheta * _23;
_23 = -sinTheta * temp + cosTheta * _23;
temp = _14;
_14 = cosTheta * _14 + sinTheta * _24;
_24 = -sinTheta * temp + cosTheta * _24;
}
void
gfx3DMatrix::PreMultiply(const gfx3DMatrix& aOther)
{
*this = aOther * (*this);
}
void
gfx3DMatrix::PreMultiply(const gfxMatrix& aOther)
{
gfx3DMatrix temp;
temp._11 = aOther._11 * _11 + aOther._12 * _21;
temp._21 = aOther._21 * _11 + aOther._22 * _21;
temp._31 = _31;
temp._41 = aOther._31 * _11 + aOther._32 * _21 + _41;
temp._12 = aOther._11 * _12 + aOther._12 * _22;
temp._22 = aOther._21 * _12 + aOther._22 * _22;
temp._32 = _32;
temp._42 = aOther._31 * _12 + aOther._32 * _22 + _42;
temp._13 = aOther._11 * _13 + aOther._12 * _23;
temp._23 = aOther._21 * _13 + aOther._22 * _23;
temp._33 = _33;
temp._43 = aOther._31 * _13 + aOther._32 * _23 + _43;
temp._14 = aOther._11 * _14 + aOther._12 * _24;
temp._24 = aOther._21 * _14 + aOther._22 * _24;
temp._34 = _34;
temp._44 = aOther._31 * _14 + aOther._32 * _24 + _44;
*this = temp;
}
gfx3DMatrix
gfx3DMatrix::Translation(float aX, float aY, float aZ)
{
gfx3DMatrix matrix;
matrix._41 = aX;
matrix._42 = aY;
matrix._43 = aZ;
return matrix;
}
gfx3DMatrix
gfx3DMatrix::Translation(const Point3D& aPoint)
{
gfx3DMatrix matrix;
matrix._41 = aPoint.x;
matrix._42 = aPoint.y;
matrix._43 = aPoint.z;
return matrix;
}
gfx3DMatrix
gfx3DMatrix::ScalingMatrix(float aFactor)
{
gfx3DMatrix matrix;
matrix._11 = matrix._22 = matrix._33 = aFactor;
return matrix;
}
gfx3DMatrix
gfx3DMatrix::ScalingMatrix(float aX, float aY, float aZ)
{
gfx3DMatrix matrix;
matrix._11 = aX;
matrix._22 = aY;
matrix._33 = aZ;
return matrix;
}
gfxFloat
gfx3DMatrix::Determinant() const
{
return _14 * _23 * _32 * _41
- _13 * _24 * _32 * _41
- _14 * _22 * _33 * _41
+ _12 * _24 * _33 * _41
+ _13 * _22 * _34 * _41
- _12 * _23 * _34 * _41
- _14 * _23 * _31 * _42
+ _13 * _24 * _31 * _42
+ _14 * _21 * _33 * _42
- _11 * _24 * _33 * _42
- _13 * _21 * _34 * _42
+ _11 * _23 * _34 * _42
+ _14 * _22 * _31 * _43
- _12 * _24 * _31 * _43
- _14 * _21 * _32 * _43
+ _11 * _24 * _32 * _43
+ _12 * _21 * _34 * _43
- _11 * _22 * _34 * _43
- _13 * _22 * _31 * _44
+ _12 * _23 * _31 * _44
+ _13 * _21 * _32 * _44
- _11 * _23 * _32 * _44
- _12 * _21 * _33 * _44
+ _11 * _22 * _33 * _44;
}
gfxFloat
gfx3DMatrix::Determinant3x3() const
{
return _11 * (_22 * _33 - _23 * _32) +
_12 * (_23 * _31 - _33 * _21) +
_13 * (_21 * _32 - _22 * _31);
}
gfx3DMatrix
gfx3DMatrix::Inverse3x3() const
{
gfxFloat det = Determinant3x3();
if (det == 0.0) {
return *this;
}
gfxFloat detInv = 1/det;
gfx3DMatrix temp;
temp._11 = (_22 * _33 - _23 * _32) * detInv;
temp._12 = (_13 * _32 - _12 * _33) * detInv;
temp._13 = (_12 * _23 - _13 * _22) * detInv;
temp._21 = (_23 * _31 - _33 * _21) * detInv;
temp._22 = (_11 * _33 - _13 * _31) * detInv;
temp._23 = (_13 * _21 - _11 * _23) * detInv;
temp._31 = (_21 * _32 - _22 * _31) * detInv;
temp._32 = (_31 * _12 - _11 * _32) * detInv;
temp._33 = (_11 * _22 - _12 * _21) * detInv;
return temp;
}
bool
gfx3DMatrix::IsSingular() const
{
return Determinant() == 0.0;
}
gfx3DMatrix
gfx3DMatrix::Inverse() const
{
if (_14 == 0 && _24 == 0 && _34 == 0 && _44 == 1) {
/**
* When the matrix contains no perspective, the inverse
* is the same as the 3x3 inverse of the rotation components
* multiplied by the inverse of the translation components.
* Doing these steps separately is faster and more numerically
* stable.
*
* Inverse of the translation matrix is just negating
* the values.
*/
gfx3DMatrix matrix3 = Inverse3x3();
matrix3.Translate(Point3D(-_41, -_42, -_43));
return matrix3;
}
gfxFloat det = Determinant();
if (det == 0.0) {
return *this;
}
gfx3DMatrix temp;
temp._11 = _23*_34*_42 - _24*_33*_42 +
_24*_32*_43 - _22*_34*_43 -
_23*_32*_44 + _22*_33*_44;
temp._12 = _14*_33*_42 - _13*_34*_42 -
_14*_32*_43 + _12*_34*_43 +
_13*_32*_44 - _12*_33*_44;
temp._13 = _13*_24*_42 - _14*_23*_42 +
_14*_22*_43 - _12*_24*_43 -
_13*_22*_44 + _12*_23*_44;
temp._14 = _14*_23*_32 - _13*_24*_32 -
_14*_22*_33 + _12*_24*_33 +
_13*_22*_34 - _12*_23*_34;
temp._21 = _24*_33*_41 - _23*_34*_41 -
_24*_31*_43 + _21*_34*_43 +
_23*_31*_44 - _21*_33*_44;
temp._22 = _13*_34*_41 - _14*_33*_41 +
_14*_31*_43 - _11*_34*_43 -
_13*_31*_44 + _11*_33*_44;
temp._23 = _14*_23*_41 - _13*_24*_41 -
_14*_21*_43 + _11*_24*_43 +
_13*_21*_44 - _11*_23*_44;
temp._24 = _13*_24*_31 - _14*_23*_31 +
_14*_21*_33 - _11*_24*_33 -
_13*_21*_34 + _11*_23*_34;
temp._31 = _22*_34*_41 - _24*_32*_41 +
_24*_31*_42 - _21*_34*_42 -
_22*_31*_44 + _21*_32*_44;
temp._32 = _14*_32*_41 - _12*_34*_41 -
_14*_31*_42 + _11*_34*_42 +
_12*_31*_44 - _11*_32*_44;
temp._33 = _12*_24*_41 - _14*_22*_41 +
_14*_21*_42 - _11*_24*_42 -
_12*_21*_44 + _11*_22*_44;
temp._34 = _14*_22*_31 - _12*_24*_31 -
_14*_21*_32 + _11*_24*_32 +
_12*_21*_34 - _11*_22*_34;
temp._41 = _23*_32*_41 - _22*_33*_41 -
_23*_31*_42 + _21*_33*_42 +
_22*_31*_43 - _21*_32*_43;
temp._42 = _12*_33*_41 - _13*_32*_41 +
_13*_31*_42 - _11*_33*_42 -
_12*_31*_43 + _11*_32*_43;
temp._43 = _13*_22*_41 - _12*_23*_41 -
_13*_21*_42 + _11*_23*_42 +
_12*_21*_43 - _11*_22*_43;
temp._44 = _12*_23*_31 - _13*_22*_31 +
_13*_21*_32 - _11*_23*_32 -
_12*_21*_33 + _11*_22*_33;
temp /= det;
return temp;
}
gfxPoint
gfx3DMatrix::Transform(const gfxPoint& point) const
{
// Note: we don't use Transform3D here because passing point.x/y via
// a Point3D would lose precision and cause bugs, e.g. bug 1091709.
gfxFloat px = point.x;
gfxFloat py = point.y;
gfxFloat x = px * _11 + py * _21 + _41;
gfxFloat y = px * _12 + py * _22 + _42;
gfxFloat w = px * _14 + py * _24 + _44;
x /= w;
y /= w;
return gfxPoint(x, y);
}
Point3D
gfx3DMatrix::Transform3D(const Point3D& point) const
{
gfxFloat x = point.x * _11 + point.y * _21 + point.z * _31 + _41;
gfxFloat y = point.x * _12 + point.y * _22 + point.z * _32 + _42;
gfxFloat z = point.x * _13 + point.y * _23 + point.z * _33 + _43;
gfxFloat w = point.x * _14 + point.y * _24 + point.z * _34 + _44;
x /= w;
y /= w;
z /= w;
return Point3D(x, y, z);
}
Point4D
gfx3DMatrix::Transform4D(const Point4D& aPoint) const
{
gfxFloat x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + aPoint.w * _41;
gfxFloat y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + aPoint.w * _42;
gfxFloat z = aPoint.x * _13 + aPoint.y * _23 + aPoint.z * _33 + aPoint.w * _43;
gfxFloat w = aPoint.x * _14 + aPoint.y * _24 + aPoint.z * _34 + aPoint.w * _44;
return Point4D(x, y, z, w);
}
gfxRect
gfx3DMatrix::TransformBounds(const gfxRect& rect) const
{
gfxPoint points[4];
points[0] = Transform(rect.TopLeft());
points[1] = Transform(gfxPoint(rect.X() + rect.Width(), rect.Y()));
points[2] = Transform(gfxPoint(rect.X(), rect.Y() + rect.Height()));
points[3] = Transform(gfxPoint(rect.X() + rect.Width(),
rect.Y() + rect.Height()));
gfxFloat min_x, max_x;
gfxFloat min_y, max_y;
min_x = max_x = points[0].x;
min_y = max_y = points[0].y;
for (int i=1; i<4; i++) {
min_x = min(points[i].x, min_x);
max_x = max(points[i].x, max_x);
min_y = min(points[i].y, min_y);
max_y = max(points[i].y, max_y);
}
return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
}
gfxQuad
gfx3DMatrix::TransformRect(const gfxRect& aRect) const
{
gfxPoint points[4];
points[0] = Transform(aRect.TopLeft());
points[1] = Transform(gfxPoint(aRect.X() + aRect.Width(), aRect.Y()));
points[2] = Transform(gfxPoint(aRect.X() + aRect.Width(),
aRect.Y() + aRect.Height()));
points[3] = Transform(gfxPoint(aRect.X(), aRect.Y() + aRect.Height()));
// Could this ever result in lines that intersect? I don't think so.
return gfxQuad(points[0], points[1], points[2], points[3]);
}
bool
gfx3DMatrix::Is2D() const
{
if (_13 != 0.0f || _14 != 0.0f ||
_23 != 0.0f || _24 != 0.0f ||
_31 != 0.0f || _32 != 0.0f || _33 != 1.0f || _34 != 0.0f ||
_43 != 0.0f || _44 != 1.0f) {
return false;
}
return true;
}
bool
gfx3DMatrix::Is2D(gfxMatrix* aMatrix) const
{
if (!Is2D()) {
return false;
}
if (aMatrix) {
aMatrix->_11 = _11;
aMatrix->_12 = _12;
aMatrix->_21 = _21;
aMatrix->_22 = _22;
aMatrix->_31 = _41;
aMatrix->_32 = _42;
}
return true;
}
bool
gfx3DMatrix::CanDraw2D(gfxMatrix* aMatrix) const
{
if (_14 != 0.0f ||
_24 != 0.0f ||
_44 != 1.0f) {
return false;
}
if (aMatrix) {
aMatrix->_11 = _11;
aMatrix->_12 = _12;
aMatrix->_21 = _21;
aMatrix->_22 = _22;
aMatrix->_31 = _41;
aMatrix->_32 = _42;
}
return true;
}
gfx3DMatrix&
gfx3DMatrix::ProjectTo2D()
{
_31 = 0.0f;
_32 = 0.0f;
_13 = 0.0f;
_23 = 0.0f;
_33 = 1.0f;
_43 = 0.0f;
_34 = 0.0f;
return *this;
}
Point4D gfx3DMatrix::ProjectPoint(const gfxPoint& aPoint) const
{
// Find a value for z that will transform to 0.
// The transformed value of z is computed as:
// z' = aPoint.x * _13 + aPoint.y * _23 + z * _33 + _43;
// Solving for z when z' = 0 gives us:
float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
// Compute the transformed point
return Transform4D(Point4D(aPoint.x, aPoint.y, z, 1));
}
Point3D gfx3DMatrix::GetNormalVector() const
{
// Define a plane in transformed space as the transformations
// of 3 points on the z=0 screen plane.
Point3D a = Transform3D(Point3D(0, 0, 0));
Point3D b = Transform3D(Point3D(0, 1, 0));
Point3D c = Transform3D(Point3D(1, 0, 0));
// Convert to two vectors on the surface of the plane.
Point3D ab = b - a;
Point3D ac = c - a;
return ac.CrossProduct(ab);
}
bool gfx3DMatrix::IsBackfaceVisible() const
{
// Inverse()._33 < 0;
gfxFloat det = Determinant();
float _33 = _12*_24*_41 - _14*_22*_41 +
_14*_21*_42 - _11*_24*_42 -
_12*_21*_44 + _11*_22*_44;
return (_33 * det) < 0;
}
void gfx3DMatrix::NudgeToIntegers(void)
{
NudgeToInteger(&_11);
NudgeToInteger(&_12);
NudgeToInteger(&_13);
NudgeToInteger(&_14);
NudgeToInteger(&_21);
NudgeToInteger(&_22);
NudgeToInteger(&_23);
NudgeToInteger(&_24);
NudgeToInteger(&_31);
NudgeToInteger(&_32);
NudgeToInteger(&_33);
NudgeToInteger(&_34);
NudgeToInteger(&_41);
NudgeToInteger(&_42);
NudgeToInteger(&_43);
NudgeToInteger(&_44);
}
void gfx3DMatrix::NudgeToIntegersFixedEpsilon(void)
{
NudgeToInteger(&_11);
NudgeToInteger(&_12);
NudgeToInteger(&_13);
NudgeToInteger(&_14);
NudgeToInteger(&_21);
NudgeToInteger(&_22);
NudgeToInteger(&_23);
NudgeToInteger(&_24);
NudgeToInteger(&_31);
NudgeToInteger(&_32);
NudgeToInteger(&_33);
NudgeToInteger(&_34);
static const float error = 1e-5;
NudgeToInteger(&_41, error);
NudgeToInteger(&_42, error);
NudgeToInteger(&_43, error);
NudgeToInteger(&_44, error);
}

View File

@ -1,357 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef GFX_3DMATRIX_H
#define GFX_3DMATRIX_H
#include <gfxTypes.h>
#include "mozilla/gfx/Point.h"
#include <gfxQuad.h>
class gfxMatrix;
/**
* This class represents a 3D transformation. The matrix is laid
* out as follows:
*
* _11 _12 _13 _14
* _21 _22 _23 _24
* _31 _32 _33 _34
* _41 _42 _43 _44
*
* This matrix is treated as row-major. Assuming we consider our vectors row
* vectors, this matrix type will be identical in memory to the OpenGL and D3D
* matrices. OpenGL matrices are column-major, however OpenGL also treats
* vectors as column vectors, the double transposition makes everything work
* out nicely.
*/
class gfx3DMatrix
{
typedef mozilla::gfx::Point3D Point3D;
typedef mozilla::gfx::Point4D Point4D;
public:
/**
* Create matrix.
*/
gfx3DMatrix(void);
friend std::ostream& operator<<(std::ostream& stream, const gfx3DMatrix& m) {
if (m.IsIdentity()) {
return stream << "[ I ]";
}
if (m.Is2D()) {
return stream << "["
<< m._11 << " " << m._12 << "; "
<< m._21 << " " << m._22 << "; "
<< m._41 << " " << m._42
<< "]";
}
return stream << "["
<< m._11 << " " << m._12 << " " << m._13 << " " << m._14 << "; "
<< m._21 << " " << m._22 << " " << m._23 << " " << m._24 << "; "
<< m._31 << " " << m._32 << " " << m._33 << " " << m._34 << "; "
<< m._41 << " " << m._42 << " " << m._43 << " " << m._44
<< "]";
}
/**
* Matrix multiplication.
*/
gfx3DMatrix operator*(const gfx3DMatrix &aMatrix) const;
gfx3DMatrix& operator*=(const gfx3DMatrix &aMatrix);
Point4D& operator[](int aIndex)
{
MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
return *reinterpret_cast<Point4D*>((&_11)+4*aIndex);
}
const Point4D& operator[](int aIndex) const
{
MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
return *reinterpret_cast<const Point4D*>((&_11)+4*aIndex);
}
/**
* Return true if this matrix and |aMatrix| are the same matrix.
*/
bool operator==(const gfx3DMatrix& aMatrix) const;
bool operator!=(const gfx3DMatrix& aMatrix) const;
bool FuzzyEqual(const gfx3DMatrix& aMatrix) const;
/**
* Divide all values in the matrix by a scalar value
*/
gfx3DMatrix& operator/=(gfxFloat scalar);
/**
* Create a 3D matrix from a gfxMatrix 2D affine transformation.
*
* \param aMatrix gfxMatrix 2D affine transformation.
*/
static gfx3DMatrix From2D(const gfxMatrix &aMatrix);
/**
* Returns true if the matrix is isomorphic to a 2D affine transformation
* (i.e. as obtained by From2D). If it is, optionally returns the 2D
* matrix in aMatrix.
*/
bool Is2D(gfxMatrix* aMatrix) const;
bool Is2D() const;
/**
* Returns true if the matrix can be reduced to a 2D affine transformation
* (i.e. as obtained by From2D). If it is, optionally returns the 2D
* matrix in aMatrix. This should only be used on matrices required for
* rendering, not for intermediate calculations. It is assumed that the 2D
* matrix will only be used for transforming objects on to the z=0 plane,
* therefore any z-component perspective is ignored. This means that if
* aMatrix is applied to objects with z != 0, the results may be incorrect.
*
* Since drawing is to a 2d plane, any 3d transform without perspective
* can be reduced by dropping the z row and column.
*/
bool CanDraw2D(gfxMatrix* aMatrix = nullptr) const;
/**
* Converts the matrix to one that doesn't modify the z coordinate of points,
* but leaves the rest of the transformation unchanged.
*/
gfx3DMatrix& ProjectTo2D();
/**
* Returns true if the matrix is the identity matrix. The most important
* property we require is that gfx3DMatrix().IsIdentity() returns true.
*/
bool IsIdentity() const;
/**
* Pre-multiplication transformation functions:
*
* These functions construct a temporary matrix containing
* a single transformation and pre-multiply it onto the current
* matrix.
*/
/**
* Add a translation by aPoint to the matrix.
*
* This creates this temporary matrix:
* | 1 0 0 0 |
* | 0 1 0 0 |
* | 0 0 1 0 |
* | aPoint.x aPoint.y aPoint.z 1 |
*/
void Translate(const Point3D& aPoint);
/**
* Skew the matrix.
*
* This creates this temporary matrix:
* | 1 tan(aYSkew) 0 0 |
* | tan(aXSkew) 1 0 0 |
* | 0 0 1 0 |
* | 0 0 0 1 |
*/
void SkewXY(double aXSkew, double aYSkew);
/**
* Scale the matrix
*
* This creates this temporary matrix:
* | aX 0 0 0 |
* | 0 aY 0 0 |
* | 0 0 aZ 0 |
* | 0 0 0 1 |
*/
void Scale(float aX, float aY, float aZ);
/**
* Return the currently set scaling factors.
*/
float GetXScale() const { return _11; }
float GetYScale() const { return _22; }
float GetZScale() const { return _33; }
/**
* Rotate around the X axis..
*
* This creates this temporary matrix:
* | 1 0 0 0 |
* | 0 cos(aTheta) sin(aTheta) 0 |
* | 0 -sin(aTheta) cos(aTheta) 0 |
* | 0 0 0 1 |
*/
void RotateX(double aTheta);
/**
* Rotate around the Y axis..
*
* This creates this temporary matrix:
* | cos(aTheta) 0 -sin(aTheta) 0 |
* | 0 1 0 0 |
* | sin(aTheta) 0 cos(aTheta) 0 |
* | 0 0 0 1 |
*/
void RotateY(double aTheta);
/**
* Rotate around the Z axis..
*
* This creates this temporary matrix:
* | cos(aTheta) sin(aTheta) 0 0 |
* | -sin(aTheta) cos(aTheta) 0 0 |
* | 0 0 1 0 |
* | 0 0 0 1 |
*/
void RotateZ(double aTheta);
/**
* Apply perspective to the matrix.
*
* This creates this temporary matrix:
* | 1 0 0 0 |
* | 0 1 0 0 |
* | 0 0 1 -1/aDepth |
* | 0 0 0 1 |
*/
void Perspective(float aDepth);
/**
* Pre multiply an existing matrix onto the current
* matrix
*/
void PreMultiply(const gfx3DMatrix& aOther);
void PreMultiply(const gfxMatrix& aOther);
/**
* Post-multiplication transformation functions:
*
* These functions construct a temporary matrix containing
* a single transformation and post-multiply it onto the current
* matrix.
*/
/**
* Add a translation by aPoint after the matrix.
* This is functionally equivalent to:
* matrix * gfx3DMatrix::Translation(aPoint)
*/
void TranslatePost(const Point3D& aPoint);
void ScalePost(float aX, float aY, float aZ);
/**
* Let T be the transformation matrix translating points in the coordinate
* space with origin aOrigin to the coordinate space used by this matrix.
* If this matrix is M, this function changes it to be (T-1)MT, the matrix
* that's equivalent to M but in the coordinate space that treats aOrigin
* as the origin.
*
* @param aOrigin The origin to translate to
* @return The modified matrix
*/
void ChangeBasis(const Point3D& aOrigin);
/**
* Transforms a point according to this matrix.
*/
gfxPoint Transform(const gfxPoint& point) const;
/**
* Transforms a rectangle according to this matrix
*/
gfxRect TransformBounds(const gfxRect& rect) const;
gfxQuad TransformRect(const gfxRect& aRect) const;
/**
* Transforms a 3D vector according to this matrix.
*/
Point3D Transform3D(const Point3D& point) const;
Point4D Transform4D(const Point4D& aPoint) const;
/**
* Given a point (x,y) find a value for z such that (x,y,z,1) transforms
* into (x',y',0,w') and returns the latter.
*/
Point4D ProjectPoint(const gfxPoint& aPoint) const;
/**
* Inverts this matrix, if possible. Otherwise, the matrix is left
* unchanged.
*/
gfx3DMatrix Inverse() const;
gfx3DMatrix& Invert()
{
*this = Inverse();
return *this;
}
/**
* Returns a unit vector that is perpendicular to the plane formed
* by transform the screen plane (z=0) by this matrix.
*/
Point3D GetNormalVector() const;
/**
* Returns true if a plane transformed by this matrix will
* have it's back face visible.
*/
bool IsBackfaceVisible() const;
/**
* Check if matrix is singular (no inverse exists).
*/
bool IsSingular() const;
/**
* Create a translation matrix.
*
* \param aX Translation on X-axis.
* \param aY Translation on Y-axis.
* \param aZ Translation on Z-axis.
*/
static gfx3DMatrix Translation(float aX, float aY, float aZ);
static gfx3DMatrix Translation(const Point3D& aPoint);
/**
* Create a scale matrix. Scales uniformly along all axes.
*
* \param aScale Scale factor
*/
static gfx3DMatrix ScalingMatrix(float aFactor);
/**
* Create a scale matrix.
*/
static gfx3DMatrix ScalingMatrix(float aX, float aY, float aZ);
gfxFloat Determinant() const;
void NudgeToIntegers(void);
void NudgeToIntegersFixedEpsilon();
private:
gfxFloat Determinant3x3() const;
gfx3DMatrix Inverse3x3() const;
gfx3DMatrix Multiply2D(const gfx3DMatrix &aMatrix) const;
public:
/** Matrix elements */
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
#endif /* GFX_3DMATRIX_H */

View File

@ -6,6 +6,7 @@
#include "gfxMatrix.h"
#include "cairo.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#define CAIRO_MATRIX(x) reinterpret_cast<cairo_matrix_t*>((x))
#define CONST_CAIRO_MATRIX(x) reinterpret_cast<const cairo_matrix_t*>((x))
@ -158,3 +159,31 @@ gfxMatrix::NudgeToIntegers(void)
NudgeToInteger(&_32);
return *this;
}
mozilla::gfx::Matrix4x4
gfxMatrix::operator *(const mozilla::gfx::Matrix4x4& aMatrix) const
{
Matrix4x4 resultMatrix;
resultMatrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21;
resultMatrix._12 = _11 * aMatrix._12 + _12 * aMatrix._22;
resultMatrix._13 = _11 * aMatrix._13 + _12 * aMatrix._23;
resultMatrix._14 = _11 * aMatrix._14 + _12 * aMatrix._24;
resultMatrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21;
resultMatrix._22 = _21 * aMatrix._12 + _22 * aMatrix._22;
resultMatrix._23 = _21 * aMatrix._13 + _22 * aMatrix._23;
resultMatrix._24 = _21 * aMatrix._14 + _22 * aMatrix._24;
resultMatrix._31 = aMatrix._31;
resultMatrix._32 = aMatrix._32;
resultMatrix._33 = aMatrix._33;
resultMatrix._34 = aMatrix._34;
resultMatrix._41 = _31 * aMatrix._11 + _32 * aMatrix._21 + aMatrix._41;
resultMatrix._42 = _31 * aMatrix._12 + _32 * aMatrix._22 + aMatrix._42;
resultMatrix._43 = _31 * aMatrix._13 + _32 * aMatrix._23 + aMatrix._43;
resultMatrix._44 = _31 * aMatrix._14 + _32 * aMatrix._24 + aMatrix._44;
return resultMatrix;
}

View File

@ -11,6 +11,12 @@
#include "gfxRect.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
} // namespace mozilla
// XX - I don't think this class should use gfxFloat at all,
// but should use 'double' and be called gfxDoubleMatrix;
// we can then typedef that to gfxMatrix where we typedef
@ -79,6 +85,11 @@ public:
return gfxMatrix(*this) *= m;
}
/**
* Multiplies *this with aMatrix and returns the result.
*/
mozilla::gfx::Matrix4x4 operator * (const mozilla::gfx::Matrix4x4& aMatrix) const;
/* Returns true if the other matrix is fuzzy-equal to this matrix.
* Note that this isn't a cheap comparison!
*/

View File

@ -9,6 +9,7 @@
#include "nsMathUtils.h"
#include "mozilla/gfx/BaseSize.h"
#include "mozilla/gfx/BasePoint.h"
#include "mozilla/gfx/Matrix.h"
#include "nsSize.h"
#include "nsPoint.h"
@ -32,6 +33,20 @@ struct gfxPoint : public mozilla::gfx::BasePoint<gfxFloat, gfxPoint> {
bool WithinEpsilonOf(const gfxPoint& aPoint, gfxFloat aEpsilon) {
return fabs(aPoint.x - x) < aEpsilon && fabs(aPoint.y - y) < aEpsilon;
}
void Transform(const mozilla::gfx::Matrix4x4 &aMatrix)
{
// Transform this point with aMatrix
double px = x;
double py = y;
x = px * aMatrix._11 + py * aMatrix._21 + aMatrix._41;
y = px * aMatrix._12 + py * aMatrix._22 + aMatrix._42;
double w = px * aMatrix._14 + py * aMatrix._24 + aMatrix._44;
x /= w;
y /= w;
}
};
inline gfxPoint

View File

@ -7,6 +7,59 @@
#include "nsMathUtils.h"
#include "mozilla/gfx/Matrix.h"
#include "gfxQuad.h"
gfxQuad
gfxRect::TransformToQuad(const mozilla::gfx::Matrix4x4 &aMatrix) const
{
gfxPoint points[4];
points[0] = TopLeft();
points[1] = TopRight();
points[2] = BottomRight();
points[3] = BottomLeft();
points[0].Transform(aMatrix);
points[1].Transform(aMatrix);
points[2].Transform(aMatrix);
points[3].Transform(aMatrix);
// Could this ever result in lines that intersect? I don't think so.
return gfxQuad(points[0], points[1], points[2], points[3]);
}
void
gfxRect::TransformBounds(const mozilla::gfx::Matrix4x4 &aMatrix)
{
gfxPoint quad[4];
quad[0] = TopLeft();
quad[1] = TopRight();
quad[2] = BottomLeft();
quad[3] = BottomRight();
quad[0].Transform(aMatrix);
double min_x = quad[0].x;
double max_x = quad[0].x;
double min_y = quad[0].y;
double max_y = quad[0].y;
for (int i=1; i<4; i++) {
quad[i].Transform(aMatrix);
min_x = std::min(quad[i].x, min_x);
max_x = std::max(quad[i].x, max_x);
min_y = std::min(quad[i].y, min_y);
max_y = std::max(quad[i].y, max_y);
}
x = min_x;
y = min_y;
width = max_x - min_x;
height = max_y - min_y;
}
static bool
WithinEpsilonOfInteger(gfxFloat aX, gfxFloat aEpsilon)
{

View File

@ -14,6 +14,14 @@
#include "mozilla/gfx/BaseRect.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namepsace gfx
} // namespace mozilla
struct gfxQuad;
struct gfxMargin : public mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> {
typedef mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> Super;
@ -137,6 +145,16 @@ struct gfxRect :
width /= k;
height /= k;
}
/*
* Transform this rectangle with aMatrix, resulting in a gfxQuad.
*/
gfxQuad TransformToQuad(const mozilla::gfx::Matrix4x4 &aMatrix) const;
/*
* Transform this rectangle with aMatrix, as an axis-aligned bounding box
*/
void TransformBounds(const mozilla::gfx::Matrix4x4 &aMatrix);
};
#endif /* GFX_RECT_H */

View File

@ -1889,6 +1889,9 @@ gfxFontGroup::GetDefaultFont()
needsBold);
if (fe) {
mDefaultFont = fe->FindOrMakeFont(&mStyle, needsBold);
if (mDefaultFont) {
break;
}
}
}
}

View File

@ -8,7 +8,6 @@ EXPORTS += [
'ContextStateTracker.h',
'DrawMode.h',
'gfx2DGlue.h',
'gfx3DMatrix.h',
'gfxAlphaRecovery.h',
'gfxASurface.h',
'gfxBaseSharedMemorySurface.h',
@ -212,7 +211,6 @@ SOURCES += [
UNIFIED_SOURCES += [
'CJKCompatSVS.cpp',
'gfx3DMatrix.cpp',
'gfxAlphaRecovery.cpp',
'gfxBaseSharedMemorySurface.cpp',
'gfxBlur.cpp',

View File

@ -5,9 +5,30 @@
#ifndef mozilla_image_BMPFileHeaders_h
#define mozilla_image_BMPFileHeaders_h
#include <stddef.h>
#include <stdint.h>
namespace mozilla {
namespace image {
// This is the real BIH size (as contained in the bihsize field of
// BMPFILEHEADER).
struct BIH_LENGTH {
enum {
OS2 = 12,
WIN_V3 = 40,
WIN_V5 = 124
};
};
struct BIH_INTERNAL_LENGTH {
enum {
OS2 = 8,
WIN_V3 = 36,
WIN_V5 = 120
};
};
struct BMPFILEHEADER {
char signature[2]; // String "BM"
uint32_t filesize;
@ -15,32 +36,22 @@ struct BMPFILEHEADER {
uint32_t dataoffset; // Offset to raster data
uint32_t bihsize;
// The length of the bitmap file header as defined in the BMP spec.
static const size_t LENGTH = 14;
// Internally we store the bitmap file header with an additional 4 bytes which
// is used to store the bitmap information header size.
static const size_t INTERNAL_LENGTH = 18;
};
// The length of the bitmap file header as defined in the BMP spec.
#define BFH_LENGTH 14
// Internally we store the bitmap file header with an additional 4 bytes which
// is used to store the bitmap information header size.
#define BFH_INTERNAL_LENGTH 18
#define OS2_INTERNAL_BIH_LENGTH 8
#define WIN_V3_INTERNAL_BIH_LENGTH 36
#define WIN_V5_INTERNAL_BIH_LENGTH 120
#define OS2_BIH_LENGTH 12 // This is the real BIH size (as contained in the
// bihsize field of BMPFILEHEADER)
#define WIN_V3_BIH_LENGTH 40 // This is the real BIH size (as contained in the
// bihsize field of BMPFILEHEADER)
#define WIN_V5_BIH_LENGTH 124 // This is the real BIH size (as contained in the
// bihsize field of BMPFILEHEADER)
#define OS2_HEADER_LENGTH (BFH_INTERNAL_LENGTH + OS2_INTERNAL_BIH_LENGTH)
#define WIN_V3_HEADER_LENGTH (BFH_INTERNAL_LENGTH + WIN_V3_INTERNAL_BIH_LENGTH)
#define WIN_V5_HEADER_LENGTH (BFH_INTERNAL_LENGTH + WIN_V5_INTERNAL_BIH_LENGTH)
#ifndef LCS_sRGB
#define LCS_sRGB 0x73524742
#endif
struct BMP_HEADER_LENGTH {
enum {
OS2 = BMPFILEHEADER::INTERNAL_LENGTH + BIH_INTERNAL_LENGTH::OS2,
WIN_V3 = BMPFILEHEADER::INTERNAL_LENGTH + BIH_INTERNAL_LENGTH::WIN_V3,
WIN_V5 = BMPFILEHEADER::INTERNAL_LENGTH + BIH_INTERNAL_LENGTH::WIN_V5
};
};
struct xyz {
int32_t x, y, z;
@ -78,6 +89,8 @@ struct BITMAPV5HEADER {
uint32_t profile_offset; // Offset to profile data in bytes
uint32_t profile_size; // Size of profile data in bytes
uint32_t reserved; // =0
static const uint32_t COLOR_SPACE_LCS_SRGB = 0x73524742;
};
struct colorTable {
@ -96,38 +109,34 @@ struct bitFields {
uint8_t greenRightShift;
uint8_t blueLeftShift;
uint8_t blueRightShift;
// Length of the bitfields structure in the BMP file.
static const size_t LENGTH = 12;
};
} // namespace image
} // namespace mozilla
struct BMPINFOHEADER {
// BMPINFOHEADER.compression definitions.
enum {
RGB = 0,
RLE8 = 1,
RLE4 = 2,
BITFIELDS = 3,
#define BITFIELD_LENGTH 12 // Length of the bitfields structure in the bmp file
#define USE_RGB
// ALPHABITFIELDS means no compression and specifies alpha bits. Valid only
// for 32bpp and 16bpp.
ALPHABITFIELDS = 4
};
};
// BMPINFOHEADER.compression defines
#ifndef BI_RGB
#define BI_RGB 0
#endif
#ifndef BI_RLE8
#define BI_RLE8 1
#endif
#ifndef BI_RLE4
#define BI_RLE4 2
#endif
#ifndef BI_BITFIELDS
#define BI_BITFIELDS 3
#endif
// BI_ALPHABITFIELDS means no compression and specifies alpha bits
// valid only for 32bpp and 16bpp
#ifndef BI_ALPHABITFIELDS
#define BI_ALPHABITFIELDS 4
#endif
// RLE Escape codes
#define RLE_ESCAPE 0
#define RLE_ESCAPE_EOL 0
#define RLE_ESCAPE_EOF 1
#define RLE_ESCAPE_DELTA 2
// RLE escape codes.
struct RLE {
enum {
ESCAPE = 0,
ESCAPE_EOL = 0,
ESCAPE_EOF = 1,
ESCAPE_DELTA = 2
};
};
/// enums for mState
enum ERLEState {
@ -141,4 +150,7 @@ enum ERLEState {
///< be read as padding
};
} // namespace image
} // namespace mozilla
#endif // mozilla_image_BMPFileHeaders_h

View File

@ -203,8 +203,8 @@ public:
return;
}
if (aDecoder->IsSizeDecode()) {
mSizeDecodeQueue.AppendElement(Move(decoder));
if (aDecoder->IsMetadataDecode()) {
mMetadataDecodeQueue.AppendElement(Move(decoder));
} else {
mFullDecodeQueue.AppendElement(Move(decoder));
}
@ -218,9 +218,9 @@ public:
MonitorAutoLock lock(mMonitor);
do {
// Prioritize size decodes over full decodes.
if (!mSizeDecodeQueue.IsEmpty()) {
return PopWorkFromQueue(mSizeDecodeQueue);
// Prioritize metadata decodes over full decodes.
if (!mMetadataDecodeQueue.IsEmpty()) {
return PopWorkFromQueue(mMetadataDecodeQueue);
}
if (!mFullDecodeQueue.IsEmpty()) {
@ -253,9 +253,9 @@ private:
nsThreadPoolNaming mThreadNaming;
// mMonitor guards mQueue and mShuttingDown.
// mMonitor guards the queues and mShuttingDown.
Monitor mMonitor;
nsTArray<nsRefPtr<Decoder>> mSizeDecodeQueue;
nsTArray<nsRefPtr<Decoder>> mMetadataDecodeQueue;
nsTArray<nsRefPtr<Decoder>> mFullDecodeQueue;
bool mShuttingDown;
};

View File

@ -42,7 +42,7 @@ Decoder::Decoder(RasterImage* aImage)
, mFrameCount(0)
, mFailCode(NS_OK)
, mInitialized(false)
, mSizeDecode(false)
, mMetadataDecode(false)
, mInFrame(false)
, mIsAnimated(false)
{ }
@ -169,7 +169,7 @@ Decoder::Write(const char* aBuffer, uint32_t aCount)
return;
}
if (IsSizeDecode() && HasSize()) {
if (IsMetadataDecode() && HasSize()) {
// More data came in since we found the size. We have nothing to do here.
return;
}
@ -200,7 +200,7 @@ Decoder::CompleteDecode()
// early because of low-memory conditions or losing a race with another
// decoder, we need to send teardown notifications (and report an error to the
// console later).
if (!IsSizeDecode() && !mDecodeDone && !WasAborted()) {
if (!IsMetadataDecode() && !mDecodeDone && !WasAborted()) {
mShouldReportError = true;
// If we only have a data error, we're usable if we have at least one
@ -218,7 +218,7 @@ Decoder::CompleteDecode()
PostDecodeDone();
} else {
// We're not usable. Record some final progress indicating the error.
if (!IsSizeDecode()) {
if (!IsMetadataDecode()) {
mProgress |= FLAG_DECODE_COMPLETE;
}
mProgress |= FLAG_HAS_ERROR;
@ -269,7 +269,7 @@ Decoder::Finish()
SetSizeOnImage();
}
if (mDecodeDone && !IsSizeDecode()) {
if (mDecodeDone && !IsMetadataDecode()) {
MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame");
// If this image wasn't animated and isn't a transient image, mark its frame
@ -424,7 +424,6 @@ Decoder::SetSizeOnImage()
*/
void Decoder::InitInternal() { }
void Decoder::WriteInternal(const char* aBuffer, uint32_t aCount) { }
void Decoder::FinishInternal() { }
void Decoder::FinishWithErrorInternal() { }
@ -478,7 +477,7 @@ Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */,
BlendMethod aBlendMethod /* = BlendMethod::OVER */)
{
// We should be mid-frame
MOZ_ASSERT(!IsSizeDecode(), "Stopping frame during a size decode");
MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode");
MOZ_ASSERT(mInFrame, "Stopping frame when we didn't start one");
MOZ_ASSERT(mCurrentFrame, "Stopping frame when we don't have one");
@ -517,7 +516,7 @@ Decoder::PostInvalidation(const nsIntRect& aRect,
void
Decoder::PostDecodeDone(int32_t aLoopCount /* = 0 */)
{
MOZ_ASSERT(!IsSizeDecode(), "Can't be done with decoding with size decode!");
MOZ_ASSERT(!IsMetadataDecode(), "Done with decoding in metadata decode");
MOZ_ASSERT(!mInFrame, "Can't be done decoding if we're mid-frame!");
MOZ_ASSERT(!mDecodeDone, "Decode already done!");
mDecodeDone = true;

View File

@ -97,15 +97,17 @@ public:
* State.
*/
// If we're doing a "size decode", we more or less pass through the image
// data, stopping only to scoop out the image dimensions. A size decode
// must be enabled by SetSizeDecode() _before_calling Init().
bool IsSizeDecode() { return mSizeDecode; }
void SetSizeDecode(bool aSizeDecode)
/**
* If we're doing a metadata decode, we only decode the image's headers, which
* is enough to determine the image's intrinsic size. A metadata decode is
* enabled by calling SetMetadataDecode() *before* calling Init().
*/
void SetMetadataDecode(bool aMetadataDecode)
{
MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet");
mSizeDecode = aSizeDecode;
mMetadataDecode = aMetadataDecode;
}
bool IsMetadataDecode() { return mMetadataDecode; }
/**
* If this decoder supports downscale-during-decode, sets the target size that
@ -209,7 +211,8 @@ public:
bool GetDecodeDone() const
{
return mDecodeDone || (mSizeDecode && HasSize()) || HasError() || mDataDone;
return mDecodeDone || (mMetadataDecode && HasSize()) ||
HasError() || mDataDone;
}
/**
@ -282,7 +285,7 @@ protected:
* only these methods.
*/
virtual void InitInternal();
virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) = 0;
virtual void FinishInternal();
virtual void FinishWithErrorInternal();
@ -423,7 +426,7 @@ private:
nsresult mFailCode;
bool mInitialized;
bool mSizeDecode;
bool mMetadataDecode;
bool mInFrame;
bool mIsAnimated;
};

177
image/DecoderFactory.cpp Normal file
View File

@ -0,0 +1,177 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#include "DecoderFactory.h"
#include "nsMimeTypes.h"
#include "nsRefPtr.h"
#include "nsString.h"
#include "Decoder.h"
#include "nsPNGDecoder.h"
#include "nsGIFDecoder2.h"
#include "nsJPEGDecoder.h"
#include "nsBMPDecoder.h"
#include "nsICODecoder.h"
#include "nsIconDecoder.h"
namespace mozilla {
using namespace gfx;
namespace image {
/* static */ DecoderType
DecoderFactory::GetDecoderType(const char* aMimeType)
{
// By default we don't know.
DecoderType type = DecoderType::UNKNOWN;
// PNG
if (!strcmp(aMimeType, IMAGE_PNG)) {
type = DecoderType::PNG;
} else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
type = DecoderType::PNG;
// GIF
} else if (!strcmp(aMimeType, IMAGE_GIF)) {
type = DecoderType::GIF;
// JPEG
} else if (!strcmp(aMimeType, IMAGE_JPEG)) {
type = DecoderType::JPEG;
} else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
type = DecoderType::JPEG;
} else if (!strcmp(aMimeType, IMAGE_JPG)) {
type = DecoderType::JPEG;
// BMP
} else if (!strcmp(aMimeType, IMAGE_BMP)) {
type = DecoderType::BMP;
} else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
type = DecoderType::BMP;
// ICO
} else if (!strcmp(aMimeType, IMAGE_ICO)) {
type = DecoderType::ICO;
} else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
type = DecoderType::ICO;
// Icon
} else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
type = DecoderType::ICON;
}
return type;
}
/* static */ already_AddRefed<Decoder>
DecoderFactory::GetDecoder(DecoderType aType,
RasterImage* aImage,
bool aIsRedecode)
{
nsRefPtr<Decoder> decoder;
switch (aType) {
case DecoderType::PNG:
decoder = new nsPNGDecoder(aImage);
break;
case DecoderType::GIF:
decoder = new nsGIFDecoder2(aImage);
break;
case DecoderType::JPEG:
// If we have all the data we don't want to waste cpu time doing
// a progressive decode.
decoder = new nsJPEGDecoder(aImage,
aIsRedecode ? Decoder::SEQUENTIAL
: Decoder::PROGRESSIVE);
break;
case DecoderType::BMP:
decoder = new nsBMPDecoder(aImage);
break;
case DecoderType::ICO:
decoder = new nsICODecoder(aImage);
break;
case DecoderType::ICON:
decoder = new nsIconDecoder(aImage);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
}
return decoder.forget();
}
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer,
const Maybe<IntSize>& aTargetSize,
uint32_t aFlags,
bool aIsRedecode,
bool aImageIsTransient,
bool aImageIsLocked)
{
if (aType == DecoderType::UNKNOWN) {
return nullptr;
}
nsRefPtr<Decoder> decoder = GetDecoder(aType, aImage, aIsRedecode);
MOZ_ASSERT(decoder, "Should have a decoder now");
// Initialize the decoder.
decoder->SetMetadataDecode(false);
decoder->SetIterator(aSourceBuffer->Iterator());
decoder->SetFlags(aFlags);
decoder->SetSendPartialInvalidations(!aIsRedecode);
decoder->SetImageIsTransient(aImageIsTransient);
if (aImageIsLocked) {
decoder->SetImageIsLocked();
}
// Set a target size for downscale-during-decode if applicable.
if (aTargetSize) {
DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
"We're downscale-during-decode but decoder doesn't support it?");
MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
}
decoder->Init();
if (NS_FAILED(decoder->GetDecoderError())) {
return nullptr;
}
return decoder.forget();
}
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer)
{
if (aType == DecoderType::UNKNOWN) {
return nullptr;
}
nsRefPtr<Decoder> decoder =
GetDecoder(aType, aImage, /* aIsRedecode = */ false);
MOZ_ASSERT(decoder, "Should have a decoder now");
// Initialize the decoder.
decoder->SetMetadataDecode(true);
decoder->SetIterator(aSourceBuffer->Iterator());
decoder->Init();
if (NS_FAILED(decoder->GetDecoderError())) {
return nullptr;
}
return decoder.forget();
}
} // namespace image
} // namespace mozilla

106
image/DecoderFactory.h Normal file
View File

@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef mozilla_image_DecoderFactory_h
#define mozilla_image_DecoderFactory_h
#include "mozilla/Maybe.h"
#include "mozilla/gfx/2D.h"
#include "nsCOMPtr.h"
class nsACString;
namespace mozilla {
namespace image {
class Decoder;
class RasterImage;
class SourceBuffer;
enum class DecoderType
{
PNG,
GIF,
JPEG,
BMP,
ICO,
ICON,
UNKNOWN
};
class DecoderFactory
{
public:
/// @return the type of decoder which is appropriate for @aMimeType.
static DecoderType GetDecoderType(const char* aMimeType);
/**
* Creates and initializes a decoder of type @aType. The decoder will send
* notifications to @aImage.
*
* XXX(seth): @aIsRedecode, @aImageIsTransient, and @aImageIsLocked should
* really be part of @aFlags. This requires changes to the way that decoder
* flags work, though. See bug 1185800.
*
* @param aType Which type of decoder to create - JPEG, PNG, etc.
* @param aImage The image will own the decoder and which should receive
* notifications as decoding progresses.
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
* from.
* @param aTargetSize If not Nothing(), the target size which the image should
* be scaled to during decoding. It's an error to specify
* a target size for a decoder type which doesn't support
* downscale-during-decode.
* @param aFlags Flags specifying what type of output the decoder should
* produce; see GetDecodeFlags() in RasterImage.h.
* @param aIsRedecode Specify 'true' if this image has been decoded before.
* @param aImageIsTransient Specify 'true' if this image is transient.
* @param aImageIsLocked Specify 'true' if this image is locked for the
* lifetime of this decoder, and should be unlocked
* when the decoder finishes.
*/
static already_AddRefed<Decoder>
CreateDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer,
const Maybe<gfx::IntSize>& aTargetSize,
uint32_t aFlags,
bool aIsRedecode,
bool aImageIsTransient,
bool aImageIsLocked);
/**
* Creates and initializes a metadata decoder of type @aType. This decoder
* will only decode the image's header, extracting metadata like the size of
* the image. No actual image data will be decoded and no surfaces will be
* allocated. The decoder will send notifications to @aImage.
*
* @param aType Which type of decoder to create - JPEG, PNG, etc.
* @param aImage The image will own the decoder and which should receive
* notifications as decoding progresses.
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
* from.
*/
static already_AddRefed<Decoder>
CreateMetadataDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer);
private:
virtual ~DecoderFactory() = 0;
/**
* An internal method which allocates a new decoder of the requested @aType.
*/
static already_AddRefed<Decoder> GetDecoder(DecoderType aType,
RasterImage* aImage,
bool aIsRedecode);
};
} // namespace image
} // namespace mozilla
#endif // mozilla_image_DecoderFactory_h

View File

@ -3,8 +3,6 @@
* 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/. */
#include "nsMimeTypes.h"
#include "Image.h"
#include "nsRefreshDriver.h"
#include "mozilla/TimeStamp.h"
@ -69,52 +67,6 @@ ImageResource::~ImageResource()
mProgressTracker->ResetImage();
}
// Translates a mimetype into a concrete decoder
Image::eDecoderType
Image::GetDecoderType(const char* aMimeType)
{
// By default we don't know
eDecoderType rv = eDecoderType_unknown;
// PNG
if (!strcmp(aMimeType, IMAGE_PNG)) {
rv = eDecoderType_png;
} else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
rv = eDecoderType_png;
// GIF
} else if (!strcmp(aMimeType, IMAGE_GIF)) {
rv = eDecoderType_gif;
// JPEG
} else if (!strcmp(aMimeType, IMAGE_JPEG)) {
rv = eDecoderType_jpeg;
} else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
rv = eDecoderType_jpeg;
} else if (!strcmp(aMimeType, IMAGE_JPG)) {
rv = eDecoderType_jpeg;
// BMP
} else if (!strcmp(aMimeType, IMAGE_BMP)) {
rv = eDecoderType_bmp;
} else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
rv = eDecoderType_bmp;
// ICO
} else if (!strcmp(aMimeType, IMAGE_ICO)) {
rv = eDecoderType_ico;
} else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
rv = eDecoderType_ico;
// Icon
} else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
rv = eDecoderType_icon;
}
return rv;
}
void
ImageResource::IncrementAnimationConsumers()
{

View File

@ -129,18 +129,6 @@ private:
class Image : public imgIContainer
{
public:
// Mimetype translation
enum eDecoderType {
eDecoderType_png = 0,
eDecoderType_gif = 1,
eDecoderType_jpeg = 2,
eDecoderType_bmp = 3,
eDecoderType_ico = 4,
eDecoderType_icon = 5,
eDecoderType_unknown = 6
};
static eDecoderType GetDecoderType(const char* aMimeType);
/**
* Flags for Image initialization.
*

View File

@ -21,18 +21,12 @@
#include "ImageRegion.h"
#include "Layers.h"
#include "LookupResult.h"
#include "nsIInputStream.h"
#include "nsPresContext.h"
#include "SourceBuffer.h"
#include "SurfaceCache.h"
#include "FrameAnimator.h"
#include "nsPNGDecoder.h"
#include "nsGIFDecoder2.h"
#include "nsJPEGDecoder.h"
#include "nsBMPDecoder.h"
#include "nsICODecoder.h"
#include "nsIconDecoder.h"
#include "gfxContext.h"
#include "mozilla/gfx/2D.h"
@ -282,8 +276,8 @@ RasterImage::Init(const char* aMimeType,
// Use the MIME type to select a decoder type, and make sure there *is* a
// decoder for this MIME type.
NS_ENSURE_ARG_POINTER(aMimeType);
mDecoderType = GetDecoderType(aMimeType);
if (mDecoderType == eDecoderType_unknown) {
mDecoderType = DecoderFactory::GetDecoderType(aMimeType);
if (mDecoderType == DecoderType::UNKNOWN) {
return NS_ERROR_FAILURE;
}
@ -294,8 +288,8 @@ RasterImage::Init(const char* aMimeType,
}
if (!mSyncLoad) {
// Create an async size decoder and verify that we succeed in doing so.
nsresult rv = Decode(Nothing(), DECODE_FLAGS_DEFAULT);
// Create an async metadata decoder and verify we succeed in doing so.
nsresult rv = DecodeMetadata(DECODE_FLAGS_DEFAULT);
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
@ -488,7 +482,7 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
// yet.) Trigger decoding so it'll be available next time.
MOZ_ASSERT(!mAnim, "Animated frames should be locked");
Decode(Some(requestedSize), aFlags);
Decode(requestedSize, aFlags);
// If we can sync decode, we should already have the frame.
if (aFlags & FLAG_SYNC_DECODE) {
@ -1166,21 +1160,22 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
// Let decoders know that there won't be any more data coming.
mSourceBuffer->Complete(aStatus);
// Allow a synchronous size decode if mSyncLoad was set, or if we're running
// on a single thread (in which case waiting for the async size decoder could
// delay this image's load event quite a bit), or if this image is transient.
bool canSyncSizeDecode = mSyncLoad || mTransient ||
DecodePool::NumberOfCores() < 2;
// Allow a synchronous metadata decode if mSyncLoad was set, or if we're
// running on a single thread (in which case waiting for the async metadata
// decoder could delay this image's load event quite a bit), or if this image
// is transient.
bool canSyncDecodeMetadata = mSyncLoad || mTransient ||
DecodePool::NumberOfCores() < 2;
if (canSyncSizeDecode && !mHasSize) {
if (canSyncDecodeMetadata && !mHasSize) {
// We're loading this image synchronously, so it needs to be usable after
// this call returns. Since we haven't gotten our size yet, we need to do a
// synchronous size decode here.
Decode(Nothing(), FLAG_SYNC_DECODE);
// synchronous metadata decode here.
DecodeMetadata(FLAG_SYNC_DECODE);
}
// Determine our final status, giving precedence to Necko failure codes. We
// check after running the size decode above in case it triggered an error.
// check after running the metadata decode in case it triggered an error.
nsresult finalStatus = mError ? NS_ERROR_FAILURE : NS_OK;
if (NS_FAILED(aStatus)) {
finalStatus = aStatus;
@ -1195,7 +1190,8 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
if (!mHasSize && !mError) {
// We don't have our size yet, so we'll fire the load event in SetSize().
MOZ_ASSERT(!canSyncSizeDecode, "Firing load async but canSyncSizeDecode?");
MOZ_ASSERT(!canSyncDecodeMetadata,
"Firing load async after metadata sync decode?");
NotifyProgress(FLAG_ONLOAD_BLOCKED);
mLoadProgress = Some(loadProgress);
return finalStatus;
@ -1325,117 +1321,6 @@ RasterImage::CanDiscard() {
!mAnim; // Can never discard animated images
}
// Sets up a decoder for this image.
already_AddRefed<Decoder>
RasterImage::CreateDecoder(const Maybe<IntSize>& aSize, uint32_t aFlags)
{
// Make sure we actually get size before doing a full decode.
if (aSize) {
MOZ_ASSERT(mHasSize, "Must do a size decode before a full decode!");
MOZ_ASSERT(mDownscaleDuringDecode || *aSize == mSize,
"Can only decode to our intrinsic size if we're not allowed to "
"downscale-during-decode");
} else {
MOZ_ASSERT(!mHasSize, "Should not do unnecessary size decodes");
}
// Instantiate the appropriate decoder.
nsRefPtr<Decoder> decoder;
switch (mDecoderType) {
case eDecoderType_png:
decoder = new nsPNGDecoder(this);
break;
case eDecoderType_gif:
decoder = new nsGIFDecoder2(this);
break;
case eDecoderType_jpeg:
// If we have all the data we don't want to waste cpu time doing
// a progressive decode.
decoder = new nsJPEGDecoder(this,
mHasBeenDecoded ? Decoder::SEQUENTIAL :
Decoder::PROGRESSIVE);
break;
case eDecoderType_bmp:
decoder = new nsBMPDecoder(this);
break;
case eDecoderType_ico:
decoder = new nsICODecoder(this);
break;
case eDecoderType_icon:
decoder = new nsIconDecoder(this);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
}
MOZ_ASSERT(decoder, "Should have a decoder now");
// Initialize the decoder.
decoder->SetSizeDecode(!aSize);
decoder->SetSendPartialInvalidations(!mHasBeenDecoded);
decoder->SetImageIsTransient(mTransient);
decoder->SetFlags(aFlags);
if (!mHasBeenDecoded && aSize) {
// Lock the image while we're decoding, so that it doesn't get evicted from
// the SurfaceCache before we have a chance to realize that it's animated.
// The corresponding unlock happens in FinalizeDecoder.
LockImage();
decoder->SetImageIsLocked();
}
decoder->SetIterator(mSourceBuffer->Iterator());
// Set a target size for downscale-during-decode if applicable.
if (mDownscaleDuringDecode && aSize && *aSize != mSize) {
DebugOnly<nsresult> rv = decoder->SetTargetSize(*aSize);
MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
"We're downscale-during-decode but decoder doesn't support it?");
MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
}
decoder->Init();
if (NS_FAILED(decoder->GetDecoderError())) {
return nullptr;
}
if (aSize) {
// Add a placeholder for the first frame to the SurfaceCache so we won't
// trigger any more decoders with the same parameters.
InsertOutcome outcome =
SurfaceCache::InsertPlaceholder(ImageKey(this),
RasterSurfaceKey(*aSize,
decoder->GetDecodeFlags(),
/* aFrameNum = */ 0));
if (outcome != InsertOutcome::SUCCESS) {
return nullptr;
}
}
if (!aSize) {
Telemetry::GetHistogramById(
Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount);
mDecodeCount++;
Telemetry::GetHistogramById(
Telemetry::IMAGE_DECODE_COUNT)->Add(mDecodeCount);
if (mDecodeCount > sMaxDecodeCount) {
// Don't subtract out 0 from the histogram, because that causes its count
// to go negative, which is not kosher.
if (sMaxDecodeCount > 0) {
Telemetry::GetHistogramById(
Telemetry::IMAGE_MAX_DECODE_COUNT)->Subtract(sMaxDecodeCount);
}
sMaxDecodeCount = mDecodeCount;
Telemetry::GetHistogramById(
Telemetry::IMAGE_MAX_DECODE_COUNT)->Add(sMaxDecodeCount);
}
}
return decoder.forget();
}
//******************************************************************************
/* void requestDecode() */
NS_IMETHODIMP
@ -1486,22 +1371,52 @@ RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags)
return NS_OK;
}
NS_IMETHODIMP
RasterImage::Decode(const Maybe<IntSize>& aSize, uint32_t aFlags)
static void
LaunchDecoder(Decoder* aDecoder,
RasterImage* aImage,
uint32_t aFlags,
bool aHaveSourceData)
{
MOZ_ASSERT(!aSize || NS_IsMainThread());
if (aHaveSourceData) {
// If we have all the data, we can sync decode if requested.
if (aFlags & imgIContainer::FLAG_SYNC_DECODE) {
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfPossible",
js::ProfileEntry::Category::GRAPHICS,
"%s", aImage->GetURIString().get());
DecodePool::Singleton()->SyncDecodeIfPossible(aDecoder);
return;
}
if (aFlags & imgIContainer::FLAG_SYNC_DECODE_IF_FAST) {
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfSmall",
js::ProfileEntry::Category::GRAPHICS,
"%s", aImage->GetURIString().get());
DecodePool::Singleton()->SyncDecodeIfSmall(aDecoder);
return;
}
}
// Perform an async decode. We also take this path if we don't have all the
// source data yet, since sync decoding is impossible in that situation.
DecodePool::Singleton()->AsyncDecode(aDecoder);
}
NS_IMETHODIMP
RasterImage::Decode(const IntSize& aSize, uint32_t aFlags)
{
MOZ_ASSERT(NS_IsMainThread());
if (mError) {
return NS_ERROR_FAILURE;
}
// If we don't have a size yet, we can't do any other decoding.
if (!mHasSize && aSize) {
if (!mHasSize) {
mWantFullDecode = true;
return NS_OK;
}
if (mDownscaleDuringDecode && aSize) {
if (mDownscaleDuringDecode) {
// We're about to decode again, which may mean that some of the previous
// sizes we've decoded at aren't useful anymore. We can allow them to
// expire from the cache by unlocking them here. When the decode finishes,
@ -1512,32 +1427,87 @@ RasterImage::Decode(const Maybe<IntSize>& aSize, uint32_t aFlags)
SurfaceCache::UnlockSurfaces(ImageKey(this));
}
MOZ_ASSERT(mDownscaleDuringDecode || aSize == mSize,
"Can only decode to our intrinsic size if we're not allowed to "
"downscale-during-decode");
Maybe<IntSize> targetSize = mSize != aSize ? Some(aSize) : Nothing();
bool imageIsLocked = false;
if (!mHasBeenDecoded) {
// Lock the image while we're decoding, so that it doesn't get evicted from
// the SurfaceCache before we have a chance to realize that it's animated.
// The corresponding unlock happens in FinalizeDecoder.
LockImage();
imageIsLocked = true;
}
// Create a decoder.
nsRefPtr<Decoder> decoder = CreateDecoder(aSize, aFlags);
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateDecoder(mDecoderType, this, mSourceBuffer, targetSize,
aFlags, mHasBeenDecoded, mTransient,
imageIsLocked);
// Make sure DecoderFactory was able to create a decoder successfully.
if (!decoder) {
return NS_ERROR_FAILURE;
}
if (mHasSourceData) {
// If we have all the data, we can sync decode if requested.
if (aFlags & FLAG_SYNC_DECODE) {
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfPossible",
js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
DecodePool::Singleton()->SyncDecodeIfPossible(decoder);
return NS_OK;
}
if (aFlags & FLAG_SYNC_DECODE_IF_FAST) {
PROFILER_LABEL_PRINTF("DecodePool", "SyncDecodeIfSmall",
js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
DecodePool::Singleton()->SyncDecodeIfSmall(decoder);
return NS_OK;
}
// Add a placeholder for the first frame to the SurfaceCache so we won't
// trigger any more decoders with the same parameters.
InsertOutcome outcome =
SurfaceCache::InsertPlaceholder(ImageKey(this),
RasterSurfaceKey(aSize,
decoder->GetDecodeFlags(),
/* aFrameNum = */ 0));
if (outcome != InsertOutcome::SUCCESS) {
return NS_ERROR_FAILURE;
}
// Perform an async decode. We also take this path if we don't have all the
// source data yet, since sync decoding is impossible in that situation.
DecodePool::Singleton()->AsyncDecode(decoder);
// Report telemetry.
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)
->Subtract(mDecodeCount);
mDecodeCount++;
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)
->Add(mDecodeCount);
if (mDecodeCount > sMaxDecodeCount) {
// Don't subtract out 0 from the histogram, because that causes its count
// to go negative, which is not kosher.
if (sMaxDecodeCount > 0) {
Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)
->Subtract(sMaxDecodeCount);
}
sMaxDecodeCount = mDecodeCount;
Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)
->Add(sMaxDecodeCount);
}
// We're ready to decode; start the decoder.
LaunchDecoder(decoder, this, aFlags, mHasSourceData);
return NS_OK;
}
NS_IMETHODIMP
RasterImage::DecodeMetadata(uint32_t aFlags)
{
if (mError) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(!mHasSize, "Should not do unnecessary metadata decodes");
// Create a decoder.
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateMetadataDecoder(mDecoderType, this, mSourceBuffer);
// Make sure DecoderFactory was able to create a decoder successfully.
if (!decoder) {
return NS_ERROR_FAILURE;
}
// We're ready to decode; start the decoder.
LaunchDecoder(decoder, this, aFlags, mHasSourceData);
return NS_OK;
}
@ -1556,13 +1526,13 @@ RasterImage::RecoverFromLossOfFrames(const IntSize& aSize, uint32_t aFlags)
// Animated images require some special handling, because we normally require
// that they never be discarded.
if (mAnim) {
Decode(Some(mSize), aFlags | FLAG_SYNC_DECODE);
Decode(mSize, aFlags | FLAG_SYNC_DECODE);
ResetAnimation();
return;
}
// For non-animated images, it's fine to recover using an async decode.
Decode(Some(aSize), aFlags);
Decode(aSize, aFlags);
}
bool
@ -2048,17 +2018,17 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
aDecoder->TakeInvalidRect(),
aDecoder->GetDecodeFlags());
bool wasSize = aDecoder->IsSizeDecode();
bool wasMetadata = aDecoder->IsMetadataDecode();
bool done = aDecoder->GetDecodeDone();
if (!wasSize && aDecoder->ChunkCount()) {
if (!wasMetadata && aDecoder->ChunkCount()) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS,
aDecoder->ChunkCount());
}
if (done) {
// Do some telemetry if this isn't a size decode.
if (!wasSize) {
// Do some telemetry if this isn't a metadata decode.
if (!wasMetadata) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME,
int32_t(aDecoder->DecodeTime().ToMicroseconds()));
@ -2075,12 +2045,12 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
// Detect errors.
if (aDecoder->HasError() && !aDecoder->WasAborted()) {
DoError();
} else if (wasSize && !mHasSize) {
} else if (wasMetadata && !mHasSize) {
DoError();
}
// If we were waiting to fire the load event, go ahead and fire it now.
if (mLoadProgress && wasSize) {
if (mLoadProgress && wasMetadata) {
NotifyForLoadEvent(*mLoadProgress);
mLoadProgress = Nothing();
NotifyProgress(FLAG_ONLOAD_UNBLOCKED);
@ -2092,8 +2062,8 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
UnlockImage();
}
// If we were a size decode and a full decode was requested, now's the time.
if (done && wasSize && mWantFullDecode) {
// If we were a metadata decode and a full decode was requested, do it.
if (done && wasMetadata && mWantFullDecode) {
mWantFullDecode = false;
RequestDecode();
}

View File

@ -26,6 +26,7 @@
#include "LookupResult.h"
#include "nsThreadUtils.h"
#include "DecodePool.h"
#include "DecoderFactory.h"
#include "Orientation.h"
#include "nsIObserver.h"
#include "mozilla/Attributes.h"
@ -339,19 +340,23 @@ private:
/**
* Creates and runs a decoder, either synchronously or asynchronously
* according to @aFlags. Passes the provided target size @aSize and decode
* flags @aFlags to CreateDecoder. If a size decode is desired, pass Nothing
* for @aSize.
* according to @aFlags. Decodes at the provided target size @aSize, using
* decode flags @aFlags.
*
* It's an error to call Decode() before this image's intrinsic size is
* available. A metadata decode must successfully complete first.
*
* If downscale-during-decode is not enabled for this image (i.e., if
* mDownscaleDuringDecode is false), it is an error to pass an @aSize value
* different from this image's intrinsic size.
*/
NS_IMETHOD Decode(const Maybe<nsIntSize>& aSize, uint32_t aFlags);
NS_IMETHOD Decode(const gfx::IntSize& aSize, uint32_t aFlags);
/**
* Creates a new decoder with a target size of @aSize and decode flags
* specified by @aFlags. If a size decode is desired, pass Nothing() for
* @aSize.
* Creates and runs a metadata decoder, either synchronously or
* asynchronously according to @aFlags.
*/
already_AddRefed<Decoder> CreateDecoder(const Maybe<nsIntSize>& aSize,
uint32_t aFlags);
NS_IMETHOD DecodeMetadata(uint32_t aFlags);
/**
* In catastrophic circumstances like a GPU driver crash, we may lose our
@ -376,7 +381,7 @@ private: // data
uint32_t mLockCount;
// The type of decoder this image needs. Computed from the MIME type in Init().
eDecoderType mDecoderType;
DecoderType mDecoderType;
// How many times we've decoded this image.
// This is currently only used for statistics
@ -425,8 +430,8 @@ private: // data
// of frames, or no more owning request
bool mAnimationFinished:1;
// Whether, once we are done doing a size decode, we should immediately kick
// off a full decode.
// Whether, once we are done doing a metadata decode, we should immediately
// kick off a full decode.
bool mWantFullDecode:1;
TimeStamp mDrawStartTime;

View File

@ -32,9 +32,11 @@
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
#undef GetCurrentTime
using namespace mozilla::dom;
namespace mozilla {
using namespace dom;
using namespace gfx;
namespace image {
NS_IMPL_ISUPPORTS(SVGDocumentWrapper,

View File

@ -39,7 +39,7 @@ GetBMPLog()
nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
: Decoder(aImage)
, mPos(0)
, mLOH(WIN_V3_HEADER_LENGTH)
, mLOH(BMP_HEADER_LENGTH::WIN_V3)
, mNumColors(0)
, mColors(nullptr)
, mRow(nullptr)
@ -101,13 +101,14 @@ nsBMPDecoder::GetImageData()
int32_t
nsBMPDecoder::GetCompressedImageSize() const
{
// For everything except BI_RGB the header field must be defined
if (mBIH.compression != BI_RGB) {
// For everything except BMPINFOHEADER::RGB the header field must be defined
if (mBIH.compression != BMPINFOHEADER::RGB) {
return mBIH.image_size;
}
// mBIH.image_size isn't always filled for BI_RGB so calculate it manually
// The pixel array size is calculated based on extra 4 byte boundary padding
// mBIH.image_size isn't always filled for BMPINFOHEADER::RGB so calculate it
// manually. The pixel array size is calculated based on extra 4 byte
// boundary padding.
uint32_t rowSize = (mBIH.bpp * mBIH.width + 7) / 8; // + 7 to round up
// Pad to DWORD Boundary
@ -140,7 +141,7 @@ nsBMPDecoder::FinishInternal()
MOZ_ASSERT(GetFrameCount() <= 1, "Multiple BMP frames?");
// Send notifications if appropriate
if (!IsSizeDecode() && HasSize()) {
if (!IsMetadataDecode() && HasSize()) {
// Invalidate
nsIntRect r(0, 0, mBIH.width, GetHeight());
@ -206,39 +207,39 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
return;
}
// This code assumes that mRawBuf == WIN_V3_INTERNAL_BIH_LENGTH
// and that sizeof(mRawBuf) >= BFH_INTERNAL_LENGTH
MOZ_ASSERT(sizeof(mRawBuf) == WIN_V3_INTERNAL_BIH_LENGTH);
MOZ_ASSERT(sizeof(mRawBuf) >= BFH_INTERNAL_LENGTH);
MOZ_ASSERT(OS2_INTERNAL_BIH_LENGTH < WIN_V3_INTERNAL_BIH_LENGTH);
// This code assumes that mRawBuf == BIH_INTERNAL_LENGTH::WIN_V3
// and that sizeof(mRawBuf) >= BMPFILEHEADER::INTERNAL_LENGTH
MOZ_ASSERT(sizeof(mRawBuf) == BIH_INTERNAL_LENGTH::WIN_V3);
MOZ_ASSERT(sizeof(mRawBuf) >= BMPFILEHEADER::INTERNAL_LENGTH);
MOZ_ASSERT(BIH_INTERNAL_LENGTH::OS2 < BIH_INTERNAL_LENGTH::WIN_V3);
// This code also assumes it's working with a byte array
MOZ_ASSERT(sizeof(mRawBuf[0]) == 1);
if (mPos < BFH_INTERNAL_LENGTH) { /* In BITMAPFILEHEADER */
// BFH_INTERNAL_LENGTH < sizeof(mRawBuf)
// mPos < BFH_INTERNAL_LENGTH
// BFH_INTERNAL_LENGTH - mPos < sizeof(mRawBuf)
// so toCopy <= BFH_INTERNAL_LENGTH
if (mPos < BMPFILEHEADER::INTERNAL_LENGTH) { /* In BITMAPFILEHEADER */
// BMPFILEHEADER::INTERNAL_LENGTH < sizeof(mRawBuf)
// mPos < BMPFILEHEADER::INTERNAL_LENGTH
// BMPFILEHEADER::INTERNAL_LENGTH - mPos < sizeof(mRawBuf)
// so toCopy <= BMPFILEHEADER::INTERNAL_LENGTH
// so toCopy < sizeof(mRawBuf)
// so toCopy > 0 && toCopy <= BFH_INTERNAL_LENGTH
uint32_t toCopy = BFH_INTERNAL_LENGTH - mPos;
// so toCopy > 0 && toCopy <= BMPFILEHEADER::INTERNAL_LENGTH
uint32_t toCopy = BMPFILEHEADER::INTERNAL_LENGTH - mPos;
if (toCopy > aCount) {
toCopy = aCount;
}
// mRawBuf is a byte array of size WIN_V3_INTERNAL_BIH_LENGTH
// mRawBuf is a byte array of size BIH_INTERNAL_LENGTH::WIN_V3
// (verified above)
// mPos is < BFH_INTERNAL_LENGTH
// BFH_INTERNAL_LENGTH < WIN_V3_INTERNAL_BIH_LENGTH
// mPos is < BMPFILEHEADER::INTERNAL_LENGTH
// BMPFILEHEADER::INTERNAL_LENGTH < BIH_INTERNAL_LENGTH::WIN_V3
// so mPos < sizeof(mRawBuf)
//
// Therefore this assert should hold
MOZ_ASSERT(mPos < sizeof(mRawBuf));
// toCopy <= BFH_INTERNAL_LENGTH
// mPos >= 0 && mPos < BFH_INTERNAL_LENGTH
// sizeof(mRawBuf) >= BFH_INTERNAL_LENGTH (verified above)
// toCopy <= BMPFILEHEADER::INTERNAL_LENGTH
// mPos >= 0 && mPos < BMPFILEHEADER::INTERNAL_LENGTH
// sizeof(mRawBuf) >= BMPFILEHEADER::INTERNAL_LENGTH (verified above)
//
// Therefore this assert should hold
MOZ_ASSERT(mPos + toCopy <= sizeof(mRawBuf));
@ -248,37 +249,37 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
aCount -= toCopy;
aBuffer += toCopy;
}
if (mPos == BFH_INTERNAL_LENGTH) {
if (mPos == BMPFILEHEADER::INTERNAL_LENGTH) {
ProcessFileHeader();
if (mBFH.signature[0] != 'B' || mBFH.signature[1] != 'M') {
PostDataError();
return;
}
if (mBFH.bihsize == OS2_BIH_LENGTH) {
mLOH = OS2_HEADER_LENGTH;
if (mBFH.bihsize == BIH_LENGTH::OS2) {
mLOH = BMP_HEADER_LENGTH::OS2;
}
}
if (mPos >= BFH_INTERNAL_LENGTH && mPos < mLOH) { /* In BITMAPINFOHEADER */
// mLOH == WIN_V3_HEADER_LENGTH || mLOH == OS2_HEADER_LENGTH
// OS2_HEADER_LENGTH < WIN_V3_HEADER_LENGTH
// BFH_INTERNAL_LENGTH < OS2_HEADER_LENGTH
// BFH_INTERNAL_LENGTH < WIN_V3_HEADER_LENGTH
if (mPos >= BMPFILEHEADER::INTERNAL_LENGTH && mPos < mLOH) { /* In BITMAPINFOHEADER */
// mLOH == BMP_HEADER_LENGTH::WIN_V3 || mLOH == BMP_HEADER_LENGTH::OS2
// BMP_HEADER_LENGTH::OS2 < BMP_HEADER_LENGTH::WIN_V3
// BMPFILEHEADER::INTERNAL_LENGTH < BMP_HEADER_LENGTH::OS2
// BMPFILEHEADER::INTERNAL_LENGTH < BMP_HEADER_LENGTH::WIN_V3
//
// So toCopy is in the range
// 1 to (WIN_V3_HEADER_LENGTH - BFH_INTERNAL_LENGTH)
// or 1 to (OS2_HEADER_LENGTH - BFH_INTERNAL_LENGTH)
// 1 to (BMP_HEADER_LENGTH::WIN_V3 - BMPFILEHEADER::INTERNAL_LENGTH)
// or 1 to (BMP_HEADER_LENGTH::OS2 - BMPFILEHEADER::INTERNAL_LENGTH)
//
// But WIN_V3_HEADER_LENGTH =
// BFH_INTERNAL_LENGTH + WIN_V3_INTERNAL_BIH_LENGTH
// and OS2_HEADER_LENGTH = BFH_INTERNAL_LENGTH + OS2_INTERNAL_BIH_LENGTH
// But BMP_HEADER_LENGTH::WIN_V3 =
// BMPFILEHEADER::INTERNAL_LENGTH + BIH_INTERNAL_LENGTH::WIN_V3
// and BMP_HEADER_LENGTH::OS2 = BMPFILEHEADER::INTERNAL_LENGTH + BIH_INTERNAL_LENGTH::OS2
//
// So toCopy is in the range
//
// 1 to WIN_V3_INTERNAL_BIH_LENGTH
// or 1 to OS2_INTERNAL_BIH_LENGTH
// and OS2_INTERNAL_BIH_LENGTH < WIN_V3_INTERNAL_BIH_LENGTH
// 1 to BIH_INTERNAL_LENGTH::WIN_V3
// or 1 to BIH_INTERNAL_LENGTH::OS2
// and BIH_INTERNAL_LENGTH::OS2 < BIH_INTERNAL_LENGTH::WIN_V3
//
// sizeof(mRawBuf) = WIN_V3_INTERNAL_BIH_LENGTH
// sizeof(mRawBuf) = BIH_INTERNAL_LENGTH::WIN_V3
// so toCopy <= sizeof(mRawBuf)
uint32_t toCopy = mLOH - mPos;
if (toCopy > aCount) {
@ -286,37 +287,37 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
}
// mPos is in the range
// BFH_INTERNAL_LENGTH to (WIN_V3_HEADER_LENGTH - 1)
// BMPFILEHEADER::INTERNAL_LENGTH to (BMP_HEADER_LENGTH::WIN_V3 - 1)
//
// offset is then in the range (see toCopy comments for more details)
// 0 to (WIN_V3_INTERNAL_BIH_LENGTH - 1)
// 0 to (BIH_INTERNAL_LENGTH::WIN_V3 - 1)
//
// sizeof(mRawBuf) is WIN_V3_INTERNAL_BIH_LENGTH so this
// sizeof(mRawBuf) is BIH_INTERNAL_LENGTH::WIN_V3 so this
// offset stays within bounds and this assert should hold
const uint32_t offset = mPos - BFH_INTERNAL_LENGTH;
const uint32_t offset = mPos - BMPFILEHEADER::INTERNAL_LENGTH;
MOZ_ASSERT(offset < sizeof(mRawBuf));
// Two cases:
// mPos = BFH_INTERNAL_LENGTH
// mLOH = WIN_V3_HEADER_LENGTH
// mPos = BMPFILEHEADER::INTERNAL_LENGTH
// mLOH = BMP_HEADER_LENGTH::WIN_V3
//
// offset = 0
// toCopy = WIN_V3_INTERNAL_BIH_LENGTH
// toCopy = BIH_INTERNAL_LENGTH::WIN_V3
//
// This will be in the bounds of sizeof(mRawBuf)
//
// Second Case:
// mPos = WIN_V3_HEADER_LENGTH - 1
// mLOH = WIN_V3_HEADER_LENGTH
// mPos = BMP_HEADER_LENGTH::WIN_V3 - 1
// mLOH = BMP_HEADER_LENGTH::WIN_V3
//
// offset = WIN_V3_INTERNAL_BIH_LENGTH - 1
// offset = BIH_INTERNAL_LENGTH::WIN_V3 - 1
// toCopy = 1
//
// This will be in the bounds of sizeof(mRawBuf)
//
// As sizeof(mRawBuf) == WIN_V3_INTERNAL_BIH_LENGTH (verified above)
// and WIN_V3_HEADER_LENGTH is the largest range of values. If mLOH
// was equal to OS2_HEADER_LENGTH then the ranges are smaller.
// As sizeof(mRawBuf) == BIH_INTERNAL_LENGTH::WIN_V3 (verified above)
// and BMP_HEADER_LENGTH::WIN_V3 is the largest range of values. If mLOH
// was equal to BMP_HEADER_LENGTH::OS2 then the ranges are smaller.
MOZ_ASSERT(offset + toCopy <= sizeof(mRawBuf));
memcpy(mRawBuf + offset, aBuffer, toCopy);
@ -368,9 +369,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
return;
}
// We have the size. If we're doing a size decode, we got what
// we came for.
if (IsSizeDecode()) {
// We have the size. If we're doing a metadata decode, we're done.
if (IsMetadataDecode()) {
return;
}
@ -386,7 +386,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// Always allocate 256 even though mNumColors might be smaller
mColors = new colorTable[256];
memset(mColors, 0, 256 * sizeof(colorTable));
} else if (mBIH.compression != BI_BITFIELDS && mBIH.bpp == 16) {
} else if (mBIH.compression != BMPINFOHEADER::BITFIELDS &&
mBIH.bpp == 16) {
// Use default 5-5-5 format
mBitFields.red = 0x7C00;
mBitFields.green = 0x03E0;
@ -396,27 +397,30 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// Make sure we have a valid value for our supported compression modes
// before adding the frame
if (mBIH.compression != BI_RGB && mBIH.compression != BI_RLE8 &&
mBIH.compression != BI_RLE4 && mBIH.compression != BI_BITFIELDS) {
if (mBIH.compression != BMPINFOHEADER::RGB &&
mBIH.compression != BMPINFOHEADER::RLE8 &&
mBIH.compression != BMPINFOHEADER::RLE4 &&
mBIH.compression != BMPINFOHEADER::BITFIELDS) {
PostDataError();
return;
}
// If we have RLE4 or RLE8 or BI_ALPHABITFIELDS, then ensure we
// have valid BPP values before adding the frame
if (mBIH.compression == BI_RLE8 && mBIH.bpp != 8) {
// If we have RLE4 or RLE8 or BMPINFOHEADER::ALPHABITFIELDS, then ensure
// we have valid BPP values before adding the frame.
if (mBIH.compression == BMPINFOHEADER::RLE8 && mBIH.bpp != 8) {
MOZ_LOG(GetBMPLog(), LogLevel::Debug,
("BMP RLE8 compression only supports 8 bits per pixel\n"));
PostDataError();
return;
}
if (mBIH.compression == BI_RLE4 && mBIH.bpp != 4 && mBIH.bpp != 1) {
if (mBIH.compression == BMPINFOHEADER::RLE4 &&
mBIH.bpp != 4 && mBIH.bpp != 1) {
MOZ_LOG(GetBMPLog(), LogLevel::Debug,
("BMP RLE4 compression only supports 4 bits per pixel\n"));
PostDataError();
return;
}
if (mBIH.compression == BI_ALPHABITFIELDS &&
if (mBIH.compression == BMPINFOHEADER::ALPHABITFIELDS &&
mBIH.bpp != 16 && mBIH.bpp != 32) {
MOZ_LOG(GetBMPLog(), LogLevel::Debug,
("BMP ALPHABITFIELDS only supports 16 or 32 bits per pixel\n"
@ -425,8 +429,9 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
return;
}
if (mBIH.compression != BI_RLE8 && mBIH.compression != BI_RLE4 &&
mBIH.compression != BI_ALPHABITFIELDS) {
if (mBIH.compression != BMPINFOHEADER::RLE8 &&
mBIH.compression != BMPINFOHEADER::RLE4 &&
mBIH.compression != BMPINFOHEADER::ALPHABITFIELDS) {
// mRow is not used for RLE encoded images
mRow = (uint8_t*)malloc((mBIH.width * mBIH.bpp) / 8 + 4);
// + 4 because the line is padded to a 4 bit boundary, but
@ -447,7 +452,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
MOZ_ASSERT(mImageData, "Should have a buffer now");
// Prepare for transparency
if ((mBIH.compression == BI_RLE8) || (mBIH.compression == BI_RLE4)) {
if ((mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4)) {
// Clear the image, as the RLE may jump over areas
memset(mImageData, 0, mImageDataLength);
}
@ -455,7 +461,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
if (mColors && mPos >= mLOH) {
// OS/2 Bitmaps have no padding byte
uint8_t bytesPerColor = (mBFH.bihsize == OS2_BIH_LENGTH) ? 3 : 4;
uint8_t bytesPerColor = (mBFH.bihsize == BIH_LENGTH::OS2) ? 3 : 4;
if (mPos < (mLOH + mNumColors * bytesPerColor)) {
// Number of bytes already received
uint32_t colorBytes = mPos - mLOH;
@ -488,62 +494,62 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
at = (at + 1) % bytesPerColor;
}
}
} else if (aCount && mBIH.compression == BI_BITFIELDS && mPos <
(WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH)) {
// If compression is used, this is a windows bitmap (compression
// can't be used with OS/2 bitmaps),
// hence we can use WIN_V3_HEADER_LENGTH instead of mLOH.
// (verified below)
} else if (aCount &&
mBIH.compression == BMPINFOHEADER::BITFIELDS &&
mPos < (BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH)) {
// If compression is used, this is a windows bitmap (compression can't be
// used with OS/2 bitmaps), hence we can use BMP_HEADER_LENGTH::WIN_V3
// instead of mLOH. (verified below)
// If aCount != 0 then mPos should be >= mLOH due to the if statements
// at the beginning of the function
MOZ_ASSERT(mPos >= mLOH);
MOZ_ASSERT(mLOH == WIN_V3_HEADER_LENGTH);
MOZ_ASSERT(mLOH == BMP_HEADER_LENGTH::WIN_V3);
// mLOH == WIN_V3_HEADER_LENGTH (verified above)
// mLOH == BMP_HEADER_LENGTH::WIN_V3 (verified above)
// mPos >= mLOH (verified above)
// mPos < WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH
// mPos < BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH
//
// So toCopy is in the range
// 0 to (BITFIELD_LENGTH - 1)
uint32_t toCopy = (WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH) - mPos;
// 0 to (bitFields::LENGTH - 1)
uint32_t toCopy = (BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH) - mPos;
if (toCopy > aCount) {
toCopy = aCount;
}
// mPos >= WIN_V3_HEADER_LENGTH
// mPos < WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH
// mPos >= BMP_HEADER_LENGTH::WIN_V3
// mPos < BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH
//
// offset is in the range
// 0 to (BITFIELD_LENGTH - 1)
// 0 to (bitFields::LENGTH - 1)
//
// BITFIELD_LENGTH < WIN_V3_INTERNAL_BIH_LENGTH
// and sizeof(mRawBuf) == WIN_V3_INTERNAL_BIH_LENGTH (verified at
// bitFields::LENGTH < BIH_INTERNAL_LENGTH::WIN_V3
// and sizeof(mRawBuf) == BIH_INTERNAL_LENGTH::WIN_V3 (verified at
// top of function)
//
// Therefore this assert should hold
const uint32_t offset = mPos - WIN_V3_HEADER_LENGTH;
const uint32_t offset = mPos - BMP_HEADER_LENGTH::WIN_V3;
MOZ_ASSERT(offset < sizeof(mRawBuf));
// Two cases:
// mPos = WIN_V3_HEADER_LENGTH
// mPos = BMP_HEADER_LENGTH::WIN_V3
//
// offset = 0
// toCopy = BITFIELD_LENGTH
// toCopy = bitFields::LENGTH
//
// This will be in the bounds of sizeof(mRawBuf)
//
// Second case:
//
// mPos = WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH - 1
// mPos = BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH - 1
//
// offset = BITFIELD_LENGTH - 1
// offset = bitFields::LENGTH - 1
// toCopy = 1
//
// This will be in the bounds of sizeof(mRawBuf)
//
// As BITFIELD_LENGTH < WIN_V3_INTERNAL_BIH_LENGTH and
// sizeof(mRawBuf) == WIN_V3_INTERNAL_BIH_LENGTH
// As bitFields::LENGTH < BIH_INTERNAL_LENGTH::WIN_V3 and
// sizeof(mRawBuf) == BIH_INTERNAL_LENGTH::WIN_V3
//
// Therefore this assert should hold
MOZ_ASSERT(offset + toCopy <= sizeof(mRawBuf));
@ -553,8 +559,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
aBuffer += toCopy;
aCount -= toCopy;
}
if (mPos == WIN_V3_HEADER_LENGTH + BITFIELD_LENGTH &&
mBIH.compression == BI_BITFIELDS) {
if (mPos == BMP_HEADER_LENGTH::WIN_V3 + bitFields::LENGTH &&
mBIH.compression == BMPINFOHEADER::BITFIELDS) {
mBitFields.red = LittleEndian::readUint32(reinterpret_cast<uint32_t*>
(mRawBuf));
mBitFields.green = LittleEndian::readUint32(reinterpret_cast<uint32_t*>
@ -570,7 +576,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
if (aCount && ++mPos >= mBFH.dataoffset) {
// Need to increment mPos, else we might get to mPos==mLOH again
// From now on, mPos is irrelevant
if (!mBIH.compression || mBIH.compression == BI_BITFIELDS) {
if (!mBIH.compression || mBIH.compression == BMPINFOHEADER::BITFIELDS) {
uint32_t rowSize = (mBIH.bpp * mBIH.width + 7) / 8; // + 7 to
// round up
if (rowSize % 4) {
@ -689,10 +695,10 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mRowBytes = 0;
}
} while (aCount > 0);
} else if ((mBIH.compression == BI_RLE8) ||
(mBIH.compression == BI_RLE4)) {
if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8)) ||
((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) &&
} else if ((mBIH.compression == BMPINFOHEADER::RLE8) ||
(mBIH.compression == BMPINFOHEADER::RLE4)) {
if (((mBIH.compression == BMPINFOHEADER::RLE8) && (mBIH.bpp != 8)) ||
((mBIH.compression == BMPINFOHEADER::RLE4) && (mBIH.bpp != 4) &&
(mBIH.bpp != 1))) {
MOZ_LOG(GetBMPLog(), LogLevel::Debug,
("BMP RLE8/RLE4 compression only supports 8/4 bits per"
@ -715,7 +721,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case eRLEStateNeedSecondEscapeByte:
byte = *aBuffer++;
aCount--;
if (mStateData != RLE_ESCAPE) { // encoded mode
if (mStateData != RLE::ESCAPE) { // encoded mode
// Encoded mode consists of two bytes:
// the first byte (mStateData) specifies the
// number of consecutive pixels to be drawn
@ -729,7 +735,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
uint32_t* d = reinterpret_cast<uint32_t*>
(mImageData) + PIXEL_OFFSET(mCurLine, mCurPos);
mCurPos += pixelsNeeded;
if (mBIH.compression == BI_RLE8) {
if (mBIH.compression == BMPINFOHEADER::RLE8) {
do {
SetPixel(d, byte, mColors);
pixelsNeeded --;
@ -744,18 +750,18 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
}
switch(byte) {
case RLE_ESCAPE_EOL:
case RLE::ESCAPE_EOL:
// End of Line: Go to next row
mCurLine --;
mCurPos = 0;
mState = eRLEStateInitial;
break;
case RLE_ESCAPE_EOF: // EndOfFile
case RLE::ESCAPE_EOF: // EndOfFile
mCurPos = mCurLine = 0;
break;
case RLE_ESCAPE_DELTA:
case RLE::ESCAPE_DELTA:
mState = eRLEStateNeedXDelta;
continue;
@ -834,7 +840,7 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
(mImageData) +
PIXEL_OFFSET(mCurLine, mCurPos);
uint32_t* oldPos = d;
if (mBIH.compression == BI_RLE8) {
if (mBIH.compression == BMPINFOHEADER::RLE8) {
while (aCount > 0 && mStateData > 0) {
byte = *aBuffer++;
aCount--;

Some files were not shown because too many files have changed in this diff Show More