mirror of
https://github.com/openharmony/developtools_global_resource_tool.git
synced 2026-07-18 17:24:42 -04:00
@@ -52,9 +52,15 @@ struct TranscodeResult {
|
||||
int32_t height;
|
||||
};
|
||||
|
||||
struct ImageSize {
|
||||
size_t width;
|
||||
size_t height;
|
||||
};
|
||||
|
||||
typedef TranscodeError (*ITranscodeImages) (const std::string &imagePath, const bool extAppend,
|
||||
std::string &outputPath, TranscodeResult &result);
|
||||
typedef bool (*ISetTranscodeOptions) (const std::string &optionJson, const std::string &optionJsonExclude);
|
||||
typedef TranscodeError (*IScaleImage) (const std::string &imagePath, std::string &outputPath, ImageSize size);
|
||||
|
||||
class CompressionParser {
|
||||
public:
|
||||
@@ -69,6 +75,8 @@ public:
|
||||
std::string PrintTransMessage();
|
||||
bool GetDefaultCompress();
|
||||
void SetOutPath(const std::string &path);
|
||||
bool ScaleIconEnable();
|
||||
bool CheckAndScaleIcon(const std::string &src, const std::string &originDst, std::string &scaleDst);
|
||||
private:
|
||||
bool ParseContext(const cJSON *contextNode);
|
||||
bool ParseCompression(const cJSON *compressionNode);
|
||||
@@ -77,6 +85,7 @@ private:
|
||||
bool SetTranscodeOptions(const std::string &optionJson, const std::string &optionJsonExclude);
|
||||
TranscodeError TranscodeImages(const std::string &imagePath, const bool extAppend,
|
||||
std::string &outputPath, TranscodeResult &result);
|
||||
TranscodeError ScaleImage(const std::string &imagePath, std::string &outputPath);
|
||||
std::vector<std::string> ParsePath(const cJSON *pathNode);
|
||||
std::string ParseRules(const cJSON *rulesNode);
|
||||
std::string ParseJsonStr(const cJSON *node);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
const FilePath &GetFilePath() const;
|
||||
static bool Exist(const std::string &path);
|
||||
static bool RemoveAllDir(const std::string &path);
|
||||
static bool RemoveFile(const std::string &path);
|
||||
static bool CreateDirs(const std::string &path);
|
||||
static bool CopyFileInner(const std::string &src, const std::string &dst);
|
||||
static bool IsDirectory(const std::string &path);
|
||||
|
||||
@@ -36,11 +36,13 @@ public:
|
||||
moduleName_ = moduleName;
|
||||
};
|
||||
uint32_t MergeResourceItem(const std::map<int64_t, std::vector<ResourceItem>> &resourceInfos);
|
||||
bool ScaleIcons(const std::string &output, const std::map<std::string, std::set<uint32_t>> &iconMap);
|
||||
|
||||
private:
|
||||
uint32_t ScanModule(const std::string &input, const std::string &output);
|
||||
uint32_t ParseReference(const std::string &output);
|
||||
void CheckAllItems(std::vector<std::pair<ResType, std::string>> &noBaseResource);
|
||||
bool ScaleIcon(const std::string &output, ResourceItem &item);
|
||||
|
||||
// id, resource items
|
||||
std::map<int64_t, std::vector<ResourceItem>> items_;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <cJSON.h>
|
||||
#include "id_worker.h"
|
||||
#include "resource_data.h"
|
||||
#include "resource_item.h"
|
||||
|
||||
namespace OHOS {
|
||||
@@ -31,6 +32,7 @@ public:
|
||||
uint32_t ParseRefInResourceItem(ResourceItem &resourceItem) const;
|
||||
uint32_t ParseRefInJsonFile(ResourceItem &resourceItem, const std::string &output, const bool isIncrement = false);
|
||||
uint32_t ParseRefInString(std::string &value, bool &update) const;
|
||||
static std::map<int64_t, std::set<int64_t>> &GetLayerIconIds();
|
||||
private:
|
||||
bool ParseRefJson(const std::string &from, const std::string &to);
|
||||
bool ParseRefResourceItemData(const ResourceItem &resourceItem, std::string &data, bool &update) const;
|
||||
@@ -46,7 +48,10 @@ private:
|
||||
const IdWorker &idWorker_;
|
||||
static const std::map<std::string, ResType> ID_REFS;
|
||||
static const std::map<std::string, ResType> ID_OHOS_REFS;
|
||||
static std::map<int64_t, std::set<int64_t>> layerIconIds_;
|
||||
cJSON *root_;
|
||||
bool isParsingMediaJson_;
|
||||
int64_t mediaJsonId_{ INVALID_ID };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,11 @@ const static std::string SOLUTIONS_ARROW = "> ";
|
||||
const static std::string LONG_PATH_HEAD = "\\\\?\\";
|
||||
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 5.011" };
|
||||
static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 5.012" };
|
||||
const static int32_t TAG_LEN = 4;
|
||||
static std::set<std::string> g_resourceSet;
|
||||
const static int8_t THREAD_POOL_SIZE = 2;
|
||||
const static int8_t INVALID_ID = -1;
|
||||
|
||||
enum class KeyType {
|
||||
LANGUAGE = 0,
|
||||
|
||||
@@ -56,6 +56,13 @@ public:
|
||||
*/
|
||||
static bool RmoveAllDir(const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief remove file.
|
||||
* @param path: input file.
|
||||
* @return true if remove success, other false.
|
||||
*/
|
||||
static bool RmoveFile(const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief open json file.
|
||||
* @param path: json file path.
|
||||
|
||||
+77
-10
@@ -95,6 +95,14 @@ uint32_t CompressionParser::Init()
|
||||
cerr << "Error: JSON file parsing failed, please check the JSON file." << NEW_LINE_PATH << filePath_ << endl;
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
cJSON *contextNode = cJSON_GetObjectItem(root_, "context");
|
||||
if (!ParseContext(contextNode)) {
|
||||
cerr << NEW_LINE_PATH << filePath_ << endl;
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
if (!LoadImageTranscoder()) {
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
cJSON *compressionNode = cJSON_GetObjectItem(root_, "compression");
|
||||
if (!ParseCompression(compressionNode)) {
|
||||
return RESTOOL_ERROR;
|
||||
@@ -102,15 +110,11 @@ uint32_t CompressionParser::Init()
|
||||
if (!mediaSwitch_) {
|
||||
return RESTOOL_SUCCESS;
|
||||
}
|
||||
cJSON *contextNode = cJSON_GetObjectItem(root_, "context");
|
||||
cJSON *filtersNode = cJSON_GetObjectItem(compressionNode, "filters");
|
||||
if (!ParseContext(contextNode) || !ParseFilters(filtersNode)) {
|
||||
if (!ParseFilters(filtersNode)) {
|
||||
cerr << NEW_LINE_PATH << filePath_ << endl;
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
if (!LoadImageTranscoder()) {
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
string caches = outPath_;
|
||||
caches.append(SEPARATOR_FILE).append(CACHES_DIR);
|
||||
if (!ResourceUtil::CreateDirs(caches)) {
|
||||
@@ -375,6 +379,35 @@ TranscodeError CompressionParser::TranscodeImages(const string &imagePath, const
|
||||
return TranscodeError::SUCCESS;
|
||||
}
|
||||
|
||||
TranscodeError CompressionParser::ScaleImage(const std::string &imagePath, std::string &outputPath)
|
||||
{
|
||||
if (!handle_) {
|
||||
cout << "Warning: ScaleImage handle_ is nullptr." << endl;
|
||||
return TranscodeError::LOAD_COMPRESS_FAILED;
|
||||
}
|
||||
#ifdef __WIN32
|
||||
IScaleImage iScaleImage = (IScaleImage)GetProcAddress(handle_, "TranscodeSLR");
|
||||
#else
|
||||
IScaleImage iScaleImage = (IScaleImage)dlsym(handle_, "TranscodeSLR");
|
||||
#endif
|
||||
if (!iScaleImage) {
|
||||
cout << "Warning: Failed to get the 'TranscodeSLR'." << endl;
|
||||
return TranscodeError::LOAD_COMPRESS_FAILED;
|
||||
}
|
||||
TranscodeError ret = (*iScaleImage)(imagePath, outputPath, { 512, 512 });
|
||||
if (ret != TranscodeError::SUCCESS) {
|
||||
auto iter = ERRORCODEMAP.find(ret);
|
||||
if (iter != ERRORCODEMAP.end()) {
|
||||
cout << "Warning: ScaleImage failed, error message: " << iter->second << ", file path = " << imagePath
|
||||
<< endl;
|
||||
} else {
|
||||
cout << "Warning: ScaleImage failed" << ", file path = " << imagePath << endl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return TranscodeError::SUCCESS;
|
||||
}
|
||||
|
||||
bool CompressionParser::CheckPath(const string &src, const vector<string> &paths)
|
||||
{
|
||||
if (paths.size() == 1 && paths[0] == "true") {
|
||||
@@ -519,14 +552,14 @@ bool CompressionParser::CheckAndTranscode(const string &src, string &dst, string
|
||||
|
||||
bool CompressionParser::CopyForTrans(const string &src, const string &originDst, const string &dst)
|
||||
{
|
||||
string srcSuffix;
|
||||
string dstSuffix;
|
||||
auto srcIndex = src.find_last_of(".");
|
||||
auto dstIndex = dst.find_last_of(".");
|
||||
if (srcIndex == string::npos || dstIndex == string::npos) {
|
||||
cerr << "Error: invalid copy path." << endl;
|
||||
return false;
|
||||
if (srcIndex != string::npos && dstIndex != string::npos) {
|
||||
srcSuffix = src.substr(srcIndex + 1);
|
||||
dstSuffix = dst.substr(dstIndex + 1);
|
||||
}
|
||||
string srcSuffix = src.substr(srcIndex + 1);
|
||||
string dstSuffix = dst.substr(dstIndex + 1);
|
||||
auto ret = false;
|
||||
if (srcSuffix == dstSuffix) {
|
||||
ret = ResourceUtil::CopyFileInner(src, dst);
|
||||
@@ -571,6 +604,40 @@ bool CompressionParser::CopyAndTranscode(const string &src, string &dst, const b
|
||||
CollectTime(totalCounts_, totalTime_, t2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CompressionParser::CheckAndScaleIcon(const std::string &src, const std::string &originDst, std::string &scaleDst)
|
||||
{
|
||||
scaleDst = src;
|
||||
if (filePath_.empty() || outPath_.empty()) {
|
||||
cout << "Info: compression path or out path is empty, unable to scale icon." << endl;
|
||||
return true;
|
||||
}
|
||||
auto index = originDst.find_last_of(SEPARATOR_FILE);
|
||||
if (index == string::npos) {
|
||||
cerr << "Error: invalid output path." << NEW_LINE_PATH << originDst << endl;
|
||||
return false;
|
||||
}
|
||||
uint32_t startIndex = outPath_.size() + RESOURCES_DIR.size() + 1;
|
||||
string qualifierDir = originDst.substr(startIndex, index - startIndex);
|
||||
string outputCache = outPath_ + SEPARATOR_FILE + CACHES_DIR + qualifierDir;
|
||||
if (!ResourceUtil::CreateDirs(outputCache)) {
|
||||
cerr << "Error: scale icon create output dir failed. dir = " << outputCache << endl;
|
||||
return false;
|
||||
}
|
||||
string fileName = originDst.substr(index + 1);
|
||||
string outputFile = outputCache + SEPARATOR_FILE + fileName;
|
||||
auto ret = ScaleImage(src, outputFile);
|
||||
if (ret == TranscodeError::SUCCESS) {
|
||||
// if scale success, change src file to scale image
|
||||
scaleDst = outputFile;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompressionParser::ScaleIconEnable()
|
||||
{
|
||||
return !filePath_.empty() && !outPath_.empty() && handle_ != nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +424,11 @@ void ConfigParser::AddCheckNode(const string &key, uint32_t id)
|
||||
} else {
|
||||
result->second.emplace(id);
|
||||
}
|
||||
auto layerIconIds = ReferenceParser::GetLayerIconIds();
|
||||
if (layerIconIds.find(id) != layerIconIds.end()) {
|
||||
auto ids = layerIconIds[id];
|
||||
jsonCheckIds_[key].insert(ids.begin(), ids.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +137,15 @@ bool FileEntry::RemoveAllDir(const string &path)
|
||||
return RemoveAllDirInner(f);
|
||||
}
|
||||
|
||||
bool FileEntry::RemoveFile(const string &path)
|
||||
{
|
||||
FileEntry f(path);
|
||||
if (!f.Init()) {
|
||||
return false;
|
||||
}
|
||||
return RemoveAllDirInner(f);
|
||||
}
|
||||
|
||||
bool FileEntry::CreateDirs(const string &path)
|
||||
{
|
||||
return CreateDirsInner(path, 0);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "file_manager.h"
|
||||
#include <algorithm>
|
||||
#include "compression_parser.h"
|
||||
#include <iostream>
|
||||
#include "factory_resource_compiler.h"
|
||||
#include "file_entry.h"
|
||||
@@ -87,6 +88,85 @@ void FileManager::CheckAllItems(vector<pair<ResType, string>> &noBaseResource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileManager::ScaleIcons(const string &output, const std::map<std::string, std::set<uint32_t>> &iconMap)
|
||||
{
|
||||
if (!CompressionParser::GetCompressionParser()->ScaleIconEnable()) {
|
||||
cout << "Info: scale icon is not enable." << endl;
|
||||
return true;
|
||||
}
|
||||
std::set<int64_t> allIconIds;
|
||||
for (auto &it : iconMap) {
|
||||
if (it.first != "icon") {
|
||||
continue;
|
||||
}
|
||||
allIconIds.insert(it.second.begin(), it.second.end());
|
||||
}
|
||||
if (allIconIds.size() == 0) {
|
||||
cout << "Info: no icons need to scale, icon ids size is 0." << endl;
|
||||
return true;
|
||||
}
|
||||
for (auto &id : allIconIds) {
|
||||
std::map<int64_t, std::vector<ResourceItem>>::iterator iter = items_.find(id);
|
||||
if (iter == items_.end()) {
|
||||
continue;
|
||||
}
|
||||
for (auto &item : iter->second) {
|
||||
if (!ScaleIcon(output, item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileManager::ScaleIcon(const string &output, ResourceItem &item)
|
||||
{
|
||||
std::string media = "media";
|
||||
// item's data is short path for icon file, such as "entry/resources/base/media/app_icon.png"
|
||||
const string currentData(reinterpret_cast<const char *>(item.GetData()), item.GetDataLength());
|
||||
auto outIndex = currentData.find_last_of(SEPARATOR);
|
||||
if (outIndex == string::npos) {
|
||||
cerr << "Error: ScaleIcon invalid output name: " << currentData << endl;
|
||||
return false;
|
||||
}
|
||||
// get current output file name and full path
|
||||
string fileName = currentData.substr(outIndex + 1);
|
||||
FileEntry::FilePath fullFilePath = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey())
|
||||
.Append(media).Append(fileName);
|
||||
if (fullFilePath.GetExtension() == JSON_EXTENSION) {
|
||||
cout << "Info: can't scale media json file." << endl;
|
||||
return true;
|
||||
}
|
||||
const string fullOutPath = fullFilePath.GetPath();
|
||||
// delete current output file
|
||||
if (!ResourceUtil::RmoveFile(fullOutPath)) {
|
||||
cout << "Error: ScaleIcon RmoveFile failed: " << fullOutPath << endl;
|
||||
return false;
|
||||
}
|
||||
// get origin icon output full path with the origin icon file name in src
|
||||
std::string dst = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey()).Append(media)
|
||||
.Append(item.GetName()).GetPath();
|
||||
// the origin full file in src
|
||||
std::string scaleDst = item.GetFilePath();
|
||||
// scale icon
|
||||
if (!CompressionParser::GetCompressionParser()->CheckAndScaleIcon(item.GetFilePath(), dst, scaleDst)) {
|
||||
return false;
|
||||
}
|
||||
// compress scaled icon
|
||||
if (!CompressionParser::GetCompressionParser()->CopyAndTranscode(scaleDst, dst)) {
|
||||
return false;
|
||||
}
|
||||
string newFileName = FileEntry::FilePath(dst).GetFilename();
|
||||
std::string newData = moduleName_ + SEPARATOR + RESOURCES_DIR + SEPARATOR + item.GetLimitKey() + SEPARATOR + media
|
||||
+ SEPARATOR + newFileName;
|
||||
if (!item.SetData(reinterpret_cast<const int8_t *>(newData.c_str()), newData.length())) {
|
||||
cerr << "Error: ScaleIcon resource item set data fail, data: " << newData << NEW_LINE_PATH
|
||||
<< item.GetFilePath() << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,9 @@ const map<string, ResType> ReferenceParser::ID_OHOS_REFS = {
|
||||
{ "^\\$ohos:symbol:", ResType::SYMBOL }
|
||||
};
|
||||
|
||||
ReferenceParser::ReferenceParser() : idWorker_(IdWorker::GetInstance()), root_(nullptr)
|
||||
std::map<int64_t, std::set<int64_t>> ReferenceParser::layerIconIds_;
|
||||
|
||||
ReferenceParser::ReferenceParser() : idWorker_(IdWorker::GetInstance()), root_(nullptr), isParsingMediaJson_(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -113,14 +115,25 @@ uint32_t ReferenceParser::ParseRefInResourceItem(ResourceItem &resourceItem) con
|
||||
uint32_t ReferenceParser::ParseRefInJsonFile(ResourceItem &resourceItem, const string &output, const bool isIncrement)
|
||||
{
|
||||
string jsonPath;
|
||||
if (resourceItem.GetResType() == ResType::MEDIA) {
|
||||
jsonPath = FileEntry::FilePath(output).Append(RESOURCES_DIR)
|
||||
.Append(resourceItem.GetLimitKey()).Append("media").Append(resourceItem.GetName()).GetPath();
|
||||
ResType resType = resourceItem.GetResType();
|
||||
string resName = resourceItem.GetName();
|
||||
if (resType == ResType::MEDIA) {
|
||||
jsonPath = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(resourceItem.GetLimitKey()).Append("media")
|
||||
.Append(resName).GetPath();
|
||||
isParsingMediaJson_ = true;
|
||||
mediaJsonId_ = idWorker_.GetId(resType, ResourceUtil::GetIdName(resName, resType));
|
||||
if (mediaJsonId_ != INVALID_ID) {
|
||||
set<int64_t> set;
|
||||
layerIconIds_[mediaJsonId_] = set;
|
||||
}
|
||||
} else {
|
||||
jsonPath = FileEntry::FilePath(output).Append(RESOURCES_DIR)
|
||||
.Append("base").Append("profile").Append(resourceItem.GetName()).GetPath();
|
||||
jsonPath = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append("base").Append("profile").Append(resName)
|
||||
.GetPath();
|
||||
}
|
||||
if (!ParseRefJson(resourceItem.GetFilePath(), jsonPath)) {
|
||||
bool parseJsonRet = ParseRefJson(resourceItem.GetFilePath(), jsonPath);
|
||||
isParsingMediaJson_ = false;
|
||||
mediaJsonId_ = INVALID_ID;
|
||||
if (!parseJsonRet) {
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
|
||||
@@ -274,6 +287,10 @@ bool ReferenceParser::ParseRefImpl(string &key, const map<string, ResType> &refs
|
||||
if (regex_search(key, result, regex(ref.first))) {
|
||||
string name = key.substr(result[0].str().length());
|
||||
int64_t id = idWorker_.GetId(ref.second, name);
|
||||
if (!isSystem && ref.second == ResType::MEDIA && mediaJsonId_ != 0
|
||||
&& layerIconIds_.find(mediaJsonId_) != layerIconIds_.end()) {
|
||||
layerIconIds_[mediaJsonId_].insert(id);
|
||||
}
|
||||
if (isSystem) {
|
||||
id = idWorker_.GetSystemId(ref.second, name);
|
||||
}
|
||||
@@ -314,6 +331,11 @@ bool ReferenceParser::ParseRefJsonImpl(cJSON *node, bool &needSave) const
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<int64_t, std::set<int64_t>> &ReferenceParser::GetLayerIconIds()
|
||||
{
|
||||
return layerIconIds_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +308,10 @@ uint32_t ResourcePack::PackNormal()
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
|
||||
if (!FileManager::GetInstance().ScaleIcons(packageParser_.GetOutput(), configJson_.GetCheckNode())) {
|
||||
return RESTOOL_ERROR;
|
||||
}
|
||||
|
||||
if (packageParser_.GetIconCheck()) {
|
||||
CheckConfigJson();
|
||||
}
|
||||
|
||||
@@ -73,6 +73,11 @@ bool ResourceUtil::RmoveAllDir(const string &path)
|
||||
return FileEntry::RemoveAllDir(path);
|
||||
}
|
||||
|
||||
bool ResourceUtil::RmoveFile(const string &path)
|
||||
{
|
||||
return FileEntry::RemoveFile(path);
|
||||
}
|
||||
|
||||
bool ResourceUtil::OpenJsonFile(const string &path, cJSON **root)
|
||||
{
|
||||
ifstream ifs(FileEntry::AdaptLongPath(path), ios::binary);
|
||||
|
||||
Reference in New Issue
Block a user