merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-12-21 11:52:31 +01:00
commit 7ad45c0d65
2222 changed files with 182795 additions and 125941 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1186934 followup needed to clear bustage
Bug 1082598 - updating Skia

View File

@ -352,6 +352,7 @@ ${EndIf}
${If} ${Errors}
WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}" "" "FirefoxHTML"
${EndIf}
WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}\OpenWithProgids" "FirefoxHTML" ""
!macroend
!define AddAssociationIfNoneExist "!insertmacro AddAssociationIfNoneExist"

View File

@ -418,7 +418,6 @@ ExDisp.h
exe386.h
execinfo.h
extras.h
fabdef.h
fcntl.h
features.h
fibdef.h
@ -628,7 +627,6 @@ libgnome/libgnome.h
libgnomeui/gnome-icon-lookup.h
libgnomeui/gnome-icon-theme.h
libgnomeui/gnome-ui-init.h
lib$routines.h
limits
limits.h
link.h
@ -889,7 +887,6 @@ resolv.h
Resources.h
Retrace.h
rld_interface.h
rmsdef.h
Roster.h
rpc.h
rpcproxy.h
@ -927,7 +924,6 @@ someincludefile.h
Sound.h
soundcard.h
sqlite3.h
ssdef.h
sstream
stack
#ifdef ANDROID
@ -1154,7 +1150,6 @@ unikbd.h
unistd.h
unix.h
unixio.h
unixlib.h
unknwn.h
UPrinting.h
UQuickTime.h

View File

@ -9260,6 +9260,22 @@ export DIST
export MOZ_LINKER
export ZLIB_IN_MOZGLUE
export MOZ_MEMORY
export AR
export RANLIB
export CPP
export CC
export CXX
export LD
export ARFLAGS
export CPPFLAGS
export CFLAGS
export CXXFLAGS
export LDFLAGS
export HOST_CC
export HOST_CXX
export HOST_CFLAGS
export HOST_CXXFLAGS
export HOST_LDFLAGS
if ! test -e js; then
mkdir js

View File

