13920e296Sopenharmony_ci/*
23920e296Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
33920e296Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43920e296Sopenharmony_ci * you may not use this file except in compliance with the License.
53920e296Sopenharmony_ci * You may obtain a copy of the License at
63920e296Sopenharmony_ci *
73920e296Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83920e296Sopenharmony_ci *
93920e296Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103920e296Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113920e296Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123920e296Sopenharmony_ci * See the License for the specific language governing permissions and
133920e296Sopenharmony_ci * limitations under the License.
143920e296Sopenharmony_ci */
153920e296Sopenharmony_ci#include "resource_check.h"
163920e296Sopenharmony_ci#include "file_manager.h"
173920e296Sopenharmony_ci#include <png.h>
183920e296Sopenharmony_ci
193920e296Sopenharmony_cinamespace OHOS {
203920e296Sopenharmony_cinamespace Global {
213920e296Sopenharmony_cinamespace Restool {
223920e296Sopenharmony_ciusing namespace std;
233920e296Sopenharmony_ci
243920e296Sopenharmony_cinamespace {
253920e296Sopenharmony_ci    constexpr int PNG_BYTRS_TO_CHECK = 8;
263920e296Sopenharmony_ci}
273920e296Sopenharmony_ci
283920e296Sopenharmony_ciResourceCheck::ResourceCheck(const std::map<std::string, std::set<uint32_t>> &jsonCheckIds,
293920e296Sopenharmony_ci    const shared_ptr<ResourceAppend> &resourceAppend) : jsonCheckIds_(jsonCheckIds), resourceAppend_(resourceAppend)
303920e296Sopenharmony_ci{
313920e296Sopenharmony_ci}
323920e296Sopenharmony_ci
333920e296Sopenharmony_civoid ResourceCheck::CheckConfigJson()
343920e296Sopenharmony_ci{
353920e296Sopenharmony_ci    auto &fileManager = FileManager::GetInstance();
363920e296Sopenharmony_ci    auto &allResource = fileManager.GetResources();
373920e296Sopenharmony_ci    for (auto it = jsonCheckIds_.begin(); it != jsonCheckIds_.end(); it++) {
383920e296Sopenharmony_ci        for (const auto &id : it->second) {
393920e296Sopenharmony_ci            auto res = allResource.find(id);
403920e296Sopenharmony_ci            if (res == allResource.end()) {
413920e296Sopenharmony_ci                continue;
423920e296Sopenharmony_ci            }
433920e296Sopenharmony_ci            for (auto resourceItem : res->second) {
443920e296Sopenharmony_ci                CheckNodeInResourceItem(it->first, resourceItem);
453920e296Sopenharmony_ci            }
463920e296Sopenharmony_ci        }
473920e296Sopenharmony_ci    }
483920e296Sopenharmony_ci}
493920e296Sopenharmony_ci
503920e296Sopenharmony_civoid ResourceCheck::CheckConfigJsonForCombine()
513920e296Sopenharmony_ci{
523920e296Sopenharmony_ci    auto &allResource = resourceAppend_->GetItems();
533920e296Sopenharmony_ci    for (auto it = jsonCheckIds_.begin(); it != jsonCheckIds_.end(); it++) {
543920e296Sopenharmony_ci        for (const auto &id : it->second) {
553920e296Sopenharmony_ci            auto res = allResource.find(id);
563920e296Sopenharmony_ci            if (res == allResource.end()) {
573920e296Sopenharmony_ci                continue;
583920e296Sopenharmony_ci            }
593920e296Sopenharmony_ci            for (auto resourceItemPtr : res->second) {
603920e296Sopenharmony_ci                CheckNodeInResourceItem(it->first, *resourceItemPtr);
613920e296Sopenharmony_ci            }
623920e296Sopenharmony_ci        }
633920e296Sopenharmony_ci    }
643920e296Sopenharmony_ci}
653920e296Sopenharmony_ci
663920e296Sopenharmony_civoid ResourceCheck::CheckNodeInResourceItem(const string &key, const ResourceItem &resourceItem)
673920e296Sopenharmony_ci{
683920e296Sopenharmony_ci    string filePath = resourceItem.GetFilePath();
693920e296Sopenharmony_ci    uint32_t width;
703920e296Sopenharmony_ci    uint32_t height;
713920e296Sopenharmony_ci    if (!GetPngWidthAndHeight(filePath, &width, &height)) {
723920e296Sopenharmony_ci        return;
733920e296Sopenharmony_ci    }
743920e296Sopenharmony_ci    if (width != height) {
753920e296Sopenharmony_ci        cerr << "Warning: the png width and height not equal" << NEW_LINE_PATH << filePath << endl;
763920e296Sopenharmony_ci        return;
773920e296Sopenharmony_ci    }
783920e296Sopenharmony_ci    auto result = g_keyNodeIndexs.find(key);
793920e296Sopenharmony_ci    if (result == g_keyNodeIndexs.end()) {
803920e296Sopenharmony_ci        return;
813920e296Sopenharmony_ci    }
823920e296Sopenharmony_ci    uint32_t normalSize = ResourceUtil::GetNormalSize(resourceItem.GetKeyParam(), result->second);
833920e296Sopenharmony_ci    if (normalSize != 0 && width > normalSize) {
843920e296Sopenharmony_ci        string warningMsg = "Warning: The width or height of the png file referenced by the " + key + \
853920e296Sopenharmony_ci            " exceeds the limit (" + to_string(normalSize) + " pixels)" + NEW_LINE_PATH + filePath;
863920e296Sopenharmony_ci        cerr << warningMsg << endl;
873920e296Sopenharmony_ci    }
883920e296Sopenharmony_ci}
893920e296Sopenharmony_ci
903920e296Sopenharmony_cibool ResourceCheck::IsValidPngImage(FILE *&in) const
913920e296Sopenharmony_ci{
923920e296Sopenharmony_ci    char checkheader[PNG_BYTRS_TO_CHECK];
933920e296Sopenharmony_ci    if (fread(checkheader, 1, PNG_BYTRS_TO_CHECK, in) != PNG_BYTRS_TO_CHECK) {
943920e296Sopenharmony_ci        return false;
953920e296Sopenharmony_ci    }
963920e296Sopenharmony_ci    if (png_sig_cmp(reinterpret_cast<png_const_bytep>(checkheader), 0, PNG_BYTRS_TO_CHECK) != 0) {
973920e296Sopenharmony_ci        return false;
983920e296Sopenharmony_ci    }
993920e296Sopenharmony_ci
1003920e296Sopenharmony_ci    rewind(in);
1013920e296Sopenharmony_ci    return true;
1023920e296Sopenharmony_ci}
1033920e296Sopenharmony_ci
1043920e296Sopenharmony_cibool ResourceCheck::GetPngWidthAndHeight(const string &filePath, uint32_t *width, uint32_t *height)
1053920e296Sopenharmony_ci{
1063920e296Sopenharmony_ci    FILE *in = fopen(filePath.c_str(), "rb");
1073920e296Sopenharmony_ci    if (in == nullptr) {
1083920e296Sopenharmony_ci        cout << "Warning: " << filePath << " can not open" << endl;
1093920e296Sopenharmony_ci        return false;
1103920e296Sopenharmony_ci    }
1113920e296Sopenharmony_ci    if (!IsValidPngImage(in)) {
1123920e296Sopenharmony_ci        cout << "Warning: " << filePath << " is not png format" << endl;
1133920e296Sopenharmony_ci        CloseFile(in);
1143920e296Sopenharmony_ci        return false;
1153920e296Sopenharmony_ci    }
1163920e296Sopenharmony_ci    png_structp pngHandle = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
1173920e296Sopenharmony_ci    if (pngHandle == nullptr) {
1183920e296Sopenharmony_ci        CloseFile(in);
1193920e296Sopenharmony_ci        return false;
1203920e296Sopenharmony_ci    }
1213920e296Sopenharmony_ci    png_infop infoHandle = png_create_info_struct(pngHandle);
1223920e296Sopenharmony_ci    if (infoHandle == nullptr) {
1233920e296Sopenharmony_ci        CloseFile(in);
1243920e296Sopenharmony_ci        png_destroy_read_struct(&pngHandle, nullptr, nullptr);
1253920e296Sopenharmony_ci        return false;
1263920e296Sopenharmony_ci    }
1273920e296Sopenharmony_ci    png_init_io(pngHandle, in);
1283920e296Sopenharmony_ci    png_read_info(pngHandle, infoHandle);
1293920e296Sopenharmony_ci    unsigned int w;
1303920e296Sopenharmony_ci    unsigned int h;
1313920e296Sopenharmony_ci    png_get_IHDR(pngHandle, infoHandle, &w, &h, nullptr, nullptr, nullptr, nullptr, nullptr);
1323920e296Sopenharmony_ci    *width = w;
1333920e296Sopenharmony_ci    *height = h;
1343920e296Sopenharmony_ci    CloseFile(in);
1353920e296Sopenharmony_ci    png_destroy_read_struct(&pngHandle, &infoHandle, 0);
1363920e296Sopenharmony_ci    return true;
1373920e296Sopenharmony_ci}
1383920e296Sopenharmony_ci
1393920e296Sopenharmony_civoid ResourceCheck::CloseFile(FILE *fp)
1403920e296Sopenharmony_ci{
1413920e296Sopenharmony_ci    if (fp != nullptr) {
1423920e296Sopenharmony_ci        fclose(fp);
1433920e296Sopenharmony_ci    }
1443920e296Sopenharmony_ci}
1453920e296Sopenharmony_ci
1463920e296Sopenharmony_ci}
1473920e296Sopenharmony_ci}
1483920e296Sopenharmony_ci}