📄 graphicslayer.cpp
字号:
/* * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#if USE(ACCELERATED_COMPOSITING)#include "GraphicsLayer.h"#include "FloatPoint.h"#include "RotateTransformOperation.h"#include "TextStream.h"namespace WebCore {void GraphicsLayer::FloatValue::set(float key, float value, const TimingFunction* timingFunction){ m_key = key; m_value = value; if (timingFunction != m_timingFunction) { if (timingFunction) m_timingFunction.set(new TimingFunction(*timingFunction)); else m_timingFunction.clear(); }}void GraphicsLayer::TransformValue::set(float key, const TransformOperations* value, const TimingFunction* timingFunction){ m_key = key; if (value != m_value) { if (value) m_value.set(new TransformOperations(*value)); else m_value.clear(); } if (timingFunction != m_timingFunction) { if (timingFunction) m_timingFunction.set(new TimingFunction(*timingFunction)); else m_timingFunction.clear(); }}void GraphicsLayer::FloatValueList::insert(float key, float value, const TimingFunction* timingFunction){ for (size_t i = 0; i < m_values.size(); ++i) { FloatValue& curFloatValue = m_values[i]; if (curFloatValue.key() == key) { curFloatValue.set(key, value, timingFunction); return; } if (curFloatValue.key() > key) { // insert before m_values.insert(i, FloatValue(key, value, timingFunction)); return; } } // append m_values.append(FloatValue(key, value, timingFunction));}void GraphicsLayer::TransformValueList::insert(float key, const TransformOperations* value, const TimingFunction* timingFunction){ for (size_t i = 0; i < m_values.size(); ++i) { TransformValue& curTransValue = m_values[i]; if (curTransValue.key() == key) { curTransValue.set(key, value, timingFunction); return; } if (curTransValue.key() > key) { // insert before m_values.insert(i, TransformValue(key, value, timingFunction)); return; } } // append m_values.append(TransformValue(key, value, timingFunction));}// An "invalid" list is one whose functions don't match, and therefore has to be animated as a Matrix// The hasBigRotation flag will always return false if isValid is false. Otherwise hasBigRotation is // true if the rotation between any two keyframes is >= 180 degrees.void GraphicsLayer::TransformValueList::makeFunctionList(FunctionList& list, bool& isValid, bool& hasBigRotation) const{ list.clear(); isValid = false; hasBigRotation = false; if (m_values.size() < 2) return; // empty transforms match anything, so find the first non-empty entry as the reference size_t firstIndex = 0; for ( ; firstIndex < m_values.size(); ++firstIndex) { if (m_values[firstIndex].value()->operations().size() > 0) break; } if (firstIndex >= m_values.size()) return; const TransformOperations* firstVal = m_values[firstIndex].value(); // see if the keyframes are valid for (size_t i = firstIndex + 1; i < m_values.size(); ++i) { const TransformOperations* val = m_values[i].value(); // a null transform matches anything if (val->operations().isEmpty()) continue; if (firstVal->operations().size() != val->operations().size()) return; for (size_t j = 0; j < firstVal->operations().size(); ++j) { if (!firstVal->operations().at(j)->isSameType(*val->operations().at(j))) return; } } // keyframes are valid, fill in the list isValid = true; double lastRotAngle = 0.0; double maxRotAngle = -1.0; list.resize(firstVal->operations().size()); for (size_t j = 0; j < firstVal->operations().size(); ++j) { TransformOperation::OperationType type = firstVal->operations().at(j)->getOperationType(); list[j] = type; // if this is a rotation entry, we need to see if any angle differences are >= 180 deg if (type == TransformOperation::ROTATE_X || type == TransformOperation::ROTATE_Y || type == TransformOperation::ROTATE_Z || type == TransformOperation::ROTATE_3D) { lastRotAngle = static_cast<RotateTransformOperation*>(firstVal->operations().at(j).get())->angle(); if (maxRotAngle < 0) maxRotAngle = fabs(lastRotAngle); for (size_t i = firstIndex + 1; i < m_values.size(); ++i) { const TransformOperations* val = m_values[i].value(); double rotAngle = val->operations().isEmpty() ? 0 : (static_cast<RotateTransformOperation*>(val->operations().at(j).get())->angle()); double diffAngle = fabs(rotAngle - lastRotAngle); if (diffAngle > maxRotAngle) maxRotAngle = diffAngle; lastRotAngle = rotAngle; } } } hasBigRotation = maxRotAngle >= 180.0;}GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) : m_client(client) , m_anchorPoint(0.5f, 0.5f, 0) , m_opacity(1)#ifndef NDEBUG , m_zPosition(0)#endif , m_backgroundColorSet(false) , m_contentsOpaque(false) , m_preserves3D(false) , m_backfaceVisibility(true) , m_usingTiledLayer(false) , m_masksToBounds(false) , m_drawsContent(false) , m_paintingPhase(GraphicsLayerPaintAllMask) , m_parent(0)#ifndef NDEBUG , m_repaintCount(0)#endif{}GraphicsLayer::~GraphicsLayer(){ removeAllAnimations(); removeAllChildren(); removeFromParent();}void GraphicsLayer::addChild(GraphicsLayer* childLayer){ ASSERT(childLayer != this); if (childLayer->parent()) childLayer->removeFromParent(); childLayer->setParent(this); m_children.append(childLayer);}void GraphicsLayer::addChildAtIndex(GraphicsLayer* childLayer, int index){ ASSERT(childLayer != this); if (childLayer->parent()) childLayer->removeFromParent(); childLayer->setParent(this); m_children.insert(index, childLayer);}void GraphicsLayer::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling){ ASSERT(childLayer != this); childLayer->removeFromParent(); bool found = false; for (unsigned i = 0; i < m_children.size(); i++) { if (sibling == m_children[i]) { m_children.insert(i, childLayer); found = true; break; } } childLayer->setParent(this); if (!found) m_children.append(childLayer);}void GraphicsLayer::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling){ childLayer->removeFromParent(); ASSERT(childLayer != this); bool found = false; for (unsigned i = 0; i < m_children.size(); i++) { if (sibling == m_children[i]) { m_children.insert(i+1, childLayer); found = true; break; } } childLayer->setParent(this); if (!found) m_children.append(childLayer);}bool GraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -