mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:34:03 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1238964 Part 1: Hold new printable page sizes in print nsIPrintSettingsWin. r=jimm (b5e4d012ba) - Bug 1238964 Part 2: Move separate DEVMODE to nsIPrintSettings copying into nsPrintSettingsWin. r=jimm (cb7bb66037) - Bug 1218029 - Adds SRICheckDataVerifier for progressing data handling. r=francois (8331afc1a7) - Bug 1218029 - Implements progressive Unicode chars decoding in nsScriptLoader. r=djvj (2c32ca259a) - Bug 1237201 part 1 - Use MOZ_ALWAYS_TRUE in nsScriptLoadHandler::TryDecodeRawData. r=yury (8f7496be23) - Bug 1237201 part 2 - Handle Vector OOM in gfx/. r=jrmuizel,kats (d5e8bd3383) - Bug 1237201 part 3 - Handle Vector OOM in StreamingLexer. r=njn (be383e35b4) - Bug 1237201 part 4 - Handle Vector OOM in ipc/. r=billm (fe9a3bf25a) - Bug 1237201 part 5 - Ignore Vector OOM in JSMainRuntimeCompartmentsReporter. r=njn (d0070c0636) - Bug 1237201 part 6 - Handle Vector OOM in media/webrtc/. r=jesup (eab4e00735) - Bug 1186491 - Splitting nsIPerformanceStats in two;r=froydnj (006b578345) - Bug 1186491 - An API for watching slow performance alerts (xpcom-level);r=froydnj (4fcefd66f5) - Bug 1237201 part 7 - Handle Vector OOM in nsPerformanceStats, telemetry. r=Yoric (6021b583ff) - Bug 1237201 part 8 - Make fallible Vector methods MOZ_WARN_UNUSED_RESULT. r=jwalden (90144c2d35) - Bug 1237201 part 9 - Fix remaining issues. r=nfroyd (25b86adb6d) - Bug 1186491 - An API for watching slow performance alerts (js-level); r=felipe (f04d277c80) - Bug 1200172 - AddonWatcher now discards data if the system is apparently too busy/just back from hibernation. r=mossop (66a3840b73) - Bug 1205840 - Typo fixes in AddonWatcher.jsm. r=felipe (760df6764c) - Bug 1186491 - Reworking AddonWatcher to use low-level performance watch API;r=mossop (81cc64263e) - Bug 1200169 - Making the slow add-on watcher more tolerant;r=Felipe (fcf988d985) - Bug 1157009 - Redesign about:performance. r=felipe (cacc590716) - Bug 1189513 - Get rid of separation between e10s and non-e10s probes; r=felipe (7a6d996c93) - Bug 1191327 - Recapitulates alerts in about:performance now. r=felipe (53ecc02da9) - Bug 1189799 - Make sure that about:performance displays each add-on only once (front-end);r=felipe (1ee53a0410) - Bug 1208747 - Move most of Stopwatch-related code to XPCOM-land (JS-level);r=felipe (84af14c20e) - Bug 1229519: Fix miscellaneous parts of toolkit to pass eslint checks. r=MattN (00ce3585c5) - Bug 1230735 - AddonWatcher.alerts is now a map;r=Felipe (81bbafbbd4) - Bug 1241838 - Removing erroneous CPOW suffix, reworking buggy jank suffix;r=Felipe (020d6928e6) - Bug 1175098 - Fix double-loading of PerformanceStats content script. r=mconley (fb1c499343) - Bug 1189799 - Make sure that about:performance displays each add-on only once (back-end);r=felipe (1eac8258df) - Bug 1221761 - Probe.prototype.release() now swallows NS_ERROR_NOT_AVAILABLE. r=felipe (ba1d0032a9) - Bug 1142937 - AddonWatcher now communicates through nsIObserverService. r=felipe (ea2e7ccdaa) - Bug 967873 - Test changes for async removeTab (r=Gijs) (dae5cbf835) - more missing parts of Bug 1132072 - Tab switch refactoring (r=mconley) (dc5e310537) - Bug 1191460 Rebased patch and added userContextId to origin attributes. (r=tanvi,r=sicking) (723999e7fa) - Bug 1239040 - Cleanup of DrawTargetSkia GetBitmapForSurface to use installPixels. r=jrmuizel (4016f4d734) - Bug 1239040 - Cleanup of DrawTargetSkia Mask and MaskSurface. r=jrmuizel (908a44d47e) - Bug 1239040 - Implement PushLayer for DrawTargetSkia. r=Bas (ae74697559) - Bug 1246756 - part 1 - fix moz2d Skia usage for Skia m49 update. r=jrmuizel (5e4b0f41e3) - Bug 1239040 - Allow usage of SkCanvas::getTopDevice in Skia. r=jrmuizel (19bdd2cecb) - Bug 1239040 - Fix DrawTargetCairo/DrawTargetSkia LockBits and BorrowedXlibDrawable to work inside PushLayer. r=jrmuizel (b9ba04009b) - Bug 1239040 - Cleanup of DrawTargetSkia CopySurface to avoid accessing bottom layer directly. r=jrmuizel (6690702507) - Bug 1240437: Implement PushLayer and PopLayer for DrawTargetRecording. r=bas (22673a1b52) - Bug 1220629 - Part 1: Add PushLayer/PopLayer API to DrawTarget baseclass. r=jrmuizel (c4b4315749) - Bug 1220629 - Part 2: Prepare DrawTargetD2D1 for the possibilities of layers existing inside it. r=jrmuizel (f2a74151a8) - Bug 1220629 - Part 3: Implement PushLayer/PopLayer API in cairo. r=jrmuizel (9a52965141) - Bug 1220629 - Part 4: Allow gfxContext to use the native pushlayer implementations based on a pref. r=jrmuizel (f13b773ff3) - Bug 1220629 - Part 5: Implement PushLayer/PopLayer API for Direct2D 1.1. r=jrmuizel (8a040648a2) - Bug 1220629 - Part 6: Implement PushLayer/PopLayer API in several wrapper DT types. r=jrmuizel (cf76723216) - Bug 1220629 - Part 7: Mark several reftests fuzzy. r=jrmuizel (a6deab2300) - Bug 1220629 - Part 8: Enable native PushLayer/PopLayer by default on Windows and Linux. r=jrmuizel (eef18e1e3e) - Bug 1234494 - part 1 - don't build in Skia GPU code if support is disabled, r=jrmuizel (4c74813077) - Bug 1234494 - part 2 - disable Skia GPU support by default on certain *BSDs, r=glandium (6184133b33) - Bug 1246756 - part 2 - update Skia moz.build for m49 update. r=jrmuizel (e0cf4ab953) - Bug 1244454 - Fixed skia compilation on mingw. r=lsalzman (064a56e56e) - Bug 1242044 - "layout/reftests/css-gradients/linear-zero-length-1 fails under Skia content". r=jmuizelaar (bee8f76e72) - Bug 1242751 - fix assertion in SkLinearGradient. r=jmuizelaar (f5df5ed88f) - Bug 1238795 - Fix SkGpuDevice::drawBitmapRect to always update clips. r=jrmuizel (05a9a6b10a) - Bug 1230096 - fix GrAAConvexTessellator assertion. r=jrmuizel (18aef9bdcc) - Bug 1237983 - Investigate and remove the Bagheera Client Implementation. r=gfritzsche (6de39c0e32) - Bug 1246756 - part 3 - update Skia to m49 branch. r=jrmuizel (a02a53e368) - Bug 1234526 - Remove services/healthreport. r=gfritzsche (bb0c567255) - Bug 1234522 - Remove services/datareporting. r=gfritzsche (c7bfec7784) - Bug 1211166 - Use AppConstants in SessionRecorder.jsm r=ted (4434996c34) - Bug 1246756 - Cross compilation fixup. r=upstream (99e3e40ba1) - Bug 1248228 - Build fix for SkOSFile_stdio on OpenBSD. r=jmuizelaar (bbb1eb7ac0) - Bug 1250196 - Part 1: Import mozilla::Forward and mozilla::UniqePtr into the std namespace in a way that is compatible with libc++; r=lsalzman (ffeebcc133) - Bug 1248851 part 4 - Mark UniquePtr::release() MOZ_WARN_UNUSED_RESULT. r=Waldo (f43cced74c) - Bug 1250196 - Part 2: Rename UniquePtr::getDeleter() to get_deleter() in order to make it compatible with std::unique_ptr; r=froydnj (f8aeabfc9a) - Bug 1248851 part 3 - Fix a potential double-free issue in indexedDB. r=sicking (4d13f5047b) - Bug 1248851 part 2 - Remove redundant release() calls in indexedDB code. r=sicking (86d67ffad8) - Bug 1239702 - Fix SK_ARM_HAS_NEON build config r=lsalzman (4233a57122) - Bug 1245979 - make mfbt Function reference-counted so that it can be cheaply copied for compatibility with Skia. r=froydnj (bd69e9c07b) - Bug 1245055 - Remove gfx/skia/Makefile.in. r=mshal (bf2c611f38) - Bug 1232694 - fix typo in Compiler.h; r=botond (2b5abb9d2d) - Bug 1228641 - Rename begin/size to aBegin/aSize to avoid shadow warnings; r=botond (9222809505) - Bug 1248784 - Rename the existing AddRefTraits to ConstRemovingRefPtrTraits. r=froydnj (99d7b0ae1f) - Bug 1248784 - Extract the AddRef/Release calls into a non-inner helper trait. r=froydnj (37243b6235) - Bug 1248784 - Followup to add requested comment. r=froydnj DONTBUILD (0e870b586b) - Bug 1242794 - make SkGrPixelRef::deepCopy preserve alpha type. r=jmuizelaar (0fb454c326) - Bug 1201037 - (Linux) squash network-change events during 1000ms, r=mcmanus (087f57c44d) - Bug 1235509 - Link monitor should not fire link change events for the refresh of the ipv6 lifetime. r=bagder (c507a319c4) - Bug 1234548 - Don't send network change events if routes are changed. r=mcmanus, r=bagder (5cd0bc582e) - Bug 1234548 - Remove unused variables. r=bustage (42df135fbf) - Bug 1240515 - change allocator for addr and localaddr from malloc to new, since the smart pointer that is used uses delete operator. r=dragana (02f5d5433c) - Bug 1241901 part 1 - Remove nsAutoPtr uses in nsNotifyAddrListener on Linux. r=bagder (f8696ad190) - Bug 1241901 part 2 - Use intptr_t to pass bluetooth service class instead of a pointer to heap. r=shawnjohnjr (5c86a164fa) - Bug 1241901 part 3 - Add IsMemberPointer and IsScalar type traits. r=froydnj (80747268bd) - Bug 1243876 - fix ConvertibleTester to not cause incomplete type errors with UniquePtr and Skia. r=nfroyd (c5588dd270) - Bug 1234736 - IonMonkey: Recover Math.imul as an int32 operation. r=h4writer (459b92c618) - Bug 1228571 - Fix GenerateSeed to not leave seed uninitialized if reading from /dev/urandom fails. r=cpeterson (3be0a2816b) - Bug 1233302: Don't crash if we can't open /dev/urandom; just fall back to PRMJ_Now. (d83ae5540a) - Bug 1167248 - Call RtlGenRandom() instead of rand_s() to workaround crashes from injected third-party hooks. r=jandem (678e7a0056) - Bug 1236619 Fix compilation failure with warnings-as-errors with some compilers. r=njn (043956881d) - Bug 1167248 - Cross compilation fixup. (f4a34fb229)
This commit is contained in:
@@ -251,7 +251,9 @@ ReserveFileDescriptors(FdArray& aReservedFds)
|
||||
MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor.");
|
||||
}
|
||||
|
||||
aReservedFds.append(target);
|
||||
if (!aReservedFds.append(target)) {
|
||||
MOZ_CRASH("Failed to append to aReservedFds");
|
||||
}
|
||||
|
||||
if (fd == target) {
|
||||
// No need to call dup2(). We already occupy the desired file descriptor.
|
||||
|
||||
@@ -649,10 +649,6 @@
|
||||
#endif
|
||||
@RESPATH@/components/servicesComponents.manifest
|
||||
@RESPATH@/components/cryptoComponents.manifest
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@RESPATH@/components/HealthReportComponents.manifest
|
||||
@RESPATH@/components/HealthReportService.js
|
||||
#endif
|
||||
@RESPATH@/components/CaptivePortalDetectComponents.manifest
|
||||
@RESPATH@/components/captivedetect.js
|
||||
@RESPATH@/components/TelemetryStartup.js
|
||||
|
||||
@@ -526,12 +526,7 @@
|
||||
@RESPATH@/components/nsINIProcessor.js
|
||||
@RESPATH@/components/nsPrompter.manifest
|
||||
@RESPATH@/components/nsPrompter.js
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
@RESPATH@/components/DataReporting.manifest
|
||||
@RESPATH@/components/DataReportingService.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@RESPATH@/components/HealthReportComponents.manifest
|
||||
@RESPATH@/browser/components/SelfSupportService.manifest
|
||||
@RESPATH@/browser/components/SelfSupportService.js
|
||||
#endif
|
||||
|
||||
@@ -7769,6 +7769,15 @@ MOZ_ARG_ENABLE_BOOL(skia,
|
||||
MOZ_ENABLE_SKIA=,
|
||||
MOZ_ENABLE_SKIA=)
|
||||
|
||||
dnl Skia GPU support may not reliably build on certain *BSDs (see bug 1234494).
|
||||
if test "${OS_TARGET}" = "OpenBSD" -o \
|
||||
"${OS_TARGET}" = "NetBSD" -o \
|
||||
"${OS_ARCH}" = "SunOS"; then
|
||||
MOZ_DISABLE_SKIA_GPU=1
|
||||
else
|
||||
MOZ_DISABLE_SKIA_GPU=
|
||||
fi
|
||||
|
||||
MOZ_ARG_DISABLE_BOOL(skia-gpu,
|
||||
[ --disable-skia-gpu Disable use of Skia-GPU],
|
||||
MOZ_DISABLE_SKIA_GPU=1,
|
||||
|
||||
@@ -13794,6 +13794,13 @@ nsDocShell::SetIsSignedPackage(const nsAString& aSignedPkg)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetUserContextId(uint32_t aUserContextId)
|
||||
{
|
||||
mUserContextId = aUserContextId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
|
||||
{
|
||||
@@ -13897,6 +13904,8 @@ nsDocShell::GetOriginAttributes()
|
||||
attrs.mAppId = mOwnOrContainingAppId;
|
||||
}
|
||||
|
||||
attrs.mUserContextId = mUserContextId;
|
||||
|
||||
if (mFrameType == eFrameTypeBrowser) {
|
||||
attrs.mInBrowser = true;
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@ public:
|
||||
NS_IMETHOD GetUseRemoteTabs(bool*) override;
|
||||
NS_IMETHOD SetRemoteTabs(bool) override;
|
||||
NS_IMETHOD GetOriginAttributes(JS::MutableHandle<JS::Value>) override;
|
||||
NS_IMETHOD SetUserContextId(uint32_t);
|
||||
|
||||
// Restores a cached presentation from history (mLSHE).
|
||||
// This method swaps out the content viewer and simulates loads for
|
||||
@@ -1011,6 +1012,9 @@ protected:
|
||||
// find it by walking up the docshell hierarchy.)
|
||||
uint32_t mOwnOrContainingAppId;
|
||||
|
||||
// userContextId signifying which container we are in
|
||||
uint32_t mUserContextId;
|
||||
|
||||
nsString mPaymentRequestId;
|
||||
|
||||
nsString GetInheritedPaymentRequestId();
|
||||
|
||||
@@ -31,8 +31,8 @@ function makeTimelineTest(frameScriptName, url) {
|
||||
info(message.data.message);
|
||||
});
|
||||
mm.addMessageListener("browser:test:finish", function(ignore) {
|
||||
finish();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -60,3 +60,40 @@ function timelineTestOpenUrl(url) {
|
||||
|
||||
return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for charset tests. It loads |url| in a new tab,
|
||||
* runs |check1| in a ContentTask when the page is ready, switches the
|
||||
* charset to |charset|, and then runs |check2| in a ContentTask when
|
||||
* the page has finished reloading.
|
||||
*
|
||||
* |charset| and |check2| can be omitted, in which case the test
|
||||
* finishes when |check1| completes.
|
||||
*/
|
||||
function runCharsetTest(url, check1, charset, check2) {
|
||||
waitForExplicitFinish();
|
||||
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, url, true).then(afterOpen);
|
||||
|
||||
function afterOpen() {
|
||||
if (charset) {
|
||||
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
|
||||
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
|
||||
BrowserSetForcedCharacterSet(charset);
|
||||
});
|
||||
} else {
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function afterChangeCharset() {
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, check2).then(() => {
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+44
-10
@@ -234,7 +234,7 @@ nsFrameLoader::LoadFrame()
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = LoadURI(uri);
|
||||
}
|
||||
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
FireErrorEvent();
|
||||
|
||||
@@ -325,7 +325,7 @@ nsFrameLoader::ReallyStartLoading()
|
||||
if (NS_FAILED(rv)) {
|
||||
FireErrorEvent();
|
||||
}
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
|
||||
// FIXME get error codes from child
|
||||
mRemoteBrowser->LoadURL(mURIToLoad);
|
||||
|
||||
|
||||
if (!mRemoteBrowserShown && !ShowRemoteFrame(ScreenIntSize(0, 0))) {
|
||||
NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
|
||||
}
|
||||
@@ -378,7 +378,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
loadInfo->SetOwner(mOwnerContent->NodePrincipal());
|
||||
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
|
||||
|
||||
nsAutoString srcdoc;
|
||||
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
|
||||
@@ -552,7 +552,7 @@ nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
{
|
||||
NS_PRECONDITION(aItem, "Must have docshell treeitem");
|
||||
NS_PRECONDITION(mOwnerContent, "Must have owning content");
|
||||
|
||||
|
||||
nsAutoString value;
|
||||
bool isContent = false;
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
|
||||
@@ -1133,7 +1133,7 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
!AllDescendantsOfType(otherDocshell, otherType))) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
// Save off the tree owners, frame elements, chrome event handlers, and
|
||||
// docshell and document parents before doing anything else.
|
||||
nsCOMPtr<nsIDocShellTreeOwner> ourOwner, otherOwner;
|
||||
@@ -1243,7 +1243,7 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
ourOwner->ContentShellRemoved(ourDocshell);
|
||||
otherOwner->ContentShellRemoved(otherDocshell);
|
||||
}
|
||||
|
||||
|
||||
ourParentItem->AddChild(otherDocshell);
|
||||
otherParentItem->AddChild(ourDocshell);
|
||||
|
||||
@@ -1794,6 +1794,23 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
mDocShell->SetName(frameName);
|
||||
}
|
||||
|
||||
//Grab the userContextId from owner if XUL
|
||||
nsAutoString userContextIdStr;
|
||||
if (namespaceID == kNameSpaceID_XUL) {
|
||||
if (mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::usercontextid)) {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::usercontextid,
|
||||
userContextIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!userContextIdStr.IsEmpty()) {
|
||||
nsresult err;
|
||||
nsDocShell * ds = nsDocShell::Cast(mDocShell);
|
||||
ds->SetUserContextId(userContextIdStr.ToInteger(&err));
|
||||
NS_ENSURE_SUCCESS(err, err);
|
||||
}
|
||||
|
||||
// Inform our docShell that it has a new child.
|
||||
// Note: This logic duplicates a lot of logic in
|
||||
// nsSubDocumentFrame::AttributeChanged. We should fix that.
|
||||
@@ -1967,7 +1984,7 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
||||
NS_WARN_IF_FALSE(treeOwner,
|
||||
"Trying to load a new url to a docshell without owner!");
|
||||
NS_ENSURE_STATE(treeOwner);
|
||||
|
||||
|
||||
if (mDocShell->ItemType() != nsIDocShellTreeItem::typeContent) {
|
||||
// No need to do recursion-protection here XXXbz why not?? Do we really
|
||||
// trust people not to screw up with non-content docshells?
|
||||
@@ -1981,7 +1998,7 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
||||
int32_t depth = 0;
|
||||
while (parentAsItem) {
|
||||
++depth;
|
||||
|
||||
|
||||
if (depth >= MAX_DEPTH_CONTENT_FRAMES) {
|
||||
mDepthTooGreat = true;
|
||||
NS_WARNING("Too many nested content frames so giving up");
|
||||
@@ -2022,7 +2039,7 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
||||
bool equal;
|
||||
rv = aURI->EqualsExceptRef(parentURI, &equal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
if (equal) {
|
||||
matchCount++;
|
||||
if (matchCount >= MAX_SAME_URL_CONTENT_FRAMES) {
|
||||
@@ -3039,6 +3056,23 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||
// Populate packageId to signedPkg.
|
||||
attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aPackageId);
|
||||
|
||||
// set the userContextId on the attrs before we pass them into
|
||||
// the tab context
|
||||
if (mOwnerContent) {
|
||||
nsAutoString userContextIdStr;
|
||||
if (mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::usercontextid)) {
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::usercontextid,
|
||||
userContextIdStr);
|
||||
}
|
||||
if (!userContextIdStr.IsEmpty()) {
|
||||
nsresult err;
|
||||
uint32_t userContextId = userContextIdStr.ToInteger(&err);
|
||||
NS_ENSURE_SUCCESS(err, err);
|
||||
attrs.mUserContextId = userContextId;
|
||||
}
|
||||
}
|
||||
|
||||
bool tabContextUpdated = aTabContext->SetTabContext(ownApp, containingApp,
|
||||
attrs, aSignedPkgOriginNoSuffix);
|
||||
NS_ENSURE_STATE(tabContextUpdated);
|
||||
|
||||
@@ -2417,6 +2417,9 @@ GK_ATOM(onboundary, "onboundary")
|
||||
|
||||
GK_ATOM(vr_state, "vr-state")
|
||||
|
||||
// Contextual Identity / Containers
|
||||
GK_ATOM(usercontextid, "usercontextid")
|
||||
|
||||
// MSE
|
||||
GK_ATOM(onsourceopen, "onsourceopen")
|
||||
GK_ATOM(onsourceended, "onsourceended")
|
||||
|
||||
+193
-42
@@ -14,7 +14,6 @@
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
@@ -54,7 +53,6 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/SRICheck.h"
|
||||
#include "nsIScriptError.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@@ -352,7 +350,13 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
||||
timedChannel->SetInitiatorType(NS_LITERAL_STRING("script"));
|
||||
}
|
||||
|
||||
RefPtr<nsScriptLoadHandler> handler = new nsScriptLoadHandler(this, aRequest);
|
||||
nsAutoPtr<mozilla::dom::SRICheckDataVerifier> sriDataVerifier;
|
||||
if (!aRequest->mIntegrity.IsEmpty()) {
|
||||
sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, mDocument);
|
||||
}
|
||||
|
||||
RefPtr<nsScriptLoadHandler> handler =
|
||||
new nsScriptLoadHandler(this, aRequest, sriDataVerifier.forget());
|
||||
|
||||
nsCOMPtr<nsIIncrementalStreamLoader> loader;
|
||||
rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
|
||||
@@ -1425,20 +1429,33 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
|
||||
nsresult
|
||||
nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString)
|
||||
nsresult aChannelStatus,
|
||||
nsresult aSRIStatus,
|
||||
mozilla::Vector<char16_t> &aString,
|
||||
mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier)
|
||||
{
|
||||
nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
|
||||
NS_ASSERTION(request, "null request in stream complete handler");
|
||||
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = NS_ERROR_SRI_CORRUPT;
|
||||
if (request->mIntegrity.IsEmpty() ||
|
||||
NS_SUCCEEDED(SRICheck::VerifyIntegrity(request->mIntegrity, aLoader,
|
||||
request->mCORSMode, aStringLen,
|
||||
aString, mDocument))) {
|
||||
rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen, aString);
|
||||
nsresult rv = NS_OK;
|
||||
if (!request->mIntegrity.IsEmpty() &&
|
||||
NS_SUCCEEDED((rv = aSRIStatus))) {
|
||||
MOZ_ASSERT(aSRIDataVerifier);
|
||||
|
||||
nsCOMPtr<nsIRequest> channelRequest;
|
||||
aLoader->GetRequest(getter_AddRefs(channelRequest));
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
channel = do_QueryInterface(channelRequest);
|
||||
|
||||
if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel,
|
||||
request->mCORSMode, mDocument))) {
|
||||
rv = NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = PrepareLoadedRequest(request, aLoader, aChannelStatus, aString);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
@@ -1481,16 +1498,12 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
} else {
|
||||
mPreloads.RemoveElement(request, PreloadRequestComparator());
|
||||
}
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
moz_free(const_cast<uint8_t *>(aString));
|
||||
rv = NS_SUCCESS_ADOPTED_DATA;
|
||||
}
|
||||
|
||||
// Process our request and/or any pending ones
|
||||
ProcessPendingRequests();
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1521,8 +1534,7 @@ nsresult
|
||||
nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
||||
nsIIncrementalStreamLoader* aLoader,
|
||||
nsresult aStatus,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString)
|
||||
mozilla::Vector<char16_t> &aString)
|
||||
{
|
||||
if (NS_FAILED(aStatus)) {
|
||||
return aStatus;
|
||||
@@ -1573,21 +1585,9 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (aStringLen) {
|
||||
// Check the charset attribute to determine script charset.
|
||||
nsAutoString hintCharset;
|
||||
if (!aRequest->IsPreload()) {
|
||||
aRequest->mElement->GetScriptCharset(hintCharset);
|
||||
} else {
|
||||
nsTArray<PreloadInfo>::index_type i =
|
||||
mPreloads.IndexOf(aRequest, 0, PreloadRequestComparator());
|
||||
NS_ASSERTION(i != mPreloads.NoIndex, "Incorrect preload bookkeeping");
|
||||
hintCharset = mPreloads[i].mCharset;
|
||||
}
|
||||
rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
|
||||
aRequest->mScriptTextBuf, aRequest->mScriptTextLength);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!aString.empty()) {
|
||||
aRequest->mScriptTextLength = aString.length();
|
||||
aRequest->mScriptTextBuf = aString.extractRawBuffer();
|
||||
}
|
||||
|
||||
// This assertion could fire errorously if we ran out of memory when
|
||||
@@ -1732,9 +1732,14 @@ nsScriptLoader::MaybeRemovedDeferRequests()
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
nsScriptLoadHandler::nsScriptLoadHandler(nsScriptLoader *aScriptLoader,
|
||||
nsScriptLoadRequest *aRequest)
|
||||
nsScriptLoadRequest *aRequest,
|
||||
mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier)
|
||||
: mScriptLoader(aScriptLoader),
|
||||
mRequest(aRequest)
|
||||
mRequest(aRequest),
|
||||
mSRIDataVerifier(aSRIDataVerifier),
|
||||
mSRIStatus(NS_OK),
|
||||
mDecoder(),
|
||||
mBuffer()
|
||||
{}
|
||||
|
||||
nsScriptLoadHandler::~nsScriptLoadHandler()
|
||||
@@ -1749,18 +1754,164 @@ nsScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
|
||||
const uint8_t* aData,
|
||||
uint32_t *aConsumedLength)
|
||||
{
|
||||
if (mRequest->IsCanceled()) {
|
||||
// If request cancelled, ignore any incoming data.
|
||||
*aConsumedLength = aDataLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!EnsureDecoder(aLoader, aData, aDataLength,
|
||||
/* aEndOfStream = */ false)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Below we will/shall consume entire data chunk.
|
||||
*aConsumedLength = aDataLength;
|
||||
|
||||
// Decoder has already been initialized. -- trying to decode all loaded bytes.
|
||||
nsresult rv = TryDecodeRawData(aData, aDataLength,
|
||||
/* aEndOfStream = */ false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If SRI is required for this load, appending new bytes to the hash.
|
||||
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
|
||||
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptLoadHandler::TryDecodeRawData(const uint8_t* aData,
|
||||
uint32_t aDataLength,
|
||||
bool aEndOfStream)
|
||||
{
|
||||
int32_t srcLen = aDataLength;
|
||||
const char* src = reinterpret_cast<const char *>(aData);
|
||||
int32_t dstLen;
|
||||
nsresult rv =
|
||||
mDecoder->GetMaxLength(src, srcLen, &dstLen);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t haveRead = mBuffer.length();
|
||||
uint32_t capacity = haveRead + dstLen;
|
||||
if (!mBuffer.reserve(capacity)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = mDecoder->Convert(src,
|
||||
&srcLen,
|
||||
mBuffer.begin() + haveRead,
|
||||
&dstLen);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
haveRead += dstLen;
|
||||
MOZ_ASSERT(haveRead <= capacity, "mDecoder produced more data than expected");
|
||||
MOZ_ALWAYS_TRUE(mBuffer.resizeUninitialized(haveRead));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
|
||||
const uint8_t* aData,
|
||||
uint32_t aDataLength,
|
||||
bool aEndOfStream)
|
||||
{
|
||||
// Check if decoder has already been created.
|
||||
if (mDecoder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString charset;
|
||||
|
||||
// Determine if BOM check should be done. This occurs either
|
||||
// if end-of-stream has been reached, or at least 3 bytes have
|
||||
// been read from input.
|
||||
if (!aEndOfStream && (aDataLength < 3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do BOM detection.
|
||||
if (DetectByteOrderMark(aData, aDataLength, charset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// BOM detection failed, check content stream for charset.
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
|
||||
NS_ASSERTION(req, "StreamLoader's request went away prematurely");
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
|
||||
|
||||
if (channel &&
|
||||
NS_SUCCEEDED(channel->GetContentCharset(charset)) &&
|
||||
EncodingUtils::FindEncodingForLabel(charset, charset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the hint charset from the script element or preload
|
||||
// request.
|
||||
nsAutoString hintCharset;
|
||||
if (!mRequest->IsPreload()) {
|
||||
mRequest->mElement->GetScriptCharset(hintCharset);
|
||||
} else {
|
||||
nsTArray<nsScriptLoader::PreloadInfo>::index_type i =
|
||||
mScriptLoader->mPreloads.IndexOf(mRequest, 0,
|
||||
nsScriptLoader::PreloadRequestComparator());
|
||||
|
||||
NS_ASSERTION(i != mScriptLoader->mPreloads.NoIndex,
|
||||
"Incorrect preload bookkeeping");
|
||||
hintCharset = mScriptLoader->mPreloads[i].mCharset;
|
||||
}
|
||||
|
||||
if (EncodingUtils::FindEncodingForLabel(hintCharset, charset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the charset from the charset of the document.
|
||||
if (mScriptLoader->mDocument) {
|
||||
charset = mScriptLoader->mDocument->GetDocumentCharacterSet();
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Curiously, there are various callers that don't pass aDocument. The
|
||||
// fallback in the old code was ISO-8859-1, which behaved like
|
||||
// windows-1252. Saying windows-1252 for clarity and for compliance
|
||||
// with the Encoding Standard.
|
||||
charset = "windows-1252";
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString)
|
||||
uint32_t aDataLength,
|
||||
const uint8_t* aData)
|
||||
{
|
||||
// pass arguments through except for the aContext,
|
||||
// we have to mediate and use mRequest instead.
|
||||
return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus,
|
||||
aStringLen, aString);
|
||||
if (!mRequest->IsCanceled()) {
|
||||
DebugOnly<bool> encoderSet =
|
||||
EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
|
||||
MOZ_ASSERT(encoderSet);
|
||||
DebugOnly<nsresult> rv = TryDecodeRawData(aData, aDataLength,
|
||||
/* aEndOfStream = */ true);
|
||||
|
||||
// If SRI is required for this load, appending new bytes to the hash.
|
||||
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
|
||||
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
|
||||
}
|
||||
}
|
||||
|
||||
// we have to mediate and use mRequest.
|
||||
return mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus,
|
||||
mBuffer, mSRIDataVerifier);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define __nsScriptLoader_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
@@ -20,8 +21,10 @@
|
||||
#include "nsIIncrementalStreamLoader.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/dom/SRIMetadata.h"
|
||||
#include "mozilla/dom/SRICheck.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
class nsScriptLoadRequestList;
|
||||
class nsIURI;
|
||||
@@ -217,6 +220,7 @@ class nsScriptLoader final : public nsISupports
|
||||
};
|
||||
|
||||
friend class nsScriptRequestProcessor;
|
||||
friend class nsScriptLoadHandler;
|
||||
friend class AutoCurrentScriptUpdater;
|
||||
|
||||
public:
|
||||
@@ -348,9 +352,10 @@ public:
|
||||
*/
|
||||
nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString);
|
||||
nsresult aChannelStatus,
|
||||
nsresult aSRIStatus,
|
||||
mozilla::Vector<char16_t> &aString,
|
||||
mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier);
|
||||
|
||||
/**
|
||||
* Processes any pending requests that are ready for processing.
|
||||
@@ -501,8 +506,7 @@ private:
|
||||
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
||||
nsIIncrementalStreamLoader* aLoader,
|
||||
nsresult aStatus,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString);
|
||||
mozilla::Vector<char16_t> &aString);
|
||||
|
||||
void AddDeferRequest(nsScriptLoadRequest* aRequest);
|
||||
bool MaybeRemovedDeferRequests();
|
||||
@@ -552,7 +556,8 @@ class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
|
||||
{
|
||||
public:
|
||||
explicit nsScriptLoadHandler(nsScriptLoader* aScriptLoader,
|
||||
nsScriptLoadRequest *aRequest);
|
||||
nsScriptLoadRequest *aRequest,
|
||||
mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
|
||||
@@ -560,8 +565,38 @@ public:
|
||||
private:
|
||||
virtual ~nsScriptLoadHandler();
|
||||
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
RefPtr<nsScriptLoadRequest> mRequest;
|
||||
/*
|
||||
* Try to decode some raw data.
|
||||
*/
|
||||
nsresult TryDecodeRawData(const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
|
||||
/*
|
||||
* Discover the charset by looking at the stream data, the script
|
||||
* tag, and other indicators. Returns true if charset has been
|
||||
* discovered.
|
||||
*/
|
||||
bool EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
|
||||
const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
|
||||
// ScriptLoader which will handle the parsed script.
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
|
||||
// The nsScriptLoadRequest for this load.
|
||||
RefPtr<nsScriptLoadRequest> mRequest;
|
||||
|
||||
// SRI data verifier.
|
||||
nsAutoPtr<mozilla::dom::SRICheckDataVerifier> mSRIDataVerifier;
|
||||
|
||||
// Status of SRI data operations.
|
||||
nsresult mSRIStatus;
|
||||
|
||||
// Unicode decoder for charset.
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
|
||||
// Accumulated decoded char buffer.
|
||||
mozilla::Vector<char16_t> mBuffer;
|
||||
};
|
||||
|
||||
class nsAutoScriptLoaderDisabler
|
||||
|
||||
@@ -862,12 +862,12 @@ CheckDBusReply(DBusMessage* aMsg, void* aServiceClass, bool aConnect)
|
||||
nsAutoString replyError;
|
||||
UnpackVoidMessage(aMsg, nullptr, v, replyError);
|
||||
|
||||
nsAutoPtr<BluetoothServiceClass> serviceClass(
|
||||
static_cast<BluetoothServiceClass*>(aServiceClass));
|
||||
BluetoothServiceClass serviceClass =
|
||||
static_cast<BluetoothServiceClass>(NS_PTR_TO_INT32(aServiceClass));
|
||||
|
||||
if (!replyError.IsEmpty()) {
|
||||
NS_DispatchToMainThread(
|
||||
new ReplyErrorToProfileManager(*serviceClass, aConnect, replyError));
|
||||
new ReplyErrorToProfileManager(serviceClass, aConnect, replyError));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2592,7 +2592,7 @@ class SendAsyncDBusMessageTask : public Task
|
||||
{
|
||||
public:
|
||||
SendAsyncDBusMessageTask(DBusReplyCallback aCallback,
|
||||
BluetoothServiceClass* aServiceClass,
|
||||
BluetoothServiceClass aServiceClass,
|
||||
const nsACString& aObjectPath,
|
||||
const char* aInterface,
|
||||
const nsACString& aMessage)
|
||||
@@ -2602,7 +2602,6 @@ public:
|
||||
, mInterface(aInterface)
|
||||
, mMessage(aMessage)
|
||||
{
|
||||
MOZ_ASSERT(mServiceClass);
|
||||
MOZ_ASSERT(!mObjectPath.IsEmpty());
|
||||
MOZ_ASSERT(!mInterface.IsEmpty());
|
||||
MOZ_ASSERT(!mMessage.IsEmpty());
|
||||
@@ -2613,18 +2612,18 @@ public:
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
|
||||
MOZ_ASSERT(sDBusConnection);
|
||||
|
||||
static_assert(sizeof(BluetoothServiceClass) <= sizeof(intptr_t),
|
||||
"BluetoothServiceClass cannot be passed via intptr_t");
|
||||
bool success = sDBusConnection->SendWithReply(
|
||||
mCallback, static_cast<void*>(mServiceClass), -1,
|
||||
mCallback, NS_INT32_TO_PTR(mServiceClass), -1,
|
||||
BLUEZ_DBUS_BASE_IFC, mObjectPath.get(), mInterface.get(),
|
||||
mMessage.get(), DBUS_TYPE_INVALID);
|
||||
NS_ENSURE_TRUE_VOID(success);
|
||||
|
||||
mServiceClass.forget();
|
||||
}
|
||||
|
||||
private:
|
||||
DBusReplyCallback mCallback;
|
||||
nsAutoPtr<BluetoothServiceClass> mServiceClass;
|
||||
BluetoothServiceClass mServiceClass;
|
||||
const nsCString mObjectPath;
|
||||
const nsCString mInterface;
|
||||
const nsCString mMessage;
|
||||
@@ -2642,18 +2641,18 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
|
||||
MOZ_ASSERT(!aObjectPath.IsEmpty());
|
||||
MOZ_ASSERT(aInterface);
|
||||
|
||||
nsAutoPtr<BluetoothServiceClass> serviceClass(new BluetoothServiceClass());
|
||||
BluetoothServiceClass serviceClass;
|
||||
if (!strcmp(aInterface, DBUS_SINK_IFACE)) {
|
||||
*serviceClass = BluetoothServiceClass::A2DP;
|
||||
serviceClass = BluetoothServiceClass::A2DP;
|
||||
} else if (!strcmp(aInterface, DBUS_INPUT_IFACE)) {
|
||||
*serviceClass = BluetoothServiceClass::HID;
|
||||
serviceClass = BluetoothServiceClass::HID;
|
||||
} else {
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Task* task = new SendAsyncDBusMessageTask(aCallback,
|
||||
serviceClass.forget(),
|
||||
serviceClass,
|
||||
NS_ConvertUTF16toUTF8(aObjectPath),
|
||||
aInterface,
|
||||
NS_ConvertUTF16toUTF8(aMessage));
|
||||
|
||||
@@ -3059,8 +3059,6 @@ UpgradeKeyFunction::OnFunctionCall(mozIStorageValueArray* aValues,
|
||||
|
||||
nsCOMPtr<nsIVariant> result = new mozilla::storage::AdoptedBlobVariant(data);
|
||||
|
||||
upgradedBlobData.release();
|
||||
|
||||
result.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -4010,12 +4008,10 @@ UpgradeIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aArguments
|
||||
uint32_t newIdvLength;
|
||||
rv = MakeCompressedIndexDataValues(oldIdv, newIdv, &newIdvLength);
|
||||
|
||||
std::pair<uint8_t*, int> data(newIdv.get(), newIdvLength);
|
||||
std::pair<uint8_t*, int> data(newIdv.release(), newIdvLength);
|
||||
|
||||
nsCOMPtr<nsIVariant> result = new storage::AdoptedBlobVariant(data);
|
||||
|
||||
newIdv.release();
|
||||
|
||||
result.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -19051,13 +19047,11 @@ DatabaseOperationBase::UpdateIndexValues(
|
||||
|
||||
if (indexDataValues) {
|
||||
rv = updateStmt->BindAdoptedBlobByName(indexDataValuesString,
|
||||
indexDataValues.get(),
|
||||
indexDataValues.release(),
|
||||
indexDataValuesLength);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
indexDataValues.release();
|
||||
} else {
|
||||
rv = updateStmt->BindNullByName(indexDataValuesString);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@@ -23812,13 +23806,11 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
|
||||
return rv;
|
||||
}
|
||||
|
||||
std::pair<uint8_t *, int> copiedBlobDataPair(indexValuesBlob.get(),
|
||||
std::pair<uint8_t *, int> copiedBlobDataPair(indexValuesBlob.release(),
|
||||
indexValuesBlobLength);
|
||||
|
||||
value = new storage::AdoptedBlobVariant(copiedBlobDataPair);
|
||||
|
||||
indexValuesBlob.release();
|
||||
|
||||
value.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -24764,12 +24756,9 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
||||
uint8_t* dataBuffer = reinterpret_cast<uint8_t*>(compressed);
|
||||
size_t dataBufferLength = compressedLength;
|
||||
|
||||
// If this call succeeds, | compressed | is now owned by the statement, and
|
||||
// we are no longer responsible for it.
|
||||
rv = stmt->BindAdoptedBlobByName(NS_LITERAL_CSTRING("data"), dataBuffer,
|
||||
dataBufferLength);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
free(compressed);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
+170
-128
@@ -11,7 +11,6 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIScriptError.h"
|
||||
@@ -97,65 +96,6 @@ IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
|
||||
return NS_ERROR_SRI_NOT_ELIGIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the hash of a sub-resource and compare it with the expected
|
||||
* value.
|
||||
*/
|
||||
static nsresult
|
||||
VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex,
|
||||
uint32_t aStringLen, const uint8_t* aString,
|
||||
const nsIDocument* aDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aString);
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
|
||||
nsAutoCString base64Hash;
|
||||
aMetadata.GetHash(aHashIndex, &base64Hash);
|
||||
SRILOG(("SRICheck::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get()));
|
||||
|
||||
nsAutoCString binaryHash;
|
||||
if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"InvalidIntegrityBase64");
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
uint32_t hashLength;
|
||||
int8_t hashType;
|
||||
aMetadata.GetHashType(&hashType, &hashLength);
|
||||
if (binaryHash.Length() != hashLength) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"InvalidIntegrityLength");
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICryptoHash> cryptoHash =
|
||||
do_CreateInstance("@mozilla.org/security/hash;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cryptoHash->Init(hashType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cryptoHash->Update(aString, aStringLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString computedHash;
|
||||
rv = cryptoHash->Finish(false, computedHash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!binaryHash.Equals(computedHash)) {
|
||||
SRILOG(("SRICheck::VerifyHash, hash[%u] did not match", aHashIndex));
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
SRILOG(("SRICheck::VerifyHash, hash[%u] verified successfully", aHashIndex));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
|
||||
const nsIDocument* aDocument,
|
||||
@@ -239,52 +179,6 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
VerifyIntegrityInternal(const SRIMetadata& aMetadata,
|
||||
nsIChannel* aChannel,
|
||||
const CORSMode aCORSMode,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString,
|
||||
const nsIDocument* aDocument)
|
||||
{
|
||||
MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
|
||||
|
||||
// IntegrityMetadata() checks this and returns "no metadata" if
|
||||
// it's disabled so we should never make it this far
|
||||
MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
|
||||
|
||||
if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) {
|
||||
return NS_ERROR_SRI_NOT_ELIGIBLE;
|
||||
}
|
||||
if (!aMetadata.IsValid()) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"NoValidMetadata");
|
||||
return NS_OK; // ignore invalid metadata for forward-compatibility
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aMetadata.HashCount(); i++) {
|
||||
if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aStringLen,
|
||||
aString, aDocument))) {
|
||||
return NS_OK; // stop at the first valid hash
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString alg;
|
||||
aMetadata.GetAlgorithm(&alg);
|
||||
NS_ConvertUTF8toUTF16 algUTF16(alg);
|
||||
const char16_t* params[] = { algUTF16.get() };
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"IntegrityMismatch",
|
||||
params, ArrayLength(params));
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
nsIUnicharStreamLoader* aLoader,
|
||||
@@ -306,40 +200,188 @@ SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
originalURI) {
|
||||
originalURI->GetAsciiSpec(requestURL);
|
||||
}
|
||||
SRILOG(("SRICheck::VerifyIntegrity (unichar stream), url=%s (length=%u)",
|
||||
requestURL.get(), utf8Hash.Length()));
|
||||
SRILOG(("SRICheck::VerifyIntegrity (unichar stream)"));
|
||||
}
|
||||
|
||||
return VerifyIntegrityInternal(aMetadata, channel, aCORSMode,
|
||||
utf8Hash.Length(), (uint8_t*)utf8Hash.get(),
|
||||
aDocument);
|
||||
SRICheckDataVerifier verifier(aMetadata, aDocument);
|
||||
nsresult rv;
|
||||
rv = verifier.Update(utf8Hash.Length(), (uint8_t*)utf8Hash.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return verifier.Verify(aMetadata, channel, aCORSMode, aDocument);
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
nsIIncrementalStreamLoader* aLoader,
|
||||
const CORSMode aCORSMode,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString,
|
||||
const nsIDocument* aDocument)
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
|
||||
const nsIDocument* aDocument)
|
||||
: mCryptoHash(nullptr),
|
||||
mBytesHashed(0),
|
||||
mInvalidMetadata(false),
|
||||
mComplete(false)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoader);
|
||||
MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
|
||||
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
aLoader->GetRequest(getter_AddRefs(request));
|
||||
NS_ENSURE_ARG_POINTER(request);
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
channel = do_QueryInterface(request);
|
||||
// IntegrityMetadata() checks this and returns "no metadata" if
|
||||
// it's disabled so we should never make it this far
|
||||
MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
|
||||
|
||||
if (!aMetadata.IsValid()) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"NoValidMetadata");
|
||||
mInvalidMetadata = true;
|
||||
return; // ignore invalid metadata for forward-compatibility
|
||||
}
|
||||
|
||||
uint32_t hashLength;
|
||||
aMetadata.GetHashType(&mHashType, &hashLength);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SRICheckDataVerifier::EnsureCryptoHash()
|
||||
{
|
||||
MOZ_ASSERT(!mInvalidMetadata);
|
||||
|
||||
if (mCryptoHash) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICryptoHash> cryptoHash =
|
||||
do_CreateInstance("@mozilla.org/security/hash;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cryptoHash->Init(mHashType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCryptoHash = cryptoHash;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SRICheckDataVerifier::Update(uint32_t aStringLen, const uint8_t* aString)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aString);
|
||||
if (mInvalidMetadata) {
|
||||
return NS_OK; // ignoring any data updates, see mInvalidMetadata usage
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
rv = EnsureCryptoHash();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mBytesHashed += aStringLen;
|
||||
|
||||
return mCryptoHash->Update(aString, aStringLen);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SRICheckDataVerifier::Finish()
|
||||
{
|
||||
if (mInvalidMetadata || mComplete) {
|
||||
return NS_OK; // already finished or invalid metadata
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
rv = EnsureCryptoHash(); // we need computed hash even for 0-length data
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mCryptoHash->Finish(false, mComputedHash);
|
||||
mCryptoHash = nullptr;
|
||||
mComplete = true;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
|
||||
uint32_t aHashIndex,
|
||||
const nsIDocument* aDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
|
||||
nsAutoCString base64Hash;
|
||||
aMetadata.GetHash(aHashIndex, &base64Hash);
|
||||
SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get()));
|
||||
|
||||
nsAutoCString binaryHash;
|
||||
if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"InvalidIntegrityBase64");
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
uint32_t hashLength;
|
||||
int8_t hashType;
|
||||
aMetadata.GetHashType(&hashType, &hashLength);
|
||||
if (binaryHash.Length() != hashLength) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"InvalidIntegrityLength");
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
if (!binaryHash.Equals(mComputedHash)) {
|
||||
SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] did not match", aHashIndex));
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] verified successfully", aHashIndex));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
|
||||
nsIChannel* aChannel,
|
||||
const CORSMode aCORSMode,
|
||||
const nsIDocument* aDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
|
||||
if (MOZ_LOG_TEST(GetSriLog(), mozilla::LogLevel::Debug)) {
|
||||
nsAutoCString requestURL;
|
||||
nsCOMPtr<nsIRequest> request;
|
||||
request = do_QueryInterface(aChannel);
|
||||
request->GetName(requestURL);
|
||||
SRILOG(("SRICheck::VerifyIntegrity (stream), url=%s (length=%u)",
|
||||
requestURL.get(), aStringLen));
|
||||
SRILOG(("SRICheckDataVerifier::Verify, url=%s (length=%lu)",
|
||||
requestURL.get(), mBytesHashed));
|
||||
}
|
||||
|
||||
return VerifyIntegrityInternal(aMetadata, channel, aCORSMode,
|
||||
aStringLen, aString, aDocument);
|
||||
nsresult rv = Finish();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) {
|
||||
return NS_ERROR_SRI_NOT_ELIGIBLE;
|
||||
}
|
||||
|
||||
if (mInvalidMetadata) {
|
||||
return NS_OK; // ignore invalid metadata for forward-compatibility
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aMetadata.HashCount(); i++) {
|
||||
if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aDocument))) {
|
||||
return NS_OK; // stop at the first valid hash
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString alg;
|
||||
aMetadata.GetAlgorithm(&alg);
|
||||
NS_ConvertUTF8toUTF16 algUTF16(alg);
|
||||
const char16_t* params[] = { algUTF16.get() };
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
|
||||
NS_LITERAL_CSTRING("Sub-resource Integrity"),
|
||||
aDocument,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"IntegrityMismatch",
|
||||
params, ArrayLength(params));
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
+25
-11
@@ -9,10 +9,11 @@
|
||||
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "SRIMetadata.h"
|
||||
|
||||
class nsIChannel;
|
||||
class nsIDocument;
|
||||
class nsIIncrementalStreamLoader;
|
||||
class nsIUnicharStreamLoader;
|
||||
|
||||
namespace mozilla {
|
||||
@@ -41,17 +42,30 @@ public:
|
||||
const CORSMode aCORSMode,
|
||||
const nsAString& aString,
|
||||
const nsIDocument* aDocument);
|
||||
};
|
||||
|
||||
/**
|
||||
* Process the integrity attribute of the element. A result of false
|
||||
* must prevent the resource from loading.
|
||||
*/
|
||||
static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
|
||||
nsIIncrementalStreamLoader* aLoader,
|
||||
const CORSMode aCORSMode,
|
||||
uint32_t aStringLen,
|
||||
const uint8_t* aString,
|
||||
const nsIDocument* aDocument);
|
||||
class SRICheckDataVerifier final
|
||||
{
|
||||
public:
|
||||
SRICheckDataVerifier(const SRIMetadata& aMetadata,
|
||||
const nsIDocument* aDocument);
|
||||
|
||||
nsresult Update(uint32_t aStringLen, const uint8_t* aString);
|
||||
nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel,
|
||||
const CORSMode aCORSMode, const nsIDocument* aDocument);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsICryptoHash> mCryptoHash;
|
||||
nsAutoCString mComputedHash;
|
||||
size_t mBytesHashed;
|
||||
int8_t mHashType;
|
||||
bool mInvalidMetadata;
|
||||
bool mComplete;
|
||||
|
||||
nsresult EnsureCryptoHash();
|
||||
nsresult Finish();
|
||||
nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex,
|
||||
const nsIDocument* aDocument);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -51,7 +51,6 @@ struct PrintData {
|
||||
bool showPrintProgress;
|
||||
|
||||
nsString paperName;
|
||||
short paperSizeType;
|
||||
short paperData;
|
||||
double paperWidth;
|
||||
double paperHeight;
|
||||
@@ -75,6 +74,8 @@ struct PrintData {
|
||||
/* Windows-specific things */
|
||||
nsString driverName;
|
||||
nsString deviceName;
|
||||
double printableWidthInInches;
|
||||
double printableHeightInInches;
|
||||
bool isFramesetDocument;
|
||||
bool isFramesetFrameSelected;
|
||||
bool isIFrameSelected;
|
||||
|
||||
@@ -74,224 +74,6 @@ static bool gDialogWasExtended = false;
|
||||
|
||||
static HWND gParentWnd = nullptr;
|
||||
|
||||
//******************************************************
|
||||
// Define native paper sizes
|
||||
//******************************************************
|
||||
typedef struct {
|
||||
short mPaperSize; // native enum
|
||||
double mWidth;
|
||||
double mHeight;
|
||||
bool mIsInches;
|
||||
} NativePaperSizes;
|
||||
|
||||
// There are around 40 default print sizes defined by Windows
|
||||
const NativePaperSizes kPaperSizes[] = {
|
||||
{DMPAPER_LETTER, 8.5, 11.0, true},
|
||||
{DMPAPER_LEGAL, 8.5, 14.0, true},
|
||||
{DMPAPER_A4, 210.0, 297.0, false},
|
||||
{DMPAPER_TABLOID, 11.0, 17.0, true},
|
||||
{DMPAPER_LEDGER, 17.0, 11.0, true},
|
||||
{DMPAPER_STATEMENT, 5.5, 8.5, true},
|
||||
{DMPAPER_EXECUTIVE, 7.25, 10.5, true},
|
||||
{DMPAPER_A3, 297.0, 420.0, false},
|
||||
{DMPAPER_A5, 148.0, 210.0, false},
|
||||
{DMPAPER_CSHEET, 17.0, 22.0, true},
|
||||
{DMPAPER_DSHEET, 22.0, 34.0, true},
|
||||
{DMPAPER_ESHEET, 34.0, 44.0, true},
|
||||
{DMPAPER_LETTERSMALL, 8.5, 11.0, true},
|
||||
{DMPAPER_A4SMALL, 210.0, 297.0, false},
|
||||
{DMPAPER_B4, 250.0, 354.0, false},
|
||||
{DMPAPER_B5, 182.0, 257.0, false},
|
||||
{DMPAPER_FOLIO, 8.5, 13.0, true},
|
||||
{DMPAPER_QUARTO, 215.0, 275.0, false},
|
||||
{DMPAPER_10X14, 10.0, 14.0, true},
|
||||
{DMPAPER_11X17, 11.0, 17.0, true},
|
||||
{DMPAPER_NOTE, 8.5, 11.0, true},
|
||||
{DMPAPER_ENV_9, 3.875, 8.875, true},
|
||||
{DMPAPER_ENV_10, 40.125, 9.5, true},
|
||||
{DMPAPER_ENV_11, 4.5, 10.375, true},
|
||||
{DMPAPER_ENV_12, 4.75, 11.0, true},
|
||||
{DMPAPER_ENV_14, 5.0, 11.5, true},
|
||||
{DMPAPER_ENV_DL, 110.0, 220.0, false},
|
||||
{DMPAPER_ENV_C5, 162.0, 229.0, false},
|
||||
{DMPAPER_ENV_C3, 324.0, 458.0, false},
|
||||
{DMPAPER_ENV_C4, 229.0, 324.0, false},
|
||||
{DMPAPER_ENV_C6, 114.0, 162.0, false},
|
||||
{DMPAPER_ENV_C65, 114.0, 229.0, false},
|
||||
{DMPAPER_ENV_B4, 250.0, 353.0, false},
|
||||
{DMPAPER_ENV_B5, 176.0, 250.0, false},
|
||||
{DMPAPER_ENV_B6, 176.0, 125.0, false},
|
||||
{DMPAPER_ENV_ITALY, 110.0, 230.0, false},
|
||||
{DMPAPER_ENV_MONARCH, 3.875, 7.5, true},
|
||||
{DMPAPER_ENV_PERSONAL, 3.625, 6.5, true},
|
||||
{DMPAPER_FANFOLD_US, 14.875, 11.0, true},
|
||||
{DMPAPER_FANFOLD_STD_GERMAN, 8.5, 12.0, true},
|
||||
{DMPAPER_FANFOLD_LGL_GERMAN, 8.5, 13.0, true},
|
||||
};
|
||||
const int32_t kNumPaperSizes = 41;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Map an incoming size to a Windows Native enum in the DevMode
|
||||
static void
|
||||
MapPaperSizeToNativeEnum(LPDEVMODEW aDevMode,
|
||||
int16_t aType,
|
||||
double aW,
|
||||
double aH)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_rods
|
||||
BOOL doingOrientation = aDevMode->dmFields & DM_ORIENTATION;
|
||||
BOOL doingPaperSize = aDevMode->dmFields & DM_PAPERSIZE;
|
||||
BOOL doingPaperLength = aDevMode->dmFields & DM_PAPERLENGTH;
|
||||
BOOL doingPaperWidth = aDevMode->dmFields & DM_PAPERWIDTH;
|
||||
#endif
|
||||
|
||||
const double kThreshold = 0.05;
|
||||
for (int32_t i=0;i<kNumPaperSizes;i++) {
|
||||
double width = kPaperSizes[i].mWidth;
|
||||
double height = kPaperSizes[i].mHeight;
|
||||
if (aW < width+kThreshold && aW > width-kThreshold &&
|
||||
aH < height+kThreshold && aH > height-kThreshold) {
|
||||
aDevMode->dmPaperSize = kPaperSizes[i].mPaperSize;
|
||||
aDevMode->dmFields &= ~DM_PAPERLENGTH;
|
||||
aDevMode->dmFields &= ~DM_PAPERWIDTH;
|
||||
aDevMode->dmFields |= DM_PAPERSIZE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
short width = 0;
|
||||
short height = 0;
|
||||
if (aType == nsIPrintSettings::kPaperSizeInches) {
|
||||
width = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aW))) / 10);
|
||||
height = short(NS_TWIPS_TO_MILLIMETERS(NS_INCHES_TO_TWIPS(float(aH))) / 10);
|
||||
|
||||
} else if (aType == nsIPrintSettings::kPaperSizeMillimeters) {
|
||||
width = short(aW / 10.0);
|
||||
height = short(aH / 10.0);
|
||||
} else {
|
||||
return; // don't set anything
|
||||
}
|
||||
|
||||
// width and height is in
|
||||
aDevMode->dmPaperSize = 0;
|
||||
aDevMode->dmPaperWidth = width;
|
||||
aDevMode->dmPaperLength = height;
|
||||
|
||||
aDevMode->dmFields |= DM_PAPERSIZE;
|
||||
aDevMode->dmFields |= DM_PAPERLENGTH;
|
||||
aDevMode->dmFields |= DM_PAPERWIDTH;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Setup Paper Size & Orientation options into the DevMode
|
||||
//
|
||||
static void
|
||||
SetupDevModeFromSettings(LPDEVMODEW aDevMode, nsIPrintSettings* aPrintSettings)
|
||||
{
|
||||
// Setup paper size
|
||||
if (aPrintSettings) {
|
||||
int16_t type;
|
||||
aPrintSettings->GetPaperSizeType(&type);
|
||||
if (type == nsIPrintSettings::kPaperSizeNativeData) {
|
||||
int16_t paperEnum;
|
||||
aPrintSettings->GetPaperData(&paperEnum);
|
||||
aDevMode->dmPaperSize = paperEnum;
|
||||
aDevMode->dmFields &= ~DM_PAPERLENGTH;
|
||||
aDevMode->dmFields &= ~DM_PAPERWIDTH;
|
||||
aDevMode->dmFields |= DM_PAPERSIZE;
|
||||
} else {
|
||||
int16_t unit;
|
||||
double width, height;
|
||||
aPrintSettings->GetPaperSizeUnit(&unit);
|
||||
aPrintSettings->GetPaperWidth(&width);
|
||||
aPrintSettings->GetPaperHeight(&height);
|
||||
MapPaperSizeToNativeEnum(aDevMode, unit, width, height);
|
||||
}
|
||||
|
||||
// Setup Orientation
|
||||
int32_t orientation;
|
||||
aPrintSettings->GetOrientation(&orientation);
|
||||
aDevMode->dmOrientation = orientation == nsIPrintSettings::kPortraitOrientation?DMORIENT_PORTRAIT:DMORIENT_LANDSCAPE;
|
||||
aDevMode->dmFields |= DM_ORIENTATION;
|
||||
|
||||
// Setup Number of Copies
|
||||
int32_t copies;
|
||||
aPrintSettings->GetNumCopies(&copies);
|
||||
aDevMode->dmCopies = copies;
|
||||
aDevMode->dmFields |= DM_COPIES;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Helper Function - Free and reallocate the string
|
||||
static nsresult
|
||||
SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings,
|
||||
LPDEVMODEW aDevMode)
|
||||
{
|
||||
if (aPrintSettings == nullptr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aPrintSettings->SetIsInitializedFromPrinter(true);
|
||||
if (aDevMode->dmFields & DM_ORIENTATION) {
|
||||
int32_t orientation = aDevMode->dmOrientation == DMORIENT_PORTRAIT?
|
||||
nsIPrintSettings::kPortraitOrientation:nsIPrintSettings::kLandscapeOrientation;
|
||||
aPrintSettings->SetOrientation(orientation);
|
||||
}
|
||||
|
||||
// Setup Number of Copies
|
||||
if (aDevMode->dmFields & DM_COPIES) {
|
||||
aPrintSettings->SetNumCopies(int32_t(aDevMode->dmCopies));
|
||||
}
|
||||
|
||||
// Scaling
|
||||
// Since we do the scaling, grab their value and reset back to 100
|
||||
if (aDevMode->dmFields & DM_SCALE) {
|
||||
double origScale = 1.0;
|
||||
aPrintSettings->GetScaling(&origScale);
|
||||
double scale = double(aDevMode->dmScale) / 100.0f;
|
||||
if (origScale == 1.0 || scale != 1.0) {
|
||||
aPrintSettings->SetScaling(scale);
|
||||
}
|
||||
aDevMode->dmScale = 100;
|
||||
// To turn this on you must change where the mPrt->mShrinkToFit is being set in the DocumentViewer
|
||||
//aPrintSettings->SetShrinkToFit(false);
|
||||
}
|
||||
|
||||
if (aDevMode->dmFields & DM_PAPERSIZE) {
|
||||
aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeNativeData);
|
||||
aPrintSettings->SetPaperData(aDevMode->dmPaperSize);
|
||||
for (int32_t i=0;i<kNumPaperSizes;i++) {
|
||||
if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) {
|
||||
aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches?nsIPrintSettings::kPaperSizeInches:nsIPrintSettings::kPaperSizeMillimeters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (aDevMode->dmFields & DM_PAPERLENGTH && aDevMode->dmFields & DM_PAPERWIDTH) {
|
||||
bool found = false;
|
||||
for (int32_t i=0;i<kNumPaperSizes;i++) {
|
||||
if (kPaperSizes[i].mPaperSize == aDevMode->dmPaperSize) {
|
||||
aPrintSettings->SetPaperSizeType(nsIPrintSettings::kPaperSizeDefined);
|
||||
aPrintSettings->SetPaperWidth(kPaperSizes[i].mWidth);
|
||||
aPrintSettings->SetPaperHeight(kPaperSizes[i].mHeight);
|
||||
aPrintSettings->SetPaperSizeUnit(kPaperSizes[i].mIsInches?nsIPrintSettings::kPaperSizeInches:nsIPrintSettings::kPaperSizeMillimeters);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Return localized bundle for resource strings
|
||||
static nsresult
|
||||
@@ -724,7 +506,9 @@ HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSett
|
||||
if (devMode) {
|
||||
memcpy(devMode, pNewDevMode, dwNeeded);
|
||||
// Initialize values from the PrintSettings
|
||||
SetupDevModeFromSettings(devMode, aPS);
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
|
||||
MOZ_ASSERT(psWin);
|
||||
psWin->CopyToNative(devMode);
|
||||
|
||||
// Sets back the changes we made to the DevMode into the Printer Driver
|
||||
dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
@@ -987,13 +771,14 @@ ShowNativePrintDialog(HWND aHWnd,
|
||||
|
||||
// Transfer the settings from the native data to the PrintSettings
|
||||
LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
|
||||
if (devMode == nullptr) {
|
||||
if (!devMode || !prntdlg.hDC) {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
psWin->SetDevMode(devMode); // copies DevMode
|
||||
SetPrintSettingsFromDevMode(aPrintSettings, devMode);
|
||||
psWin->CopyFromNative(prntdlg.hDC, devMode);
|
||||
::GlobalUnlock(prntdlg.hDevMode);
|
||||
::DeleteDC(prntdlg.hDC);
|
||||
|
||||
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
|
||||
bool printSelection = prntdlg.Flags & PD_SELECTION;
|
||||
|
||||
+35
-1
@@ -746,7 +746,8 @@ public:
|
||||
* Release takes the original data pointer for safety.
|
||||
*/
|
||||
virtual bool LockBits(uint8_t** aData, IntSize* aSize,
|
||||
int32_t* aStride, SurfaceFormat* aFormat) { return false; }
|
||||
int32_t* aStride, SurfaceFormat* aFormat,
|
||||
IntPoint* aOrigin = nullptr) { return false; }
|
||||
virtual void ReleaseBits(uint8_t* aData) {}
|
||||
|
||||
/** Ensure that the DrawTarget backend has flushed all drawing operations to
|
||||
@@ -967,6 +968,35 @@ public:
|
||||
*/
|
||||
virtual void PopClip() = 0;
|
||||
|
||||
/**
|
||||
* Push a 'layer' to the DrawTarget, a layer is a temporary surface that all
|
||||
* drawing will be redirected to, this is used for example to support group
|
||||
* opacity or the masking of groups. Clips must be balanced within a layer,
|
||||
* i.e. between a matching PushLayer/PopLayer pair there must be as many
|
||||
* PushClip(Rect) calls as there are PopClip calls.
|
||||
*
|
||||
* @param aOpaque Whether the layer will be opaque
|
||||
* @param aOpacity Opacity of the layer
|
||||
* @param aMask Mask applied to the layer
|
||||
* @param aMaskTransform Transform applied to the layer mask
|
||||
* @param aBounds Optional bounds in device space to which the layer is
|
||||
* limited in size.
|
||||
* @param aCopyBackground Whether to copy the background into the layer, this
|
||||
* is only supported when aOpaque is true.
|
||||
*/
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) { MOZ_CRASH(); }
|
||||
|
||||
/**
|
||||
* This balances a call to PushLayer and proceeds to blend the layer back
|
||||
* onto the background. This blend will blend the temporary surface back
|
||||
* onto the target in device space using POINT sampling and operator over.
|
||||
*/
|
||||
virtual void PopLayer() { MOZ_CRASH(); }
|
||||
|
||||
/**
|
||||
* Create a SourceSurface optimized for use with this DrawTarget from
|
||||
* existing bitmap data in memory.
|
||||
@@ -1113,6 +1143,10 @@ public:
|
||||
return mOpaqueRect;
|
||||
}
|
||||
|
||||
virtual bool IsCurrentGroupOpaque() {
|
||||
return GetFormat() == SurfaceFormat::B8G8R8X8;
|
||||
}
|
||||
|
||||
virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) {
|
||||
mPermitSubpixelAA = aPermitSubpixelAA;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ public:
|
||||
Drawable GetDrawable() const { return mDrawable; }
|
||||
Screen *GetScreen() const { return mScreen; }
|
||||
Visual *GetVisual() const { return mVisual; }
|
||||
IntSize GetSize() const { return mSize; }
|
||||
Point GetOffset() const { return mOffset; }
|
||||
|
||||
XRenderPictFormat* GetXRenderFormat() const { return mXRenderFormat; }
|
||||
|
||||
@@ -134,6 +136,8 @@ private:
|
||||
Screen *mScreen;
|
||||
Visual *mVisual;
|
||||
XRenderPictFormat *mXRenderFormat;
|
||||
IntSize mSize;
|
||||
Point mOffset;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+126
-11
@@ -714,17 +714,32 @@ DrawTargetCairo::Snapshot()
|
||||
|
||||
bool
|
||||
DrawTargetCairo::LockBits(uint8_t** aData, IntSize* aSize,
|
||||
int32_t* aStride, SurfaceFormat* aFormat)
|
||||
int32_t* aStride, SurfaceFormat* aFormat,
|
||||
IntPoint* aOrigin)
|
||||
{
|
||||
if (cairo_surface_get_type(mSurface) == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
cairo_surface_t* surf = cairo_get_group_target(mContext);
|
||||
if (cairo_surface_get_type(surf) == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
PointDouble offset;
|
||||
cairo_surface_get_device_offset(surf, &offset.x, &offset.y);
|
||||
// verify the device offset can be converted to integers suitable for a bounds rect
|
||||
IntPoint origin(int32_t(-offset.x), int32_t(-offset.y));
|
||||
if (-PointDouble(origin) != offset ||
|
||||
(!aOrigin && origin != IntPoint())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WillChange();
|
||||
Flush();
|
||||
|
||||
mLockedBits = cairo_image_surface_get_data(mSurface);
|
||||
mLockedBits = cairo_image_surface_get_data(surf);
|
||||
*aData = mLockedBits;
|
||||
*aSize = GetSize();
|
||||
*aStride = cairo_image_surface_get_stride(mSurface);
|
||||
*aFormat = GetFormat();
|
||||
*aSize = IntSize(cairo_image_surface_get_width(surf),
|
||||
cairo_image_surface_get_height(surf));
|
||||
*aStride = cairo_image_surface_get_stride(surf);
|
||||
*aFormat = CairoFormatToGfxFormat(cairo_image_surface_get_format(surf));
|
||||
if (aOrigin) {
|
||||
*aOrigin = origin;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -736,13 +751,14 @@ DrawTargetCairo::ReleaseBits(uint8_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(mLockedBits == aData);
|
||||
mLockedBits = nullptr;
|
||||
cairo_surface_mark_dirty(mSurface);
|
||||
cairo_surface_t* surf = cairo_get_group_target(mContext);
|
||||
cairo_surface_mark_dirty(surf);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::Flush()
|
||||
{
|
||||
cairo_surface_t* surf = cairo_get_target(mContext);
|
||||
cairo_surface_t* surf = cairo_get_group_target(mContext);
|
||||
cairo_surface_flush(surf);
|
||||
}
|
||||
|
||||
@@ -1234,6 +1250,18 @@ DrawTargetCairo::Fill(const Path *aPath,
|
||||
DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
|
||||
}
|
||||
|
||||
bool
|
||||
DrawTargetCairo::IsCurrentGroupOpaque()
|
||||
{
|
||||
cairo_surface_t* surf = cairo_get_group_target(mContext);
|
||||
|
||||
if (!surf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return cairo_surface_get_content(surf) == CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::SetPermitSubpixelAA(bool aPermitSubpixelAA)
|
||||
{
|
||||
@@ -1455,6 +1483,87 @@ DrawTargetCairo::PopClip()
|
||||
|
||||
cairo_set_matrix(mContext, &mat);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
cairo_content_t content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||
|
||||
if (mFormat == SurfaceFormat::A8) {
|
||||
content = CAIRO_CONTENT_ALPHA;
|
||||
} else if (aOpaque) {
|
||||
content = CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
|
||||
if (aCopyBackground) {
|
||||
cairo_surface_t* source = cairo_get_group_target(mContext);
|
||||
cairo_push_group_with_content(mContext, content);
|
||||
cairo_surface_t* dest = cairo_get_group_target(mContext);
|
||||
cairo_t* ctx = cairo_create(dest);
|
||||
cairo_set_source_surface(ctx, source, 0, 0);
|
||||
cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
} else {
|
||||
cairo_push_group_with_content(mContext, content);
|
||||
}
|
||||
|
||||
PushedLayer layer(aOpacity, mPermitSubpixelAA);
|
||||
|
||||
if (aMask) {
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aMask);
|
||||
if (surf) {
|
||||
layer.mMaskPattern = cairo_pattern_create_for_surface(surf);
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(aMaskTransform, mat);
|
||||
cairo_matrix_invert(&mat);
|
||||
cairo_pattern_set_matrix(layer.mMaskPattern, &mat);
|
||||
cairo_surface_destroy(surf);
|
||||
} else {
|
||||
gfxCriticalError() << "Failed to get cairo surface for mask surface!";
|
||||
}
|
||||
}
|
||||
|
||||
mPushedLayers.push_back(layer);
|
||||
|
||||
SetPermitSubpixelAA(aOpaque);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PopLayer()
|
||||
{
|
||||
MOZ_ASSERT(mPushedLayers.size());
|
||||
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
|
||||
cairo_pop_group_to_source(mContext);
|
||||
|
||||
PushedLayer layer = mPushedLayers.back();
|
||||
mPushedLayers.pop_back();
|
||||
|
||||
if (!layer.mMaskPattern) {
|
||||
cairo_paint_with_alpha(mContext, layer.mOpacity);
|
||||
} else {
|
||||
if (layer.mOpacity != Float(1.0)) {
|
||||
cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
// Now draw the content using the desired operator
|
||||
cairo_paint_with_alpha(mContext, layer.mOpacity);
|
||||
|
||||
cairo_pop_group_to_source(mContext);
|
||||
}
|
||||
cairo_mask(mContext, layer.mMaskPattern);
|
||||
}
|
||||
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(mTransform, mat);
|
||||
cairo_set_matrix(mContext, &mat);
|
||||
|
||||
cairo_pattern_destroy(layer.mMaskPattern);
|
||||
SetPermitSubpixelAA(layer.mWasPermittingSubpixelAA);
|
||||
}
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FillRule::FILL_WINDING */) const
|
||||
@@ -1765,7 +1874,7 @@ void *
|
||||
DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
|
||||
{
|
||||
if (aType == NativeSurfaceType::CAIRO_SURFACE) {
|
||||
return cairo_get_target(mContext);
|
||||
return cairo_get_group_target(mContext);
|
||||
}
|
||||
if (aType == NativeSurfaceType::CAIRO_CONTEXT) {
|
||||
return mContext;
|
||||
@@ -1868,7 +1977,7 @@ BorrowedXlibDrawable::Init(DrawTarget* aDT)
|
||||
}
|
||||
|
||||
DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
|
||||
cairo_surface_t* surf = cairoDT->mSurface;
|
||||
cairo_surface_t* surf = cairo_get_group_target(cairoDT->mContext);
|
||||
if (cairo_surface_get_type(surf) != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
return false;
|
||||
}
|
||||
@@ -1881,6 +1990,12 @@ BorrowedXlibDrawable::Init(DrawTarget* aDT)
|
||||
mScreen = cairo_xlib_surface_get_screen(surf);
|
||||
mVisual = cairo_xlib_surface_get_visual(surf);
|
||||
mXRenderFormat = cairo_xlib_surface_get_xrender_format(surf);
|
||||
mSize.width = cairo_xlib_surface_get_width(surf);
|
||||
mSize.height = cairo_xlib_surface_get_height(surf);
|
||||
|
||||
double x = 0, y = 0;
|
||||
cairo_surface_get_device_offset(surf, &x, &y);
|
||||
mOffset = Point(x, y);
|
||||
|
||||
return true;
|
||||
#else
|
||||
@@ -1892,7 +2007,7 @@ void
|
||||
BorrowedXlibDrawable::Finish()
|
||||
{
|
||||
DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(mDT);
|
||||
cairo_surface_t* surf = cairoDT->mSurface;
|
||||
cairo_surface_t* surf = cairo_get_group_target(cairoDT->mContext);
|
||||
cairo_surface_mark_dirty(surf);
|
||||
if (mDrawable) {
|
||||
mDrawable = None;
|
||||
|
||||
@@ -65,10 +65,13 @@ public:
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
virtual IntSize GetSize() override;
|
||||
|
||||
virtual bool IsCurrentGroupOpaque() override;
|
||||
|
||||
virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) override;
|
||||
|
||||
virtual bool LockBits(uint8_t** aData, IntSize* aSize,
|
||||
int32_t* aStride, SurfaceFormat* aFormat) override;
|
||||
int32_t* aStride, SurfaceFormat* aFormat,
|
||||
IntPoint* aOrigin = nullptr) override;
|
||||
virtual void ReleaseBits(uint8_t* aData) override;
|
||||
|
||||
virtual void Flush() override;
|
||||
@@ -134,6 +137,12 @@ public:
|
||||
virtual void PushClip(const Path *aPath) override;
|
||||
virtual void PushClipRect(const Rect &aRect) override;
|
||||
virtual void PopClip() override;
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PopLayer() override;
|
||||
|
||||
virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
|
||||
|
||||
@@ -214,6 +223,19 @@ private: // data
|
||||
|
||||
uint8_t* mLockedBits;
|
||||
|
||||
struct PushedLayer
|
||||
{
|
||||
PushedLayer(Float aOpacity, bool aWasPermittingSubpixelAA)
|
||||
: mOpacity(aOpacity)
|
||||
, mMaskPattern(nullptr)
|
||||
, mWasPermittingSubpixelAA(aWasPermittingSubpixelAA)
|
||||
{}
|
||||
Float mOpacity;
|
||||
cairo_pattern_t* mMaskPattern;
|
||||
bool mWasPermittingSubpixelAA;
|
||||
};
|
||||
std::vector<PushedLayer> mPushedLayers;
|
||||
|
||||
// The latest snapshot of this surface. This needs to be told when this
|
||||
// target is modified. We keep it alive as a cache.
|
||||
RefPtr<SourceSurfaceCairo> mSnapshot;
|
||||
|
||||
+159
-72
@@ -31,7 +31,7 @@ ID2D1Factory1 *D2DFactory1()
|
||||
}
|
||||
|
||||
DrawTargetD2D1::DrawTargetD2D1()
|
||||
: mClipsArePushed(false)
|
||||
: mPushedLayers(1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ DrawTargetD2D1::ClearRect(const Rect &aRect)
|
||||
mDC->FillGeometry(geom, brush);
|
||||
mDC->PopAxisAlignedClip();
|
||||
|
||||
mDC->SetTarget(mBitmap);
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
list->Close();
|
||||
|
||||
mDC->DrawImage(list, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_DESTINATION_OUT);
|
||||
@@ -515,7 +515,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
||||
PrepareForDrawing(aOptions.mCompositionOp, aPattern);
|
||||
|
||||
bool forceClearType = false;
|
||||
if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
|
||||
if (!CurrentLayer().mIsOpaque && mPermitSubpixelAA &&
|
||||
aOptions.mCompositionOp == CompositionOp::OP_OVER && aaMode == AntialiasMode::SUBPIXEL) {
|
||||
forceClearType = true;
|
||||
}
|
||||
@@ -538,7 +538,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
||||
}
|
||||
|
||||
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
|
||||
mFormat != SurfaceFormat::B8G8R8X8 && !forceClearType) {
|
||||
!CurrentLayer().mIsOpaque && !forceClearType) {
|
||||
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
}
|
||||
|
||||
@@ -555,10 +555,10 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
||||
DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
|
||||
|
||||
bool needsRepushedLayers = false;
|
||||
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && mFormat != SurfaceFormat::B8G8R8X8) {
|
||||
if (forceClearType) {
|
||||
D2D1_RECT_F rect;
|
||||
bool isAligned;
|
||||
needsRepushedLayers = mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||
needsRepushedLayers = CurrentLayer().mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||
|
||||
// If we have a complex clip in our stack and we have a transparent
|
||||
// background, and subpixel AA is permitted, we need to repush our layer
|
||||
@@ -587,11 +587,7 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
|
||||
D2DFactory()->CreatePathGeometry(getter_AddRefs(path));
|
||||
RefPtr<ID2D1GeometrySink> sink;
|
||||
path->Open(getter_AddRefs(sink));
|
||||
sink->BeginFigure(D2D1::Point2F(userRect.left, userRect.top), D2D1_FIGURE_BEGIN_FILLED);
|
||||
sink->AddLine(D2D1::Point2F(userRect.right, userRect.top));
|
||||
sink->AddLine(D2D1::Point2F(userRect.right, userRect.bottom));
|
||||
sink->AddLine(D2D1::Point2F(userRect.left, userRect.bottom));
|
||||
sink->EndFigure(D2D1_FIGURE_END_CLOSED);
|
||||
AddRectToSink(sink, userRect);
|
||||
sink->Close();
|
||||
|
||||
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), path, D2D1_ANTIALIAS_MODE_ALIASED,
|
||||
@@ -664,14 +660,14 @@ DrawTargetD2D1::PushClip(const Path *aPath)
|
||||
|
||||
pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
|
||||
|
||||
mPushedClips.push_back(clip);
|
||||
CurrentLayer().mPushedClips.push_back(clip);
|
||||
|
||||
// The transform of clips is relative to the world matrix, since we use the total
|
||||
// transform for the clips, make the world matrix identity.
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
if (mClipsArePushed) {
|
||||
if (CurrentLayer().mClipsArePushed) {
|
||||
PushD2DLayer(mDC, pathD2D->mGeometry, clip.mTransform);
|
||||
}
|
||||
}
|
||||
@@ -704,12 +700,12 @@ DrawTargetD2D1::PushClipRect(const Rect &aRect)
|
||||
// Do not store the transform, just store the device space rectangle directly.
|
||||
clip.mBounds = D2DRect(rect);
|
||||
|
||||
mPushedClips.push_back(clip);
|
||||
CurrentLayer().mPushedClips.push_back(clip);
|
||||
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
if (mClipsArePushed) {
|
||||
if (CurrentLayer().mClipsArePushed) {
|
||||
mDC->PushAxisAlignedClip(clip.mBounds, clip.mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
||||
}
|
||||
}
|
||||
@@ -719,14 +715,95 @@ DrawTargetD2D1::PopClip()
|
||||
{
|
||||
mCurrentClippedGeometry = nullptr;
|
||||
|
||||
if (mClipsArePushed) {
|
||||
if (mPushedClips.back().mPath) {
|
||||
if (CurrentLayer().mClipsArePushed) {
|
||||
if (CurrentLayer().mPushedClips.back().mPath) {
|
||||
mDC->PopLayer();
|
||||
} else {
|
||||
mDC->PopAxisAlignedClip();
|
||||
}
|
||||
}
|
||||
mPushedClips.pop_back();
|
||||
CurrentLayer().mPushedClips.pop_back();
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D1::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
D2D1_LAYER_OPTIONS1 options = D2D1_LAYER_OPTIONS1_NONE;
|
||||
|
||||
if (aOpaque) {
|
||||
options |= D2D1_LAYER_OPTIONS1_IGNORE_ALPHA;
|
||||
}
|
||||
if (aCopyBackground) {
|
||||
options |= D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
|
||||
}
|
||||
|
||||
RefPtr<ID2D1BitmapBrush> mask;
|
||||
|
||||
Matrix maskTransform = aMaskTransform;
|
||||
|
||||
RefPtr<ID2D1PathGeometry> clip;
|
||||
if (aMask) {
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
RefPtr<ID2D1Image> image = GetImageForSurface(aMask, maskTransform, ExtendMode::CLAMP);
|
||||
|
||||
// The mask is given in user space. Our layer will apply it in device space.
|
||||
maskTransform = maskTransform * mTransform;
|
||||
|
||||
if (image) {
|
||||
RefPtr<ID2D1Bitmap> bitmap;
|
||||
image->QueryInterface((ID2D1Bitmap**)getter_AddRefs(bitmap));
|
||||
|
||||
mDC->CreateBitmapBrush(bitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(1.0f, D2DMatrix(maskTransform)), getter_AddRefs(mask));
|
||||
MOZ_ASSERT(bitmap); // This should always be true since it was created for a surface.
|
||||
|
||||
factory()->CreatePathGeometry(getter_AddRefs(clip));
|
||||
RefPtr<ID2D1GeometrySink> sink;
|
||||
clip->Open(getter_AddRefs(sink));
|
||||
AddRectToSink(sink, D2D1::RectF(0, 0, aMask->GetSize().width, aMask->GetSize().height));
|
||||
sink->Close();
|
||||
} else {
|
||||
gfxCriticalError() << "Failed to get image for mask surface!";
|
||||
}
|
||||
}
|
||||
|
||||
PushAllClips();
|
||||
|
||||
mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), clip, D2D1_ANTIALIAS_MODE_ALIASED, D2DMatrix(maskTransform), aOpacity, mask, options), nullptr);
|
||||
PushedLayer pushedLayer;
|
||||
pushedLayer.mClipsArePushed = false;
|
||||
pushedLayer.mIsOpaque = aOpaque;
|
||||
pushedLayer.mOldPermitSubpixelAA = mPermitSubpixelAA;
|
||||
mPermitSubpixelAA = aOpaque;
|
||||
|
||||
mDC->CreateCommandList(getter_AddRefs(pushedLayer.mCurrentList));
|
||||
mPushedLayers.push_back(pushedLayer);
|
||||
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D1::PopLayer()
|
||||
{
|
||||
MOZ_ASSERT(CurrentLayer().mPushedClips.size() == 0);
|
||||
|
||||
RefPtr<ID2D1CommandList> list = CurrentLayer().mCurrentList;
|
||||
mPermitSubpixelAA = CurrentLayer().mOldPermitSubpixelAA;
|
||||
|
||||
mPushedLayers.pop_back();
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
|
||||
list->Close();
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
DCCommandSink sink(mDC);
|
||||
list->Stream(&sink);
|
||||
|
||||
mDC->PopLayer();
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
@@ -878,10 +955,12 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
|
||||
return false;
|
||||
}
|
||||
|
||||
mDC->SetTarget(mBitmap);
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
|
||||
mDC->BeginDraw();
|
||||
|
||||
CurrentLayer().mIsOpaque = aFormat == SurfaceFormat::B8G8R8X8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -922,7 +1001,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
|
||||
return false;
|
||||
}
|
||||
|
||||
mDC->SetTarget(mBitmap);
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
|
||||
hr = mDC->CreateSolidColorBrush(D2D1::ColorF(0, 0), getter_AddRefs(mSolidColorBrush));
|
||||
|
||||
@@ -933,6 +1012,8 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
|
||||
|
||||
mDC->BeginDraw();
|
||||
|
||||
CurrentLayer().mIsOpaque = aFormat == SurfaceFormat::B8G8R8X8;
|
||||
|
||||
mDC->Clear();
|
||||
|
||||
mFormat = aFormat;
|
||||
@@ -1048,7 +1129,7 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
|
||||
|
||||
PopAllClips();
|
||||
|
||||
mDC->SetTarget(mBitmap);
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
mCommandList->Close();
|
||||
|
||||
RefPtr<ID2D1CommandList> source = mCommandList;
|
||||
@@ -1061,31 +1142,23 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
|
||||
if (D2DSupportsCompositeMode(aOp)) {
|
||||
D2D1_RECT_F rect;
|
||||
bool isAligned;
|
||||
RefPtr<ID2D1Bitmap> tmpBitmap;
|
||||
bool clipIsComplex = mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||
RefPtr<ID2D1Image> tmpImage;
|
||||
bool clipIsComplex = CurrentLayer().mPushedClips.size() && !GetDeviceSpaceClipRect(rect, isAligned);
|
||||
|
||||
if (clipIsComplex) {
|
||||
if (!IsOperatorBoundByMask(aOp)) {
|
||||
HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 6CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
|
||||
// For now, crash in this scenario; this should happen because tmpBitmap is
|
||||
// null and CopyFromBitmap call below dereferences it.
|
||||
// return;
|
||||
}
|
||||
mDC->Flush();
|
||||
|
||||
tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
|
||||
tmpImage = GetImageForLayerContent();
|
||||
}
|
||||
} else {
|
||||
PushAllClips();
|
||||
}
|
||||
mDC->DrawImage(source, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2DCompositionMode(aOp));
|
||||
|
||||
if (tmpBitmap) {
|
||||
RefPtr<ID2D1BitmapBrush> brush;
|
||||
if (tmpImage) {
|
||||
RefPtr<ID2D1ImageBrush> brush;
|
||||
RefPtr<ID2D1Geometry> inverseGeom = GetInverseClippedGeometry();
|
||||
mDC->CreateBitmapBrush(tmpBitmap, getter_AddRefs(brush));
|
||||
mDC->CreateImageBrush(tmpImage, D2D1::ImageBrushProperties(D2D1::RectF(0, 0, mSize.width, mSize.height)),
|
||||
getter_AddRefs(brush));
|
||||
|
||||
mDC->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
|
||||
mDC->FillGeometry(inverseGeom, brush);
|
||||
@@ -1094,37 +1167,23 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mBlendEffect) {
|
||||
HRESULT hr = mDC->CreateEffect(CLSID_D2D1Blend, getter_AddRefs(mBlendEffect));
|
||||
RefPtr<ID2D1Effect> blendEffect;
|
||||
HRESULT hr = mDC->CreateEffect(CLSID_D2D1Blend, getter_AddRefs(blendEffect));
|
||||
|
||||
if (FAILED(hr) || !mBlendEffect) {
|
||||
gfxWarning() << "Failed to create blend effect!";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID2D1Bitmap> tmpBitmap;
|
||||
HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 5CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
|
||||
if (FAILED(hr) || !blendEffect) {
|
||||
gfxWarning() << "Failed to create blend effect!";
|
||||
return;
|
||||
}
|
||||
|
||||
// This flush is important since the copy method will not know about the context drawing to the surface.
|
||||
// We also need to pop all the clips to make sure any drawn content will have made it to the final bitmap.
|
||||
mDC->Flush();
|
||||
RefPtr<ID2D1Image> tmpImage = GetImageForLayerContent();
|
||||
|
||||
// We need to use a copy here because affects don't accept a surface on
|
||||
// both their in- and outputs.
|
||||
tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
|
||||
|
||||
mBlendEffect->SetInput(0, tmpBitmap);
|
||||
mBlendEffect->SetInput(1, source);
|
||||
mBlendEffect->SetValue(D2D1_BLEND_PROP_MODE, D2DBlendMode(aOp));
|
||||
blendEffect->SetInput(0, tmpImage);
|
||||
blendEffect->SetInput(1, source);
|
||||
blendEffect->SetValue(D2D1_BLEND_PROP_MODE, D2DBlendMode(aOp));
|
||||
|
||||
PushAllClips();
|
||||
|
||||
mDC->DrawImage(mBlendEffect, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
|
||||
mDC->DrawImage(blendEffect, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1184,12 +1243,12 @@ IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2)
|
||||
bool
|
||||
DrawTargetD2D1::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned)
|
||||
{
|
||||
if (!mPushedClips.size()) {
|
||||
if (!CurrentLayer().mPushedClips.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aClipRect = D2D1::RectF(0, 0, mSize.width, mSize.height);
|
||||
for (auto iter = mPushedClips.begin();iter != mPushedClips.end(); iter++) {
|
||||
for (auto iter = CurrentLayer().mPushedClips.begin();iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||
if (iter->mPath) {
|
||||
return false;
|
||||
}
|
||||
@@ -1201,6 +1260,35 @@ DrawTargetD2D1::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAli
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<ID2D1Image>
|
||||
DrawTargetD2D1::GetImageForLayerContent()
|
||||
{
|
||||
if (!CurrentLayer().mCurrentList) {
|
||||
RefPtr<ID2D1Bitmap> tmpBitmap;
|
||||
HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 6CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
|
||||
// For now, crash in this scenario; this should happen because tmpBitmap is
|
||||
// null and CopyFromBitmap call below dereferences it.
|
||||
// return;
|
||||
}
|
||||
mDC->Flush();
|
||||
|
||||
tmpBitmap->CopyFromBitmap(nullptr, mBitmap, nullptr);
|
||||
return tmpBitmap.forget();
|
||||
} else {
|
||||
RefPtr<ID2D1CommandList> list = CurrentLayer().mCurrentList;
|
||||
mDC->CreateCommandList(getter_AddRefs(CurrentLayer().mCurrentList));
|
||||
mDC->SetTarget(CurrentTarget());
|
||||
list->Close();
|
||||
|
||||
DCCommandSink sink(mDC);
|
||||
list->Stream(&sink);
|
||||
|
||||
return list.forget();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ID2D1Geometry>
|
||||
DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
||||
{
|
||||
@@ -1210,7 +1298,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
||||
return clippedGeometry.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPushedClips.size());
|
||||
MOZ_ASSERT(CurrentLayer().mPushedClips.size());
|
||||
|
||||
mCurrentClipBounds = IntRect(IntPoint(0, 0), mSize);
|
||||
|
||||
@@ -1218,7 +1306,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
||||
RefPtr<ID2D1Geometry> pathGeom;
|
||||
D2D1_RECT_F pathRect;
|
||||
bool pathRectIsAxisAligned = false;
|
||||
auto iter = mPushedClips.begin();
|
||||
auto iter = CurrentLayer().mPushedClips.begin();
|
||||
|
||||
if (iter->mPath) {
|
||||
pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform);
|
||||
@@ -1228,7 +1316,7 @@ DrawTargetD2D1::GetClippedGeometry(IntRect *aClipBounds)
|
||||
}
|
||||
|
||||
iter++;
|
||||
for (;iter != mPushedClips.end(); iter++) {
|
||||
for (;iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||
// Do nothing but add it to the current clip bounds.
|
||||
if (!iter->mPath && iter->mIsPixelAligned) {
|
||||
mCurrentClipBounds.IntersectRect(mCurrentClipBounds,
|
||||
@@ -1313,20 +1401,20 @@ DrawTargetD2D1::GetInverseClippedGeometry()
|
||||
void
|
||||
DrawTargetD2D1::PopAllClips()
|
||||
{
|
||||
if (mClipsArePushed) {
|
||||
if (CurrentLayer().mClipsArePushed) {
|
||||
PopClipsFromDC(mDC);
|
||||
|
||||
mClipsArePushed = false;
|
||||
CurrentLayer().mClipsArePushed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D1::PushAllClips()
|
||||
{
|
||||
if (!mClipsArePushed) {
|
||||
if (!CurrentLayer().mClipsArePushed) {
|
||||
PushClipsToDC(mDC);
|
||||
|
||||
mClipsArePushed = true;
|
||||
CurrentLayer().mClipsArePushed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1336,8 +1424,7 @@ DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha, c
|
||||
mDC->SetTransform(D2D1::IdentityMatrix());
|
||||
mTransformDirty = true;
|
||||
|
||||
for (std::vector<PushedClip>::iterator iter = mPushedClips.begin();
|
||||
iter != mPushedClips.end(); iter++) {
|
||||
for (auto iter = CurrentLayer().mPushedClips.begin(); iter != CurrentLayer().mPushedClips.end(); iter++) {
|
||||
if (iter->mPath) {
|
||||
PushD2DLayer(aDC, iter->mPath->mGeometry, iter->mTransform, aForceIgnoreAlpha, aMaxRect);
|
||||
} else {
|
||||
@@ -1349,8 +1436,8 @@ DrawTargetD2D1::PushClipsToDC(ID2D1DeviceContext *aDC, bool aForceIgnoreAlpha, c
|
||||
void
|
||||
DrawTargetD2D1::PopClipsFromDC(ID2D1DeviceContext *aDC)
|
||||
{
|
||||
for (int i = mPushedClips.size() - 1; i >= 0; i--) {
|
||||
if (mPushedClips[i].mPath) {
|
||||
for (int i = CurrentLayer().mPushedClips.size() - 1; i >= 0; i--) {
|
||||
if (CurrentLayer().mPushedClips[i].mPath) {
|
||||
aDC->PopLayer();
|
||||
} else {
|
||||
aDC->PopAxisAlignedClip();
|
||||
|
||||
+39
-5
@@ -94,6 +94,12 @@ public:
|
||||
virtual void PushClip(const Path *aPath) override;
|
||||
virtual void PushClipRect(const Rect &aRect) override;
|
||||
virtual void PopClip() override;
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PopLayer() override;
|
||||
|
||||
virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
@@ -117,6 +123,7 @@ public:
|
||||
virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
|
||||
|
||||
virtual bool SupportsRegionClipping() const override { return false; }
|
||||
virtual bool IsCurrentGroupOpaque() override { return CurrentLayer().mIsOpaque; }
|
||||
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType) override { return nullptr; }
|
||||
|
||||
@@ -167,14 +174,27 @@ private:
|
||||
}
|
||||
void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
|
||||
|
||||
// Must be called with all clips popped and an identity matrix set.
|
||||
already_AddRefed<ID2D1Image> GetImageForLayerContent();
|
||||
|
||||
ID2D1Image* CurrentTarget()
|
||||
{
|
||||
if (CurrentLayer().mCurrentList) {
|
||||
return CurrentLayer().mCurrentList;
|
||||
}
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
// This returns the clipped geometry, in addition it returns aClipBounds which
|
||||
// represents the intersection of all pixel-aligned rectangular clips that
|
||||
// are currently set. The returned clipped geometry must be clipped by these
|
||||
// bounds to correctly reflect the total clip. This is in device space.
|
||||
// bounds to correctly reflect the total clip. This is in device space and
|
||||
// only for clips applied to the -current layer-.
|
||||
already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
|
||||
|
||||
already_AddRefed<ID2D1Geometry> GetInverseClippedGeometry();
|
||||
|
||||
// This gives the device space clip rect applied to the -current layer-.
|
||||
bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
|
||||
|
||||
void PopAllClips();
|
||||
@@ -201,7 +221,6 @@ private:
|
||||
mutable RefPtr<ID2D1DeviceContext> mDC;
|
||||
RefPtr<ID2D1Bitmap1> mBitmap;
|
||||
RefPtr<ID2D1CommandList> mCommandList;
|
||||
RefPtr<ID2D1Effect> mBlendEffect;
|
||||
|
||||
RefPtr<ID2D1SolidColorBrush> mSolidColorBrush;
|
||||
|
||||
@@ -220,7 +239,24 @@ private:
|
||||
};
|
||||
RefPtr<PathD2D> mPath;
|
||||
};
|
||||
std::vector<PushedClip> mPushedClips;
|
||||
|
||||
// List of pushed layers.
|
||||
struct PushedLayer
|
||||
{
|
||||
PushedLayer() : mClipsArePushed(false), mIsOpaque(false), mOldPermitSubpixelAA(false) {}
|
||||
|
||||
std::vector<PushedClip> mPushedClips;
|
||||
RefPtr<ID2D1CommandList> mCurrentList;
|
||||
// True if the current clip stack is pushed to the CurrentTarget().
|
||||
bool mClipsArePushed;
|
||||
bool mIsOpaque;
|
||||
bool mOldPermitSubpixelAA;
|
||||
};
|
||||
std::vector<PushedLayer> mPushedLayers;
|
||||
PushedLayer& CurrentLayer()
|
||||
{
|
||||
return mPushedLayers.back();
|
||||
}
|
||||
|
||||
// The latest snapshot of this surface. This needs to be told when this
|
||||
// target is modified. We keep it alive as a cache.
|
||||
@@ -230,8 +266,6 @@ private:
|
||||
// A list of targets which have this object in their mDependentTargets set
|
||||
TargetSet mDependingOnTargets;
|
||||
|
||||
// True of the current clip stack is pushed to the main RT.
|
||||
bool mClipsArePushed;
|
||||
static ID2D1Factory1 *mFactory;
|
||||
static IDWriteFactory *mDWriteFactory;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,11 @@ class DualSurface
|
||||
public:
|
||||
inline explicit DualSurface(SourceSurface *aSurface)
|
||||
{
|
||||
if (!aSurface) {
|
||||
mA = mB = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() != SurfaceType::DUAL_DT) {
|
||||
mA = mB = aSurface;
|
||||
return;
|
||||
@@ -181,6 +186,16 @@ DrawTargetDual::Mask(const Pattern &aSource, const Pattern &aMask, const DrawOpt
|
||||
mB->Mask(*source.mB, *mask.mB, aOptions);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetDual::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
DualSurface mask(aMask);
|
||||
mA->PushLayer(aOpaque, aOpacity, mask.mA, aMaskTransform, aBounds, aCopyBackground);
|
||||
mB->PushLayer(aOpaque, aOpacity, mask.mB, aMaskTransform, aBounds, aCopyBackground);
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
DrawTargetDual::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
|
||||
{
|
||||
|
||||
+10
-1
@@ -54,6 +54,7 @@ public:
|
||||
FORWARD_FUNCTION1(PushClip, const Path *, aPath)
|
||||
FORWARD_FUNCTION1(PushClipRect, const Rect &, aRect)
|
||||
FORWARD_FUNCTION(PopClip)
|
||||
FORWARD_FUNCTION(PopLayer)
|
||||
FORWARD_FUNCTION1(ClearRect, const Rect &, aRect)
|
||||
|
||||
virtual void SetTransform(const Matrix &aTransform) override {
|
||||
@@ -104,7 +105,13 @@ public:
|
||||
const GlyphRenderingOptions *aRenderingOptions) override;
|
||||
|
||||
virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions) override;
|
||||
|
||||
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
|
||||
virtual already_AddRefed<SourceSurface>
|
||||
CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
@@ -155,6 +162,8 @@ public:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsCurrentGroupOpaque() override { return mA->IsCurrentGroupOpaque(); }
|
||||
|
||||
private:
|
||||
RefPtr<DrawTarget> mA;
|
||||
|
||||
@@ -558,6 +558,30 @@ DrawTargetRecording::PopClip()
|
||||
mFinalDT->PopClip();
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds, bool aCopyBackground)
|
||||
{
|
||||
if (aMask) {
|
||||
EnsureSurfaceStored(mRecorder, aMask, "PushLayer");
|
||||
}
|
||||
|
||||
mRecorder->RecordEvent(RecordedPushLayer(this, aOpacity, aOpacity, aMask,
|
||||
aMaskTransform, aBounds,
|
||||
aCopyBackground));
|
||||
mFinalDT->PushLayer(aOpacity, aOpacity, aMask, aMaskTransform, aBounds,
|
||||
aCopyBackground);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetRecording::PopLayer()
|
||||
{
|
||||
mRecorder->RecordEvent(RecordedPopLayer(this));
|
||||
mFinalDT->PopLayer();
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
|
||||
@@ -217,6 +217,35 @@ public:
|
||||
*/
|
||||
virtual void PopClip() override;
|
||||
|
||||
/**
|
||||
* Push a 'layer' to the DrawTarget, a layer is a temporary surface that all
|
||||
* drawing will be redirected to, this is used for example to support group
|
||||
* opacity or the masking of groups. Clips must be balanced within a layer,
|
||||
* i.e. between a matching PushLayer/PopLayer pair there must be as many
|
||||
* PushClip(Rect) calls as there are PopClip calls.
|
||||
*
|
||||
* @param aOpaque Whether the layer will be opaque
|
||||
* @param aOpacity Opacity of the layer
|
||||
* @param aMask Mask applied to the layer
|
||||
* @param aMaskTransform Transform applied to the layer mask
|
||||
* @param aBounds Optional bounds in device space to which the layer is
|
||||
* limited in size.
|
||||
* @param aCopyBackground Whether to copy the background into the layer, this
|
||||
* is only supported when aOpaque is true.
|
||||
*/
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
|
||||
/**
|
||||
* This balances a call to PushLayer and proceeds to blend the layer back
|
||||
* onto the background. This blend will blend the temporary surface back
|
||||
* onto the target in device space using POINT sampling and operator over.
|
||||
*/
|
||||
virtual void PopLayer() override;
|
||||
|
||||
/*
|
||||
* Create a SourceSurface optimized for use with this DrawTarget from
|
||||
* existing bitmap data in memory.
|
||||
@@ -286,6 +315,10 @@ public:
|
||||
*/
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType) override { return mFinalDT->GetNativeSurface(aType); }
|
||||
|
||||
virtual bool IsCurrentGroupOpaque() override {
|
||||
return mFinalDT->IsCurrentGroupOpaque();
|
||||
}
|
||||
|
||||
private:
|
||||
Path *GetPathForPathRecording(const Path *aPath) const;
|
||||
already_AddRefed<PathRecording> EnsurePathStored(const Path *aPath);
|
||||
|
||||
+206
-129
@@ -75,29 +75,32 @@ public:
|
||||
/**
|
||||
* When constructing a temporary SkBitmap via GetBitmapForSurface, we may also
|
||||
* have to construct a temporary DataSourceSurface, which must live as long as
|
||||
* the SkBitmap. So we return a pair of the SkBitmap and the (optional)
|
||||
* temporary surface.
|
||||
* the SkBitmap. We attach this temporary surface to the bitmap's pixelref, so
|
||||
* that it can be released once the pixelref is freed.
|
||||
*/
|
||||
struct TempBitmap
|
||||
static void
|
||||
ReleaseTemporarySurface(void* aPixels, void* aContext)
|
||||
{
|
||||
SkBitmap mBitmap;
|
||||
RefPtr<SourceSurface> mTmpSurface;
|
||||
};
|
||||
DataSourceSurface* surf = static_cast<DataSourceSurface*>(aContext);
|
||||
if (surf) {
|
||||
surf->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static TempBitmap
|
||||
static SkBitmap
|
||||
GetBitmapForSurface(SourceSurface* aSurface)
|
||||
{
|
||||
TempBitmap result;
|
||||
SkBitmap bitmap;
|
||||
|
||||
if (aSurface->GetType() == SurfaceType::SKIA) {
|
||||
result.mBitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
|
||||
return result;
|
||||
bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> surf = aSurface->GetDataSurface();
|
||||
DataSourceSurface* surf = aSurface->GetDataSurface().take();
|
||||
if (!surf) {
|
||||
gfxDevCrash(LogReason::SourceSurfaceIncompatible) << "Non-skia SourceSurfaces need to be DataSourceSurfaces";
|
||||
return result;
|
||||
gfxDevCrash(LogReason::SourceSurfaceIncompatible) << "Non-Skia SourceSurfaces need to be DataSourceSurfaces";
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
SkAlphaType alphaType = (surf->GetFormat() == SurfaceFormat::B8G8R8X8) ?
|
||||
@@ -107,11 +110,12 @@ GetBitmapForSurface(SourceSurface* aSurface)
|
||||
surf->GetSize().height,
|
||||
GfxFormatToSkiaColorType(surf->GetFormat()),
|
||||
alphaType);
|
||||
result.mBitmap.setInfo(info, surf->Stride());
|
||||
if (!bitmap.installPixels(info, surf->GetData(), surf->Stride(), nullptr,
|
||||
ReleaseTemporarySurface, surf)) {
|
||||
gfxDebug() << "Failed installing pixels on Skia bitmap for temporary surface";
|
||||
}
|
||||
|
||||
result.mBitmap.setPixels(surf->GetData());
|
||||
result.mTmpSurface = surf.forget();
|
||||
return result;
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
DrawTargetSkia::DrawTargetSkia()
|
||||
@@ -143,8 +147,15 @@ DrawTargetSkia::Snapshot()
|
||||
|
||||
bool
|
||||
DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
|
||||
int32_t* aStride, SurfaceFormat* aFormat)
|
||||
int32_t* aStride, SurfaceFormat* aFormat,
|
||||
IntPoint* aOrigin)
|
||||
{
|
||||
// Ensure the layer is at the origin if required.
|
||||
SkIPoint origin = mCanvas->getTopDevice()->getOrigin();
|
||||
if (!aOrigin && !origin.isZero()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Test if the canvas' device has accessible pixels first, as actually
|
||||
* accessing the pixels may trigger side-effects, even if it fails.
|
||||
*/
|
||||
@@ -165,6 +176,9 @@ DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
|
||||
*aSize = IntSize(info.width(), info.height());
|
||||
*aStride = int32_t(rowBytes);
|
||||
*aFormat = SkiaColorTypeToGfxFormat(info.colorType());
|
||||
if (aOrigin) {
|
||||
*aOrigin = IntPoint(origin.x(), origin.y());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -174,8 +188,7 @@ DrawTargetSkia::ReleaseBits(uint8_t* aData)
|
||||
}
|
||||
|
||||
static void
|
||||
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap,
|
||||
Float aAlpha = 1.0)
|
||||
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0)
|
||||
{
|
||||
switch (aPattern.GetType()) {
|
||||
case PatternType::COLOR: {
|
||||
@@ -193,22 +206,16 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap
|
||||
points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
|
||||
points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
|
||||
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
SkShader* shader = SkGradientShader::CreateLinear(points,
|
||||
&stops->mColors.front(),
|
||||
&stops->mPositions.front(),
|
||||
stops->mCount,
|
||||
mode);
|
||||
|
||||
if (shader) {
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
SkShader* matrixShader = SkShader::CreateLocalMatrixShader(shader, mat);
|
||||
SkSafeUnref(shader);
|
||||
SkSafeUnref(aPaint.setShader(matrixShader));
|
||||
}
|
||||
|
||||
mode, 0, &mat);
|
||||
SkSafeUnref(aPaint.setShader(shader));
|
||||
} else {
|
||||
aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
|
||||
aPaint.setColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -222,6 +229,8 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap
|
||||
points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
|
||||
points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
|
||||
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0],
|
||||
SkFloatToScalar(pat.mRadius1),
|
||||
points[1],
|
||||
@@ -229,24 +238,16 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap
|
||||
&stops->mColors.front(),
|
||||
&stops->mPositions.front(),
|
||||
stops->mCount,
|
||||
mode);
|
||||
if (shader) {
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
SkShader* matrixShader = SkShader::CreateLocalMatrixShader(shader, mat);
|
||||
SkSafeUnref(shader);
|
||||
SkSafeUnref(aPaint.setShader(matrixShader));
|
||||
}
|
||||
|
||||
mode, 0, &mat);
|
||||
SkSafeUnref(aPaint.setShader(shader));
|
||||
} else {
|
||||
aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
|
||||
aPaint.setColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
|
||||
aTmpBitmap = GetBitmapForSurface(pat.mSurface);
|
||||
SkBitmap& bitmap = aTmpBitmap.mBitmap;
|
||||
SkBitmap bitmap = GetBitmapForSurface(pat.mSurface);
|
||||
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
@@ -260,10 +261,8 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap
|
||||
SkShader::TileMode xTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::X_AXIS);
|
||||
SkShader::TileMode yTileMode = ExtendModeToTileMode(pat.mExtendMode, Axis::Y_AXIS);
|
||||
|
||||
SkShader* shader = SkShader::CreateBitmapShader(bitmap, xTileMode, yTileMode);
|
||||
SkShader* matrixShader = SkShader::CreateLocalMatrixShader(shader, mat);
|
||||
SkSafeUnref(shader);
|
||||
SkSafeUnref(aPaint.setShader(matrixShader));
|
||||
SkShader* shader = SkShader::CreateBitmapShader(bitmap, xTileMode, yTileMode, &mat);
|
||||
SkSafeUnref(aPaint.setShader(shader));
|
||||
if (pat.mFilter == Filter::POINT) {
|
||||
aPaint.setFilterQuality(kNone_SkFilterQuality);
|
||||
}
|
||||
@@ -285,7 +284,7 @@ struct AutoPaintSetup {
|
||||
: mNeedsRestore(false), mAlpha(1.0)
|
||||
{
|
||||
Init(aCanvas, aOptions, aMaskBounds);
|
||||
SetPaintPattern(mPaint, aPattern, mTmpBitmap, mAlpha);
|
||||
SetPaintPattern(mPaint, aPattern, mAlpha);
|
||||
}
|
||||
|
||||
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr)
|
||||
@@ -337,7 +336,6 @@ struct AutoPaintSetup {
|
||||
|
||||
// TODO: Maybe add an operator overload to access this easier?
|
||||
SkPaint mPaint;
|
||||
TempBitmap mTmpBitmap;
|
||||
bool mNeedsRestore;
|
||||
SkCanvas* mCanvas;
|
||||
Float mAlpha;
|
||||
@@ -376,14 +374,14 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
|
||||
SkRect destRect = RectToSkRect(aDest);
|
||||
SkRect sourceRect = RectToSkRect(aSource);
|
||||
|
||||
TempBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
SkBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
|
||||
if (aSurfOptions.mFilter == Filter::POINT) {
|
||||
paint.mPaint.setFilterQuality(kNone_SkFilterQuality);
|
||||
}
|
||||
|
||||
mCanvas->drawBitmapRect(bitmap.mBitmap, sourceRect, destRect, &paint.mPaint);
|
||||
mCanvas->drawBitmapRect(bitmap, sourceRect, destRect, &paint.mPaint);
|
||||
}
|
||||
|
||||
DrawTargetType
|
||||
@@ -424,7 +422,7 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
mCanvas->save();
|
||||
mCanvas->resetMatrix();
|
||||
|
||||
TempBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
SkBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(GfxOpToSkiaOp(aOperator));
|
||||
@@ -446,17 +444,12 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
shadowPaint.setImageFilter(blurFilter.get());
|
||||
shadowPaint.setColorFilter(colorFilter.get());
|
||||
|
||||
// drawBitmap implicitly calls saveLayer with a src-over xfer mode if given
|
||||
// an image filter, whereas the supplied xfer mode gets used to render into
|
||||
// the layer, which is the wrong order. We instead must use drawSprite which
|
||||
// applies the image filter directly to the bitmap without rendering it first,
|
||||
// then uses the xfer mode to composite it.
|
||||
IntPoint shadowDest = RoundedToInt(aDest + aOffset);
|
||||
mCanvas->drawSprite(bitmap.mBitmap, shadowDest.x, shadowDest.y, &shadowPaint);
|
||||
mCanvas->drawBitmap(bitmap, shadowDest.x, shadowDest.y, &shadowPaint);
|
||||
|
||||
// Composite the original image after the shadow
|
||||
IntPoint dest = RoundedToInt(aDest);
|
||||
mCanvas->drawSprite(bitmap.mBitmap, dest.x, dest.y, &paint);
|
||||
mCanvas->drawBitmap(bitmap, dest.x, dest.y, &paint);
|
||||
|
||||
mCanvas->restore();
|
||||
}
|
||||
@@ -636,15 +629,14 @@ DrawTargetSkia::Mask(const Pattern &aSource,
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
|
||||
|
||||
SkPaint maskPaint;
|
||||
TempBitmap tmpBitmap;
|
||||
SetPaintPattern(maskPaint, aMask, tmpBitmap);
|
||||
SetPaintPattern(maskPaint, aMask);
|
||||
|
||||
SkLayerRasterizer::Builder builder;
|
||||
builder.addLayer(maskPaint);
|
||||
SkAutoTUnref<SkRasterizer> raster(builder.detachRasterizer());
|
||||
paint.mPaint.setRasterizer(raster.get());
|
||||
|
||||
mCanvas->drawRect(SkRectCoveringWholeSurface(), paint.mPaint);
|
||||
mCanvas->drawPaint(paint.mPaint);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -656,32 +648,21 @@ DrawTargetSkia::MaskSurface(const Pattern &aSource,
|
||||
MarkChanged();
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
|
||||
|
||||
TempBitmap bitmap = GetBitmapForSurface(aMask);
|
||||
if (bitmap.mBitmap.colorType() == kAlpha_8_SkColorType) {
|
||||
if (aOffset != Point(0, 0)) {
|
||||
SkMatrix transform;
|
||||
transform.setTranslate(SkFloatToScalar(-aOffset.x), SkFloatToScalar(-aOffset.y));
|
||||
SkShader* matrixShader = SkShader::CreateLocalMatrixShader(paint.mPaint.getShader(), transform);
|
||||
SkSafeUnref(paint.mPaint.setShader(matrixShader));
|
||||
}
|
||||
|
||||
mCanvas->drawBitmap(bitmap.mBitmap, aOffset.x, aOffset.y, &paint.mPaint);
|
||||
} else {
|
||||
SkPaint maskPaint;
|
||||
TempBitmap tmpBitmap;
|
||||
SetPaintPattern(maskPaint,
|
||||
SurfacePattern(aMask, ExtendMode::CLAMP, Matrix::Translation(aOffset)),
|
||||
tmpBitmap);
|
||||
|
||||
SkLayerRasterizer::Builder builder;
|
||||
builder.addLayer(maskPaint);
|
||||
SkAutoTUnref<SkRasterizer> raster(builder.detachRasterizer());
|
||||
paint.mPaint.setRasterizer(raster.get());
|
||||
|
||||
IntSize size = aMask->GetSize();
|
||||
Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height);
|
||||
mCanvas->drawRect(RectToSkRect(rect), paint.mPaint);
|
||||
SkBitmap bitmap = GetBitmapForSurface(aMask);
|
||||
if (bitmap.colorType() != kAlpha_8_SkColorType &&
|
||||
!bitmap.extractAlpha(&bitmap)) {
|
||||
gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOffset != Point(0, 0)) {
|
||||
SkMatrix transform;
|
||||
transform.setTranslate(PointToSkPoint(-aOffset));
|
||||
SkShader* matrixShader = paint.mPaint.getShader()->newWithLocalMatrix(transform);
|
||||
SkSafeUnref(paint.mPaint.setShader(matrixShader));
|
||||
}
|
||||
|
||||
mCanvas->drawBitmap(bitmap, aOffset.x, aOffset.y, &paint.mPaint);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
@@ -782,54 +763,32 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
|
||||
const IntRect& aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{
|
||||
//TODO: We could just use writePixels() here if the sourceRect is the entire source
|
||||
|
||||
if (aSurface->GetType() != SurfaceType::SKIA && aSurface->GetType() != SurfaceType::DATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
MarkChanged();
|
||||
|
||||
TempBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
// This is a fast path that is disabled for now to mimimize risk
|
||||
if (false && !bitmap.mBitmap.getTexture() && mCanvas->imageInfo() == bitmap.mBitmap.info()) {
|
||||
SkBitmap bm(bitmap.mBitmap);
|
||||
bm.lockPixels();
|
||||
if (bm.getPixels()) {
|
||||
SkImageInfo info = bm.info().makeWH(aSourceRect.width, aSourceRect.height);
|
||||
uint8_t* pixels = static_cast<uint8_t*>(bm.getPixels());
|
||||
// adjust pixels for the source offset
|
||||
pixels += aSourceRect.x + aSourceRect.y*bm.rowBytes();
|
||||
mCanvas->writePixels(info, pixels, bm.rowBytes(), aDestination.x, aDestination.y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SkBitmap bitmap = GetBitmapForSurface(aSurface);
|
||||
|
||||
mCanvas->save();
|
||||
mCanvas->resetMatrix();
|
||||
SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height));
|
||||
SkIRect source = IntRectToSkIRect(aSourceRect);
|
||||
mCanvas->clipRect(dest, SkRegion::kReplace_Op);
|
||||
SkPaint paint;
|
||||
|
||||
if (mCanvas->imageInfo().colorType() == kRGB_565_SkColorType) {
|
||||
// Set the xfermode to SOURCE_OVER to workaround
|
||||
SkPaint paint;
|
||||
if (!bitmap.isOpaque()) {
|
||||
// Keep the xfermode as SOURCE_OVER for opaque bitmaps
|
||||
// http://code.google.com/p/skia/issues/detail?id=628
|
||||
// RGB565 is opaque so they're equivalent anyway
|
||||
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
||||
} else {
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
}
|
||||
// drawBitmapRect with A8 bitmaps ends up doing a mask operation
|
||||
// so we need to clear before
|
||||
if (bitmap.mBitmap.colorType() == kAlpha_8_SkColorType) {
|
||||
SkPaint clearPaint;
|
||||
clearPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
|
||||
clearPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
mCanvas->drawPaint(clearPaint);
|
||||
if (bitmap.colorType() == kAlpha_8_SkColorType) {
|
||||
mCanvas->clear(SK_ColorTRANSPARENT);
|
||||
}
|
||||
mCanvas->drawBitmapRect(bitmap.mBitmap, source, dest, &paint);
|
||||
mCanvas->drawBitmapRect(bitmap, source, dest, &paint);
|
||||
mCanvas->restore();
|
||||
}
|
||||
|
||||
@@ -856,7 +815,7 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
|
||||
return false;
|
||||
}
|
||||
|
||||
bitmap.eraseARGB(0, 0, 0, 0);
|
||||
bitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
|
||||
mCanvas.adopt(new SkCanvas(bitmap));
|
||||
mSize = aSize;
|
||||
@@ -964,12 +923,9 @@ void
|
||||
DrawTargetSkia::ClearRect(const Rect &aRect)
|
||||
{
|
||||
MarkChanged();
|
||||
SkPaint paint;
|
||||
mCanvas->save();
|
||||
mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op, true);
|
||||
paint.setColor(SkColorSetARGB(0, 0, 0, 0));
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
mCanvas->drawPaint(paint);
|
||||
mCanvas->clear(SK_ColorTRANSPARENT);
|
||||
mCanvas->restore();
|
||||
}
|
||||
|
||||
@@ -1000,6 +956,135 @@ DrawTargetSkia::PopClip()
|
||||
mCanvas->restore();
|
||||
}
|
||||
|
||||
// Image filter that just passes the source through to the result unmodified.
|
||||
class CopyLayerImageFilter : public SkImageFilter
|
||||
{
|
||||
public:
|
||||
CopyLayerImageFilter()
|
||||
: SkImageFilter(0, nullptr)
|
||||
{}
|
||||
|
||||
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
|
||||
SkBitmap* result, SkIPoint* offset) const override {
|
||||
*result = src;
|
||||
offset->set(0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(CopyLayerImageFilter)
|
||||
};
|
||||
|
||||
SkFlattenable*
|
||||
CopyLayerImageFilter::CreateProc(SkReadBuffer& buffer)
|
||||
{
|
||||
SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
|
||||
return new CopyLayerImageFilter;
|
||||
}
|
||||
|
||||
#ifndef SK_IGNORE_TO_STRING
|
||||
void
|
||||
CopyLayerImageFilter::toString(SkString* str) const
|
||||
{
|
||||
str->append("CopyLayerImageFilter: ()");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
DrawTargetSkia::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
PushedLayer layer(GetPermitSubpixelAA(), aOpaque, aOpacity, aMask, aMaskTransform);
|
||||
mPushedLayers.push_back(layer);
|
||||
|
||||
SkPaint paint;
|
||||
|
||||
// If we have a mask, set the opacity to 0 so that SkCanvas::restore skips
|
||||
// implicitly drawing the layer so that we can properly mask it in PopLayer.
|
||||
paint.setAlpha(aMask ? 0 : ColorFloatToByte(aOpacity));
|
||||
|
||||
SkRect bounds = IntRectToSkRect(aBounds);
|
||||
|
||||
SkAutoTUnref<SkImageFilter> backdrop(aCopyBackground ? new CopyLayerImageFilter : nullptr);
|
||||
|
||||
SkCanvas::SaveLayerRec saveRec(aBounds.IsEmpty() ? nullptr : &bounds,
|
||||
&paint,
|
||||
backdrop.get(),
|
||||
aOpaque ? SkCanvas::kIsOpaque_SaveLayerFlag : 0);
|
||||
|
||||
mCanvas->saveLayer(saveRec);
|
||||
|
||||
SetPermitSubpixelAA(aOpaque);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::PopLayer()
|
||||
{
|
||||
MarkChanged();
|
||||
|
||||
MOZ_ASSERT(mPushedLayers.size());
|
||||
const PushedLayer& layer = mPushedLayers.back();
|
||||
|
||||
if (layer.mMask) {
|
||||
// If we have a mask, take a reference to the layer's bitmap device so that
|
||||
// we can mask it ourselves. This assumes we forced SkCanvas::restore to
|
||||
// skip implicitly drawing the layer.
|
||||
SkAutoTUnref<SkBaseDevice> layerDevice(SkSafeRef(mCanvas->getTopDevice()));
|
||||
SkIRect layerBounds = layerDevice->getGlobalBounds();
|
||||
SkBitmap layerBitmap = layerDevice->accessBitmap(false);
|
||||
|
||||
// Restore the background with the layer's device left alive.
|
||||
mCanvas->restore();
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAlpha(ColorFloatToByte(layer.mOpacity));
|
||||
|
||||
SkMatrix maskMat, layerMat;
|
||||
// Get the total transform affecting the mask, considering its pattern
|
||||
// transform and the current canvas transform.
|
||||
GfxMatrixToSkiaMatrix(layer.mMaskTransform, maskMat);
|
||||
maskMat.postConcat(mCanvas->getTotalMatrix());
|
||||
if (!maskMat.invert(&layerMat)) {
|
||||
gfxDebug() << *this << ": PopLayer() failed to invert mask transform";
|
||||
} else {
|
||||
// The layer should not be affected by the current canvas transform,
|
||||
// even though the mask is. So first we use the inverse of the transform
|
||||
// affecting the mask, then add back on the layer's origin.
|
||||
layerMat.preTranslate(layerBounds.x(), layerBounds.y());
|
||||
SkShader* shader = SkShader::CreateBitmapShader(layerBitmap,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode,
|
||||
&layerMat);
|
||||
SkSafeUnref(paint.setShader(shader));
|
||||
|
||||
SkBitmap mask = GetBitmapForSurface(layer.mMask);
|
||||
if (mask.colorType() != kAlpha_8_SkColorType &&
|
||||
!mask.extractAlpha(&mask)) {
|
||||
gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask";
|
||||
} else {
|
||||
mCanvas->save();
|
||||
|
||||
// The layer may be smaller than the canvas size, so make sure drawing is
|
||||
// clipped to within the bounds of the layer.
|
||||
mCanvas->resetMatrix();
|
||||
mCanvas->clipRect(SkRect::Make(layerBounds));
|
||||
|
||||
mCanvas->setMatrix(maskMat);
|
||||
mCanvas->drawBitmap(mask, 0, 0, &paint);
|
||||
|
||||
mCanvas->restore();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mCanvas->restore();
|
||||
}
|
||||
|
||||
SetPermitSubpixelAA(layer.mOldPermitSubpixelAA);
|
||||
|
||||
mPushedLayers.pop_back();
|
||||
}
|
||||
|
||||
already_AddRefed<GradientStops>
|
||||
DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
|
||||
{
|
||||
@@ -1028,14 +1113,6 @@ DrawTargetSkia::MarkChanged()
|
||||
}
|
||||
}
|
||||
|
||||
// Return a rect (in user space) that covers the entire surface by applying
|
||||
// the inverse of GetTransform() to (0, 0, mSize.width, mSize.height).
|
||||
SkRect
|
||||
DrawTargetSkia::SkRectCoveringWholeSurface() const
|
||||
{
|
||||
return RectToSkRect(mTransform.TransformBounds(Rect(0, 0, mSize.width, mSize.height)));
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::SnapshotDestroyed()
|
||||
{
|
||||
|
||||
+29
-3
@@ -37,7 +37,8 @@ public:
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
virtual IntSize GetSize() override { return mSize; }
|
||||
virtual bool LockBits(uint8_t** aData, IntSize* aSize,
|
||||
int32_t* aStride, SurfaceFormat* aFormat) override;
|
||||
int32_t* aStride, SurfaceFormat* aFormat,
|
||||
IntPoint* aOrigin = nullptr) override;
|
||||
virtual void ReleaseBits(uint8_t* aData) override;
|
||||
virtual void Flush() override;
|
||||
virtual void DrawSurface(SourceSurface *aSurface,
|
||||
@@ -93,6 +94,12 @@ public:
|
||||
virtual void PushClip(const Path *aPath) override;
|
||||
virtual void PushClipRect(const Rect& aRect) override;
|
||||
virtual void PopClip() override;
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PopLayer() override;
|
||||
virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
int32_t aStride,
|
||||
@@ -136,10 +143,29 @@ private:
|
||||
|
||||
bool ShouldLCDRenderText(FontType aFontType, AntialiasMode aAntialiasMode);
|
||||
|
||||
SkRect SkRectCoveringWholeSurface() const;
|
||||
|
||||
bool UsingSkiaGPU() const;
|
||||
|
||||
struct PushedLayer
|
||||
{
|
||||
PushedLayer(bool aOldPermitSubpixelAA,
|
||||
bool aOpaque,
|
||||
Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform)
|
||||
: mOldPermitSubpixelAA(aOldPermitSubpixelAA),
|
||||
mOpaque(aOpaque),
|
||||
mOpacity(aOpacity),
|
||||
mMask(aMask),
|
||||
mMaskTransform(aMaskTransform)
|
||||
{}
|
||||
bool mOldPermitSubpixelAA;
|
||||
bool mOpaque;
|
||||
Float mOpacity;
|
||||
RefPtr<SourceSurface> mMask;
|
||||
Matrix mMaskTransform;
|
||||
};
|
||||
std::vector<PushedLayer> mPushedLayers;
|
||||
|
||||
#ifdef USE_SKIA_GPU
|
||||
RefPtrSkia<GrContext> mGrContext;
|
||||
GrGLuint mTexture;
|
||||
|
||||
@@ -305,5 +305,29 @@ DrawTargetTiled::Fill(const Path* aPath, const Pattern& aPattern, const DrawOpti
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform, const IntRect& aBounds,
|
||||
bool aCopyBackground)
|
||||
{
|
||||
// XXX - not sure this is what we want or whether we want to continue drawing to a larger
|
||||
// intermediate surface, that would require tweaking the code in here a little though.
|
||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||
IntRect bounds = aBounds;
|
||||
bounds.MoveBy(-mTiles[i].mTileOrigin);
|
||||
mTiles[i].mDrawTarget->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, aBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::PopLayer()
|
||||
{
|
||||
// XXX - not sure this is what we want or whether we want to continue drawing to a larger
|
||||
// intermediate surface, that would require tweaking the code in here a little though.
|
||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||
mTiles[i].mDrawTarget->PopLayer();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -103,6 +103,13 @@ public:
|
||||
virtual void PushClip(const Path *aPath) override;
|
||||
virtual void PushClipRect(const Rect &aRect) override;
|
||||
virtual void PopClip() override;
|
||||
virtual void PushLayer(bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask,
|
||||
const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds = IntRect(),
|
||||
bool aCopyBackground = false) override;
|
||||
virtual void PopLayer() override;
|
||||
|
||||
|
||||
virtual void SetTransform(const Matrix &aTransform) override;
|
||||
|
||||
|
||||
@@ -696,6 +696,267 @@ CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestin
|
||||
}
|
||||
}
|
||||
|
||||
static inline void AddRectToSink(ID2D1GeometrySink* aSink, const D2D1_RECT_F& aRect)
|
||||
{
|
||||
aSink->BeginFigure(D2D1::Point2F(aRect.left, aRect.top), D2D1_FIGURE_BEGIN_FILLED);
|
||||
aSink->AddLine(D2D1::Point2F(aRect.right, aRect.top));
|
||||
aSink->AddLine(D2D1::Point2F(aRect.right, aRect.bottom));
|
||||
aSink->AddLine(D2D1::Point2F(aRect.left, aRect.bottom));
|
||||
aSink->EndFigure(D2D1_FIGURE_END_CLOSED);
|
||||
}
|
||||
|
||||
class DCCommandSink : public ID2D1CommandSink
|
||||
{
|
||||
public:
|
||||
DCCommandSink(ID2D1DeviceContext* aCtx) : mCtx(aCtx)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(const IID &aIID, void **aPtr)
|
||||
{
|
||||
if (!aPtr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (aIID == IID_IUnknown) {
|
||||
*aPtr = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else if (aIID == IID_ID2D1CommandSink) {
|
||||
*aPtr = static_cast<ID2D1CommandSink*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
STDMETHODIMP BeginDraw()
|
||||
{
|
||||
// We don't want to do anything here!
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHODIMP EndDraw()
|
||||
{
|
||||
// We don't want to do anything here!
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetAntialiasMode(
|
||||
D2D1_ANTIALIAS_MODE antialiasMode
|
||||
)
|
||||
{
|
||||
mCtx->SetAntialiasMode(antialiasMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetTags(D2D1_TAG tag1, D2D1_TAG tag2)
|
||||
{
|
||||
mCtx->SetTags(tag1, tag2);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode)
|
||||
{
|
||||
mCtx->SetTextAntialiasMode(textAntialiasMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetTextRenderingParams(_In_opt_ IDWriteRenderingParams *textRenderingParams)
|
||||
{
|
||||
mCtx->SetTextRenderingParams(textRenderingParams);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetTransform(_In_ CONST D2D1_MATRIX_3X2_F *transform)
|
||||
{
|
||||
mCtx->SetTransform(transform);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND primitiveBlend)
|
||||
{
|
||||
mCtx->SetPrimitiveBlend(primitiveBlend);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP SetUnitMode(D2D1_UNIT_MODE unitMode)
|
||||
{
|
||||
mCtx->SetUnitMode(unitMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP Clear(_In_opt_ CONST D2D1_COLOR_F *color)
|
||||
{
|
||||
mCtx->Clear(color);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawGlyphRun(
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
_In_ CONST DWRITE_GLYPH_RUN *glyphRun,
|
||||
_In_opt_ CONST DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription,
|
||||
_In_ ID2D1Brush *foregroundBrush,
|
||||
DWRITE_MEASURING_MODE measuringMode
|
||||
)
|
||||
{
|
||||
mCtx->DrawGlyphRun(baselineOrigin, glyphRun, glyphRunDescription,
|
||||
foregroundBrush, measuringMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawLine(
|
||||
D2D1_POINT_2F point0,
|
||||
D2D1_POINT_2F point1,
|
||||
_In_ ID2D1Brush *brush,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle
|
||||
)
|
||||
{
|
||||
mCtx->DrawLine(point0, point1, brush, strokeWidth, strokeStyle);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawGeometry(
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
_In_ ID2D1Brush *brush,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle
|
||||
)
|
||||
{
|
||||
mCtx->DrawGeometry(geometry, brush, strokeWidth, strokeStyle);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawRectangle(
|
||||
_In_ CONST D2D1_RECT_F *rect,
|
||||
_In_ ID2D1Brush *brush,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle
|
||||
)
|
||||
{
|
||||
mCtx->DrawRectangle(rect, brush, strokeWidth, strokeStyle);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawBitmap(
|
||||
_In_ ID2D1Bitmap *bitmap,
|
||||
_In_opt_ CONST D2D1_RECT_F *destinationRectangle,
|
||||
FLOAT opacity,
|
||||
D2D1_INTERPOLATION_MODE interpolationMode,
|
||||
_In_opt_ CONST D2D1_RECT_F *sourceRectangle,
|
||||
_In_opt_ CONST D2D1_MATRIX_4X4_F *perspectiveTransform
|
||||
)
|
||||
{
|
||||
mCtx->DrawBitmap(bitmap, destinationRectangle, opacity,
|
||||
interpolationMode, sourceRectangle,
|
||||
perspectiveTransform);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawImage(
|
||||
_In_ ID2D1Image *image,
|
||||
_In_opt_ CONST D2D1_POINT_2F *targetOffset,
|
||||
_In_opt_ CONST D2D1_RECT_F *imageRectangle,
|
||||
D2D1_INTERPOLATION_MODE interpolationMode,
|
||||
D2D1_COMPOSITE_MODE compositeMode
|
||||
)
|
||||
{
|
||||
mCtx->DrawImage(image, targetOffset, imageRectangle,
|
||||
interpolationMode, compositeMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP DrawGdiMetafile(
|
||||
_In_ ID2D1GdiMetafile *gdiMetafile,
|
||||
_In_opt_ CONST D2D1_POINT_2F *targetOffset
|
||||
)
|
||||
{
|
||||
mCtx->DrawGdiMetafile(gdiMetafile, targetOffset);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP FillMesh(
|
||||
_In_ ID2D1Mesh *mesh,
|
||||
_In_ ID2D1Brush *brush
|
||||
)
|
||||
{
|
||||
mCtx->FillMesh(mesh, brush);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP FillOpacityMask(
|
||||
_In_ ID2D1Bitmap *opacityMask,
|
||||
_In_ ID2D1Brush *brush,
|
||||
_In_opt_ CONST D2D1_RECT_F *destinationRectangle,
|
||||
_In_opt_ CONST D2D1_RECT_F *sourceRectangle
|
||||
)
|
||||
{
|
||||
mCtx->FillOpacityMask(opacityMask, brush, destinationRectangle,
|
||||
sourceRectangle);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP FillGeometry(
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
_In_ ID2D1Brush *brush,
|
||||
_In_opt_ ID2D1Brush *opacityBrush
|
||||
)
|
||||
{
|
||||
mCtx->FillGeometry(geometry, brush, opacityBrush);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP FillRectangle(
|
||||
_In_ CONST D2D1_RECT_F *rect,
|
||||
_In_ ID2D1Brush *brush
|
||||
)
|
||||
{
|
||||
mCtx->FillRectangle(rect, brush);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PushAxisAlignedClip(
|
||||
_In_ CONST D2D1_RECT_F *clipRect,
|
||||
D2D1_ANTIALIAS_MODE antialiasMode
|
||||
)
|
||||
{
|
||||
mCtx->PushAxisAlignedClip(clipRect, antialiasMode);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PushLayer(
|
||||
_In_ CONST D2D1_LAYER_PARAMETERS1 *layerParameters1,
|
||||
_In_opt_ ID2D1Layer *layer
|
||||
)
|
||||
{
|
||||
mCtx->PushLayer(layerParameters1, layer);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PopAxisAlignedClip()
|
||||
{
|
||||
mCtx->PopAxisAlignedClip();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PopLayer()
|
||||
{
|
||||
mCtx->PopLayer();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ID2D1DeviceContext* mCtx;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +156,9 @@ StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
|
||||
pattern[i] = SkScalarMulDiv(SK_ScalarNearlyZero, 33, 32);
|
||||
}
|
||||
|
||||
SkDashPathEffect* dash = SkDashPathEffect::Create(&pattern.front(),
|
||||
dashCount,
|
||||
SkFloatToScalar(aOptions.mDashOffset));
|
||||
SkPathEffect* dash = SkDashPathEffect::Create(&pattern.front(),
|
||||
dashCount,
|
||||
SkFloatToScalar(aOptions.mDashOffset));
|
||||
SkSafeUnref(aPaint.setPathEffect(dash));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ int32_t
|
||||
PreferenceAccess::RegisterLivePref(const char* aName, int32_t* aVar,
|
||||
int32_t aDefault)
|
||||
{
|
||||
Int32Prefs().append(Int32Pref{ aName, aVar });
|
||||
if (!Int32Prefs().append(Int32Pref{ aName, aVar })) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
@@ -57,4 +59,4 @@ PreferenceAccess::SetAccess(PreferenceAccess* aAccess)
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -80,6 +80,8 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType)
|
||||
LOAD_EVENT_TYPE(FILTERNODESETINPUT, RecordedFilterNodeSetInput);
|
||||
LOAD_EVENT_TYPE(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget);
|
||||
LOAD_EVENT_TYPE(FONTDATA, RecordedFontData);
|
||||
LOAD_EVENT_TYPE(PUSHLAYER, RecordedPushLayer);
|
||||
LOAD_EVENT_TYPE(POPLAYER, RecordedPopLayer);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -157,6 +159,10 @@ RecordedEvent::GetEventName(EventType aType)
|
||||
return "CreateSimilarDrawTarget";
|
||||
case FONTDATA:
|
||||
return "FontData";
|
||||
case PUSHLAYER:
|
||||
return "PushLayer";
|
||||
case POPLAYER:
|
||||
return "PopLayer";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -927,6 +933,68 @@ RecordedPopClip::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
aStringStream << "[" << mDT << "] PopClip";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPushLayer::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
SourceSurface* mask = mMask ? aTranslator->LookupSourceSurface(mMask)
|
||||
: nullptr;
|
||||
aTranslator->LookupDrawTarget(mDT)->
|
||||
PushLayer(mOpaque, mOpacity, mask, mMaskTransform, mBounds, mCopyBackground);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPushLayer::RecordToStream(ostream &aStream) const
|
||||
{
|
||||
RecordedDrawingEvent::RecordToStream(aStream);
|
||||
WriteElement(aStream, mOpaque);
|
||||
WriteElement(aStream, mOpacity);
|
||||
WriteElement(aStream, mMask);
|
||||
WriteElement(aStream, mMaskTransform);
|
||||
WriteElement(aStream, mBounds);
|
||||
WriteElement(aStream, mCopyBackground);
|
||||
}
|
||||
|
||||
RecordedPushLayer::RecordedPushLayer(istream &aStream)
|
||||
: RecordedDrawingEvent(PUSHLAYER, aStream)
|
||||
{
|
||||
ReadElement(aStream, mOpaque);
|
||||
ReadElement(aStream, mOpacity);
|
||||
ReadElement(aStream, mMask);
|
||||
ReadElement(aStream, mMaskTransform);
|
||||
ReadElement(aStream, mBounds);
|
||||
ReadElement(aStream, mCopyBackground);
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPushLayer::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mDT << "] PushPLayer (Opaque=" << mOpaque <<
|
||||
", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPopLayer::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
aTranslator->LookupDrawTarget(mDT)->PopLayer();
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPopLayer::RecordToStream(ostream &aStream) const
|
||||
{
|
||||
RecordedDrawingEvent::RecordToStream(aStream);
|
||||
}
|
||||
|
||||
RecordedPopLayer::RecordedPopLayer(istream &aStream)
|
||||
: RecordedDrawingEvent(POPLAYER, aStream)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RecordedPopLayer::OutputSimpleEventInfo(stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mDT << "] PopLayer";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedSetTransform::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
|
||||
+52
-1
@@ -27,7 +27,7 @@ const uint32_t kMagicInt = 0xc001feed;
|
||||
const uint16_t kMajorRevision = 4;
|
||||
// A change in minor revision means additions of new events. New streams will
|
||||
// not play in older players.
|
||||
const uint16_t kMinorRevision = 0;
|
||||
const uint16_t kMinorRevision = 1;
|
||||
|
||||
struct ReferencePtr
|
||||
{
|
||||
@@ -192,6 +192,8 @@ public:
|
||||
FILTERNODESETINPUT,
|
||||
CREATESIMILARDRAWTARGET,
|
||||
FONTDATA,
|
||||
PUSHLAYER,
|
||||
POPLAYER,
|
||||
};
|
||||
static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1;
|
||||
|
||||
@@ -624,6 +626,55 @@ private:
|
||||
MOZ_IMPLICIT RecordedPopClip(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedPushLayer : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedPushLayer(DrawTarget* aDT, bool aOpaque, Float aOpacity,
|
||||
SourceSurface* aMask, const Matrix& aMaskTransform,
|
||||
const IntRect& aBounds, bool aCopyBackground)
|
||||
: RecordedDrawingEvent(PUSHLAYER, aDT), mOpaque(aOpaque)
|
||||
, mOpacity(aOpacity), mMask(aMask), mMaskTransform(aMaskTransform)
|
||||
, mBounds(aBounds), mCopyBackground(aCopyBackground)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
|
||||
|
||||
virtual std::string GetName() const { return "PushLayer"; }
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
MOZ_IMPLICIT RecordedPushLayer(std::istream &aStream);
|
||||
|
||||
bool mOpaque;
|
||||
Float mOpacity;
|
||||
ReferencePtr mMask;
|
||||
Matrix mMaskTransform;
|
||||
IntRect mBounds;
|
||||
bool mCopyBackground;
|
||||
};
|
||||
|
||||
class RecordedPopLayer : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedPopLayer(DrawTarget* aDT)
|
||||
: RecordedDrawingEvent(POPLAYER, aDT)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void PlayEvent(Translator *aTranslator) const;
|
||||
|
||||
virtual void RecordToStream(std::ostream &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
|
||||
|
||||
virtual std::string GetName() const { return "PopLayer"; }
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
MOZ_IMPLICIT RecordedPopLayer(std::istream &aStream);
|
||||
};
|
||||
|
||||
class RecordedSetTransform : public RecordedDrawingEvent {
|
||||
public:
|
||||
RecordedSetTransform(DrawTarget *aDT, const Matrix &aTransform)
|
||||
|
||||
+3
-1
@@ -194,7 +194,9 @@ SFNTData::GetU16FullNames(Vector<mozilla::u16string>& aU16FullNames)
|
||||
if (mFonts[i]->GetU16FullName(name)) {
|
||||
fontFound = true;
|
||||
}
|
||||
aU16FullNames.append(Move(name));
|
||||
if (!aU16FullNames.append(Move(name))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return fontFound;
|
||||
|
||||
@@ -128,37 +128,45 @@ CreateCanonicalU16Matchers(const BigEndianUint16& aNameID)
|
||||
NameRecordMatchers *matchers = new NameRecordMatchers();
|
||||
|
||||
// First, look for the English name (this will normally succeed).
|
||||
matchers->append(
|
||||
if (!matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->languageID == CANONICAL_LANG_ID &&
|
||||
aNameRecord->platformID == PLATFORM_ID &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
})) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// Second, look for all languages.
|
||||
matchers->append(
|
||||
if (!matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->platformID == PLATFORM_ID &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
})) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// On Mac may be dealing with font that only has Microsoft name entries.
|
||||
matchers->append(
|
||||
if (!matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->languageID == LANG_ID_MICROSOFT_EN_US &&
|
||||
aNameRecord->platformID == PLATFORM_ID_MICROSOFT &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
matchers->append(
|
||||
})) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (!matchers->append(
|
||||
[=](const NameRecord *aNameRecord) {
|
||||
return aNameRecord->nameID == aNameID &&
|
||||
aNameRecord->platformID == PLATFORM_ID_MICROSOFT &&
|
||||
IsUTF16Encoding(aNameRecord);
|
||||
});
|
||||
})) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
#endif
|
||||
|
||||
return matchers;
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
friend class ::mozilla::StaticRefPtr;
|
||||
|
||||
template<class U>
|
||||
friend class ::RefPtr;
|
||||
friend struct mozilla::RefPtrTraits;
|
||||
|
||||
template<class U>
|
||||
friend struct ::RunnableMethodTraits;
|
||||
|
||||
@@ -2430,7 +2430,7 @@ void
|
||||
SetAntialiasingFlags(Layer* aLayer, DrawTarget* aTarget)
|
||||
{
|
||||
bool permitSubpixelAA = !(aLayer->GetContentFlags() & Layer::CONTENT_DISABLE_SUBPIXEL_AA);
|
||||
if (aTarget->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
if (aTarget->IsCurrentGroupOpaque()) {
|
||||
aTarget->SetPermitSubpixelAA(permitSubpixelAA);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -516,9 +516,11 @@ public:
|
||||
// while holding mMonitor, because otherwise, if the overscrolled APZC
|
||||
// is this one, then the SetState(NOTHING) in UpdateAnimation will
|
||||
// stomp on the SetState(SNAP_BACK) it does.
|
||||
mDeferredTasks.append(NewRunnableMethod(mOverscrollHandoffChain.get(),
|
||||
&OverscrollHandoffChain::SnapBackOverscrolledApzc,
|
||||
&mApzc));
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(mOverscrollHandoffChain.get(),
|
||||
&OverscrollHandoffChain::SnapBackOverscrolledApzc,
|
||||
&mApzc))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -567,11 +569,13 @@ public:
|
||||
// the lock ordering. Instead we schedule HandleFlingOverscroll() to be
|
||||
// called after mMonitor is released.
|
||||
APZC_LOG("%p fling went into overscroll, handing off with velocity %s\n", &mApzc, Stringify(velocity).c_str());
|
||||
mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleFlingOverscroll,
|
||||
velocity,
|
||||
mOverscrollHandoffChain,
|
||||
mScrolledApzc));
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleFlingOverscroll,
|
||||
velocity,
|
||||
mOverscrollHandoffChain,
|
||||
mScrolledApzc))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// If there is a remaining velocity on this APZC, continue this fling
|
||||
// as well. (This fling and the handed-off fling will run concurrently.)
|
||||
@@ -796,9 +800,11 @@ public:
|
||||
// HandleSmoothScrollOverscroll() (which acquires the tree lock) would violate
|
||||
// the lock ordering. Instead we schedule HandleSmoothScrollOverscroll() to be
|
||||
// called after mMonitor is released.
|
||||
mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll,
|
||||
velocity));
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll,
|
||||
velocity))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# 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/.
|
||||
|
||||
ifeq ($(CPU_ARCH)_$(GNU_CC),arm_1)
|
||||
# The assembly uses the frame pointer register (r7 in Thumb/r11 in
|
||||
# ARM), the compiler doesn't like that.
|
||||
CXXFLAGS := $(filter-out -fno-omit-frame-pointer,$(CXXFLAGS)) -fomit-frame-pointer
|
||||
CFLAGS := $(filter-out -fno-omit-frame-pointer,$(CFLAGS)) -fomit-frame-pointer
|
||||
endif
|
||||
@@ -37,7 +37,6 @@ LOCAL_INCLUDES += [
|
||||
'skia/include/gpu',
|
||||
'skia/include/images',
|
||||
'skia/include/pathops',
|
||||
'skia/include/pipe',
|
||||
'skia/include/ports',
|
||||
'skia/include/private',
|
||||
'skia/include/utils',
|
||||
@@ -112,6 +111,9 @@ elif CONFIG['CLANG_CL']:
|
||||
|
||||
DEFINES['SKIA_IMPLEMENTATION'] = 1
|
||||
|
||||
if not CONFIG['MOZ_ENABLE_SKIA_GPU']:
|
||||
DEFINES['SK_SUPPORT_GPU'] = 0
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += [
|
||||
'-Wno-deprecated-declarations',
|
||||
@@ -240,7 +242,8 @@ def generate_separated_sources(platform_sources):
|
||||
'skia/src/opts/SkOpts_neon.cpp',
|
||||
'skia/src/opts/SkBitmapProcState_arm_neon.cpp',
|
||||
},
|
||||
'none': set()
|
||||
'none': set(),
|
||||
'gpu': set()
|
||||
})
|
||||
|
||||
for plat in platform_sources.keys():
|
||||
@@ -261,6 +264,8 @@ def generate_separated_sources(platform_sources):
|
||||
key = 'arm'
|
||||
elif '_none' in value:
|
||||
key = 'none'
|
||||
elif 'gpu' in value or 'Gpu' in value:
|
||||
key = 'gpu'
|
||||
elif all(value in platform_sources.get(p, {})
|
||||
for p in platforms if p != plat):
|
||||
key = 'common'
|
||||
@@ -371,6 +376,9 @@ def write_mozbuild(sources):
|
||||
|
||||
write_sources(f, sources['common'], 0)
|
||||
|
||||
f.write("if CONFIG['MOZ_ENABLE_SKIA_GPU']:\n")
|
||||
write_sources(f, sources['gpu'], 4)
|
||||
|
||||
f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):\n")
|
||||
write_sources(f, sources['android'], 4)
|
||||
|
||||
|
||||
+200
-192
@@ -25,7 +25,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/core/SkBitmapCache.cpp',
|
||||
'skia/src/core/SkBitmapController.cpp',
|
||||
'skia/src/core/SkBitmapDevice.cpp',
|
||||
'skia/src/core/SkBitmapFilter.cpp',
|
||||
'skia/src/core/SkBitmapHeap.cpp',
|
||||
'skia/src/core/SkBitmapProcShader.cpp',
|
||||
'skia/src/core/SkBitmapProcState.cpp',
|
||||
@@ -43,6 +42,7 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/core/SkClipStack.cpp',
|
||||
'skia/src/core/SkColor.cpp',
|
||||
'skia/src/core/SkColorFilter.cpp',
|
||||
'skia/src/core/SkColorFilterShader.cpp',
|
||||
'skia/src/core/SkColorTable.cpp',
|
||||
'skia/src/core/SkComposeShader.cpp',
|
||||
'skia/src/core/SkConfig8888.cpp',
|
||||
@@ -65,7 +65,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/core/SkEdgeClipper.cpp',
|
||||
'skia/src/core/SkError.cpp',
|
||||
'skia/src/core/SkFilterProc.cpp',
|
||||
'skia/src/core/SkFilterShader.cpp',
|
||||
'skia/src/core/SkFlattenable.cpp',
|
||||
'skia/src/core/SkFlattenableSerialization.cpp',
|
||||
'skia/src/core/SkFloatBits.cpp',
|
||||
@@ -76,6 +75,7 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/core/SkFontStyle.cpp',
|
||||
'skia/src/core/SkForceCPlusPlusLinking.cpp',
|
||||
'skia/src/core/SkGeometry.cpp',
|
||||
'skia/src/core/SkGlobalInitialization_core.cpp',
|
||||
'skia/src/core/SkGlyphCache.cpp',
|
||||
'skia/src/core/SkGraphics.cpp',
|
||||
'skia/src/core/SkHalf.cpp',
|
||||
@@ -98,6 +98,7 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/core/SkMetaData.cpp',
|
||||
'skia/src/core/SkMiniRecorder.cpp',
|
||||
'skia/src/core/SkMipMap.cpp',
|
||||
'skia/src/core/SkModeColorFilter.cpp',
|
||||
'skia/src/core/SkMultiPictureDraw.cpp',
|
||||
'skia/src/core/SkNinePatchIter.cpp',
|
||||
'skia/src/core/SkPackBits.cpp',
|
||||
@@ -181,7 +182,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/effects/gradients/SkRadialGradient.cpp',
|
||||
'skia/src/effects/gradients/SkSweepGradient.cpp',
|
||||
'skia/src/effects/gradients/SkTwoPointConicalGradient.cpp',
|
||||
'skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp',
|
||||
'skia/src/effects/GrCircleBlurFragmentProcessor.cpp',
|
||||
'skia/src/effects/Sk1DPathEffect.cpp',
|
||||
'skia/src/effects/Sk2DPathEffect.cpp',
|
||||
@@ -194,7 +194,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/effects/SkBlurMaskFilter.cpp',
|
||||
'skia/src/effects/SkColorCubeFilter.cpp',
|
||||
'skia/src/effects/SkColorFilterImageFilter.cpp',
|
||||
'skia/src/effects/SkColorFilters.cpp',
|
||||
'skia/src/effects/SkColorMatrix.cpp',
|
||||
'skia/src/effects/SkColorMatrixFilter.cpp',
|
||||
'skia/src/effects/SkComposeImageFilter.cpp',
|
||||
@@ -205,7 +204,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/effects/SkDropShadowImageFilter.cpp',
|
||||
'skia/src/effects/SkEmbossMask.cpp',
|
||||
'skia/src/effects/SkEmbossMaskFilter.cpp',
|
||||
'skia/src/effects/SkGpuBlurUtils.cpp',
|
||||
'skia/src/effects/SkImageSource.cpp',
|
||||
'skia/src/effects/SkLayerDrawLooper.cpp',
|
||||
'skia/src/effects/SkLayerRasterizer.cpp',
|
||||
@@ -218,10 +216,10 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/effects/SkMorphologyImageFilter.cpp',
|
||||
'skia/src/effects/SkOffsetImageFilter.cpp',
|
||||
'skia/src/effects/SkPaintFlagsDrawFilter.cpp',
|
||||
'skia/src/effects/SkPaintImageFilter.cpp',
|
||||
'skia/src/effects/SkPerlinNoiseShader.cpp',
|
||||
'skia/src/effects/SkPictureImageFilter.cpp',
|
||||
'skia/src/effects/SkPixelXorXfermode.cpp',
|
||||
'skia/src/effects/SkRectShaderImageFilter.cpp',
|
||||
'skia/src/effects/SkTableColorFilter.cpp',
|
||||
'skia/src/effects/SkTableMaskFilter.cpp',
|
||||
'skia/src/effects/SkTestImageFilters.cpp',
|
||||
@@ -232,133 +230,11 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/fonts/SkRandomScalerContext.cpp',
|
||||
'skia/src/fonts/SkRemotableFontMgr.cpp',
|
||||
'skia/src/fonts/SkTestScalerContext.cpp',
|
||||
'skia/src/gpu/batches/GrAtlasTextBatch.cpp',
|
||||
'skia/src/gpu/batches/GrBatch.cpp',
|
||||
'skia/src/gpu/batches/GrCopySurfaceBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDashLinePathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrDefaultPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrDrawAtlasBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawPathBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawVerticesBatch.cpp',
|
||||
'skia/src/gpu/batches/GrNinePatch.cpp',
|
||||
'skia/src/gpu/batches/GrNonAAFillRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrNonAAStrokeRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrRectBatchFactory.cpp',
|
||||
'skia/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrTessellatingPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrVertexBatch.cpp',
|
||||
'skia/src/gpu/effects/GrBezierEffect.cpp',
|
||||
'skia/src/gpu/effects/GrBicubicEffect.cpp',
|
||||
'skia/src/gpu/effects/GrBitmapTextGeoProc.cpp',
|
||||
'skia/src/gpu/effects/GrConfigConversionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrConstColorProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrConvexPolyEffect.cpp',
|
||||
'skia/src/gpu/effects/GrConvolutionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrCoverageSetOpXP.cpp',
|
||||
'skia/src/gpu/effects/GrCustomXfermode.cpp',
|
||||
'skia/src/gpu/effects/GrDashingEffect.cpp',
|
||||
'skia/src/gpu/effects/GrDisableColorXP.cpp',
|
||||
'skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp',
|
||||
'skia/src/gpu/effects/GrDitherEffect.cpp',
|
||||
'skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrOvalEffect.cpp',
|
||||
'skia/src/gpu/effects/GrPorterDuffXferProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrRRectEffect.cpp',
|
||||
'skia/src/gpu/effects/GrSimpleTextureEffect.cpp',
|
||||
'skia/src/gpu/effects/GrSingleTextureEffect.cpp',
|
||||
'skia/src/gpu/effects/GrTextureDomain.cpp',
|
||||
'skia/src/gpu/effects/GrTextureStripAtlas.cpp',
|
||||
'skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrYUVtoRGBEffect.cpp',
|
||||
'skia/src/gpu/gl/debug/GrBufferObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrDebugGL.cpp',
|
||||
'skia/src/gpu/gl/debug/GrFrameBufferObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrProgramObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrShaderObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrTextureObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrTextureUnitObj.cpp',
|
||||
'skia/src/gpu/gl/debug/SkDebugGLContext.cpp',
|
||||
'skia/src/gpu/gl/SkGLContext.cpp',
|
||||
'skia/src/gpu/gl/SkNullGLContext.cpp',
|
||||
'skia/src/gpu/GrAtlasTextBlob.cpp',
|
||||
'skia/src/gpu/GrAtlasTextContext.cpp',
|
||||
'skia/src/gpu/GrBatchFlushState.cpp',
|
||||
'skia/src/gpu/GrBatchFontCache.cpp',
|
||||
'skia/src/gpu/GrBatchTest.cpp',
|
||||
'skia/src/gpu/GrBlend.cpp',
|
||||
'skia/src/gpu/GrBlurUtils.cpp',
|
||||
'skia/src/gpu/GrBufferAllocPool.cpp',
|
||||
'skia/src/gpu/GrCaps.cpp',
|
||||
'skia/src/gpu/GrClip.cpp',
|
||||
'skia/src/gpu/GrClipMaskManager.cpp',
|
||||
'skia/src/gpu/GrContext.cpp',
|
||||
'skia/src/gpu/GrCoordTransform.cpp',
|
||||
'skia/src/gpu/GrDefaultGeoProcFactory.cpp',
|
||||
'skia/src/gpu/GrDrawingManager.cpp',
|
||||
'skia/src/gpu/GrDrawTarget.cpp',
|
||||
'skia/src/gpu/GrFontScaler.cpp',
|
||||
'skia/src/gpu/GrFragmentProcessor.cpp',
|
||||
'skia/src/gpu/GrGpu.cpp',
|
||||
'skia/src/gpu/GrGpuFactory.cpp',
|
||||
'skia/src/gpu/GrGpuResource.cpp',
|
||||
'skia/src/gpu/GrGpuResourceRef.cpp',
|
||||
'skia/src/gpu/GrImageIDTextureAdjuster.cpp',
|
||||
'skia/src/gpu/GrInvariantOutput.cpp',
|
||||
'skia/src/gpu/GrLayerAtlas.cpp',
|
||||
'skia/src/gpu/GrLayerCache.cpp',
|
||||
'skia/src/gpu/GrLayerHoister.cpp',
|
||||
'skia/src/gpu/GrMemoryPool.cpp',
|
||||
'skia/src/gpu/GrOvalRenderer.cpp',
|
||||
'skia/src/gpu/GrPaint.cpp',
|
||||
'skia/src/gpu/GrPath.cpp',
|
||||
'skia/src/gpu/GrPathProcessor.cpp',
|
||||
'skia/src/gpu/GrPathRange.cpp',
|
||||
'skia/src/gpu/GrPathRenderer.cpp',
|
||||
'skia/src/gpu/GrPathRendererChain.cpp',
|
||||
'skia/src/gpu/GrPathRendering.cpp',
|
||||
'skia/src/gpu/GrPathUtils.cpp',
|
||||
'skia/src/gpu/GrPipeline.cpp',
|
||||
'skia/src/gpu/GrPipelineBuilder.cpp',
|
||||
'skia/src/gpu/GrPrimitiveProcessor.cpp',
|
||||
'skia/src/gpu/GrProcessor.cpp',
|
||||
'skia/src/gpu/GrProcessorUnitTest.cpp',
|
||||
'skia/src/gpu/GrProcOptInfo.cpp',
|
||||
'skia/src/gpu/GrProgramElement.cpp',
|
||||
'skia/src/gpu/GrRecordReplaceDraw.cpp',
|
||||
'skia/src/gpu/GrRectanizer_pow2.cpp',
|
||||
'skia/src/gpu/GrRectanizer_skyline.cpp',
|
||||
'skia/src/gpu/GrReducedClip.cpp',
|
||||
'skia/src/gpu/GrRenderTarget.cpp',
|
||||
'skia/src/gpu/GrResourceProvider.cpp',
|
||||
'skia/src/gpu/GrSoftwarePathRenderer.cpp',
|
||||
'skia/src/gpu/GrStencil.cpp',
|
||||
'skia/src/gpu/GrStencilAndCoverTextContext.cpp',
|
||||
'skia/src/gpu/GrStencilAttachment.cpp',
|
||||
'skia/src/gpu/GrStrokeInfo.cpp',
|
||||
'skia/src/gpu/GrSurface.cpp',
|
||||
'skia/src/gpu/GrSWMaskHelper.cpp',
|
||||
'skia/src/gpu/GrTestUtils.cpp',
|
||||
'skia/src/gpu/GrTextBlobCache.cpp',
|
||||
'skia/src/gpu/GrTextContext.cpp',
|
||||
'skia/src/gpu/GrTexture.cpp',
|
||||
'skia/src/gpu/GrTextureAccess.cpp',
|
||||
'skia/src/gpu/GrTextureParamsAdjuster.cpp',
|
||||
'skia/src/gpu/GrTextureProvider.cpp',
|
||||
'skia/src/gpu/GrTraceMarker.cpp',
|
||||
'skia/src/gpu/GrXferProcessor.cpp',
|
||||
'skia/src/gpu/GrYUVProvider.cpp',
|
||||
'skia/src/gpu/SkGpuDevice.cpp',
|
||||
'skia/src/gpu/SkGpuDevice_drawTexture.cpp',
|
||||
'skia/src/gpu/SkGr.cpp',
|
||||
'skia/src/gpu/SkGrPixelRef.cpp',
|
||||
'skia/src/gpu/SkGrTexturePixelRef.cpp',
|
||||
'skia/src/image/SkImage.cpp',
|
||||
'skia/src/image/SkImage_Generator.cpp',
|
||||
'skia/src/image/SkImage_Raster.cpp',
|
||||
'skia/src/image/SkImageShader.cpp',
|
||||
'skia/src/image/SkSurface.cpp',
|
||||
'skia/src/image/SkSurface_Gpu.cpp',
|
||||
'skia/src/image/SkSurface_Raster.cpp',
|
||||
'skia/src/images/bmpdecoderhelper.cpp',
|
||||
'skia/src/images/SkDecodingImageGenerator.cpp',
|
||||
@@ -397,17 +273,15 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/pathops/SkPathOpsWinding.cpp',
|
||||
'skia/src/pathops/SkPathWriter.cpp',
|
||||
'skia/src/pathops/SkReduceOrder.cpp',
|
||||
'skia/src/pipe/SkGPipeRead.cpp',
|
||||
'skia/src/pipe/SkGPipeWrite.cpp',
|
||||
'skia/src/ports/SkDiscardableMemory_none.cpp',
|
||||
'skia/src/ports/SkGlobalInitialization_default.cpp',
|
||||
'skia/src/ports/SkImageDecoder_empty.cpp',
|
||||
'skia/src/ports/SkImageGenerator_skia.cpp',
|
||||
'skia/src/ports/SkMemory_mozalloc.cpp',
|
||||
'skia/src/ports/SkOSEnvironment.cpp',
|
||||
'skia/src/ports/SkOSFile_stdio.cpp',
|
||||
'skia/src/sfnt/SkOTTable_name.cpp',
|
||||
'skia/src/sfnt/SkOTUtils.cpp',
|
||||
'skia/src/utils/android/SkAndroidSDKCanvas.cpp',
|
||||
'skia/src/utils/SkBase64.cpp',
|
||||
'skia/src/utils/SkBitmapSourceDeserializer.cpp',
|
||||
'skia/src/utils/SkBitSet.cpp',
|
||||
@@ -415,8 +289,6 @@ UNIFIED_SOURCES += [
|
||||
'skia/src/utils/SkCamera.cpp',
|
||||
'skia/src/utils/SkCanvasStack.cpp',
|
||||
'skia/src/utils/SkCanvasStateUtils.cpp',
|
||||
'skia/src/utils/SkCubicInterval.cpp',
|
||||
'skia/src/utils/SkCullPoints.cpp',
|
||||
'skia/src/utils/SkDashPath.cpp',
|
||||
'skia/src/utils/SkDumpCanvas.cpp',
|
||||
'skia/src/utils/SkEventTracer.cpp',
|
||||
@@ -455,71 +327,205 @@ SOURCES += [
|
||||
'skia/src/core/SkPictureData.cpp',
|
||||
'skia/src/core/SkRecorder.cpp',
|
||||
'skia/src/core/SkScan_Antihair.cpp',
|
||||
'skia/src/effects/SkArithmeticMode_gpu.cpp',
|
||||
'skia/src/gpu/batches/GrAAConvexPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAConvexTessellator.cpp',
|
||||
'skia/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAFillRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrAAHairLinePathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAStrokeRectBatch.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
|
||||
'skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLAssembleInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLBufferImpl.cpp',
|
||||
'skia/src/gpu/gl/GrGLCaps.cpp',
|
||||
'skia/src/gpu/gl/GrGLContext.cpp',
|
||||
'skia/src/gpu/gl/GrGLCreateNativeInterface_none.cpp',
|
||||
'skia/src/gpu/gl/GrGLCreateNullInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLDefaultInterface_native.cpp',
|
||||
'skia/src/gpu/gl/GrGLExtensions.cpp',
|
||||
'skia/src/gpu/gl/GrGLGLSL.cpp',
|
||||
'skia/src/gpu/gl/GrGLGpu.cpp',
|
||||
'skia/src/gpu/gl/GrGLGpuProgramCache.cpp',
|
||||
'skia/src/gpu/gl/GrGLIndexBuffer.cpp',
|
||||
'skia/src/gpu/gl/GrGLInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLNameAllocator.cpp',
|
||||
'skia/src/gpu/gl/GrGLNoOpInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLPath.cpp',
|
||||
'skia/src/gpu/gl/GrGLPathRange.cpp',
|
||||
'skia/src/gpu/gl/GrGLPathRendering.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgram.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgramDataManager.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgramDesc.cpp',
|
||||
'skia/src/gpu/gl/GrGLRenderTarget.cpp',
|
||||
'skia/src/gpu/gl/GrGLStencilAttachment.cpp',
|
||||
'skia/src/gpu/gl/GrGLTexture.cpp',
|
||||
'skia/src/gpu/gl/GrGLTextureRenderTarget.cpp',
|
||||
'skia/src/gpu/gl/GrGLUtil.cpp',
|
||||
'skia/src/gpu/gl/GrGLVaryingHandler.cpp',
|
||||
'skia/src/gpu/gl/GrGLVertexArray.cpp',
|
||||
'skia/src/gpu/gl/GrGLVertexBuffer.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSL.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLBlend.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLCaps.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLFragmentProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLProgramBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLUtil.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLVarying.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLXferProcessor.cpp',
|
||||
'skia/src/gpu/GrBatchAtlas.cpp',
|
||||
'skia/src/gpu/GrDrawContext.cpp',
|
||||
'skia/src/gpu/GrResourceCache.cpp',
|
||||
'skia/src/image/SkImage_Gpu.cpp',
|
||||
'skia/src/pathops/SkPathOpsDebug.cpp',
|
||||
'skia/src/utils/SkMD5.cpp',
|
||||
'skia/src/utils/SkParse.cpp',
|
||||
'skia/src/utils/SkParsePath.cpp',
|
||||
'skia/src/utils/SkSHA1.cpp',
|
||||
]
|
||||
if CONFIG['MOZ_ENABLE_SKIA_GPU']:
|
||||
UNIFIED_SOURCES += [
|
||||
'skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp',
|
||||
'skia/src/effects/SkGpuBlurUtils.cpp',
|
||||
'skia/src/gpu/batches/GrAtlasTextBatch.cpp',
|
||||
'skia/src/gpu/batches/GrBatch.cpp',
|
||||
'skia/src/gpu/batches/GrCopySurfaceBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDashLinePathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrDefaultPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrDrawAtlasBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawPathBatch.cpp',
|
||||
'skia/src/gpu/batches/GrDrawVerticesBatch.cpp',
|
||||
'skia/src/gpu/batches/GrNinePatch.cpp',
|
||||
'skia/src/gpu/batches/GrNonAAFillRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrNonAAStrokeRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrRectBatchFactory.cpp',
|
||||
'skia/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrTessellatingPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrVertexBatch.cpp',
|
||||
'skia/src/gpu/effects/GrBezierEffect.cpp',
|
||||
'skia/src/gpu/effects/GrBicubicEffect.cpp',
|
||||
'skia/src/gpu/effects/GrBitmapTextGeoProc.cpp',
|
||||
'skia/src/gpu/effects/GrConfigConversionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrConstColorProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrConvexPolyEffect.cpp',
|
||||
'skia/src/gpu/effects/GrConvolutionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrCoverageSetOpXP.cpp',
|
||||
'skia/src/gpu/effects/GrCustomXfermode.cpp',
|
||||
'skia/src/gpu/effects/GrDashingEffect.cpp',
|
||||
'skia/src/gpu/effects/GrDisableColorXP.cpp',
|
||||
'skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp',
|
||||
'skia/src/gpu/effects/GrDitherEffect.cpp',
|
||||
'skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp',
|
||||
'skia/src/gpu/effects/GrOvalEffect.cpp',
|
||||
'skia/src/gpu/effects/GrPorterDuffXferProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrRRectEffect.cpp',
|
||||
'skia/src/gpu/effects/GrSimpleTextureEffect.cpp',
|
||||
'skia/src/gpu/effects/GrSingleTextureEffect.cpp',
|
||||
'skia/src/gpu/effects/GrTextureDomain.cpp',
|
||||
'skia/src/gpu/effects/GrTextureStripAtlas.cpp',
|
||||
'skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp',
|
||||
'skia/src/gpu/effects/GrYUVtoRGBEffect.cpp',
|
||||
'skia/src/gpu/gl/debug/GrBufferObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrDebugGL.cpp',
|
||||
'skia/src/gpu/gl/debug/GrFrameBufferObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrProgramObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrShaderObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrTextureObj.cpp',
|
||||
'skia/src/gpu/gl/debug/GrTextureUnitObj.cpp',
|
||||
'skia/src/gpu/gl/debug/SkDebugGLContext.cpp',
|
||||
'skia/src/gpu/gl/SkGLContext.cpp',
|
||||
'skia/src/gpu/gl/SkNullGLContext.cpp',
|
||||
'skia/src/gpu/GrAuditTrail.cpp',
|
||||
'skia/src/gpu/GrBatchFlushState.cpp',
|
||||
'skia/src/gpu/GrBatchTest.cpp',
|
||||
'skia/src/gpu/GrBlend.cpp',
|
||||
'skia/src/gpu/GrBlurUtils.cpp',
|
||||
'skia/src/gpu/GrBufferAllocPool.cpp',
|
||||
'skia/src/gpu/GrCaps.cpp',
|
||||
'skia/src/gpu/GrClip.cpp',
|
||||
'skia/src/gpu/GrClipMaskManager.cpp',
|
||||
'skia/src/gpu/GrContext.cpp',
|
||||
'skia/src/gpu/GrCoordTransform.cpp',
|
||||
'skia/src/gpu/GrDefaultGeoProcFactory.cpp',
|
||||
'skia/src/gpu/GrDrawingManager.cpp',
|
||||
'skia/src/gpu/GrDrawTarget.cpp',
|
||||
'skia/src/gpu/GrFragmentProcessor.cpp',
|
||||
'skia/src/gpu/GrGpu.cpp',
|
||||
'skia/src/gpu/GrGpuFactory.cpp',
|
||||
'skia/src/gpu/GrGpuResource.cpp',
|
||||
'skia/src/gpu/GrGpuResourceRef.cpp',
|
||||
'skia/src/gpu/GrImageIDTextureAdjuster.cpp',
|
||||
'skia/src/gpu/GrInvariantOutput.cpp',
|
||||
'skia/src/gpu/GrLayerAtlas.cpp',
|
||||
'skia/src/gpu/GrLayerCache.cpp',
|
||||
'skia/src/gpu/GrLayerHoister.cpp',
|
||||
'skia/src/gpu/GrMemoryPool.cpp',
|
||||
'skia/src/gpu/GrOvalRenderer.cpp',
|
||||
'skia/src/gpu/GrPaint.cpp',
|
||||
'skia/src/gpu/GrPath.cpp',
|
||||
'skia/src/gpu/GrPathProcessor.cpp',
|
||||
'skia/src/gpu/GrPathRange.cpp',
|
||||
'skia/src/gpu/GrPathRenderer.cpp',
|
||||
'skia/src/gpu/GrPathRendererChain.cpp',
|
||||
'skia/src/gpu/GrPathRendering.cpp',
|
||||
'skia/src/gpu/GrPathUtils.cpp',
|
||||
'skia/src/gpu/GrPipeline.cpp',
|
||||
'skia/src/gpu/GrPipelineBuilder.cpp',
|
||||
'skia/src/gpu/GrPrimitiveProcessor.cpp',
|
||||
'skia/src/gpu/GrProcessor.cpp',
|
||||
'skia/src/gpu/GrProcessorUnitTest.cpp',
|
||||
'skia/src/gpu/GrProcOptInfo.cpp',
|
||||
'skia/src/gpu/GrProgramElement.cpp',
|
||||
'skia/src/gpu/GrRecordReplaceDraw.cpp',
|
||||
'skia/src/gpu/GrRectanizer_pow2.cpp',
|
||||
'skia/src/gpu/GrRectanizer_skyline.cpp',
|
||||
'skia/src/gpu/GrReducedClip.cpp',
|
||||
'skia/src/gpu/GrRenderTarget.cpp',
|
||||
'skia/src/gpu/GrResourceProvider.cpp',
|
||||
'skia/src/gpu/GrSoftwarePathRenderer.cpp',
|
||||
'skia/src/gpu/GrStencil.cpp',
|
||||
'skia/src/gpu/GrStencilAttachment.cpp',
|
||||
'skia/src/gpu/GrStrokeInfo.cpp',
|
||||
'skia/src/gpu/GrSurface.cpp',
|
||||
'skia/src/gpu/GrSWMaskHelper.cpp',
|
||||
'skia/src/gpu/GrTessellator.cpp',
|
||||
'skia/src/gpu/GrTestUtils.cpp',
|
||||
'skia/src/gpu/GrTexture.cpp',
|
||||
'skia/src/gpu/GrTextureAccess.cpp',
|
||||
'skia/src/gpu/GrTextureParamsAdjuster.cpp',
|
||||
'skia/src/gpu/GrTextureProvider.cpp',
|
||||
'skia/src/gpu/GrTraceMarker.cpp',
|
||||
'skia/src/gpu/GrXferProcessor.cpp',
|
||||
'skia/src/gpu/GrYUVProvider.cpp',
|
||||
'skia/src/gpu/SkGpuDevice.cpp',
|
||||
'skia/src/gpu/SkGpuDevice_drawTexture.cpp',
|
||||
'skia/src/gpu/SkGr.cpp',
|
||||
'skia/src/gpu/SkGrPixelRef.cpp',
|
||||
'skia/src/gpu/SkGrTexturePixelRef.cpp',
|
||||
'skia/src/gpu/text/GrAtlasTextBlob.cpp',
|
||||
'skia/src/gpu/text/GrAtlasTextContext.cpp',
|
||||
'skia/src/gpu/text/GrBatchFontCache.cpp',
|
||||
'skia/src/gpu/text/GrDistanceFieldAdjustTable.cpp',
|
||||
'skia/src/gpu/text/GrFontScaler.cpp',
|
||||
'skia/src/gpu/text/GrStencilAndCoverTextContext.cpp',
|
||||
'skia/src/gpu/text/GrTextBlobCache.cpp',
|
||||
'skia/src/gpu/text/GrTextContext.cpp',
|
||||
'skia/src/gpu/text/GrTextUtils.cpp',
|
||||
'skia/src/image/SkSurface_Gpu.cpp',
|
||||
]
|
||||
SOURCES += [
|
||||
'skia/src/effects/SkArithmeticMode_gpu.cpp',
|
||||
'skia/src/gpu/batches/GrAAConvexPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAConvexTessellator.cpp',
|
||||
'skia/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAFillRectBatch.cpp',
|
||||
'skia/src/gpu/batches/GrAAHairLinePathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp',
|
||||
'skia/src/gpu/batches/GrAAStrokeRectBatch.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
|
||||
'skia/src/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
|
||||
'skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLAssembleInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLBufferImpl.cpp',
|
||||
'skia/src/gpu/gl/GrGLCaps.cpp',
|
||||
'skia/src/gpu/gl/GrGLContext.cpp',
|
||||
'skia/src/gpu/gl/GrGLCreateNullInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLDefaultInterface_native.cpp',
|
||||
'skia/src/gpu/gl/GrGLExtensions.cpp',
|
||||
'skia/src/gpu/gl/GrGLGLSL.cpp',
|
||||
'skia/src/gpu/gl/GrGLGpu.cpp',
|
||||
'skia/src/gpu/gl/GrGLGpuProgramCache.cpp',
|
||||
'skia/src/gpu/gl/GrGLIndexBuffer.cpp',
|
||||
'skia/src/gpu/gl/GrGLInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLNoOpInterface.cpp',
|
||||
'skia/src/gpu/gl/GrGLPath.cpp',
|
||||
'skia/src/gpu/gl/GrGLPathRange.cpp',
|
||||
'skia/src/gpu/gl/GrGLPathRendering.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgram.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgramDataManager.cpp',
|
||||
'skia/src/gpu/gl/GrGLProgramDesc.cpp',
|
||||
'skia/src/gpu/gl/GrGLRenderTarget.cpp',
|
||||
'skia/src/gpu/gl/GrGLStencilAttachment.cpp',
|
||||
'skia/src/gpu/gl/GrGLTexture.cpp',
|
||||
'skia/src/gpu/gl/GrGLTextureRenderTarget.cpp',
|
||||
'skia/src/gpu/gl/GrGLTransferBuffer.cpp',
|
||||
'skia/src/gpu/gl/GrGLUniformHandler.cpp',
|
||||
'skia/src/gpu/gl/GrGLUtil.cpp',
|
||||
'skia/src/gpu/gl/GrGLVaryingHandler.cpp',
|
||||
'skia/src/gpu/gl/GrGLVertexArray.cpp',
|
||||
'skia/src/gpu/gl/GrGLVertexBuffer.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSL.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLBlend.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLCaps.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLFragmentProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLGeometryShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLProgramBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLUtil.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLVarying.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp',
|
||||
'skia/src/gpu/glsl/GrGLSLXferProcessor.cpp',
|
||||
'skia/src/gpu/GrBatchAtlas.cpp',
|
||||
'skia/src/gpu/GrDrawContext.cpp',
|
||||
'skia/src/gpu/GrResourceCache.cpp',
|
||||
'skia/src/image/SkImage_Gpu.cpp',
|
||||
]
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
|
||||
UNIFIED_SOURCES += [
|
||||
'skia/src/ports/SkDebug_android.cpp',
|
||||
@@ -649,7 +655,6 @@ LOCAL_INCLUDES += [
|
||||
'skia/include/gpu',
|
||||
'skia/include/images',
|
||||
'skia/include/pathops',
|
||||
'skia/include/pipe',
|
||||
'skia/include/ports',
|
||||
'skia/include/private',
|
||||
'skia/include/utils',
|
||||
@@ -730,6 +735,9 @@ elif CONFIG['CLANG_CL']:
|
||||
|
||||
DEFINES['SKIA_IMPLEMENTATION'] = 1
|
||||
|
||||
if not CONFIG['MOZ_ENABLE_SKIA_GPU']:
|
||||
DEFINES['SK_SUPPORT_GPU'] = 0
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += [
|
||||
'-Wno-deprecated-declarations',
|
||||
|
||||
@@ -50,7 +50,25 @@ public:
|
||||
/**
|
||||
* Format of the encoded data.
|
||||
*/
|
||||
SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
|
||||
SkEncodedFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
|
||||
|
||||
/**
|
||||
* @param requestedColorType Color type requested by the client
|
||||
*
|
||||
* If it is possible to decode to requestedColorType, this returns
|
||||
* requestedColorType. Otherwise, this returns whichever color type
|
||||
* is suggested by the codec as the best match for the encoded data.
|
||||
*/
|
||||
SkColorType computeOutputColorType(SkColorType requestedColorType);
|
||||
|
||||
/**
|
||||
* @param requestedUnpremul Indicates if the client requested
|
||||
* unpremultiplied output
|
||||
*
|
||||
* Returns the appropriate alpha type to decode to. If the image
|
||||
* has alpha, the value of requestedUnpremul will be honored.
|
||||
*/
|
||||
SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the scaled output image, for an input
|
||||
@@ -210,9 +228,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
SkAndroidCodec(const SkImageInfo&);
|
||||
SkAndroidCodec(SkCodec*);
|
||||
|
||||
virtual SkEncodedFormat onGetEncodedFormat() const = 0;
|
||||
SkCodec* codec() const { return fCodec.get(); }
|
||||
|
||||
virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
|
||||
|
||||
@@ -226,5 +244,7 @@ private:
|
||||
// This will always be a reference to the info that is contained by the
|
||||
// embedded SkCodec.
|
||||
const SkImageInfo& fInfo;
|
||||
|
||||
SkAutoTDelete<SkCodec> fCodec;
|
||||
};
|
||||
#endif // SkAndroidCodec_DEFINED
|
||||
|
||||
@@ -25,10 +25,35 @@ class SkSampler;
|
||||
*/
|
||||
class SkCodec : SkNoncopyable {
|
||||
public:
|
||||
/**
|
||||
* Minimum number of bytes that must be buffered in SkStream input.
|
||||
*
|
||||
* An SkStream passed to NewFromStream must be able to use this many
|
||||
* bytes to determine the image type. Then the same SkStream must be
|
||||
* passed to the correct decoder to read from the beginning.
|
||||
*
|
||||
* This can be accomplished by implementing peek() to support peeking
|
||||
* this many bytes, or by implementing rewind() to be able to rewind()
|
||||
* after reading this many bytes.
|
||||
*/
|
||||
static size_t MinBufferedBytesNeeded();
|
||||
|
||||
/**
|
||||
* If this stream represents an encoded image that we know how to decode,
|
||||
* return an SkCodec that can decode it. Otherwise return NULL.
|
||||
*
|
||||
* As stated above, this call must be able to peek or read
|
||||
* MinBufferedBytesNeeded to determine the correct format, and then start
|
||||
* reading from the beginning. First it will attempt to peek, and it
|
||||
* assumes that if less than MinBufferedBytesNeeded bytes (but more than
|
||||
* zero) are returned, this is because the stream is shorter than this,
|
||||
* so falling back to reading would not provide more data. If peek()
|
||||
* returns zero bytes, this call will instead attempt to read(). This
|
||||
* will require that the stream can be rewind()ed.
|
||||
*
|
||||
* If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
|
||||
* the image is a png.
|
||||
*
|
||||
* If the SkPngChunkReader is not NULL then:
|
||||
* If the image is not a PNG, the SkPngChunkReader will be ignored.
|
||||
* If the image is a PNG, the SkPngChunkReader will be reffed.
|
||||
@@ -252,18 +277,6 @@ public:
|
||||
*/
|
||||
Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Some images may initially report that they have alpha due to the format
|
||||
* of the encoded data, but then never use any colors which have alpha
|
||||
* less than 100%. This function can be called *after* decoding to
|
||||
* determine if such an image truly had alpha. Calling it before decoding
|
||||
* is undefined.
|
||||
* FIXME: see skbug.com/3582.
|
||||
*/
|
||||
bool reallyHasAlpha() const {
|
||||
return this->onReallyHasAlpha();
|
||||
}
|
||||
|
||||
/**
|
||||
* The remaining functions revolve around decoding scanlines.
|
||||
*/
|
||||
@@ -400,6 +413,8 @@ public:
|
||||
/**
|
||||
* An enum representing the order in which scanlines will be returned by
|
||||
* the scanline decoder.
|
||||
*
|
||||
* This is undefined before startScanlineDecode() is called.
|
||||
*/
|
||||
SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
|
||||
|
||||
@@ -415,9 +430,9 @@ public:
|
||||
int nextScanline() const { return this->outputScanline(fCurrScanline); }
|
||||
|
||||
/**
|
||||
* Returns the output y-coordinate of the row that corresponds to an input
|
||||
* y-coordinate. The input y-coordinate represents where the scanline
|
||||
* is located in the encoded data.
|
||||
* Returns the output y-coordinate of the row that corresponds to an input
|
||||
* y-coordinate. The input y-coordinate represents where the scanline
|
||||
* is located in the encoded data.
|
||||
*
|
||||
* This will equal inputScanline, except in the case of strangely
|
||||
* encoded image types (bottom-up bmps, interlaced gifs).
|
||||
@@ -459,8 +474,6 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool onReallyHasAlpha() const { return false; }
|
||||
|
||||
/**
|
||||
* If the stream was previously read, attempt to rewind.
|
||||
*
|
||||
@@ -529,14 +542,22 @@ protected:
|
||||
virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
|
||||
|
||||
/**
|
||||
* Update the next scanline. Used by interlaced png.
|
||||
* Update the current scanline. Used by interlaced png.
|
||||
*/
|
||||
void updateNextScanline(int newY) { fCurrScanline = newY; }
|
||||
void updateCurrScanline(int newY) { fCurrScanline = newY; }
|
||||
|
||||
const SkImageInfo& dstInfo() const { return fDstInfo; }
|
||||
|
||||
const SkCodec::Options& options() const { return fOptions; }
|
||||
|
||||
/**
|
||||
* Returns the number of scanlines that have been decoded so far.
|
||||
* This is unaffected by the SkScanlineOrder.
|
||||
*
|
||||
* Returns -1 if we have not started a scanline decode.
|
||||
*/
|
||||
int currScanline() const { return fCurrScanline; }
|
||||
|
||||
virtual int onOutputScanline(int inputScanline) const;
|
||||
|
||||
private:
|
||||
@@ -610,5 +631,6 @@ private:
|
||||
virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
|
||||
|
||||
friend class SkSampledCodec;
|
||||
friend class SkIcoCodec;
|
||||
};
|
||||
#endif // SkCodec_DEFINED
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
|
||||
|
||||
#define SK_SUPPORT_LEGACY_GETDEVICE
|
||||
#define SK_SUPPORT_LEGACY_GETTOPDEVICE
|
||||
|
||||
#define SK_IGNORE_ETC1_SUPPORT
|
||||
|
||||
|
||||
@@ -54,12 +54,24 @@ public:
|
||||
*/
|
||||
SkBitmap(const SkBitmap& src);
|
||||
|
||||
/**
|
||||
* Copy the settings from the src into this bitmap. If the src has pixels
|
||||
* allocated, ownership of the pixels will be taken.
|
||||
*/
|
||||
SkBitmap(SkBitmap&& src);
|
||||
|
||||
~SkBitmap();
|
||||
|
||||
/** Copies the src bitmap into this bitmap. Ownership of the src bitmap's pixels remains
|
||||
with the src bitmap.
|
||||
/** Copies the src bitmap into this bitmap. Ownership of the src
|
||||
bitmap's pixels is shared with the src bitmap.
|
||||
*/
|
||||
SkBitmap& operator=(const SkBitmap& src);
|
||||
|
||||
/** Copies the src bitmap into this bitmap. Takes ownership of the src
|
||||
bitmap's pixels.
|
||||
*/
|
||||
SkBitmap& operator=(SkBitmap&& src);
|
||||
|
||||
/** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
|
||||
*/
|
||||
// This method is not exported to java.
|
||||
@@ -294,6 +306,14 @@ public:
|
||||
return this->installPixels(info, pixels, rowBytes, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call installPixels with no ReleaseProc specified. This means
|
||||
* that the caller must ensure that the specified pixels and
|
||||
* colortable are valid for the lifetime of the created bitmap
|
||||
* (and its pixelRef).
|
||||
*/
|
||||
bool installPixels(const SkPixmap&);
|
||||
|
||||
/**
|
||||
* Calls installPixels() with the value in the SkMask. The caller must
|
||||
* ensure that the specified mask pixels are valid for the lifetime
|
||||
|
||||
@@ -37,6 +37,16 @@ class SkSurface;
|
||||
class SkSurface_Base;
|
||||
class SkTextBlob;
|
||||
|
||||
/*
|
||||
* If you want the legacy cliptolayer flag (i.e. android), then you must have the new
|
||||
* legacy saveflags.
|
||||
*/
|
||||
#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
|
||||
#ifndef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
#define SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** \class SkCanvas
|
||||
|
||||
A Canvas encapsulates all of the state about drawing into a device (bitmap).
|
||||
@@ -53,6 +63,10 @@ class SkTextBlob;
|
||||
etc.
|
||||
*/
|
||||
class SK_API SkCanvas : public SkRefCnt {
|
||||
enum PrivateSaveLayerFlags {
|
||||
kDontClipToLayer_PrivateSaveLayerFlag = 1 << 31,
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
|
||||
@@ -281,6 +295,7 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
enum SaveFlags {
|
||||
/** save the matrix state, restoring it on restore() */
|
||||
// [deprecated] kMatrix_SaveFlag = 0x01,
|
||||
@@ -307,6 +322,7 @@ public:
|
||||
#endif
|
||||
kARGB_ClipLayer_SaveFlag = 0x1F
|
||||
};
|
||||
#endif
|
||||
|
||||
/** This call saves the current matrix, clip, and drawFilter, and pushes a
|
||||
copy onto a private stack. Subsequent calls to translate, scale,
|
||||
@@ -336,6 +352,14 @@ public:
|
||||
return this->saveLayer(&bounds, paint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary name.
|
||||
* Will allow any requests for LCD text to be respected, so the caller must be careful to
|
||||
* only draw on top of opaque sections of the layer to get good results.
|
||||
*/
|
||||
int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
/** DEPRECATED - use saveLayer(const SkRect*, const SkPaint*) instead.
|
||||
|
||||
This behaves the same as saveLayer(const SkRect*, const SkPaint*),
|
||||
@@ -353,6 +377,7 @@ public:
|
||||
*/
|
||||
SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
|
||||
int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
|
||||
#endif
|
||||
|
||||
/** This behaves the same as save(), but in addition it allocates an
|
||||
offscreen bitmap. All drawing calls are directed there, and only when
|
||||
@@ -367,6 +392,7 @@ public:
|
||||
*/
|
||||
int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
/** DEPRECATED - use saveLayerAlpha(const SkRect*, U8CPU) instead.
|
||||
|
||||
This behaves the same as saveLayerAlpha(const SkRect*, U8CPU),
|
||||
@@ -383,6 +409,43 @@ public:
|
||||
*/
|
||||
SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
|
||||
int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, SaveFlags flags);
|
||||
#endif
|
||||
|
||||
enum {
|
||||
kIsOpaque_SaveLayerFlag = 1 << 0,
|
||||
kPreserveLCDText_SaveLayerFlag = 1 << 1,
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
|
||||
kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
|
||||
#endif
|
||||
};
|
||||
typedef uint32_t SaveLayerFlags;
|
||||
|
||||
struct SaveLayerRec {
|
||||
SaveLayerRec()
|
||||
: fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
|
||||
{}
|
||||
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
|
||||
: fBounds(bounds)
|
||||
, fPaint(paint)
|
||||
, fBackdrop(nullptr)
|
||||
, fSaveLayerFlags(saveLayerFlags)
|
||||
{}
|
||||
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
|
||||
SaveLayerFlags saveLayerFlags)
|
||||
: fBounds(bounds)
|
||||
, fPaint(paint)
|
||||
, fBackdrop(backdrop)
|
||||
, fSaveLayerFlags(saveLayerFlags)
|
||||
{}
|
||||
|
||||
const SkRect* fBounds; // optional
|
||||
const SkPaint* fPaint; // optional
|
||||
const SkImageFilter* fBackdrop; // optional
|
||||
SaveLayerFlags fSaveLayerFlags;
|
||||
};
|
||||
|
||||
int saveLayer(const SaveLayerRec&);
|
||||
|
||||
/** This call balances a previous call to save(), and is used to remove all
|
||||
modifications to the matrix/clip/drawFilter state since the last save
|
||||
@@ -606,8 +669,8 @@ public:
|
||||
* This makes the contents of the canvas undefined. Subsequent calls that
|
||||
* require reading the canvas contents will produce undefined results. Examples
|
||||
* include blending and readPixels. The actual implementation is backend-
|
||||
* dependent and one legal implementation is to do nothing. Like clear(), this
|
||||
* ignores the clip.
|
||||
* dependent and one legal implementation is to do nothing. This method
|
||||
* ignores the current clip.
|
||||
*
|
||||
* This function should only be called if the caller intends to subsequently
|
||||
* draw to the canvas. The canvas may do real work at discard() time in order
|
||||
@@ -617,7 +680,7 @@ public:
|
||||
void discard() { this->onDiscard(); }
|
||||
|
||||
/**
|
||||
* Fill the entire canvas' bitmap (restricted to the current clip) with the
|
||||
* Fill the entire canvas (restricted to the current clip) with the
|
||||
* specified paint.
|
||||
* @param paint The paint used to fill the canvas
|
||||
*/
|
||||
@@ -904,19 +967,6 @@ public:
|
||||
void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
|
||||
const SkPaint* paint = NULL);
|
||||
|
||||
/** Draw the specified bitmap, with its top/left corner at (x,y),
|
||||
NOT transformed by the current matrix. Note: if the paint
|
||||
contains a maskfilter that generates a mask which extends beyond the
|
||||
bitmap's original width/height, then the bitmap will be drawn as if it
|
||||
were in a Shader with CLAMP mode. Thus the color outside of the original
|
||||
width/height will be the edge color replicated.
|
||||
@param bitmap The bitmap to be drawn
|
||||
@param left The position of the left side of the bitmap being drawn
|
||||
@param top The position of the top side of the bitmap being drawn
|
||||
@param paint The paint used to draw the bitmap, or NULL
|
||||
*/
|
||||
void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint = NULL);
|
||||
|
||||
/** Draw the text, with origin at (x,y), using the specified paint.
|
||||
The origin is interpreted based on the Align setting in the paint.
|
||||
@param text The text to be drawn
|
||||
@@ -1223,14 +1273,15 @@ protected:
|
||||
|
||||
// Subclass save/restore notifiers.
|
||||
// Overriders should call the corresponding INHERITED method up the inheritance chain.
|
||||
// willSaveLayer()'s return value may suppress full layer allocation.
|
||||
// getSaveLayerStrategy()'s return value may suppress full layer allocation.
|
||||
enum SaveLayerStrategy {
|
||||
kFullLayer_SaveLayerStrategy,
|
||||
kNoLayer_SaveLayerStrategy
|
||||
kNoLayer_SaveLayerStrategy,
|
||||
};
|
||||
|
||||
virtual void willSave() {}
|
||||
virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
|
||||
// Overriders should call the corresponding INHERITED method up the inheritance chain.
|
||||
virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
|
||||
return kFullLayer_SaveLayerStrategy;
|
||||
}
|
||||
virtual void willRestore() {}
|
||||
@@ -1285,7 +1336,6 @@ protected:
|
||||
SrcRectConstraint);
|
||||
virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
|
||||
const SkPaint*);
|
||||
virtual void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*);
|
||||
|
||||
enum ClipEdgeStyle {
|
||||
kHard_ClipEdgeStyle,
|
||||
@@ -1311,11 +1361,21 @@ protected:
|
||||
// returns false if the entire rectangle is entirely clipped out
|
||||
// If non-NULL, The imageFilter parameter will be used to expand the clip
|
||||
// and offscreen bounds for any margin required by the filter DAG.
|
||||
bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
|
||||
SkIRect* intersection,
|
||||
bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
|
||||
const SkImageFilter* imageFilter = NULL);
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
// Needed by SkiaCanvasProxy in Android. Make sure that class is updated
|
||||
// before removing this method.
|
||||
static uint32_t SaveLayerFlagsToSaveFlags(SaveLayerFlags);
|
||||
#endif
|
||||
private:
|
||||
static bool BoundsAffectsClip(SaveLayerFlags);
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
static uint32_t SaveFlagsToSaveLayerFlags(SaveFlags);
|
||||
#endif
|
||||
static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
|
||||
|
||||
enum ShaderOverrideOpacity {
|
||||
kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
|
||||
kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
|
||||
@@ -1375,6 +1435,7 @@ private:
|
||||
friend class SkNoSaveLayerCanvas; // InitFlags
|
||||
friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
|
||||
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
|
||||
friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
|
||||
|
||||
enum InitFlags {
|
||||
kDefault_InitFlags = 0,
|
||||
@@ -1406,7 +1467,7 @@ private:
|
||||
const SkRect& dst, const SkPaint* paint,
|
||||
SrcRectConstraint);
|
||||
void internalDrawPaint(const SkPaint& paint);
|
||||
void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy);
|
||||
void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
|
||||
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
|
||||
|
||||
// shared by save() and saveLayer()
|
||||
@@ -1428,6 +1489,10 @@ private:
|
||||
*/
|
||||
bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
|
||||
|
||||
/**
|
||||
* Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
|
||||
*/
|
||||
bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
|
||||
|
||||
/* These maintain a cache of the clip bounds in local coordinates,
|
||||
(converted to 2s-compliment if floats are slow).
|
||||
@@ -1505,49 +1570,7 @@ private:
|
||||
};
|
||||
#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
|
||||
|
||||
/**
|
||||
* If the caller wants read-only access to the pixels in a canvas, it can just
|
||||
* call canvas->peekPixels(), since that is the fastest way to "peek" at the
|
||||
* pixels on a raster-backed canvas.
|
||||
*
|
||||
* If the canvas has pixels, but they are not readily available to the CPU
|
||||
* (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
|
||||
* succeed (though be slower, since it will return a copy of the pixels).
|
||||
*
|
||||
* SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
|
||||
* peekPixels() (for performance), but if that fails, calling readPixels() and
|
||||
* storing the copy locally.
|
||||
*
|
||||
* The caller must respect the restrictions associated with peekPixels(), since
|
||||
* that may have been called: The returned information is invalidated if...
|
||||
* - any API is called on the canvas (or its parent surface if present)
|
||||
* - the canvas goes out of scope
|
||||
*/
|
||||
class SkAutoROCanvasPixels : SkNoncopyable {
|
||||
public:
|
||||
SkAutoROCanvasPixels(SkCanvas* canvas);
|
||||
|
||||
// returns NULL on failure
|
||||
const void* addr() const { return fAddr; }
|
||||
|
||||
// undefined if addr() == NULL
|
||||
size_t rowBytes() const { return fRowBytes; }
|
||||
|
||||
// undefined if addr() == NULL
|
||||
const SkImageInfo& info() const { return fInfo; }
|
||||
|
||||
// helper that, if returns true, installs the pixels into the bitmap. Note
|
||||
// that the bitmap may reference the address returned by peekPixels(), so
|
||||
// the caller must respect the restrictions associated with peekPixels().
|
||||
bool asROBitmap(SkBitmap*) const;
|
||||
|
||||
private:
|
||||
SkBitmap fBitmap; // used if peekPixels() fails
|
||||
const void* fAddr; // NULL on failure
|
||||
SkImageInfo fInfo;
|
||||
size_t fRowBytes;
|
||||
};
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
|
||||
static inline SkCanvas::SaveFlags operator|(const SkCanvas::SaveFlags lhs,
|
||||
const SkCanvas::SaveFlags rhs) {
|
||||
return static_cast<SkCanvas::SaveFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||
@@ -1558,6 +1581,7 @@ static inline SkCanvas::SaveFlags& operator|=(SkCanvas::SaveFlags& lhs,
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
#endif
|
||||
|
||||
class SkCanvasClipVisitor {
|
||||
public:
|
||||
|
||||
@@ -106,13 +106,6 @@ public:
|
||||
*/
|
||||
static SkColorFilter* CreateModeFilter(SkColor c, SkXfermode::Mode mode);
|
||||
|
||||
/** Create a colorfilter that multiplies the RGB channels by one color, and
|
||||
then adds a second color, pinning the result for each component to
|
||||
[0..255]. The alpha components of the mul and add arguments
|
||||
are ignored.
|
||||
*/
|
||||
static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
|
||||
|
||||
/** Construct a colorfilter whose effect is to first apply the inner filter and then apply
|
||||
* the outer filter to the result of the inner's.
|
||||
* The reference counts for outer and inner are incremented.
|
||||
|
||||
@@ -333,16 +333,26 @@ protected:
|
||||
const SkPaint*);
|
||||
|
||||
struct CreateInfo {
|
||||
static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry);
|
||||
static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
|
||||
bool preserveLCDText);
|
||||
|
||||
// The constructor may change the pixel geometry based on other parameters.
|
||||
CreateInfo(const SkImageInfo& info,
|
||||
TileUsage tileUsage,
|
||||
SkPixelGeometry geo,
|
||||
bool forImageFilter = false)
|
||||
SkPixelGeometry geo)
|
||||
: fInfo(info)
|
||||
, fTileUsage(tileUsage)
|
||||
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo))
|
||||
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
|
||||
, fForImageFilter(false) {}
|
||||
|
||||
CreateInfo(const SkImageInfo& info,
|
||||
TileUsage tileUsage,
|
||||
SkPixelGeometry geo,
|
||||
bool preserveLCDText,
|
||||
bool forImageFilter)
|
||||
: fInfo(info)
|
||||
, fTileUsage(tileUsage)
|
||||
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
|
||||
, fForImageFilter(forImageFilter) {}
|
||||
|
||||
const SkImageInfo fInfo;
|
||||
@@ -374,9 +384,13 @@ private:
|
||||
friend class SkDeviceFilteredPaint;
|
||||
friend class SkImageFilter::DeviceProxy;
|
||||
friend class SkNoPixelsBitmapDevice;
|
||||
|
||||
friend class SkSurface_Raster;
|
||||
|
||||
/**
|
||||
* Calls through to drawSprite, processing imagefilter as needed.
|
||||
*/
|
||||
void drawBitmapAsSprite(const SkDraw&, const SkBitmap&, int x, int y, const SkPaint&);
|
||||
|
||||
// used to change the backend's pixels (and possibly config/rowbytes)
|
||||
// but cannot change the width/height, so there should be no change to
|
||||
// any clip information.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "SkTime.h"
|
||||
|
||||
class SkCanvas;
|
||||
class SkPixelSerializer;
|
||||
class SkWStream;
|
||||
|
||||
/** SK_ScalarDefaultDPI is 72 DPI.
|
||||
@@ -57,6 +58,24 @@ public:
|
||||
static SkDocument* CreatePDF(SkWStream*,
|
||||
SkScalar dpi = SK_ScalarDefaultRasterDPI);
|
||||
|
||||
/**
|
||||
* @param jpegEncoder For PDF documents, if a jpegEncoder is set,
|
||||
* use it to encode SkImages and SkBitmaps as [JFIF]JPEGs.
|
||||
* This feature is deprecated and is only supplied for
|
||||
* backwards compatability.
|
||||
*
|
||||
* The prefered method to create PDFs with JPEG images is
|
||||
* to use SkImage::NewFromEncoded() and not jpegEncoder.
|
||||
* Chromium uses NewFromEncoded.
|
||||
*
|
||||
* If the encoder is unset, or if jpegEncoder->onEncode()
|
||||
* returns NULL, fall back on encoding images losslessly
|
||||
* with Deflate.
|
||||
*/
|
||||
static SkDocument* CreatePDF(SkWStream*,
|
||||
SkScalar dpi,
|
||||
SkPixelSerializer* jpegEncoder);
|
||||
|
||||
/**
|
||||
* Create a PDF-backed document, writing the results into a file.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,8 @@ class SkCanvas;
|
||||
class SkPaint;
|
||||
|
||||
/**
|
||||
* DEPRECATED - use SkPaintFilterCanvas instead.
|
||||
*
|
||||
* Right before something is being draw, filter() is called with the
|
||||
* paint. The filter may modify the paint as it wishes, which will then be
|
||||
* used for the actual drawing. Note: this modification only lasts for the
|
||||
|
||||
@@ -86,9 +86,9 @@ typedef int32_t SkFixed;
|
||||
#if defined(SK_SUPPORT_LEGACY_DIVBITS_UB)
|
||||
#define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
|
||||
#else
|
||||
// TODO(reed): this clamp shouldn't be needed. Use SkToS32().
|
||||
// The divide may exceed 32 bits. Clamp to a signed 32 bit result.
|
||||
#define SkFixedDiv(numer, denom) \
|
||||
SkTPin<int32_t>(((int64_t)numer << 16) / denom, SK_MinS32, SK_MaxS32)
|
||||
SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)numer, 16) / denom), SK_MinS32, SK_MaxS32))
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -145,9 +145,9 @@ inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
|
||||
|
||||
typedef int64_t SkFixed3232; // 32.32
|
||||
|
||||
#define SkIntToFixed3232(x) ((SkFixed3232)(x) << 32)
|
||||
#define SkIntToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 32))
|
||||
#define SkFixed3232ToInt(x) ((int)((x) >> 32))
|
||||
#define SkFixedToFixed3232(x) ((SkFixed3232)(x) << 16)
|
||||
#define SkFixedToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 16))
|
||||
#define SkFixed3232ToFixed(x) ((SkFixed)((x) >> 16))
|
||||
#define SkFloatToFixed3232(x) ((SkFixed3232)((x) * (65536.0f * 65536.0f)))
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class SkPrivateEffectInitializer;
|
||||
#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
|
||||
private: \
|
||||
static SkFlattenable* CreateProc(SkReadBuffer&); \
|
||||
friend class ::SkPrivateEffectInitializer; \
|
||||
friend class SkFlattenable::PrivateInitializer; \
|
||||
public: \
|
||||
Factory getFactory() const override { return CreateProc; }
|
||||
|
||||
@@ -108,6 +108,13 @@ public:
|
||||
*/
|
||||
virtual void flatten(SkWriteBuffer&) const {}
|
||||
|
||||
protected:
|
||||
class PrivateInitializer {
|
||||
public:
|
||||
static void InitCore();
|
||||
static void InitEffects();
|
||||
};
|
||||
|
||||
private:
|
||||
static void InitializeFlattenablesIfNeeded();
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
* attempt to reuse existing encoded data (as returned by refEncoded).
|
||||
*
|
||||
* We defer to the SkPixelSerializer both for vetting existing encoded data
|
||||
* (useEncodedData) and for encoding the image (encodePixels) when no such data is
|
||||
* (useEncodedData) and for encoding the image (encode) when no such data is
|
||||
* present or is rejected by the serializer.
|
||||
*
|
||||
* If not specified, we use a default serializer which 1) always accepts existing data
|
||||
@@ -324,28 +324,6 @@ public:
|
||||
*/
|
||||
bool isLazyGenerated() const;
|
||||
|
||||
/**
|
||||
* Apply the specified filter to this image, and return the result as a new image.
|
||||
*
|
||||
* if forceResultToOriginalSize is true, then the resulting image will be the same size as the
|
||||
* src, regardless of the normal output of the filter.
|
||||
*
|
||||
* If offset is non-null, it is set to the relative offset needed to draw the resulting image
|
||||
* in the same logical place as the original.
|
||||
*
|
||||
* e.g.
|
||||
* If the filter makes the result larger by a margin of 4 the output would be:
|
||||
* result->width() == this->width + 8
|
||||
* result->height() == this->height + 8
|
||||
* offset.x() == -4
|
||||
* offset.y() == -4
|
||||
*
|
||||
* If the filter fails to create a resulting image, null is returned, and the offset parameter
|
||||
* (if specified) will be undefined.
|
||||
*/
|
||||
SkImage* applyFilter(SkImageFilter* filter, SkIPoint* offset,
|
||||
bool forceResultToOriginalSize) const;
|
||||
|
||||
protected:
|
||||
SkImage(int width, int height, uint32_t uniqueID);
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#include "SkTRegistry.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
//#define SK_LEGACY_PEEKER
|
||||
|
||||
class SkStream;
|
||||
class SkStreamRewindable;
|
||||
|
||||
@@ -129,18 +127,6 @@ public:
|
||||
*/
|
||||
bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; }
|
||||
|
||||
#ifdef SK_LEGACY_PEEKER
|
||||
// Android subclasses SkImageDecoder::Peeker, which has been changed into SkPngChunkReader.
|
||||
// Temporarily use this class until Android can be updated to directly inherit from
|
||||
// SkPngChunkReader.
|
||||
class Peeker : public SkPngChunkReader {
|
||||
public:
|
||||
bool readChunk(const char tag[], const void* data, size_t length) final {
|
||||
return this->peek(tag, data, length);
|
||||
}
|
||||
virtual bool peek(const char tag[], const void* data, size_t length) = 0;
|
||||
};
|
||||
#endif
|
||||
SkPngChunkReader* getPeeker() const { return fPeeker; }
|
||||
SkPngChunkReader* setPeeker(SkPngChunkReader*);
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "SkTRegistry.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkPixelSerializer;
|
||||
class SkPixmap;
|
||||
class SkData;
|
||||
class SkWStream;
|
||||
|
||||
@@ -64,11 +66,17 @@ public:
|
||||
Type, int quality);
|
||||
static SkData* EncodeData(const SkBitmap&, Type, int quality);
|
||||
|
||||
static SkData* EncodeData(const SkPixmap&, Type, int quality);
|
||||
|
||||
static bool EncodeFile(const char file[], const SkBitmap&, Type,
|
||||
int quality);
|
||||
static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
|
||||
int quality);
|
||||
|
||||
/** Uses SkImageEncoder to serialize images that are not already
|
||||
encoded as SkImageEncoder::kPNG_Type images. */
|
||||
static SkPixelSerializer* CreatePixelSerializer();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode bitmap 'bm' in the desired format, writing results to
|
||||
|
||||
@@ -42,33 +42,25 @@ public:
|
||||
virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
|
||||
virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
|
||||
virtual void purge() {}
|
||||
};
|
||||
|
||||
enum SizeConstraint {
|
||||
kExact_SizeConstraint,
|
||||
kApprox_SizeConstraint,
|
||||
virtual void purgeByImageFilterId(uint32_t) {}
|
||||
};
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache,
|
||||
SizeConstraint constraint)
|
||||
Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
|
||||
: fCTM(ctm)
|
||||
, fClipBounds(clipBounds)
|
||||
, fCache(cache)
|
||||
, fSizeConstraint(constraint)
|
||||
{}
|
||||
|
||||
const SkMatrix& ctm() const { return fCTM; }
|
||||
const SkIRect& clipBounds() const { return fClipBounds; }
|
||||
Cache* cache() const { return fCache; }
|
||||
SizeConstraint sizeConstraint() const { return fSizeConstraint; }
|
||||
|
||||
private:
|
||||
SkMatrix fCTM;
|
||||
SkIRect fClipBounds;
|
||||
Cache* fCache;
|
||||
SizeConstraint fSizeConstraint;
|
||||
};
|
||||
|
||||
class CropRect {
|
||||
@@ -106,11 +98,17 @@ public:
|
||||
uint32_t fFlags;
|
||||
};
|
||||
|
||||
enum TileUsage {
|
||||
kPossible_TileUsage, //!< the created device may be drawn tiled
|
||||
kNever_TileUsage, //!< the created device will never be drawn tiled
|
||||
};
|
||||
|
||||
class Proxy {
|
||||
public:
|
||||
virtual ~Proxy() {}
|
||||
|
||||
virtual SkBaseDevice* createDevice(int width, int height) = 0;
|
||||
virtual SkBaseDevice* createDevice(int width, int height,
|
||||
TileUsage usage = kNever_TileUsage) = 0;
|
||||
|
||||
// Returns true if the proxy handled the filter itself. If this returns
|
||||
// false then the filter's code will be called.
|
||||
@@ -123,7 +121,8 @@ public:
|
||||
public:
|
||||
DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
|
||||
|
||||
SkBaseDevice* createDevice(int width, int height) override;
|
||||
SkBaseDevice* createDevice(int width, int height,
|
||||
TileUsage usage = kNever_TileUsage) override;
|
||||
|
||||
// Returns true if the proxy handled the filter itself. If this returns
|
||||
// false then the filter's code will be called.
|
||||
@@ -199,12 +198,7 @@ public:
|
||||
* replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
|
||||
* same way.
|
||||
*/
|
||||
bool asAColorFilter(SkColorFilter** filterPtr) const {
|
||||
return this->countInputs() > 0 &&
|
||||
NULL == this->getInput(0) &&
|
||||
!this->affectsTransparentBlack() &&
|
||||
this->isColorFilterNode(filterPtr);
|
||||
}
|
||||
bool asAColorFilter(SkColorFilter** filterPtr) const;
|
||||
|
||||
/**
|
||||
* Returns the number of inputs this filter will accept (some inputs can
|
||||
@@ -240,7 +234,7 @@ public:
|
||||
virtual void computeFastBounds(const SkRect&, SkRect*) const;
|
||||
|
||||
// Can this filter DAG compute the resulting bounds of an object-space rectangle?
|
||||
bool canComputeFastBounds() const;
|
||||
virtual bool canComputeFastBounds() const;
|
||||
|
||||
/**
|
||||
* If this filter can be represented by another filter + a localMatrix, return that filter,
|
||||
@@ -256,11 +250,6 @@ public:
|
||||
SkImageFilter* input = NULL);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
/**
|
||||
* Wrap the given texture in a texture-backed SkBitmap.
|
||||
*/
|
||||
static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
|
||||
|
||||
// Helper function which invokes GPU filter processing on the
|
||||
// input at the specified "index". If the input is null, it leaves
|
||||
// "result" and "offset" untouched, and returns true. If the input
|
||||
@@ -268,7 +257,7 @@ public:
|
||||
// Otherwise, the filter will be processed in software and
|
||||
// uploaded to the GPU.
|
||||
bool filterInputGPU(int index, SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
|
||||
SkBitmap* result, SkIPoint* offset, bool relaxSizeConstraint = true) const;
|
||||
SkBitmap* result, SkIPoint* offset) const;
|
||||
#endif
|
||||
|
||||
SK_TO_STRING_PUREVIRT()
|
||||
@@ -351,6 +340,25 @@ protected:
|
||||
// implementation recursively unions all input bounds, or returns false if
|
||||
// no inputs.
|
||||
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
|
||||
enum MapDirection {
|
||||
kForward_MapDirection,
|
||||
kReverse_MapDirection
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a forwards or reverse mapping of the given rect to accommodate
|
||||
* this filter's margin requirements. kForward_MapDirection is used to
|
||||
* determine the destination pixels which would be touched by filtering
|
||||
* the given given source rect (e.g., given source bitmap bounds,
|
||||
* determine the optimal bounds of the filtered offscreen bitmap).
|
||||
* kReverse_MapDirection is used to determine which pixels of the
|
||||
* input(s) would be required to fill the given destination rect
|
||||
* (e.g., clip bounds). NOTE: these operations may not be the
|
||||
* inverse of the other. For example, blurring expands the given rect
|
||||
* in both forward and reverse directions. Unlike
|
||||
* onFilterBounds(), this function is non-recursive.
|
||||
*/
|
||||
virtual void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const;
|
||||
|
||||
// Helper function which invokes filter processing on the input at the
|
||||
// specified "index". If the input is null, it leaves "result" and
|
||||
@@ -358,7 +366,7 @@ protected:
|
||||
// calls filterImage() on that input, and returns true on success.
|
||||
// i.e., return !getInput(index) || getInput(index)->filterImage(...);
|
||||
bool filterInput(int index, Proxy*, const SkBitmap& src, const Context&,
|
||||
SkBitmap* result, SkIPoint* offset, bool relaxSizeConstraint = true) const;
|
||||
SkBitmap* result, SkIPoint* offset) const;
|
||||
|
||||
/**
|
||||
* Return true (and return a ref'd colorfilter) if this node in the DAG is just a
|
||||
@@ -411,12 +419,12 @@ protected:
|
||||
const SkIRect& bounds) const;
|
||||
|
||||
/**
|
||||
* Returns true if this filter can cause transparent black pixels to become
|
||||
* visible (ie., alpha > 0). The default implementation returns false. This
|
||||
* function is non-recursive, i.e., only queries this filter and not its
|
||||
* inputs.
|
||||
* Creates a modified Context for use when recursing up the image filter DAG.
|
||||
* The clip bounds are adjusted to accommodate any margins that this
|
||||
* filter requires by calling this node's
|
||||
* onFilterNodeBounds(..., kReverse_MapDirection).
|
||||
*/
|
||||
virtual bool affectsTransparentBlack() const;
|
||||
Context mapContext(const Context& ctx) const;
|
||||
|
||||
private:
|
||||
friend class SkGraphics;
|
||||
|
||||
@@ -22,6 +22,12 @@ class SkMatrix;
|
||||
class SkPaint;
|
||||
class SkPicture;
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
|
||||
#define SK_REFENCODEDDATA_CTXPARAM
|
||||
#else
|
||||
#define SK_REFENCODEDDATA_CTXPARAM GrContext* ctx
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Takes ownership of SkImageGenerator. If this method fails for
|
||||
* whatever reason, it will return false and immediatetely delete
|
||||
@@ -64,12 +70,20 @@ public:
|
||||
|
||||
/**
|
||||
* Return a ref to the encoded (i.e. compressed) representation,
|
||||
* of this data.
|
||||
* of this data. If the GrContext is non-null, then the caller is only interested in
|
||||
* gpu-specific formats, so the impl may return null even if they have encoded data,
|
||||
* assuming they know it is not suitable for the gpu.
|
||||
*
|
||||
* If non-NULL is returned, the caller is responsible for calling
|
||||
* unref() on the data when it is finished.
|
||||
*/
|
||||
SkData* refEncodedData() { return this->onRefEncodedData(); }
|
||||
SkData* refEncodedData(GrContext* ctx = nullptr) {
|
||||
#ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
|
||||
return this->onRefEncodedData();
|
||||
#else
|
||||
return this->onRefEncodedData(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ImageInfo associated with this generator.
|
||||
@@ -230,7 +244,7 @@ public:
|
||||
protected:
|
||||
SkImageGenerator(const SkImageInfo& info);
|
||||
|
||||
virtual SkData* onRefEncodedData();
|
||||
virtual SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM);
|
||||
|
||||
virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
||||
SkPMColor ctable[], int* ctableCount);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
the 3-channel 3D format. These are passed to SkMaskFilter objects.
|
||||
*/
|
||||
struct SkMask {
|
||||
SkMask() : fImage(nullptr) {}
|
||||
|
||||
enum Format {
|
||||
kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
|
||||
kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
|
||||
|
||||
@@ -184,9 +184,7 @@ protected:
|
||||
|
||||
class NinePatch : ::SkNoncopyable {
|
||||
public:
|
||||
NinePatch() : fCache(NULL) {
|
||||
fMask.fImage = NULL;
|
||||
}
|
||||
NinePatch() : fCache(nullptr) { }
|
||||
~NinePatch();
|
||||
|
||||
SkMask fMask; // fBounds must have [0,0] in its top-left
|
||||
|
||||
@@ -635,15 +635,17 @@ public:
|
||||
|
||||
/**
|
||||
* Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper
|
||||
* left 2x2. If the matrix has perspective -1 is returned.
|
||||
* left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
|
||||
* -1 is returned.
|
||||
*
|
||||
* @return minumum scale factor
|
||||
* @return minimum scale factor
|
||||
*/
|
||||
SkScalar getMinScale() const;
|
||||
|
||||
/**
|
||||
* Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper
|
||||
* left 2x2. If the matrix has perspective -1 is returned.
|
||||
* left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
|
||||
* -1 is returned.
|
||||
*
|
||||
* @return maximum scale factor
|
||||
*/
|
||||
@@ -651,10 +653,10 @@ public:
|
||||
|
||||
/**
|
||||
* Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max
|
||||
* is scaleFactors[1]. If the matrix has perspective false will be returned and scaleFactors
|
||||
* will be unchanged.
|
||||
* is scaleFactors[1]. If the min/max scale factors cannot be computed false is returned and the
|
||||
* values of scaleFactors[] are undefined.
|
||||
*/
|
||||
bool getMinMaxScales(SkScalar scaleFactors[2]) const;
|
||||
bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
|
||||
|
||||
/**
|
||||
* Attempt to decompose this matrix into a scale-only component and whatever remains, where
|
||||
|
||||
@@ -41,6 +41,7 @@ size_t sk_fwrite(const void* buffer, size_t byteCount, FILE*);
|
||||
char* sk_fgets(char* str, int size, FILE* f);
|
||||
|
||||
void sk_fflush(FILE*);
|
||||
void sk_fsync(FILE*);
|
||||
|
||||
bool sk_fseek(FILE*, size_t);
|
||||
bool sk_fmove(FILE*, long);
|
||||
|
||||
@@ -631,13 +631,6 @@ public:
|
||||
SkAnnotation* getAnnotation() const { return fAnnotation; }
|
||||
SkAnnotation* setAnnotation(SkAnnotation*);
|
||||
|
||||
/**
|
||||
* Returns true if there is an annotation installed on this paint, and
|
||||
* the annotation specifics no-drawing.
|
||||
*/
|
||||
SK_ATTR_DEPRECATED("use getAnnotation and check for non-null")
|
||||
bool isNoDrawAnnotation() const { return this->getAnnotation() != NULL; }
|
||||
|
||||
/**
|
||||
* Return the paint's SkDrawLooper (if any). Does not affect the looper's
|
||||
* reference count.
|
||||
@@ -1089,12 +1082,11 @@ private:
|
||||
friend class SkCanvas;
|
||||
friend class SkDraw;
|
||||
friend class SkPDFDevice;
|
||||
friend class GrBitmapTextContext;
|
||||
friend class GrAtlasTextBlob;
|
||||
friend class GrAtlasTextContext;
|
||||
friend class GrDistanceFieldTextContext;
|
||||
friend class GrStencilAndCoverTextContext;
|
||||
friend class GrPathRendering;
|
||||
friend class GrTextContext;
|
||||
friend class GrTextUtils;
|
||||
friend class GrGLPathRendering;
|
||||
friend class SkScalerContext;
|
||||
friend class SkTextToPathIter;
|
||||
|
||||
@@ -956,6 +956,14 @@ public:
|
||||
return (Verb) fRawIter.next(pts);
|
||||
}
|
||||
|
||||
/** Return what the next verb will be, but do not visit the next segment.
|
||||
|
||||
@return The verb for the next segment
|
||||
*/
|
||||
Verb peek() const {
|
||||
return (Verb) fRawIter.peek();
|
||||
}
|
||||
|
||||
SkScalar conicWeight() const {
|
||||
return fRawIter.conicWeight();
|
||||
}
|
||||
|
||||
@@ -89,8 +89,12 @@ private:
|
||||
|
||||
struct Segment {
|
||||
SkScalar fDistance; // total distance up to this point
|
||||
unsigned fPtIndex : 15; // index into the fPts array
|
||||
unsigned fPtIndex; // index into the fPts array
|
||||
#ifdef SK_SUPPORT_LEGACY_PATH_MEASURE_TVALUE
|
||||
unsigned fTValue : 15;
|
||||
#else
|
||||
unsigned fTValue : 30;
|
||||
#endif
|
||||
unsigned fType : 2;
|
||||
|
||||
SkScalar getScalarT() const;
|
||||
|
||||
@@ -124,6 +124,7 @@ public:
|
||||
@return The verb for the current segment
|
||||
*/
|
||||
uint8_t next(SkPoint pts[4]);
|
||||
uint8_t peek() const;
|
||||
|
||||
SkScalar conicWeight() const { return *fConicWeights; }
|
||||
|
||||
|
||||
@@ -225,7 +225,8 @@ public:
|
||||
return this->onGetYUV8Planes(sizes, planes, rowBytes, colorSpace);
|
||||
}
|
||||
|
||||
bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
|
||||
/** Populates dst with the pixels of this pixelRef, converting them to colorType. */
|
||||
bool readPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subset = NULL);
|
||||
|
||||
/**
|
||||
* Makes a deep copy of this PixelRef, respecting the requested config.
|
||||
@@ -299,7 +300,7 @@ protected:
|
||||
*
|
||||
* The base class implementation returns false;
|
||||
*/
|
||||
virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
|
||||
virtual bool onReadPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subsetOrNull);
|
||||
|
||||
// default impl returns NULL.
|
||||
virtual SkData* onRefEncodedData();
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#define SkPixelSerializer_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkPixmap.h"
|
||||
|
||||
class SkData;
|
||||
struct SkImageInfo;
|
||||
|
||||
/**
|
||||
* Interface for serializing pixels, e.g. SkBitmaps in an SkPicture.
|
||||
@@ -32,14 +32,12 @@ public:
|
||||
* Call to get the client's version of encoding these pixels. If it
|
||||
* returns NULL, serialize the raw pixels.
|
||||
*/
|
||||
SkData* encodePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
|
||||
return this->onEncodePixels(info, pixels, rowBytes);
|
||||
}
|
||||
SkData* encode(const SkPixmap& pixmap) { return this->onEncode(pixmap); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return true if you want to serialize the encoded data, false if you want
|
||||
* another version serialized (e.g. the result of encodePixels).
|
||||
* another version serialized (e.g. the result of this->encode()).
|
||||
*/
|
||||
virtual bool onUseEncodedData(const void* data, size_t len) = 0;
|
||||
|
||||
@@ -47,6 +45,6 @@ protected:
|
||||
* If you want to encode these pixels, return the encoded data as an SkData
|
||||
* Return null if you want to serialize the raw pixels.
|
||||
*/
|
||||
virtual SkData* onEncodePixels(const SkImageInfo&, const void* pixels, size_t rowBytes) = 0;
|
||||
virtual SkData* onEncode(const SkPixmap&) = 0;
|
||||
};
|
||||
#endif // SkPixelSerializer_DEFINED
|
||||
|
||||
@@ -300,14 +300,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(SK_BUILD_FOR_WIN) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
|
||||
#define SK_VECTORCALL __vectorcall
|
||||
#elif defined(SK_CPU_ARM32)
|
||||
#define SK_VECTORCALL __attribute__((pcs("aapcs-vfp")))
|
||||
#else
|
||||
#define SK_VECTORCALL
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
#define SK_BUILD_FOR_ANDROID
|
||||
#elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
|
||||
defined(__DragonFly__) || defined(__GLIBC__) || defined(__GNU__)
|
||||
defined(__DragonFly__) || defined(__GLIBC__) || defined(__GNU__) || \
|
||||
defined(__unix__)
|
||||
#define SK_BUILD_FOR_UNIX
|
||||
#elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
#define SK_BUILD_FOR_IOS
|
||||
@@ -192,7 +193,7 @@
|
||||
|
||||
// All 64-bit ARM chips have NEON. Many 32-bit ARM chips do too.
|
||||
// TODO: Why don't we want NEON on iOS?
|
||||
#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_FOR_IOS) && defined(__ARM_NEON)
|
||||
#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_FOR_IOS) && (defined(__ARM_NEON__) || defined(__ARM_NEON))
|
||||
#define SK_ARM_HAS_NEON
|
||||
#endif
|
||||
|
||||
|
||||
@@ -153,6 +153,12 @@ public:
|
||||
return rr;
|
||||
}
|
||||
|
||||
static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
|
||||
SkRRect rr;
|
||||
rr.setRectXY(rect, xRad, yRad);
|
||||
return rr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this RR to match the supplied oval. All x radii will equal half the
|
||||
* width and all y radii will equal half the height.
|
||||
|
||||
@@ -824,24 +824,6 @@ public:
|
||||
SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) using
|
||||
* double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), which
|
||||
* may be slower than calling SkScalarRountToInt(), but gives slightly more accurate results.
|
||||
*
|
||||
* e.g.
|
||||
* SkScalar x = 0.49999997f;
|
||||
* int ix = SkScalarRoundToInt(x);
|
||||
* SkASSERT(0 == ix); // <--- fails
|
||||
* ix = SkDScalarRoundToInt(x);
|
||||
* SkASSERT(0 == ix); // <--- succeeds
|
||||
*/
|
||||
void dround(SkIRect* dst) const {
|
||||
SkASSERT(dst);
|
||||
dst->set(SkDScalarRoundToInt(fLeft), SkDScalarRoundToInt(fTop),
|
||||
SkDScalarRoundToInt(fRight), SkDScalarRoundToInt(fBottom));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dst rectangle by rounding "out" this rectangle, choosing the
|
||||
* SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
|
||||
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
void unref() const {
|
||||
if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
|
||||
SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert
|
||||
delete (const Derived*)this;
|
||||
delete (const Derived*)this;
|
||||
}
|
||||
}
|
||||
void deref() const { this->unref(); }
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "SkPaint.h"
|
||||
#include "../gpu/GrColor.h"
|
||||
|
||||
class SkColorFilter;
|
||||
class SkPath;
|
||||
class SkPicture;
|
||||
class SkXfermode;
|
||||
@@ -72,31 +73,14 @@ public:
|
||||
|
||||
enum Flags {
|
||||
//!< set if all of the colors will be opaque
|
||||
kOpaqueAlpha_Flag = 0x01,
|
||||
|
||||
//! set if this shader's shadeSpan16() method can be called
|
||||
kHasSpan16_Flag = 0x02,
|
||||
|
||||
/** Set this bit if the shader's native data type is instrinsically 16
|
||||
bit, meaning that calling the 32bit shadeSpan() entry point will
|
||||
mean the the impl has to up-sample 16bit data into 32bit. Used as a
|
||||
a means of clearing a dither request if the it will have no effect
|
||||
*/
|
||||
kIntrinsicly16_Flag = 0x04,
|
||||
kOpaqueAlpha_Flag = 1 << 0,
|
||||
|
||||
/** set if the spans only vary in X (const in Y).
|
||||
e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
|
||||
that varies from left-to-right. This flag specifies this for
|
||||
shadeSpan().
|
||||
*/
|
||||
kConstInY32_Flag = 0x08,
|
||||
|
||||
/** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
|
||||
which may not always be the case, since shadeSpan16 may be
|
||||
predithered, which would mean it was not const in Y, even though
|
||||
the 32bit shadeSpan() would be const.
|
||||
*/
|
||||
kConstInY16_Flag = 0x10
|
||||
kConstInY32_Flag = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -136,12 +120,6 @@ public:
|
||||
*/
|
||||
virtual uint32_t getFlags() const { return 0; }
|
||||
|
||||
/**
|
||||
* Return the alpha associated with the data returned by shadeSpan16(). If
|
||||
* kHasSpan16_Flag is not set, this value is meaningless.
|
||||
*/
|
||||
virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
|
||||
|
||||
/**
|
||||
* Called for each span of the object being drawn. Your subclass should
|
||||
* set the appropriate colors (with premultiplied alpha) that correspond
|
||||
@@ -149,14 +127,12 @@ public:
|
||||
*/
|
||||
virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
|
||||
|
||||
typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
|
||||
virtual ShadeProc asAShadeProc(void** ctx);
|
||||
|
||||
/**
|
||||
* Called only for 16bit devices when getFlags() returns
|
||||
* kOpaqueAlphaFlag | kHasSpan16_Flag
|
||||
* The const void* ctx is only const because all the implementations are const.
|
||||
* This can be changed to non-const if a new shade proc needs to change the ctx.
|
||||
*/
|
||||
virtual void shadeSpan16(int x, int y, uint16_t[], int count);
|
||||
typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count);
|
||||
virtual ShadeProc asAShadeProc(void** ctx);
|
||||
|
||||
/**
|
||||
* Similar to shadeSpan, but only returns the alpha-channel for a span.
|
||||
@@ -165,14 +141,6 @@ public:
|
||||
*/
|
||||
virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
|
||||
|
||||
/**
|
||||
* Helper function that returns true if this shader's shadeSpan16() method
|
||||
* can be called.
|
||||
*/
|
||||
bool canCallShadeSpan16() {
|
||||
return SkShader::CanCallShadeSpan16(this->getFlags());
|
||||
}
|
||||
|
||||
// Notification from blitter::blitMask in case we need to see the non-alpha channels
|
||||
virtual void set3DMask(const SkMask*) {}
|
||||
|
||||
@@ -215,13 +183,6 @@ public:
|
||||
*/
|
||||
virtual size_t contextSize() const;
|
||||
|
||||
/**
|
||||
* Helper to check the flags to know if it is legal to call shadeSpan16()
|
||||
*/
|
||||
static bool CanCallShadeSpan16(uint32_t flags) {
|
||||
return (flags & kHasSpan16_Flag) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
|
||||
* localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
|
||||
@@ -342,8 +303,23 @@ public:
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Factory methods for stock shaders
|
||||
// Methods to create combinations or variants of shaders
|
||||
|
||||
/**
|
||||
* Return a shader that will apply the specified localMatrix to this shader.
|
||||
* The specified matrix will be applied before any matrix associated with this shader.
|
||||
*/
|
||||
SkShader* newWithLocalMatrix(const SkMatrix&) const;
|
||||
|
||||
/**
|
||||
* Create a new shader that produces the same colors as invoking this shader and then applying
|
||||
* the colorfilter.
|
||||
*/
|
||||
SkShader* newWithColorFilter(SkColorFilter*) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Factory methods for stock shaders
|
||||
|
||||
/**
|
||||
* Call this to create a new "empty" shader, that will not draw anything.
|
||||
*/
|
||||
@@ -394,14 +370,6 @@ public:
|
||||
const SkMatrix* localMatrix,
|
||||
const SkRect* tile);
|
||||
|
||||
/**
|
||||
* Return a shader that will apply the specified localMatrix to the proxy shader.
|
||||
* The specified matrix will be applied before any matrix associated with the proxy.
|
||||
*
|
||||
* Note: ownership of the proxy is not transferred (though a ref is taken).
|
||||
*/
|
||||
static SkShader* CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix);
|
||||
|
||||
/**
|
||||
* If this shader can be represented by another shader + a localMatrix, return that shader
|
||||
* and, if not NULL, the localMatrix. If not, return NULL and ignore the localMatrix parameter.
|
||||
|
||||
@@ -65,17 +65,18 @@ public:
|
||||
|
||||
/**
|
||||
* Attempt to peek at size bytes.
|
||||
* If this stream supports peeking, and it can peek size bytes, copy size
|
||||
* bytes into buffer, and return true.
|
||||
* If the stream does not support peeking, or cannot peek size bytes,
|
||||
* return false and leave buffer unchanged.
|
||||
* If this stream supports peeking, copy min(size, peekable bytes) into
|
||||
* buffer, and return the number of bytes copied.
|
||||
* If the stream does not support peeking, or cannot peek any bytes,
|
||||
* return 0 and leave buffer unchanged.
|
||||
* The stream is guaranteed to be in the same visible state after this
|
||||
* call, regardless of success or failure.
|
||||
* @param buffer Must not be NULL. Destination to copy bytes.
|
||||
* @param buffer Must not be NULL, and must be at least size bytes. Destination
|
||||
* to copy bytes.
|
||||
* @param size Number of bytes to copy.
|
||||
* @return Whether the peek was performed.
|
||||
* @return The number of bytes peeked/copied.
|
||||
*/
|
||||
virtual bool peek(void* /* buffer */, size_t /* size */) const { return false; }
|
||||
virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
|
||||
|
||||
/** Returns true when all the bytes in the stream have been read.
|
||||
* This may return true early (when there are no more bytes to be read)
|
||||
@@ -325,7 +326,7 @@ public:
|
||||
size_t read(void* buffer, size_t size) override;
|
||||
bool isAtEnd() const override;
|
||||
|
||||
bool peek(void* buffer, size_t size) const override;
|
||||
size_t peek(void* buffer, size_t size) const override;
|
||||
|
||||
bool rewind() override;
|
||||
SkMemoryStream* duplicate() const override;
|
||||
@@ -359,6 +360,7 @@ public:
|
||||
|
||||
bool write(const void* buffer, size_t size) override;
|
||||
void flush() override;
|
||||
void fsync();
|
||||
size_t bytesWritten() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -267,7 +267,22 @@ template <> inline void SkTSwap(SkString& a, SkString& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
enum SkStrSplitMode {
|
||||
// Strictly return all results. If the input is ",," and the separator is ',' this will return
|
||||
// an array of three empty strings.
|
||||
kStrict_SkStrSplitMode,
|
||||
|
||||
// Only nonempty results will be added to the results. Multiple separators will be
|
||||
// coalesced. Separators at the beginning and end of the input will be ignored. If the input is
|
||||
// ",," and the separator is ',', this will return an empty vector.
|
||||
kCoalesce_SkStrSplitMode
|
||||
};
|
||||
|
||||
// Split str on any characters in delimiters into out. (Think, strtok with a sane API.)
|
||||
void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out);
|
||||
void SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,
|
||||
SkTArray<SkString>* out);
|
||||
inline void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
|
||||
SkStrSplit(str, delimiters, kCoalesce_SkStrSplitMode, out);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "SkTypes.h"
|
||||
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
template <typename T, bool MEM_COPY = false> class SkTArray;
|
||||
|
||||
@@ -23,11 +24,11 @@ inline void copy(SkTArray<T, true>* self, int dst, int src) {
|
||||
}
|
||||
template<typename T>
|
||||
inline void copy(SkTArray<T, true>* self, const T* array) {
|
||||
memcpy(self->fMemArray, array, self->fCount * sizeof(T));
|
||||
sk_careful_memcpy(self->fMemArray, array, self->fCount * sizeof(T));
|
||||
}
|
||||
template<typename T>
|
||||
inline void copyAndDelete(SkTArray<T, true>* self, char* newMemArray) {
|
||||
memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
|
||||
sk_careful_memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -198,7 +199,7 @@ public:
|
||||
*/
|
||||
template<class... Args> T& emplace_back(Args&&... args) {
|
||||
T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
|
||||
return *new (newT) T(skstd::forward<Args>(args)...);
|
||||
return *new (newT) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
SkTDArray<T> tmp(src.fArray, src.fCount);
|
||||
this->swap(tmp);
|
||||
} else {
|
||||
memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
|
||||
sk_careful_memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
|
||||
fCount = src.fCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../private/SkTemplates.h"
|
||||
#include "SkTypes.h"
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* Efficient way to defer allocating/initializing a class until it is needed
|
||||
@@ -50,7 +51,7 @@ public:
|
||||
if (this->isValid()) {
|
||||
fPtr->~T();
|
||||
}
|
||||
fPtr = new (SkTCast<T*>(fStorage.get())) T(skstd::forward<Args>(args)...);
|
||||
fPtr = new (SkTCast<T*>(fStorage.get())) T(std::forward<Args>(args)...);
|
||||
return fPtr;
|
||||
}
|
||||
|
||||
@@ -130,6 +131,8 @@ class SkTCopyOnFirstWrite {
|
||||
public:
|
||||
SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
|
||||
|
||||
SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
|
||||
|
||||
// Constructor for delayed initialization.
|
||||
SkTCopyOnFirstWrite() : fObj(NULL) {}
|
||||
|
||||
|
||||
@@ -38,10 +38,6 @@ public:
|
||||
static double GetNSecs();
|
||||
};
|
||||
|
||||
#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN32)
|
||||
extern SkMSec gForceTickCount;
|
||||
#endif
|
||||
|
||||
#define SK_TIME_FACTOR 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -24,6 +24,28 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* sk_careful_memcpy() is just like memcpy(), but guards against undefined behavior.
|
||||
*
|
||||
* It is undefined behavior to call memcpy() with null dst or src, even if len is 0.
|
||||
* If an optimizer is "smart" enough, it can exploit this to do unexpected things.
|
||||
* memcpy(dst, src, 0);
|
||||
* if (src) {
|
||||
* printf("%x\n", *src);
|
||||
* }
|
||||
* In this code the compiler can assume src is not null and omit the if (src) {...} check,
|
||||
* unconditionally running the printf, crashing the program if src really is null.
|
||||
* Of the compilers we pay attention to only GCC performs this optimization in practice.
|
||||
*/
|
||||
static inline void* sk_careful_memcpy(void* dst, const void* src, size_t len) {
|
||||
// When we pass >0 len we had better already be passing valid pointers.
|
||||
// So we just need to skip calling memcpy when len == 0.
|
||||
if (len) {
|
||||
memcpy(dst,src,len);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/** \file SkTypes.h
|
||||
*/
|
||||
|
||||
@@ -83,7 +105,10 @@ SK_API extern void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize
|
||||
|
||||
// bzero is safer than memset, but we can't rely on it, so... sk_bzero()
|
||||
static inline void sk_bzero(void* buffer, size_t size) {
|
||||
memset(buffer, 0, size);
|
||||
// Please c.f. sk_careful_memcpy. It's undefined behavior to call memset(null, 0, 0).
|
||||
if (size) {
|
||||
memset(buffer, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -227,12 +252,6 @@ typedef int S16CPU;
|
||||
*/
|
||||
typedef unsigned U16CPU;
|
||||
|
||||
/**
|
||||
* Meant to be faster than bool (doesn't promise to be 0 or 1,
|
||||
* just 0 or non-zero
|
||||
*/
|
||||
typedef int SkBool;
|
||||
|
||||
/**
|
||||
* Meant to be a small version of bool, for storage purposes. Will be 0 or 1
|
||||
*/
|
||||
@@ -262,7 +281,7 @@ typedef uint8_t SkBool8;
|
||||
|
||||
/** Returns 0 or 1 based on the condition
|
||||
*/
|
||||
#define SkToBool(cond) ((cond) != 0)
|
||||
#define SkToBool(cond) (!!(cond))
|
||||
|
||||
#define SK_MaxS16 32767
|
||||
#define SK_MinS16 -32767
|
||||
@@ -287,6 +306,14 @@ static inline bool SkIsU16(long x) {
|
||||
return (uint16_t)x == x;
|
||||
}
|
||||
|
||||
static inline int32_t SkLeftShift(int32_t value, int32_t shift) {
|
||||
return (int32_t) ((uint32_t) value << shift);
|
||||
}
|
||||
|
||||
static inline int64_t SkLeftShift(int64_t value, int32_t shift) {
|
||||
return (int64_t) ((uint64_t) value << shift);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Returns the number of entries in an array (not a pointer) */
|
||||
@@ -414,17 +441,6 @@ template <typename T> static inline const T& SkTPin(const T& value, const T& min
|
||||
return SkTMax(SkTMin(value, max), min);
|
||||
}
|
||||
|
||||
static inline uint32_t SkSetClearShift(uint32_t bits, bool cond,
|
||||
unsigned shift) {
|
||||
SkASSERT((int)cond == 0 || (int)cond == 1);
|
||||
return (bits & ~(1 << shift)) | ((int)cond << shift);
|
||||
}
|
||||
|
||||
static inline uint32_t SkSetClearMask(uint32_t bits, bool cond,
|
||||
uint32_t mask) {
|
||||
return cond ? bits | mask : bits & ~mask;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Use to combine multiple bits in a bitmask in a type safe way.
|
||||
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
*/
|
||||
void write(const void* values, size_t size) {
|
||||
SkASSERT(SkAlign4(size) == size);
|
||||
memcpy(this->reserve(size), values, size);
|
||||
sk_careful_memcpy(this->reserve(size), values, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
* Write size bytes from src, and pad to 4 byte alignment with zeroes.
|
||||
*/
|
||||
void writePad(const void* src, size_t size) {
|
||||
memcpy(this->reservePad(size), src, size);
|
||||
sk_careful_memcpy(this->reservePad(size), src, size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,8 +56,7 @@ public:
|
||||
@param style how to transform path at each point (based on the current
|
||||
position and tangent)
|
||||
*/
|
||||
static SkPath1DPathEffect* Create(const SkPath& path, SkScalar advance, SkScalar phase,
|
||||
Style style) {
|
||||
static SkPathEffect* Create(const SkPath& path, SkScalar advance, SkScalar phase, Style style) {
|
||||
return new SkPath1DPathEffect(path, advance, phase, style);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
|
||||
class SK_API SkLine2DPathEffect : public Sk2DPathEffect {
|
||||
public:
|
||||
static SkLine2DPathEffect* Create(SkScalar width, const SkMatrix& matrix) {
|
||||
static SkPathEffect* Create(SkScalar width, const SkMatrix& matrix) {
|
||||
return new SkLine2DPathEffect(width, matrix);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
* Stamp the specified path to fill the shape, using the matrix to define
|
||||
* the latice.
|
||||
*/
|
||||
static SkPath2DPathEffect* Create(const SkMatrix& matrix, const SkPath& path) {
|
||||
static SkPathEffect* Create(const SkMatrix& matrix, const SkPath& path) {
|
||||
return new SkPath2DPathEffect(matrix, path);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
*/
|
||||
static SkImageFilter* Create(const SkRegion& region, SkScalar innerThreshold,
|
||||
SkScalar outerThreshold, SkImageFilter* input = NULL);
|
||||
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
kAll_BlurFlag = 0x07
|
||||
};
|
||||
|
||||
static SkBlurDrawLooper* Create(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy,
|
||||
uint32_t flags = kNone_BlurFlag) {
|
||||
static SkDrawLooper* Create(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy,
|
||||
uint32_t flags = kNone_BlurFlag) {
|
||||
return new SkBlurDrawLooper(color, sigma, dx, dy, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ class SK_API SkBlurImageFilter : public SkImageFilter {
|
||||
public:
|
||||
static SkImageFilter* Create(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input = NULL,
|
||||
const CropRect* cropRect = NULL) {
|
||||
if (0 == sigmaX && 0 == sigmaY && nullptr == cropRect) {
|
||||
return SkSafeRef(input);
|
||||
}
|
||||
return new SkBlurImageFilter(sigmaX, sigmaY, input, cropRect);
|
||||
}
|
||||
|
||||
@@ -27,7 +30,8 @@ protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
|
||||
SkIPoint* offset) const override;
|
||||
bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override;
|
||||
void onFilterNodeBounds(const SkIRect& src, const SkMatrix&,
|
||||
SkIRect* dst, MapDirection) const override;
|
||||
bool canFilterImageGPU() const override { return true; }
|
||||
bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, SkBitmap* result,
|
||||
SkIPoint* offset) const override;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkData.h"
|
||||
#include "../private/SkMutex.h"
|
||||
#include "../private/SkTemplates.h"
|
||||
|
||||
class SK_API SkColorCubeFilter : public SkColorFilter {
|
||||
public:
|
||||
@@ -55,7 +56,7 @@ private:
|
||||
SkScalar* fColorToFactors[2];
|
||||
SkScalar* fColorToScalar;
|
||||
|
||||
SkAutoMalloc fLutStorage;
|
||||
SkAutoTMalloc<uint8_t> fLutStorage;
|
||||
|
||||
const int fCubeDimension;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ protected:
|
||||
bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
|
||||
SkIPoint* loc) const override;
|
||||
bool onIsColorFilterNode(SkColorFilter**) const override;
|
||||
bool affectsTransparentBlack() const override;
|
||||
bool canComputeFastBounds() const override;
|
||||
|
||||
private:
|
||||
SkColorFilterImageFilter(SkColorFilter* cf,
|
||||
|
||||
@@ -13,13 +13,21 @@
|
||||
|
||||
class SK_API SkColorMatrixFilter : public SkColorFilter {
|
||||
public:
|
||||
static SkColorMatrixFilter* Create(const SkColorMatrix& cm) {
|
||||
static SkColorFilter* Create(const SkColorMatrix& cm) {
|
||||
return new SkColorMatrixFilter(cm);
|
||||
}
|
||||
static SkColorMatrixFilter* Create(const SkScalar array[20]) {
|
||||
static SkColorFilter* Create(const SkScalar array[20]) {
|
||||
return new SkColorMatrixFilter(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a colorfilter that multiplies the RGB channels by one color, and
|
||||
* then adds a second color, pinning the result for each component to
|
||||
* [0..255]. The alpha components of the mul and add arguments
|
||||
* are ignored.
|
||||
*/
|
||||
static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
|
||||
uint32_t getFlags() const override;
|
||||
bool asColorMatrix(SkScalar matrix[20]) const override;
|
||||
@@ -29,11 +37,6 @@ public:
|
||||
const GrFragmentProcessor* asFragmentProcessor(GrContext*) const override;
|
||||
#endif
|
||||
|
||||
struct State {
|
||||
int32_t fArray[20];
|
||||
int fShift;
|
||||
};
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorMatrixFilter)
|
||||
@@ -46,13 +49,7 @@ protected:
|
||||
private:
|
||||
SkColorMatrix fMatrix;
|
||||
float fTranspose[SkColorMatrix::kCount]; // for Sk4s
|
||||
|
||||
typedef void (*Proc)(const State&, unsigned r, unsigned g, unsigned b,
|
||||
unsigned a, int32_t result[4]);
|
||||
|
||||
Proc fProc;
|
||||
State fState;
|
||||
uint32_t fFlags;
|
||||
uint32_t fFlags;
|
||||
|
||||
void initState(const SkScalar array[20]);
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ public:
|
||||
/** radius must be > 0 to have an effect. It specifies the distance from each corner
|
||||
that should be "rounded".
|
||||
*/
|
||||
static SkCornerPathEffect* Create(SkScalar radius) { return new SkCornerPathEffect(radius); }
|
||||
virtual ~SkCornerPathEffect();
|
||||
static SkPathEffect* Create(SkScalar radius) { return new SkCornerPathEffect(radius); }
|
||||
|
||||
virtual bool filterPath(SkPath* dst, const SkPath& src,
|
||||
SkStrokeRec*, const SkRect*) const override;
|
||||
@@ -34,6 +33,8 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual ~SkCornerPathEffect();
|
||||
|
||||
explicit SkCornerPathEffect(SkScalar radius);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ public:
|
||||
|
||||
Note: only affects stroked paths.
|
||||
*/
|
||||
static SkDashPathEffect* Create(const SkScalar intervals[], int count,
|
||||
SkScalar phase) {
|
||||
static SkPathEffect* Create(const SkScalar intervals[], int count, SkScalar phase) {
|
||||
return new SkDashPathEffect(intervals, count, phase);
|
||||
}
|
||||
virtual ~SkDashPathEffect();
|
||||
|
||||
@@ -29,9 +29,7 @@ public:
|
||||
they can pass in a different seedAssist to get a
|
||||
different set of path segments.
|
||||
*/
|
||||
static SkDiscretePathEffect* Create(SkScalar segLength,
|
||||
SkScalar deviation,
|
||||
uint32_t seedAssist=0) {
|
||||
static SkPathEffect* Create(SkScalar segLength, SkScalar deviation, uint32_t seedAssist = 0) {
|
||||
return new SkDiscretePathEffect(segLength, deviation, seedAssist);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ public:
|
||||
|
||||
~SkDisplacementMapEffect();
|
||||
|
||||
static SkDisplacementMapEffect* Create(ChannelSelectorType xChannelSelector,
|
||||
ChannelSelectorType yChannelSelector,
|
||||
SkScalar scale, SkImageFilter* displacement,
|
||||
SkImageFilter* color = NULL,
|
||||
const CropRect* cropRect = NULL);
|
||||
static SkImageFilter* Create(ChannelSelectorType xChannelSelector,
|
||||
ChannelSelectorType yChannelSelector,
|
||||
SkScalar scale, SkImageFilter* displacement,
|
||||
SkImageFilter* color = NULL,
|
||||
const CropRect* cropRect = NULL);
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDisplacementMapEffect)
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
|
||||
virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&,
|
||||
SkIRect* dst) const override;
|
||||
void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool canFilterImageGPU() const override { return true; }
|
||||
|
||||
@@ -35,7 +35,8 @@ protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onFilterImage(Proxy*, const SkBitmap& source, const Context&, SkBitmap* result,
|
||||
SkIPoint* loc) const override;
|
||||
bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override;
|
||||
void onFilterNodeBounds(const SkIRect& src, const SkMatrix&,
|
||||
SkIRect* dst, MapDirection) const override;
|
||||
|
||||
private:
|
||||
SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor,
|
||||
|
||||
@@ -23,14 +23,14 @@ public:
|
||||
uint8_t fSpecular; // exponent, 4.4 right now
|
||||
};
|
||||
|
||||
static SkEmbossMaskFilter* Create(SkScalar blurSigma, const Light& light);
|
||||
static SkMaskFilter* Create(SkScalar blurSigma, const Light& light);
|
||||
|
||||
// overrides from SkMaskFilter
|
||||
// This method is not exported to java.
|
||||
SkMask::Format getFormat() const override;
|
||||
// This method is not exported to java.
|
||||
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
|
||||
SkIPoint* margin) const override;
|
||||
bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
|
||||
SkIPoint* margin) const override;
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmbossMaskFilter)
|
||||
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
const SkImageFilterLight* light() const { return fLight.get(); }
|
||||
SkScalar surfaceScale() const { return fSurfaceScale; }
|
||||
bool affectsTransparentBlack() const override { return true; }
|
||||
bool canComputeFastBounds() const override { return false; }
|
||||
|
||||
private:
|
||||
typedef SkImageFilter INHERITED;
|
||||
|
||||
@@ -52,15 +52,15 @@ public:
|
||||
passed to filterImage() is used instead.
|
||||
@param cropRect The rectangle to which the output processing will be limited.
|
||||
*/
|
||||
static SkMatrixConvolutionImageFilter* Create(const SkISize& kernelSize,
|
||||
const SkScalar* kernel,
|
||||
SkScalar gain,
|
||||
SkScalar bias,
|
||||
const SkIPoint& kernelOffset,
|
||||
TileMode tileMode,
|
||||
bool convolveAlpha,
|
||||
SkImageFilter* input = NULL,
|
||||
const CropRect* cropRect = NULL);
|
||||
static SkImageFilter* Create(const SkISize& kernelSize,
|
||||
const SkScalar* kernel,
|
||||
SkScalar gain,
|
||||
SkScalar bias,
|
||||
const SkIPoint& kernelOffset,
|
||||
TileMode tileMode,
|
||||
bool convolveAlpha,
|
||||
SkImageFilter* input = NULL,
|
||||
const CropRect* cropRect = NULL);
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter)
|
||||
@@ -79,8 +79,8 @@ protected:
|
||||
|
||||
bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
|
||||
SkBitmap* result, SkIPoint* loc) const override;
|
||||
bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const override;
|
||||
|
||||
void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
|
||||
bool canComputeFastBounds() const override;
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user