@ -3,7 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const DEFAULT_MAX_DEPTH = 3;
const { Visitor, walk } = require("resource://devtools/shared/heapsnapshot/CensusUtils.js");
const DEFAULT_MAX_DEPTH = 4;
const DEFAULT_MAX_SIBLINGS = 15;
/**
@ -12,10 +14,16 @@ const DEFAULT_MAX_SIBLINGS = 15;
* @param {NodeId} nodeId
* @param {NodeSize} retainedSize
*/
function DominatorTreeNode(nodeId, retainedSize) {
function DominatorTreeNode(nodeId, label, shallowSize, retainedSize) {
// The id of this node.
this.nodeId = nodeId;
// The label structure generated by describing the given node.
this.label = label;
// The shallow size of this node.
this.shallowSize = shallowSize;
// The retained size of this node.
this.retainedSize = retainedSize;
@ -59,6 +67,109 @@ DominatorTreeNode.addChild = function (parent, child) {
child.parentId = parent.nodeId;
};
/**
* A Visitor that is used to generate a label for a node in the heap snapshot
* and get its shallow size as well while we are at it.
*/
function LabelAndShallowSizeVisitor() {
// As we walk the description, we accumulate edges in this array.
this._labelPieces = [];
// Once we reach the non-zero count leaf node in the description, we move the
// labelPieces here to signify that we no longer need to accumulate edges.
this._label = undefined;
// Once we reach the non-zero count leaf node in the description, we grab the
// shallow size and place it here.
this._shallowSize = 0;
}
DominatorTreeNode.LabelAndShallowSizeVisitor = LabelAndShallowSizeVisitor;
LabelAndShallowSizeVisitor.prototype = Object.create(Visitor);
/**
* @overrides Visitor.prototype.enter
*/
LabelAndShallowSizeVisitor.prototype.enter = function (breakdown, report, edge) {
if (this._labelPieces && edge) {
this._labelPieces.push(edge);
}
};
/**
* @overrides Visitor.prototype.exit
*/
LabelAndShallowSizeVisitor.prototype.exit = function (breakdown, report, edge) {
if (this._labelPieces && edge) {
this._labelPieces.pop();
}
};
/**
* @overrides Visitor.prototype.count
*/
LabelAndShallowSizeVisitor.prototype.count = function (breakdown, report, edge) {
if (report.count === 0) {
return;
}
this._label = this._labelPieces;
this._labelPieces = undefined;
this._shallowSize = report.bytes;
};
/**
* Get the generated label structure accumulated by this visitor.
*
* @returns {Object}
*/
LabelAndShallowSizeVisitor.prototype.label = function () {
return this._label;
};
/**
* Get the shallow size of the node this visitor visited.
*
* @returns {Number}
*/
LabelAndShallowSizeVisitor.prototype.shallowSize = function () {
return this._shallowSize;
};
/**
* Generate a label structure for the node with the given id and grab its
* shallow size.
*
* What is a "label" structure? HeapSnapshot.describeNode essentially takes a
* census of a single node rather than the whole heap graph. The resulting
* report has only one count leaf that is non-zero. The label structure is the
* path in this report from the root to the non-zero count leaf.
*
* @param {Number} nodeId
* @param {HeapSnapshot} snapshot
* @param {Object} breakdown
*
* @returns {Object}
* An object with the following properties:
* - {Number} shallowSize
* - {Object} label
*/
DominatorTreeNode.getLabelAndShallowSize = function (nodeId,
snapshot,
breakdown) {
const description = snapshot.describeNode(breakdown, nodeId);
const visitor = new LabelAndShallowSizeVisitor();
walk(breakdown, description, visitor);
return {
label: visitor.label(),
shallowSize: visitor.shallowSize(),
};
};
/**
* Do a partial traversal of the given dominator tree and convert it into a tree
* of `DominatorTreeNode`s. Dominator trees have a node for every node in the
@ -75,11 +186,15 @@ DominatorTreeNode.addChild = function (parent, child) {
* @returns {DominatorTreeNode}
*/
DominatorTreeNode.partialTraversal = function (dominatorTree,
snapshot,
breakdown,
maxDepth = DEFAULT_MAX_DEPTH,
maxSiblings = DEFAULT_MAX_SIBLINGS) {
function dfs(nodeId, depth) {
const size = dominatorTree.getRetainedSize(nodeId);
const node = new DominatorTreeNode(nodeId, size);
const { label, shallowSize } =
DominatorTreeNode.getLabelAndShallowSize(nodeId, snapshot, breakdown);
const retainedSize = dominatorTree.getRetainedSize(nodeId);
const node = new DominatorTreeNode(nodeId, label, shallowSize, retainedSize);
const childNodeIds = dominatorTree.getImmediatelyDominated(nodeId);
const newDepth = depth + 1;

View File

@ -173,6 +173,8 @@ HeapAnalysesClient.prototype.computeDominatorTree = function (snapshotFilePath)
* An object specifying options for this request.
* - {DominatorTreeId} dominatorTreeId
* The id of the dominator tree.
* - {Object} breakdown
* The breakdown used to generate node labels.
* - {Number} maxDepth
* The maximum depth to traverse down the tree to create this initial
* view.
@ -195,6 +197,8 @@ HeapAnalysesClient.prototype.getDominatorTree = function (opts) {
* The id of the dominator tree.
* - {NodeId} nodeId
* The id of the node whose children are being found.
* - {Object} breakdown
* The breakdown used to generate node labels.
* - {Number} startIndex
* The starting index within the full set of immediately dominated
* children of the children being requested. Children are always sorted

View File

@ -103,6 +103,13 @@ workerHelper.createTask(self, "getCreationTime", snapshotFilePath => {
*/
const dominatorTrees = [];
/**
* The i^th HeapSnapshot in this array is the snapshot used to generate the i^th
* dominator tree in `dominatorTrees` above. This lets us map from a dominator
* tree id to the snapshot it came from.
*/
const dominatorTreeSnapshots = [];
/**
* @see HeapAnalysesClient.prototype.computeDominatorTree
*/
@ -114,6 +121,7 @@ workerHelper.createTask(self, "computeDominatorTree", snapshotFilePath => {
const id = dominatorTrees.length;
dominatorTrees.push(snapshot.computeDominatorTree());
dominatorTreeSnapshots.push(snapshot);
return id;
});
@ -123,6 +131,7 @@ workerHelper.createTask(self, "computeDominatorTree", snapshotFilePath => {
workerHelper.createTask(self, "getDominatorTree", request => {
const {
dominatorTreeId,
breakdown,
maxDepth,
maxSiblings
} = request;
@ -132,7 +141,12 @@ workerHelper.createTask(self, "getDominatorTree", request => {
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
}
return DominatorTreeNode.partialTraversal(dominatorTrees[dominatorTreeId],
const dominatorTree = dominatorTrees[dominatorTreeId];
const snapshot = dominatorTreeSnapshots[dominatorTreeId];
return DominatorTreeNode.partialTraversal(dominatorTree,
snapshot,
breakdown,
maxDepth,
maxSiblings);
});
@ -144,6 +158,7 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
const {
dominatorTreeId,
nodeId,
breakdown,
startIndex,
maxCount
} = request;
@ -154,6 +169,8 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
}
const dominatorTree = dominatorTrees[dominatorTreeId];
const snapshot = dominatorTreeSnapshots[dominatorTreeId];
const childIds = dominatorTree.getImmediatelyDominated(nodeId);
if (!childIds) {
throw new Error(`${nodeId} is not a node id in the dominator tree`);
@ -166,8 +183,10 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
const nodes = childIds
.slice(start, end)
.map(id => {
const size = dominatorTree.getRetainedSize(id);
const node = new DominatorTreeNode(id, size);
const { label, shallowSize } =
DominatorTreeNode.getLabelAndShallowSize(id, snapshot, breakdown);
const retainedSize = dominatorTree.getRetainedSize(id);
const node = new DominatorTreeNode(id, label, shallowSize, retainedSize);
node.parentId = nodeId;
// DominatorTree.getImmediatelyDominated will always return non-null here
// because we got the id directly from the dominator tree.

View File

@ -522,6 +522,43 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
}
}
void
HeapSnapshot::DescribeNode(JSContext* cx, JS::HandleObject breakdown, uint64_t nodeId,
JS::MutableHandleValue rval, ErrorResult& rv) {
MOZ_ASSERT(breakdown);
JS::RootedValue breakdownVal(cx, JS::ObjectValue(*breakdown));
JS::ubi::CountTypePtr rootType = JS::ubi::ParseBreakdown(cx, breakdownVal);
if (NS_WARN_IF(!rootType)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JS::ubi::RootedCount rootCount(cx, rootType->makeCount());
if (NS_WARN_IF(!rootCount)) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
JS::ubi::Node::Id id(nodeId);
Maybe<JS::ubi::Node> node = getNodeById(id);
if (NS_WARN_IF(node.isNothing())) {
rv.Throw(NS_ERROR_INVALID_ARG);
return;
}
MallocSizeOf mallocSizeOf = GetCurrentThreadDebuggerMallocSizeOf();
if (NS_WARN_IF(!rootCount->count(mallocSizeOf, *node))) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
if (NS_WARN_IF(!rootCount->report(cx, rval))) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
}
already_AddRefed<DominatorTree>
HeapSnapshot::ComputeDominatorTree(ErrorResult& rv)
{

View File

@ -159,6 +159,9 @@ public:
void TakeCensus(JSContext* cx, JS::HandleObject options,
JS::MutableHandleValue rval, ErrorResult& rv);
void DescribeNode(JSContext* cx, JS::HandleObject breakdown, uint64_t nodeId,
JS::MutableHandleValue rval, ErrorResult& rv);
already_AddRefed<DominatorTree> ComputeDominatorTree(ErrorResult& rv);
dom::Nullable<uint64_t> GetCreationTime() {

View File

@ -22,6 +22,9 @@ const HeapAnalysesClient =
const Services = require("Services");
const { censusReportToCensusTreeNode } = require("devtools/shared/heapsnapshot/census-tree-node");
const CensusUtils = require("devtools/shared/heapsnapshot/CensusUtils");
const DominatorTreeNode = require("devtools/shared/heapsnapshot/DominatorTreeNode");
const { LabelAndShallowSizeVisitor } = DominatorTreeNode;
// Always log packets when running tests. runxpcshelltests.py will throw
// the output away anyway, unless you give it the --verbose flag.
@ -296,3 +299,29 @@ function assertDiff(breakdown, first, second, expected) {
assertStructurallyEquivalent(actual, expected);
}
/**
* Assert that creating a label and getting a shallow size from the given node
* description with the specified breakdown is as expected.
*
* @param {Object} breakdown
* @param {Object} givenDescription
* @param {Number} expectedShallowSize
* @param {Object} expectedLabel
*/
function assertLabelAndShallowSize(breakdown, givenDescription, expectedShallowSize, expectedLabel) {
dumpn("Computing label and shallow size from node description:");
dumpn("Breakdown: " + JSON.stringify(breakdown, null, 4));
dumpn("Given description: " + JSON.stringify(givenDescription, null, 4));
const visitor = new LabelAndShallowSizeVisitor();
CensusUtils.walk(breakdown, description, visitor);
dumpn("Expected shallow size: " + expectedShallowSize);
dumpn("Actual shallow size: " + visitor.shallowSize());
equal(visitor.shallowSize(), expectedShallowSize, "Shallow size should be correct");
dumpn("Expected label: " + JSON.stringify(expectedLabel, null, 4));
dumpn("Actual label: " + JSON.stringify(visitor.label(), null, 4));
assertStructurallyEquivalent(visitor.label(), expectedLabel);
}

View File

@ -0,0 +1,46 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can generate label structures from node description reports.
const breakdown = {
by: "coarseType",
objects: {
by: "objectClass",
then: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
},
strings: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
scripts: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
other: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
objects: {
Function: { count: 1, bytes: 32 },
other: { count: 0, bytes: 0 }
},
strings: {},
scripts: {},
other: {}
};
const expected = [
"objects",
"Function"
];
const shallowSize = 32;
function run_test() {
assertLabelAndShallowSize(breakdown, description, shallowSize, expected);
}

View File

@ -0,0 +1,45 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can generate label structures from node description reports.
const breakdown = {
by: "coarseType",
objects: {
by: "objectClass",
then: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
},
strings: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
scripts: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
other: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
objects: {
other: { count: 1, bytes: 10 }
},
strings: {},
scripts: {},
other: {}
};
const expected = [
"objects",
"other"
];
const shallowSize = 10;
function run_test() {
assertLabelAndShallowSize(breakdown, description, shallowSize, expected);
}

View File

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can generate label structures from node description reports.
const breakdown = {
by: "coarseType",
objects: {
by: "objectClass",
then: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
},
strings: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
scripts: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
other: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
};
const description = {
objects: {
other: { count: 0, bytes: 0 }
},
strings: {
"JSString": { count: 1, bytes: 42 },
},
scripts: {},
other: {}
};
const expected = [
"strings",
"JSString"
];
const shallowSize = 42;
function run_test() {
assertLabelAndShallowSize(breakdown, description, shallowSize, expected);
}

View File

@ -0,0 +1,53 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can generate label structures from node description reports.
const breakdown = {
by: "coarseType",
objects: {
by: "objectClass",
then: {
by: "allocationStack",
then: { by: "count", count: true, bytes: true },
noStack: { by: "count", count: true, bytes: true },
},
other: { by: "count", count: true, bytes: true },
},
strings: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
scripts: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
other: {
by: "internalType",
then: { by: "count", count: true, bytes: true },
},
};
const stack = saveStack();
const description = {
objects: {
Array: new Map([[stack, { count: 1, bytes: 512 }]]),
other: { count: 0, bytes: 0 }
},
strings: {},
scripts: {},
other: {}
};
const expected = [
"objects",
"Array",
stack
];
const shallowSize = 512;
function run_test() {
assertLabelAndShallowSize(breakdown, description, shallowSize, expected);
}

View File

@ -7,6 +7,14 @@ function run_test() {
run_next_test();
}
const breakdown = {
by: "coarseType",
objects: { by: "count", count: true, bytes: true },
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
};
add_task(function* () {
const client = new HeapAnalysesClient();
@ -18,7 +26,10 @@ add_task(function* () {
equal(typeof dominatorTreeId, "number",
"should get a dominator tree id, and it should be a number");
const partialTree = yield client.getDominatorTree({ dominatorTreeId });
const partialTree = yield client.getDominatorTree({
dominatorTreeId,
breakdown
});
ok(partialTree, "Should get a partial tree");
equal(typeof partialTree, "object",
"partialTree should be an object");

View File

@ -8,12 +8,20 @@ function run_test() {
run_next_test();
}
const breakdown = {
by: "coarseType",
objects: { by: "count", count: true, bytes: true },
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
};
add_task(function* () {
const client = new HeapAnalysesClient();
let threw = false;
try {
yield client.getDominatorTree({ dominatorTreeId: 42 });
yield client.getDominatorTree({ dominatorTreeId: 42, breakdown });
} catch (_) {
threw = true;
}

View File

@ -7,6 +7,14 @@ function run_test() {
run_next_test();
}
const breakdown = {
by: "coarseType",
objects: { by: "count", count: true, bytes: true },
scripts: { by: "count", count: true, bytes: true },
strings: { by: "count", count: true, bytes: true },
other: { by: "count", count: true, bytes: true },
};
add_task(function* () {
const client = new HeapAnalysesClient();
@ -14,13 +22,17 @@ add_task(function* () {
yield client.readHeapSnapshot(snapshotFilePath);
const dominatorTreeId = yield client.computeDominatorTree(snapshotFilePath);
const partialTree = yield client.getDominatorTree({ dominatorTreeId });
const partialTree = yield client.getDominatorTree({
dominatorTreeId,
breakdown
});
ok(partialTree.children.length > 0,
"root should immediately dominate some nodes");
// First, test getting a subset of children available.
const response = yield client.getImmediatelyDominated({
dominatorTreeId,
breakdown,
nodeId: partialTree.nodeId,
startIndex: 0,
maxCount: partialTree.children.length - 1
@ -33,6 +45,7 @@ add_task(function* () {
// Next, test getting a subset of children available.
const secondResponse = yield client.getImmediatelyDominated({
dominatorTreeId,
breakdown,
nodeId: partialTree.nodeId,
startIndex: 0,
maxCount: Infinity

View File

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that we can describe nodes with a breakdown.
function run_test() {
const path = saveNewHeapSnapshot();
const snapshot = ChromeUtils.readHeapSnapshot(path);
ok(snapshot.describeNode);
equal(typeof snapshot.describeNode, "function");
const dt = snapshot.computeDominatorTree();
let threw = false;
try {
snapshot.describeNode(undefined, dt.root);
} catch (_) {
threw = true;
}
ok(threw, "Should require a breakdown");
const breakdown = {
by: "coarseType",
objects: { by: "objectClass" },
scripts: { by: "internalType" },
strings: { by: "internalType" },
other: { by: "internalType" }
};
threw = false;
try {
snapshot.describeNode(breakdown, 0);
} catch (_) {
threw = true;
}
ok(threw, "Should throw when given an invalid node id");
const description = snapshot.describeNode(breakdown, dt.root);
ok(description);
ok(description.other);
ok(description.other["JS::ubi::RootList"]);
}

View File

@ -33,6 +33,10 @@ support-files =
[test_DominatorTree_03.js]
[test_DominatorTree_04.js]
[test_DominatorTree_05.js]
[test_DominatorTreeNode_LabelAndShallowSize_01.js]
[test_DominatorTreeNode_LabelAndShallowSize_02.js]
[test_DominatorTreeNode_LabelAndShallowSize_03.js]
[test_DominatorTreeNode_LabelAndShallowSize_04.js]
[test_HeapAnalyses_computeDominatorTree_01.js]
[test_HeapAnalyses_computeDominatorTree_02.js]
[test_HeapAnalyses_getCreationTime_01.js]
@ -51,6 +55,7 @@ support-files =
[test_HeapAnalyses_takeCensus_07.js]
[test_HeapSnapshot_creationTime_01.js]
[test_HeapSnapshot_deepStack_01.js]
[test_HeapSnapshot_describeNode_01.js]
[test_HeapSnapshot_takeCensus_01.js]
[test_HeapSnapshot_takeCensus_02.js]
[test_HeapSnapshot_takeCensus_03.js]

View File

@ -12,7 +12,6 @@ support-files =
file_use_counter_svg_fill_pattern_data.svg
[browser_bug593387.js]
skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.iframe.addEventListener)
[browser_bug902350.js]
tags = mcb
[browser_messagemanager_loadprocessscript.js]

View File

@ -6,6 +6,8 @@
#include "WebGL2Context.h"
#include "GLContext.h"
#include "WebGLQuery.h"
#include "gfxPrefs.h"
#include "nsThreadUtils.h"
namespace mozilla {
@ -255,6 +257,7 @@ WebGL2Context::EndQuery(GLenum target)
}
UpdateBoundQuery(target, nullptr);
NS_DispatchToCurrentThread(new WebGLQuery::AvailableRunnable(activeQuery));
}
already_AddRefed<WebGLQuery>
@ -325,6 +328,11 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
return;
}
// We must wait for an event loop before the query can be available
if (!query->mCanBeAvailable && !gfxPrefs::WebGLImmediateQueries()) {
return;
}
MakeContextCurrent();
GLuint returned = 0;
switch (pname) {

View File

@ -785,7 +785,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
// GLES 3.0.4, p147, table 3.19
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
#if ALLOW_ES3_FORMATS
// Note that all compressed texture formats are filterable:
// GLES 3.0.4 p161:
// "[A] texture is complete unless any of the following conditions hold true:
@ -805,7 +805,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_RG11_EAC ), false, true);
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), false, true);
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), false, true);
#endif
#undef FOO
// GLES 3.0.4, p206, "Required Renderbuffer Formats":

View File

@ -20,6 +20,7 @@ WebGLQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
WebGLQuery::WebGLQuery(WebGLContext* webgl)
: WebGLContextBoundObject(webgl)
, mCanBeAvailable(false)
, mGLName(0)
, mType(0)
{

View File

@ -10,6 +10,7 @@
#include "nsWrapperCache.h"
#include "WebGLObjectModel.h"
#include "nsThreadUtils.h"
namespace mozilla {
@ -22,6 +23,19 @@ class WebGLQuery final
public:
explicit WebGLQuery(WebGLContext* webgl);
class AvailableRunnable final : public nsRunnable
{
public:
explicit AvailableRunnable(WebGLQuery* query) : mQuery(query) { }
NS_IMETHOD Run() override {
mQuery->mCanBeAvailable = true;
return NS_OK;
}
private:
const RefPtr<WebGLQuery> mQuery;
};
bool IsActive() const;
bool HasEverBeenActive() const {
@ -42,6 +56,8 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQuery)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQuery)
// Track whether the event loop has spun
bool mCanBeAvailable;
private:
~WebGLQuery() {

View File

@ -14401,12 +14401,7 @@ ctx.moveTo(50, 25);
ctx.bezierCurveTo(50, 25, 50, 25, 50, 25);
ctx.stroke();
if (IsAzureSkia()) {
isPixel(ctx, 50,25, 0,255,0,255, 0);
} else {
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
}
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
}
</script>
@ -14438,11 +14433,7 @@ ctx.moveTo(50, 25);
ctx.lineTo(50, 25);
ctx.stroke();
if (IsAzureSkia()) {
isPixel(ctx, 50,25, 0,255,0,255, 0);
} else {
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
}
todo_isPixel(ctx, 50,25, 0,255,0,255, 0);
}
</script>

View File

@ -271,6 +271,13 @@ DeviceStorageStatics::DumpDirs()
nullptr
};
const char* ptStr;
if (XRE_IsParentProcess()) {
ptStr = "parent";
} else {
ptStr = "child";
}
for (uint32_t i = 0; i < TYPE_COUNT; ++i) {
MOZ_ASSERT(storageTypes[i]);
@ -278,8 +285,8 @@ DeviceStorageStatics::DumpDirs()
if (mDirs[i]) {
mDirs[i]->GetPath(path);
}
DS_LOG_INFO("%s: '%s'",
storageTypes[i], NS_LossyConvertUTF16toASCII(path).get());
DS_LOG_INFO("(%s) %s: '%s'",
ptStr, storageTypes[i], NS_LossyConvertUTF16toASCII(path).get());
}
#endif
}
@ -297,6 +304,47 @@ DeviceStorageStatics::Shutdown()
Preferences::RemoveObserver(this, kPrefWritableName);
}
/* static */ void
DeviceStorageStatics::GetDeviceStorageAreasForIPC(
DeviceStorageAreaInfo& aAreaInfo)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
InitializeDirs();
GetDirPath(TYPE_APPS, aAreaInfo.apps());
GetDirPath(TYPE_CRASHES, aAreaInfo.crashes());
GetDirPath(TYPE_PICTURES, aAreaInfo.pictures());
GetDirPath(TYPE_VIDEOS, aAreaInfo.videos());
GetDirPath(TYPE_MUSIC, aAreaInfo.music());
GetDirPath(TYPE_SDCARD, aAreaInfo.sdcard());
}
/* static */ void
DeviceStorageStatics::RecvDeviceStorageAreasFromParent(
const DeviceStorageAreaInfo& aAreaInfo)
{
if (XRE_IsParentProcess()) {
// We are the parent. Therefore our info is already correct.
return;
}
StaticMutexAutoLock lock(sMutex);
if (NS_WARN_IF(!sInstance)) {
return;
}
NS_NewLocalFile(aAreaInfo.apps(), true, getter_AddRefs(sInstance->mDirs[TYPE_APPS]));
NS_NewLocalFile(aAreaInfo.crashes(), true, getter_AddRefs(sInstance->mDirs[TYPE_CRASHES]));
NS_NewLocalFile(aAreaInfo.pictures(), true, getter_AddRefs(sInstance->mDirs[TYPE_PICTURES]));
NS_NewLocalFile(aAreaInfo.videos(), true, getter_AddRefs(sInstance->mDirs[TYPE_VIDEOS]));
NS_NewLocalFile(aAreaInfo.music(), true, getter_AddRefs(sInstance->mDirs[TYPE_MUSIC]));
NS_NewLocalFile(aAreaInfo.sdcard(), true, getter_AddRefs(sInstance->mDirs[TYPE_SDCARD]));
sInstance->mInitialized = true;
}
/* static */ already_AddRefed<nsIFile>
DeviceStorageStatics::GetDir(DeviceStorageType aType)
{
@ -332,6 +380,16 @@ DeviceStorageStatics::GetDir(DeviceStorageType aType)
return file.forget();
}
/* static */ void
DeviceStorageStatics::GetDirPath(DeviceStorageType aType, nsString& aDirPath)
{
aDirPath.Truncate();
nsCOMPtr<nsIFile> file = GetDir(aType);
if (file) {
file->GetPath(aDirPath);
}
}
/* static */ bool
DeviceStorageStatics::HasOverrideRootDir()
{

View File

@ -8,7 +8,12 @@
#define mozilla_dom_devicestorage_DeviceStorageStatics_h
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "nsArrayUtils.h"
class nsString;
class nsDOMDeviceStorage;
class DeviceStorageFile;
#ifdef MOZ_WIDGET_GONK
@ -35,6 +40,9 @@ public:
static void GetWritableName(nsString& aName);
static void SetWritableName(const nsAString& aName);
static void GetDeviceStorageAreasForIPC(DeviceStorageAreaInfo& aAreaInfo);
static void RecvDeviceStorageAreasFromParent(const DeviceStorageAreaInfo& aAreaInfo);
static bool HasOverrideRootDir();
static already_AddRefed<nsIFile> GetAppsDir();
static already_AddRefed<nsIFile> GetCrashesDir();
@ -56,6 +64,7 @@ private:
};
static already_AddRefed<nsIFile> GetDir(DeviceStorageType aType);
static void GetDirPath(DeviceStorageType aType, nsString& aString);
DeviceStorageStatics();
virtual ~DeviceStorageStatics();

View File

@ -1883,6 +1883,11 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
aGraph = MediaStreamGraph::GetInstance(graphDriverType, mAudioChannel);
}
if (!mOutputStreams.IsEmpty() &&
aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) {
return nullptr;
}
OutputMediaStream* out = mOutputStreams.AppendElement();
out->mStream = DOMMediaStream::CreateTrackUnionStream(window, aGraph);
RefPtr<nsIPrincipal> principal = GetCurrentPrincipal();

View File

@ -17,6 +17,7 @@
#include "BlobChild.h"
#include "CrashReporterChild.h"
#include "GeckoProfiler.h"
#include "DeviceStorageStatics.h"
#include "TabChild.h"
#include "HandlerServiceChild.h"
@ -2594,6 +2595,15 @@ ContentChild::RecvVolumes(nsTArray<VolumeInfo>&& aVolumes)
return true;
}
bool
ContentChild::RecvDeviceStorageAreas(const DeviceStorageAreaInfo& areaInfo)
{
#if !defined(MOZ_WIDGET_GONK)
DeviceStorageStatics::RecvDeviceStorageAreasFromParent(areaInfo);
#endif
return true;
}
bool
ContentChild::RecvFilePathUpdate(const nsString& aStorageType,
const nsString& aStorageName,

View File

@ -383,6 +383,7 @@ public:
virtual bool RecvLastPrivateDocShellDestroyed() override;
virtual bool RecvVolumes(InfallibleTArray<VolumeInfo>&& aVolumes) override;
virtual bool RecvDeviceStorageAreas(const DeviceStorageAreaInfo& areaInfo) override;
virtual bool RecvFilePathUpdate(const nsString& aStorageType,
const nsString& aStorageName,
const nsString& aPath,

View File

@ -30,6 +30,7 @@
#include "AudioChannelService.h"
#include "BlobParent.h"
#include "CrashReporterParent.h"
#include "DeviceStorageStatics.h"
#include "GMPServiceParent.h"
#include "HandlerServiceParent.h"
#include "IHistory.h"
@ -1606,6 +1607,10 @@ ContentParent::ForwardKnownInfo()
vs->GetVolumesForIPC(&volumeInfo);
Unused << SendVolumes(volumeInfo);
}
#else
DeviceStorageAreaInfo areaInfo;
DeviceStorageStatics::GetDeviceStorageAreasForIPC(areaInfo);
Unused << SendDeviceStorageAreas(areaInfo);
#endif /* MOZ_WIDGET_GONK */
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =

View File

@ -364,6 +364,15 @@ struct VolumeInfo {
bool isHotSwappable;
};
struct DeviceStorageAreaInfo {
nsString music;
nsString pictures;
nsString videos;
nsString sdcard;
nsString apps;
nsString crashes;
};
struct ClipboardCapabilities {
bool supportsSelectionClipboard;
bool supportsFindClipboard;
@ -595,6 +604,8 @@ child:
Volumes(VolumeInfo[] volumes);
DeviceStorageAreas(DeviceStorageAreaInfo areaInfo);
FlushMemory(nsString reason);
GarbageCollect();

View File

@ -57,6 +57,7 @@ void GraphDriver::SetGraphTime(GraphDriver* aPreviousDriver,
GraphTime aLastSwitchNextIterationStart,
GraphTime aLastSwitchNextIterationEnd)
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
// We set mIterationEnd here, because the first thing a driver do when it
// does an iteration is to update graph times, so we are in fact setting
// mIterationStart of the next iteration by setting the end of the previous
@ -64,13 +65,14 @@ void GraphDriver::SetGraphTime(GraphDriver* aPreviousDriver,
mIterationStart = aLastSwitchNextIterationStart;
mIterationEnd = aLastSwitchNextIterationEnd;
STREAM_LOG(LogLevel::Debug, ("Setting previous driver: %p (%s)", aPreviousDriver, aPreviousDriver->AsAudioCallbackDriver() ? "AudioCallbackDriver" : "SystemClockDriver"));
MOZ_ASSERT(!mPreviousDriver);
mPreviousDriver = aPreviousDriver;
STREAM_LOG(LogLevel::Debug, ("Setting previous driver: %p (%s)", PreviousDriver(), PreviousDriver()->AsAudioCallbackDriver() ? "AudioCallbackDriver" : "SystemClockDriver"));
MOZ_ASSERT(!PreviousDriver());
SetPreviousDriver(aPreviousDriver);
}
void GraphDriver::SwitchAtNextIteration(GraphDriver* aNextDriver)
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
// This is the situation where `mPreviousDriver` is an AudioCallbackDriver
// that is switching device, and the graph has found the current driver is not
// an AudioCallbackDriver, but tries to switch to a _new_ AudioCallbackDriver
@ -78,23 +80,15 @@ void GraphDriver::SwitchAtNextIteration(GraphDriver* aNextDriver)
// request to switch, since we know we will switch back to the old
// AudioCallbackDriver when it has recovered from the device switching.
if (aNextDriver->AsAudioCallbackDriver() &&
mPreviousDriver &&
mPreviousDriver->AsAudioCallbackDriver()->IsSwitchingDevice() &&
mPreviousDriver != aNextDriver) {
PreviousDriver() &&
PreviousDriver()->AsAudioCallbackDriver()->IsSwitchingDevice() &&
PreviousDriver() != aNextDriver) {
return;
}
LIFECYCLE_LOG("Switching to new driver: %p (%s)",
aNextDriver, aNextDriver->AsAudioCallbackDriver() ?
"AudioCallbackDriver" : "SystemClockDriver");
mNextDriver = aNextDriver;
}
void GraphDriver::EnsureImmediateWakeUpLocked()
{
mGraphImpl->GetMonitor().AssertCurrentThreadOwns();
mWaitState = WAITSTATE_WAKING_UP;
mGraphImpl->mGraphDriverAsleep = false; // atomic
mGraphImpl->GetMonitor().Notify();
SetNextDriver(aNextDriver);
}
GraphTime
@ -151,6 +145,36 @@ void GraphDriver::Shutdown()
}
}
bool GraphDriver::Switching()
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
return mNextDriver || mPreviousDriver;
}
GraphDriver* GraphDriver::NextDriver()
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
return mNextDriver;
}
GraphDriver* GraphDriver::PreviousDriver()
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
return mPreviousDriver;
}
void GraphDriver::SetNextDriver(GraphDriver* aNextDriver)
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
mNextDriver = aNextDriver;
}
void GraphDriver::SetPreviousDriver(GraphDriver* aPreviousDriver)
{
GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
mPreviousDriver = aPreviousDriver;
}
ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
: GraphDriver(aGraphImpl)
{ }
@ -174,20 +198,28 @@ public:
profiler_register_thread("MediaStreamGraph", &aLocal);
LIFECYCLE_LOG("Starting a new system driver for graph %p\n",
mDriver->mGraphImpl);
if (mDriver->mPreviousDriver) {
GraphDriver* previousDriver = nullptr;
{
MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
previousDriver = mDriver->PreviousDriver();
}
if (previousDriver) {
LIFECYCLE_LOG("%p releasing an AudioCallbackDriver(%p), for graph %p\n",
mDriver,
mDriver->mPreviousDriver.get(),
previousDriver,
mDriver->GraphImpl());
MOZ_ASSERT(!mDriver->AsAudioCallbackDriver());
// Stop and release the previous driver off-main-thread, but only if we're
// not in the situation where we've fallen back to a system clock driver
// because the osx audio stack is currently switching output device.
if (!mDriver->mPreviousDriver->AsAudioCallbackDriver()->IsSwitchingDevice()) {
if (!previousDriver->AsAudioCallbackDriver()->IsSwitchingDevice()) {
RefPtr<AsyncCubebTask> releaseEvent =
new AsyncCubebTask(mDriver->mPreviousDriver->AsAudioCallbackDriver(), AsyncCubebOperation::SHUTDOWN);
mDriver->mPreviousDriver = nullptr;
new AsyncCubebTask(previousDriver->AsAudioCallbackDriver(), AsyncCubebOperation::SHUTDOWN);
releaseEvent->Dispatch();
MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
mDriver->SetPreviousDriver(nullptr);
}
} else {
MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
@ -228,10 +260,10 @@ ThreadedDriver::Revive()
// If we were switching, switch now. Otherwise, tell thread to run the main
// loop again.
MonitorAutoLock mon(mGraphImpl->GetMonitor());
if (mNextDriver) {
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
mNextDriver->Start();
if (NextDriver()) {
NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(NextDriver());
NextDriver()->Start();
} else {
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
mThread->Dispatch(event, NS_DISPATCH_NORMAL);
@ -302,11 +334,12 @@ ThreadedDriver::RunThread()
stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime);
if (mNextDriver && stillProcessing) {
MonitorAutoLock lock(GraphImpl()->GetMonitor());
if (NextDriver() && stillProcessing) {
STREAM_LOG(LogLevel::Debug, ("Switching to AudioCallbackDriver"));
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
mNextDriver->Start();
NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(NextDriver());
NextDriver()->Start();
return;
}
}
@ -373,8 +406,7 @@ SystemClockDriver::WaitForNextIteration()
mGraphImpl->mNeedAnotherIteration = false;
}
void
SystemClockDriver::WakeUp()
void SystemClockDriver::WakeUp()
{
mGraphImpl->GetMonitor().AssertCurrentThreadOwns();
mWaitState = WAITSTATE_WAKING_UP;
@ -509,7 +541,6 @@ AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl)
, mStarted(false)
, mAudioChannel(aGraphImpl->AudioChannel())
, mInCallback(false)
, mPauseRequested(false)
, mMicrophoneActive(false)
#ifdef XP_MACOSX
, mCallbackReceivedWhileSwitching(0)
@ -568,12 +599,13 @@ AudioCallbackDriver::Init()
} else {
NS_WARNING("Could not create a cubeb stream for MediaStreamGraph, falling back to a SystemClockDriver");
// Fall back to a driver using a normal thread.
mNextDriver = new SystemClockDriver(GraphImpl());
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
MonitorAutoLock lock(GraphImpl()->GetMonitor());
SetNextDriver(new SystemClockDriver(GraphImpl()));
NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(NextDriver());
DebugOnly<bool> found = mGraphImpl->RemoveMixerCallback(this);
NS_WARN_IF_FALSE(!found, "Mixer callback not added when switching?");
mNextDriver->Start();
NextDriver()->Start();
return;
}
@ -614,18 +646,23 @@ AudioCallbackDriver::Start()
initEvent->Dispatch();
} else {
STREAM_LOG(LogLevel::Debug, ("Starting audio threads for MediaStreamGraph %p from the previous driver's thread", mGraphImpl));
Init();
{
MonitorAutoUnlock mon(GraphImpl()->GetMonitor());
Init();
}
// Check if we need to resolve promises because the driver just got switched
// because of a resuming AudioContext
if (!mPromisesForOperation.IsEmpty()) {
// CompleteAudioContextOperations takes the lock as needed
MonitorAutoUnlock mon(GraphImpl()->GetMonitor());
CompleteAudioContextOperations(AsyncCubebOperation::INIT);
}
if (mPreviousDriver) {
if (PreviousDriver()) {
nsCOMPtr<nsIRunnable> event =
new MediaStreamGraphShutdownThreadRunnable(mPreviousDriver);
mPreviousDriver = nullptr;
new MediaStreamGraphShutdownThreadRunnable(PreviousDriver());
SetPreviousDriver(nullptr);
NS_DispatchToMainThread(event);
}
}
@ -661,10 +698,10 @@ AudioCallbackDriver::Revive()
STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver reviving."));
// If we were switching, switch now. Otherwise, start the audio thread again.
MonitorAutoLock mon(mGraphImpl->GetMonitor());
if (mNextDriver) {
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
mNextDriver->Start();
if (NextDriver()) {
NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(NextDriver());
NextDriver()->Start();
} else {
STREAM_LOG(LogLevel::Debug, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl));
RefPtr<AsyncCubebTask> initEvent =
@ -743,7 +780,7 @@ AudioCallbackDriver::OSXDeviceSwitchingWorkaround()
// the self reference and unref the SystemClockDriver we fallen back on.
if (GraphImpl()->CurrentDriver() == this) {
mSelfReference.Drop(this);
mNextDriver = nullptr;
SetNextDriver(nullptr);
} else {
GraphImpl()->CurrentDriver()->SwitchAtNextIteration(this);
}
@ -761,11 +798,6 @@ AudioCallbackDriver::DataCallback(AudioDataValue* aBuffer, long aFrames)
{
bool stillProcessing;
if (mPauseRequested) {
PodZero(aBuffer, aFrames * mGraphImpl->AudioChannelCount());
return aFrames;
}
#ifdef XP_MACOSX
if (OSXDeviceSwitchingWorkaround()) {
PodZero(aBuffer, aFrames * mGraphImpl->AudioChannelCount());
@ -853,19 +885,23 @@ AudioCallbackDriver::DataCallback(AudioDataValue* aBuffer, long aFrames)
mBuffer.BufferFilled();
if (mNextDriver && stillProcessing) {
{
// If the audio stream has not been started by the previous driver or
// the graph itself, keep it alive.
MonitorAutoLock mon(mGraphImpl->GetMonitor());
if (!IsStarted()) {
return aFrames;
}
bool switching = false;
{
MonitorAutoLock mon(mGraphImpl->GetMonitor());
switching = !!NextDriver();
}
if (switching && stillProcessing) {
// If the audio stream has not been started by the previous driver or
// the graph itself, keep it alive.
MonitorAutoLock mon(mGraphImpl->GetMonitor());
if (!IsStarted()) {
return aFrames;
}
STREAM_LOG(LogLevel::Debug, ("Switching to system driver."));
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
mNextDriver->Start();
NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(NextDriver());
NextDriver()->Start();
// Returning less than aFrames starts the draining and eventually stops the
// audio thread. This function will never get called again.
return aFrames - 1;
@ -968,7 +1004,7 @@ AudioCallbackDriver::DeviceChangedCallback() {
STREAM_LOG(LogLevel::Error, ("Switching to SystemClockDriver during output switch"));
mSelfReference.Take(this);
mCallbackReceivedWhileSwitching = 0;
mNextDriver = new SystemClockDriver(GraphImpl());
SetNextDriver(new SystemClockDriver(GraphImpl()));
mNextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(mNextDriver);
mNextDriver->Start();

View File

@ -61,6 +61,46 @@ class OfflineClockDriver;
* OfflineClockDriver, if the graph is offline, or a SystemClockDriver, if the
* graph is real time.
* A MediaStreamGraph holds an owning reference to its driver.
*
* The lifetime of drivers is a complicated affair. Here are the different
* scenarii that can happen:
*
* Starting a MediaStreamGraph with an AudioCallbackDriver
* - A new thread T is created, from the main thread.
* - On this thread T, cubeb is initialized if needed, and a cubeb_stream is
* created and started
* - The thread T posts a message to the main thread to terminate itself.
* - The graph runs off the audio thread
*
* Starting a MediaStreamGraph with a SystemClockDriver:
* - A new thread T is created from the main thread.
* - The graph runs off this thread.
*
* Switching from a SystemClockDriver to an AudioCallbackDriver:
* - A new AudioCallabackDriver is created and initialized on the graph thread
* - At the end of the MSG iteration, the SystemClockDriver transfers its timing
* info and a reference to itself to the AudioCallbackDriver. It then starts
* the AudioCallbackDriver.
* - When the AudioCallbackDriver starts, it checks if it has been switched from
* a SystemClockDriver, and if that is the case, sends a message to the main
* thread to shut the SystemClockDriver thread down.
* - The graph now runs off an audio callback
*
* Switching from an AudioCallbackDriver to a SystemClockDriver:
* - A new SystemClockDriver is created, and set as mNextDriver.
* - At the end of the MSG iteration, the AudioCallbackDriver transfers its
* timing info and a reference to itself to the SystemClockDriver. A new
* SystemClockDriver is started from the current audio thread.
* - When starting, the SystemClockDriver checks if it has been switched from an
* AudioCallbackDriver. If yes, it creates a new temporary thread to release
* the cubeb_streams. This temporary thread closes the cubeb_stream, and
* then dispatches a message to the main thread to be terminated.
* - The graph now runs off a normal thread.
*
* Two drivers cannot run at the same time for the same graph. The thread safety
* of the different attributes of drivers, and they access pattern is documented
* next to the members themselves.
*
*/
class GraphDriver
{
@ -92,14 +132,14 @@ public:
virtual uint32_t IterationDuration() = 0;
/* Return whether we are switching or not. */
bool Switching() {
return mNextDriver || mPreviousDriver;
}
bool Switching();
GraphDriver* NextDriver()
{
return mNextDriver;
}
// Those are simply or setting the associated pointer, but assert that the
// lock is held.
GraphDriver* NextDriver();
GraphDriver* PreviousDriver();
void SetNextDriver(GraphDriver* aNextDriver);
void SetPreviousDriver(GraphDriver* aPreviousDriver);
/**
* If we are running a real time graph, get the current time stamp to schedule
@ -109,19 +149,6 @@ public:
return mCurrentTimeStamp;
}
bool IsWaiting() {
return mWaitState == WAITSTATE_WAITING_INDEFINITELY ||
mWaitState == WAITSTATE_WAITING_FOR_NEXT_ITERATION;
}
bool IsWaitingIndefinitly() {
return mWaitState == WAITSTATE_WAITING_INDEFINITELY;
}
GraphTime IterationStart() {
return mIterationStart;
}
GraphTime IterationEnd() {
return mIterationEnd;
}
@ -151,13 +178,6 @@ public:
void SetGraphTime(GraphDriver* aPreviousDriver,
GraphTime aLastSwitchNextIterationStart,
GraphTime aLastSwitchNextIterationEnd);
/**
* Call this to indicate that another iteration of the control loop is
* required immediately. The monitor must already be held.
*/
void EnsureImmediateWakeUpLocked();
/**
* Call this to indicate that another iteration of the control loop is
* required on its regular schedule. The monitor must not be held.
@ -179,12 +199,15 @@ public:
protected:
GraphTime StateComputedTime() const;
// Time of the start of this graph iteration.
// Time of the start of this graph iteration. This must be accessed while
// having the monitor.
GraphTime mIterationStart;
// Time of the end of this graph iteration.
// Time of the end of this graph iteration. This must be accessed while having
// the monitor.
GraphTime mIterationEnd;
// The MediaStreamGraphImpl that owns this driver. This has a lifetime longer
// than the driver, and will never be null.
// than the driver, and will never be null. Hence, it can be accesed without
// monitor.
MediaStreamGraphImpl* mGraphImpl;
// This enum specifies the wait state of the driver.
@ -200,15 +223,26 @@ protected:
// but it hasn't done so yet
WAITSTATE_WAKING_UP
};
// This must be access with the monitor.
WaitState mWaitState;
// This is used on the main thread (during initialization), and the graph
// thread. No monitor needed because we know the graph thread does not run
// during the initialization.
TimeStamp mCurrentTimeStamp;
// This is non-null only when this driver has recently switched from an other
// driver, and has not cleaned it up yet (for example because the audio stream
// is currently calling the callback during initialization).
//
// This is written to when changing driver, from the previous driver's thread,
// or a thread created for the occasion. This is read each time we need to
// check whether we're changing driver (in Switching()), from the graph
// thread.
// This must be accessed using the {Set,Get}PreviousDriver methods.
RefPtr<GraphDriver> mPreviousDriver;
// This is non-null only when this driver is going to switch to an other
// driver at the end of this iteration.
// This must be accessed using the {Set,Get}NextDriver methods.
RefPtr<GraphDriver> mNextDriver;
virtual ~GraphDriver()
{ }
@ -264,6 +298,8 @@ public:
private:
// Those are only modified (after initialization) on the graph thread. The
// graph thread does not run during the initialization.
TimeStamp mInitialTimeStamp;
TimeStamp mLastTimeStamp;
};
@ -420,18 +456,22 @@ private:
/* The size of this buffer comes from the fact that some audio backends can
* call back with a number of frames lower than one block (128 frames), so we
* need to keep at most two block in the SpillBuffer, because we always round
* up to block boundaries during an iteration. */
* up to block boundaries during an iteration.
* This is only ever accessed on the audio callback thread. */
SpillBuffer<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 2, ChannelCount> mScratchBuffer;
/* Wrapper to ensure we write exactly the number of frames we need in the
* audio buffer cubeb passes us. */
* audio buffer cubeb passes us. This is only ever accessed on the audio
* callback thread. */
AudioCallbackBufferWrapper<AudioDataValue, ChannelCount> mBuffer;
/* cubeb stream for this graph. This is guaranteed to be non-null after Init()
* has been called. */
* has been called, and is synchronized internaly. */
nsAutoRef<cubeb_stream> mAudioStream;
/* The sample rate for the aforementionned cubeb stream. */
/* The sample rate for the aforementionned cubeb stream. This is set on
* initialization and can be read safely afterwards. */
uint32_t mSampleRate;
/* Approximation of the time between two callbacks. This is used to schedule
* video frames. This is in milliseconds. */
* video frames. This is in milliseconds. Only even used (after
* inizatialization) on the audio callback thread. */
uint32_t mIterationDurationMS;
/* cubeb_stream_init calls the audio callback to prefill the buffers. The
* previous driver has to be kept alive until the audio stream has been
@ -459,13 +499,13 @@ private:
/* Thread for off-main-thread initialization and
* shutdown of the audio stream. */
nsCOMPtr<nsIThread> mInitShutdownThread;
/* This must be accessed with the graph monitor held. */
nsAutoTArray<StreamAndPromiseForOperation, 1> mPromisesForOperation;
/* This is set during initialization, and ca be read safely afterwards. */
dom::AudioChannel mAudioChannel;
/* This is atomic and is set by the audio callback thread. It can be read by
* any thread safely. */
Atomic<bool> mInCallback;
/* A thread has been created to be able to pause and restart the audio thread,
* but has not done so yet. This indicates that the callback should return
* early */
bool mPauseRequested;
/**
* True if microphone is being used by this process. This is synchronized by
* the graph's monitor. */

View File

@ -361,9 +361,15 @@ MediaStreamGraphImpl::UpdateStreamOrder()
}
}
bool switching = false;
{
MonitorAutoLock mon(mMonitor);
switching = CurrentDriver()->Switching();
}
if (audioTrackPresent && mRealtime &&
!CurrentDriver()->AsAudioCallbackDriver() &&
!CurrentDriver()->Switching()) {
!switching) {
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
@ -621,8 +627,15 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream)
audioOutputStream->mLastTickWritten = 0;
audioOutputStream->mTrackID = tracks->GetID();
bool switching = false;
{
MonitorAutoLock lock(mMonitor);
switching = CurrentDriver()->Switching();
}
if (!CurrentDriver()->AsAudioCallbackDriver() &&
!CurrentDriver()->Switching()) {
!switching) {
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
@ -1164,8 +1177,13 @@ MediaStreamGraphImpl::Process()
// If we are switching away from an AudioCallbackDriver, we don't need the
// mixer anymore.
bool switching = false;
{
MonitorAutoLock lock(mMonitor);
switching = CurrentDriver()->Switching();
}
if (CurrentDriver()->AsAudioCallbackDriver() &&
CurrentDriver()->Switching()) {
switching) {
bool isStarted;
{
MonitorAutoLock mon(mMonitor);
@ -3023,6 +3041,16 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
SuspendOrResumeStreams(aOperation, aStreams);
bool switching = false;
GraphDriver* nextDriver = nullptr;
{
MonitorAutoLock lock(mMonitor);
switching = CurrentDriver()->Switching();
if (switching) {
nextDriver = CurrentDriver()->NextDriver();
}
}
// If we have suspended the last AudioContext, and we don't have other
// streams that have audio, this graph will automatically switch to a
// SystemCallbackDriver, because it can't find a MediaStream that has an audio
@ -3032,12 +3060,13 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
if (aOperation == AudioContextOperation::Resume) {
if (!CurrentDriver()->AsAudioCallbackDriver()) {
AudioCallbackDriver* driver;
if (CurrentDriver()->Switching()) {
MOZ_ASSERT(CurrentDriver()->NextDriver()->AsAudioCallbackDriver());
driver = CurrentDriver()->NextDriver()->AsAudioCallbackDriver();
if (switching) {
MOZ_ASSERT(nextDriver->AsAudioCallbackDriver());
driver = nextDriver->AsAudioCallbackDriver();
} else {
driver = new AudioCallbackDriver(this);
mMixer.AddCallback(driver);
MonitorAutoLock lock(mMonitor);
CurrentDriver()->SwitchAtNextIteration(driver);
}
driver->EnqueueStreamAndPromiseForOperation(aDestinationStream,
@ -3071,19 +3100,20 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
aOperation);
SystemClockDriver* driver;
if (CurrentDriver()->NextDriver()) {
MOZ_ASSERT(!CurrentDriver()->NextDriver()->AsAudioCallbackDriver());
if (nextDriver) {
MOZ_ASSERT(!nextDriver->AsAudioCallbackDriver());
} else {
driver = new SystemClockDriver(this);
mMixer.RemoveCallback(CurrentDriver()->AsAudioCallbackDriver());
MonitorAutoLock lock(mMonitor);
CurrentDriver()->SwitchAtNextIteration(driver);
}
// We are closing or suspending an AudioContext, but we just got resumed.
// Queue the operation on the next driver so that the ordering is
// preserved.
} else if (!audioTrackPresent && CurrentDriver()->Switching()) {
MOZ_ASSERT(CurrentDriver()->NextDriver()->AsAudioCallbackDriver());
CurrentDriver()->NextDriver()->AsAudioCallbackDriver()->
} else if (!audioTrackPresent && switching) {
MOZ_ASSERT(nextDriver->AsAudioCallbackDriver());
nextDriver->AsAudioCallbackDriver()->
EnqueueStreamAndPromiseForOperation(aDestinationStream, aPromise,
aOperation);
} else {

View File

@ -57,7 +57,7 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats)
{
FFMPEG_LOG("Choosing FFmpeg pixel format for video decoding.");
for (; *aFormats > -1; aFormats++) {
if (*aFormats == PIX_FMT_YUV420P) {
if (*aFormats == PIX_FMT_YUV420P || *aFormats == PIX_FMT_YUVJ420P) {
FFMPEG_LOG("Requesting pixel format YUV420P.");
return PIX_FMT_YUV420P;
}

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<script>
var htmlAudio = new Audio(URL.createObjectURL(new window.MediaSource()));
(new window.AudioContext("ringer")).createMediaElementSource(htmlAudio);
(new window.AudioContext("alarm")).createMediaElementSource(htmlAudio);
</script>
</head>
</html>

View File

@ -81,6 +81,7 @@ load 1157994.html
load 1158427.html
load 1185176.html
load 1185192.html
load 1228484.html
load analyser-channels-1.html
load audiocontext-double-suspend.html
load buffer-source-duration-1.html

View File

@ -13,8 +13,7 @@ const char* kPermissionTypes[] = {
"geo",
"desktop-notification",
// Alias `push` to `desktop-notification`.
"desktop-notification",
"midi"
"desktop-notification"
};
// `-1` for the last null entry.

View File

@ -56,7 +56,7 @@ CreatePushPermissionStatus(JSContext* aCx,
}
if (permission.mUserVisible) {
aRv.Throw(NS_ERROR_UNEXPECTED);
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
}
@ -84,8 +84,8 @@ CreatePermissionStatus(JSContext* aCx,
case PermissionName::Push:
return CreatePushPermissionStatus(aCx, aPermission, aWindow, aRv);
case PermissionName::Midi:
default:
MOZ_ASSERT_UNREACHABLE("Unhandled type");
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
}

View File

@ -27,7 +27,8 @@ const PERMISSIONS = [
];
const UNSUPPORTED_PERMISSIONS = [
'midi',
'foobarbaz', // Not in spec, for testing only.
'midi'
];
function setup() {
@ -61,7 +62,10 @@ function checkUnsupportedPermissions() {
return Promise.all(UNSUPPORTED_PERMISSIONS.map(name => {
return navigator.permissions.query({ name }).then(
result => ok(false, `query should not have resolved for '${name}'`),
error => ok(true, `query should have rejected for '${name}'`));
error => {
is(error.name, 'TypeError',
`query should have thrown TypeError for '${name}'`);
});
}));
}

View File

@ -6,6 +6,7 @@
#include "mozilla/dom/PushManager.h"
#include "mozilla/Base64.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
@ -65,6 +66,26 @@ GetPermissionState(nsIPrincipal* aPrincipal,
return NS_OK;
}
void
SubscriptionToJSON(PushSubscriptionJSON& aJSON, const nsString& aEndpoint,
const nsTArray<uint8_t>& aRawP256dhKey,
const nsTArray<uint8_t>& aAuthSecret)
{
aJSON.mEndpoint.Construct();
aJSON.mEndpoint.Value() = aEndpoint;
aJSON.mKeys.mP256dh.Construct();
nsresult rv = Base64URLEncode(aRawP256dhKey.Length(),
aRawP256dhKey.Elements(),
aJSON.mKeys.mP256dh.Value());
Unused << NS_WARN_IF(NS_FAILED(rv));
aJSON.mKeys.mAuth.Construct();
rv = Base64URLEncode(aAuthSecret.Length(), aAuthSecret.Elements(),
aJSON.mKeys.mAuth.Value());
Unused << NS_WARN_IF(NS_FAILED(rv));
}
} // anonymous namespace
class UnsubscribeResultCallback final : public nsIUnsubscribeResultCallback
@ -123,6 +144,12 @@ PushSubscription::Unsubscribe(ErrorResult& aRv)
return p.forget();
}
void
PushSubscription::ToJSON(PushSubscriptionJSON& aJSON)
{
SubscriptionToJSON(aJSON, mEndpoint, mRawP256dhKey, mAuthSecret);
}
PushSubscription::PushSubscription(nsIGlobalObject* aGlobal,
const nsAString& aEndpoint,
const nsAString& aScope,
@ -507,6 +534,12 @@ WorkerPushSubscription::Unsubscribe(ErrorResult &aRv)
return p.forget();
}
void
WorkerPushSubscription::ToJSON(PushSubscriptionJSON& aJSON)
{
SubscriptionToJSON(aJSON, mEndpoint, mRawP256dhKey, mAuthSecret);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerPushSubscription)
NS_IMPL_CYCLE_COLLECTING_ADDREF(WorkerPushSubscription)

View File

@ -104,6 +104,9 @@ public:
already_AddRefed<Promise>
Unsubscribe(ErrorResult& aRv);
void
ToJSON(PushSubscriptionJSON& aJSON);
protected:
~PushSubscription();
@ -197,6 +200,9 @@ public:
already_AddRefed<Promise>
Unsubscribe(ErrorResult& aRv);
void
ToJSON(PushSubscriptionJSON& aJSON);
protected:
~WorkerPushSubscription();

View File

@ -77,6 +77,47 @@ http://creativecommons.org/licenses/publicdomain/
});
}
function base64UrlDecode(s) {
s = s.replace(/-/g, '+').replace(/_/g, '/');
// Replace padding if it was stripped by the sender.
// See http://tools.ietf.org/html/rfc4648#section-4
switch (s.length % 4) {
case 0:
break; // No pad chars in this case
case 2:
s += '==';
break; // Two pad chars
case 3:
s += '=';
break; // One pad char
default:
throw new Error('Illegal base64url string!');
}
// With correct padding restored, apply the standard base64 decoder
var decoded = atob(s);
var array = new Uint8Array(new ArrayBuffer(decoded.length));
for (var i = 0; i < decoded.length; i++) {
array[i] = decoded.charCodeAt(i);
}
return array;
}
add_task(function* compareJSONSubscription() {
var json = pushSubscription.toJSON();
is(json.endpoint, pushSubscription.endpoint, "Wrong endpoint");
["p256dh", "auth"].forEach(keyName => {
isDeeply(
base64UrlDecode(json.keys[keyName]),
new Uint8Array(pushSubscription.getKey(keyName)),
"Mismatched Base64-encoded key: " + keyName
);
});
});
add_task(function* comparePublicKey() {
var data = yield sendRequestToWorker({ type: "publicKey" });
var p256dhKey = new Uint8Array(pushSubscription.getKey("p256dh"));

View File

@ -57,6 +57,17 @@ interface HeapSnapshot {
[Throws]
any takeCensus(object? options);
/**
* Describe `node` with the specified `breakdown`. See the comment above
* `takeCensus` or `js/src/doc/Debugger/Debugger.Memory.md` for detailed
* documentation on breakdowns.
*
* Throws an error when `node` is not the id of a node in the heap snapshot,
* or if the breakdown is invalid.
*/
[Throws]
any describeNode(object breakdown, NodeId node);
/**
* Compute the dominator tree for this heap snapshot.
*

View File

@ -10,8 +10,8 @@
enum PermissionName {
"geolocation",
"notifications",
"push",
"midi"
"push"
// Unsupported: "midi"
};
dictionary PermissionDescriptor {

View File

@ -15,6 +15,18 @@ enum PushEncryptionKeyName
"auth"
};
dictionary PushSubscriptionKeys
{
ByteString p256dh;
ByteString auth;
};
dictionary PushSubscriptionJSON
{
USVString endpoint;
PushSubscriptionKeys keys;
};
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",
ChromeConstructor(DOMString pushEndpoint, DOMString scope,
ArrayBuffer? key, ArrayBuffer? authSecret)]
@ -24,7 +36,9 @@ interface PushSubscription
ArrayBuffer? getKey(PushEncryptionKeyName name);
[Throws, UseCounter]
Promise<boolean> unsubscribe();
jsonifier;
// Implements the custom serializer specified in Push API, section 9.
PushSubscriptionJSON toJSON();
// Used to set the principal from the JS implemented PushManager.
[Exposed=Window,ChromeOnly]

View File

@ -946,22 +946,21 @@ class ServiceWorkerJobBase : public ServiceWorkerJob
public:
ServiceWorkerJobBase(ServiceWorkerJobQueue* aQueue,
ServiceWorkerJob::Type aJobType,
ServiceWorkerUpdateFinishCallback* aCallback)
: ServiceWorkerJobBase(aQueue, aJobType, aCallback, nullptr, nullptr)
{ }
ServiceWorkerJobBase(ServiceWorkerJobQueue* aQueue,
ServiceWorkerJob::Type aJobType,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
ServiceWorkerUpdateFinishCallback* aCallback,
ServiceWorkerRegistrationInfo* aRegistration,
ServiceWorkerInfo* aServiceWorkerInfo)
: ServiceWorkerJob(aQueue, aJobType)
, mPrincipal(aPrincipal)
, mScope(aScope)
, mScriptSpec(aScriptSpec)
, mCallback(aCallback)
, mCanceled(false)
, mRegistration(aRegistration)
, mUpdateAndInstallInfo(aServiceWorkerInfo)
, mCanceled(false)
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
}
void
@ -972,14 +971,49 @@ public:
}
protected:
nsCOMPtr<nsIPrincipal> mPrincipal;
const nsCString mScope;
const nsCString mScriptSpec;
RefPtr<ServiceWorkerUpdateFinishCallback> mCallback;
bool mCanceled;
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
RefPtr<ServiceWorkerInfo> mUpdateAndInstallInfo;
bool mCanceled;
~ServiceWorkerJobBase()
{ }
// Ensure that mRegistration is set for the job. Also, if mRegistration was
// already set, ensure that a new registration object has not replaced it in
// the ServiceWorkerManager. This can happen when jobs race such that the
// registration is cleared and recreated while an update job is executing.
nsresult
EnsureAndVerifyRegistration()
{
AssertIsOnMainThread();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (NS_WARN_IF(!swm)) {
mRegistration = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<ServiceWorkerRegistrationInfo> registration =
swm->GetRegistration(mPrincipal, mScope);
if (NS_WARN_IF(!registration)) {
mRegistration = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_WARN_IF(mRegistration && registration != mRegistration)) {
mRegistration = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
mRegistration = registration.forget();
return NS_OK;
}
void
Succeed()
{
@ -990,25 +1024,6 @@ protected:
mCallback = nullptr;
}
}
};
// Base type for jobs that work with a specific service worker script.
class ServiceWorkerScriptJobBase : public ServiceWorkerJobBase
{
protected:
const nsCString mScriptSpec;
ServiceWorkerScriptJobBase(ServiceWorkerJobQueue* aQueue,
ServiceWorkerJob::Type aJobType,
ServiceWorkerUpdateFinishCallback* aCallback,
ServiceWorkerRegistrationInfo* aRegistration,
ServiceWorkerInfo* aServiceWorkerInfo,
const nsACString& aScriptSpec)
: ServiceWorkerJobBase(aQueue, aJobType, aCallback, aRegistration,
aServiceWorkerInfo)
, mScriptSpec(aScriptSpec)
{
}
// This MUST only be called when the job is still performing actions related
// to registration or update. After the spec resolves the update promise, use
@ -1018,7 +1033,6 @@ protected:
FailWithErrorResult(ErrorResult& aRv)
{
AssertIsOnMainThread();
MOZ_ASSERT(mRegistration);
// With cancellation support, we may only be running with one reference
// from another object like a stream loader or something.
@ -1036,7 +1050,7 @@ protected:
aRv.SuppressException();
NS_ConvertUTF8toUTF16 scriptSpec(mScriptSpec);
NS_ConvertUTF8toUTF16 scope(mRegistration->mScope);
NS_ConvertUTF8toUTF16 scope(mScope);
// Throw the type error with a generic error message.
aRv.ThrowTypeError<MSG_SW_INSTALL_ERROR>(scriptSpec, scope);
@ -1050,8 +1064,14 @@ protected:
aRv.SuppressException();
mUpdateAndInstallInfo = nullptr;
if (!mRegistration) {
Done(origStatus);
return;
}
if (mRegistration->mInstallingWorker) {
nsresult rv = serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
mRegistration->mInstallingWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the installing worker cache.");
@ -1073,21 +1093,27 @@ protected:
}
};
class ServiceWorkerInstallJob final : public ServiceWorkerScriptJobBase
class ServiceWorkerInstallJob final : public ServiceWorkerJobBase
{
friend class ContinueInstallTask;
public:
enum InstallType {
UpdateSameScript,
OverwriteScript
};
ServiceWorkerInstallJob(ServiceWorkerJobQueue* aQueue,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
ServiceWorkerUpdateFinishCallback* aCallback,
ServiceWorkerRegistrationInfo* aRegistration,
ServiceWorkerInfo* aServiceWorkerInfo,
const nsACString& aScriptSpec)
: ServiceWorkerScriptJobBase(aQueue, Type::InstallJob, aCallback,
aRegistration, aServiceWorkerInfo,
aScriptSpec)
InstallType aType)
: ServiceWorkerJobBase(aQueue, Type::InstallJob, aPrincipal, aScope,
aScriptSpec, aCallback, aServiceWorkerInfo)
, mType(aType)
{
MOZ_ASSERT(aRegistration);
}
void
@ -1103,10 +1129,25 @@ public:
Install()
{
RefPtr<ServiceWorkerJob> kungFuDeathGrip = this;
if (mCanceled) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
MOZ_ASSERT(mRegistration);
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
// If we are trying to install an update for an existing script, then
// make sure we don't overwrite a recent script change or resurrect a
// dead registration.
if (mType == UpdateSameScript) {
RefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
if (!newest || !mScriptSpec.Equals(newest->ScriptSpec())) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
}
// Begin [[Install]] atomic step 3.
if (mRegistration->mInstallingWorker) {
@ -1148,8 +1189,8 @@ public:
// which sends the install event to the worker.
ServiceWorkerPrivate* workerPrivate =
mRegistration->mInstallingWorker->WorkerPrivate();
nsresult rv = workerPrivate->SendLifeCycleEvent(NS_LITERAL_STRING("install"),
callback, failRunnable);
rv = workerPrivate->SendLifeCycleEvent(NS_LITERAL_STRING("install"),
callback, failRunnable);
if (NS_WARN_IF(NS_FAILED(rv))) {
ContinueAfterInstallEvent(false /* aSuccess */);
@ -1163,6 +1204,11 @@ public:
return Done(NS_ERROR_DOM_ABORT_ERR);
}
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
if (!mRegistration->mInstallingWorker) {
NS_WARNING("mInstallingWorker was null.");
return Done(NS_ERROR_DOM_ABORT_ERR);
@ -1196,6 +1242,7 @@ public:
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
mRegistration->NotifyListenersOnChange();
swm->StoreRegistration(mPrincipal, mRegistration);
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
@ -1208,15 +1255,16 @@ public:
// Activate() is invoked out of band of atomic.
mRegistration->TryToActivate();
}
private:
const InstallType mType;
};
class ServiceWorkerRegisterJob final : public ServiceWorkerScriptJobBase,
class ServiceWorkerRegisterJob final : public ServiceWorkerJobBase,
public serviceWorkerScriptCache::CompareCallback
{
friend class ContinueUpdateRunnable;
nsCString mScope;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsILoadGroup> mLoadGroup;
~ServiceWorkerRegisterJob()
@ -1227,15 +1275,13 @@ public:
// [[Register]]
ServiceWorkerRegisterJob(ServiceWorkerJobQueue* aQueue,
const nsCString& aScope,
const nsCString& aScriptSpec,
ServiceWorkerUpdateFinishCallback* aCallback,
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
ServiceWorkerUpdateFinishCallback* aCallback,
nsILoadGroup* aLoadGroup)
: ServiceWorkerScriptJobBase(aQueue, Type::RegisterJob, aCallback, nullptr,
nullptr, aScriptSpec)
, mScope(aScope)
, mPrincipal(aPrincipal)
: ServiceWorkerJobBase(aQueue, Type::RegisterJob, aPrincipal, aScope,
aScriptSpec, aCallback, nullptr)
, mLoadGroup(aLoadGroup)
{
AssertIsOnMainThread();
@ -1245,11 +1291,12 @@ public:
// [[Update]]
ServiceWorkerRegisterJob(ServiceWorkerJobQueue* aQueue,
ServiceWorkerRegistrationInfo* aRegistration,
ServiceWorkerUpdateFinishCallback* aCallback,
const nsACString& aScriptSpec)
: ServiceWorkerScriptJobBase(aQueue, Type::UpdateJob, aCallback,
aRegistration, nullptr, aScriptSpec)
nsIPrincipal* aPrincipal,
const nsACString& aScope,
const nsACString& aScriptSpec,
ServiceWorkerUpdateFinishCallback* aCallback)
: ServiceWorkerJobBase(aQueue, Type::UpdateJob, aPrincipal, aScope,
aScriptSpec, aCallback, nullptr)
{
AssertIsOnMainThread();
}
@ -1269,13 +1316,13 @@ public:
}
if (mJobType == RegisterJob) {
MOZ_ASSERT(!mRegistration);
mRegistration = swm->GetRegistration(mPrincipal, mScope);
if (mRegistration) {
mRegistration->mPendingUninstall = false;
RefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
if (newest && mScriptSpec.Equals(newest->ScriptSpec())) {
swm->StoreRegistration(mPrincipal, mRegistration);
Succeed();
// Done() must always be called async from Start()
@ -1291,15 +1338,22 @@ public:
} else {
mRegistration = swm->CreateNewRegistration(mScope, mPrincipal);
}
swm->StoreRegistration(mPrincipal, mRegistration);
} else {
MOZ_ASSERT(mJobType == UpdateJob);
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
// Do nothing here, but since mRegistration is nullptr we will
// trigger the async Fail() call below.
MOZ_ASSERT(!mRegistration);
}
// If a different script spec has been registered between when this update
// was scheduled and it running now, then simply abort.
RefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
if (newest && !mScriptSpec.Equals(newest->ScriptSpec())) {
RefPtr<ServiceWorkerInfo> newest = mRegistration ? mRegistration->Newest()
: nullptr;
if (!mRegistration ||
(newest && !mScriptSpec.Equals(newest->ScriptSpec()))) {
// Done() must always be called async from Start()
nsCOMPtr<nsIRunnable> runnable =
@ -1322,6 +1376,7 @@ public:
const nsACString& aMaxScope) override
{
RefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
if (NS_WARN_IF(mCanceled)) {
Fail(NS_ERROR_DOM_ABORT_ERR);
return;
@ -1332,6 +1387,11 @@ public:
return;
}
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
if (aInCacheAndEqual) {
Succeed();
Done(NS_OK);
@ -1344,7 +1404,7 @@ public:
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsCOMPtr<nsIURI> scriptURI;
nsresult rv = NS_NewURI(getter_AddRefs(scriptURI), mScriptSpec);
rv = NS_NewURI(getter_AddRefs(scriptURI), mScriptSpec);
if (NS_WARN_IF(NS_FAILED(rv))) {
Fail(NS_ERROR_DOM_SECURITY_ERR);
return;
@ -1417,7 +1477,12 @@ private:
ContinueInstall(bool aScriptEvaluationResult)
{
AssertIsOnMainThread();
MOZ_ASSERT(mRegistration);
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
mRegistration->mUpdating = false;
RefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
@ -1434,9 +1499,22 @@ private:
return FailWithErrorResult(error);
}
// For updates we want to make sure our install job does not end up
// changing the script for the registration. Since a registration
// script change can be queued in an install job, we can not
// conclusively verify that the update install should proceed here.
// Instead, we have to pass a flag into our install job indicating
// if a script change is allowed or not. This can then be used to
// check the current script after all previous install jobs have been
// flushed.
ServiceWorkerInstallJob::InstallType installType =
mJobType == UpdateJob ? ServiceWorkerInstallJob::UpdateSameScript
: ServiceWorkerInstallJob::OverwriteScript;
RefPtr<ServiceWorkerInstallJob> job =
new ServiceWorkerInstallJob(mQueue, mCallback, mRegistration,
mUpdateAndInstallInfo, mScriptSpec);
new ServiceWorkerInstallJob(mQueue, mPrincipal, mScope, mScriptSpec,
mCallback, mUpdateAndInstallInfo,
installType);
mQueue->Append(job);
Done(NS_OK);
}
@ -1463,10 +1541,16 @@ private:
{
AssertIsOnMainThread();
RefPtr<ServiceWorkerRegisterJob> kungFuDeathGrip = this;
if (mCanceled) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
nsresult rv = EnsureAndVerifyRegistration();
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(NS_ERROR_DOM_ABORT_ERR);
}
if (mRegistration->mInstallingWorker) {
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
mRegistration->mInstallingWorker->WorkerPrivate()->TerminateWorker();
@ -1483,10 +1567,9 @@ private:
cacheName = workerInfo->CacheName();
}
nsresult rv =
serviceWorkerScriptCache::Compare(mRegistration, mRegistration->mPrincipal, cacheName,
NS_ConvertUTF8toUTF16(mScriptSpec), this,
mLoadGroup);
rv = serviceWorkerScriptCache::Compare(mRegistration, mPrincipal, cacheName,
NS_ConvertUTF8toUTF16(mScriptSpec),
this, mLoadGroup);
if (NS_WARN_IF(NS_FAILED(rv))) {
return Fail(rv);
}
@ -1735,7 +1818,8 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
RefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(queue, cleanedScope, spec, cb, documentPrincipal, loadGroup);
new ServiceWorkerRegisterJob(queue, documentPrincipal, cleanedScope, spec,
cb, loadGroup);
queue->Append(job);
AssertIsOnMainThread();
@ -3712,10 +3796,23 @@ ServiceWorkerManager::NotifyServiceWorkerRegistrationRemoved(ServiceWorkerRegist
}
void
ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
ServiceWorkerManager::SoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsACString& aScope)
{
AssertIsOnMainThread();
nsCOMPtr<nsIURI> scopeURI;
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(scopeURI, aOriginAttributes);
if (NS_WARN_IF(!principal)) {
return;
}
nsAutoCString scopeKey;
aOriginAttributes.CreateSuffix(scopeKey);
@ -3752,8 +3849,8 @@ ServiceWorkerManager::SoftUpdate(const OriginAttributes& aOriginAttributes,
MOZ_ASSERT(queue);
RefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(queue, registration, nullptr,
newest->ScriptSpec());
new ServiceWorkerRegisterJob(queue, principal, registration->mScope,
newest->ScriptSpec(), nullptr);
queue->Append(job);
}
}
@ -3804,8 +3901,8 @@ ServiceWorkerManager::Update(nsIPrincipal* aPrincipal,
// "Invoke Update algorithm, or its equivalent, with client, registration as
// its argument."
RefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(queue, registration, aCallback,
newest->ScriptSpec());
new ServiceWorkerRegisterJob(queue, aPrincipal, registration->mScope,
newest->ScriptSpec(), aCallback);
queue->Append(job);
}

View File

@ -393,7 +393,7 @@ public:
ServiceWorkerUpdateFinishCallback* aCallback);
void
SoftUpdate(const OriginAttributes& aOriginAttributes,
SoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsACString& aScope);
void

View File

@ -12,11 +12,7 @@
#include "FilterNodeSoftware.h"
#include "HelpersSkia.h"
#ifdef USE_SKIA_GPU
#include "skia/include/gpu/SkGpuDevice.h"
#include "skia/include/gpu/gl/GrGLInterface.h"
#endif
#include "skia/include/core/SkSurface.h"
#include "skia/include/core/SkTypeface.h"
#include "skia/include/effects/SkGradientShader.h"
#include "skia/include/core/SkColorFilter.h"
@ -149,29 +145,32 @@ bool
DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize,
int32_t* aStride, SurfaceFormat* aFormat)
{
const SkBitmap &bitmap = mCanvas->getDevice()->accessBitmap(false);
if (!bitmap.lockPixelsAreWritable()) {
/* Test if the canvas' device has accessible pixels first, as actually
* accessing the pixels may trigger side-effects, even if it fails.
*/
if (!mCanvas->peekPixels(nullptr, nullptr)) {
return false;
}
SkImageInfo info;
size_t rowBytes;
void* pixels = mCanvas->accessTopLayerPixels(&info, &rowBytes);
if (!pixels) {
return false;
}
MarkChanged();
bitmap.lockPixels();
*aData = reinterpret_cast<uint8_t*>(bitmap.getPixels());
*aSize = IntSize(bitmap.width(), bitmap.height());
*aStride = int32_t(bitmap.rowBytes());
*aFormat = SkiaColorTypeToGfxFormat(bitmap.colorType());
*aData = reinterpret_cast<uint8_t*>(pixels);
*aSize = IntSize(info.width(), info.height());
*aStride = int32_t(rowBytes);
*aFormat = SkiaColorTypeToGfxFormat(info.colorType());
return true;
}
void
DrawTargetSkia::ReleaseBits(uint8_t* aData)
{
const SkBitmap &bitmap = mCanvas->getDevice()->accessBitmap(false);
MOZ_ASSERT(bitmap.lockPixelsAreWritable());
bitmap.unlockPixels();
bitmap.notifyPixelsChanged();
}
static void
@ -266,7 +265,7 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap
SkSafeUnref(shader);
SkSafeUnref(aPaint.setShader(matrixShader));
if (pat.mFilter == Filter::POINT) {
aPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
aPaint.setFilterQuality(kNone_SkFilterQuality);
}
break;
}
@ -333,7 +332,7 @@ struct AutoPaintSetup {
mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
mAlpha = aOptions.mAlpha;
}
mPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
mPaint.setFilterQuality(kLow_SkFilterQuality);
}
// TODO: Maybe add an operator overload to access this easier?
@ -381,10 +380,10 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
if (aSurfOptions.mFilter == Filter::POINT) {
paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
paint.mPaint.setFilterQuality(kNone_SkFilterQuality);
}
mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
mCanvas->drawBitmapRect(bitmap.mBitmap, sourceRect, destRect, &paint.mPaint);
}
DrawTargetType
@ -797,9 +796,7 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
SkBitmap bm(bitmap.mBitmap);
bm.lockPixels();
if (bm.getPixels()) {
SkImageInfo info = bm.info();
info.fWidth = aSourceRect.width;
info.fHeight = aSourceRect.height;
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();
@ -831,7 +828,7 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
clearPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
mCanvas->drawPaint(clearPaint);
}
mCanvas->drawBitmapRect(bitmap.mBitmap, &source, dest, &paint);
mCanvas->drawBitmapRect(bitmap.mBitmap, source, dest, &paint);
mCanvas->restore();
}
@ -854,7 +851,7 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
SkBitmap bitmap;
bitmap.setInfo(skiInfo, stride);
if (!bitmap.allocPixels()) {
if (!bitmap.tryAllocPixels()) {
return false;
}
@ -883,24 +880,28 @@ DrawTargetSkia::InitWithGrContext(GrContext* aGrContext,
mSize = aSize;
mFormat = aFormat;
GrTextureDesc targetDescriptor;
GrSurfaceDesc targetDescriptor;
targetDescriptor.fFlags = kRenderTarget_GrTextureFlagBit;
targetDescriptor.fFlags = kRenderTarget_GrSurfaceFlag;
targetDescriptor.fWidth = mSize.width;
targetDescriptor.fHeight = mSize.height;
targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat);
targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin;
targetDescriptor.fSampleCnt = 0;
SkAutoTUnref<GrTexture> skiaTexture(mGrContext->createUncachedTexture(targetDescriptor, NULL, 0));
SkAutoTUnref<GrTexture> skiaTexture(mGrContext->textureProvider()->createTexture(targetDescriptor, SkSurface::kNo_Budgeted, nullptr, 0));
if (!skiaTexture) {
return false;
}
mTexture = (uint32_t)skiaTexture->getTextureHandle();
SkAutoTUnref<SkSurface> gpuSurface(SkSurface::NewRenderTargetDirect(skiaTexture->asRenderTarget()));
if (!gpuSurface) {
return false;
}
SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), skiaTexture->asRenderTarget()));
mCanvas.adopt(new SkCanvas(device.get()));
mTexture = reinterpret_cast<GrGLTextureInfo *>(skiaTexture->getTextureHandle())->fID;
mCanvas = gpuSurface->getCanvas();
return true;
}

View File

@ -142,7 +142,7 @@ private:
#ifdef USE_SKIA_GPU
RefPtrSkia<GrContext> mGrContext;
uint32_t mTexture;
GrGLuint mTexture;
#endif
IntSize mSize;

View File

@ -41,20 +41,20 @@ SkTypeface* ScaledFontCairo::GetSkTypeface()
{
if (!mTypeface) {
cairo_font_face_t* fontFace = cairo_scaled_font_get_font_face(mScaledFont);
MOZ_ASSERT(cairo_font_face_status(fontFace) == CAIRO_STATUS_SUCCESS);
FT_Face face = cairo_ft_scaled_font_lock_face(mScaledFont);
int style = SkTypeface::kNormal;
if (face->style_flags & FT_STYLE_FLAG_ITALIC)
style |= SkTypeface::kItalic;
if (face->style_flags & FT_STYLE_FLAG_BOLD)
style |= SkTypeface::kBold;
SkFontStyle style(face->style_flags & FT_STYLE_FLAG_BOLD ?
SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
SkFontStyle::kNormal_Width,
face->style_flags & FT_STYLE_FLAG_ITALIC ?
SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
bool isFixedWidth = face->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
cairo_ft_scaled_font_unlock_face(mScaledFont);
mTypeface = SkCreateTypefaceFromCairoFont(fontFace, (SkTypeface::Style)style, isFixedWidth);
mTypeface = SkCreateTypefaceFromCairoFont(fontFace, style, isFixedWidth);
}
return mTypeface;

View File

@ -13,6 +13,7 @@
#include "DataSurfaceHelpers.h"
#ifdef USE_SKIA_GPU
#include "GLDefs.h"
#include "skia/include/gpu/SkGrPixelRef.h"
#endif
@ -50,13 +51,11 @@ SourceSurfaceSkia::InitFromCanvas(SkCanvas* aCanvas,
SurfaceFormat aFormat,
DrawTargetSkia* aOwner)
{
SkISize size = aCanvas->getDeviceSize();
mBitmap = (SkBitmap)aCanvas->getDevice()->accessBitmap(false);
mBitmap = aCanvas->getDevice()->accessBitmap(false);
mFormat = aFormat;
mSize = IntSize(size.fWidth, size.fHeight);
mSize = IntSize(mBitmap.width(), mBitmap.height());
mStride = mBitmap.rowBytes();
mDrawTarget = aOwner;
@ -84,10 +83,6 @@ SourceSurfaceSkia::InitFromData(unsigned char* aData,
return false;
}
if (aFormat == SurfaceFormat::B8G8R8X8) {
mBitmap.setAlphaType(kIgnore_SkAlphaType);
}
mSize = aSize;
mFormat = aFormat;
mStride = mBitmap.rowBytes();
@ -109,11 +104,15 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
skiaTexGlue.fOrigin = kTopLeft_GrSurfaceOrigin;
skiaTexGlue.fConfig = GfxFormatToGrConfig(aFormat);
skiaTexGlue.fSampleCnt = 0;
skiaTexGlue.fTextureHandle = aTexture;
GrTexture *skiaTexture = aOwner->mGrContext->wrapBackendTexture(skiaTexGlue);
GrGLTextureInfo texInfo;
texInfo.fTarget = LOCAL_GL_TEXTURE_2D;
texInfo.fID = aTexture;
skiaTexGlue.fTextureHandle = reinterpret_cast<GrBackendObject>(&texInfo);
GrTexture *skiaTexture = aOwner->mGrContext->textureProvider()->wrapBackendTexture(skiaTexGlue);
SkImageInfo imgInfo = SkImageInfo::Make(aSize.width, aSize.height, GfxFormatToSkiaColorType(aFormat), kOpaque_SkAlphaType);
SkGrPixelRef *texRef = new SkGrPixelRef(imgInfo, skiaTexture, false);
SkGrPixelRef *texRef = new SkGrPixelRef(imgInfo, skiaTexture);
mBitmap.setInfo(imgInfo);
mBitmap.setPixelRef(texRef);
mFormat = aFormat;

View File

@ -89,6 +89,11 @@ GrGLvoid glBlendColor_mozilla(GrGLclampf red, GrGLclampf green, GrGLclampf blue,
return sGLContext.get()->fBlendColor(red, green, blue, alpha);
}
GrGLvoid glBlendEquation_mozilla(GrGLenum mode)
{
return sGLContext.get()->fBlendEquation(mode);
}
GrGLvoid glBlendFunc_mozilla(GrGLenum sfactor, GrGLenum dfactor)
{
return sGLContext.get()->fBlendFunc(sfactor, dfactor);
@ -315,6 +320,11 @@ GrGLvoid glGetShaderiv_mozilla(GrGLuint shader, GrGLenum pname, GrGLint* params)
return sGLContext.get()->fGetShaderiv(shader, pname, params);
}
GrGLvoid glGetShaderPrecisionFormat_mozilla(GrGLenum shadertype, GrGLenum precisiontype, GLint *range, GLint *precision)
{
return sGLContext.get()->fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
}
const GLubyte* glGetString_mozilla(GrGLenum name)
{
// GLContext only exposes a OpenGL 2.0 style API, so we have to intercept a bunch
@ -357,6 +367,12 @@ const GLubyte* glGetString_mozilla(GrGLenum name)
if (sGLContext.get()->IsSupported(GLFeature::standard_derivatives)) {
strcat(extensionsString, "GL_OES_standard_derivatives ");
}
} else {
if (sGLContext.get()->IsSupported(GLFeature::framebuffer_object)) {
strcat(extensionsString, "GL_ARB_framebuffer_object ");
} else if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_framebuffer_object)) {
strcat(extensionsString, "GL_EXT_framebuffer_object ");
}
}
if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_texture_format_BGRA8888)) {
@ -581,6 +597,21 @@ GrGLvoid glUseProgram_mozilla(GrGLuint program)
return sGLContext.get()->fUseProgram(program);
}
GrGLvoid glVertexAttrib1f_mozilla(GrGLuint index, GrGLfloat value)
{
return sGLContext.get()->fVertexAttrib1f(index, value);
}
GrGLvoid glVertexAttrib2fv_mozilla(GrGLuint index, const GrGLfloat* values)
{
return sGLContext.get()->fVertexAttrib2fv(index, values);
}
GrGLvoid glVertexAttrib3fv_mozilla(GrGLuint index, const GrGLfloat* values)
{
return sGLContext.get()->fVertexAttrib3fv(index, values);
}
GrGLvoid glVertexAttrib4fv_mozilla(GrGLuint index, const GrGLfloat* values)
{
return sGLContext.get()->fVertexAttrib4fv(index, values);
@ -767,6 +798,7 @@ static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fFunctions.fBindTexture = glBindTexture_mozilla;
i->fFunctions.fBlendFunc = glBlendFunc_mozilla;
i->fFunctions.fBlendColor = glBlendColor_mozilla;
i->fFunctions.fBlendEquation = glBlendEquation_mozilla;
i->fFunctions.fBufferData = glBufferData_mozilla;
i->fFunctions.fBufferSubData = glBufferSubData_mozilla;
i->fFunctions.fCheckFramebufferStatus = glCheckFramebufferStatus_mozilla;
@ -811,6 +843,7 @@ static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fFunctions.fGetRenderbufferParameteriv = glGetRenderbufferParameteriv_mozilla;
i->fFunctions.fGetShaderInfoLog = glGetShaderInfoLog_mozilla;
i->fFunctions.fGetShaderiv = glGetShaderiv_mozilla;
i->fFunctions.fGetShaderPrecisionFormat = glGetShaderPrecisionFormat_mozilla;
i->fFunctions.fGetString = glGetString_mozilla;
i->fFunctions.fGetUniformLocation = glGetUniformLocation_mozilla;
i->fFunctions.fLineWidth = glLineWidth_mozilla;
@ -847,6 +880,9 @@ static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fFunctions.fUniformMatrix3fv = glUniformMatrix3fv_mozilla;
i->fFunctions.fUniformMatrix4fv = glUniformMatrix4fv_mozilla;
i->fFunctions.fUseProgram = glUseProgram_mozilla;
i->fFunctions.fVertexAttrib1f = glVertexAttrib1f_mozilla;
i->fFunctions.fVertexAttrib2fv = glVertexAttrib2fv_mozilla;
i->fFunctions.fVertexAttrib3fv = glVertexAttrib3fv_mozilla;
i->fFunctions.fVertexAttrib4fv = glVertexAttrib4fv_mozilla;
i->fFunctions.fVertexAttribPointer = glVertexAttribPointer_mozilla;
i->fFunctions.fViewport = glViewport_mozilla;

View File

@ -254,9 +254,9 @@ Transform(DataSourceSurface* aDest,
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setAntiAlias(true);
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
paint.setFilterQuality(kLow_SkFilterQuality);
SkRect destRect = SkRect::MakeXYWH(0, 0, srcSize.width, srcSize.height);
destCanvas.drawBitmapRectToRect(src, nullptr, destRect, &paint);
destCanvas.drawBitmapRect(src, destRect, &paint);
}
#else
static pixman_transform

View File

@ -742,9 +742,9 @@ Transform(const gfxImageSurface* aDest,
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setAntiAlias(true);
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
paint.setFilterQuality(kLow_SkFilterQuality);
SkRect destRect = SkRect::MakeXYWH(0, 0, srcSize.width, srcSize.height);
destCanvas.drawBitmapRectToRect(src, nullptr, destRect, &paint);
destCanvas.drawBitmapRect(src, destRect, &paint);
}
#else
static pixman_transform

View File

@ -25,34 +25,12 @@ header = """
footer = """
# can we find a better way of dealing with asm sources?
# left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
#XXX: doesn't build with Apple's assembler
if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC'] and CONFIG['OS_TARGET'] != 'Darwin':
SOURCES += [
'skia/src/opts/memset.arm.S',
]
if CONFIG['BUILD_ARM_NEON']:
SOURCES += [
'skia/src/opts/memset16_neon.S',
'skia/src/opts/memset32_neon.S',
]
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC'] and CONFIG['OS_ARCH'] != 'WINNT':
if CONFIG['CPU_ARCH'] == 'x86_64':
SOURCES += [
'skia/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
]
else:
SOURCES += [
'skia/src/opts/SkBlitRow_opts_SSE4_asm.S',
]
# We allow warnings for third-party code that can be updated from upstream.
ALLOW_COMPILER_WARNINGS = True
FINAL_LIBRARY = 'gkmedias'
LOCAL_INCLUDES += [
'skia/include/c',
'skia/include/config',
'skia/include/core',
'skia/include/effects',
@ -61,6 +39,7 @@ LOCAL_INCLUDES += [
'skia/include/pathops',
'skia/include/pipe',
'skia/include/ports',
'skia/include/private',
'skia/include/utils',
'skia/include/utils/mac',
'skia/include/utils/win',
@ -78,12 +57,6 @@ LOCAL_INCLUDES += [
'skia/src/utils/win',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in {'android', 'gtk2', 'gtk3', 'qt', 'gonk', 'cocoa', 'uikit'}:
DEFINES['SK_USE_POSIX_THREADS'] = 1
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']:
DEFINES['SK_BUILD_SSSE3'] = 1
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0
@ -101,37 +74,33 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in {
if CONFIG['_MSC_VER']:
# MSVC doesn't need special compiler flags, but Skia needs to be told that these files should
# be built with the required SSE level or it will simply compile in stubs and cause runtime crashes
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkBlitRect_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkMorphology_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkUtils_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkXfermode_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['/arch:AVX -DSK_CPU_SSE_LEVEL=51']
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC']:
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkBlitRect_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkMorphology_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkUtils_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkXfermode_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC'] and CONFIG['BUILD_ARM_NEON']:
DEFINES['__ARM_HAVE_OPTIONAL_NEON_SUPPORT'] = 1
DEFINES['USE_ANDROID_NDK_CPU_FEATURES'] = 0
DEFINES['SK_ARM_HAS_OPTIONAL_NEON'] = 1
elif CONFIG['CLANG_CL']:
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
DEFINES['SKIA_IMPLEMENTATION'] = 1
DEFINES['GR_IMPLEMENTATION'] = 1
if CONFIG['GNU_CXX']:
CXXFLAGS += [
@ -147,6 +116,8 @@ if CONFIG['GNU_CXX']:
'-Wno-macro-redefined',
'-Wno-unused-private-field',
]
# work around inline function linking bug with template arguments
SOURCES['skia/src/gpu/GrResourceCache.cpp'].flags += ['-fkeep-inline-functions']
else:
CXXFLAGS += [
'-Wno-logical-op',
@ -180,7 +151,7 @@ def generate_platform_sources():
sources = {}
for plat in platforms:
if os.system("cd skia && GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=%s gyp/skia_lib.gyp" % plat) != 0:
if os.system("cd skia && GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=%s -D host_os=linux gyp/skia_lib.gyp" % plat) != 0:
print 'Failed to generate sources for ' + plat
continue
@ -195,31 +166,26 @@ def generate_platform_sources():
def generate_separated_sources(platform_sources):
blacklist = [
'ChromeUtils',
'SkImageDecoder_',
'_gif',
'SkFontConfigParser_android',
'SkJpeg',
'SkXML',
'SkCity',
'GrGLCreateNativeInterface',
'SkCreatePlatformGLContext',
'fontconfig',
'SkCondVar',
'SkThreadUtils_pthread_',
'SkImage_Codec',
'SkBitmapChecksummer',
'SkNativeGLContext',
'SkFontConfig',
'SkFontHost_win_dw',
'SkFontMgr_android',
'SkFontMgr_custom',
'SkFontHost_FreeType.cpp',
'SkForceLinking',
'SkMovie',
'SkImageDecoder',
'SkImageEncoder',
'SkBitmapHasher',
'SkBitmapRegion',
'codec',
'SkWGL',
'SkImages',
'SkDiscardableMemory_ashmem',
'SkMemory_malloc',
'SkOpts_',
'opts_check_x86',
'third_party',
]
@ -233,30 +199,18 @@ def generate_separated_sources(platform_sources):
separated = defaultdict(set, {
'common': {
#'skia/src/effects/gradients/SkGradientTileProc.cpp',
'skia/src/gpu/gl/GrGLCreateNativeInterface_none.cpp',
'skia/src/ports/SkDiscardableMemory_none.cpp',
'skia/src/ports/SkImageDecoder_empty.cpp',
'skia/src/ports/SkMemory_mozalloc.cpp',
# 'skia/src/images/SkImages.cpp',
# 'skia/src/images/SkImageRef.cpp',
# 'skia/src/images/SkImageRef_GlobalPool.cpp',
# 'skia/src/images/SkImageRefPool.cpp',
# 'skia/src/images/SkImageDecoder.cpp',
# 'skia/src/images/SkImageDecoder_Factory.cpp',
},
'android': {
# 'skia/src/ports/SkDebug_android.cpp',
'skia/src/ports/SkFontHost_android_old.cpp',
'skia/src/ports/SkFontHost_cairo.cpp',
# 'skia/src/ports/SkFontHost_FreeType.cpp',
# 'skia/src/ports/SkFontHost_FreeType_common.cpp',
# 'skia/src/ports/SkThread_pthread.cpp',
# 'skia/src/ports/SkPurgeableMemoryBlock_android.cpp',
# 'skia/src/ports/SkTime_Unix.cpp',
# 'skia/src/utils/SkThreadUtils_pthread.cpp',
# 'skia/src/images/SkImageRef_ashmem.cpp',
# 'skia/src/utils/android/ashmem.cpp',
},
'linux': {
'skia/src/ports/SkFontHost_cairo.cpp',
@ -264,18 +218,18 @@ def generate_separated_sources(platform_sources):
'intel': {
# There is currently no x86-specific opt for SkTextureCompression
'skia/src/opts/opts_check_x86.cpp',
'skia/src/opts/SkTextureCompression_opts_none.cpp',
'skia/src/opts/SkOpts_ssse3.cpp',
'skia/src/opts/SkOpts_sse41.cpp',
'skia/src/opts/SkOpts_avx.cpp',
},
'arm': {
'skia/src/opts/SkUtils_opts_arm.cpp',
'skia/src/core/SkUtilsArm.cpp',
},
'neon': {
'skia/src/opts/SkOpts_neon.cpp',
'skia/src/opts/SkBitmapProcState_arm_neon.cpp',
},
'none': {
'skia/src/opts/SkUtils_opts_none.cpp',
}
'none': set()
})
for plat in platform_sources.keys():
@ -341,15 +295,22 @@ def write_sources(f, values, indent):
'SkBlitter_Sprite.cpp',
'SkBlitRow_opts_arm.cpp',
'SkScan_Antihair.cpp',
'SkCondVar.cpp',
'SkParse.cpp',
'GrAddPathRenderers_default.cpp',
'GrDistanceFieldTextContext.cpp',
'SkSHA1.cpp',
'SkMD5.cpp',
'SkPictureData.cpp',
'SkScaledImageCache.cpp',
'opts_check_x86.cpp',
'GrDrawContext',
'GrResourceCache',
'GrAA',
'GrGL',
'GrBatchAtlas.cpp',
'SkArithmeticMode_gpu.cpp',
'SkImage_Gpu.cpp',
'SkPathOpsDebug.cpp',
'SkParsePath.cpp',
'SkOpts',
'SkRecorder.cpp',
]
def isblacklisted(value):

View File

@ -14,26 +14,31 @@
# DO NOT MODIFY THIS FILE IT IS AUTOGENERATED.
#
UNIFIED_SOURCES += [
'skia/src/c/sk_paint.cpp',
'skia/src/c/sk_surface.cpp',
'skia/src/core/SkAAClip.cpp',
'skia/src/core/SkAlphaRuns.cpp',
'skia/src/core/SkAnnotation.cpp',
'skia/src/core/SkBBHFactory.cpp',
'skia/src/core/SkBBoxHierarchyRecord.cpp',
'skia/src/core/SkBBoxRecord.cpp',
'skia/src/core/SkBigPicture.cpp',
'skia/src/core/SkBitmap.cpp',
'skia/src/core/SkBitmap_scroll.cpp',
'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',
'skia/src/core/SkBitmapProvider.cpp',
'skia/src/core/SkBitmapScaler.cpp',
'skia/src/core/SkBlitMask_D32.cpp',
'skia/src/core/SkBlitRow_D16.cpp',
'skia/src/core/SkBlitRow_D32.cpp',
'skia/src/core/SkBlitter.cpp',
'skia/src/core/SkBuffer.cpp',
'skia/src/core/SkCachedData.cpp',
'skia/src/core/SkCanvas.cpp',
'skia/src/core/SkChecksum.cpp',
'skia/src/core/SkChunkAlloc.cpp',
'skia/src/core/SkClipStack.cpp',
'skia/src/core/SkColor.cpp',
@ -53,6 +58,7 @@ UNIFIED_SOURCES += [
'skia/src/core/SkDistanceFieldGen.cpp',
'skia/src/core/SkDither.cpp',
'skia/src/core/SkDraw.cpp',
'skia/src/core/SkDrawable.cpp',
'skia/src/core/SkDrawLooper.cpp',
'skia/src/core/SkEdge.cpp',
'skia/src/core/SkEdgeBuilder.cpp',
@ -62,75 +68,85 @@ UNIFIED_SOURCES += [
'skia/src/core/SkFilterShader.cpp',
'skia/src/core/SkFlattenable.cpp',
'skia/src/core/SkFlattenableSerialization.cpp',
'skia/src/core/SkFloat.cpp',
'skia/src/core/SkFloatBits.cpp',
'skia/src/core/SkFont.cpp',
'skia/src/core/SkFontDescriptor.cpp',
'skia/src/core/SkFontMgr.cpp',
'skia/src/core/SkFontStream.cpp',
'skia/src/core/SkFontStyle.cpp',
'skia/src/core/SkForceCPlusPlusLinking.cpp',
'skia/src/core/SkGeometry.cpp',
'skia/src/core/SkGlyphCache.cpp',
'skia/src/core/SkGraphics.cpp',
'skia/src/core/SkHalf.cpp',
'skia/src/core/SkImageCacherator.cpp',
'skia/src/core/SkImageFilter.cpp',
'skia/src/core/SkImageGenerator.cpp',
'skia/src/core/SkImageInfo.cpp',
'skia/src/core/SkInstCnt.cpp',
'skia/src/core/SkLightingShader.cpp',
'skia/src/core/SkLineClipper.cpp',
'skia/src/core/SkLocalMatrixImageFilter.cpp',
'skia/src/core/SkLocalMatrixShader.cpp',
'skia/src/core/SkMallocPixelRef.cpp',
'skia/src/core/SkMask.cpp',
'skia/src/core/SkMaskCache.cpp',
'skia/src/core/SkMaskFilter.cpp',
'skia/src/core/SkMaskGamma.cpp',
'skia/src/core/SkMath.cpp',
'skia/src/core/SkMatrix.cpp',
'skia/src/core/SkMatrixClipStateMgr.cpp',
'skia/src/core/SkMatrixImageFilter.cpp',
'skia/src/core/SkMetaData.cpp',
'skia/src/core/SkMiniRecorder.cpp',
'skia/src/core/SkMipMap.cpp',
'skia/src/core/SkMultiPictureDraw.cpp',
'skia/src/core/SkNinePatchIter.cpp',
'skia/src/core/SkPackBits.cpp',
'skia/src/core/SkPaint.cpp',
'skia/src/core/SkPaintOptionsAndroid.cpp',
'skia/src/core/SkPaintPriv.cpp',
'skia/src/core/SkPatch.cpp',
'skia/src/core/SkPath.cpp',
'skia/src/core/SkPathEffect.cpp',
'skia/src/core/SkPathHeap.cpp',
'skia/src/core/SkPathMeasure.cpp',
'skia/src/core/SkPathRef.cpp',
'skia/src/core/SkPicture.cpp',
'skia/src/core/SkPictureContentInfo.cpp',
'skia/src/core/SkPictureFlat.cpp',
'skia/src/core/SkPictureImageGenerator.cpp',
'skia/src/core/SkPicturePlayback.cpp',
'skia/src/core/SkPictureRangePlayback.cpp',
'skia/src/core/SkPictureRecord.cpp',
'skia/src/core/SkPictureRecorder.cpp',
'skia/src/core/SkPictureReplacementPlayback.cpp',
'skia/src/core/SkPictureShader.cpp',
'skia/src/core/SkPictureStateTree.cpp',
'skia/src/core/SkPixelRef.cpp',
'skia/src/core/SkPixmap.cpp',
'skia/src/core/SkPoint.cpp',
'skia/src/core/SkProcSpriteBlitter.cpp',
'skia/src/core/SkPoint3.cpp',
'skia/src/core/SkPtrRecorder.cpp',
'skia/src/core/SkQuadClipper.cpp',
'skia/src/core/SkQuadTree.cpp',
'skia/src/core/SkRasterClip.cpp',
'skia/src/core/SkRasterizer.cpp',
'skia/src/core/SkReadBuffer.cpp',
'skia/src/core/SkRecordAnalysis.cpp',
'skia/src/core/SkRecord.cpp',
'skia/src/core/SkRecordDraw.cpp',
'skia/src/core/SkRecorder.cpp',
'skia/src/core/SkRecording.cpp',
'skia/src/core/SkRecordOpts.cpp',
'skia/src/core/SkRecords.cpp',
'skia/src/core/SkRect.cpp',
'skia/src/core/SkRefDict.cpp',
'skia/src/core/SkRegion.cpp',
'skia/src/core/SkRegion_path.cpp',
'skia/src/core/SkRemote.cpp',
'skia/src/core/SkResourceCache.cpp',
'skia/src/core/SkRRect.cpp',
'skia/src/core/SkRTree.cpp',
'skia/src/core/SkRWBuffer.cpp',
'skia/src/core/SkScalar.cpp',
'skia/src/core/SkScalerContext.cpp',
'skia/src/core/SkScan.cpp',
'skia/src/core/SkScan_AntiPath.cpp',
'skia/src/core/SkScan_Hairline.cpp',
'skia/src/core/SkScan_Path.cpp',
'skia/src/core/SkSemaphore.cpp',
'skia/src/core/SkShader.cpp',
'skia/src/core/SkSharedMutex.cpp',
'skia/src/core/SkSpinlock.cpp',
'skia/src/core/SkSpriteBlitter_ARGB32.cpp',
'skia/src/core/SkSpriteBlitter_RGB16.cpp',
'skia/src/core/SkStream.cpp',
@ -139,7 +155,10 @@ UNIFIED_SOURCES += [
'skia/src/core/SkStroke.cpp',
'skia/src/core/SkStrokeRec.cpp',
'skia/src/core/SkStrokerPriv.cpp',
'skia/src/core/SkTileGrid.cpp',
'skia/src/core/SkTaskGroup.cpp',
'skia/src/core/SkTextBlob.cpp',
'skia/src/core/SkThreadID.cpp',
'skia/src/core/SkTime.cpp',
'skia/src/core/SkTLS.cpp',
'skia/src/core/SkTSearch.cpp',
'skia/src/core/SkTypeface.cpp',
@ -147,30 +166,33 @@ UNIFIED_SOURCES += [
'skia/src/core/SkUnPreMultiply.cpp',
'skia/src/core/SkUtils.cpp',
'skia/src/core/SkValidatingReadBuffer.cpp',
'skia/src/core/SkVarAlloc.cpp',
'skia/src/core/SkVertState.cpp',
'skia/src/core/SkWriteBuffer.cpp',
'skia/src/core/SkWriter32.cpp',
'skia/src/core/SkXfermode.cpp',
'skia/src/core/SkXfermodeInterpretation.cpp',
'skia/src/core/SkYUVPlanesCache.cpp',
'skia/src/doc/SkDocument.cpp',
'skia/src/effects/gradients/SkBitmapCache.cpp',
'skia/src/effects/gradients/SkClampRange.cpp',
'skia/src/effects/gradients/SkGradientBitmapCache.cpp',
'skia/src/effects/gradients/SkGradientShader.cpp',
'skia/src/effects/gradients/SkLinearGradient.cpp',
'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/gradients/SkTwoPointRadialGradient.cpp',
'skia/src/effects/GrCircleBlurFragmentProcessor.cpp',
'skia/src/effects/Sk1DPathEffect.cpp',
'skia/src/effects/Sk2DPathEffect.cpp',
'skia/src/effects/SkAlphaThresholdFilter.cpp',
'skia/src/effects/SkArcToPathEffect.cpp',
'skia/src/effects/SkArithmeticMode.cpp',
'skia/src/effects/SkAvoidXfermode.cpp',
'skia/src/effects/SkBitmapSource.cpp',
'skia/src/effects/SkBlurDrawLooper.cpp',
'skia/src/effects/SkBlurImageFilter.cpp',
'skia/src/effects/SkBlurMask.cpp',
'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',
@ -184,6 +206,7 @@ UNIFIED_SOURCES += [
'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',
'skia/src/effects/SkLerpXfermode.cpp',
@ -191,7 +214,6 @@ UNIFIED_SOURCES += [
'skia/src/effects/SkLumaColorFilter.cpp',
'skia/src/effects/SkMagnifierImageFilter.cpp',
'skia/src/effects/SkMatrixConvolutionImageFilter.cpp',
'skia/src/effects/SkMatrixImageFilter.cpp',
'skia/src/effects/SkMergeImageFilter.cpp',
'skia/src/effects/SkMorphologyImageFilter.cpp',
'skia/src/effects/SkOffsetImageFilter.cpp',
@ -199,131 +221,142 @@ UNIFIED_SOURCES += [
'skia/src/effects/SkPerlinNoiseShader.cpp',
'skia/src/effects/SkPictureImageFilter.cpp',
'skia/src/effects/SkPixelXorXfermode.cpp',
'skia/src/effects/SkPorterDuff.cpp',
'skia/src/effects/SkRectShaderImageFilter.cpp',
'skia/src/effects/SkStippleMaskFilter.cpp',
'skia/src/effects/SkTableColorFilter.cpp',
'skia/src/effects/SkTableMaskFilter.cpp',
'skia/src/effects/SkTestImageFilters.cpp',
'skia/src/effects/SkTileImageFilter.cpp',
'skia/src/effects/SkTransparentShader.cpp',
'skia/src/effects/SkXfermodeImageFilter.cpp',
'skia/src/fonts/SkFontMgr_indirect.cpp',
'skia/src/fonts/SkGScalerContext.cpp',
'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/GrCustomCoordsTextureEffect.cpp',
'skia/src/gpu/effects/GrCoverageSetOpXP.cpp',
'skia/src/gpu/effects/GrCustomXfermode.cpp',
'skia/src/gpu/effects/GrDashingEffect.cpp',
'skia/src/gpu/effects/GrDistanceFieldTextureEffect.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/GrGLCreateDebugInterface.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/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/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/GrGLProgram.cpp',
'skia/src/gpu/gl/GrGLProgramDesc.cpp',
'skia/src/gpu/gl/GrGLProgramEffects.cpp',
'skia/src/gpu/gl/GrGLRenderTarget.cpp',
'skia/src/gpu/gl/GrGLShaderBuilder.cpp',
'skia/src/gpu/gl/GrGLSL.cpp',
'skia/src/gpu/gl/GrGLStencilBuffer.cpp',
'skia/src/gpu/gl/GrGLTexture.cpp',
'skia/src/gpu/gl/GrGLUniformManager.cpp',
'skia/src/gpu/gl/GrGLUtil.cpp',
'skia/src/gpu/gl/GrGLVertexArray.cpp',
'skia/src/gpu/gl/GrGLVertexBuffer.cpp',
'skia/src/gpu/gl/GrGpuGL.cpp',
'skia/src/gpu/gl/GrGpuGL_program.cpp',
'skia/src/gpu/gl/SkGLContextHelper.cpp',
'skia/src/gpu/gl/SkGLContext.cpp',
'skia/src/gpu/gl/SkNullGLContext.cpp',
'skia/src/gpu/GrAAConvexPathRenderer.cpp',
'skia/src/gpu/GrAAHairLinePathRenderer.cpp',
'skia/src/gpu/GrAARectRenderer.cpp',
'skia/src/gpu/GrAllocPool.cpp',
'skia/src/gpu/GrAtlas.cpp',
'skia/src/gpu/GrBitmapTextContext.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/GrCacheID.cpp',
'skia/src/gpu/GrClipData.cpp',
'skia/src/gpu/GrClipMaskCache.cpp',
'skia/src/gpu/GrCaps.cpp',
'skia/src/gpu/GrClip.cpp',
'skia/src/gpu/GrClipMaskManager.cpp',
'skia/src/gpu/GrContext.cpp',
'skia/src/gpu/GrDefaultPathRenderer.cpp',
'skia/src/gpu/GrDrawState.cpp',
'skia/src/gpu/GrCoordTransform.cpp',
'skia/src/gpu/GrDefaultGeoProcFactory.cpp',
'skia/src/gpu/GrDrawingManager.cpp',
'skia/src/gpu/GrDrawTarget.cpp',
'skia/src/gpu/GrEffect.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/GrInOrderDrawBuffer.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/GrPictureUtils.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/GrResourceCache.cpp',
'skia/src/gpu/GrResourceProvider.cpp',
'skia/src/gpu/GrSoftwarePathRenderer.cpp',
'skia/src/gpu/GrStencil.cpp',
'skia/src/gpu/GrStencilAndCoverPathRenderer.cpp',
'skia/src/gpu/GrStencilAndCoverTextContext.cpp',
'skia/src/gpu/GrStencilBuffer.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/GrTextStrike.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_Gpu.cpp',
'skia/src/image/SkImage_Generator.cpp',
'skia/src/image/SkImage_Raster.cpp',
'skia/src/image/SkImagePriv.cpp',
'skia/src/image/SkImageShader.cpp',
'skia/src/image/SkSurface.cpp',
'skia/src/image/SkSurface_Gpu.cpp',
'skia/src/image/SkSurface_Raster.cpp',
@ -331,26 +364,27 @@ UNIFIED_SOURCES += [
'skia/src/images/SkDecodingImageGenerator.cpp',
'skia/src/images/SkPageFlipper.cpp',
'skia/src/images/SkScaledBitmapSampler.cpp',
'skia/src/lazy/SkCachingPixelRef.cpp',
'skia/src/lazy/SkDiscardableMemoryPool.cpp',
'skia/src/lazy/SkDiscardablePixelRef.cpp',
'skia/src/pathops/SkAddIntersections.cpp',
'skia/src/pathops/SkDCubicIntersection.cpp',
'skia/src/pathops/SkDConicLineIntersection.cpp',
'skia/src/pathops/SkDCubicLineIntersection.cpp',
'skia/src/pathops/SkDCubicToQuads.cpp',
'skia/src/pathops/SkDLineIntersection.cpp',
'skia/src/pathops/SkDQuadImplicit.cpp',
'skia/src/pathops/SkDQuadIntersection.cpp',
'skia/src/pathops/SkDQuadLineIntersection.cpp',
'skia/src/pathops/SkIntersections.cpp',
'skia/src/pathops/SkOpAngle.cpp',
'skia/src/pathops/SkOpBuilder.cpp',
'skia/src/pathops/SkOpCoincidence.cpp',
'skia/src/pathops/SkOpContour.cpp',
'skia/src/pathops/SkOpCubicHull.cpp',
'skia/src/pathops/SkOpEdgeBuilder.cpp',
'skia/src/pathops/SkOpSegment.cpp',
'skia/src/pathops/SkPathOpsBounds.cpp',
'skia/src/pathops/SkOpSpan.cpp',
'skia/src/pathops/SkPathOpsCommon.cpp',
'skia/src/pathops/SkPathOpsConic.cpp',
'skia/src/pathops/SkPathOpsCubic.cpp',
'skia/src/pathops/SkPathOpsDebug.cpp',
'skia/src/pathops/SkPathOpsCurve.cpp',
'skia/src/pathops/SkPathOpsLine.cpp',
'skia/src/pathops/SkPathOpsOp.cpp',
'skia/src/pathops/SkPathOpsPoint.cpp',
@ -358,21 +392,24 @@ UNIFIED_SOURCES += [
'skia/src/pathops/SkPathOpsRect.cpp',
'skia/src/pathops/SkPathOpsSimplify.cpp',
'skia/src/pathops/SkPathOpsTightBounds.cpp',
'skia/src/pathops/SkPathOpsTriangle.cpp',
'skia/src/pathops/SkPathOpsTSect.cpp',
'skia/src/pathops/SkPathOpsTypes.cpp',
'skia/src/pathops/SkPathOpsWinding.cpp',
'skia/src/pathops/SkPathWriter.cpp',
'skia/src/pathops/SkQuarticRoot.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/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',
'skia/src/utils/SkBoundaryPatch.cpp',
'skia/src/utils/SkCamera.cpp',
@ -381,11 +418,10 @@ UNIFIED_SOURCES += [
'skia/src/utils/SkCubicInterval.cpp',
'skia/src/utils/SkCullPoints.cpp',
'skia/src/utils/SkDashPath.cpp',
'skia/src/utils/SkDeferredCanvas.cpp',
'skia/src/utils/SkDumpCanvas.cpp',
'skia/src/utils/SkEventTracer.cpp',
'skia/src/utils/SkFrontBufferedStream.cpp',
'skia/src/utils/SkGatherPixelRefsAndRects.cpp',
'skia/src/utils/SkImageGeneratorUtils.cpp',
'skia/src/utils/SkInterpolator.cpp',
'skia/src/utils/SkLayer.cpp',
'skia/src/utils/SkMatrix22.cpp',
@ -395,16 +431,17 @@ UNIFIED_SOURCES += [
'skia/src/utils/SkNullCanvas.cpp',
'skia/src/utils/SkNWayCanvas.cpp',
'skia/src/utils/SkOSFile.cpp',
'skia/src/utils/SkPaintFilterCanvas.cpp',
'skia/src/utils/SkParseColor.cpp',
'skia/src/utils/SkParsePath.cpp',
'skia/src/utils/SkPathUtils.cpp',
'skia/src/utils/SkPictureUtils.cpp',
'skia/src/utils/SkProxyCanvas.cpp',
'skia/src/utils/SkPatchGrid.cpp',
'skia/src/utils/SkPatchUtils.cpp',
'skia/src/utils/SkRTConf.cpp',
'skia/src/utils/SkTextBox.cpp',
'skia/src/utils/SkTextureCompressor.cpp',
'skia/src/utils/SkTextureCompressor_ASTC.cpp',
'skia/src/utils/SkTextureCompressor_LATC.cpp',
'skia/src/utils/SkTextureCompressor_R11EAC.cpp',
'skia/src/utils/SkWhitelistTypefaces.cpp',
]
SOURCES += [
'skia/src/core/SkAdvancedTypefaceMetrics.cpp',
@ -414,33 +451,93 @@ SOURCES += [
'skia/src/core/SkBlitter_RGB16.cpp',
'skia/src/core/SkBlitter_Sprite.cpp',
'skia/src/core/SkFontHost.cpp',
'skia/src/core/SkOpts.cpp',
'skia/src/core/SkPictureData.cpp',
'skia/src/core/SkScaledImageCache.cpp',
'skia/src/core/SkRecorder.cpp',
'skia/src/core/SkScan_Antihair.cpp',
'skia/src/gpu/GrAddPathRenderers_default.cpp',
'skia/src/gpu/GrDistanceFieldTextContext.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_WIDGET_TOOLKIT'] in ('android', 'gonk'):
UNIFIED_SOURCES += [
'skia/src/ports/SkDebug_android.cpp',
'skia/src/ports/SkOSFile_posix.cpp',
'skia/src/ports/SkOSLibrary_posix.cpp',
'skia/src/ports/SkTime_Unix.cpp',
'skia/src/ports/SkTLS_pthread.cpp',
'skia/src/utils/SkThreadUtils_pthread.cpp',
]
SOURCES += [
'skia/src/ports/SkFontHost_android_old.cpp',
'skia/src/ports/SkFontHost_cairo.cpp',
'skia/src/ports/SkFontHost_FreeType.cpp',
'skia/src/ports/SkFontHost_FreeType_common.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in {'cocoa', 'uikit'}:
UNIFIED_SOURCES += [
'skia/src/ports/SkDebug_stdio.cpp',
'skia/src/ports/SkOSFile_posix.cpp',
'skia/src/ports/SkOSLibrary_posix.cpp',
'skia/src/ports/SkTime_Unix.cpp',
'skia/src/ports/SkTLS_pthread.cpp',
'skia/src/utils/mac/SkCreateCGImageRef.cpp',
@ -454,35 +551,36 @@ if CONFIG['MOZ_WIDGET_GTK']:
UNIFIED_SOURCES += [
'skia/src/ports/SkDebug_stdio.cpp',
'skia/src/ports/SkOSFile_posix.cpp',
'skia/src/ports/SkOSLibrary_posix.cpp',
'skia/src/ports/SkTime_Unix.cpp',
'skia/src/ports/SkTLS_pthread.cpp',
'skia/src/utils/SkThreadUtils_pthread.cpp',
]
SOURCES += [
'skia/src/ports/SkFontHost_cairo.cpp',
'skia/src/ports/SkFontHost_FreeType.cpp',
'skia/src/ports/SkFontHost_FreeType_common.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
UNIFIED_SOURCES += [
'skia/src/ports/SkDebug_stdio.cpp',
'skia/src/ports/SkOSFile_posix.cpp',
'skia/src/ports/SkOSLibrary_posix.cpp',
'skia/src/ports/SkTime_Unix.cpp',
'skia/src/ports/SkTLS_pthread.cpp',
'skia/src/utils/SkThreadUtils_pthread.cpp',
]
SOURCES += [
'skia/src/ports/SkFontHost_cairo.cpp',
'skia/src/ports/SkFontHost_FreeType.cpp',
'skia/src/ports/SkFontHost_FreeType_common.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [
'skia/src/ports/SkDebug_win.cpp',
'skia/src/ports/SkFontHost_win.cpp',
'skia/src/ports/SkFontMgr_default_dw.cpp',
'skia/src/ports/SkFontMgr_win_dw.cpp',
'skia/src/ports/SkFontMgr_win_dw_factory.cpp',
'skia/src/ports/SkOSFile_win.cpp',
'skia/src/ports/SkOSLibrary_win.cpp',
'skia/src/ports/SkRemotableFontMgr_win_dw.cpp',
'skia/src/ports/SkScalerContext_win_dw.cpp',
'skia/src/ports/SkTime_win.cpp',
@ -497,32 +595,22 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'skia/src/utils/win/SkIStream.cpp',
]
if CONFIG['INTEL_ARCHITECTURE']:
UNIFIED_SOURCES += [
'skia/src/opts/SkTextureCompression_opts_none.cpp',
]
SOURCES += [
'skia/src/opts/opts_check_x86.cpp',
'skia/src/opts/SkBitmapFilter_opts_SSE2.cpp',
'skia/src/opts/SkBitmapProcState_opts_SSE2.cpp',
'skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp',
'skia/src/opts/SkBlitRect_opts_SSE2.cpp',
'skia/src/opts/SkBlitRow_opts_SSE2.cpp',
'skia/src/opts/SkBlurImage_opts_SSE2.cpp',
'skia/src/opts/SkBlurImage_opts_SSE4.cpp',
'skia/src/opts/SkMorphology_opts_SSE2.cpp',
'skia/src/opts/SkUtils_opts_SSE2.cpp',
'skia/src/opts/SkXfermode_opts_SSE2.cpp',
'skia/src/opts/SkBlitRow_opts_SSE4.cpp',
'skia/src/opts/SkOpts_avx.cpp',
'skia/src/opts/SkOpts_sse41.cpp',
'skia/src/opts/SkOpts_ssse3.cpp',
]
elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
UNIFIED_SOURCES += [
'skia/src/core/SkUtilsArm.cpp',
'skia/src/opts/SkBitmapProcState_opts_arm.cpp',
'skia/src/opts/SkBlitMask_opts_arm.cpp',
'skia/src/opts/SkBlurImage_opts_arm.cpp',
'skia/src/opts/SkMorphology_opts_arm.cpp',
'skia/src/opts/SkTextureCompression_opts_arm.cpp',
'skia/src/opts/SkUtils_opts_arm.cpp',
'skia/src/opts/SkXfermode_opts_arm.cpp',
]
SOURCES += [
'skia/src/opts/SkBlitRow_opts_arm.cpp',
@ -533,61 +621,27 @@ elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
'skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp',
'skia/src/opts/SkBlitMask_opts_arm_neon.cpp',
'skia/src/opts/SkBlitRow_opts_arm_neon.cpp',
'skia/src/opts/SkBlurImage_opts_neon.cpp',
'skia/src/opts/SkMorphology_opts_neon.cpp',
'skia/src/opts/SkTextureCompression_opts_neon.cpp',
'skia/src/opts/SkXfermode_opts_arm_neon.cpp',
'skia/src/opts/SkOpts_neon.cpp',
]
SOURCES['skia/src/opts/SkBitmapProcState_arm_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkBlitMask_opts_arm_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkBlitRow_opts_arm_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkBlurImage_opts_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkMorphology_opts_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkTextureCompression_opts_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkXfermode_opts_arm_neon.cpp'].flags += ['-mfpu=neon']
SOURCES['skia/src/opts/SkOpts_neon.cpp'].flags += ['-mfpu=neon']
else:
UNIFIED_SOURCES += [
'skia/src/opts/SkBitmapProcState_opts_none.cpp',
'skia/src/opts/SkBlitMask_opts_none.cpp',
'skia/src/opts/SkBlitRow_opts_none.cpp',
'skia/src/opts/SkBlurImage_opts_none.cpp',
'skia/src/opts/SkMorphology_opts_none.cpp',
'skia/src/opts/SkTextureCompression_opts_none.cpp',
'skia/src/opts/SkUtils_opts_none.cpp',
'skia/src/opts/SkXfermode_opts_none.cpp',
]
# can we find a better way of dealing with asm sources?
# left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
#XXX: doesn't build with Apple's assembler
if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC'] and CONFIG['OS_TARGET'] != 'Darwin':
SOURCES += [
'skia/src/opts/memset.arm.S',
]
if CONFIG['BUILD_ARM_NEON']:
SOURCES += [
'skia/src/opts/memset16_neon.S',
'skia/src/opts/memset32_neon.S',
]
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC'] and CONFIG['OS_ARCH'] != 'WINNT':
if CONFIG['CPU_ARCH'] == 'x86_64':
SOURCES += [
'skia/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
]
else:
SOURCES += [
'skia/src/opts/SkBlitRow_opts_SSE4_asm.S',
]
# We allow warnings for third-party code that can be updated from upstream.
ALLOW_COMPILER_WARNINGS = True
FINAL_LIBRARY = 'gkmedias'
LOCAL_INCLUDES += [
'skia/include/c',
'skia/include/config',
'skia/include/core',
'skia/include/effects',
@ -596,6 +650,7 @@ LOCAL_INCLUDES += [
'skia/include/pathops',
'skia/include/pipe',
'skia/include/ports',
'skia/include/private',
'skia/include/utils',
'skia/include/utils/mac',
'skia/include/utils/win',
@ -613,16 +668,16 @@ LOCAL_INCLUDES += [
'skia/src/utils/win',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'qt', 'gonk', 'cocoa', 'uikit'):
DEFINES['SK_USE_POSIX_THREADS'] = 1
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']:
DEFINES['SK_BUILD_SSSE3'] = 1
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0
if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt') or CONFIG['MOZ_WIDGET_GTK']:
if CONFIG['MOZ_WIDGET_TOOLKIT'] in {
'android',
'cocoa',
'uikit',
'gonk',
'qt',
} or CONFIG['MOZ_WIDGET_GTK']:
DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
# We should autogenerate these SSE related flags.
@ -630,37 +685,33 @@ if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or (CONFIG['MOZ_WIDGET_TOOLKIT
if CONFIG['_MSC_VER']:
# MSVC doesn't need special compiler flags, but Skia needs to be told that these files should
# be built with the required SSE level or it will simply compile in stubs and cause runtime crashes
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkBlitRect_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkMorphology_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkUtils_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkXfermode_opts_SSE2.cpp'].flags += ['-DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=20']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=31']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['/arch:SSE2 -DSK_CPU_SSE_LEVEL=41']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['/arch:AVX -DSK_CPU_SSE_LEVEL=51']
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['GNU_CC']:
SOURCES['skia/src/opts/SkBitmapFilter_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkBlitRect_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkMorphology_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkUtils_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkXfermode_opts_SSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC'] and CONFIG['BUILD_ARM_NEON']:
DEFINES['__ARM_HAVE_OPTIONAL_NEON_SUPPORT'] = 1
DEFINES['USE_ANDROID_NDK_CPU_FEATURES'] = 0
DEFINES['SK_ARM_HAS_OPTIONAL_NEON'] = 1
elif CONFIG['CLANG_CL']:
SOURCES['skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkBlurImage_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkBlitRow_opts_SSE4.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_ssse3.cpp'].flags += ['-mssse3']
SOURCES['skia/src/opts/SkOpts_sse41.cpp'].flags += ['-msse4.1']
SOURCES['skia/src/opts/SkOpts_avx.cpp'].flags += ['-mavx']
DEFINES['SKIA_IMPLEMENTATION'] = 1
DEFINES['GR_IMPLEMENTATION'] = 1
if CONFIG['GNU_CXX']:
CXXFLAGS += [
@ -676,6 +727,8 @@ if CONFIG['GNU_CXX']:
'-Wno-macro-redefined',
'-Wno-unused-private-field',
]
# work around inline function linking bug with template arguments
SOURCES['skia/src/gpu/GrResourceCache.cpp'].flags += ['-fkeep-inline-functions']
else:
CXXFLAGS += [
'-Wno-logical-op',

View File

@ -0,0 +1,29 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBRDAllocator_DEFINED
#define SkBRDAllocator_DEFINED
#include "SkBitmap.h"
#include "SkCodec.h"
/**
* Abstract subclass of SkBitmap's allocator.
* Allows the allocator to indicate if the memory it allocates
* is zero initialized.
*/
class SkBRDAllocator : public SkBitmap::Allocator {
public:
/**
* Indicates if the memory allocated by this allocator is
* zero initialized.
*/
virtual SkCodec::ZeroInitialized zeroInit() const = 0;
};
#endif // SkBRDAllocator_DEFINED

View File

@ -0,0 +1,90 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBitmapRegionDecoder_DEFINED
#define SkBitmapRegionDecoder_DEFINED
#include "SkBitmap.h"
#include "SkBRDAllocator.h"
#include "SkEncodedFormat.h"
#include "SkStream.h"
/*
* This class aims to provide an interface to test multiple implementations of
* SkBitmapRegionDecoder.
*/
class SkBitmapRegionDecoder {
public:
enum Strategy {
kCanvas_Strategy, // Draw to the canvas, uses SkCodec
kAndroidCodec_Strategy, // Uses SkAndroidCodec for scaling and subsetting
};
/*
* @param data Refs the data while this object exists, unrefs on destruction
* @param strategy Strategy used for scaling and subsetting
* @return Tries to create an SkBitmapRegionDecoder, returns NULL on failure
*/
static SkBitmapRegionDecoder* Create(
SkData* data, Strategy strategy);
/*
* @param stream Takes ownership of the stream
* @param strategy Strategy used for scaling and subsetting
* @return Tries to create an SkBitmapRegionDecoder, returns NULL on failure
*/
static SkBitmapRegionDecoder* Create(
SkStreamRewindable* stream, Strategy strategy);
/*
* Decode a scaled region of the encoded image stream
*
* @param bitmap Container for decoded pixels. It is assumed that the pixels
* are initially unallocated and will be allocated by this function.
* @param allocator Allocator for the pixels. If this is NULL, the default
* allocator (HeapAllocator) will be used.
* @param desiredSubset Subset of the original image to decode.
* @param sampleSize An integer downscaling factor for the decode.
* @param colorType Preferred output colorType.
* New implementations should return NULL if they do not support
* decoding to this color type.
* The old kOriginal_Strategy will decode to a default color type
* if this color type is unsupported.
* @param requireUnpremul If the image is not opaque, we will use this to determine the
* alpha type to use.
*
*/
virtual bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
const SkIRect& desiredSubset, int sampleSize,
SkColorType colorType, bool requireUnpremul) = 0;
/*
* @param Requested destination color type
* @return true if we support the requested color type and false otherwise
*/
virtual bool conversionSupported(SkColorType colorType) = 0;
virtual SkEncodedFormat getEncodedFormat() = 0;
int width() const { return fWidth; }
int height() const { return fHeight; }
virtual ~SkBitmapRegionDecoder() {}
protected:
SkBitmapRegionDecoder(int width, int height)
: fWidth(width)
, fHeight(height)
{}
private:
const int fWidth;
const int fHeight;
};
#endif

View File

@ -0,0 +1,154 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_canvas_DEFINED
#define sk_canvas_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Save the current matrix and clip on the canvas. When the
balancing call to sk_canvas_restore() is made, the previous matrix
and clip are restored.
*/
SK_API void sk_canvas_save(sk_canvas_t*);
/**
This behaves the same as sk_canvas_save(), but in addition it
allocates an offscreen surface. All drawing calls are directed
there, and only when the balancing call to sk_canvas_restore() is
made is that offscreen transfered to the canvas (or the previous
layer).
@param sk_rect_t* (may be null) This rect, if non-null, is used as
a hint to limit the size of the offscreen, and
thus drawing may be clipped to it, though that
clipping is not guaranteed to happen. If exact
clipping is desired, use sk_canvas_clip_rect().
@param sk_paint_t* (may be null) The paint is copied, and is applied
to the offscreen when sk_canvas_restore() is
called.
*/
SK_API void sk_canvas_save_layer(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
/**
This call balances a previous call to sk_canvas_save() or
sk_canvas_save_layer(), and is used to remove all modifications to
the matrix and clip state since the last save call. It is an
error to call sk_canvas_restore() more times than save and
save_layer were called.
*/
SK_API void sk_canvas_restore(sk_canvas_t*);
/**
Preconcat the current coordinate transformation matrix with the
specified translation.
*/
SK_API void sk_canvas_translate(sk_canvas_t*, float dx, float dy);
/**
Preconcat the current coordinate transformation matrix with the
specified scale.
*/
SK_API void sk_canvas_scale(sk_canvas_t*, float sx, float sy);
/**
Preconcat the current coordinate transformation matrix with the
specified rotation in degrees.
*/
SK_API void sk_canvas_rotate_degrees(sk_canvas_t*, float degrees);
/**
Preconcat the current coordinate transformation matrix with the
specified rotation in radians.
*/
SK_API void sk_canvas_rotate_radians(sk_canvas_t*, float radians);
/**
Preconcat the current coordinate transformation matrix with the
specified skew.
*/
SK_API void sk_canvas_skew(sk_canvas_t*, float sx, float sy);
/**
Preconcat the current coordinate transformation matrix with the
specified matrix.
*/
SK_API void sk_canvas_concat(sk_canvas_t*, const sk_matrix_t*);
/**
Modify the current clip with the specified rectangle. The new
current clip will be the intersection of the old clip and the
rectange.
*/
SK_API void sk_canvas_clip_rect(sk_canvas_t*, const sk_rect_t*);
/**
Modify the current clip with the specified path. The new
current clip will be the intersection of the old clip and the
path.
*/
SK_API void sk_canvas_clip_path(sk_canvas_t*, const sk_path_t*);
/**
Fill the entire canvas (restricted to the current clip) with the
specified paint.
*/
SK_API void sk_canvas_draw_paint(sk_canvas_t*, const sk_paint_t*);
/**
Draw the specified rectangle using the specified paint. The
rectangle will be filled or stroked based on the style in the
paint.
*/
SK_API void sk_canvas_draw_rect(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
/**
Draw the specified oval using the specified paint. The oval will be
filled or framed based on the style in the paint
*/
SK_API void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
/**
Draw the specified path using the specified paint. The path will be
filled or framed based on the style in the paint
*/
SK_API void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*);
/**
Draw the specified image, with its top/left corner at (x,y), using
the specified paint, transformed by the current matrix.
@param sk_paint_t* (may be NULL) the paint used to draw the image.
*/
SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*,
float x, float y, const sk_paint_t*);
/**
Draw the specified image, scaling and translating so that it fills
the specified dst rect. If the src rect is non-null, only that
subset of the image is transformed and drawn.
@param sk_paint_t* (may be NULL) The paint used to draw the image.
*/
SK_API void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*,
const sk_rect_t* src,
const sk_rect_t* dst, const sk_paint_t*);
/**
Draw the picture into this canvas (replay the pciture's drawing commands).
@param sk_matrix_t* If non-null, apply that matrix to the CTM when
drawing this picture. This is logically
equivalent to: save, concat, draw_picture,
restore.
@param sk_paint_t* If non-null, draw the picture into a temporary
buffer, and then apply the paint's alpha,
colorfilter, imagefilter, and xfermode to that
buffer as it is drawn to the canvas. This is
logically equivalent to save_layer(paint),
draw_picture, restore.
*/
SK_API void sk_canvas_draw_picture(sk_canvas_t*, const sk_picture_t*,
const sk_matrix_t*, const sk_paint_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,70 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_data_DEFINED
#define sk_data_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Returns a new empty sk_data_t. This call must be balanced with a call to
sk_data_unref().
*/
SK_API sk_data_t* sk_data_new_empty();
/**
Returns a new sk_data_t by copying the specified source data.
This call must be balanced with a call to sk_data_unref().
*/
SK_API sk_data_t* sk_data_new_with_copy(const void* src, size_t length);
/**
Pass ownership of the given memory to a new sk_data_t, which will
call free() when the refernce count of the data goes to zero. For
example:
size_t length = 1024;
void* buffer = malloc(length);
memset(buffer, 'X', length);
sk_data_t* data = sk_data_new_from_malloc(buffer, length);
This call must be balanced with a call to sk_data_unref().
*/
SK_API sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length);
/**
Returns a new sk_data_t using a subset of the data in the
specified source sk_data_t. This call must be balanced with a
call to sk_data_unref().
*/
SK_API sk_data_t* sk_data_new_subset(const sk_data_t* src, size_t offset, size_t length);
/**
Increment the reference count on the given sk_data_t. Must be
balanced by a call to sk_data_unref().
*/
SK_API void sk_data_ref(const sk_data_t*);
/**
Decrement the reference count. If the reference count is 1 before
the decrement, then release both the memory holding the sk_data_t
and the memory it is managing. New sk_data_t are created with a
reference count of 1.
*/
SK_API void sk_data_unref(const sk_data_t*);
/**
Returns the number of bytes stored.
*/
SK_API size_t sk_data_get_size(const sk_data_t*);
/**
Returns the pointer to the data.
*/
SK_API const void* sk_data_get_data(const sk_data_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_image_DEFINED
#define sk_image_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
* Return a new image that has made a copy of the provided pixels, or NULL on failure.
* Balance with a call to sk_image_unref().
*/
SK_API sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes);
/**
* If the specified data can be interpreted as a compressed image (e.g. PNG or JPEG) then this
* returns an image. If the encoded data is not supported, returns NULL.
*
* On success, the encoded data may be processed immediately, or it may be ref()'d for later
* use.
*/
SK_API sk_image_t* sk_image_new_from_encoded(const sk_data_t* encoded, const sk_irect_t* subset);
/**
* Encode the image's pixels and return the result as a new PNG in a
* sk_data_t, which the caller must manage: call sk_data_unref() when
* they are done.
*
* If the image type cannot be encoded, this will return NULL.
*/
SK_API sk_data_t* sk_image_encode(const sk_image_t*);
/**
* Increment the reference count on the given sk_image_t. Must be
* balanced by a call to sk_image_unref().
*/
SK_API void sk_image_ref(const sk_image_t*);
/**
* Decrement the reference count. If the reference count is 1 before
* the decrement, then release both the memory holding the sk_image_t
* and the memory it is managing. New sk_image_t are created with a
reference count of 1.
*/
SK_API void sk_image_unref(const sk_image_t*);
/**
* Return the width of the sk_image_t/
*/
SK_API int sk_image_get_width(const sk_image_t*);
/**
* Return the height of the sk_image_t/
*/
SK_API int sk_image_get_height(const sk_image_t*);
/**
* Returns a non-zero value unique among all images.
*/
SK_API uint32_t sk_image_get_unique_id(const sk_image_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_maskfilter_DEFINED
#define sk_maskfilter_DEFINED
#include "sk_types.h"
typedef enum {
NORMAL_SK_BLUR_STYLE, //!< fuzzy inside and outside
SOLID_SK_BLUR_STYLE, //!< solid inside, fuzzy outside
OUTER_SK_BLUR_STYLE, //!< nothing inside, fuzzy outside
INNER_SK_BLUR_STYLE, //!< fuzzy inside, nothing outside
} sk_blurstyle_t;
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Increment the reference count on the given sk_maskfilter_t. Must be
balanced by a call to sk_maskfilter_unref().
*/
void sk_maskfilter_ref(sk_maskfilter_t*);
/**
Decrement the reference count. If the reference count is 1 before
the decrement, then release both the memory holding the
sk_maskfilter_t and any other associated resources. New
sk_maskfilter_t are created with a reference count of 1.
*/
void sk_maskfilter_unref(sk_maskfilter_t*);
/**
Create a blur maskfilter.
@param sk_blurstyle_t The SkBlurStyle to use
@param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
*/
sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_matrix_DEFINED
#define sk_matrix_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/** Set the matrix to identity */
void sk_matrix_set_identity(sk_matrix_t*);
/** Set the matrix to translate by (tx, ty). */
void sk_matrix_set_translate(sk_matrix_t*, float tx, float ty);
/**
Preconcats the matrix with the specified translation.
M' = M * T(dx, dy)
*/
void sk_matrix_pre_translate(sk_matrix_t*, float tx, float ty);
/**
Postconcats the matrix with the specified translation.
M' = T(dx, dy) * M
*/
void sk_matrix_post_translate(sk_matrix_t*, float tx, float ty);
/** Set the matrix to scale by sx and sy. */
void sk_matrix_set_scale(sk_matrix_t*, float sx, float sy);
/**
Preconcats the matrix with the specified scale.
M' = M * S(sx, sy)
*/
void sk_matrix_pre_scale(sk_matrix_t*, float sx, float sy);
/**
Postconcats the matrix with the specified scale.
M' = S(sx, sy) * M
*/
void sk_matrix_post_scale(sk_matrix_t*, float sx, float sy);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,145 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_paint_DEFINED
#define sk_paint_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Create a new paint with default settings:
antialias : false
stroke : false
stroke width : 0.0f (hairline)
stroke miter : 4.0f
stroke cap : BUTT_SK_STROKE_CAP
stroke join : MITER_SK_STROKE_JOIN
color : opaque black
shader : NULL
maskfilter : NULL
xfermode_mode : SRCOVER_SK_XFERMODE_MODE
*/
SK_API sk_paint_t* sk_paint_new();
/**
Release the memory storing the sk_paint_t and unref() all
associated objects.
*/
SK_API void sk_paint_delete(sk_paint_t*);
/**
Return true iff the paint has antialiasing enabled.
*/
SK_API bool sk_paint_is_antialias(const sk_paint_t*);
/**
Set to true to enable antialiasing, false to disable it on this
sk_paint_t.
*/
SK_API void sk_paint_set_antialias(sk_paint_t*, bool);
/**
Return the paint's curent drawing color.
*/
SK_API sk_color_t sk_paint_get_color(const sk_paint_t*);
/**
Set the paint's curent drawing color.
*/
SK_API void sk_paint_set_color(sk_paint_t*, sk_color_t);
/* stroke settings */
/**
Return true iff stroking is enabled rather than filling on this
sk_paint_t.
*/
SK_API bool sk_paint_is_stroke(const sk_paint_t*);
/**
Set to true to enable stroking rather than filling with this
sk_paint_t.
*/
SK_API void sk_paint_set_stroke(sk_paint_t*, bool);
/**
Return the width for stroking. A value of 0 strokes in hairline mode.
*/
SK_API float sk_paint_get_stroke_width(const sk_paint_t*);
/**
Set the width for stroking. A value of 0 strokes in hairline mode
(always draw 1-pixel wide, regardless of the matrix).
*/
SK_API void sk_paint_set_stroke_width(sk_paint_t*, float width);
/**
Return the paint's stroke miter value. This is used to control the
behavior of miter joins when the joins angle is sharp.
*/
SK_API float sk_paint_get_stroke_miter(const sk_paint_t*);
/**
Set the paint's stroke miter value. This is used to control the
behavior of miter joins when the joins angle is sharp. This value
must be >= 0.
*/
SK_API void sk_paint_set_stroke_miter(sk_paint_t*, float miter);
typedef enum {
BUTT_SK_STROKE_CAP,
ROUND_SK_STROKE_CAP,
SQUARE_SK_STROKE_CAP
} sk_stroke_cap_t;
/**
Return the paint's stroke cap type, controlling how the start and
end of stroked lines and paths are treated.
*/
SK_API sk_stroke_cap_t sk_paint_get_stroke_cap(const sk_paint_t*);
/**
Set the paint's stroke cap type, controlling how the start and
end of stroked lines and paths are treated.
*/
SK_API void sk_paint_set_stroke_cap(sk_paint_t*, sk_stroke_cap_t);
typedef enum {
MITER_SK_STROKE_JOIN,
ROUND_SK_STROKE_JOIN,
BEVEL_SK_STROKE_JOIN
} sk_stroke_join_t;
/**
Return the paint's stroke join type, specifies the treatment that
is applied to corners in paths and rectangles
*/
SK_API sk_stroke_join_t sk_paint_get_stroke_join(const sk_paint_t*);
/**
Set the paint's stroke join type, specifies the treatment that
is applied to corners in paths and rectangles
*/
SK_API void sk_paint_set_stroke_join(sk_paint_t*, sk_stroke_join_t);
/**
* Set the paint's shader to the specified parameter. This will automatically call unref() on
* any previous value, and call ref() on the new value.
*/
SK_API void sk_paint_set_shader(sk_paint_t*, sk_shader_t*);
/**
* Set the paint's maskfilter to the specified parameter. This will automatically call unref() on
* any previous value, and call ref() on the new value.
*/
SK_API void sk_paint_set_maskfilter(sk_paint_t*, sk_maskfilter_t*);
/**
* Set the paint's xfermode to the specified parameter.
*/
SK_API void sk_paint_set_xfermode_mode(sk_paint_t*, sk_xfermode_mode_t);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,84 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_path_DEFINED
#define sk_path_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
typedef enum {
CW_SK_PATH_DIRECTION,
CCW_SK_PATH_DIRECTION,
} sk_path_direction_t;
/** Create a new, empty path. */
SK_API sk_path_t* sk_path_new();
/** Release the memory used by a sk_path_t. */
SK_API void sk_path_delete(sk_path_t*);
/** Set the beginning of the next contour to the point (x,y). */
SK_API void sk_path_move_to(sk_path_t*, float x, float y);
/**
Add a line from the last point to the specified point (x,y). If no
sk_path_move_to() call has been made for this contour, the first
point is automatically set to (0,0).
*/
SK_API void sk_path_line_to(sk_path_t*, float x, float y);
/**
Add a quadratic bezier from the last point, approaching control
point (x0,y0), and ending at (x1,y1). If no sk_path_move_to() call
has been made for this contour, the first point is automatically
set to (0,0).
*/
SK_API void sk_path_quad_to(sk_path_t*, float x0, float y0, float x1, float y1);
/**
Add a conic curve from the last point, approaching control point
(x0,y01), and ending at (x1,y1) with weight w. If no
sk_path_move_to() call has been made for this contour, the first
point is automatically set to (0,0).
*/
SK_API void sk_path_conic_to(sk_path_t*, float x0, float y0, float x1, float y1, float w);
/**
Add a cubic bezier from the last point, approaching control points
(x0,y0) and (x1,y1), and ending at (x2,y2). If no
sk_path_move_to() call has been made for this contour, the first
point is automatically set to (0,0).
*/
SK_API void sk_path_cubic_to(sk_path_t*,
float x0, float y0,
float x1, float y1,
float x2, float y2);
/**
Close the current contour. If the current point is not equal to the
first point of the contour, a line segment is automatically added.
*/
SK_API void sk_path_close(sk_path_t*);
/**
Add a closed rectangle contour to the path.
*/
SK_API void sk_path_add_rect(sk_path_t*, const sk_rect_t*, sk_path_direction_t);
/**
Add a closed oval contour to the path
*/
SK_API void sk_path_add_oval(sk_path_t*, const sk_rect_t*, sk_path_direction_t);
/**
* If the path is empty, return false and set the rect parameter to [0, 0, 0, 0].
* else return true and set the rect parameter to the bounds of the control-points
* of the path.
*/
SK_API bool sk_path_get_bounds(const sk_path_t*, sk_rect_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,70 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_picture_DEFINED
#define sk_picture_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Create a new sk_picture_recorder_t. Its resources should be
released with a call to sk_picture_recorder_delete().
*/
sk_picture_recorder_t* sk_picture_recorder_new();
/**
Release the memory and other resources used by this
sk_picture_recorder_t.
*/
void sk_picture_recorder_delete(sk_picture_recorder_t*);
/**
Returns the canvas that records the drawing commands
@param sk_rect_t* the cull rect used when recording this
picture. Any drawing the falls outside of this
rect is undefined, and may be drawn or it may not.
*/
sk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t*, const sk_rect_t*);
/**
Signal that the caller is done recording. This invalidates the
canvas returned by begin_recording. Ownership of the sk_picture_t
is passed to the caller, who must call sk_picture_unref() when
they are done using it. The returned picture is immutable.
*/
sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t*);
/**
Increment the reference count on the given sk_picture_t. Must be
balanced by a call to sk_picture_unref().
*/
void sk_picture_ref(sk_picture_t*);
/**
Decrement the reference count. If the reference count is 1 before
the decrement, then release both the memory holding the
sk_picture_t and any resouces it may be managing. New
sk_picture_t are created with a reference count of 1.
*/
void sk_picture_unref(sk_picture_t*);
/**
Returns a non-zero value unique among all pictures.
*/
uint32_t sk_picture_get_unique_id(sk_picture_t*);
/**
Return the cull rect specified when this picture was recorded.
*/
sk_rect_t sk_picture_get_bounds(sk_picture_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,143 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_shader_DEFINED
#define sk_shader_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
void sk_shader_ref(sk_shader_t*);
void sk_shader_unref(sk_shader_t*);
typedef enum {
CLAMP_SK_SHADER_TILEMODE,
REPEAT_SK_SHADER_TILEMODE,
MIRROR_SK_SHADER_TILEMODE,
} sk_shader_tilemode_t;
/**
Returns a shader that generates a linear gradient between the two
specified points.
@param points The start and end points for the gradient.
@param colors The array[count] of colors, to be distributed between
the two points
@param colorPos May be NULL. array[count] of SkScalars, or NULL, of
the relative position of each corresponding color
in the colors array. If this is NULL, the the
colors are distributed evenly between the start
and end point. If this is not null, the values
must begin with 0, end with 1.0, and intermediate
values must be strictly increasing.
@param colorCount Must be >=2. The number of colors (and pos if not
NULL) entries.
@param mode The tiling mode
*/
sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t points[2],
const sk_color_t colors[],
const float colorPos[],
int colorCount,
sk_shader_tilemode_t tileMode,
const sk_matrix_t* localMatrix);
/**
Returns a shader that generates a radial gradient given the center
and radius.
@param center The center of the circle for this gradient
@param radius Must be positive. The radius of the circle for this
gradient
@param colors The array[count] of colors, to be distributed
between the center and edge of the circle
@param colorPos May be NULL. The array[count] of the relative
position of each corresponding color in the colors
array. If this is NULL, the the colors are
distributed evenly between the center and edge of
the circle. If this is not null, the values must
begin with 0, end with 1.0, and intermediate
values must be strictly increasing.
@param count Must be >= 2. The number of colors (and pos if not
NULL) entries
@param tileMode The tiling mode
@param localMatrix May be NULL
*/
sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center,
float radius,
const sk_color_t colors[],
const float colorPos[],
int colorCount,
sk_shader_tilemode_t tileMode,
const sk_matrix_t* localMatrix);
/**
Returns a shader that generates a sweep gradient given a center.
@param center The coordinates of the center of the sweep
@param colors The array[count] of colors, to be distributed around
the center.
@param colorPos May be NULL. The array[count] of the relative
position of each corresponding color in the colors
array. If this is NULL, the the colors are
distributed evenly between the center and edge of
the circle. If this is not null, the values must
begin with 0, end with 1.0, and intermediate
values must be strictly increasing.
@param colorCount Must be >= 2. The number of colors (and pos if
not NULL) entries
@param localMatrix May be NULL
*/
sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center,
const sk_color_t colors[],
const float colorPos[],
int colorCount,
const sk_matrix_t* localMatrix);
/**
Returns a shader that generates a conical gradient given two circles, or
returns NULL if the inputs are invalid. The gradient interprets the
two circles according to the following HTML spec.
http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
Returns a shader that generates a sweep gradient given a center.
@param start, startRadius Defines the first circle.
@param end, endRadius Defines the first circle.
@param colors The array[count] of colors, to be distributed between
the two circles.
@param colorPos May be NULL. The array[count] of the relative
position of each corresponding color in the colors
array. If this is NULL, the the colors are
distributed evenly between the two circles. If
this is not null, the values must begin with 0,
end with 1.0, and intermediate values must be
strictly increasing.
@param colorCount Must be >= 2. The number of colors (and pos if
not NULL) entries
@param tileMode The tiling mode
@param localMatrix May be NULL
*/
sk_shader_t* sk_shader_new_two_point_conical_gradient(
const sk_point_t* start,
float startRadius,
const sk_point_t* end,
float endRadius,
const sk_color_t colors[],
const float colorPos[],
int colorCount,
sk_shader_tilemode_t tileMode,
const sk_matrix_t* localMatrix);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,73 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_surface_DEFINED
#define sk_surface_DEFINED
#include "sk_types.h"
SK_C_PLUS_PLUS_BEGIN_GUARD
/**
Return a new surface, with the memory for the pixels automatically
allocated. If the requested surface cannot be created, or the
request is not a supported configuration, NULL will be returned.
@param sk_imageinfo_t* Specify the width, height, color type, and
alpha type for the surface.
@param sk_surfaceprops_t* If not NULL, specify additional non-default
properties of the surface.
*/
SK_API sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*, const sk_surfaceprops_t*);
/**
Create a new surface which will draw into the specified pixels
with the specified rowbytes. If the requested surface cannot be
created, or the request is not a supported configuration, NULL
will be returned.
@param sk_imageinfo_t* Specify the width, height, color type, and
alpha type for the surface.
@param void* pixels Specify the location in memory where the
destination pixels are. This memory must
outlast this surface.
@param size_t rowBytes Specify the difference, in bytes, between
each adjacent row. Should be at least
(width * sizeof(one pixel)).
@param sk_surfaceprops_t* If not NULL, specify additional non-default
properties of the surface.
*/
SK_API sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*,
void* pixels, size_t rowBytes,
const sk_surfaceprops_t* props);
/**
Decrement the reference count. If the reference count is 1 before
the decrement, then release both the memory holding the
sk_surface_t and any pixel memory it may be managing. New
sk_surface_t are created with a reference count of 1.
*/
SK_API void sk_surface_unref(sk_surface_t*);
/**
* Return the canvas associated with this surface. Note: the canvas is owned by the surface,
* so the returned object is only valid while the owning surface is valid.
*/
SK_API sk_canvas_t* sk_surface_get_canvas(sk_surface_t*);
/**
* Call sk_image_unref() when the returned image is no longer used.
*/
SK_API sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*);
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,205 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
// DO NOT USE -- FOR INTERNAL TESTING ONLY
#ifndef sk_types_DEFINED
#define sk_types_DEFINED
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
#define SK_C_PLUS_PLUS_BEGIN_GUARD extern "C" {
#define SK_C_PLUS_PLUS_END_GUARD }
#else
#include <stdbool.h>
#define SK_C_PLUS_PLUS_BEGIN_GUARD
#define SK_C_PLUS_PLUS_END_GUARD
#endif
#ifndef SK_API
#define SK_API
#endif
///////////////////////////////////////////////////////////////////////////////////////
SK_C_PLUS_PLUS_BEGIN_GUARD
typedef uint32_t sk_color_t;
/* This macro assumes all arguments are >=0 and <=255. */
#define sk_color_set_argb(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define sk_color_get_a(c) (((c) >> 24) & 0xFF)
#define sk_color_get_r(c) (((c) >> 16) & 0xFF)
#define sk_color_get_g(c) (((c) >> 8) & 0xFF)
#define sk_color_get_b(c) (((c) >> 0) & 0xFF)
typedef enum {
UNKNOWN_SK_COLORTYPE,
RGBA_8888_SK_COLORTYPE,
BGRA_8888_SK_COLORTYPE,
ALPHA_8_SK_COLORTYPE,
} sk_colortype_t;
typedef enum {
OPAQUE_SK_ALPHATYPE,
PREMUL_SK_ALPHATYPE,
UNPREMUL_SK_ALPHATYPE,
} sk_alphatype_t;
typedef enum {
INTERSECT_SK_CLIPTYPE,
DIFFERENCE_SK_CLIPTYPE,
} sk_cliptype_t;
typedef enum {
UNKNOWN_SK_PIXELGEOMETRY,
RGB_H_SK_PIXELGEOMETRY,
BGR_H_SK_PIXELGEOMETRY,
RGB_V_SK_PIXELGEOMETRY,
BGR_V_SK_PIXELGEOMETRY,
} sk_pixelgeometry_t;
/**
Return the default sk_colortype_t; this is operating-system dependent.
*/
SK_API sk_colortype_t sk_colortype_get_default_8888();
typedef struct {
int32_t width;
int32_t height;
sk_colortype_t colorType;
sk_alphatype_t alphaType;
} sk_imageinfo_t;
typedef struct {
sk_pixelgeometry_t pixelGeometry;
} sk_surfaceprops_t;
typedef struct {
float x;
float y;
} sk_point_t;
typedef struct {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
} sk_irect_t;
typedef struct {
float left;
float top;
float right;
float bottom;
} sk_rect_t;
typedef struct {
float mat[9];
} sk_matrix_t;
/**
A sk_canvas_t encapsulates all of the state about drawing into a
destination This includes a reference to the destination itself,
and a stack of matrix/clip values.
*/
typedef struct sk_canvas_t sk_canvas_t;
/**
A sk_data_ holds an immutable data buffer.
*/
typedef struct sk_data_t sk_data_t;
/**
A sk_image_t is an abstraction for drawing a rectagle of pixels.
The content of the image is always immutable, though the actual
storage may change, if for example that image can be re-created via
encoded data or other means.
*/
typedef struct sk_image_t sk_image_t;
/**
A sk_maskfilter_t is an object that perform transformations on an
alpha-channel mask before drawing it; it may be installed into a
sk_paint_t. Each time a primitive is drawn, it is first
scan-converted into a alpha mask, which os handed to the
maskfilter, which may create a new mask is to render into the
destination.
*/
typedef struct sk_maskfilter_t sk_maskfilter_t;
/**
A sk_paint_t holds the style and color information about how to
draw geometries, text and bitmaps.
*/
typedef struct sk_paint_t sk_paint_t;
/**
A sk_path_t encapsulates compound (multiple contour) geometric
paths consisting of straight line segments, quadratic curves, and
cubic curves.
*/
typedef struct sk_path_t sk_path_t;
/**
A sk_picture_t holds recorded canvas drawing commands to be played
back at a later time.
*/
typedef struct sk_picture_t sk_picture_t;
/**
A sk_picture_recorder_t holds a sk_canvas_t that records commands
to create a sk_picture_t.
*/
typedef struct sk_picture_recorder_t sk_picture_recorder_t;
/**
A sk_shader_t specifies the source color(s) for what is being drawn. If a
paint has no shader, then the paint's color is used. If the paint
has a shader, then the shader's color(s) are use instead, but they
are modulated by the paint's alpha.
*/
typedef struct sk_shader_t sk_shader_t;
/**
A sk_surface_t holds the destination for drawing to a canvas. For
raster drawing, the destination is an array of pixels in memory.
For GPU drawing, the destination is a texture or a framebuffer.
*/
typedef struct sk_surface_t sk_surface_t;
typedef enum {
CLEAR_SK_XFERMODE_MODE,
SRC_SK_XFERMODE_MODE,
DST_SK_XFERMODE_MODE,
SRCOVER_SK_XFERMODE_MODE,
DSTOVER_SK_XFERMODE_MODE,
SRCIN_SK_XFERMODE_MODE,
DSTIN_SK_XFERMODE_MODE,
SRCOUT_SK_XFERMODE_MODE,
DSTOUT_SK_XFERMODE_MODE,
SRCATOP_SK_XFERMODE_MODE,
DSTATOP_SK_XFERMODE_MODE,
XOR_SK_XFERMODE_MODE,
PLUS_SK_XFERMODE_MODE,
MODULATE_SK_XFERMODE_MODE,
SCREEN_SK_XFERMODE_MODE,
OVERLAY_SK_XFERMODE_MODE,
DARKEN_SK_XFERMODE_MODE,
LIGHTEN_SK_XFERMODE_MODE,
COLORDODGE_SK_XFERMODE_MODE,
COLORBURN_SK_XFERMODE_MODE,
HARDLIGHT_SK_XFERMODE_MODE,
SOFTLIGHT_SK_XFERMODE_MODE,
DIFFERENCE_SK_XFERMODE_MODE,
EXCLUSION_SK_XFERMODE_MODE,
MULTIPLY_SK_XFERMODE_MODE,
HUE_SK_XFERMODE_MODE,
SATURATION_SK_XFERMODE_MODE,
COLOR_SK_XFERMODE_MODE,
LUMINOSITY_SK_XFERMODE_MODE,
} sk_xfermode_mode_t;
//////////////////////////////////////////////////////////////////////////////////////////
SK_C_PLUS_PLUS_END_GUARD
#endif

View File

@ -0,0 +1,230 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkAndroidCodec_DEFINED
#define SkAndroidCodec_DEFINED
#include "SkCodec.h"
#include "SkEncodedFormat.h"
#include "SkStream.h"
#include "SkTypes.h"
/**
* Abstract interface defining image codec functionality that is necessary for
* Android.
*/
class SkAndroidCodec : SkNoncopyable {
public:
/**
* If this stream represents an encoded image that we know how to decode,
* return an SkAndroidCodec that can decode it. Otherwise return NULL.
*
* The SkPngChunkReader handles unknown chunks in PNGs.
* See SkCodec.h for more details.
*
* If NULL is returned, the stream is deleted immediately. Otherwise, the
* SkCodec takes ownership of it, and will delete it when done with it.
*/
static SkAndroidCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
/**
* If this data represents an encoded image that we know how to decode,
* return an SkAndroidCodec that can decode it. Otherwise return NULL.
*
* The SkPngChunkReader handles unknown chunks in PNGs.
* See SkCodec.h for more details.
*
* Will take a ref if it returns a codec, else will not affect the data.
*/
static SkAndroidCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
virtual ~SkAndroidCodec() {}
const SkImageInfo& getInfo() const { return fInfo; }
/**
* Format of the encoded data.
*/
SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
/**
* Returns the dimensions of the scaled output image, for an input
* sampleSize.
*
* When the sample size divides evenly into the original dimensions, the
* scaled output dimensions will simply be equal to the original
* dimensions divided by the sample size.
*
* When the sample size does not divide even into the original
* dimensions, the codec may round up or down, depending on what is most
* efficient to decode.
*
* Finally, the codec will always recommend a non-zero output, so the output
* dimension will always be one if the sampleSize is greater than the
* original dimension.
*/
SkISize getSampledDimensions(int sampleSize) const;
/**
* Return (via desiredSubset) a subset which can decoded from this codec,
* or false if the input subset is invalid.
*
* @param desiredSubset in/out parameter
* As input, a desired subset of the original bounds
* (as specified by getInfo).
* As output, if true is returned, desiredSubset may
* have been modified to a subset which is
* supported. Although a particular change may have
* been made to desiredSubset to create something
* supported, it is possible other changes could
* result in a valid subset. If false is returned,
* desiredSubset's value is undefined.
* @return true If the input desiredSubset is valid.
* desiredSubset may be modified to a subset
* supported by the codec.
* false If desiredSubset is invalid (NULL or not fully
* contained within the image).
*/
bool getSupportedSubset(SkIRect* desiredSubset) const;
// TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
/**
* Returns the dimensions of the scaled, partial output image, for an
* input sampleSize and subset.
*
* @param sampleSize Factor to scale down by.
* @param subset Must be a valid subset of the original image
* dimensions and a subset supported by SkAndroidCodec.
* getSubset() can be used to obtain a subset supported
* by SkAndroidCodec.
* @return Size of the scaled partial image. Or zero size
* if either of the inputs is invalid.
*/
SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
/**
* Additional options to pass to getAndroidPixels().
*/
// FIXME: It's a bit redundant to name these AndroidOptions when this class is already
// called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
// these Options when SkCodec has a slightly different set of Options. Maybe these
// should be DecodeOptions or SamplingOptions?
struct AndroidOptions {
AndroidOptions()
: fZeroInitialized(SkCodec::kNo_ZeroInitialized)
, fSubset(nullptr)
, fColorPtr(nullptr)
, fColorCount(nullptr)
, fSampleSize(1)
{}
/**
* Indicates is destination pixel memory is zero initialized.
*/
SkCodec::ZeroInitialized fZeroInitialized;
/**
* If not NULL, represents a subset of the original image to decode.
*
* Must be within the bounds returned by getInfo().
*
* If the EncodedFormat is kWEBP_SkEncodedFormat, the top and left
* values must be even.
*/
SkIRect* fSubset;
/**
* If the client has requested a decode to kIndex8_SkColorType
* (specified in the SkImageInfo), then the caller must provide
* storage for up to 256 SkPMColor values in fColorPtr. On success,
* the codec must copy N colors into that storage, (where N is the
* logical number of table entries) and set fColorCount to N.
*
* If the client does not request kIndex8_SkColorType, then the last
* two parameters may be NULL. If fColorCount is not null, it will be
* set to 0.
*/
SkPMColor* fColorPtr;
int* fColorCount;
/**
* The client may provide an integer downscale factor for the decode.
* The codec may implement this downscaling by sampling or another
* method if it is more efficient.
*/
int fSampleSize;
};
/**
* Decode into the given pixels, a block of memory of size at
* least (info.fHeight - 1) * rowBytes + (info.fWidth *
* bytesPerPixel)
*
* Repeated calls to this function should give the same results,
* allowing the PixelRef to be immutable.
*
* @param info A description of the format (config, size)
* expected by the caller. This can simply be identical
* to the info returned by getInfo().
*
* This contract also allows the caller to specify
* different output-configs, which the implementation can
* decide to support or not.
*
* A size that does not match getInfo() implies a request
* to scale or subset. If the codec cannot perform this
* scaling or subsetting, it will return an error code.
*
* If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
* SkPMColor values in options->fColorPtr. On success the codec must copy N colors into
* that storage, (where N is the logical number of table entries) and set
* options->fColorCount to N.
*
* If info is not kIndex8_SkColorType, options->fColorPtr and options->fColorCount may
* be nullptr.
*
* The AndroidOptions object is also used to specify any requested scaling or subsetting
* using options->fSampleSize and options->fSubset.
*
* @return Result kSuccess, or another value explaining the type of failure.
*/
// FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
// called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
// this getPixels() when it is a slightly different API than SkCodec's getPixels().
// Maybe this should be decode() or decodeSubset()?
SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const AndroidOptions* options);
/**
* Simplified version of getAndroidPixels() where we supply the default AndroidOptions.
*
* This will return an error if the info is kIndex_8_SkColorType and also will not perform
* any scaling or subsetting.
*/
SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
protected:
SkAndroidCodec(const SkImageInfo&);
virtual SkEncodedFormat onGetEncodedFormat() const = 0;
virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
size_t rowBytes, const AndroidOptions& options) = 0;
private:
// This will always be a reference to the info that is contained by the
// embedded SkCodec.
const SkImageInfo& fInfo;
};
#endif // SkAndroidCodec_DEFINED

View File

@ -0,0 +1,614 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkCodec_DEFINED
#define SkCodec_DEFINED
#include "../private/SkTemplates.h"
#include "SkColor.h"
#include "SkEncodedFormat.h"
#include "SkImageInfo.h"
#include "SkSize.h"
#include "SkStream.h"
#include "SkTypes.h"
class SkData;
class SkPngChunkReader;
class SkSampler;
/**
* Abstraction layer directly on top of an image codec.
*/
class SkCodec : SkNoncopyable {
public:
/**
* If this stream represents an encoded image that we know how to decode,
* return an SkCodec that can decode it. Otherwise return NULL.
*
* 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.
* If the PNG has unknown chunks, the SkPngChunkReader will be used
* to handle these chunks. SkPngChunkReader will be called to read
* any unknown chunk at any point during the creation of the codec
* or the decode. Note that if SkPngChunkReader fails to read a
* chunk, this could result in a failure to create the codec or a
* failure to decode the image.
* If the PNG does not contain unknown chunks, the SkPngChunkReader
* will not be used or modified.
*
* If NULL is returned, the stream is deleted immediately. Otherwise, the
* SkCodec takes ownership of it, and will delete it when done with it.
*/
static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
/**
* If this data represents an encoded image that we know how to decode,
* return an SkCodec that can decode it. Otherwise return NULL.
*
* 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.
* If the PNG has unknown chunks, the SkPngChunkReader will be used
* to handle these chunks. SkPngChunkReader will be called to read
* any unknown chunk at any point during the creation of the codec
* or the decode. Note that if SkPngChunkReader fails to read a
* chunk, this could result in a failure to create the codec or a
* failure to decode the image.
* If the PNG does not contain unknown chunks, the SkPngChunkReader
* will not be used or modified.
*
* Will take a ref if it returns a codec, else will not affect the data.
*/
static SkCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
virtual ~SkCodec();
/**
* Return the ImageInfo associated with this codec.
*/
const SkImageInfo& getInfo() const { return fSrcInfo; }
/**
* Return a size that approximately supports the desired scale factor.
* The codec may not be able to scale efficiently to the exact scale
* factor requested, so return a size that approximates that scale.
* The returned value is the codec's suggestion for the closest valid
* scale that it can natively support
*/
SkISize getScaledDimensions(float desiredScale) const {
// Negative and zero scales are errors.
SkASSERT(desiredScale > 0.0f);
if (desiredScale <= 0.0f) {
return SkISize::Make(0, 0);
}
// Upscaling is not supported. Return the original size if the client
// requests an upscale.
if (desiredScale >= 1.0f) {
return this->getInfo().dimensions();
}
return this->onGetScaledDimensions(desiredScale);
}
/**
* Return (via desiredSubset) a subset which can decoded from this codec,
* or false if this codec cannot decode subsets or anything similar to
* desiredSubset.
*
* @param desiredSubset In/out parameter. As input, a desired subset of
* the original bounds (as specified by getInfo). If true is returned,
* desiredSubset may have been modified to a subset which is
* supported. Although a particular change may have been made to
* desiredSubset to create something supported, it is possible other
* changes could result in a valid subset.
* If false is returned, desiredSubset's value is undefined.
* @return true if this codec supports decoding desiredSubset (as
* returned, potentially modified)
*/
bool getValidSubset(SkIRect* desiredSubset) const {
return this->onGetValidSubset(desiredSubset);
}
/**
* Format of the encoded data.
*/
SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
/**
* Used to describe the result of a call to getPixels().
*
* Result is the union of possible results from subclasses.
*/
enum Result {
/**
* General return value for success.
*/
kSuccess,
/**
* The input is incomplete. A partial image was generated.
*/
kIncompleteInput,
/**
* The generator cannot convert to match the request, ignoring
* dimensions.
*/
kInvalidConversion,
/**
* The generator cannot scale to requested size.
*/
kInvalidScale,
/**
* Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
* too small, etc.
*/
kInvalidParameters,
/**
* The input did not contain a valid image.
*/
kInvalidInput,
/**
* Fulfilling this request requires rewinding the input, which is not
* supported for this input.
*/
kCouldNotRewind,
/**
* This method is not implemented by this codec.
* FIXME: Perhaps this should be kUnsupported?
*/
kUnimplemented,
};
/**
* Whether or not the memory passed to getPixels is zero initialized.
*/
enum ZeroInitialized {
/**
* The memory passed to getPixels is zero initialized. The SkCodec
* may take advantage of this by skipping writing zeroes.
*/
kYes_ZeroInitialized,
/**
* The memory passed to getPixels has not been initialized to zero,
* so the SkCodec must write all zeroes to memory.
*
* This is the default. It will be used if no Options struct is used.
*/
kNo_ZeroInitialized,
};
/**
* Additional options to pass to getPixels.
*/
struct Options {
Options()
: fZeroInitialized(kNo_ZeroInitialized)
, fSubset(NULL)
{}
ZeroInitialized fZeroInitialized;
/**
* If not NULL, represents a subset of the original image to decode.
* Must be within the bounds returned by getInfo().
* If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
* currently supports subsets), the top and left values must be even.
*
* In getPixels, we will attempt to decode the exact rectangular
* subset specified by fSubset.
*
* In a scanline decode, it does not make sense to specify a subset
* top or subset height, since the client already controls which rows
* to get and which rows to skip. During scanline decodes, we will
* require that the subset top be zero and the subset height be equal
* to the full height. We will, however, use the values of
* subset left and subset width to decode partial scanlines on calls
* to getScanlines().
*/
SkIRect* fSubset;
};
/**
* Decode into the given pixels, a block of memory of size at
* least (info.fHeight - 1) * rowBytes + (info.fWidth *
* bytesPerPixel)
*
* Repeated calls to this function should give the same results,
* allowing the PixelRef to be immutable.
*
* @param info A description of the format (config, size)
* expected by the caller. This can simply be identical
* to the info returned by getInfo().
*
* This contract also allows the caller to specify
* different output-configs, which the implementation can
* decide to support or not.
*
* A size that does not match getInfo() implies a request
* to scale. If the generator cannot perform this scale,
* it will return kInvalidScale.
*
* If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
* SkPMColor values in ctable. On success the generator must copy N colors into that storage,
* (where N is the logical number of table entries) and set ctableCount to N.
*
* If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
* is not null, it will be set to 0.
*
* If a scanline decode is in progress, scanline mode will end, requiring the client to call
* startScanlineDecode() in order to return to decoding scanlines.
*
* @return Result kSuccess, or another value explaining the type of failure.
*/
Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
SkPMColor ctable[], int* ctableCount);
/**
* Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
* uses the default Options.
*/
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.
*/
/**
* Prepare for a scanline decode with the specified options.
*
* After this call, this class will be ready to decode the first scanline.
*
* This must be called in order to call getScanlines or skipScanlines.
*
* This may require rewinding the stream.
*
* Not all SkCodecs support this.
*
* @param dstInfo Info of the destination. If the dimensions do not match
* those of getInfo, this implies a scale.
* @param options Contains decoding options, including if memory is zero
* initialized.
* @param ctable A pointer to a color table. When dstInfo.colorType() is
* kIndex8, this should be non-NULL and have enough storage for 256
* colors. The color table will be populated after decoding the palette.
* @param ctableCount A pointer to the size of the color table. When
* dstInfo.colorType() is kIndex8, this should be non-NULL. It will
* be modified to the true size of the color table (<= 256) after
* decoding the palette.
* @return Enum representing success or reason for failure.
*/
Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options,
SkPMColor ctable[], int* ctableCount);
/**
* Simplified version of startScanlineDecode() that asserts that info is NOT
* kIndex8_SkColorType and uses the default Options.
*/
Result startScanlineDecode(const SkImageInfo& dstInfo);
/**
* Write the next countLines scanlines into dst.
*
* Not valid to call before calling startScanlineDecode().
*
* @param dst Must be non-null, and large enough to hold countLines
* scanlines of size rowBytes.
* @param countLines Number of lines to write.
* @param rowBytes Number of bytes per row. Must be large enough to hold
* a scanline based on the SkImageInfo used to create this object.
* @return the number of lines successfully decoded. If this value is
* less than countLines, this will fill the remaining lines with a
* default value.
*/
int getScanlines(void* dst, int countLines, size_t rowBytes);
/**
* Skip count scanlines.
*
* Not valid to call before calling startScanlineDecode().
*
* The default version just calls onGetScanlines and discards the dst.
* NOTE: If skipped lines are the only lines with alpha, this default
* will make reallyHasAlpha return true, when it could have returned
* false.
*
* @return true if the scanlines were successfully skipped
* false on failure, possible reasons for failure include:
* An incomplete input image stream.
* Calling this function before calling startScanlineDecode().
* If countLines is less than zero or so large that it moves
* the current scanline past the end of the image.
*/
bool skipScanlines(int countLines);
/**
* The order in which rows are output from the scanline decoder is not the
* same for all variations of all image types. This explains the possible
* output row orderings.
*/
enum SkScanlineOrder {
/*
* By far the most common, this indicates that the image can be decoded
* reliably using the scanline decoder, and that rows will be output in
* the logical order.
*/
kTopDown_SkScanlineOrder,
/*
* This indicates that the scanline decoder reliably outputs rows, but
* they will be returned in reverse order. If the scanline format is
* kBottomUp, the nextScanline() API can be used to determine the actual
* y-coordinate of the next output row, but the client is not forced
* to take advantage of this, given that it's not too tough to keep
* track independently.
*
* For full image decodes, it is safe to get all of the scanlines at
* once, since the decoder will handle inverting the rows as it
* decodes.
*
* For subset decodes and sampling, it is simplest to get and skip
* scanlines one at a time, using the nextScanline() API. It is
* possible to ask for larger chunks at a time, but this should be used
* with caution. As with full image decodes, the decoder will handle
* inverting the requested rows, but rows will still be delivered
* starting from the bottom of the image.
*
* Upside down bmps are an example.
*/
kBottomUp_SkScanlineOrder,
/*
* This indicates that the scanline decoder reliably outputs rows, but
* they will not be in logical order. If the scanline format is
* kOutOfOrder, the nextScanline() API should be used to determine the
* actual y-coordinate of the next output row.
*
* For this scanline ordering, it is advisable to get and skip
* scanlines one at a time.
*
* Interlaced gifs are an example.
*/
kOutOfOrder_SkScanlineOrder,
/*
* Indicates that the entire image must be decoded in order to output
* any amount of scanlines. In this case, it is a REALLY BAD IDEA to
* request scanlines 1-by-1 or in small chunks. The client should
* determine which scanlines are needed and ask for all of them in
* a single call to getScanlines().
*
* Interlaced pngs are an example.
*/
kNone_SkScanlineOrder,
};
/**
* An enum representing the order in which scanlines will be returned by
* the scanline decoder.
*/
SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
/**
* Returns the y-coordinate of the next row to be returned by the scanline
* decoder.
*
* This will equal fCurrScanline, except in the case of strangely
* encoded image types (bottom-up bmps, interlaced gifs).
*
* Results are undefined when not in scanline decoding mode.
*/
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.
*
* This will equal inputScanline, except in the case of strangely
* encoded image types (bottom-up bmps, interlaced gifs).
*/
int outputScanline(int inputScanline) const;
protected:
SkCodec(const SkImageInfo&, SkStream*);
virtual SkISize onGetScaledDimensions(float /* desiredScale */) const {
// By default, scaling is not supported.
return this->getInfo().dimensions();
}
// FIXME: What to do about subsets??
/**
* Subclasses should override if they support dimensions other than the
* srcInfo's.
*/
virtual bool onDimensionsSupported(const SkISize&) {
return false;
}
virtual SkEncodedFormat onGetEncodedFormat() const = 0;
/**
* @param rowsDecoded When the encoded image stream is incomplete, this function
* will return kIncompleteInput and rowsDecoded will be set to
* the number of scanlines that were successfully decoded.
* This will allow getPixels() to fill the uninitialized memory.
*/
virtual Result onGetPixels(const SkImageInfo& info,
void* pixels, size_t rowBytes, const Options&,
SkPMColor ctable[], int* ctableCount,
int* rowsDecoded) = 0;
virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const {
// By default, subsets are not supported.
return false;
}
virtual bool onReallyHasAlpha() const { return false; }
/**
* If the stream was previously read, attempt to rewind.
*
* If the stream needed to be rewound, call onRewind.
* @returns true if the codec is at the right position and can be used.
* false if there was a failure to rewind.
*
* This is called by getPixels() and start(). Subclasses may call if they
* need to rewind at another time.
*/
bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
/**
* Called by rewindIfNeeded, if the stream needed to be rewound.
*
* Subclasses should do any set up needed after a rewind.
*/
virtual bool onRewind() {
return true;
}
/**
* On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
* scanlines. This allows the subclass to indicate what value to fill with.
*
* @param colorType Destination color type.
* @param alphaType Destination alpha type.
* @return The value with which to fill uninitialized pixels.
*
* Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color,
* an 8-bit gray color, or an 8-bit index into a color table, depending on the color
* type.
*/
uint32_t getFillValue(SkColorType colorType, SkAlphaType alphaType) const {
return this->onGetFillValue(colorType, alphaType);
}
/**
* Some subclasses will override this function, but this is a useful default for the color
* types that we support. Note that for color types that do not use the full 32-bits,
* we will simply take the low bits of the fill value.
*
* kN32_SkColorType: Transparent or Black
* kRGB_565_SkColorType: Black
* kGray_8_SkColorType: Black
* kIndex_8_SkColorType: First color in color table
*/
virtual uint32_t onGetFillValue(SkColorType /*colorType*/, SkAlphaType alphaType) const {
return kOpaque_SkAlphaType == alphaType ? SK_ColorBLACK : SK_ColorTRANSPARENT;
}
/**
* Get method for the input stream
*/
SkStream* stream() {
return fStream.get();
}
/**
* The remaining functions revolve around decoding scanlines.
*/
/**
* Most images types will be kTopDown and will not need to override this function.
*/
virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
/**
* Update the next scanline. Used by interlaced png.
*/
void updateNextScanline(int newY) { fCurrScanline = newY; }
const SkImageInfo& dstInfo() const { return fDstInfo; }
const SkCodec::Options& options() const { return fOptions; }
virtual int onOutputScanline(int inputScanline) const;
private:
const SkImageInfo fSrcInfo;
SkAutoTDelete<SkStream> fStream;
bool fNeedsRewind;
// These fields are only meaningful during scanline decodes.
SkImageInfo fDstInfo;
SkCodec::Options fOptions;
int fCurrScanline;
/**
* Return whether these dimensions are supported as a scale.
*
* The codec may choose to cache the information about scale and subset.
* Either way, the same information will be passed to onGetPixels/onStart
* on success.
*
* This must return true for a size returned from getScaledDimensions.
*/
bool dimensionsSupported(const SkISize& dim) {
return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
}
// Methods for scanline decoding.
virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
return kUnimplemented;
}
// Naive default version just calls onGetScanlines on temp memory.
virtual bool onSkipScanlines(int countLines) {
// FIXME (msarett): Make this a pure virtual and always override this.
SkAutoMalloc storage(fDstInfo.minRowBytes());
// Note that we pass 0 to rowBytes so we continue to use the same memory.
// Also note that while getScanlines checks that rowBytes is big enough,
// onGetScanlines bypasses that check.
// Calling the virtual method also means we do not double count
// countLines.
return countLines == this->onGetScanlines(storage.get(), countLines, 0);
}
virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
/**
* On an incomplete decode, getPixels() and getScanlines() will call this function
* to fill any uinitialized memory.
*
* @param dstInfo Contains the destination color type
* Contains the destination alpha type
* Contains the destination width
* The height stored in this info is unused
* @param dst Pointer to the start of destination pixel memory
* @param rowBytes Stride length in destination pixel memory
* @param zeroInit Indicates if memory is zero initialized
* @param linesRequested Number of lines that the client requested
* @param linesDecoded Number of lines that were successfully decoded
*/
void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
/**
* Return an object which will allow forcing scanline decodes to sample in X.
*
* May create a sampler, if one is not currently being used. Otherwise, does
* not affect ownership.
*
* Only valid during scanline decoding.
*/
virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
friend class SkSampledCodec;
};
#endif // SkCodec_DEFINED

View File

@ -0,0 +1,27 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkEncodedFormat_DEFINED
#define SkEncodedFormat_DEFINED
/**
* Enum describing format of encoded data.
*/
enum SkEncodedFormat {
kUnknown_SkEncodedFormat,
kBMP_SkEncodedFormat,
kGIF_SkEncodedFormat,
kICO_SkEncodedFormat,
kJPEG_SkEncodedFormat,
kPNG_SkEncodedFormat,
kWBMP_SkEncodedFormat,
kWEBP_SkEncodedFormat,
kPKM_SkEncodedFormat,
kKTX_SkEncodedFormat,
kASTC_SkEncodedFormat,
};
#endif // SkEncodedFormat_DEFINED

View File

@ -58,13 +58,6 @@
//#define SK_DEBUG_GLYPH_CACHE
//#define SK_DEBUG_PATH
/* To assist debugging, Skia provides an instance counting utility in
include/core/SkInstCount.h. This flag turns on and off that utility to
allow instance count tracking in either debug or release builds. By
default it is enabled in debug but disabled in release.
*/
#define SK_ENABLE_INST_COUNT 0
/* If, in debugging mode, Skia needs to stop (presumably to invoke a debugger)
it will call SK_CRASH(). If this is not defined it, it is defined in
SkPostConfig.h to write to an illegal address
@ -107,14 +100,6 @@
*/
//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
/* If zlib is available and you want to support the flate compression
algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the
include path. Alternatively, define SK_SYSTEM_ZLIB to use the system zlib
library specified as "#include <zlib.h>".
*/
//#define SK_ZLIB_INCLUDE <zlib.h>
//#define SK_SYSTEM_ZLIB
/* Define this to allow PDF scalars above 32k. The PDF/A spec doesn't allow
them, but modern PDF interpreters should handle them just fine.
*/
@ -139,17 +124,15 @@
//#define SK_SUPPORT_UNITTEST
#endif
/* If your system embeds skia and has complex event logging, define this
symbol to name a file that maps the following macros to your system's
equivalents:
SK_TRACE_EVENT0(event)
SK_TRACE_EVENT1(event, name1, value1)
SK_TRACE_EVENT2(event, name1, value1, name2, value2)
src/utils/SkDebugTrace.h has a trivial implementation that writes to
the debug output stream. If SK_USER_TRACE_INCLUDE_FILE is not defined,
SkTrace.h will define the above three macros to do nothing.
*/
//#undef SK_USER_TRACE_INCLUDE_FILE
/* Change the ordering to work in X windows.
*/
//#ifdef SK_SAMPLES_FOR_X
// #define SK_R32_SHIFT 16
// #define SK_G32_SHIFT 8
// #define SK_B32_SHIFT 0
// #define SK_A32_SHIFT 24
//#endif
/* Determines whether to build code that supports the GPU backend. Some classes
that are not GPU-specific, such as SkShader subclasses, have optional code
@ -161,40 +144,14 @@
//#define SK_SUPPORT_GPU 1
/* The PDF generation code uses Path Ops to generate inverse fills and complex
* clipping paths, but at this time, Path Ops is not release ready yet. So,
* the code is hidden behind this #define guard. If you are feeling adventurous
* and want the latest and greatest PDF generation code, uncomment the #define.
/* The PDF generation code uses Path Ops to handle complex clipping paths,
* but at this time, Path Ops is not release ready yet. So, the code is
* hidden behind this #define guard. If you are feeling adventurous and
* want the latest and greatest PDF generation code, uncomment the #define.
* When Path Ops is release ready, the define guards and this user config
* define should be removed entirely.
*/
//#define SK_PDF_USE_PATHOPS
/* Skia uses these defines as the target of include preprocessor directives.
* The header files pointed to by these defines provide declarations and
* possibly inline implementations of threading primitives.
*
* See SkThread.h for documentation on what these includes must contain.
*/
//#define SK_ATOMICS_PLATFORM_H "SkAtomics_xxx.h"
//#define SK_MUTEX_PLATFORM_H "SkMutex_xxx.h"
#if defined(_MSC_VER)
# define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_win.h"
#else
# define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_sync.h"
#endif
#if defined(_WIN32)
# define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_win.h"
#else
# define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_pthread.h"
#endif
#if defined(SK_CPU_ARM32) || defined(SK_CPU_ARM64)
# define SK_BARRIERS_PLATFORM_H "../../src/ports/SkBarriers_arm.h"
#else
# define SK_BARRIERS_PLATFORM_H "../../src/ports/SkBarriers_x86.h"
#endif
//#define SK_PDF_USE_PATHOPS_CLIPPING
// On all platforms we have this byte order
#define SK_A32_SHIFT 24
@ -205,8 +162,21 @@
#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
#define SK_SUPPORT_LEGACY_GETDEVICE
#define SK_IGNORE_ETC1_SUPPORT
#define SK_RASTERIZE_EVEN_ROUNDING
#define GR_GL_PER_GL_FUNC_CALLBACK 1
#define MOZ_SKIA 1
#ifndef MOZ_IMPLICIT
# ifdef MOZ_CLANG_PLUGIN
# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
# else
# define MOZ_IMPLICIT
# endif
#endif
#endif

View File

@ -10,12 +10,11 @@
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTypes.h"
class SkData;
class SkReadBuffer;
class SkWriteBuffer;
class SkStream;
class SkWStream;
struct SkPoint;
/**
@ -27,12 +26,10 @@ public:
virtual ~SkAnnotation();
static SkAnnotation* Create(const char key[], SkData* value) {
return SkNEW_ARGS(SkAnnotation, (key, value));
return new SkAnnotation(key, value);
}
static SkAnnotation* Create(SkReadBuffer& buffer) {
return SkNEW_ARGS(SkAnnotation, (buffer));
}
static SkAnnotation* Create(SkReadBuffer& buffer) { return new SkAnnotation(buffer); }
/**
* Return the data for the specified key, or NULL.

View File

@ -8,62 +8,24 @@
#ifndef SkBBHFactory_DEFINED
#define SkBBHFactory_DEFINED
#include "SkSize.h"
#include "SkPoint.h"
#include "SkTypes.h"
class SkBBoxHierarchy;
struct SkRect;
class SK_API SkBBHFactory {
public:
/**
* Allocate a new SkBBoxHierarchy. Return NULL on failure.
*/
virtual SkBBoxHierarchy* operator()(int width, int height) const = 0;
virtual SkBBoxHierarchy* operator()(const SkRect& bounds) const = 0;
virtual ~SkBBHFactory() {};
};
class SK_API SkQuadTreeFactory : public SkBBHFactory {
public:
virtual SkBBoxHierarchy* operator()(int width, int height) const SK_OVERRIDE;
private:
typedef SkBBHFactory INHERITED;
};
class SK_API SkRTreeFactory : public SkBBHFactory {
public:
virtual SkBBoxHierarchy* operator()(int width, int height) const SK_OVERRIDE;
SkBBoxHierarchy* operator()(const SkRect& bounds) const override;
private:
typedef SkBBHFactory INHERITED;
};
class SK_API SkTileGridFactory : public SkBBHFactory {
public:
struct TileGridInfo {
/** Tile placement interval */
SkISize fTileInterval;
/** Pixel coverage overlap between adjacent tiles */
SkISize fMargin;
/** Offset added to device-space bounding box positions to convert
* them to tile-grid space. This can be used to adjust the "phase"
* of the tile grid to match probable query rectangles that will be
* used to search into the tile grid. As long as the offset is smaller
* or equal to the margin, there is no need to extend the domain of
* the tile grid to prevent data loss.
*/
SkIPoint fOffset;
};
SkTileGridFactory(const TileGridInfo& info) : fInfo(info) { }
virtual SkBBoxHierarchy* operator()(int width, int height) const SK_OVERRIDE;
private:
TileGridInfo fInfo;
typedef SkBBHFactory INHERITED;
};
#endif

View File

@ -11,6 +11,7 @@
#include "SkColor.h"
#include "SkColorTable.h"
#include "SkImageInfo.h"
#include "SkPixmap.h"
#include "SkPoint.h"
#include "SkRefCnt.h"
@ -38,29 +39,6 @@ class SK_API SkBitmap {
public:
class SK_API Allocator;
#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
enum Config {
kNo_Config, //!< bitmap has not been configured
kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors
kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
kARGB_4444_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
kARGB_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing)
};
// do not add this to the Config enum, otherwise the compiler will let us
// pass this as a valid parameter for Config.
enum {
kConfigCount = kARGB_8888_Config + 1
};
/** Return the config for the bitmap. */
Config config() const;
SK_ATTR_DEPRECATED("use config()")
Config getConfig() const { return this->config(); }
#endif
/**
* Default construct creates a bitmap with zero width and height, and no pixels.
* Its colortype is set to kUnknown_SkColorType.
@ -91,10 +69,11 @@ public:
const SkImageInfo& info() const { return fInfo; }
int width() const { return fInfo.fWidth; }
int height() const { return fInfo.fHeight; }
SkColorType colorType() const { return fInfo.fColorType; }
SkAlphaType alphaType() const { return fInfo.fAlphaType; }
int width() const { return fInfo.width(); }
int height() const { return fInfo.height(); }
SkColorType colorType() const { return fInfo.colorType(); }
SkAlphaType alphaType() const { return fInfo.alphaType(); }
SkColorProfileType profileType() const { return fInfo.profileType(); }
/**
* Return the number of bytes per pixel based on the colortype. If the colortype is
@ -155,7 +134,7 @@ public:
Note this truncates the result to 32bits. Call getSize64() to detect
if the real size exceeds 32bits.
*/
size_t getSize() const { return fInfo.fHeight * fRowBytes; }
size_t getSize() const { return fInfo.height() * fRowBytes; }
/** Return the number of bytes from the pointer returned by getPixels()
to the end of the allocated space in the buffer. Required in
@ -167,7 +146,7 @@ public:
* Return the full size of the bitmap, in bytes.
*/
int64_t computeSize64() const {
return sk_64_mul(fInfo.fHeight, fRowBytes);
return sk_64_mul(fInfo.height(), fRowBytes);
}
/**
@ -233,6 +212,14 @@ public:
void getBounds(SkRect* bounds) const;
void getBounds(SkIRect* bounds) const;
SkIRect bounds() const { return fInfo.bounds(); }
SkISize dimensions() const { return fInfo.dimensions(); }
// Returns the bounds of this bitmap, offset by its pixelref origin.
SkIRect getSubset() const {
return SkIRect::MakeXYWH(fPixelRefOrigin.x(), fPixelRefOrigin.y(),
fInfo.width(), fInfo.height());
}
bool setInfo(const SkImageInfo&, size_t rowBytes = 0);
/**
@ -241,7 +228,13 @@ public:
* a colortable, then ColorTable must be non-null, and will be ref'd.
* On failure, the bitmap will be set to empty and return false.
*/
bool allocPixels(const SkImageInfo&, SkPixelRefFactory*, SkColorTable*);
bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo&, SkPixelRefFactory*, SkColorTable*);
void allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, SkColorTable* ctable) {
if (!this->tryAllocPixels(info, factory, ctable)) {
sk_throw();
}
}
/**
* Allocate the bitmap's pixels to match the requested image info and
@ -251,24 +244,32 @@ public:
* the pixel size specified by info.colorType()) then false is returned
* and the bitmap is set to empty.
*/
bool allocPixels(const SkImageInfo& info, size_t rowBytes);
bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes);
/**
* Allocate a pixelref to match the specified image info, using the default
* allocator.
* On success, the bitmap's pixels will be "locked", and return true.
* On failure, the bitmap will be set to empty and return false.
*/
bool allocPixels(const SkImageInfo& info) {
return this->allocPixels(info, info.minRowBytes());
void allocPixels(const SkImageInfo& info, size_t rowBytes) {
if (!this->tryAllocPixels(info, rowBytes)) {
sk_throw();
}
}
bool allocN32Pixels(int width, int height, bool isOpaque = false) {
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
if (isOpaque) {
info.fAlphaType = kOpaque_SkAlphaType;
}
return this->allocPixels(info);
bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info) {
return this->tryAllocPixels(info, info.minRowBytes());
}
void allocPixels(const SkImageInfo& info) {
this->allocPixels(info, info.minRowBytes());
}
bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false) {
SkImageInfo info = SkImageInfo::MakeN32(width, height,
isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
return this->tryAllocPixels(info);
}
void allocN32Pixels(int width, int height, bool isOpaque = false) {
SkImageInfo info = SkImageInfo::MakeN32(width, height,
isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
this->allocPixels(info);
}
/**
@ -277,6 +278,9 @@ public:
* referenced, if releaseProc is not null, it will be called with the
* pixels and context as parameters.
* On failure, the bitmap will be set to empty and return false.
*
* If specified, the releaseProc will always be called, even on failure. It is also possible
* for success but the releaseProc is immediately called (e.g. valid Info but NULL pixels).
*/
bool installPixels(const SkImageInfo&, void* pixels, size_t rowBytes, SkColorTable*,
void (*releaseProc)(void* addr, void* context), void* context);
@ -343,8 +347,12 @@ public:
@return true if the allocation succeeds. If not the pixelref field of
the bitmap will be unchanged.
*/
bool allocPixels(SkColorTable* ctable = NULL) {
return this->allocPixels(NULL, ctable);
bool SK_WARN_UNUSED_RESULT tryAllocPixels(SkColorTable* ctable = NULL) {
return this->tryAllocPixels(NULL, ctable);
}
void allocPixels(SkColorTable* ctable = NULL) {
this->allocPixels(NULL, ctable);
}
/** Use the specified Allocator to create the pixelref that manages the
@ -365,7 +373,13 @@ public:
@return true if the allocation succeeds. If not the pixelref field of
the bitmap will be unchanged.
*/
bool allocPixels(Allocator* allocator, SkColorTable* ctable);
bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator, SkColorTable* ctable);
void allocPixels(Allocator* allocator, SkColorTable* ctable) {
if (!this->tryAllocPixels(allocator, ctable)) {
sk_throw();
}
}
/**
* Return the current pixelref object or NULL if there is none. This does
@ -423,13 +437,15 @@ public:
*/
bool lockPixelsAreWritable() const;
bool requestLock(SkAutoPixmapUnlock* result) const;
/** Call this to be sure that the bitmap is valid enough to be drawn (i.e.
it has non-null pixels, and if required by its colortype, it has a
non-null colortable. Returns true if all of the above are met.
*/
bool readyToDraw() const {
return this->getPixels() != NULL &&
(this->colorType() != kIndex_8_SkColorType || NULL != fColorTable);
(this->colorType() != kIndex_8_SkColorType || fColorTable);
}
/** Returns the pixelRef's texture, or NULL
@ -462,10 +478,7 @@ public:
* of the color is ignored (treated as opaque). If the colortype only supports
* alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
*/
void eraseColor(SkColor c) const {
this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
SkColorGetB(c));
}
void eraseColor(SkColor c) const;
/**
* Fill the entire bitmap with the specified color.
@ -473,7 +486,9 @@ public:
* of the color is ignored (treated as opaque). If the colortype only supports
* alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
*/
void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
this->eraseColor(SkColorSetARGB(a, r, g, b));
}
SK_ATTR_DEPRECATED("use eraseARGB or eraseColor")
void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
@ -486,29 +501,12 @@ public:
* of the color is ignored (treated as opaque). If the colortype only supports
* alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
*/
void eraseArea(const SkIRect& area, SkColor c) const;
void erase(SkColor c, const SkIRect& area) const;
/** Scroll (a subset of) the contents of this bitmap by dx/dy. If there are
no pixels allocated (i.e. getPixels() returns null) the method will
still update the inval region (if present). If the bitmap is immutable,
do nothing and return false.
@param subset The subset of the bitmap to scroll/move. To scroll the
entire contents, specify [0, 0, width, height] or just
pass null.
@param dx The amount to scroll in X
@param dy The amount to scroll in Y
@param inval Optional (may be null). Returns the area of the bitmap that
was scrolled away. E.g. if dx = dy = 0, then inval would
be set to empty. If dx >= width or dy >= height, then
inval would be set to the entire bounds of the bitmap.
@return true if the scroll was doable. Will return false if the colortype is kUnkown or
if the bitmap is immutable.
If no pixels are present (i.e. getPixels() returns false)
inval will still be updated, and true will be returned.
*/
bool scrollRect(const SkIRect* subset, int dx, int dy,
SkRegion* inval = NULL) const;
// DEPRECATED
void eraseArea(const SkIRect& area, SkColor c) const {
this->erase(c, area);
}
/**
* Return the SkColor of the specified pixel. In most cases this will
@ -665,12 +663,21 @@ public:
bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
SkIPoint* offset) const;
/**
* If the pixels are available from this bitmap (w/o locking) return true, and fill out the
* specified pixmap (if not null). If the pixels are not available (either because there are
* none, or becuase accessing them would require locking or other machinary) return false and
* ignore the pixmap parameter.
*
* Note: if this returns true, the results (in the pixmap) are only valid until the bitmap
* is changed in anyway, in which case the results are invalid.
*/
bool peekPixels(SkPixmap*) const;
SkDEBUGCODE(void validate() const;)
class Allocator : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(Allocator)
/** Allocate the pixel memory for the bitmap, given its dimensions and
colortype. Return true on success, where success means either setPixels
or setPixelRef was called. The pixels need not be locked when this
@ -689,7 +696,7 @@ public:
*/
class HeapAllocator : public Allocator {
public:
virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
bool allocPixelRef(SkBitmap*, SkColorTable*) override;
};
class RLEPixels {
@ -736,24 +743,17 @@ private:
};
SkImageInfo fInfo;
uint32_t fRowBytes;
uint8_t fFlags;
void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const;
/* Unreference any pixelrefs or colortables
*/
void freePixels();
void updatePixelsFromRef() const;
void legacyUnflatten(SkReadBuffer&);
static void WriteRawPixels(SkWriteBuffer*, const SkBitmap&);
static bool ReadRawPixels(SkReadBuffer*, SkBitmap*);
friend class SkBitmapSource; // unflatten
friend class SkReadBuffer; // unflatten, rawpixels
friend class SkWriteBuffer; // rawpixels
friend struct SkBitmapProcState;
@ -780,60 +780,6 @@ private:
//TODO(mtklein): uncomment when 71713004 lands and Chromium's fixed.
//#define SkAutoLockPixels(...) SK_REQUIRE_LOCAL_VAR(SkAutoLockPixels)
/** Helper class that performs the lock/unlockColors calls on a colortable.
The destructor will call unlockColors(false) if it has a bitmap's colortable
*/
class SkAutoLockColors : SkNoncopyable {
public:
/** Initialize with no bitmap. Call lockColors(bitmap) to lock bitmap's
colortable
*/
SkAutoLockColors() : fCTable(NULL), fColors(NULL) {}
/** Initialize with bitmap, locking its colortable if present
*/
explicit SkAutoLockColors(const SkBitmap& bm) {
fCTable = bm.getColorTable();
fColors = fCTable ? fCTable->lockColors() : NULL;
}
/** Initialize with a colortable (may be null)
*/
explicit SkAutoLockColors(SkColorTable* ctable) {
fCTable = ctable;
fColors = ctable ? ctable->lockColors() : NULL;
}
~SkAutoLockColors() {
if (fCTable) {
fCTable->unlockColors();
}
}
/** Return the currently locked colors, or NULL if no bitmap's colortable
is currently locked.
*/
const SkPMColor* colors() const { return fColors; }
/** Locks the table and returns is colors (assuming ctable is not null) and
unlocks the previous table if one was present
*/
const SkPMColor* lockColors(SkColorTable* ctable) {
if (fCTable) {
fCTable->unlockColors();
}
fCTable = ctable;
fColors = ctable ? ctable->lockColors() : NULL;
return fColors;
}
const SkPMColor* lockColors(const SkBitmap& bm) {
return this->lockColors(bm.getColorTable());
}
private:
SkColorTable* fCTable;
const SkPMColor* fColors;
};
#define SkAutoLockColors(...) SK_REQUIRE_LOCAL_VAR(SkAutoLockColors)
///////////////////////////////////////////////////////////////////////////////
inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
@ -865,13 +811,4 @@ inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}
#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
///////////////////////////////////////////////////////////////////////////////
//
// Helpers until we can fully deprecate SkBitmap::Config
//
SK_API SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType);
SK_API SkColorType SkBitmapConfigToColorType(SkBitmap::Config);
#endif
#endif

View File

@ -9,54 +9,74 @@
#ifndef SkBitmapDevice_DEFINED
#define SkBitmapDevice_DEFINED
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkDevice.h"
#include "SkImageFilter.h"
#include "SkImageInfo.h"
#include "SkRect.h"
#include "SkScalar.h"
#include "SkSize.h"
#include "SkSurfaceProps.h"
#include "SkTypes.h"
class SkDraw;
class SkMatrix;
class SkPaint;
class SkPath;
class SkPixelRef;
class SkPixmap;
class SkRRect;
class SkSurface;
class SkXfermode;
struct SkPoint;
///////////////////////////////////////////////////////////////////////////////
class SK_API SkBitmapDevice : public SkBaseDevice {
public:
SK_DECLARE_INST_COUNT(SkBitmapDevice)
/**
* Construct a new device with the specified bitmap as its backend. It is
* valid for the bitmap to have no pixels associated with it. In that case,
* any drawing to this device will have no effect.
*/
*/
SkBitmapDevice(const SkBitmap& bitmap);
/**
* Create a new device along with its requisite pixel memory using
* default SkSurfaceProps (i.e., kLegacyFontHost_InitType-style).
* Note: this entry point is slated for removal - no one should call it.
*/
static SkBitmapDevice* Create(const SkImageInfo& info);
/**
* Construct a new device with the specified bitmap as its backend. It is
* valid for the bitmap to have no pixels associated with it. In that case,
* any drawing to this device will have no effect.
*/
SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties);
*/
SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& surfaceProps);
static SkBitmapDevice* Create(const SkImageInfo&,
const SkDeviceProperties* = NULL);
static SkBitmapDevice* Create(const SkImageInfo&, const SkSurfaceProps&);
virtual SkImageInfo imageInfo() const SK_OVERRIDE;
SkImageInfo imageInfo() const override;
protected:
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE;
/** Clears the entire device to the specified color (including alpha).
* Ignores the clip.
*/
virtual void clear(SkColor color) SK_OVERRIDE;
bool onShouldDisableLCD(const SkPaint&) const override;
/** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations,
and are handling any looping from the paint, and any effects from the
DrawFilter.
*/
virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE;
void drawPaint(const SkDraw&, const SkPaint& paint) override;
virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
const SkPoint[], const SkPaint& paint) SK_OVERRIDE;
const SkPoint[], const SkPaint& paint) override;
virtual void drawRect(const SkDraw&, const SkRect& r,
const SkPaint& paint) SK_OVERRIDE;
const SkPaint& paint) override;
virtual void drawOval(const SkDraw&, const SkRect& oval,
const SkPaint& paint) SK_OVERRIDE;
const SkPaint& paint) override;
virtual void drawRRect(const SkDraw&, const SkRRect& rr,
const SkPaint& paint) SK_OVERRIDE;
const SkPaint& paint) override;
/**
* If pathIsMutable, then the implementation is allowed to cast path to a
@ -72,43 +92,34 @@ protected:
virtual void drawPath(const SkDraw&, const SkPath& path,
const SkPaint& paint,
const SkMatrix* prePathMatrix = NULL,
bool pathIsMutable = false) SK_OVERRIDE;
bool pathIsMutable = false) override;
virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE;
const SkMatrix& matrix, const SkPaint& paint) override;
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) SK_OVERRIDE;
int x, int y, const SkPaint& paint) override;
/**
* The default impl. will create a bitmap-shader from the bitmap,
* and call drawRect with it.
*/
virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
const SkRect* srcOrNull, const SkRect& dst,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE;
void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect*, const SkRect&,
const SkPaint&, SkCanvas::SrcRectConstraint) override;
/**
* Does not handle text decoration.
* Decorations (underline and stike-thru) will be handled by SkCanvas.
*/
virtual void drawText(const SkDraw&, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE;
SkScalar x, SkScalar y, const SkPaint& paint) override;
virtual void drawPosText(const SkDraw&, const void* text, size_t len,
const SkScalar pos[], SkScalar constY,
int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE;
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) SK_OVERRIDE;
const SkScalar pos[], int scalarsPerPos,
const SkPoint& offset, const SkPaint& paint) override;
virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
const SkPoint verts[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
/** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to
onCreateDevice on this device with kSaveLayer_Usage.
*/
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) SK_OVERRIDE;
const SkPaint& paint) override;
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) override;
///////////////////////////////////////////////////////////////////////////
@ -117,7 +128,7 @@ protected:
altered. The config/width/height/rowbytes must remain unchanged.
@return the device contents as a bitmap
*/
virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE;
const SkBitmap& onAccessBitmap() override;
SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
// just for subclasses, to assign a custom pixelref
@ -126,15 +137,12 @@ protected:
return pr;
}
virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) SK_OVERRIDE;
virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int, int) SK_OVERRIDE;
virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes) SK_OVERRIDE;
/** Called when this device is installed into a Canvas. Balanced by a call
to unlockPixels() when the device is removed from a Canvas.
*/
virtual void lockPixels() SK_OVERRIDE;
virtual void unlockPixels() SK_OVERRIDE;
bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) override;
bool onWritePixels(const SkImageInfo&, const void*, size_t, int, int) override;
bool onPeekPixels(SkPixmap*) override;
bool onAccessPixels(SkPixmap*) override;
void onAttachToCanvas(SkCanvas*) override;
void onDetachFromCanvas() override;
private:
friend class SkCanvas;
@ -142,22 +150,24 @@ private:
friend class SkDraw;
friend class SkDrawIter;
friend class SkDeviceFilteredPaint;
friend class SkDeviceImageFilterProxy;
friend class SkSurface_Raster;
// 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.
virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE;
void replaceBitmapBackendForRasterSurface(const SkBitmap&) override;
virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes) SK_OVERRIDE;
SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) override;
SkImageFilter::Cache* getImageFilterCache() override;
SkBitmap fBitmap;
void setNewSize(const SkISize&); // Used by SkCanvas for resetForNextPicture().
typedef SkBaseDevice INHERITED;
};

View File

@ -26,17 +26,26 @@ public:
a corresponding scanline of 16bit colors (specific format based on the
config passed to the Factory.
The x,y params are useful just for dithering
The x,y params provide the dithering phase for the start of the scanline
@param alpha A global alpha to be applied to all of the src colors
@param x The x coordinate of the beginning of the scanline
@param y THe y coordinate of the scanline
*/
typedef void (*Proc)(uint16_t* dst,
const SkPMColor* src,
int count, U8CPU alpha, int x, int y);
typedef void (*Proc16)(uint16_t dst[], const SkPMColor src[], int count,
U8CPU alpha, int x, int y);
static Proc Factory(unsigned flags, SkColorType);
static Proc16 Factory16(unsigned flags);
/**
* Function pointer that blends a single src color onto a scaline of dst colors.
*
* The x,y params provide the dithering phase for the start of the scanline
*/
typedef void (*ColorProc16)(uint16_t dst[], SkPMColor src, int count, int x, int y);
// Note : we ignore the kGlobalAlpha_Flag setting, but do respect kSrcPixelAlpha_Flag
static ColorProc16 ColorFactory16(unsigned flags);
///////////// D32 version
@ -51,38 +60,15 @@ public:
@param count number of colors to blend
@param alpha global alpha to be applied to all src colors
*/
typedef void (*Proc32)(uint32_t* dst,
const SkPMColor* src,
int count, U8CPU alpha);
typedef void (*Proc32)(uint32_t dst[], const SkPMColor src[], int count, U8CPU alpha);
static Proc32 Factory32(unsigned flags32);
/** Function pointer that blends a single color with a row of 32-bit colors
onto a 32-bit destination
*/
typedef void (*ColorProc)(SkPMColor* dst, const SkPMColor* src, int count,
SkPMColor color);
/** Blend a single color onto a row of S32 pixels, writing the result
into a row of D32 pixels. src and dst may be the same memory, but
if they are not, they may not overlap.
*/
static void Color32(SkPMColor dst[], const SkPMColor src[],
int count, SkPMColor color);
//! Public entry-point to return a blit function ptr
static ColorProc ColorProcFactory();
/** Function pointer that blends a single color onto a 32-bit rectangle. */
typedef void (*ColorRectProc)(SkPMColor* dst, int width, int height,
size_t rowBytes, SkPMColor color);
/** Blend a single color into a rectangle of D32 pixels. */
static void ColorRect32(SkPMColor* dst, int width, int height,
size_t rowBytes, SkPMColor color);
//! Public entry-point to return a blit function ptr
static ColorRectProc ColorRectProcFactory();
static void Color32(SkPMColor dst[], const SkPMColor src[], int count, SkPMColor color);
/** These static functions are called by the Factory and Factory32
functions, and should return either NULL, or a
@ -91,8 +77,9 @@ public:
*/
static Proc32 PlatformProcs32(unsigned flags);
static Proc PlatformProcs565(unsigned flags);
static ColorProc PlatformColorProc();
static Proc16 PlatformFactory565(unsigned flags);
static ColorProc16 PlatformColorFactory565(unsigned flags);
private:
enum {

View File

@ -11,30 +11,31 @@
#include "SkTypes.h"
#include "SkBitmap.h"
#include "SkDeque.h"
#include "SkClipStack.h"
#include "SkPaint.h"
#include "SkRefCnt.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkSurfaceProps.h"
#include "SkXfermode.h"
#ifdef SK_SUPPORT_LEGACY_DRAWTEXT_VIRTUAL
#define SK_LEGACY_DRAWTEXT_VIRTUAL virtual
#else
#define SK_LEGACY_DRAWTEXT_VIRTUAL
#endif
class SkCanvasClipVisitor;
class SkBaseDevice;
class SkDraw;
class SkDrawFilter;
class SkMetaData;
class SkPicture;
class SkRRect;
class SkSurface;
class SkSurface_Base;
class GrContext;
class GrRenderTarget;
class SkBaseDevice;
class SkCanvasClipVisitor;
class SkClipStack;
class SkDraw;
class SkDrawable;
class SkDrawFilter;
class SkImage;
class SkImageFilter;
class SkMetaData;
class SkPath;
class SkPicture;
class SkPixmap;
class SkRRect;
struct SkRSXform;
class SkSurface;
class SkSurface_Base;
class SkTextBlob;
/** \class SkCanvas
@ -53,37 +54,6 @@ class GrRenderTarget;
*/
class SK_API SkCanvas : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkCanvas)
/**
* Attempt to allocate an offscreen raster canvas, matching the ImageInfo.
* On success, return a new canvas that will draw into that offscreen.
*
* The caller can access the pixels after drawing into this canvas by
* calling readPixels() or peekPixels().
*
* If the requested ImageInfo is opaque (either the colortype is
* intrinsically opaque like RGB_565, or the info's alphatype is kOpaque)
* then the pixel memory may be uninitialized. Otherwise, the pixel memory
* will be initialized to 0, which is interpreted as transparent.
*
* On failure, return NULL. This can fail for several reasons:
* 1. the memory allocation failed (e.g. request is too large)
* 2. invalid ImageInfo (e.g. negative dimensions)
* 3. unsupported ImageInfo for a canvas
* - kUnknown_SkColorType, kIndex_8_SkColorType
* - kIgnore_SkAlphaType
* - this list is not complete, so others may also be unsupported
*
* Note: it is valid to request a supported ImageInfo, but with zero
* dimensions.
*/
static SkCanvas* NewRaster(const SkImageInfo&);
static SkCanvas* NewRasterN32(int width, int height) {
return NewRaster(SkImageInfo::MakeN32Premul(width, height));
}
/**
* Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
* specified pixels. To access the pixels after drawing to them, the caller should call
@ -93,7 +63,7 @@ public:
* 1. invalid ImageInfo (e.g. negative dimensions)
* 2. unsupported ImageInfo for a canvas
* - kUnknown_SkColorType, kIndex_8_SkColorType
* - kIgnore_SkAlphaType
* - kUnknown_SkAlphaType
* - this list is not complete, so others may also be unsupported
*
* Note: it is valid to request a supported ImageInfo, but with zero
@ -116,7 +86,7 @@ public:
* by any device/pixels. Typically this use used by subclasses who handle
* the draw calls in some other way.
*/
SkCanvas(int width, int height);
SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
/** Construct a canvas with the specified device to draw into.
@ -129,6 +99,14 @@ public:
structure are copied to the canvas.
*/
explicit SkCanvas(const SkBitmap& bitmap);
/** Construct a canvas with the specified bitmap to draw into.
@param bitmap Specifies a bitmap for the canvas to draw into. Its
structure are copied to the canvas.
@param props New canvas surface properties.
*/
SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
virtual ~SkCanvas();
SkMetaData& getMetaData();
@ -151,7 +129,7 @@ public:
* origin of the base layer is always (0,0). The current drawable area may be
* smaller (due to clipping or saveLayer).
*/
SkISize getBaseLayerSize() const;
virtual SkISize getBaseLayerSize() const;
/**
* DEPRECATED: call getBaseLayerSize
@ -169,6 +147,9 @@ protected: // Can we make this private?
#endif
SkBaseDevice* getDevice() const;
public:
SkBaseDevice* getDevice_just_for_deprecated_compatibility_testing() const {
return this->getDevice();
}
/**
* saveLayer() can create another device (which is later drawn onto
@ -193,8 +174,12 @@ public:
* Create a new surface matching the specified info, one that attempts to
* be maximally compatible when used with this canvas. If there is no matching Surface type,
* NULL is returned.
*
* If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
* inherits the properties of the surface that owns this canvas. If this canvas has no parent
* surface, then the new surface is created with default properties.
*/
SkSurface* newSurface(const SkImageInfo&);
SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL);
/**
* Return the GPU context of the device that is associated with the canvas.
@ -347,6 +332,9 @@ public:
@return The value to pass to restoreToCount() to balance this save()
*/
int saveLayer(const SkRect* bounds, const SkPaint* paint);
int saveLayer(const SkRect& bounds, const SkPaint* paint) {
return this->saveLayer(&bounds, paint);
}
/** DEPRECATED - use saveLayer(const SkRect*, const SkPaint*) instead.
@ -417,11 +405,6 @@ public:
*/
void restoreToCount(int saveCount);
/** Returns true if drawing is currently going to a layer (from saveLayer)
* rather than to the root device.
*/
virtual bool isDrawingToLayer() const;
/** Preconcat the current matrix with the specified translation
@param dx The distance to translate in X
@param dy The distance to translate in Y
@ -609,24 +592,15 @@ public:
@param color the color to draw with
@param mode the mode to apply the color in (defaults to SrcOver)
*/
void drawColor(SkColor color,
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
/**
* This erases the entire drawing surface to the specified color,
* irrespective of the clip. It does not blend with the previous pixels,
* but always overwrites them.
*
* It is roughly equivalent to the following:
* canvas.save();
* canvas.clipRect(hugeRect, kReplace_Op);
* paint.setColor(color);
* paint.setXfermodeMode(kSrc_Mode);
* canvas.drawPaint(paint);
* canvas.restore();
* though it is almost always much more efficient.
* Helper method for drawing a color in SRC mode, completely replacing all the pixels
* in the current clip with this color.
*/
virtual void clear(SkColor);
void clear(SkColor color) {
this->drawColor(color, SkXfermode::kSrc_Mode);
}
/**
* This makes the contents of the canvas undefined. Subsequent calls that
@ -647,7 +621,7 @@ public:
* specified paint.
* @param paint The paint used to fill the canvas
*/
virtual void drawPaint(const SkPaint& paint);
void drawPaint(const SkPaint& paint);
enum PointMode {
/** drawPoints draws each point separately */
@ -679,8 +653,7 @@ public:
@param pts Array of points to draw
@param paint The paint used to draw the points
*/
virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
const SkPaint& paint);
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
/** Helper method for drawing a single point. See drawPoints() for a more
details.
@ -711,7 +684,7 @@ public:
@param rect The rect to be drawn
@param paint The paint used to draw the rect
*/
virtual void drawRect(const SkRect& rect, const SkPaint& paint);
void drawRect(const SkRect& rect, const SkPaint& paint);
/** Draw the specified rectangle using the specified paint. The rectangle
will be filled or framed based on the Style in the paint.
@ -740,7 +713,7 @@ public:
@param oval The rectangle bounds of the oval to be drawn
@param paint The paint used to draw the oval
*/
virtual void drawOval(const SkRect& oval, const SkPaint&);
void drawOval(const SkRect& oval, const SkPaint&);
/**
* Draw the specified RRect using the specified paint The rrect will be filled or stroked
@ -749,7 +722,7 @@ public:
* @param rrect The round-rect to draw
* @param paint The paint used to draw the round-rect
*/
virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
void drawRRect(const SkRRect& rrect, const SkPaint& paint);
/**
* Draw the annulus formed by the outer and inner rrects. The results
@ -797,7 +770,84 @@ public:
@param path The path to be drawn
@param paint The paint used to draw the path
*/
virtual void drawPath(const SkPath& path, const SkPaint& paint);
void drawPath(const SkPath& path, const SkPaint& paint);
/** Draw the specified image, with its top/left corner at (x,y), using the
specified paint, transformed by the current matrix.
@param image The image to be drawn
@param left The position of the left side of the image being drawn
@param top The position of the top side of the image being drawn
@param paint The paint used to draw the image, or NULL
*/
void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
/**
* Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
* trading off speed for exactness.
*
* When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
* the pixels in the image. If there is a src-rect specified, it is intended to restrict the
* pixels that will be read. However, for performance reasons, some implementations may slow
* down if they cannot read 1-pixel past the src-rect boundary at times.
*
* This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
* If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
* must be strictly respected, the caller should pass kStrict.
*/
enum SrcRectConstraint {
/**
* If kStrict is specified, the implementation must respect the src-rect
* (if specified) strictly, and will never sample outside of those bounds during sampling
* even when filtering. This may be slower than kFast.
*/
kStrict_SrcRectConstraint,
/**
* If kFast is specified, the implementation may sample outside of the src-rect
* (if specified) by half the width of filter. This allows greater flexibility
* to the implementation and can make the draw much faster.
*/
kFast_SrcRectConstraint,
};
/** Draw the specified image, scaling and translating so that it fills the specified
* dst rect. If the src rect is non-null, only that subset of the image is transformed
* and drawn.
*
* @param image The image to be drawn
* @param src Optional: specify the subset of the image to be drawn
* @param dst The destination rectangle where the scaled/translated
* image will be drawn
* @param paint The paint used to draw the image, or NULL
* @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
*/
void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
const SkPaint* paint,
SrcRectConstraint constraint = kStrict_SrcRectConstraint);
// variant that takes src SkIRect
void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
// variant that assumes src == image-bounds
void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
SrcRectConstraint = kStrict_SrcRectConstraint);
/**
* Draw the image stretched differentially to fit into dst.
* center is a rect within the image, and logically divides the image
* into 9 sections (3x3). For example, if the middle pixel of a [5x5]
* image is the "center", then the center-rect should be [2, 2, 3, 3].
*
* If the dst is >= the image size, then...
* - The 4 corners are not stretched at all.
* - The sides are stretched in only one axis.
* - The center is stretched in both axes.
* Else, for each axis where dst < image,
* - The corners shrink proportionally
* - The sides (along the shrink axis) and center are not drawn
*/
void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint* paint = NULL);
/** Draw the specified bitmap, with its top/left corner at (x,y), using the
specified paint, transformed by the current matrix. Note: if the paint
@ -815,51 +865,27 @@ public:
@param top The position of the top side of the bitmap being drawn
@param paint The paint used to draw the bitmap, or NULL
*/
virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
const SkPaint* paint = NULL);
void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
const SkPaint* paint = NULL);
enum DrawBitmapRectFlags {
kNone_DrawBitmapRectFlag = 0x0,
/**
* When filtering is enabled, allow the color samples outside of
* the src rect (but still in the src bitmap) to bleed into the
* drawn portion
*/
kBleed_DrawBitmapRectFlag = 0x1,
};
/** Draw the specified bitmap, with the specified matrix applied (before the
canvas' matrix is applied).
@param bitmap The bitmap to be drawn
@param src Optional: specify the subset of the bitmap to be drawn
@param dst The destination rectangle where the scaled/translated
image will be drawn
@param paint The paint used to draw the bitmap, or NULL
*/
virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst,
const SkPaint* paint = NULL,
DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
const SkPaint* paint = NULL) {
this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
}
void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
const SkRect& dst, const SkPaint* paint = NULL,
DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
SkRect realSrcStorage;
SkRect* realSrcPtr = NULL;
if (isrc) {
realSrcStorage.set(*isrc);
realSrcPtr = &realSrcStorage;
}
this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
}
virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
const SkPaint* paint = NULL);
/** Draw the specified bitmap, scaling and translating so that it fills the specified
* dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
* and drawn.
*
* @param bitmap The bitmap to be drawn
* @param src Optional: specify the subset of the bitmap to be drawn
* @param dst The destination rectangle where the scaled/translated
* bitmap will be drawn
* @param paint The paint used to draw the bitmap, or NULL
* @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
*/
void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
// variant where src is SkIRect
void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
SrcRectConstraint = kStrict_SrcRectConstraint);
/**
* Draw the bitmap stretched differentially to fit into dst.
@ -875,8 +901,8 @@ public:
* - The corners shrink proportionally
* - The sides (along the shrink axis) and center are not drawn
*/
virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint = NULL);
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
@ -889,8 +915,7 @@ public:
@param top The position of the top side of the bitmap being drawn
@param paint The paint used to draw the bitmap, or NULL
*/
virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
const SkPaint* paint = 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.
@ -900,8 +925,8 @@ public:
@param y The y-coordinate of the origin of the text being drawn
@param paint The paint used for the text (e.g. color, size, style)
*/
SK_LEGACY_DRAWTEXT_VIRTUAL void drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint);
void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint);
/** Draw the text, with each character/glyph origin specified by the pos[]
array. The origin is interpreted by the Align setting in the paint.
@ -910,8 +935,8 @@ public:
@param pos Array of positions, used to position each character
@param paint The paint used for the text (e.g. color, size, style)
*/
SK_LEGACY_DRAWTEXT_VIRTUAL void drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint);
void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
const SkPaint& paint);
/** Draw the text, with each character/glyph origin specified by the x
coordinate taken from the xpos[] array, and the y from the constY param.
@ -922,9 +947,8 @@ public:
@param constY The shared Y coordinate for all of the positions
@param paint The paint used for the text (e.g. color, size, style)
*/
SK_LEGACY_DRAWTEXT_VIRTUAL void drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint);
void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
const SkPaint& paint);
/** Draw the text, with origin at (x,y), using the specified paint, along
the specified path. The paint's Align setting determins where along the
@ -938,8 +962,7 @@ public:
position the text
@param paint The paint used for the text
*/
void drawTextOnPathHV(const void* text, size_t byteLength,
const SkPath& path, SkScalar hOffset,
void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
SkScalar vOffset, const SkPaint& paint);
/** Draw the text, with origin at (x,y), using the specified paint, along
@ -952,17 +975,16 @@ public:
mapped onto the path
@param paint The paint used for the text
*/
SK_LEGACY_DRAWTEXT_VIRTUAL void drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint);
void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint& paint);
/** PRIVATE / EXPERIMENTAL -- do not call
Perform back-end analysis/optimization of a picture. This may attach
optimization data to the picture which can be used by a later
drawPicture call.
@param picture The recorded drawing commands to analyze/optimize
/** Draw the text blob, offset by (x,y), using the specified paint.
@param blob The text blob to be drawn
@param x The x-offset of the text being drawn
@param y The y-offset of the text being drawn
@param paint The paint used for the text (e.g. color, size, style)
*/
void EXPERIMENTAL_optimize(const SkPicture* picture);
void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
/** Draw the picture into this canvas. This method effective brackets the
playback of the picture's draw calls with save/restore, so the state
@ -970,7 +992,23 @@ public:
@param picture The recorded drawing commands to playback into this
canvas.
*/
void drawPicture(const SkPicture* picture);
void drawPicture(const SkPicture* picture) {
this->drawPicture(picture, NULL, NULL);
}
/**
* Draw the picture into this canvas.
*
* If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
* logically equivalent to
* save/concat/drawPicture/restore
*
* If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
* alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
* This is logically equivalent to
* saveLayer(paint)/drawPicture/restore
*/
void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
enum VertexMode {
kTriangles_VertexMode,
@ -1001,48 +1039,64 @@ public:
@param indexCount number of entries in the indices array (if not null)
@param paint Specifies the shader/texture if present.
*/
virtual void drawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint);
void drawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint);
/** Send a blob of data to the canvas.
For canvases that draw, this call is effectively a no-op, as the data
is not parsed, but just ignored. However, this call exists for
subclasses like SkPicture's recording canvas, that can store the data
and then play it back later (via another call to drawData).
*/
virtual void drawData(const void* data, size_t length) {
// do nothing. Subclasses may do something with the data
}
/**
Draw a cubic coons patch
/** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
Each comment added via addComment is notionally attached to its
enclosing group. Top-level comments simply belong to no group.
@param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
starting at the top left corner.
@param colors specifies the colors for the corners which will be bilerp across the patch,
their order is clockwise starting at the top left corner.
@param texCoords specifies the texture coordinates that will be bilerp across the patch,
their order is the same as the colors.
@param xmode specifies how are the colors and the textures combined if both of them are
present.
@param paint Specifies the shader/texture if present.
*/
virtual void beginCommentGroup(const char* description) {
// do nothing. Subclasses may do something
}
virtual void addComment(const char* kywd, const char* value) {
// do nothing. Subclasses may do something
}
virtual void endCommentGroup() {
// do nothing. Subclasses may do something
void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
/**
* Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
* coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
* into a quad.
*
* xform maps [0, 0, tex.width, tex.height] -> quad
*
* The color array is optional. When specified, each color modulates the pixels in its
* corresponding quad (via the specified SkXfermode::Mode).
*
* The cullRect is optional. When specified, it must be a conservative bounds of all of the
* resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
* intersect the current clip.
*
* The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
* and xfermode are used to affect each of the quads.
*/
void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
const SkColor colors[], int count, SkXfermode::Mode, const SkRect* cullRect,
const SkPaint* paint);
void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
const SkRect* cullRect, const SkPaint* paint) {
this->drawAtlas(atlas, xform, tex, NULL, count, SkXfermode::kDst_Mode, cullRect, paint);
}
/**
* With this call the client asserts that subsequent draw operations (up to the
* matching popCull()) are fully contained within the given bounding box. The assertion
* is not enforced, but the information might be used to quick-reject command blocks,
* so an incorrect bounding box may result in incomplete rendering.
* Draw the contents of this drawable into the canvas. If the canvas is async
* (e.g. it is recording into a picture) then the drawable will be referenced instead,
* to have its draw() method called when the picture is finalized.
*
* If the intent is to force the contents of the drawable into this canvas immediately,
* then drawable->draw(canvas) may be called.
*/
void pushCull(const SkRect& cullRect);
/**
* Terminates the current culling block, and restores the previous one (if any).
*/
void popCull();
void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
//////////////////////////////////////////////////////////////////////////
@ -1085,25 +1139,13 @@ public:
*/
const SkMatrix& getTotalMatrix() const;
#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
enum ClipType {
kEmpty_ClipType = 0,
kRect_ClipType,
kComplex_ClipType
};
/** Returns a description of the total clip; may be cheaper than
getting the clip and querying it directly.
*/
virtual ClipType getClipType() const;
#endif
/** Return the clip stack. The clip stack stores all the individual
* clips organized by the save/restore frame in which they were
* added.
* @return the current clip stack ("list" of individual clip elements)
*/
const SkClipStack* getClipStack() const {
return &fClipStack;
return fClipStack;
}
typedef SkCanvasClipVisitor ClipVisitor;
@ -1154,20 +1196,30 @@ public:
bool fDone;
};
// don't call
const SkRegion& internal_private_getTotalClip() const;
// don't call
void internal_private_getTotalClipAsPath(SkPath*) const;
// don't call
GrRenderTarget* internal_private_accessTopLayerRenderTarget();
// don't call
static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
static bool Internal_Private_GetIgnoreSaveLayerBounds();
static void Internal_Private_SetTreatSpriteAsBitmap(bool);
static bool Internal_Private_GetTreatSpriteAsBitmap();
// TEMP helpers until we switch virtual over to const& for src-rect
void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint,
SrcRectConstraint constraint = kStrict_SrcRectConstraint);
void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
const SkPaint* paint,
SrcRectConstraint constraint = kStrict_SrcRectConstraint);
protected:
// default impl defers to getDevice()->newSurface(info)
virtual SkSurface* onNewSurface(const SkImageInfo&);
virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
// default impl defers to its device
virtual const void* onPeekPixels(SkImageInfo*, size_t* rowBytes);
virtual void* onAccessTopLayerPixels(SkImageInfo*, size_t* rowBytes);
virtual bool onPeekPixels(SkPixmap*);
virtual bool onAccessTopLayerPixels(SkPixmap*);
// Subclass save/restore notifiers.
// Overriders should call the corresponding INHERITED method up the inheritance chain.
@ -1182,6 +1234,7 @@ protected:
return kFullLayer_SaveLayerStrategy;
}
virtual void willRestore() {}
virtual void didRestore() {}
virtual void didConcat(const SkMatrix&) {}
virtual void didSetMatrix(const SkMatrix&) {}
@ -1201,6 +1254,39 @@ protected:
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint);
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint);
virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
virtual void onDrawPaint(const SkPaint&);
virtual void onDrawRect(const SkRect&, const SkPaint&);
virtual void onDrawOval(const SkRect&, const SkPaint&);
virtual void onDrawRRect(const SkRRect&, const SkPaint&);
virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount, const SkPaint&);
virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*);
virtual void onDrawPath(const SkPath&, const SkPaint&);
virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
SrcRectConstraint);
virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint*);
virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
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,
kSoft_ClipEdgeStyle
@ -1213,7 +1299,7 @@ protected:
virtual void onDiscard();
virtual void onDrawPicture(const SkPicture* picture);
virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
// Returns the canvas to be used by DrawIter. Default implementation
// returns this. Subclasses that encapsulate an indirect canvas may
@ -1229,30 +1315,40 @@ protected:
SkIRect* intersection,
const SkImageFilter* imageFilter = NULL);
// Called by child classes that override clipPath and clipRRect to only
// track fast conservative clip bounds, rather than exact clips.
void updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
bool inverseFilled);
private:
enum ShaderOverrideOpacity {
kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
};
// notify our surface (if we have one) that we are about to draw, so it
// can perform copy-on-write or invalidate any cached images
void predrawNotify();
void predrawNotify(bool willOverwritesEntireSurface = false);
void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
: kNotOpaque_ShaderOverrideOpacity);
}
virtual void onPushCull(const SkRect& cullRect);
virtual void onPopCull();
private:
class MCRec;
SkClipStack fClipStack;
SkAutoTUnref<SkClipStack> fClipStack;
SkDeque fMCStack;
// points to top of stack
MCRec* fMCRec;
// the first N recs that can fit here mean we won't call malloc
uint32_t fMCRecStorage[32];
enum {
kMCRecSize = 128, // most recent measurement
kMCRecCount = 32, // common depth for save/restores
kDeviceCMSize = 136, // most recent measurement
};
intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
int fSaveLayerCount; // number of successful saveLayer calls
int fCullCount; // number of active culls
const SkSurfaceProps fProps;
int fSaveCount; // value returned by getSaveCount()
SkMetaData* fMetaData;
@ -1267,25 +1363,37 @@ private:
bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
void updateDeviceCMCache();
void doSave();
void checkForDeferredSave();
friend class SkDrawIter; // needs setupDrawForLayerDevice()
friend class AutoDrawLooper;
friend class SkLua; // needs top layer size and offset
friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
friend class SkDeferredDevice; // needs getTopDevice()
friend class SkSurface_Raster; // needs getDevice()
friend class SkRecorder; // InitFlags
friend class SkNoSaveLayerCanvas; // InitFlags
friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
SkBaseDevice* createLayerDevice(const SkImageInfo&);
enum InitFlags {
kDefault_InitFlags = 0,
kConservativeRasterClip_InitFlag = 1 << 0,
};
SkCanvas(const SkIRect& bounds, InitFlags);
SkCanvas(SkBaseDevice* device, InitFlags);
SkBaseDevice* init(SkBaseDevice*);
void resetForNextPicture(const SkIRect& bounds);
/**
* DEPRECATED
*
* Specify a device for this canvas to draw into. If it is not null, its
* reference count is incremented. If the canvas was already holding a
* device, its reference count is decremented. The new device is returned.
*/
SkBaseDevice* setRootDevice(SkBaseDevice* device);
// needs gettotalclip()
friend class SkCanvasStateUtils;
// call this each time we attach ourselves to a device
// - constructor
// - internalSaveLayer
void setupDevice(SkBaseDevice*);
SkBaseDevice* init(SkBaseDevice*, InitFlags);
/**
* Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
@ -1294,21 +1402,15 @@ private:
SkISize getTopLayerSize() const;
SkIPoint getTopLayerOrigin() const;
// internal methods are not virtual, so they can safely be called by other
// canvas apis, without confusing subclasses (like SkPictureRecording)
void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
DrawBitmapRectFlags flags);
void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint);
SrcRectConstraint);
void internalDrawPaint(const SkPaint& paint);
int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy);
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy);
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
// shared by save() and saveLayer()
int internalSave();
void internalSave();
void internalRestore();
static void DrawRect(const SkDraw& draw, const SkPaint& paint,
const SkRect& r, SkScalar textSize);
@ -1316,6 +1418,17 @@ private:
const char text[], size_t byteLength,
SkScalar x, SkScalar y);
// only for canvasutils
const SkRegion& internal_private_getTotalClip() const;
/*
* Returns true if drawing the specified rect (or all if it is null) with the specified
* paint (or default if null) would overwrite the entire root device of the canvas
* (i.e. the canvas' surface if it had one).
*/
bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
/* These maintain a cache of the clip bounds in local coordinates,
(converted to 2s-compliment if floats are slow).
*/
@ -1323,6 +1436,7 @@ private:
mutable bool fCachedLocalClipBoundsDirty;
bool fAllowSoftClip;
bool fAllowSimplifyClip;
const bool fConservativeRasterClip;
const SkRect& getLocalClipBounds() const {
if (fCachedLocalClipBoundsDirty) {
@ -1346,9 +1460,6 @@ private:
};
#ifdef SK_DEBUG
// The cull stack rects are in device-space
SkTDArray<SkIRect> fCullStack;
void validateCull(const SkIRect&);
void validateClip() const;
#else
void validateClip() const {}
@ -1394,28 +1505,6 @@ private:
};
#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
/** Stack helper class to automatically open and close a comment block
*/
class SkAutoCommentBlock : SkNoncopyable {
public:
SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
fCanvas = canvas;
if (NULL != fCanvas) {
fCanvas->beginCommentGroup(description);
}
}
~SkAutoCommentBlock() {
if (NULL != fCanvas) {
fCanvas->endCommentGroup();
}
}
private:
SkCanvas* fCanvas;
};
#define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock)
/**
* 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

View File

@ -22,6 +22,11 @@ public:
* pointers.
*/
void reset();
/**
* Reset to 0 used bytes preserving as much memory as possible.
* This invalidates all returned pointers.
*/
void rewind();
enum AllocFailType {
kReturnNil_AllocFailType,
@ -43,7 +48,8 @@ public:
size_t totalCapacity() const { return fTotalCapacity; }
size_t totalUsed() const { return fTotalUsed; }
int blockCount() const { return fBlockCount; }
SkDEBUGCODE(int blockCount() const { return fBlockCount; })
SkDEBUGCODE(size_t totalLost() const { return fTotalLost; })
/**
* Returns true if the specified address is within one of the chunks, and
@ -60,9 +66,13 @@ private:
size_t fChunkSize;
size_t fTotalCapacity;
size_t fTotalUsed; // will be <= fTotalCapacity
int fBlockCount;
SkDEBUGCODE(int fBlockCount;)
SkDEBUGCODE(size_t fTotalLost;) // will be <= fTotalCapacity
Block* newBlock(size_t bytes, AllocFailType ftype);
Block* addBlockIfNecessary(size_t bytes, AllocFailType ftype);
SkDEBUGCODE(void validate();)
};
#endif

View File

@ -24,7 +24,7 @@ class SkCanvasClipVisitor;
// (i.e., the fSaveCount in force when it was added). Restores are thus
// implemented by removing clips from fDeque that have an fSaveCount larger
// then the freshly decremented count.
class SK_API SkClipStack {
class SK_API SkClipStack : public SkNVRefCnt<SkClipStack> {
public:
enum BoundsType {
// The bounding box contains all the pixels that can be written to
@ -309,13 +309,6 @@ public:
BoundsType* boundType,
bool* isIntersectionOfRects = NULL) const;
/**
* Takes an input rect in device space and conservatively clips it to the
* clip-stack. If false is returned then the rect does not intersect the
* clip and is unmodified.
*/
bool intersectRectWithClip(SkRect* devRect) const;
/**
* Returns true if the input rect in device space is entirely contained
* by the clip. A return value of false does not guarantee that the rect
@ -323,6 +316,12 @@ public:
*/
bool quickContains(const SkRect& devRect) const;
/**
* Flattens the clip stack into a single SkPath. Returns true if any of
* the clip stack components requires anti-aliasing.
*/
bool asPath(SkPath* path) const;
void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
SkRect r;
r.set(ir);

View File

@ -1,4 +1,3 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -6,11 +5,11 @@
* found in the LICENSE file.
*/
#ifndef SkColor_DEFINED
#define SkColor_DEFINED
#include "SkScalar.h"
#include "SkTypes.h"
/** \file SkColor.h
@ -161,9 +160,4 @@ SK_API SkPMColor SkPreMultiplyColor(SkColor c);
*/
typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst);
/** Define a function pointer type for combining a premultiplied src color
and a 16bit device color.
*/
typedef uint16_t (*SkXfermodeProc16)(SkPMColor src, uint16_t dst);
#endif

