Chromium Code Reviews| Index: Source/platform/graphics/paint/DisplayItemPropertyTreeBuilder.cpp |
| diff --git a/Source/platform/graphics/paint/DisplayItemPropertyTreeBuilder.cpp b/Source/platform/graphics/paint/DisplayItemPropertyTreeBuilder.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a55db1033886a5c2ab28614843e32d3b8ab11625 |
| --- /dev/null |
| +++ b/Source/platform/graphics/paint/DisplayItemPropertyTreeBuilder.cpp |
| @@ -0,0 +1,164 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "platform/graphics/paint/DisplayItemPropertyTreeBuilder.h" |
| + |
| +#include "platform/graphics/paint/DisplayItem.h" |
| +#include "platform/graphics/paint/DisplayItemClipTree.h" |
| +#include "platform/graphics/paint/DisplayItemTransformTree.h" |
| +#include "platform/graphics/paint/Transform3DDisplayItem.h" |
| + |
| +namespace blink { |
| + |
| +DisplayItemPropertyTreeBuilder::DisplayItemPropertyTreeBuilder() |
| + : m_transformTree(adoptPtr(new DisplayItemTransformTree)) |
| + , m_clipTree(adoptPtr(new DisplayItemClipTree)) |
| + , m_rangeBeginIndex(0) |
| + , m_currentIndex(0) |
| +{ |
| + m_stateStack.append(State()); |
| +} |
| + |
| +DisplayItemPropertyTreeBuilder::~DisplayItemPropertyTreeBuilder() |
| +{ |
| +} |
| + |
| +PassOwnPtr<DisplayItemTransformTree> DisplayItemPropertyTreeBuilder::releaseTransformTree() |
| +{ |
| + ASSERT(m_stateStack.size() == 1); |
| + ASSERT(currentState().ignoredBeginCount == 0); |
| + finishRange(); |
| + return m_transformTree.release(); |
| +} |
| + |
| +PassOwnPtr<DisplayItemClipTree> DisplayItemPropertyTreeBuilder::releaseClipTree() |
| +{ |
| + ASSERT(m_stateStack.size() == 1); |
| + ASSERT(currentState().ignoredBeginCount == 0); |
| + finishRange(); |
| + return m_clipTree.release(); |
| +} |
| + |
| +Vector<DisplayItemPropertyTreeBuilder::RangeRecord> DisplayItemPropertyTreeBuilder::releaseRangeRecords() |
| +{ |
| + Vector<RangeRecord> output; |
| + output.swap(m_rangeRecords); |
| + return output; |
| +} |
| + |
| +void DisplayItemPropertyTreeBuilder::processDisplayItem(const DisplayItem& displayItem) |
| +{ |
| + if (displayItem.isBegin()) |
| + processBeginItem(displayItem); |
| + else if (displayItem.isEnd()) |
| + processEndItem(displayItem); |
| + m_currentIndex++; |
| +} |
| + |
| +namespace { |
| + |
| +enum TransformKind { NotATransform = 0, Only2DTranslation, RequiresTransformNode }; |
| +enum ClipKind { NotAClip = 0, RequiresClipNode }; |
| + |
| +struct BeginDisplayItemClassification { |
|
pdr.
2015/08/17 22:25:07
This seems overabstracted.
WDYT about just adding
jbroman
2015/08/17 23:57:19
Then the "copying out the matrix" bit will require
pdr.
2015/08/18 04:31:42
I still don't follow but I may be missing somethin
jbroman
2015/08/18 14:18:16
Yes, I do expect that display items may create nod
|
| + TransformKind transformKind = NotATransform; |
| + TransformationMatrix matrix; |
| + ClipKind clipKind = NotAClip; |
| + FloatRect clipRect; |
| +}; |
| + |
| +// Classifies a begin display item based on how it affects the property trees. |
| +static BeginDisplayItemClassification classifyBeginItem(const DisplayItem& beginDisplayItem) |
| +{ |
| + ASSERT(beginDisplayItem.isBegin()); |
| + |
| + BeginDisplayItemClassification result; |
| + DisplayItem::Type type = beginDisplayItem.type(); |
| + if (DisplayItem::isTransform3DType(type)) { |
| + const auto& begin3D = static_cast<const BeginTransform3DDisplayItem&>(beginDisplayItem); |
| + result.matrix = begin3D.transform(); |
| + result.transformKind = result.matrix.isIdentityOr2DTranslation() ? Only2DTranslation : RequiresTransformNode; |
| + } |
| + return result; |
| +} |
| + |
| +} // namespace |
| + |
| +void DisplayItemPropertyTreeBuilder::processBeginItem(const DisplayItem& displayItem) |
| +{ |
| + BeginDisplayItemClassification classification = classifyBeginItem(displayItem); |
| + |
| + if (!classification.transformKind && !classification.clipKind) { |
| + currentState().ignoredBeginCount++; |
| + return; |
| + } |
| + |
| + finishRange(); |
| + State newState(currentState()); |
| + newState.ignoredBeginCount = 0; |
| + |
| + switch (classification.transformKind) { |
| + case NotATransform: |
| + break; |
| + case Only2DTranslation: |
| + // Adjust the offset associated with the current transform node. |
| + newState.offset += classification.matrix.to2DTranslation(); |
| + break; |
| + case RequiresTransformNode: |
| + // Emit a transform node. |
| + newState.transformNode = m_transformTree->createNewNode( |
| + newState.transformNode, classification.matrix); |
| + newState.offset = FloatSize(); |
| + break; |
| + } |
| + |
| + switch (classification.clipKind) { |
| + case NotAClip: |
| + break; |
| + case RequiresClipNode: |
| + // Emit a clip node. |
| + FloatRect adjustedClipRect = classification.clipRect; |
| + adjustedClipRect.move(newState.offset); |
| + newState.clipNode = m_clipTree->createNewNode( |
| + newState.clipNode, newState.transformNode, adjustedClipRect); |
| + break; |
| + } |
| + |
| + m_stateStack.append(newState); |
| +} |
| + |
| +void DisplayItemPropertyTreeBuilder::processEndItem(const DisplayItem& displayItem) |
| +{ |
| + if (currentState().ignoredBeginCount) { |
| + // Ignored this end display item. |
| + currentState().ignoredBeginCount--; |
| + } else { |
| + // We've closed the scope of some property. |
| + finishRange(); |
| + m_stateStack.removeLast(); |
| + ASSERT(!m_stateStack.isEmpty()); |
| + } |
| +} |
| + |
| +void DisplayItemPropertyTreeBuilder::finishRange() |
| +{ |
| + // Don't emit an empty range record. |
| + if (m_rangeBeginIndex < m_currentIndex) { |
| + const auto& current = currentState(); |
| + RangeRecord rangeRecord; |
| + rangeRecord.displayListBeginIndex = m_rangeBeginIndex; |
| + rangeRecord.displayListEndIndex = m_currentIndex; |
| + rangeRecord.transformNodeIndex = current.transformNode; |
| + rangeRecord.offset = current.offset; |
| + rangeRecord.clipNodeIndex = current.clipNode; |
| + m_rangeRecords.append(rangeRecord); |
| + } |
| + |
| + // The current display item is a boundary. |
| + // The earliest the next range could begin is the next one. |
| + m_rangeBeginIndex = m_currentIndex + 1; |
| +} |
| + |
| +} // namespace blink |