Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | |
michael@0 | 2 | /* |
michael@0 | 3 | * Copyright 2012 Google Inc. |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | #include "SkPictureStateTree.h" |
michael@0 | 10 | #include "SkCanvas.h" |
michael@0 | 11 | |
michael@0 | 12 | SkPictureStateTree::SkPictureStateTree() |
michael@0 | 13 | : fAlloc(2048) |
michael@0 | 14 | , fLastRestoredNode(NULL) |
michael@0 | 15 | , fStateStack(sizeof(Draw), 16) { |
michael@0 | 16 | fRootMatrix.reset(); |
michael@0 | 17 | fRoot.fParent = NULL; |
michael@0 | 18 | fRoot.fMatrix = &fRootMatrix; |
michael@0 | 19 | fRoot.fFlags = Node::kSave_Flag; |
michael@0 | 20 | fRoot.fOffset = 0; |
michael@0 | 21 | fRoot.fLevel = 0; |
michael@0 | 22 | fCurrentState.fNode = &fRoot; |
michael@0 | 23 | fCurrentState.fMatrix = &fRootMatrix; |
michael@0 | 24 | *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState; |
michael@0 | 25 | } |
michael@0 | 26 | |
michael@0 | 27 | SkPictureStateTree::~SkPictureStateTree() { |
michael@0 | 28 | } |
michael@0 | 29 | |
michael@0 | 30 | SkPictureStateTree::Draw* SkPictureStateTree::appendDraw(size_t offset) { |
michael@0 | 31 | Draw* draw = static_cast<Draw*>(fAlloc.allocThrow(sizeof(Draw))); |
michael@0 | 32 | *draw = fCurrentState; |
michael@0 | 33 | draw->fOffset = SkToU32(offset); |
michael@0 | 34 | return draw; |
michael@0 | 35 | } |
michael@0 | 36 | |
michael@0 | 37 | void SkPictureStateTree::appendSave() { |
michael@0 | 38 | *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState; |
michael@0 | 39 | fCurrentState.fNode->fFlags |= Node::kSave_Flag; |
michael@0 | 40 | } |
michael@0 | 41 | |
michael@0 | 42 | void SkPictureStateTree::appendSaveLayer(size_t offset) { |
michael@0 | 43 | *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState; |
michael@0 | 44 | this->appendNode(offset); |
michael@0 | 45 | fCurrentState.fNode->fFlags |= Node::kSaveLayer_Flag; |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | void SkPictureStateTree::saveCollapsed() { |
michael@0 | 49 | SkASSERT(NULL != fLastRestoredNode); |
michael@0 | 50 | SkASSERT(SkToBool(fLastRestoredNode->fFlags & \ |
michael@0 | 51 | (Node::kSaveLayer_Flag | Node::kSave_Flag))); |
michael@0 | 52 | SkASSERT(fLastRestoredNode->fParent == fCurrentState.fNode); |
michael@0 | 53 | // The structure of the tree is not modified here. We just turn off |
michael@0 | 54 | // the save or saveLayer flag to prevent the iterator from making state |
michael@0 | 55 | // changing calls on the playback canvas when traversing a save or |
michael@0 | 56 | // saveLayerNode node. |
michael@0 | 57 | fLastRestoredNode->fFlags = 0; |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | void SkPictureStateTree::appendRestore() { |
michael@0 | 61 | fLastRestoredNode = fCurrentState.fNode; |
michael@0 | 62 | fCurrentState = *static_cast<Draw*>(fStateStack.back()); |
michael@0 | 63 | fStateStack.pop_back(); |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | void SkPictureStateTree::appendTransform(const SkMatrix& trans) { |
michael@0 | 67 | SkMatrix* m = static_cast<SkMatrix*>(fAlloc.allocThrow(sizeof(SkMatrix))); |
michael@0 | 68 | *m = trans; |
michael@0 | 69 | fCurrentState.fMatrix = m; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | void SkPictureStateTree::appendClip(size_t offset) { |
michael@0 | 73 | this->appendNode(offset); |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | SkPictureStateTree::Iterator SkPictureStateTree::getIterator(const SkTDArray<void*>& draws, |
michael@0 | 77 | SkCanvas* canvas) { |
michael@0 | 78 | return Iterator(draws, canvas, &fRoot); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | void SkPictureStateTree::appendNode(size_t offset) { |
michael@0 | 82 | Node* n = static_cast<Node*>(fAlloc.allocThrow(sizeof(Node))); |
michael@0 | 83 | n->fOffset = SkToU32(offset); |
michael@0 | 84 | n->fFlags = 0; |
michael@0 | 85 | n->fParent = fCurrentState.fNode; |
michael@0 | 86 | n->fLevel = fCurrentState.fNode->fLevel + 1; |
michael@0 | 87 | n->fMatrix = fCurrentState.fMatrix; |
michael@0 | 88 | fCurrentState.fNode = n; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | SkPictureStateTree::Iterator::Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root) |
michael@0 | 92 | : fDraws(&draws) |
michael@0 | 93 | , fCanvas(canvas) |
michael@0 | 94 | , fCurrentNode(root) |
michael@0 | 95 | , fPlaybackMatrix(canvas->getTotalMatrix()) |
michael@0 | 96 | , fCurrentMatrix(NULL) |
michael@0 | 97 | , fPlaybackIndex(0) |
michael@0 | 98 | , fSave(false) |
michael@0 | 99 | , fValid(true) { |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | uint32_t SkPictureStateTree::Iterator::draw() { |
michael@0 | 103 | SkASSERT(this->isValid()); |
michael@0 | 104 | if (fPlaybackIndex >= fDraws->count()) { |
michael@0 | 105 | // restore back to where we started |
michael@0 | 106 | fCanvas->setMatrix(fPlaybackMatrix); |
michael@0 | 107 | if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); } |
michael@0 | 108 | fCurrentNode = fCurrentNode->fParent; |
michael@0 | 109 | while (NULL != fCurrentNode) { |
michael@0 | 110 | if (fCurrentNode->fFlags & Node::kSave_Flag) { fCanvas->restore(); } |
michael@0 | 111 | if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); } |
michael@0 | 112 | fCurrentNode = fCurrentNode->fParent; |
michael@0 | 113 | } |
michael@0 | 114 | return kDrawComplete; |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]); |
michael@0 | 118 | Node* targetNode = draw->fNode; |
michael@0 | 119 | |
michael@0 | 120 | if (fSave) { |
michael@0 | 121 | fCanvas->save(SkCanvas::kClip_SaveFlag); |
michael@0 | 122 | fSave = false; |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | if (fCurrentNode != targetNode) { |
michael@0 | 126 | // If we're not at the target and we don't have a list of nodes to get there, we need to |
michael@0 | 127 | // figure out the path from our current node, to the target |
michael@0 | 128 | if (fNodes.count() == 0) { |
michael@0 | 129 | // Trace back up to a common ancestor, restoring to get our current state to match that |
michael@0 | 130 | // of the ancestor, and saving a list of nodes whose state we need to apply to get to |
michael@0 | 131 | // the target (we can restore up to the ancestor immediately, but we'll need to return |
michael@0 | 132 | // an offset for each node on the way down to the target, to apply the desired clips and |
michael@0 | 133 | // saveLayers, so it may take several draw() calls before the next draw actually occurs) |
michael@0 | 134 | Node* tmp = fCurrentNode; |
michael@0 | 135 | Node* ancestor = targetNode; |
michael@0 | 136 | while (tmp != ancestor) { |
michael@0 | 137 | uint16_t currentLevel = tmp->fLevel; |
michael@0 | 138 | uint16_t targetLevel = ancestor->fLevel; |
michael@0 | 139 | if (currentLevel >= targetLevel) { |
michael@0 | 140 | if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) { fCanvas->restore(); } |
michael@0 | 141 | if (tmp->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); } |
michael@0 | 142 | tmp = tmp->fParent; |
michael@0 | 143 | } |
michael@0 | 144 | if (currentLevel <= targetLevel) { |
michael@0 | 145 | fNodes.push(ancestor); |
michael@0 | 146 | ancestor = ancestor->fParent; |
michael@0 | 147 | } |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | if (ancestor->fFlags & Node::kSave_Flag) { |
michael@0 | 151 | if (fCurrentNode != ancestor) { fCanvas->restore(); } |
michael@0 | 152 | if (targetNode != ancestor) { fCanvas->save(SkCanvas::kClip_SaveFlag); } |
michael@0 | 153 | } |
michael@0 | 154 | fCurrentNode = ancestor; |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | // If we're not at the target node yet, we'll need to return an offset to make the caller |
michael@0 | 158 | // apply the next clip or saveLayer. |
michael@0 | 159 | if (fCurrentNode != targetNode) { |
michael@0 | 160 | if (fCurrentMatrix != fNodes.top()->fMatrix) { |
michael@0 | 161 | fCurrentMatrix = fNodes.top()->fMatrix; |
michael@0 | 162 | SkMatrix tmp = *fNodes.top()->fMatrix; |
michael@0 | 163 | tmp.postConcat(fPlaybackMatrix); |
michael@0 | 164 | fCanvas->setMatrix(tmp); |
michael@0 | 165 | } |
michael@0 | 166 | uint32_t offset = fNodes.top()->fOffset; |
michael@0 | 167 | fCurrentNode = fNodes.top(); |
michael@0 | 168 | fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::kSave_Flag; |
michael@0 | 169 | fNodes.pop(); |
michael@0 | 170 | return offset; |
michael@0 | 171 | } |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | // If we got this far, the clip/saveLayer state is all set, so we can proceed to set the matrix |
michael@0 | 175 | // for the draw, and return its offset. |
michael@0 | 176 | |
michael@0 | 177 | if (fCurrentMatrix != draw->fMatrix) { |
michael@0 | 178 | SkMatrix tmp = *draw->fMatrix; |
michael@0 | 179 | tmp.postConcat(fPlaybackMatrix); |
michael@0 | 180 | fCanvas->setMatrix(tmp); |
michael@0 | 181 | fCurrentMatrix = draw->fMatrix; |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | ++fPlaybackIndex; |
michael@0 | 185 | return draw->fOffset; |
michael@0 | 186 | } |