View File

@ -1,4 +1,3 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -6,17 +5,17 @@
* found in the LICENSE file.
*/
#ifndef SkColorFilter_DEFINED
#define SkColorFilter_DEFINED
#include "SkColor.h"
#include "SkFlattenable.h"
#include "SkTDArray.h"
#include "SkXfermode.h"
class SkBitmap;
class GrEffect;
class GrContext;
class GrFragmentProcessor;
class SkBitmap;
/**
* ColorFilters are optional objects in the drawing pipeline. When present in
@ -28,8 +27,6 @@ class GrContext;
*/
class SK_API SkColorFilter : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkColorFilter)
/**
* If the filter can be represented by a source color plus Mode, this
* returns true, and sets (if not NULL) the color and mode appropriately.
@ -69,34 +66,27 @@ public:
@param count the number of entries in the src[] and result[] arrays
@param result written by the filter
*/
virtual void filterSpan(const SkPMColor src[], int count,
SkPMColor result[]) const = 0;
/** Called with a scanline of colors, as if there was a shader installed.
The implementation writes out its filtered version into result[].
Note: shader and result may be the same buffer.
@param src array of colors, possibly generated by a shader
@param count the number of entries in the src[] and result[] arrays
@param result written by the filter
*/
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const;
virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0;
enum Flags {
/** If set the filter methods will not change the alpha channel of the
colors.
/** If set the filter methods will not change the alpha channel of the colors.
*/
kAlphaUnchanged_Flag = 0x01,
/** If set, this subclass implements filterSpan16(). If this flag is
set, then kAlphaUnchanged_Flag must also be set.
*/
kHasFilter16_Flag = 0x02
};
/** Returns the flags for this filter. Override in subclasses to return
custom flags.
/** Returns the flags for this filter. Override in subclasses to return custom flags.
*/
virtual uint32_t getFlags() const { return 0; }
/**
* If this subclass can optimally createa composition with the inner filter, return it as
* a new filter (which the caller must unref() when it is done). If no such optimization
* is known, return NULL.
*
* e.g. result(color) == this_filter(inner(color))
*/
virtual SkColorFilter* newComposed(const SkColorFilter* /*inner*/) const { return NULL; }
/**
* Apply this colorfilter to the specified SkColor. This routine handles
* converting to SkPMColor, calling the filter, and then converting back
@ -123,10 +113,31 @@ public:
*/
static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
/** A subclass may implement this factory function to work with the GPU backend. If the return
is non-NULL then the caller owns a ref on the returned object.
/** 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.
*
* Due to internal limits, it is possible that this will return NULL, so the caller must
* always check.
*/
virtual GrEffect* asNewEffect(GrContext*) const;
static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
/**
* A subclass may implement this factory function to work with the GPU backend. It returns
* a GrFragmentProcessor that implemets the color filter in GPU shader code.
*
* The fragment processor receives a premultiplied input color and produces a premultiplied
* output color.
*
* A null return indicates that the color filter isn't implemented for the GPU backend.
*/
virtual const GrFragmentProcessor* asFragmentProcessor(GrContext*) const {
return nullptr;
}
bool affectsTransparentBlack() const {
return this->filterColor(0) != 0;
}
SK_TO_STRING_PUREVIRT()
@ -135,9 +146,18 @@ public:
protected:
SkColorFilter() {}
SkColorFilter(SkReadBuffer& rb) : INHERITED(rb) {}
private:
/*
* Returns 1 if this is a single filter (not a composition of other filters), otherwise it
* reutrns the number of leaf-node filters in a composition. This should be the same value
* as the number of GrFragmentProcessors returned by asFragmentProcessors's array parameter.
*
* e.g. compose(filter, compose(compose(filter, filter), filter)) --> 4
*/
virtual int privateComposedFilterCount() const { return 1; }
friend class SkComposeColorFilter;
typedef SkFlattenable INHERITED;
};

