From de7fd9f728243ee4c98a12504ad3f52bc5c60241 Mon Sep 17 00:00:00 2001 From: fangyunzhong Date: Mon, 10 Jul 2023 09:35:26 +0000 Subject: [PATCH] =?UTF-8?q?=E9=92=88=E5=AF=B9png=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E8=BF=9B=E8=A1=8C=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fangyunzhong --- BUILD.gn | 2 + bundle.json | 3 +- include/config_parser.h | 9 ++- include/resource_append.h | 4 + include/resource_check.h | 50 +++++++++++++ include/resource_data.h | 29 +++++++- include/resource_pack.h | 3 + include/resource_util.h | 8 ++ src/config_parser.cpp | 19 ++++- src/header.cpp | 2 +- src/resource_check.cpp | 151 ++++++++++++++++++++++++++++++++++++++ src/resource_pack.cpp | 19 ++++- src/resource_util.cpp | 31 ++++++++ 13 files changed, 320 insertions(+), 10 deletions(-) create mode 100755 include/resource_check.h create mode 100755 src/resource_check.cpp diff --git a/BUILD.gn b/BUILD.gn index 966a397..fd4c2e5 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -37,6 +37,7 @@ ohos_executable("restool") { "src/preview_manager.cpp", "src/reference_parser.cpp", "src/resource_append.cpp", + "src/resource_check.cpp", "src/resource_directory.cpp", "src/resource_item.cpp", "src/resource_merge.cpp", @@ -66,6 +67,7 @@ ohos_executable("restool") { "build/bounds_checking_function:restool_bounds_checking_function", "build/jsoncpp:restool_jsoncpp", "build/sqlite3:restool_sqlite", + "//third_party/libpng:libpng_static", "//third_party/libxml2:static_libxml2", ] diff --git a/bundle.json b/bundle.json index cb35589..3c7139f 100644 --- a/bundle.json +++ b/bundle.json @@ -23,7 +23,8 @@ "bounds_checking_function", "libxml2", "jsoncpp", - "sqlite" + "sqlite", + "libpng" ] }, "build": { diff --git a/include/config_parser.h b/include/config_parser.h index 6b090c7..b6d25ce 100644 --- a/include/config_parser.h +++ b/include/config_parser.h @@ -16,7 +16,8 @@ #ifndef OHOS_RESTOOL_CONFIG_PARSER_H #define OHOS_RESTOOL_CONFIG_PARSER_H -#include +#include +#include #include "resource_util.h" namespace OHOS { @@ -45,6 +46,10 @@ public: ModuleType GetModuleType() const; uint32_t ParseRefence(); uint32_t Save(const std::string &filePath) const; + const std::map> GetCheckNode() const + { + return jsonCheckIds_; + } void SetDependEntry(const bool isDenpend) { dependEntry = isDenpend; @@ -75,6 +80,7 @@ private: bool GetRefIdFromString(std::string &value, bool &update, const std::string &match) const; bool ParseModuleType(const std::string &type); bool ParseAbilitiesForDepend(Json::Value &moduleNode); + void AddCheckNode(const std::string &key, uint32_t id); std::string filePath_; std::string packageName_; std::string moduleName_; @@ -83,6 +89,7 @@ private: std::string mainAbility_; int32_t abilityIconId_; int32_t abilityLabelId_; + std::map> jsonCheckIds_; static const std::map MODULE_TYPES; static const std::map JSON_STRING_IDS; static const std::map JSON_ARRAY_IDS; diff --git a/include/resource_append.h b/include/resource_append.h index b0220b0..5549941 100644 --- a/include/resource_append.h +++ b/include/resource_append.h @@ -30,6 +30,10 @@ public: virtual ~ResourceAppend() {}; uint32_t Append(); uint32_t Combine(); + const std::map>> GetItems() const + { + return items_; + } private: bool Combine(const std::string &folderPath); diff --git a/include/resource_check.h b/include/resource_check.h new file mode 100755 index 0000000..f0796a6 --- /dev/null +++ b/include/resource_check.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_RESTOOL_RESOURCE_CHECK_H +#define OHOS_RESTOOL_RESOURCE_CHECK_H + +#include "config_parser.h" +#include "resource_append.h" +#include "resource_item.h" +#include +#include +#include +#include + +namespace OHOS { +namespace Global { +namespace Restool { + +class ResourceCheck { +public: + ResourceCheck(const ConfigParser &configJson, const std::shared_ptr &resourceAppend = nullptr); + virtual ~ResourceCheck() {}; + void CheckConfigJson(); + void CheckConfigJsonForCombine(); + +private: + const ConfigParser configJson_; + const std::shared_ptr resourceAppend_; + void CheckNodeInResourceItem(const std::string &key, const ResourceItem &resourceItem); + bool GetPngWidthAndHeight(const std::string &filePath, uint32_t *width, uint32_t *height); + bool IsValidPngImage(FILE *&in) const; + void CloseFile(FILE *fp); +}; + +} +} +} +#endif \ No newline at end of file diff --git a/include/resource_data.h b/include/resource_data.h index fe5bc9c..0f8574c 100644 --- a/include/resource_data.h +++ b/include/resource_data.h @@ -16,9 +16,10 @@ #ifndef OHOS_RESTOOL_RESOURCE_DATA_H #define OHOS_RESTOOL_RESOURCE_DATA_H -#include -#include -#include +#include +#include +#include +#include namespace OHOS { namespace Global { @@ -38,7 +39,7 @@ const static std::string LONG_PATH_HEAD = "\\\\?\\"; const static std::string ID_DEFINED_INDENTATION = " "; const static int32_t VERSION_MAX_LEN = 128; const static int32_t INT_TO_BYTES = sizeof(uint32_t); -static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 4.003" }; +static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 4.004" }; const static int32_t TAG_LEN = 4; enum class KeyType { @@ -216,6 +217,26 @@ const std::map g_resTypeMap = { { static_cast(ResType::INVALID_RES_TYPE), ResType::INVALID_RES_TYPE}, }; +const std::map> g_normalIconMap = { + { "sdpi-phone", {41, 144} }, + { "sdpi-tablet", {51, 192} }, + { "mdpi-phone", {54, 192} }, + { "mdpi-tablet", {68, 256} }, + { "ldpi-phone", {81, 288} }, + { "ldpi-tablet", {102, 384} }, + { "xldpi-phone", {108, 384} }, + { "xldpi-tablet", {136, 512} }, + { "xxldpi-phone", {162, 576} }, + { "xxldpi-tablet", {204, 768} }, + { "xxxldpi-phone", {216, 768} }, + { "xxxldpi-tablet", {272, 1024} }, +}; + +const std::map g_keyNodeIndexs = { + { "icon", 0 }, + { "startWindowIcon", 1 }, +}; + struct DirectoryInfo { std::string limitKey; std::string fileCluster; diff --git a/include/resource_pack.h b/include/resource_pack.h index 99a21bc..eb10054 100644 --- a/include/resource_pack.h +++ b/include/resource_pack.h @@ -21,6 +21,7 @@ #include "resource_util.h" #include "resource_item.h" #include "resource_data.h" +#include "resource_append.h" namespace OHOS { namespace Global { @@ -55,6 +56,8 @@ private: uint32_t HandleLabel(std::vector &items, ConfigParser &config) const; uint32_t HandleIcon(std::vector &items, ConfigParser &config) const; void SaveResourceItem(const ResourceItem &resourceItem, int32_t nextId) const; + void CheckConfigJson(); + void CheckConfigJsonForCombine(ResourceAppend &resourceAppend); bool CopyIcon(std::string &dataPath, const std::string &idName, std::string &fileName) const; PackageParser packageParser_; std::string moduleName_; diff --git a/include/resource_util.h b/include/resource_util.h index 582bb19..7aa11de 100644 --- a/include/resource_util.h +++ b/include/resource_util.h @@ -208,6 +208,14 @@ public: */ static FileEntry::FilePath GetMainPath(const std::string input); + /** + * @brief Gets the standard size of icons under different qualifier phrases + * @param keyParams set of qualifiers + * @param uint32_t index + * @return standard size of the png + */ + static uint32_t GetNormalSize(const std::vector &keyParams, uint32_t index); + private: enum class IgnoreType { IGNORE_FILE, diff --git a/src/config_parser.cpp b/src/config_parser.cpp index 2b32ab5..984bb76 100644 --- a/src/config_parser.cpp +++ b/src/config_parser.cpp @@ -14,8 +14,8 @@ */ #include "config_parser.h" -#include -#include +#include +#include #include "reference_parser.h" #include "restool_errors.h" @@ -370,10 +370,25 @@ bool ConfigParser::ParseJsonStringRef(Json::Value &parent, const string &key, Js } if (update) { parent[key + "Id"] = atoi(value.c_str()); + AddCheckNode(key, static_cast(atoi(value.c_str()))); } return true; } +void ConfigParser::AddCheckNode(const string &key, uint32_t id) +{ + if (g_keyNodeIndexs.find(key) != g_keyNodeIndexs.end()) { + auto result = jsonCheckIds_.find(key); + if (result == jsonCheckIds_.end()) { + set set; + set.emplace(id); + jsonCheckIds_.emplace(key, set); + } else { + result->second.emplace(id); + } + } +} + bool ConfigParser::GetRefIdFromString(string &value, bool &update, const string &match) const { ReferenceParser refParser; diff --git a/src/header.cpp b/src/header.cpp index 73f1c06..5fdc639 100644 --- a/src/header.cpp +++ b/src/header.cpp @@ -24,7 +24,7 @@ namespace Global { namespace Restool { using namespace std; const std::string Header::LICENSE_HEADER = "/*\n\ - * Copyright (c) 2021 Huawei Device Co., Ltd.\n\ + * Copyright (c) 2023 Huawei Device Co., Ltd.\n\ * Licensed under the Apache License, Version 2.0 (the \"License\");\n\ * you may not use this file except in compliance with the License.\n\ * You may obtain a copy of the License at\n\ diff --git a/src/resource_check.cpp b/src/resource_check.cpp new file mode 100755 index 0000000..74d72e3 --- /dev/null +++ b/src/resource_check.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023 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 "resource_check.h" +#include "file_manager.h" +#include + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +namespace { + constexpr int PNG_BYTRS_TO_CHECK = 8; +} + +ResourceCheck::ResourceCheck(const ConfigParser &configJson, const shared_ptr &resourceAppend) + : configJson_(configJson), resourceAppend_(resourceAppend) +{ +} + +void ResourceCheck::CheckConfigJson() +{ + const map> jsonCheckIds = configJson_.GetCheckNode(); + auto &fileManager = FileManager::GetInstance(); + auto &allResource = fileManager.GetResources(); + for (auto it = jsonCheckIds.begin(); it != jsonCheckIds.end(); it++) { + for (const auto &id : it->second) { + auto res = allResource.find(id); + if (res == allResource.end()) { + continue; + } + for (auto resourceItem : res->second) { + CheckNodeInResourceItem(it->first, resourceItem); + } + } + } +} + +void ResourceCheck::CheckConfigJsonForCombine() +{ + const map> jsonCheckIds = configJson_.GetCheckNode(); + auto &allResource = resourceAppend_->GetItems(); + for (auto it = jsonCheckIds.begin(); it != jsonCheckIds.end(); it++) { + for (const auto &id : it->second) { + auto res = allResource.find(id); + if (res == allResource.end()) { + continue; + } + for (auto resourceItemPtr : res->second) { + CheckNodeInResourceItem(it->first, *resourceItemPtr); + } + } + } +} + +void ResourceCheck::CheckNodeInResourceItem(const string &key, const ResourceItem &resourceItem) +{ + string limitKey = resourceItem.GetLimitKey(); + string filePath = resourceItem.GetFilePath(); + uint32_t width; + uint32_t height; + if (!GetPngWidthAndHeight(filePath, &width, &height)) { + return; + } + if (width != height) { + cout << "Warning: the png width and height not equal" << NEW_LINE_PATH << filePath << endl; + return; + } + auto result = g_keyNodeIndexs.find(key); + if (result == g_keyNodeIndexs.end()) { + return; + } + uint32_t normalSize = ResourceUtil::GetNormalSize(resourceItem.GetKeyParam(), result->second); + if (normalSize != 0 && width > normalSize) { + string warningMsg = "Warning: The width or height of the png file referenced by the " + key + \ + " exceeds the limit (" + to_string(normalSize) + " pixels)" + NEW_LINE_PATH + filePath; + cout << warningMsg << endl; + } +} + +bool ResourceCheck::IsValidPngImage(FILE *&in) const +{ + char checkheader[PNG_BYTRS_TO_CHECK]; + if (fread(checkheader, 1, PNG_BYTRS_TO_CHECK, in) != PNG_BYTRS_TO_CHECK) { + return false; + } + if (png_sig_cmp(reinterpret_cast(checkheader), 0, PNG_BYTRS_TO_CHECK) != 0) { + return false; + } + + rewind(in); + return true; +} + +bool ResourceCheck::GetPngWidthAndHeight(const string &filePath, uint32_t *width, uint32_t *height) +{ + FILE *in = fopen(filePath.c_str(), "rb"); + if (in == nullptr) { + cout << "Warning: " << filePath << " can not open" << endl; + return false; + } + if (!IsValidPngImage(in)) { + cout << "Warning: " << filePath << " is not png format" << endl; + CloseFile(in); + return false; + } + png_structp pngHandle = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (pngHandle == nullptr) { + CloseFile(in); + return false; + } + png_infop infoHandle = png_create_info_struct(pngHandle); + if (infoHandle == nullptr) { + CloseFile(in); + png_destroy_read_struct(&pngHandle, nullptr, nullptr); + return false; + } + png_init_io(pngHandle, in); + png_read_info(pngHandle, infoHandle); + unsigned int w; + unsigned int h; + png_get_IHDR(pngHandle, infoHandle, &w, &h, nullptr, nullptr, nullptr, nullptr, nullptr); + *width = w; + *height = h; + CloseFile(in); + png_destroy_read_struct(&pngHandle, &infoHandle, 0); + return true; +} + +void ResourceCheck::CloseFile(FILE *fp) +{ + if (fp != nullptr) { + fclose(fp); + } +} + +} +} +} \ No newline at end of file diff --git a/src/resource_pack.cpp b/src/resource_pack.cpp index 75d53b4..d457bc3 100644 --- a/src/resource_pack.cpp +++ b/src/resource_pack.cpp @@ -22,7 +22,7 @@ #include "increment_manager.h" #include "resource_merge.h" #include "resource_table.h" -#include "resource_append.h" +#include "resource_check.h" #include "preview_manager.h" namespace OHOS { @@ -315,6 +315,12 @@ uint32_t ResourcePack::GenerateConfigJson() return configJson_.Save(outputPath); } +void ResourcePack::CheckConfigJson() +{ + ResourceCheck resourceCheck(configJson_); + resourceCheck.CheckConfigJson(); +} + uint32_t ResourcePack::ScanResources(const vector &inputs, const string &output) { auto &fileManager = FileManager::GetInstance(); @@ -364,6 +370,8 @@ uint32_t ResourcePack::PackNormal() return RESTOOL_ERROR; } + CheckConfigJson(); + ResourceTable resourceTable; if (!packageParser_.GetDependEntry().empty()) { if (HandleFeature() != RESTOOL_SUCCESS) { @@ -588,11 +596,20 @@ uint32_t ResourcePack::PackCombine() return RESTOOL_ERROR; } + CheckConfigJsonForCombine(resourceAppend); + if (GenerateHeader() != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } return RESTOOL_SUCCESS; } + +void ResourcePack::CheckConfigJsonForCombine(ResourceAppend &resourceAppend) +{ + ResourceCheck resourceCheck(configJson_, make_shared(resourceAppend)); + resourceCheck.CheckConfigJsonForCombine(); +} + } } } diff --git a/src/resource_util.cpp b/src/resource_util.cpp index a8184a2..efce845 100644 --- a/src/resource_util.cpp +++ b/src/resource_util.cpp @@ -402,6 +402,37 @@ FileEntry::FilePath ResourceUtil::GetMainPath(const string input) return FileEntry::FilePath(input).GetParent(); } +uint32_t ResourceUtil::GetNormalSize(const vector &keyParams, uint32_t index) +{ + string device; + string dpi; + if (keyParams.size() == 0) { + device = "phone"; + dpi = "sdpi"; + } + for (const auto &keyparam : keyParams) { + string limitKey = GetKeyParamValue(keyparam); + if (limitKey.empty()) { + continue; + } + if (keyparam.keyType == KeyType::DEVICETYPE) { + device = limitKey; + } else if (keyparam.keyType == KeyType::RESOLUTION) { + dpi = limitKey; + } + } + if (device.empty()) { + device = "phone"; + } + if (dpi.empty()) { + dpi = "sdpi"; + } + if (device != "phone" && device != "tablet") { + return 0; + } + return g_normalIconMap.find(dpi + "-" + device)->second[index]; +} + } } }