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:
2023-07-22 09:12:54 +08:00
parent 159d7b9c2f
commit b0cbe263c6
762 changed files with 22213 additions and 31919 deletions
+3 -1
View File
@@ -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.
-4
View File
@@ -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
-5
View File
@@ -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
+9
View File
@@ -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,
+9
View File
@@ -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;
}
+4
View File
@@ -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();
+38 -1
View File
@@ -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
View File
@@ -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);
+3
View File
@@ -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
View File
@@ -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);
}
+43 -8
View File
@@ -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
+12 -13
View File
@@ -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));
+3 -14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+4
View File
@@ -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
View File
@@ -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;
+23 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+24
View File
@@ -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,
+33
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+24
View File
@@ -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
+7
View File
@@ -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;
+261
View File
@@ -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;
};
}
}
+3 -3
View File
@@ -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));
}
+4 -2
View File
@@ -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
+68
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+16 -8
View File
@@ -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;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+17 -11
View File
@@ -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;
}
-11
View File
@@ -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
+10 -2
View File
@@ -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
View File
@@ -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',
+23 -3
View File
@@ -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
+41 -19
View File
@@ -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
+22 -2
View File
@@ -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
+90 -66
View File
@@ -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.
+19 -5
View File
@@ -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.
+19
View File
@@ -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
+4 -4
View File
@@ -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)))
+8 -1
View File
@@ -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();
+1 -23
View File
@@ -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
+39 -31
View File
@@ -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;
+17 -3
View File
@@ -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);
+2
View File
@@ -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)
+1 -3
View File
@@ -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
+8 -6
View File
@@ -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
+1
View File
@@ -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);
+2 -10
View File
@@ -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;
+8
View File
@@ -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();
}
+5 -1
View File
@@ -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;
+1
View File
@@ -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; }
+3 -2
View File
@@ -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
+3 -2
View File
@@ -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
+6
View File
@@ -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.
-18
View File
@@ -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.
+1 -1
View File
@@ -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(); }
+23 -55
View File
@@ -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.
+10 -8
View File
@@ -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:
+16 -1
View File
@@ -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
+4 -3
View File
@@ -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)...);
}
/**
+1 -1
View File
@@ -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;
}
}
+4 -1
View File
@@ -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) {}
-4
View File
@@ -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
///////////////////////////////////////////////////////////////////////////////
+35 -19
View File
@@ -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.
+2 -2
View File
@@ -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