View File

@ -193,7 +193,7 @@ static inline unsigned Sk255To256(U8CPU value) {
/** Multiplify value by 0..256, and shift the result down 8
(i.e. return (value * alpha256) >> 8)
*/
#define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8)
#define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
// The caller may want negative values, so keep all params signed (int)
// so we don't accidentally slip into unsigned math and lose the sign
@ -213,11 +213,21 @@ static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
SkASSERT((int16_t)dst == dst);
SkASSERT((uint8_t)alpha == alpha);
int prod = SkMulS16(src - dst, alpha) + 128;
int prod = (src - dst) * alpha + 128;
prod = (prod + (prod >> 8)) >> 8;
return dst + prod;
}
static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
if (x < 0) {
return 0;
}
if (x >= SK_Scalar1) {
return 255;
}
return SkScalarToFixed(x) >> 8;
}
#define SK_R16_BITS 5
#define SK_G16_BITS 6
#define SK_B16_BITS 5
@ -281,6 +291,16 @@ static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
// this helper explicitly returns a clean 16bit value (but slower)
#define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s)
/** Blend pre-expanded RGB32 with 16bit color value by the 0..32 scale parameter.
The computation yields only 16bits of valid data, but we claim to return
32bits, so that the compiler won't generate extra instructions to "clean"
the top 16bits.
*/
static inline U16CPU SkBlend32_RGB16(uint32_t src_expand, uint16_t dst, unsigned scale) {
uint32_t dst_expand = SkExpand_rgb_16(dst) * scale;
return SkCompact_rgb_16((src_expand + dst_expand) >> 5);
}
/** Blend src and dst 16bit colors by the 0..256 scale parameter.
The computation yields only 16bits of valid data, but we claim
to return 32bits, so that the compiler won't generate extra instructions to
@ -306,7 +326,8 @@ static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
do {
uint32_t src32 = SkExpand_rgb_16(*src++);
uint32_t dst32 = SkExpand_rgb_16(*dst);
*dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
*dst++ = static_cast<uint16_t>(
SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)));
} while (--count > 0);
}
@ -345,21 +366,31 @@ static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
#ifdef SK_DEBUG
static inline void SkPMColorAssert(SkPMColor c) {
unsigned a = SkGetPackedA32(c);
unsigned r = SkGetPackedR32(c);
unsigned g = SkGetPackedG32(c);
unsigned b = SkGetPackedB32(c);
SkA32Assert(a);
SkASSERT(r <= a);
SkASSERT(g <= a);
SkASSERT(b <= a);
}
#define SkPMColorAssert(color_value) \
do { \
SkPMColor pm_color_value = (color_value); \
uint32_t alpha_color_value = SkGetPackedA32(pm_color_value); \
SkA32Assert(alpha_color_value); \
SkASSERT(SkGetPackedR32(pm_color_value) <= alpha_color_value); \
SkASSERT(SkGetPackedG32(pm_color_value) <= alpha_color_value); \
SkASSERT(SkGetPackedB32(pm_color_value) <= alpha_color_value); \
} while (false)
#else
#define SkPMColorAssert(c)
#endif
static inline bool SkPMColorValid(SkPMColor c) {
auto a = SkGetPackedA32(c);
bool valid = a <= SK_A32_MASK
&& SkGetPackedR32(c) <= a
&& SkGetPackedG32(c) <= a
&& SkGetPackedB32(c) <= a;
if (valid) {
SkPMColorAssert(c); // Make sure we're consistent when it counts.
}
return valid;
}
/**
* Pack the components into a SkPMColor, checking (in the debug version) that
* the components are 0..255, and are already premultiplied (i.e. alpha >= color)
@ -787,7 +818,7 @@ static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
(g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
}
static inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
static inline SkPMColor16 SkAlphaMulQ4(SkPMColor16 c, int scale) {
SkASSERT(scale <= 16);
const unsigned mask = 0xF0F; //gMask_0F0F;
@ -797,14 +828,14 @@ static inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
unsigned ag = ((c >> 4) & mask) * scale;
return (rb & mask) | (ag & ~mask);
#else
c = (c & mask) | ((c & (mask << 4)) << 12);
c = c * scale >> 4;
return (c & mask) | ((c >> 12) & (mask << 4));
unsigned expanded_c = (c & mask) | ((c & (mask << 4)) << 12);
unsigned scaled_c = (expanded_c * scale) >> 4;
return (scaled_c & mask) | ((scaled_c >> 12) & (mask << 4));
#endif
}
/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
once by a value up to 16. Used in conjunction with SkCompact_4444.
once by a value up to 16.
*/
static inline uint32_t SkExpand_4444(U16CPU c) {
SkASSERT(c == (uint16_t)c);
@ -813,18 +844,6 @@ static inline uint32_t SkExpand_4444(U16CPU c) {
return (c & mask) | ((c & ~mask) << 12);
}
/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
It does this for speed, since if it is being written directly to 16bits of
memory, the top 16bits will be ignored. Casting the result to uint16_t here
would add 2 more instructions, slow us down. It is up to the caller to
perform the cast if needed.
*/
static inline U16CPU SkCompact_4444(uint32_t c) {
const unsigned mask = 0xF0F; //gMask_0F0F;
return (c & mask) | ((c >> 12) & ~mask);
}
static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
unsigned sa = SkGetPackedA4444(s);
unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
@ -856,22 +875,6 @@ static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale1
return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
}
static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
SkASSERT((unsigned)scale16 <= 16);
uint32_t src32 = SkExpand_4444(src) * scale16;
// the scaled srcAlpha is the bottom byte
#ifdef SK_DEBUG
{
unsigned srcA = SkGetPackedA4444(src) * scale16;
SkASSERT(srcA == (src32 & 0xFF));
}
#endif
unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
uint32_t dst32 = SkExpand_4444(dst) * dstScale;
return SkCompact_4444((src32 + dst32) >> 4);
}
static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
(SkGetPackedR4444(c) << SK_R32_SHIFT) |

