* Copyright (c) 2025 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 "session_utils.h"
#include "window_manager_hilog.h"
namespace OHOS::Rosen {
namespace SessionUtils {
bool IsAspectRatioValid(float aspectRatio, const WindowLimits& limits, const WindowDecoration& decoration)
{
if (MathHelper::NearZero(aspectRatio)) {
return true;
}
WindowLimits contentLimits = limits;
contentLimits.Clip(decoration.Horizontal(), decoration.Vertical());
if (!contentLimits.IsValid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid contentLimits: %{public}s", contentLimits.ToString().c_str());
return false;
}
float minRatio = contentLimits.maxHeight_ > 0 ?
static_cast<float>(contentLimits.minWidth_) / static_cast<float>(contentLimits.maxHeight_) : 0.0f;
float maxRatio = contentLimits.minHeight_ > 0 ?
static_cast<float>(contentLimits.maxWidth_) / static_cast<float>(contentLimits.minHeight_) : FLT_MAX;
if (MathHelper::LessNotEqual(aspectRatio, minRatio) || MathHelper::GreatNotEqual(aspectRatio, maxRatio)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid aspectRatio: %{public}f, valid range: [%{public}f, %{public}f]",
aspectRatio, minRatio, maxRatio);
return false;
}
return true;
}
WindowLimits AdjustLimitsByAspectRatio(const WindowLimits& limits,
const WindowDecoration& decoration,
float aspectRatio)
{
if (MathHelper::NearZero(aspectRatio)) {
return limits;
}
const uint32_t decorW = decoration.Horizontal();
const uint32_t decorH = decoration.Vertical();
WindowLimits adjustedLimits = limits;
adjustedLimits.Clip(decorW, decorH);
if (!adjustedLimits.IsValid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid adjustedLimits: %{public}s", adjustedLimits.ToString().c_str());
return limits;
}
const uint32_t minWByH = static_cast<uint32_t>(std::ceil(adjustedLimits.minHeight_ * aspectRatio));
const uint32_t minHByW = static_cast<uint32_t>(std::ceil(adjustedLimits.minWidth_ / aspectRatio));
const uint32_t maxHByW = static_cast<uint32_t>(std::floor(adjustedLimits.maxWidth_ / aspectRatio));
const uint32_t maxWByH = static_cast<uint32_t>(std::floor(adjustedLimits.maxHeight_ * aspectRatio));
if (adjustedLimits.minWidth_ < minWByH) {
adjustedLimits.minWidth_ = minWByH;
} else {
adjustedLimits.minHeight_ = minHByW;
}
if (adjustedLimits.maxWidth_ > maxWByH) {
adjustedLimits.maxWidth_ = maxWByH;
} else {
adjustedLimits.maxHeight_ = maxHByW;
}
adjustedLimits.Expand(decorW, decorH);
return adjustedLimits.IsValid() ? adjustedLimits : limits;
}
WSRect AdjustRectByAspectRatio(const WSRect& rect,
const WindowLimits& limits,
const WindowDecoration& decoration,
float aspectRatio,
int tolerancePx)
{
if (MathHelper::NearZero(aspectRatio)) {
return rect;
}
const uint32_t decorW = decoration.Horizontal();
const uint32_t decorH = decoration.Vertical();
WindowLimits adjustedLimits = limits;
adjustedLimits.Clip(decorW, decorH);
if (!adjustedLimits.IsValid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid adjustedLimits: %{public}s", adjustedLimits.ToString().c_str());
return rect;
}
uint32_t minWByH = static_cast<uint32_t>(std::ceil(adjustedLimits.minHeight_ * aspectRatio));
uint32_t maxWByH = static_cast<uint32_t>(std::floor(adjustedLimits.maxHeight_ * aspectRatio));
uint32_t minW = std::max(adjustedLimits.minWidth_, minWByH);
uint32_t maxW = std::min(adjustedLimits.maxWidth_, maxWByH);
if (minW > maxW) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"Aspect ratio conflicts with limits, aspectRatio: %{public}f, adjustedLimits: %{public}s",
aspectRatio, adjustedLimits.ToString().c_str());
return rect;
}
uint32_t availW = static_cast<uint32_t>(rect.width_) - decorW;
uint32_t targetW = std::clamp(availW, minW, maxW);
uint32_t targetH = static_cast<uint32_t>(std::round(static_cast<float>(targetW) / aspectRatio));
targetH = std::clamp(targetH, adjustedLimits.minHeight_, adjustedLimits.maxHeight_);
WSRect adjustedRect = rect;
adjustedRect.width_ = static_cast<int32_t>(targetW + decorW);
adjustedRect.height_ = static_cast<int32_t>(targetH + decorH);
if (std::abs(rect.width_ - adjustedRect.width_) <= tolerancePx &&
std::abs(rect.height_ - adjustedRect.height_) <= tolerancePx) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Adjustment within tolerance: %{public}dpx, no adjustment", tolerancePx);
return rect;
}
return adjustedRect;
}
}
}