* Copyright (c) 2022 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 "adapter/android/osal/resource_theme_style.h"
#include <set>
namespace OHOS::Ace {
namespace {
constexpr char COLOR_VALUE_PREFIX[] = "$color:";
constexpr char RES_TAG[] = "resource:///";
constexpr char MEDIA_VALUE_KEY_WORD[] = "/";
constexpr char REF_ATTR_VALUE_KEY_WORD[] = "?theme:";
static const std::set<std::string> stringAttrs = {
"attribute_text_font_family_regular",
"attribute_text_font_family_medium",
"description_current_location",
"description_add_location",
"description_select_location",
"description_share_location",
"description_send_location",
"description_locating",
"description_location",
"description_send_current_location",
"description_relocation",
"description_punch_in",
"description_current_position",
"common_cancel_text",
"common_ok_text",
"stepper_back",
"stepper_skip",
"stepper_start",
"stepper_next",
"text_overlay_menu_cut_label",
"text_overlay_menu_copy_label",
"text_overlay_menu_paste_label",
"text_overlay_menu_select_all_label",
"text_overlay_menu_translate_label",
"text_overlay_menu_share_label",
"text_overlay_menu_search_label"
};
constexpr bool IsColor(const std::string& value)
{
return !value.empty() &&
(value.front() == '#' || value.find(COLOR_VALUE_PREFIX) != std::string::npos);
}
constexpr bool IsMediaPath(const std::string& value)
{
return value.find(MEDIA_VALUE_KEY_WORD) != std::string::npos;
}
bool IsNamedString(const std::string& name)
{
return stringAttrs.find(name) != stringAttrs.end();
}
constexpr bool IsReference(const std::string& value)
{
return value.find(REF_ATTR_VALUE_KEY_WORD) != std::string::npos;
}
double ParseDoubleUnit(const std::string& value, std::string& unit)
{
for (size_t i = 0; i < value.length(); i++) {
if (i == 0 && (value[i] == '-' || value[i] == '+')) {
continue;
}
if (value[i] != '.' && (value[i] < '0' || value[i] > '9')) {
unit = value.substr(i);
return std::atof(value.substr(0, i).c_str());
}
}
return std::atof(value.c_str());
}
DimensionUnit ParseDimensionUnit(const std::string& unit)
{
if (unit == "px") {
return DimensionUnit::PX;
} else if (unit == "fp") {
return DimensionUnit::FP;
} else if (unit == "lpx") {
return DimensionUnit::LPX;
} else if (unit == "%") {
return DimensionUnit::PERCENT;
} else {
return DimensionUnit::VP;
}
}
}
void ResourceThemeStyle::ParseContent()
{
for (auto& [attrName, attrValue] : rawAttrs_) {
if (attrName.empty() || attrValue.empty()) {
LOGW("theme attr name:%{public}s or value:%{public}s is empty", attrName.c_str(), attrValue.c_str());
continue;
}
if (IsColor(attrValue)) {
attributes_[attrName] = { .type = ThemeConstantsType::COLOR, .value = Color::FromString(attrValue) };
continue;
}
if (IsMediaPath(attrValue)) {
attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = std::string(RES_TAG) + attrValue };
continue;
}
if (IsNamedString(attrName)) {
attributes_[attrName] = { .type = ThemeConstantsType::STRING, .value = attrValue };
continue;
}
if (IsReference(attrValue)) {
attributes_[attrName] = { .type = ThemeConstantsType::REFERENCE_ATTR, .value = attrValue };
continue;
}
std::string unit = "";
auto doubleValue = ParseDoubleUnit(attrValue, unit);
if (unit.empty()) {
attributes_[attrName] = { .type = ThemeConstantsType::DOUBLE, .value = doubleValue };
} else {
attributes_[attrName] = { .type = ThemeConstantsType::DIMENSION,
.value = Dimension(doubleValue, ParseDimensionUnit(unit)) };
}
}
LOGD("theme attribute size:%{public}zu", attributes_.size());
OnParseStyle();
}
void ResourceThemeStyle::OnParseStyle()
{
for (auto& [patternName, patternMap]: patternAttrs_) {
auto patternStyle = AceType::MakeRefPtr<ResourceThemeStyle>(resAdapter_);
patternStyle->SetName(patternName);
patternStyle->parentStyle_ = AceType::WeakClaim(this);
patternStyle->rawAttrs_ = patternMap;
patternStyle->ParseContent();
attributes_[patternName] = { .type = ThemeConstantsType::PATTERN,
.value = RefPtr<ThemeStyle>(std::move(patternStyle)) };
}
}
}