View File

@ -10,6 +10,7 @@
#ifndef SkColorTable_DEFINED
#define SkColorTable_DEFINED
#include "../private/SkOncePtr.h"
#include "SkColor.h"
#include "SkFlattenable.h"
#include "SkImageInfo.h"
@ -18,75 +19,64 @@
SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by
8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable.
*/
class SkColorTable : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkColorTable)
/** Makes a deep copy of colors.
SkColorTable is thread-safe.
*/
class SK_API SkColorTable : public SkRefCnt {
public:
/** Copy up to 256 colors into a new SkColorTable.
*/
SkColorTable(const SkColorTable& src);
SkColorTable(const SkPMColor colors[], int count,
SkAlphaType alphaType = kPremul_SkAlphaType);
SkColorTable(const SkPMColor colors[], int count);
virtual ~SkColorTable();
SkAlphaType alphaType() const { return (SkAlphaType)fAlphaType; }
bool isOpaque() const {
return SkAlphaTypeIsOpaque(this->alphaType());
}
/** Returns the number of colors in the table.
*/
*/
int count() const { return fCount; }
/** Returns the specified color from the table. In the debug build, this asserts that
the index is in range (0 <= index < count).
*/
* the index is in range (0 <= index < count).
*/
SkPMColor operator[](int index) const {
SkASSERT(fColors != NULL && (unsigned)index < fCount);
SkASSERT(fColors != NULL && (unsigned)index < (unsigned)fCount);
return fColors[index];
}
/**
* Return the array of colors for reading. This must be balanced by a call
* to unlockColors().
/** Return the array of colors for reading.
*/
const SkPMColor* lockColors() {
SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);)
return fColors;
}
const SkPMColor* readColors() const { return fColors; }
/**
* Balancing call to lockColors().
/** read16BitCache() returns the array of RGB16 colors that mirror the 32bit colors.
*/
void unlockColors();
const uint16_t* read16BitCache() const;
/** Similar to lockColors(), lock16BitCache() returns the array of
RGB16 colors that mirror the 32bit colors. However, this function
will return null if kColorsAreOpaque_Flag is not set.
Also, unlike lockColors(), the returned array here cannot be modified.
*/
const uint16_t* lock16BitCache();
/** Balancing call to lock16BitCache().
*/
void unlock16BitCache() {
SkASSERT(f16BitCacheLockCount > 0);
SkDEBUGCODE(f16BitCacheLockCount -= 1);
}
explicit SkColorTable(SkReadBuffer&);
void writeToBuffer(SkWriteBuffer&) const;
private:
SkPMColor* fColors;
uint16_t* f16BitCache;
uint16_t fCount;
uint8_t fAlphaType;
SkDEBUGCODE(int fColorLockCount;)
SkDEBUGCODE(int f16BitCacheLockCount;)
// may return null
static SkColorTable* Create(SkReadBuffer&);
void inval16BitCache();
private:
enum AllocatedWithMalloc {
kAllocatedWithMalloc
};
// assumes ownership of colors (assumes it was allocated w/ malloc)
SkColorTable(SkPMColor* colors, int count, AllocatedWithMalloc);
SkPMColor* fColors;
SkOncePtr<uint16_t[]> f16BitCache;
int fCount;
void init(const SkPMColor* colors, int count);
friend class SkImageGenerator;
// Only call if no other thread or cache has seen this table.
void dangerous_overwriteColors(const SkPMColor newColors[], int count) {
if (count < 0 || count > fCount) {
sk_throw();
}
// assumes that f16BitCache nas NOT been initialized yet, so we don't try to update it
memcpy(fColors, newColors, count * sizeof(SkPMColor));
fCount = count; // update fCount, in case count is smaller
}
typedef SkRefCnt INHERITED;
};

