* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "components/root_view.h"
#include "common/screen.h"
#include "core/render_manager.h"
#include "draw/draw_utils.h"
#include "gfx_utils/graphic_log.h"
#if defined(ENABLE_WINDOW) && ENABLE_WINDOW
#include "window/window_impl.h"
#endif
#include "securec.h"
namespace OHOS {
namespace {
#if defined(LOCAL_RENDER) && LOCAL_RENDER
const constexpr uint8_t MAX_SPLIT_NUM = 32;
const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH * 2;
#else
const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH;
const constexpr uint8_t MAX_INVALIDATE_SIZE = 24;
#endif
static Rect g_maskStack[COMPONENT_NESTING_DEPTH];
static UIView* g_viewStack[VIEW_STACK_DEPTH];
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
UIView* g_layoutViewStack[VIEW_STACK_DEPTH];
#endif
}
RootView::RootView()
{
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_init(&lock_, nullptr);
#endif
InitDrawContext();
}
RootView* RootView::GetInstance()
{
static RootView instance;
return &instance;
}
RootView::~RootView()
{
DestroyDrawContext();
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_destroy(&lock_);
#endif
}
#if defined(ENABLE_WINDOW) && ENABLE_WINDOW
Window* RootView::GetBoundWindow() const
{
return boundWindow_;
}
#endif
Rect RootView::GetScreenRect()
{
#if defined(ENABLE_WINDOW) && ENABLE_WINDOW
Rect screenRect = GetRect();
#else
Rect screenRect(0, 0, Screen::GetInstance().GetWidth() - 1, Screen::GetInstance().GetHeight() - 1);
#endif
return screenRect;
}
#if defined(LOCAL_RENDER) && LOCAL_RENDER
using namespace Graphic;
static void DivideInvalidateRect(const Rect& originRect, Rect& leftoverRect, Vector<Rect>& splitRects)
{
Rect mask;
if (!mask.Intersect(originRect, leftoverRect)) {
splitRects.PushBack(leftoverRect);
return;
}
* +---+---+---+
* | | A | | originRect :A+B
* | +---+ | leftoverRect :A->0
* | B | mask :A
* +-----------+
*/
if (originRect.IsContains(leftoverRect)) {
return;
}
int16_t reserveCnt = MAX_SPLIT_NUM - splitRects.Size();
if (reserveCnt <= 0) {
splitRects.PushBack(leftoverRect);
return;
}
if (mask.GetWidth() == leftoverRect.GetWidth()) {
* +---+
* | A | originRect :B+C
* +-----------+ leftoverRect :A+B->A
* | | B | | mask :B
* | +---+ |
* | C |
* +-----------+
*/
if (mask.GetBottom() == leftoverRect.GetBottom()) {
leftoverRect.SetBottom(mask.GetTop() - 1);
} else if (mask.GetTop() == leftoverRect.GetTop()) {
leftoverRect.SetTop(mask.GetBottom() + 1);
} else {
splitRects.PushBack(leftoverRect);
splitRects.Back().SetBottom(mask.GetTop() - 1);
leftoverRect.SetTop(mask.GetBottom() + 1);
}
splitRects.PushBack(leftoverRect);
return;
}
if (mask.GetHeight() == leftoverRect.GetHeight()) {
* +---------+ originRect :B+C
* +-------+ | leftoverRect :A+B->A
* | A | B | C | mask :B
* +-------+ |
* +---------+
*/
if (mask.GetLeft() == leftoverRect.GetLeft()) {
leftoverRect.SetLeft(mask.GetRight() + 1);
} else if (mask.GetRight() == leftoverRect.GetRight()) {
leftoverRect.SetRight(mask.GetLeft() - 1);
} else {
splitRects.PushBack(leftoverRect);
splitRects.Back().SetRight(mask.GetLeft() - 1);
leftoverRect.SetLeft(mask.GetRight() + 1);
}
splitRects.PushBack(leftoverRect);
return;
}
Vector<Rect> copyRect(splitRects);
if (mask.GetLeft() != leftoverRect.GetLeft()) {
* |
* +-------+
* | +---+ mask :A
* | B | A | leftoverRect :A+B
* | +---+
* +-------+
* |
*/
if (reserveCnt-- <= 0) {
splitRects.Swap(copyRect);
splitRects.PushBack(leftoverRect);
return;
}
splitRects.PushBack(leftoverRect);
splitRects.Back().SetRight(mask.GetLeft() - 1);
leftoverRect.SetLeft(mask.GetLeft());
}
if (mask.GetTop() != leftoverRect.GetTop()) {
* +-------+
* | B | mask :A
* ---+---+--- leftoverRect :A+B
* | | A | |
* +-+---+-+
*/
if (reserveCnt-- <= 0) {
splitRects.Swap(copyRect);
splitRects.PushBack(leftoverRect);
return;
}
splitRects.PushBack(leftoverRect);
splitRects.Back().SetBottom(mask.GetTop() - 1);
leftoverRect.SetTop(mask.GetTop());
}
if (mask.GetRight() != leftoverRect.GetRight()) {
* |
* +-------+
* +---+ | mask :A
* | A | B | leftoverRect :A+B
* +---+ |
* +-------+
* |
*/
if (reserveCnt-- <= 0) {
splitRects.Swap(copyRect);
splitRects.PushBack(leftoverRect);
return;
}
splitRects.PushBack(leftoverRect);
splitRects.Back().SetLeft(mask.GetRight() + 1);
leftoverRect.SetRight(mask.GetRight());
}
if (mask.GetBottom() != leftoverRect.GetBottom()) {
* +-+---+-+
* | | A | | mask :A
* ---+---+--- leftoverRect :A+B
* | B |
* +-------+
*/
if (reserveCnt-- <= 0) {
splitRects.Swap(copyRect);
splitRects.PushBack(leftoverRect);
return;
}
splitRects.PushBack(leftoverRect);
splitRects.Back().SetTop(mask.GetBottom() + 1);
leftoverRect.SetBottom(mask.GetBottom());
}
return;
}
static void AddRenderedRects(Rect& rect, List<Rect>& renderedRects, ListNode<Rect>* iter)
{
for (; iter != renderedRects.End(); iter = iter->next_) {
Rect& curRect = iter->data_;
if (!curRect.IsIntersect(rect)) {
continue;
}
if (curRect.IsContains(rect)) {
return;
}
if (rect.IsContains(curRect)) {
} else if (((curRect.GetLeft() == rect.GetLeft()) && (curRect.GetRight() == rect.GetRight())) ||
((curRect.GetTop() == rect.GetTop()) && (curRect.GetBottom() == rect.GetBottom()))) {
rect.Join(curRect, rect);
} else {
continue;
}
iter = renderedRects.Remove(iter)->prev_;
break;
}
if (iter == renderedRects.End()) {
if (renderedRects.Size() == 128) {
renderedRects.PopBack();
}
renderedRects.PushFront(rect);
} else {
AddRenderedRects(rect, renderedRects, iter);
}
}
void RootView::RemoveViewFromInvalidMap(UIView* view)
{
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_lock(&lock_);
#endif
int16_t stackCount = 0;
do {
while (view != nullptr) {
auto entry = invalidateMap_.find(view);
if (entry != invalidateMap_.end()) {
invalidateMap_.erase(entry);
}
if (view->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
g_viewStack[stackCount++] = view;
view = static_cast<UIViewGroup*>(view)->GetChildrenRenderHead();
continue;
}
view = view->GetNextRenderSibling();
}
if (--stackCount >= 0) {
view = g_viewStack[stackCount]->GetNextRenderSibling();
}
} while (stackCount >= 0);
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_unlock(&lock_);
#endif
}
void RootView::OptimizeInvalidView(UIView* curview, UIView* background, List<Rect>& renderedRects)
{
if (curview == nullptr) {
return;
}
auto mapEntry = invalidateMap_.find(curview);
if (mapEntry == invalidateMap_.end()) {
return;
}
Rect& invalidRect = mapEntry->second.Front();
if (((curview->GetStyleConst().bgOpa_ != OPA_OPAQUE) || (curview->GetOpaScale() != OPA_OPAQUE) ||
(!curview->IsTransInvalid())) &&
(curview != this)) {
AddInvalidateRect(invalidRect, background);
invalidateMap_.erase(mapEntry);
return;
}
* For performance reason, split numbers are strictly restrained.
*/
Vector<Rect> splitInvalidRects(MAX_SPLIT_NUM << 1);
Rect invalidRectCopy(invalidRect);
for (auto iter = renderedRects.Begin(); iter != renderedRects.End(); iter = iter->next_) {
for (int8_t i = 0; i < mapEntry->second.Size(); i++) {
DivideInvalidateRect(iter->data_, mapEntry->second[i], splitInvalidRects);
}
mapEntry->second.Swap(splitInvalidRects);
splitInvalidRects.Clear();
}
Rect preDrawRect(invalidRectCopy);
if (!curview->OnPreDraw(preDrawRect)) {
AddInvalidateRect(invalidRectCopy, background);
}
AddRenderedRects(preDrawRect, renderedRects, renderedRects.Begin());
}
void RootView::OptimizeInvalidMap()
{
UIView* curview = this;
int16_t stackCount = 0;
int16_t opaStackCount = 0;
UIView* background[VIEW_STACK_DEPTH];
bool flags[VIEW_STACK_DEPTH];
List<Rect> renderedRects;
do {
if (curview != nullptr) {
if (stackCount >= VIEW_STACK_DEPTH) {
return;
}
g_viewStack[stackCount] = curview;
flags[stackCount++] = false;
curview = curview->GetNextRenderSibling();
continue;
}
curview = g_viewStack[--stackCount];
Rect rect;
if (!curview->IsVisible() || !rect.Intersect(curview->GetRect(), GetScreenRect())) {
curview = nullptr;
continue;
}
if (!flags[stackCount]) {
if (curview->IsViewGroup()) {
if (((curview->GetStyleConst().bgOpa_ == OPA_OPAQUE) && (curview->GetOpaScale() == OPA_OPAQUE) &&
curview->IsTransInvalid()) ||
(curview == this)) {
background[opaStackCount] = curview;
} else {
background[opaStackCount] = background[opaStackCount - 1];
}
++opaStackCount;
if (opaStackCount >= VIEW_STACK_DEPTH) {
return;
}
flags[stackCount++] = true;
curview = static_cast<UIViewGroup*>(curview)->GetChildrenRenderHead();
continue;
}
} else {
opaStackCount--;
}
OptimizeInvalidView(curview, background[opaStackCount - 1], renderedRects);
curview = nullptr;
} while (stackCount > 0);
renderedRects.Clear();
}
void RootView::DrawInvalidMap(const Rect& buffRect)
{
OptimizeInvalidMap();
Rect rect;
for (auto& viewEntry : invalidateMap_) {
Vector<Rect>& viewRenderRect = viewEntry.second;
for (uint16_t i = 0; i < viewRenderRect.Size(); i++) {
rect.Intersect(viewRenderRect[i], buffRect);
DrawTop(viewEntry.first, rect);
}
}
}
#else
void RootView::OptimizeAddRect(Rect& rect)
{
Rect joinRect;
for (ListNode<Rect>* iter = invalidateRects_.Begin(); iter != invalidateRects_.End(); iter = iter->next_) {
if (iter->data_.IsContains(rect)) {
return;
}
if (iter->data_.IsIntersect(rect)) {
joinRect.Join(iter->data_, rect);
if (joinRect.GetSize() < iter->data_.GetSize() + rect.GetSize()) {
iter->data_ = joinRect;
return;
}
}
}
if (invalidateRects_.Size() < MAX_INVALIDATE_SIZE) {
invalidateRects_.PushBack(rect);
} else {
invalidateRects_.Clear();
invalidateRects_.PushBack(GetScreenRect());
}
}
void RootView::OptimizeInvalidateRects()
{
Rect joinRect;
for (ListNode<Rect>* iter1 = invalidateRects_.Begin(); iter1 != invalidateRects_.End(); iter1 = iter1->next_) {
for (ListNode<Rect>* iter2 = invalidateRects_.Begin(); iter2 != invalidateRects_.End(); iter2 = iter2->next_) {
if (iter1 == iter2) {
continue;
}
if (iter2->data_.IsIntersect(iter1->data_)) {
joinRect.Join(iter1->data_, iter2->data_);
if (joinRect.GetSize() < (iter1->data_.GetSize() + iter2->data_.GetSize())) {
iter2->data_ = joinRect;
iter1 = invalidateRects_.Remove(iter1)->prev_;
break;
}
}
}
}
}
#endif
void RootView::AddInvalidateRect(Rect& rect, UIView* view)
{
Rect commonRect;
if (commonRect.Intersect(rect, GetScreenRect())) {
#if defined(LOCAL_RENDER) && LOCAL_RENDER
Vector<Rect>& invalidRects = invalidateMap_[view];
if (invalidRects.IsEmpty()) {
invalidRects.PushBack(commonRect);
} else {
invalidRects[0].Join(invalidRects[0], commonRect);
}
#else
OptimizeAddRect(commonRect);
#endif
}
}
void RootView::AddInvalidateRectWithLock(Rect& rect, UIView* view)
{
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_lock(&lock_);
#endif
AddInvalidateRect(rect, view);
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_unlock(&lock_);
#endif
}
void RootView::Measure()
{
#if defined(LOCAL_RENDER) && LOCAL_RENDER
if (!invalidateMap_.empty()) {
MeasureView(GetChildrenRenderHead());
}
#else
if (invalidateRects_.Size() > 0) {
MeasureView(GetChildrenRenderHead());
}
#endif
}
#if defined(CONFIG_DYNAMIC_LAYOUT) && (CONFIG_DYNAMIC_LAYOUT == 1)
void RootView::MeasureView(UIView* view)
{
int16_t stackCount = 0;
int16_t layoutCount = 0;
UIView* curView = view;
while (stackCount >= 0) {
while (curView != nullptr) {
if (!curView->IsVisible()) {
curView = curView->GetNextRenderSibling();
continue;
}
if (curView->GetViewType() == UI_FLEXLAYOUT) {
g_layoutViewStack[layoutCount++] = curView;
}
curView->ReMeasure();
if (curView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
g_viewStack[stackCount++] = curView;
curView = static_cast<UIViewGroup*>(curView)->GetChildrenRenderHead();
continue;
}
curView = curView->GetNextRenderSibling();
}
if (--stackCount >= 0) {
curView = (g_viewStack[stackCount])->GetNextRenderSibling();
}
}
while (layoutCount > 0) {
g_layoutViewStack[--layoutCount]->LayoutChildren(true);
}
}
#else
void RootView::MeasureView(UIView* view)
{
int16_t stackCount = 0;
UIView* curView = view;
while (stackCount >= 0) {
while (curView != nullptr) {
if (!curView->IsVisible()) {
curView = curView->GetNextRenderSibling();
continue;
}
curView->ReMeasure();
if (curView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
g_viewStack[stackCount++] = curView;
curView = static_cast<UIViewGroup*>(curView)->GetChildrenRenderHead();
continue;
}
curView = curView->GetNextRenderSibling();
}
if (--stackCount >= 0) {
curView = (g_viewStack[stackCount])->GetNextRenderSibling();
}
}
}
#endif
void RootView::Render()
{
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_lock(&lock_);
#endif
#if defined(LOCAL_RENDER) && (!LOCAL_RENDER)
OptimizeInvalidateRects();
#endif
Rect flushRect(GetScreenRect());
#if defined(LOCAL_RENDER) && LOCAL_RENDER
if (!invalidateMap_.empty()) {
RenderManager::RenderRect(flushRect, this);
invalidateMap_.clear();
#else
if (invalidateRects_.Size() > 0) {
independent between each other, so buffers need to be FULLY_RENDER. */
#if defined(FULLY_RENDER) && (FULLY_RENDER != 1)
flushRect = invalidateRects_.Begin()->data_;
for (ListNode<Rect>* iter = invalidateRects_.Begin(); iter != invalidateRects_.End(); iter = iter->next_) {
RenderManager::RenderRect(iter->data_, this);
flushRect.Join(flushRect, iter->data_);
}
#else
RenderManager::RenderRect(flushRect, this);
#endif
invalidateRects_.Clear();
#endif
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_unlock(&lock_);
#endif
#if defined(ENABLE_WINDOW) && ENABLE_WINDOW
if (boundWindow_) {
boundWindow_->Flush();
boundWindow_->Update();
}
#endif
BaseGfxEngine::GetInstance()->Flush(flushRect);
} else {
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
pthread_mutex_unlock(&lock_);
#endif
}
}
void RootView::BlitMapBuffer(Rect& curViewRect, TransformMap& transMap, const Rect& invalidatedArea)
{
Rect invalidRect = curViewRect;
transMap.SetTransMapRect(curViewRect);
invalidRect.Join(invalidRect, transMap.GetBoxRect());
if (invalidRect.Intersect(invalidRect, invalidatedArea)) {
uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode);
ImageInfo imageInfo;
imageInfo.header.colorMode = dc_.mapBufferInfo->mode;
imageInfo.dataSize = dc_.mapBufferInfo->width * dc_.mapBufferInfo->height * (pxSize >> 3);
imageInfo.header.width = dc_.mapBufferInfo->width;
imageInfo.header.height = dc_.mapBufferInfo->height;
imageInfo.header.reserved = 0;
imageInfo.data = reinterpret_cast<uint8_t*>(dc_.mapBufferInfo->virAddr);
TransformDataInfo imageTranDataInfo = {imageInfo.header, imageInfo.data, pxSize, LEVEL0, BILINEAR};
BaseGfxEngine::GetInstance()->DrawTransform(*dc_.bufferInfo, invalidRect, {0, 0}, Color::Black(), OPA_OPAQUE,
transMap, imageTranDataInfo);
}
}
void RootView::ClearMapBuffer()
{
uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode);
uint32_t dataSize = dc_.mapBufferInfo->width * dc_.mapBufferInfo->height * (pxSize >> 3);
if (memset_s(dc_.mapBufferInfo->virAddr, dataSize, 0, dataSize) != EOK) {
GRAPHIC_LOGE("animator buffer memset failed.");
}
}
void RootView::UpdateMapBufferInfo(Rect& invalidatedArea)
{
int16_t width = invalidatedArea.GetWidth();
int16_t height = invalidatedArea.GetHeight();
invalidatedArea.SetWidth(height);
invalidatedArea.SetHeight(width);
dc_.mapBufferInfo->width = height;
dc_.mapBufferInfo->height = width;
dc_.mapBufferInfo->stride =
dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >> 3);
}
void RootView::RestoreMapBufferInfo()
{
dc_.mapBufferInfo->width = dc_.bufferInfo->width;
dc_.mapBufferInfo->height = dc_.bufferInfo->height;
dc_.mapBufferInfo->stride =
dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >> 3);
}
bool RootView::CheckNeedRootViewTransView(UIView *curView) {
if ((curView->GetViewType() == UI_IMAGE_VIEW) && (curView->GetStyle(STYLE_BORDER_WIDTH) == 0)) {
return false;
}
if (curView->GetViewType() == UI_TEXTURE_MAPPER) {
return false;
}
if (curView->IsTransInvalid()) {
return false;
}
return true;
}
void RootView::DrawTop(UIView* view, const Rect& rect)
{
if (view == nullptr) {
return;
}
int16_t stackCount = 0;
UIView* par = view->GetParent();
if (par == nullptr) {
par = view;
}
UIView* curView = view;
UIView* transViewGroup = nullptr;
Rect curViewRect;
Rect mask = rect;
Rect origRect;
Rect relativeRect;
bool enableAnimator = false;
TransformMap curTransMap;
bool updateMapBufferInfo = false;
#if defined(ENABLE_WINDOW) && ENABLE_WINDOW
WindowImpl* boundWin = static_cast<WindowImpl*>(GetBoundWindow());
BufferInfo* gfxDstBuffer = boundWin->GetBufferInfo();
UpdateBufferInfo(gfxDstBuffer);
#endif
while (par != nullptr) {
if (curView != nullptr) {
if (curView->IsVisible()) {
if (curViewRect.Intersect(curView->GetMaskedRect(), mask) || enableAnimator) {
if (CheckNeedRootViewTransView(curView) && !enableAnimator) {
origRect = curView->GetOrigRect();
relativeRect = curView->GetRelativeRect();
curView->GetTransformMap().SetInvalid(true);
curView->SetPosition(
relativeRect.GetX() - origRect.GetX() - curView->GetStyle(STYLE_MARGIN_LEFT),
relativeRect.GetY() - origRect.GetY() - curView->GetStyle(STYLE_MARGIN_TOP));
ClearMapBuffer();
curTransMap = curView->GetTransformMap();
enableAnimator = true;
}
if (enableAnimator) {
Rect invalidatedArea;
invalidatedArea.SetWidth(dc_.mapBufferInfo->width);
invalidatedArea.SetHeight(dc_.mapBufferInfo->height);
if (invalidatedArea.GetWidth() < curView->GetWidth()) {
UpdateMapBufferInfo(invalidatedArea);
updateMapBufferInfo = true;
}
curView->OnDraw(*dc_.mapBufferInfo, invalidatedArea);
curViewRect = invalidatedArea;
} else {
curView->OnDraw(*dc_.bufferInfo, curViewRect);
}
if ((curView->IsViewGroup()) && (stackCount < COMPONENT_NESTING_DEPTH)) {
if (enableAnimator && (transViewGroup == nullptr)) {
transViewGroup = curView;
}
par = curView;
g_viewStack[stackCount] = curView;
g_maskStack[stackCount] = mask;
stackCount++;
curView = static_cast<UIViewGroup*>(curView)->GetChildrenRenderHead();
mask = par->GetContentRect();
mask.Intersect(mask, curViewRect);
continue;
}
if (enableAnimator) {
curView->OnPostDraw(*dc_.mapBufferInfo, curViewRect);
} else {
curView->OnPostDraw(*dc_.bufferInfo, curViewRect);
}
if (enableAnimator && (transViewGroup == nullptr)) {
BlitMapBuffer(origRect, curTransMap, mask);
if (updateMapBufferInfo) {
RestoreMapBufferInfo();
updateMapBufferInfo = false;
}
curView->GetTransformMap().SetInvalid(false);
enableAnimator = false;
curView->SetPosition(relativeRect.GetX() - curView->GetStyle(STYLE_MARGIN_LEFT),
relativeRect.GetY() - curView->GetStyle(STYLE_MARGIN_TOP));
}
}
}
curView = curView->GetNextRenderSibling();
continue;
}
if (--stackCount >= 0) {
curViewRect = par->GetMaskedRect();
mask = g_maskStack[stackCount];
if (enableAnimator) {
par->OnPostDraw(*dc_.mapBufferInfo, curViewRect);
} else if (curViewRect.Intersect(curViewRect, mask)) {
par->OnPostDraw(*dc_.bufferInfo, curViewRect);
}
if (enableAnimator && transViewGroup == g_viewStack[stackCount]) {
BlitMapBuffer(origRect, curTransMap, mask);
if (updateMapBufferInfo) {
RestoreMapBufferInfo();
updateMapBufferInfo = false;
}
transViewGroup->GetTransformMap().SetInvalid(false);
enableAnimator = false;
transViewGroup->SetPosition(relativeRect.GetX() - transViewGroup->GetStyle(STYLE_MARGIN_LEFT),
relativeRect.GetY() - transViewGroup->GetStyle(STYLE_MARGIN_TOP));
transViewGroup = nullptr;
}
curView = g_viewStack[stackCount]->GetNextRenderSibling();
par = par->GetParent();
continue;
}
stackCount = 0;
curView = par->GetNextRenderSibling();
if (enableAnimator) {
par->OnPostDraw(*dc_.mapBufferInfo, rect);
} else {
par->OnPostDraw(*dc_.bufferInfo, rect);
}
par = par->GetParent();
}
}
UIView* RootView::GetTopUIView(const Rect& rect)
{
int16_t stackCount = 0;
UIView* currentView = this;
UIView* topView = currentView;
Rect copyRect(rect);
while (stackCount >= 0) {
while (currentView != nullptr) {
if (currentView->GetOrigRect().IsContains(rect) && currentView->IsVisible()) {
if (currentView->GetStyle(STYLE_BACKGROUND_OPA) == OPA_OPAQUE && currentView->OnPreDraw(copyRect) &&
currentView->GetOpaScale() == OPA_OPAQUE) {
topView = currentView;
}
if (currentView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
g_viewStack[stackCount++] = currentView;
currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenRenderHead();
continue;
}
}
currentView = currentView->GetNextRenderSibling();
}
if (--stackCount >= 0) {
currentView = (g_viewStack[stackCount])->GetNextRenderSibling();
}
}
UIView* parentView = topView;
while (parentView->GetParent() != nullptr) {
UIView* tempView = parentView;
parentView = parentView->GetParent();
if (!tempView->IsTransInvalid()) {
topView = parentView;
}
}
return topView;
}
bool RootView::FindSubView(const UIView& parentView, const UIView* subView)
{
const UIView* root = &parentView;
if (root == subView) {
return true;
} else if (!root->IsViewGroup() || (subView == nullptr)) {
return false;
}
UIView* currentView = static_cast<const UIViewGroup*>(root)->GetChildrenRenderHead();
const UIView* parent = root;
int8_t deep = 1;
while (deep > 0) {
if (parent == nullptr) {
return false;
}
if (currentView == subView) {
return true;
}
if (currentView == nullptr) {
currentView = parent->GetNextRenderSibling();
parent = parent->GetParent();
deep--;
} else if (currentView->IsViewGroup()) {
parent = currentView;
currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenRenderHead();
deep++;
} else {
currentView = currentView->GetNextRenderSibling();
}
}
return false;
}
void RootView::InitMapBufferInfo(BufferInfo* bufferInfo)
{
dc_.mapBufferInfo = new BufferInfo();
if (dc_.mapBufferInfo == nullptr) {
return;
}
if (memcpy_s(dc_.mapBufferInfo, sizeof(BufferInfo), bufferInfo, sizeof(BufferInfo)) != EOK) {
delete dc_.mapBufferInfo;
dc_.mapBufferInfo = nullptr;
return;
}
dc_.mapBufferInfo->mode = ARGB8888;
dc_.mapBufferInfo->stride = dc_.mapBufferInfo->width * (DrawUtils::GetPxSizeByColorMode(dc_.mapBufferInfo->mode) >>
3);
BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
baseGfxEngine->AdjustLineStride(*dc_.mapBufferInfo);
uint32_t bufferSize = dc_.mapBufferInfo->stride * dc_.mapBufferInfo->height;
dc_.mapBufferInfo->virAddr = dc_.mapBufferInfo->phyAddr =
baseGfxEngine->AllocBuffer(bufferSize, BUFFER_MAP_SURFACE);
}
void RootView::DestroyMapBufferInfo()
{
if (dc_.mapBufferInfo != nullptr) {
BaseGfxEngine::GetInstance()->FreeBuffer(static_cast<uint8_t*>(dc_.mapBufferInfo->virAddr), BUFFER_MAP_SURFACE);
dc_.mapBufferInfo->virAddr = dc_.mapBufferInfo->phyAddr = nullptr;
delete dc_.mapBufferInfo;
dc_.mapBufferInfo = nullptr;
}
}
void RootView::InitDrawContext()
{
dc_.bufferInfo = BaseGfxEngine::GetInstance()->GetFBBufferInfo();
if (dc_.bufferInfo != nullptr) {
InitMapBufferInfo(dc_.bufferInfo);
}
bakDc_.bufferInfo = nullptr;
bakDc_.mapBufferInfo = nullptr;
}
void RootView::DestroyDrawContext()
{
DestroyMapBufferInfo();
}
void RootView::UpdateBufferInfo(BufferInfo* fbBufferInfo)
{
if (dc_.bufferInfo == nullptr) {
dc_.bufferInfo = fbBufferInfo;
InitMapBufferInfo(fbBufferInfo);
} else {
if (dc_.bufferInfo->width != fbBufferInfo->width || dc_.bufferInfo->height != fbBufferInfo->height ||
dc_.bufferInfo->mode != fbBufferInfo->mode) {
DestroyMapBufferInfo();
InitMapBufferInfo(fbBufferInfo);
}
dc_.bufferInfo = fbBufferInfo;
}
}
void RootView::SaveDrawContext()
{
bakDc_.bufferInfo = dc_.bufferInfo;
dc_.bufferInfo = nullptr;
bakDc_.mapBufferInfo = dc_.mapBufferInfo;
dc_.mapBufferInfo = nullptr;
}
void RootView::RestoreDrawContext()
{
DestroyDrawContext();
dc_.bufferInfo = bakDc_.bufferInfo;
bakDc_.bufferInfo = nullptr;
dc_.mapBufferInfo = bakDc_.mapBufferInfo;
bakDc_.mapBufferInfo = nullptr;
}
}