View File

@ -34,7 +34,14 @@ public:
SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL);
virtual ~SkComposeShader();
virtual size_t contextSize() const SK_OVERRIDE;
size_t contextSize() const override;
#if SK_SUPPORT_GPU
const GrFragmentProcessor* asFragmentProcessor(GrContext*,
const SkMatrix& viewM,
const SkMatrix* localMatrix,
SkFilterQuality) const override;
#endif
class ComposeShaderContext : public SkShader::Context {
public:
@ -48,7 +55,7 @@ public:
virtual ~ComposeShaderContext();
virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
void shadeSpan(int x, int y, SkPMColor[], int count) override;
private:
SkShader::Context* fShaderContextA;
@ -62,15 +69,15 @@ public:
SkShader* getShaderB() { return fShaderB; }
#endif
virtual bool asACompose(ComposeRec* rec) const SK_OVERRIDE;
bool asACompose(ComposeRec* rec) const override;
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader)
protected:
SkComposeShader(SkReadBuffer& );
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
virtual Context* onCreateContext(const ContextRec&, void*) const SK_OVERRIDE;
void flatten(SkWriteBuffer&) const override;
Context* onCreateContext(const ContextRec&, void*) const override;
private:
SkShader* fShaderA;

View File

@ -1,4 +1,3 @@
/*
* Copyright 2011 Google Inc.
*
@ -6,14 +5,14 @@
* found in the LICENSE file.
*/
#ifndef SkData_DEFINED
#define SkData_DEFINED
#include <stdio.h>
#include "SkRefCnt.h"
struct SkFILE;
class SkStream;
/**
* SkData holds an immutable data buffer. Not only is the data immutable,
@ -22,8 +21,6 @@ struct SkFILE;
*/
class SK_API SkData : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkData)
/**
* Returns the number of bytes stored.
*/
@ -44,6 +41,19 @@ public:
return reinterpret_cast<const uint8_t*>(fPtr);
}
/**
* USE WITH CAUTION.
* This call will assert that the refcnt is 1, as a precaution against modifying the
* contents when another client/thread has access to the data.
*/
void* writable_data() {
if (fSize) {
// only assert we're unique if we're not empty
SkASSERT(this->unique());
}
return fPtr;
}
/**
* Helper to copy a range of the data into a caller-provided buffer.
* Returns the actual number of bytes copied, after clamping offset and
@ -60,15 +70,21 @@ public:
/**
* Function that, if provided, will be called when the SkData goes out
* of scope, allowing for custom allocation/freeing of the data.
* of scope, allowing for custom allocation/freeing of the data's contents.
*/
typedef void (*ReleaseProc)(const void* ptr, size_t length, void* context);
typedef void (*ReleaseProc)(const void* ptr, void* context);
/**
* Create a new dataref by copying the specified data
*/
static SkData* NewWithCopy(const void* data, size_t length);
/**
* Create a new data with uninitialized contents. The caller should call writable_data()
* to write into the buffer, but this must be done before another ref() is made.
*/
static SkData* NewUninitialized(size_t length);
/**
* Create a new dataref by copying the specified c-string
* (a null-terminated array of bytes). The returned SkData will have size()
@ -78,11 +94,18 @@ public:
static SkData* NewWithCString(const char cstr[]);
/**
* Create a new dataref, taking the data ptr as is, and using the
* Create a new dataref, taking the ptr as is, and using the
* releaseproc to free it. The proc may be NULL.
*/
static SkData* NewWithProc(const void* data, size_t length,
ReleaseProc proc, void* context);
static SkData* NewWithProc(const void* ptr, size_t length, ReleaseProc proc, void* context);
/**
* Call this when the data parameter is already const and will outlive the lifetime of the
* SkData. Suitable for with const globals.
*/
static SkData* NewWithoutCopy(const void* data, size_t length) {
return NewWithProc(data, length, DummyReleaseProc, NULL);
}
/**
* Create a new dataref from a pointer allocated by malloc. The Data object
@ -97,13 +120,13 @@ public:
static SkData* NewFromFileName(const char path[]);
/**
* Create a new dataref from a SkFILE.
* This does not take ownership of the SkFILE, nor close it.
* The caller is free to close the SkFILE at its convenience.
* The SkFILE must be open for reading only.
* Create a new dataref from a stdio FILE.
* This does not take ownership of the FILE, nor close it.
* The caller is free to close the FILE at its convenience.
* The FILE must be open for reading only.
* Returns NULL on failure.
*/
static SkData* NewFromFILE(SkFILE* f);
static SkData* NewFromFILE(FILE* f);
/**
* Create a new dataref from a file descriptor.
@ -114,6 +137,13 @@ public:
*/
static SkData* NewFromFD(int fd);
/**
* Attempt to read size bytes into a SkData. If the read succeeds, return the data,
* else return NULL. Either way the stream's cursor may have been changed as a result
* of calling read().
*/
static SkData* NewFromStream(SkStream*, size_t size);
/**
* Create a new dataref using a subset of the data in the specified
* src dataref.
@ -129,16 +159,29 @@ public:
private:
ReleaseProc fReleaseProc;
void* fReleaseProcContext;
const void* fPtr;
void* fPtr;
size_t fSize;
SkData(const void* ptr, size_t size, ReleaseProc, void* context);
explicit SkData(size_t size); // inplace new/delete
virtual ~SkData();
// Objects of this type are sometimes created in a custom fashion using sk_malloc_throw and
// therefore must be sk_freed. We overload new to also call sk_malloc_throw so that memory
// can be unconditionally released using sk_free in an overloaded delete. Overloading regular
// new means we must also overload placement new.
void* operator new(size_t size) { return sk_malloc_throw(size); }
void* operator new(size_t, void* p) { return p; }
void operator delete(void* p) { sk_free(p); }
// Called the first time someone calls NewEmpty to initialize the singleton.
static SkData* NewEmptyImpl();
static void DeleteEmpty(SkData*);
friend SkData* sk_new_empty_data();
// shared internal factory
static SkData* PrivateNewWithCopy(const void* srcOrNull, size_t length);
static void DummyReleaseProc(const void*, void*) {}
typedef SkRefCnt INHERITED;
};

View File

@ -20,8 +20,6 @@
*/
class SK_API SkDataTable : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkDataTable)
/**
* Returns true if the table is empty (i.e. has no entries).
*/

View File

@ -9,47 +9,31 @@
#define SkDevice_DEFINED
#include "SkRefCnt.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkDeviceProperties.h"
#include "SkImageFilter.h"
#include "SkSurfaceProps.h"
class SkBitmap;
class SkClipStack;
class SkDraw;
class SkDrawFilter;
struct SkIRect;
class SkMatrix;
class SkMetaData;
class SkRegion;
class GrRenderTarget;
class SK_API SkBaseDevice : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkBaseDevice)
/**
* Construct a new device.
*/
SkBaseDevice();
/**
* Construct a new device.
*/
SkBaseDevice(const SkDeviceProperties& deviceProperties);
explicit SkBaseDevice(const SkSurfaceProps&);
virtual ~SkBaseDevice();
SkBaseDevice* createCompatibleDevice(const SkImageInfo&);
SkMetaData& getMetaData();
/** Return the image properties of the device. */
virtual const SkDeviceProperties& getDeviceProperties() const {
//Currently, all the properties are leaky.
return fLeakyProperties;
}
/**
* Return ImageInfo for this device. If the canvas is not backed by pixels
* (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
@ -67,6 +51,12 @@ public:
bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
}
SkIRect getGlobalBounds() const {
SkIRect bounds;
this->getGlobalBounds(&bounds);
return bounds;
}
int width() const {
return this->imageInfo().width();
}
@ -89,7 +79,22 @@ public:
bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y);
void* accessPixels(SkImageInfo* info, size_t* rowBytes);
/**
* Try to get write-access to the pixels behind the device. If successful, this returns true
* and fills-out the pixmap parameter. On success it also bumps the genID of the underlying
* bitmap.
*
* On failure, returns false and ignores the pixmap parameter.
*/
bool accessPixels(SkPixmap* pmap);
/**
* Try to get read-only-access to the pixels behind the device. If successful, this returns
* true and fills-out the pixmap parameter.
*
* On failure, returns false and ignores the pixmap parameter.
*/
bool peekPixels(SkPixmap*);
/**
* Return the device's associated gpu render target, or NULL.
@ -111,7 +116,6 @@ public:
*/
virtual void onAttachToCanvas(SkCanvas*) {
SkASSERT(!fAttachedToCanvas);
this->lockPixels();
#ifdef SK_DEBUG
fAttachedToCanvas = true;
#endif
@ -125,30 +129,28 @@ public:
*/
virtual void onDetachFromCanvas() {
SkASSERT(fAttachedToCanvas);
this->unlockPixels();
#ifdef SK_DEBUG
fAttachedToCanvas = false;
#endif
};
protected:
enum Usage {
kGeneral_Usage,
kSaveLayer_Usage // <! internal use only
enum TileUsage {
kPossible_TileUsage, //!< the created device may be drawn tiled
kNever_TileUsage, //!< the created device will never be drawn tiled
};
struct TextFlags {
uint32_t fFlags; // SkPaint::getFlags()
SkPaint::Hinting fHinting;
uint32_t fFlags; // SkPaint::getFlags()
};
/**
* Device may filter the text flags for drawing text here. If it wants to
* make a change to the specified values, it should write them into the
* textflags parameter (output) and return true. If the paint is fine as
* is, then ignore the textflags parameter and return false.
* Returns the text-related flags, possibly modified based on the state of the
* device (e.g. support for LCD).
*/
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) { return false; }
uint32_t filterTextFlags(const SkPaint&) const;
virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
/**
*
@ -169,14 +171,6 @@ protected:
virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
const SkClipStack&) {};
/** Clears the entire device to the specified color (including alpha).
* Ignores the clip.
*/
virtual void clear(SkColor color) = 0;
SK_ATTR_DEPRECATED("use clear() instead")
void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
/** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations,
and are handling any looping from the paint, and any effects from the
@ -223,7 +217,15 @@ protected:
virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
const SkRect* srcOrNull, const SkRect& dst,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) = 0;
SkCanvas::SrcRectConstraint) = 0;
virtual void drawBitmapNine(const SkDraw&, const SkBitmap&, const SkIRect& center,
const SkRect& dst, const SkPaint&);
virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint&, SkCanvas::SrcRectConstraint);
virtual void drawImageNine(const SkDraw&, const SkImage*, const SkIRect& center,
const SkRect& dst, const SkPaint&);
/**
* Does not handle text decoration.
@ -232,22 +234,33 @@ protected:
virtual void drawText(const SkDraw&, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint) = 0;
virtual void drawPosText(const SkDraw&, const void* text, size_t len,
const SkScalar pos[], SkScalar constY,
int scalarsPerPos, const SkPaint& paint) = 0;
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) = 0;
const SkScalar pos[], int scalarsPerPos,
const SkPoint& offset, const SkPaint& paint) = 0;
virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
const SkPoint verts[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) = 0;
// default implementation unrolls the blob runs.
virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y,
const SkPaint& paint, SkDrawFilter* drawFilter);
// default implementation calls drawVertices
virtual void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
// default implementation calls drawPath
virtual void drawAtlas(const SkDraw&, const SkImage* atlas, const SkRSXform[], const SkRect[],
const SkColor[], int count, SkXfermode::Mode, const SkPaint&);
/** The SkDevice passed will be an SkDevice which was returned by a call to
onCreateDevice on this device with kSaveLayer_Usage.
onCreateDevice on this device with kNeverTile_TileExpectation.
*/
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) = 0;
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath&,
const SkMatrix*, const SkPaint&);
bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
///////////////////////////////////////////////////////////////////////////
@ -258,20 +271,6 @@ protected:
*/
virtual const SkBitmap& onAccessBitmap() = 0;
/** Called when this device is installed into a Canvas. Balanced by a call
to unlockPixels() when the device is removed from a Canvas.
*/
virtual void lockPixels() {}
virtual void unlockPixels() {}
/**
* Returns true if the device allows processing of this imagefilter. If
* false is returned, then the filter is ignored. This may happen for
* some subclasses that do not support pixel manipulations after drawing
* has occurred (e.g. printing). The default implementation returns true.
*/
virtual bool allowImageFilter(const SkImageFilter*) { return true; }
/**
* Override and return true for filters that the device can handle
* intrinsically. Doing so means that SkCanvas will pass-through this
@ -289,17 +288,14 @@ protected:
* it just returns false and leaves result and offset unchanged.
*/
virtual bool filterImage(const SkImageFilter*, const SkBitmap&,
const SkImageFilter::Context& ctx,
SkBitmap* result, SkIPoint* offset) {
const SkImageFilter::Context&,
SkBitmap* /*result*/, SkIPoint* /*offset*/) {
return false;
}
protected:
// default impl returns NULL
virtual SkSurface* newSurface(const SkImageInfo&);
// default impl returns NULL
virtual const void* peekPixels(SkImageInfo*, size_t* rowBytes);
virtual SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) { return NULL; }
virtual bool onPeekPixels(SkPixmap*) { return false; }
/**
* The caller is responsible for "pre-clipping" the dst. The impl can assume that the dst
@ -317,24 +313,11 @@ protected:
*/
virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y);
/**
* Default impl returns NULL.
*/
virtual void* onAccessPixels(SkImageInfo* info, size_t* rowBytes);
virtual bool onAccessPixels(SkPixmap*) { return false; }
/**
* Leaky properties are those which the device should be applying but it isn't.
* These properties will be applied by the draw, when and as it can.
* If the device does handle a property, that property should be set to the identity value
* for that property, effectively making it non-leaky.
*/
SkDeviceProperties fLeakyProperties;
/**
* PRIVATE / EXPERIMENTAL -- do not call
* Construct an acceleration object and attach it to 'picture'
*/
virtual void EXPERIMENTAL_optimize(const SkPicture* picture);
const SkSurfaceProps& surfaceProps() const {
return fSurfaceProps;
}
/**
* PRIVATE / EXPERIMENTAL -- do not call
@ -346,7 +329,42 @@ protected:
* to perform some device-specific warm up tasks and then let SkCanvas
* perform the main rendering loop (by return false from here).
*/
virtual bool EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* picture);
virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*,
const SkPaint*);
struct CreateInfo {
static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry);
// The constructor may change the pixel geometry based on other parameters.
CreateInfo(const SkImageInfo& info,
TileUsage tileUsage,
SkPixelGeometry geo,
bool forImageFilter = false)
: fInfo(info)
, fTileUsage(tileUsage)
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo))
, fForImageFilter(forImageFilter) {}
const SkImageInfo fInfo;
const TileUsage fTileUsage;
const SkPixelGeometry fPixelGeometry;
const bool fForImageFilter;
};
/**
* Create a new device based on CreateInfo. If the paint is not null, then it represents a
* preview of how the new device will be composed with its creator device (this).
*
* The subclass may be handed this device in drawDevice(), so it must always return
* a device that it knows how to draw, and that it knows how to identify if it is not of the
* same subclass (since drawDevice is passed a SkBaseDevice*). If the subclass cannot fulfill
* that contract (e.g. PDF cannot support some settings on the paint) it should return NULL,
* and the caller may then decide to explicitly create a bitmapdevice, knowing that later
* it could not call drawDevice with it (but it could call drawSprite or drawBitmap).
*/
virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) {
return NULL;
}
private:
friend class SkCanvas;
@ -354,8 +372,8 @@ private:
friend class SkDraw;
friend class SkDrawIter;
friend class SkDeviceFilteredPaint;
friend class SkDeviceImageFilterProxy;
friend class SkDeferredDevice; // for newSurface
friend class SkImageFilter::DeviceProxy;
friend class SkNoPixelsBitmapDevice;
friend class SkSurface_Raster;
@ -365,21 +383,20 @@ private:
// TODO: move to SkBitmapDevice
virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
virtual bool forceConservativeRasterClip() const { return false; }
// just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); }
// just called by SkCanvas for saveLayer
SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&);
virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) {
return NULL;
}
/** Causes any deferred drawing to the device to be completed.
*/
virtual void flush() {}
virtual SkImageFilter::Cache* getImageFilterCache() { return NULL; }
SkIPoint fOrigin;
SkMetaData* fMetaData;
SkSurfaceProps fSurfaceProps;
#ifdef SK_DEBUG
bool fAttachedToCanvas;

View File

@ -1,103 +0,0 @@
#ifndef SkDeviceProperties_DEFINED
#define SkDeviceProperties_DEFINED
//TODO: get everyone to stop using SkFontLCDConfig::SetSubpixel* and remove this import.
#include "SkFontLCDConfig.h"
struct SkDeviceProperties {
struct Geometry {
/** The orientation of the pixel specifies the interpretation of the
* layout. If the orientation is horizontal, the layout is interpreted as
* left to right. It the orientation is vertical, the layout is
* interpreted top to bottom (rotated 90deg cw from horizontal).
*/
enum Orientation {
kUnknown_Orientation = 0x0,
kKnown_Orientation = 0x2,
kHorizontal_Orientation = 0x2, //!< this is the default
kVertical_Orientation = 0x3,
kOrientationMask = 0x3,
};
/** The layout of the pixel specifies its subpixel geometry.
*
* kUnknown_Layout means that the subpixel elements are not spatially
* separated in any known or usable fashion.
*/
enum Layout {
kUnknown_Layout = 0x0,
kKnown_Layout = 0x8,
kRGB_Layout = 0x8, //!< this is the default
kBGR_Layout = 0xC,
kLayoutMask = 0xC,
};
Orientation getOrientation() {
return static_cast<Orientation>(fGeometry & kOrientationMask);
}
Layout getLayout() {
return static_cast<Layout>(fGeometry & kLayoutMask);
}
bool isOrientationKnown() {
return SkToBool(fGeometry & kKnown_Orientation);
}
bool isLayoutKnown() {
return SkToBool(fGeometry & kKnown_Layout);
}
private:
//TODO: get everyone to stop using SkFontLCDConfig::SetSubpixel* and replace these calls with constants.
static Orientation fromOldOrientation(SkFontLCDConfig::LCDOrientation orientation) {
switch (orientation) {
case SkFontLCDConfig::kHorizontal_LCDOrientation: return kHorizontal_Orientation;
case SkFontLCDConfig::kVertical_LCDOrientation: return kVertical_Orientation;
default: return kUnknown_Orientation;
}
}
static Layout fromOldLayout(SkFontLCDConfig::LCDOrder order) {
switch (order) {
case SkFontLCDConfig::kRGB_LCDOrder: return kRGB_Layout;
case SkFontLCDConfig::kBGR_LCDOrder: return kBGR_Layout;
default: return kUnknown_Layout;
}
}
public:
static Geometry MakeDefault() {
Orientation orientation = fromOldOrientation(SkFontLCDConfig::GetSubpixelOrientation()); //kHorizontal_Orientation
Layout layout = fromOldLayout(SkFontLCDConfig::GetSubpixelOrder()); //kRGB_Layout
Geometry ret = { SkToU8(orientation | layout) };
return ret;
}
static Geometry Make(Orientation orientation, Layout layout) {
Geometry ret = { SkToU8(orientation | layout) };
return ret;
}
uint8_t fGeometry;
};
static SkDeviceProperties MakeDefault() {
SkDeviceProperties ret = { Geometry::MakeDefault(), SK_GAMMA_EXPONENT };
return ret;
}
static SkDeviceProperties Make(Geometry geometry, SkScalar gamma) {
SkDeviceProperties ret = { geometry, gamma };
return ret;
}
/** Each pixel of an image will have some number of channels.
* Can the layout of those channels be exploited? */
Geometry fGeometry;
/** Represents the color space of the image. This is a woefully inadequate beginning. */
SkScalar fGamma;
};
#endif

View File

@ -12,6 +12,8 @@
#include "SkPicture.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTime.h"
class SkCanvas;
class SkWStream;
@ -30,56 +32,50 @@ class SkWStream;
* c. doc->endPage();
* 3. Close the document with doc->close().
*/
class SkDocument : public SkRefCnt {
class SK_API SkDocument : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkDocument)
/**
* Create a PDF-backed document, writing the results into a SkWStream.
*
* PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
*
* @param SkWStream* A PDF document will be written to this
* stream. The document may write to the stream at
* anytime during its lifetime, until either close() is
* called or the document is deleted.
* @param dpi The DPI (pixels-per-inch) at which features without
* native PDF support will be rasterized (e.g. draw image
* with perspective, draw text with perspective, ...) A
* larger DPI would create a PDF that reflects the
* original intent with better fidelity, but it can make
* for larger PDF files too, which would use more memory
* while rendering, and it would be slower to be processed
* or sent online or to printer.
* @returns NULL if there is an error, otherwise a newly created
* PDF-backed SkDocument.
*/
static SkDocument* CreatePDF(SkWStream*,
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Create a PDF-backed document, writing the results into a file.
* If there is an error trying to create the doc, returns NULL.
* encoder sets the DCTEncoder for images, to encode a bitmap
* as JPEG (DCT).
* rasterDpi - the DPI at which features without native PDF support
* will be rasterized (e.g. draw image with perspective,
* draw text with perspective, ...)
* A larger DPI would create a PDF that reflects the original
* intent with better fidelity, but it can make for larger
* PDF files too, which would use more memory while rendering,
* and it would be slower to be processed or sent online or
* to printer.
*/
static SkDocument* CreatePDF(
const char filename[],
SkPicture::EncodeBitmap encoder = NULL,
SkScalar rasterDpi = SK_ScalarDefaultRasterDPI);
static SkDocument* CreatePDF(const char outputFilePath[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Create a PDF-backed document, writing the results into a stream.
* If there is an error trying to create the doc, returns NULL.
*
* The document may write to the stream at anytime during its lifetime,
* until either close() is called or the document is deleted. Once close()
* has been called, and all of the data has been written to the stream,
* if there is a Done proc provided, it will be called with the stream.
* The proc can delete the stream, or whatever it needs to do.
* encoder sets the DCTEncoder for images, to encode a bitmap
* as JPEG (DCT).
* Done - clean up method intended to allow deletion of the stream.
* Its aborted parameter is true if the cleanup is due to an abort
* call. It is false otherwise.
* rasterDpi - the DPI at which features without native PDF support
* will be rasterized (e.g. draw image with perspective,
* draw text with perspective, ...)
* A larger DPI would create a PDF that reflects the original
* intent with better fidelity, but it can make for larger
* PDF files too, which would use more memory while rendering,
* and it would be slower to be processed or sent online or
* to printer. */
static SkDocument* CreatePDF(
SkWStream*, void (*Done)(SkWStream*,bool aborted) = NULL,
SkPicture::EncodeBitmap encoder = NULL,
SkScalar rasterDpi = SK_ScalarDefaultRasterDPI);
* Create a XPS-backed document, writing the results into the stream.
* Returns NULL if XPS is not supported.
*/
static SkDocument* CreateXPS(SkWStream* stream,
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Create a XPS-backed document, writing the results into a file.
* Returns NULL if XPS is not supported.
*/
static SkDocument* CreateXPS(const char path[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Begin a new page for the document, returning the canvas that will draw
* into the page. The document owns this canvas, and it will go out of
@ -110,8 +106,36 @@ public:
*/
void abort();
/**
* Set the document's metadata, if supported by the document
* type. The creationDate and modifiedDate parameters can be
* nullptr. For example:
*
* SkDocument* make_doc(SkWStream* output) {
* SkTArray<SkDocument::Attribute> info;
* info.emplace_back(SkString("Title"), SkString("..."));
* info.emplace_back(SkString("Author"), SkString("..."));
* info.emplace_back(SkString("Subject"), SkString("..."));
* info.emplace_back(SkString("Keywords"), SkString("..."));
* info.emplace_back(SkString("Creator"), SkString("..."));
* SkTime::DateTime now;
* SkTime::GetDateTime(&now);
* SkDocument* doc = SkDocument::CreatePDF(output);
* doc->setMetadata(info, &now, &now);
* return doc;
* }
*/
struct Attribute {
SkString fKey, fValue;
Attribute(const SkString& k, const SkString& v) : fKey(k), fValue(v) {}
};
virtual void setMetadata(const SkTArray<SkDocument::Attribute>&,
const SkTime::DateTime* /* creationDate */,
const SkTime::DateTime* /* modifiedDate */) {}
protected:
SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted));
// note: subclasses must call close() in their destructor, as the base class
// cannot do this for them.
virtual ~SkDocument();
@ -122,6 +146,9 @@ protected:
virtual bool onClose(SkWStream*) = 0;
virtual void onAbort() = 0;
// Allows subclasses to write to the stream as pages are written.
SkWStream* getStream() { return fStream; }
enum State {
kBetweenPages_State,
kInPage_State,

View File

@ -17,6 +17,7 @@
class SkBitmap;
class SkClipStack;
class SkBaseDevice;
class SkBlitter;
class SkMatrix;
class SkPath;
class SkRegion;
@ -33,7 +34,11 @@ public:
void drawPaint(const SkPaint&) const;
void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[],
const SkPaint&, bool forceUseDevice = false) const;
void drawRect(const SkRect&, const SkPaint&) const;
void drawRect(const SkRect& prePaintRect, const SkPaint&, const SkMatrix* paintMatrix,
const SkRect* postPaintRect) const;
void drawRect(const SkRect& rect, const SkPaint& paint) const {
this->drawRect(rect, paint, NULL, NULL);
}
void drawRRect(const SkRRect&, const SkPaint&) const;
/**
* To save on mallocs, we allow a flag that tells us that srcPath is
@ -49,19 +54,20 @@ public:
this->drawPath(path, paint, prePathMatrix, pathIsMutable, false);
}
void drawPath(const SkPath& path, const SkPaint& paint) const {
this->drawPath(path, paint, NULL, false, false);
void drawPath(const SkPath& path, const SkPaint& paint,
SkBlitter* customBlitter = NULL) const {
this->drawPath(path, paint, NULL, false, false, customBlitter);
}
void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const;
/* If dstOrNull is null, computes a dst by mapping the bitmap's bounds through the matrix. */
void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull,
const SkPaint&) const;
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
void drawText(const char text[], size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) const;
void drawPosText(const char text[], size_t byteLength,
const SkScalar pos[], SkScalar constY,
int scalarsPerPosition, const SkPaint& paint) const;
void drawTextOnPath(const char text[], size_t byteLength,
const SkPath&, const SkMatrix*, const SkPaint&) const;
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkPaint& paint) const;
void drawVertices(SkCanvas::VertexMode mode, int count,
const SkPoint vertices[], const SkPoint textures[],
const SkColor colors[], SkXfermode* xmode,
@ -74,8 +80,9 @@ public:
*
* Only device A8 is supported right now.
*/
void drawPathCoverage(const SkPath& src, const SkPaint& paint) const {
this->drawPath(src, paint, NULL, false, true);
void drawPathCoverage(const SkPath& src, const SkPaint& paint,
SkBlitter* customBlitter = NULL) const {
this->drawPath(src, paint, NULL, false, true, customBlitter);
}
/** Helper function that creates a mask from a path and an optional maskfilter.
@ -110,15 +117,16 @@ public:
void drawText_asPaths(const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkPaint&) const;
void drawPosText_asPaths(const char text[], size_t byteLength,
const SkScalar pos[], SkScalar constY,
int scalarsPerPosition, const SkPaint&) const;
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkPaint&) const;
private:
void drawDevMask(const SkMask& mask, const SkPaint&) const;
void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const;
void drawPath(const SkPath&, const SkPaint&, const SkMatrix* preMatrix,
bool pathIsMutable, bool drawCoverage) const;
bool pathIsMutable, bool drawCoverage,
SkBlitter* customBlitter = NULL) const;
/**
* Return the current clip bounds, in local coordinates, with slop to account
@ -132,14 +140,13 @@ private:
computeConservativeLocalClipBounds(SkRect* bounds) const;
public:
const SkBitmap* fBitmap; // required
SkPixmap fDst;
const SkMatrix* fMatrix; // required
const SkRegion* fClip; // DEPRECATED
const SkRasterClip* fRC; // required
const SkClipStack* fClipStack; // optional
SkBaseDevice* fDevice; // optional
SkDrawProcs* fProcs; // optional
#ifdef SK_DEBUG
void validate() const;

View File

@ -23,8 +23,6 @@ class SkPaint;
*/
class SK_API SkDrawFilter : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkDrawFilter)
enum Type {
kPaint_Type,
kPoint_Type,

View File

@ -30,8 +30,6 @@ class SkString;
*/
class SK_API SkDrawLooper : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkDrawLooper)
/**
* Holds state during a draw. Users call next() until it returns false.
*
@ -87,9 +85,8 @@ public:
* storage rect, where the storage rect is with the union of the src rect
* and the looper's bounding rect.
*/
virtual bool canComputeFastBounds(const SkPaint& paint) const;
virtual void computeFastBounds(const SkPaint& paint,
const SkRect& src, SkRect* dst) const;
bool canComputeFastBounds(const SkPaint& paint) const;
void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;
struct BlurShadowRec {
SkScalar fSigma;
@ -114,7 +111,6 @@ public:
protected:
SkDrawLooper() {}
SkDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {}
private:
typedef SkFlattenable INHERITED;

View File

@ -1,29 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDrawPictureCallback_DEFINED
#define SkDrawPictureCallback_DEFINED
/**
* Subclasses of this can be passed to canvas.drawPicture(). During the drawing
* of the picture, this callback will periodically be invoked. If its
* abortDrawing() returns true, then picture playback will be interrupted.
*
* The resulting drawing is undefined, as there is no guarantee how often the
* callback will be invoked. If the abort happens inside some level of nested
* calls to save(), restore will automatically be called to return the state
* to the same level it was before the drawPicture call was made.
*/
class SK_API SkDrawPictureCallback {
public:
SkDrawPictureCallback() {}
virtual ~SkDrawPictureCallback() {}
virtual bool abortDrawing() = 0;
};
#endif//SkDrawPictureCallback_DEFINED

View File

@ -0,0 +1,77 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDrawable_DEFINED
#define SkDrawable_DEFINED
#include "SkRefCnt.h"
class SkCanvas;
class SkPicture;
struct SkRect;
/**
* Base-class for objects that draw into SkCanvas.
*
* The object has a generation ID, which is guaranteed to be unique across all drawables. To
* allow for clients of the drawable that may want to cache the results, the drawable must
* change its generation ID whenever its internal state changes such that it will draw differently.
*/
class SkDrawable : public SkRefCnt {
public:
SkDrawable();
/**
* Draws into the specified content. The drawing sequence will be balanced upon return
* (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
* and the current matrix and clip settings will not be changed.
*/
void draw(SkCanvas*, const SkMatrix* = NULL);
void draw(SkCanvas*, SkScalar x, SkScalar y);
SkPicture* newPictureSnapshot();
/**
* Return a unique value for this instance. If two calls to this return the same value,
* it is presumed that calling the draw() method will render the same thing as well.
*
* Subclasses that change their state should call notifyDrawingChanged() to ensure that
* a new value will be returned the next time it is called.
*/
uint32_t getGenerationID();
/**
* Return the (conservative) bounds of what the drawable will draw. If the drawable can
* change what it draws (e.g. animation or in response to some external change), then this
* must return a bounds that is always valid for all possible states.
*/
SkRect getBounds();
/**
* Calling this invalidates the previous generation ID, and causes a new one to be computed
* the next time getGenerationID() is called. Typically this is called by the object itself,
* in response to its internal state changing.
*/
void notifyDrawingChanged();
protected:
virtual SkRect onGetBounds() = 0;
virtual void onDraw(SkCanvas*) = 0;
/**
* Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
* may override if they have a more efficient way to return a picture for the current state
* of their drawable. Note: this picture must draw the same as what would be drawn from
* onDraw().
*/
virtual SkPicture* onNewPictureSnapshot();
private:
int32_t fGenerationID;
};
#endif

View File

@ -1,113 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDynamicAnnotations_DEFINED
#define SkDynamicAnnotations_DEFINED
// This file contains macros used to send out-of-band signals to dynamic instrumentation systems,
// namely thread sanitizer. This is a cut-down version of the full dynamic_annotations library with
// only the features used by Skia.
#if SK_DYNAMIC_ANNOTATIONS_ENABLED
extern "C" {
// TSAN provides these hooks.
void AnnotateIgnoreReadsBegin(const char* file, int line);
void AnnotateIgnoreReadsEnd(const char* file, int line);
void AnnotateIgnoreWritesBegin(const char* file, int line);
void AnnotateIgnoreWritesEnd(const char* file, int line);
void AnnotateBenignRaceSized(const char* file, int line,
const volatile void* addr, long size, const char* desc);
} // extern "C"
// SK_ANNOTATE_UNPROTECTED_READ can wrap any variable read to tell TSAN to ignore that it appears to
// be a racy read. This should be used only when we can make an external guarantee that though this
// particular read is racy, it is being used as part of a mechanism which is thread safe. Examples:
// - the first check in double-checked locking;
// - checking if a ref count is equal to 1.
// Note that in both these cases, we must still add terrifyingly subtle memory barriers to provide
// that overall thread safety guarantee. Using this macro to shut TSAN up without providing such an
// external guarantee is pretty much never correct.
template <typename T>
inline T SK_ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
AnnotateIgnoreReadsBegin(__FILE__, __LINE__);
T read = x;
AnnotateIgnoreReadsEnd(__FILE__, __LINE__);
return read;
}
// Like SK_ANNOTATE_UNPROTECTED_READ, but for writes.
template <typename T>
inline void SK_ANNOTATE_UNPROTECTED_WRITE(T* ptr, const volatile T& val) {
AnnotateIgnoreWritesBegin(__FILE__, __LINE__);
*ptr = val;
AnnotateIgnoreWritesEnd(__FILE__, __LINE__);
}
// Ignore racy reads and racy writes to this pointer, indefinitely.
// If at all possible, use the more precise SK_ANNOTATE_UNPROTECTED_READ.
template <typename T>
void SK_ANNOTATE_BENIGN_RACE(T* ptr) {
AnnotateBenignRaceSized(__FILE__, __LINE__, ptr, sizeof(*ptr), "SK_ANNOTATE_BENIGN_RACE");
}
#else // !SK_DYNAMIC_ANNOTATIONS_ENABLED
#define SK_ANNOTATE_UNPROTECTED_READ(x) (x)
#define SK_ANNOTATE_UNPROTECTED_WRITE(ptr, val) *(ptr) = (val)
#define SK_ANNOTATE_BENIGN_RACE(ptr)
#endif
// Can be used to wrap values that are intentionally racy, usually small mutable cached values, e.g.
// - SkMatrix type mask
// - SkPixelRef genIDs
template <typename T>
class SkTRacy {
public:
operator const T() const {
return SK_ANNOTATE_UNPROTECTED_READ(fVal);
}
SkTRacy& operator=(const T& val) {
SK_ANNOTATE_UNPROTECTED_WRITE(&fVal, val);
return *this;
}
private:
T fVal;
};
// This is like SkTRacy, but allows you to return the value by reference.
// TSAN is better at suppressing SkTRacy than SkTRacyReffable, so use SkTRacy when possible.
//
// We use this for SkPathRef bounds, which is an SkRect we pass around by reference publically.
template <typename T>
class SkTRacyReffable {
public:
SkTRacyReffable() { SK_ANNOTATE_BENIGN_RACE(&fVal); }
operator const T&() const {
return fVal;
}
SkTRacyReffable& operator=(const T& val) {
fVal = val;
return *this;
}
const T* get() const { return &fVal; }
T* get() { return &fVal; }
const T* operator->() const { return &fVal; }
T* operator->() { return &fVal; }
private:
T fVal;
};
#endif//SkDynamicAnnotations_DEFINED

View File

@ -0,0 +1,24 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFilterQuality_DEFINED
#define SkFilterQuality_DEFINED
#include "SkTypes.h"
/**
* Controls how much filtering to be done when scaling/transforming complex colors
* e.g. images
*/
enum SkFilterQuality {
kNone_SkFilterQuality, //!< fastest but lowest quality, typically nearest-neighbor
kLow_SkFilterQuality, //!< typically bilerp
kMedium_SkFilterQuality, //!< typically bilerp + mipmaps for down-scaling
kHigh_SkFilterQuality //!< slowest but highest quality, typically bicubic or better
};
#endif

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