Signed-off-by: zhongjianfei <zhongjianfei@huawei.com>
Change-Id: Id693aa3c4e59c491ca42006bd4ba19e5f335ee16
This commit is contained in:
zhongjianfei 2021-08-17 15:26:15 +08:00
parent d32cd0ddfa
commit cce980c0f8
1675 changed files with 121322 additions and 30945 deletions

View File

@ -35,7 +35,8 @@ group("ace_packages") {
deps += [
"adapter/common/cpp:libace_engine_qjs",
"adapter/common/cpp:libace_engine_qjs_debug",
"adapter/common/cpp:libace_engine_declarative_qjs"
"adapter/common/cpp:libace_engine_declarative_qjs",
"adapter/common/cpp:libace_engine_pa_qjs"
]
}
}
@ -102,6 +103,10 @@ config("ace_config") {
cflags += [ "-std=c++17" ]
defines += [ "_USE_MATH_DEFINES" ]
}
if (enable_ace_debug) {
defines += [ "ACE_DEBUG" ]
}
}
config("ace_test_config") {

View File

@ -14,6 +14,7 @@
import("//third_party/flutter/flutter_ace_config.gni")
ace_root = "//foundation/ace/ace_engine"
ace_flutter_engine_root = "//third_party/flutter"
ace_test_output_root = "ace_engine_standard"
@ -24,3 +25,4 @@ node_js_path = "//prebuilts/ace-toolkit/nodejs/node-v12.18.4-linux-x64/bin/"
cjson_root = "//third_party/cJSON"
use_js_debug = false
enable_ace_debug = false

View File

@ -23,8 +23,8 @@ template("ace_base_platform_source_set") {
defines += invoker.defines
configs = [
"$ace_root:ace_config",
"$flutter_root:flutter_config",
"$flutter_root:icu_config_$platform",
"$ace_flutter_engine_root:flutter_config",
"$ace_flutter_engine_root:icu_config_$platform",
]
include_dirs = [ "//utils/native/base/include" ]
@ -34,8 +34,10 @@ template("ace_base_platform_source_set") {
"ace_res_key_parser.cpp",
"ace_trace.cpp",
"file_asset_provider.cpp",
"flutter_asset_manager.cpp",
"flutter_task_executor.cpp",
"localization.cpp",
"string_utils.cpp",
"thread_util.cpp",
]
if (is_standard_system) {
@ -72,14 +74,13 @@ template("libace_shared_library") {
"$ace_root/frameworks/core/accessibility:ace_accessibility_$platform",
]
if (link_qjs_engine) {
if (use_js_debug) {
deps += [ "$ace_root/frameworks/bridge:js_engine_debug_$platform" ]
} else {
deps += [
"$ace_root/frameworks/bridge:js_engine_$platform",
"$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform",
]
deps += [ "$ace_root/frameworks/bridge:js_engine_$platform",
"$ace_root/frameworks/bridge:js_backend_engine_$platform" ]
}
}
@ -137,7 +138,8 @@ template("ace_platform_engine") {
} else if (is_declarative) {
deps += [ "$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform" ]
} else {
deps += [ "$ace_root/frameworks/bridge:js_engine_$platform"]
deps += [ "$ace_root/frameworks/bridge:js_engine_$platform",
"$ace_root/frameworks/bridge:js_backend_engine_$platform"]
}
}
@ -169,6 +171,15 @@ ace_platform_engine("libace_engine_declarative_qjs") {
is_declarative = true
}
ace_platform_engine("libace_engine_pa_qjs") {
is_ohos_platform = true
use_quickjs_engine = true
if (is_standard_system) {
platform = "ohos"
}
is_declarative = false
}
ace_platform_engine("libace_engine_qjs_debug") {
is_ohos_platform = true
use_quickjs_engine = true

View File

@ -108,13 +108,18 @@ std::unique_ptr<fml::Mapping> FileAssetProvider::GetAsMapping(const std::string&
std::string FileAssetProvider::GetAssetPath(const std::string& assetName)
{
auto filePath = filePathMap_.find(assetName);
if (filePath == filePathMap_.end()) {
return "";
for (const auto& basePath: assetBasePaths_) {
std::string assetBasePath = packagePath_ + basePath;
std::string fileName = assetBasePath + assetName;
std::FILE* fp = std::fopen(fileName.c_str(), "r");
if (fp == nullptr) {
continue;
}
std::fclose(fp);
return assetBasePath;
}
std::string assetPath;
assetPath.append(packagePath_).append("!/").append(filePath->second);
return assetPath;
LOGE("Cannot find base path of %{public}s", assetName.c_str());
return "";
}
} // namespace OHOS::Ace

View File

@ -13,22 +13,21 @@
* limitations under the License.
*/
#include "core/components/box/box_base_element.h"
#include "core/components/box/box_base_component.h"
#include "adapter/common/cpp/flutter_asset_manager.h"
#include "adapter/common/cpp/file_asset_provider.h"
namespace OHOS::Ace {
void BoxBaseElement::PerformBuild()
std::string FlutterAssetManager::GetAssetPath(const std::string& assetName)
{
RefPtr<BoxBaseComponent> box = AceType::DynamicCast<BoxBaseComponent>(component_);
if (box) {
RefPtr<Component> newComponent = box->GetChild();
if (newComponent) {
const auto& child = children_.empty() ? nullptr : children_.front();
UpdateChild(child, newComponent);
for (const auto& provider : providers_) {
auto fileAssetProvider = static_cast<FileAssetProvider*>(provider.get());
std::string path = fileAssetProvider->GetAssetPath(assetName);
if (!path.empty()) {
return path;
}
}
return "";
}
} // namespace OHOS::Ace

View File

@ -47,7 +47,7 @@ private:
std::unique_ptr<fml::Mapping> mapping_;
};
class FlutterAssetManager final : public AssetManager {
class ACE_EXPORT FlutterAssetManager final : public AssetManager {
DECLARE_ACE_TYPE(FlutterAssetManager, AssetManager);
public:
@ -86,6 +86,8 @@ public:
return nullptr;
}
std::string GetAssetPath(const std::string& assetName) override;
private:
std::deque<std::unique_ptr<flutter::AssetResolver>> providers_;
};

View File

@ -76,6 +76,10 @@ FlutterTaskExecutor::~FlutterTaskExecutor()
void FlutterTaskExecutor::InitPlatformThread()
{
platformRunner_ = flutter::PlatformTaskRunnerAdapter::CurrentTaskRunner();
#ifdef ACE_DEBUG
FillTaskTypeTable(TaskType::PLATFORM);
#endif
}
void FlutterTaskExecutor::InitJsThread(bool newThread)
@ -86,6 +90,11 @@ void FlutterTaskExecutor::InitJsThread(bool newThread)
} else {
jsRunner_ = uiRunner_;
}
#ifdef ACE_DEBUG
PostTaskToTaskRunner(
jsRunner_, [weak = AceType::WeakClaim(this)] { FillTaskTypeTable(weak, TaskType::JS); }, 0);
#endif
}
void FlutterTaskExecutor::InitOtherThreads(const flutter::TaskRunners& taskRunners)
@ -98,6 +107,15 @@ void FlutterTaskExecutor::InitOtherThreads(const flutter::TaskRunners& taskRunne
uiRunner_, [] { SetThreadPriority(UI_THREAD_PRIORITY); }, 0);
PostTaskToTaskRunner(
gpuRunner_, [] { SetThreadPriority(GPU_THREAD_PRIORITY); }, 0);
#ifdef ACE_DEBUG
PostTaskToTaskRunner(
uiRunner_, [weak = AceType::WeakClaim(this)] { FillTaskTypeTable(weak, TaskType::UI); }, 0);
PostTaskToTaskRunner(
ioRunner_, [weak = AceType::WeakClaim(this)] { FillTaskTypeTable(weak, TaskType::IO); }, 0);
PostTaskToTaskRunner(
gpuRunner_, [weak = AceType::WeakClaim(this)] { FillTaskTypeTable(weak, TaskType::GPU); }, 0);
#endif
}
bool FlutterTaskExecutor::OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const
@ -152,4 +170,100 @@ void FlutterTaskExecutor::RemoveTaskObserver()
fml::MessageLoop::GetCurrent().RemoveTaskObserver(reinterpret_cast<intptr_t>(this));
}
#ifdef ACE_DEBUG
static const char* TaskTypeToString(TaskExecutor::TaskType type)
{
switch (type) {
case TaskExecutor::TaskType::PLATFORM:
return "PLATFORM";
case TaskExecutor::TaskType::UI:
return "UI";
case TaskExecutor::TaskType::IO:
return "IO";
case TaskExecutor::TaskType::GPU:
return "GPU";
case TaskExecutor::TaskType::JS:
return "JS";
case TaskExecutor::TaskType::BACKGROUND:
return "BACKGROUND";
case TaskExecutor::TaskType::UNKNOWN:
default:
return "UNKNOWN";
}
}
thread_local TaskExecutor::TaskType FlutterTaskExecutor::localTaskType = TaskExecutor::TaskType::UNKNOWN;
bool FlutterTaskExecutor::OnPreSyncTask(TaskType type) const
{
std::lock_guard<std::mutex> lock(tableMutex_);
auto it = taskTypeTable_.find(type);
// when task type not filled, just skip
if (it == taskTypeTable_.end()) {
return true;
}
auto itSync = syncTaskTable_.find(it->second.threadId);
while (itSync != syncTaskTable_.end()) {
if (itSync->second == std::this_thread::get_id()) {
DumpDeadSyncTask(localTaskType, type);
ACE_DCHECK(itSync->second != std::this_thread::get_id() && "DEAD LOCK HAPPENED !!!");
return false;
}
itSync = syncTaskTable_.find(itSync->second);
}
syncTaskTable_.emplace(std::this_thread::get_id(), it->second.threadId);
return true;
}
void FlutterTaskExecutor::OnPostSyncTask() const
{
std::lock_guard<std::mutex> lock(tableMutex_);
syncTaskTable_.erase(std::this_thread::get_id());
}
void FlutterTaskExecutor::DumpDeadSyncTask(TaskType from, TaskType to) const
{
auto itFrom = taskTypeTable_.find(from);
auto itTo = taskTypeTable_.find(to);
ACE_DCHECK(itFrom != taskTypeTable_.end());
ACE_DCHECK(itTo != taskTypeTable_.end());
LOGE("DEAD LOCK HAPPEN: %{public}s(%{public}d, %{public}s) -> %{public}s(%{public}d, %{public}s)",
TaskTypeToString(from), itFrom->second.tid, itFrom->second.threadName.c_str(),
TaskTypeToString(to), itTo->second.tid, itTo->second.threadName.c_str());
}
void FlutterTaskExecutor::FillTaskTypeTable(TaskType type)
{
constexpr size_t MAX_THREAD_NAME_SIZE = 32;
char threadNameBuf[MAX_THREAD_NAME_SIZE] = {0};
const char *threadName = threadNameBuf;
if (pthread_getname_np(pthread_self(), threadNameBuf, sizeof(threadNameBuf)) != 0) {
threadName = "unknown";
}
localTaskType = type;
ThreadInfo info = {
.threadId = std::this_thread::get_id(),
.tid = gettid(),
.threadName = threadName,
};
std::lock_guard<std::mutex> lock(tableMutex_);
taskTypeTable_.emplace(type, info);
}
void FlutterTaskExecutor::FillTaskTypeTable(const WeakPtr<FlutterTaskExecutor>& weak, TaskType type)
{
auto taskExecutor = weak.Upgrade();
if (taskExecutor) {
taskExecutor->FillTaskTypeTable(type);
}
}
#endif
} // namespace OHOS::Ace

View File

@ -16,6 +16,11 @@
#ifndef FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
#define FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
#ifdef ACE_DEBUG
#include <thread>
#include <unordered_map>
#endif
#include "flutter/common/task_runners.h"
#include "flutter/fml/thread.h"
@ -41,6 +46,27 @@ public:
private:
bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const final;
#ifdef ACE_DEBUG
bool OnPreSyncTask(TaskType type) const final;
void OnPostSyncTask() const final;
void DumpDeadSyncTask(TaskType from, TaskType to) const;
void FillTaskTypeTable(TaskType type);
static void FillTaskTypeTable(const WeakPtr<FlutterTaskExecutor>& weak, TaskType type);
struct ThreadInfo {
std::thread::id threadId;
int32_t tid = 0;
std::string threadName;
};
mutable std::mutex tableMutex_;
mutable std::unordered_map<std::thread::id, std::thread::id> syncTaskTable_;
std::unordered_map<TaskType, ThreadInfo> taskTypeTable_;
static thread_local TaskType localTaskType;
#endif
std::unique_ptr<fml::Thread> jsThread_;
fml::RefPtr<fml::TaskRunner> platformRunner_;

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021 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 "base/utils/string_utils.h"
#ifndef WINDOWS_PLATFORM
#include "securec.h"
#endif
namespace OHOS::Ace::StringUtils {
namespace {
const size_t MAX_STRING_SIZE = 256;
}
const std::string FormatString(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
char name[MAX_STRING_SIZE] = { 0 };
if (vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args) < 0) {
va_end(args);
return "";
}
va_end(args);
return name;
}
} // namespace OHOS::Ace::StringUtils

View File

@ -24,8 +24,11 @@ template("ace_base_platform_source_set") {
sources = [
"$ace_root/adapter/ohos/cpp/ace_ability.cpp",
"$ace_root/adapter/ohos/cpp/ace_service_ability.cpp",
"$ace_root/adapter/ohos/cpp/ace_data_ability.cpp",
"$ace_root/adapter/ohos/cpp/ace_application_info.cpp",
"$ace_root/adapter/ohos/cpp/ace_container.cpp",
"$ace_root/adapter/ohos/cpp/pa_container.cpp",
"$ace_root/adapter/ohos/cpp/flutter_ace_view.cpp",
]
@ -35,7 +38,12 @@ template("ace_base_platform_source_set") {
"$flutter_root:icu_config_$platform",
]
include_dirs = [ "//utils/native/base/include" ]
include_dirs = [
"//foundation/aafwk/standard/interfaces/kits/napi/aafwk/featureAbility",
"//foundation/ace/napi/interfaces/kits",
"//third_party/node/src",
"//utils/native/base/include",
]
deps = [
"$flutter_root:ace_skia_$platform",

View File

@ -15,6 +15,7 @@
#include "adapter/ohos/cpp/ace_ability.h"
#include "ability_process.h"
#include "adapter/ohos/cpp/ace_container.h"
#include "adapter/ohos/cpp/flutter_ace_view.h"
#include "base/log/log.h"
@ -65,6 +66,12 @@ FrontendType GetFrontendTypeFromManifest(const std::string& packagePathStr)
std::string jsonString(jsonStream.get(), jsonStream.get() + size);
auto rootJson = JsonUtil::ParseJsonString(jsonString);
auto mode = rootJson->GetObject("mode");
if (mode != nullptr) {
if (mode->GetString("syntax") == "ets" || mode->GetString("type") == "pageAbility") {
return FrontendType::DECLARATIVE_JS;
}
}
std::string frontendType = rootJson->GetString("type");
if (frontendType == "normal") {
return FrontendType::JS;
@ -201,9 +208,10 @@ void AceAbility::OnStart(const Want& want)
parsedPageUrl = "";
}
// set window id
auto context = Platform::AceContainer::GetContainer(abilityId_)->GetPipelineContext();
if (context != nullptr) {
context->SetWindowId(window->GetWindowID());
context->SetWindowId(window->GetWindowID());
}
// run page.
@ -295,5 +303,20 @@ void AceAbility::OnConfigurationUpdated(const Configuration& configuration)
LOGI("AceAbility::OnConfigurationUpdated called End");
}
void AceAbility::OnAbilityResult(int requestCode, int resultCode, const OHOS::AAFwk::Want& resultData)
{
LOGI("AceAbility::OnAbilityResult called ");
AbilityProcess::GetInstance()->OnAbilityResult(this, requestCode, resultCode, resultData);
LOGI("AceAbility::OnAbilityResult called End");
}
void AceAbility::OnRequestPermissionsFromUserResult(
int requestCode, const std::vector<std::string> &permissions, const std::vector<int> &grantResults)
{
LOGI("AceAbility::OnRequestPermissionsFromUserResult called ");
AbilityProcess::GetInstance()->OnRequestPermissionsFromUserResult(this, requestCode, permissions, grantResults);
LOGI("AceAbility::OnRequestPermissionsFromUserResult called End");
}
}
} // namespace OHOS::Ace

View File

@ -16,6 +16,8 @@
#ifndef FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
#define FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
#include <string>
#include <vector>
#include "ability.h"
#include "ability_loader.h"
#include "want.h"
@ -42,6 +44,9 @@ public:
void OnRestoreAbilityState(const OHOS::AppExecFwk::PacMap& inState) override;
void OnSaveAbilityState(OHOS::AppExecFwk::PacMap& outState) override;
void OnConfigurationUpdated(const OHOS::AppExecFwk::Configuration& configuration) override;
void OnAbilityResult(int requestCode, int resultCode, const OHOS::AAFwk::Want& resultData) override;
void OnRequestPermissionsFromUserResult(
int requestCode, const std::vector<std::string> &permissions, const std::vector<int> &grantResults) override;
private:
static int32_t instanceId_;

0
adapter/ohos/cpp/ace_application_info.cpp Executable file → Normal file
View File

26
adapter/ohos/cpp/ace_application_info.h Executable file → Normal file
View File

@ -38,13 +38,33 @@ public:
void ChangeLocale(const std::string& language, const std::string& countryOrRegion) override;
std::vector<std::string> GetLocaleFallback(const std::vector<std::string>& localeList) const override;
std::vector<std::string> GetResourceFallback(const std::vector<std::string>& resourceList) const override;
double GetLifeTime() const override { return 0.0f; }
std::string GetCurrentDeviceResTag() const override;
std::vector<std::string> GetStyleResourceFallback(const std::vector<std::string>& resourceList) const override
{
return std::vector<std::string>();
}
std::vector<std::string> GetDeclarativeResourceFallback(const std::set<std::string>& resourceList) const override
{
std::vector<std::string> vector;
return vector;
}
bool GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const override;
bool GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo) override;
double GetLifeTime() const override
{
return 0.0;
}
std::string GetJsEngineParam(const std::string& key) const override;
std::string GetCurrentDeviceResTag() const override;
std::string GetCurrentDeviceDeclarativeResTag() const override
{
return std::string();
}
double GetTargetMediaScaleRatio(const std::string& targetResTag) const override
{
return 1.0;
}
void SetJsEngineParam(const std::string& key, const std::string& value);

View File

@ -51,11 +51,30 @@ AceContainer::AceContainer(int32_t instanceId, FrontendType type, AceAbility* ac
flutterTaskExecutor->InitPlatformThread();
flutterTaskExecutor->InitJsThread();
taskExecutor_ = flutterTaskExecutor;
if (type_ != FrontendType::DECLARATIVE_JS) {
InitializeFrontend();
taskExecutor_->PostTask([id = instanceId_]() { Container::InitForThread(id); }, TaskExecutor::TaskType::JS);
platformEventCallback_ = std::move(callback);
}
void AceContainer::Initialize()
{
InitializeFrontend();
}
void AceContainer::Destroy()
{
if (pipelineContext_ && taskExecutor_) {
if (taskExecutor_) {
taskExecutor_->PostTask([context = pipelineContext_]() { context->Destroy(); }, TaskExecutor::TaskType::UI);
}
}
if (frontend_) {
frontend_->UpdateState(Frontend::State::ON_DESTROY);
}
platformEventCallback_ = std::move(callback);
resRegister_.Reset();
assetManager_.Reset();
frontend_.Reset();
pipelineContext_.Reset();
}
void AceContainer::InitializeFrontend()
@ -67,10 +86,15 @@ void AceContainer::InitializeFrontend()
jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
jsFrontend->SetAbility(aceAbility_);
} else if (type_ == FrontendType::JS_CARD) {
AceApplicationInfo::GetInstance().SetCardType();
frontend_ = AceType::MakeRefPtr<CardFrontend>();
} else if (type_ == FrontendType::DECLARATIVE_JS) {
frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
declarativeFrontend->SetJsEngine(Framework::JsEngineLoader::GetDeclarative().CreateJsEngine(instanceId_));
declarativeFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
declarativeFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
} else {
LOGE("Frontend type not supported");
EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR);
@ -286,16 +310,6 @@ void AceContainer::InitializeCallback()
[context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
};
aceView_->RegisterIdleCallback(idleCallback);
auto&& viewDestoryCallback = [context = pipelineContext_](AceView::ViewReleaseCallback&& callback) {
context->GetTaskExecutor()->PostTask(
[context, callback = std::move(callback)]() {
context->GetTaskExecutor()->PostTask(
[callback = std::move(callback)]() { callback(); }, TaskExecutor::TaskType::PLATFORM);
},
TaskExecutor::TaskType::UI);
};
aceView_->RegisterViewDestroyCallback(viewDestoryCallback);
}
void AceContainer::CreateContainer(int32_t instanceId, FrontendType type, AceAbility* aceAbility,
@ -303,6 +317,7 @@ void AceContainer::CreateContainer(int32_t instanceId, FrontendType type, AceAbi
{
auto aceContainer = AceType::MakeRefPtr<AceContainer>(instanceId, type, aceAbility, std::move(callback));
AceEngine::Get().AddContainer(instanceId, aceContainer);
aceContainer->Initialize();
auto front = aceContainer->GetFrontend();
if (front) {
front->UpdateState(Frontend::State::ON_CREATE);
@ -312,24 +327,18 @@ void AceContainer::CreateContainer(int32_t instanceId, FrontendType type, AceAbi
void AceContainer::DestroyContainer(int32_t instanceId)
{
LOGI("DestroyContainer with id %{private}d", instanceId);
auto container = AceEngine::Get().GetContainer(instanceId);
if (!container) {
LOGE("no AceContainer with id %{private}d", instanceId);
LOGE("no AceContainer with id %{private}d in AceEngine", instanceId);
return;
}
auto context = container->GetPipelineContext();
if (context) {
auto taskExecutor = context->GetTaskExecutor();
if (taskExecutor) {
taskExecutor->PostTask([context]() { context->Destroy(); }, TaskExecutor::TaskType::UI);
}
container->Destroy();
auto taskExecutor = container->GetTaskExecutor();
if (taskExecutor) {
taskExecutor->PostSyncTask([] { LOGI("Wait UI thread..."); }, TaskExecutor::TaskType::UI);
taskExecutor->PostSyncTask([] { LOGI("Wait JS thread..."); }, TaskExecutor::TaskType::JS);
}
AceEngine::Get().RemoveContainer(instanceId);
auto front = container->GetFrontend();
if (front) {
front->UpdateState(Frontend::State::ON_DESTROY);
}
}
void AceContainer::SetView(AceView* view, double density, int32_t width, int32_t height)
@ -445,9 +454,7 @@ void AceContainer::AddAssetPath(
} else {
flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
container->assetManager_ = flutterAssetManager;
if (container->type_ != FrontendType::DECLARATIVE_JS) {
container->frontend_->SetAssetManager(flutterAssetManager);
}
container->frontend_->SetAssetManager(flutterAssetManager);
}
if (flutterAssetManager && !packagePath.empty()) {
auto assetProvider = std::make_unique<FileAssetProvider>();
@ -467,19 +474,6 @@ void AceContainer::AttachView(
ACE_DCHECK(state != nullptr);
auto flutterTaskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(taskExecutor_);
flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners());
if (type_ == FrontendType::DECLARATIVE_JS) {
// For DECLARATIVE_JS or UJOINT_JS frontend display UI in JS thread temporarily.
flutterTaskExecutor->InitJsThread(false);
InitializeFrontend();
auto front = GetFrontend();
if (front) {
front->UpdateState(Frontend::State::ON_CREATE);
front->SetJsMessageDispatcher(AceType::Claim(this));
front->SetAssetManager(assetManager_);
}
}
resRegister_ = aceView_->GetPlatformResRegister();
pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(std::move(window),
taskExecutor_,

View File

@ -36,6 +36,10 @@ public:
std::unique_ptr<PlatformEventCallback> callback);
~AceContainer() override = default;
void Initialize() override;
void Destroy() override;
static bool Register();
int32_t GetInstanceId() const override
@ -89,6 +93,10 @@ public:
void Dispatch(
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const override;
void DispatchSync(
const std::string& group, std::vector<uint8_t>&& data, uint8_t** resData, long& position) const override
{}
void DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override;
bool Dump(const std::vector<std::string>& params) override;

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2021 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/ohos/cpp/ace_data_ability.h"
#include "adapter/ohos/cpp/pa_container.h"
#include "adapter/ohos/cpp/platform_event_callback.h"
#include "base/log/log.h"
#include "core/common/backend.h"
#include "frameworks/bridge/pa_backend/pa_backend.h"
#include "res_config.h"
#include "resource_manager.h"
namespace OHOS {
namespace Ace {
using namespace OHOS::AAFwk;
using namespace OHOS::AppExecFwk;
using DataPlatformFinish = std::function<void()>;
class DataPlatformEventCallback final : public Platform::PlatformEventCallback {
public:
explicit DataPlatformEventCallback(DataPlatformFinish onFinish) : onFinish_(onFinish) {}
~DataPlatformEventCallback() = default;
virtual void OnFinish() const
{
LOGI("DataPlatformEventCallback OnFinish");
if (onFinish_) {
onFinish_();
}
}
virtual void OnStatusBarBgColorChanged(uint32_t color)
{
LOGI("DataPlatformEventCallback OnStatusBarBgColorChanged");
}
private:
DataPlatformFinish onFinish_;
};
int32_t AceDataAbility::instanceId_ = 0;
const std::string AceDataAbility::START_PARAMS_KEY = "__startParams";
const std::string AceDataAbility::URI = "url";
REGISTER_AA(AceDataAbility)
void AceDataAbility::OnStart(const OHOS::AAFwk::Want &want)
{
Ability::OnStart(want);
LOGI("AceDataAbility::OnStart called");
// get url
std::string parsedUrl;
if (want.HasParameter(URI)) {
parsedUrl = want.GetStringParam(URI);
} else {
parsedUrl = "data.js";
}
// init data ability
BackendType backendType = BackendType::DATA;
Platform::PaContainer::CreateContainer(
abilityId_, backendType, this,
std::make_unique<DataPlatformEventCallback>([this]() {
TerminateAbility();
}));
// get asset
auto packagePathStr = GetBundleCodePath();
auto moduleInfo = GetHapModuleInfo();
if (moduleInfo != nullptr) {
packagePathStr += "/" + moduleInfo->name + "/";
}
auto assetBasePathStr = {std::string("assets/js/default/"), std::string("assets/js/share/")};
Platform::PaContainer::AddAssetPath(abilityId_, packagePathStr, assetBasePathStr);
// run data ability
Platform::PaContainer::RunPa(
abilityId_, parsedUrl, want.GetStringParam(START_PARAMS_KEY));
LOGI("AceDataAbility::OnStart called End");
}
void AceDataAbility::OnStop()
{
LOGI("AceDataAbility::OnStop called ");
Ability::OnStop();
Platform::PaContainer::DestroyContainer(abilityId_);
LOGI("AceDataAbility::OnStop called End");
}
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_DATA_ABILITY_H
#define FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_DATA_ABILITY_H
#include <string>
#include <vector>
#include "ability.h"
#include "ability_loader.h"
#include "want.h"
#include "iremote_object.h"
namespace OHOS::Ace {
class AceDataAbility final : public OHOS::AppExecFwk::Ability {
public:
AceDataAbility()
{
abilityId_ = instanceId_;
instanceId_++;
}
virtual ~AceDataAbility() = default;
void OnStart(const OHOS::AAFwk::Want& want) override;
void OnStop() override;
private:
int32_t abilityId_ = 0;
static int32_t instanceId_;
static const std::string START_PARAMS_KEY;
static const std::string URI;
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_DATA_ABILITY_H

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2021 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/ohos/cpp/ace_service_ability.h"
#include "adapter/ohos/cpp/pa_container.h"
#include "adapter/ohos/cpp/platform_event_callback.h"
#include "base/log/log.h"
#include "core/common/backend.h"
#include "frameworks/bridge/pa_backend/pa_backend.h"
#include "res_config.h"
#include "resource_manager.h"
namespace OHOS {
namespace Ace {
using namespace OHOS::AAFwk;
using namespace OHOS::AppExecFwk;
using ServicePlatformFinish = std::function<void()>;
class ServicePlatformEventCallback final : public Platform::PlatformEventCallback {
public:
explicit ServicePlatformEventCallback(ServicePlatformFinish onFinish) : onFinish_(onFinish) {}
~ServicePlatformEventCallback() = default;
virtual void OnFinish() const
{
LOGI("ServicePlatformEventCallback OnFinish");
if (onFinish_) {
onFinish_();
}
}
virtual void OnStatusBarBgColorChanged(uint32_t color)
{
LOGI("ServicePlatformEventCallback OnStatusBarBgColorChanged");
}
private:
ServicePlatformFinish onFinish_;
};
int32_t AceServiceAbility::instanceId_ = 0;
const std::string AceServiceAbility::START_PARAMS_KEY = "__startParams";
const std::string AceServiceAbility::URI = "url";
REGISTER_AA(AceServiceAbility)
void AceServiceAbility::OnStart(const OHOS::AAFwk::Want &want)
{
Ability::OnStart(want);
LOGI("AceServiceAbility::OnStart called");
// get url
std::string parsedUrl;
if (want.HasParameter(URI)) {
parsedUrl = want.GetStringParam(URI);
} else {
parsedUrl = "service.js";
}
// init service
BackendType backendType = BackendType::SERVICE;
Platform::PaContainer::CreateContainer(
abilityId_, backendType, this,
std::make_unique<ServicePlatformEventCallback>([this]() {
TerminateAbility();
}));
// get asset
auto packagePathStr = GetBundleCodePath();
auto moduleInfo = GetHapModuleInfo();
if (moduleInfo != nullptr) {
packagePathStr += "/" + moduleInfo->name + "/";
}
auto assetBasePathStr = {std::string("assets/js/default/"), std::string("assets/js/share/")};
Platform::PaContainer::AddAssetPath(abilityId_, packagePathStr, assetBasePathStr);
// run service
Platform::PaContainer::RunPa(
abilityId_, parsedUrl, want.GetStringParam(START_PARAMS_KEY));
LOGI("AceServiceAbility::OnStart called End");
}
void AceServiceAbility::OnStop()
{
LOGI("AceServiceAbility::OnStop called ");
Ability::OnStop();
Platform::PaContainer::DestroyContainer(abilityId_);
LOGI("AceServiceAbility::OnStop called End");
}
sptr<IRemoteObject> AceServiceAbility::OnConnet(const Want &want)
{
LOGI("AceServiceAbility::OnConnet");
return nullptr;
}
void AceServiceAbility::OnDisconnect(const Want &want)
{
LOGI("AceServiceAbility::OnDisconnect");
}
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_SERVICE_ABILITY_H
#define FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_SERVICE_ABILITY_H
#include <string>
#include <vector>
#include "ability.h"
#include "ability_loader.h"
#include "want.h"
#include "iremote_object.h"
namespace OHOS::Ace {
class AceServiceAbility final : public OHOS::AppExecFwk::Ability {
public:
AceServiceAbility()
{
abilityId_ = instanceId_;
instanceId_++;
}
virtual ~AceServiceAbility() = default;
void OnStart(const OHOS::AAFwk::Want& want) override;
void OnStop() override;
sptr<IRemoteObject> OnConnet(const OHOS::AAFwk::Want &want);
void OnDisconnect(const OHOS::AAFwk::Want &want) override;
private:
int32_t abilityId_ = 0;
static int32_t instanceId_;
static const std::string START_PARAMS_KEY;
static const std::string URI;
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_SERVICE_ABILITY_H

View File

@ -177,7 +177,7 @@ void FlutterAceView::SurfaceChanged(FlutterAceView* view, int32_t width, int32_t
view->NotifySurfaceChanged(width, height);
auto platformView = view->GetShellHolder()->GetPlatformView();
LOGI("FlutterAceView::SurfaceChanged GetPlatformView");
LOGI("FlutterAceView::SurfaceChanged, GetPlatformView");
if (platformView) {
LOGI("FlutterAceView::SurfaceChanged, call NotifyChanged");
platformView->NotifyChanged(SkISize::Make(width, height));

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2021 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/common/cpp/file_asset_provider.h"
#include "adapter/ohos/cpp/ace_application_info.h"
#include "adapter/ohos/cpp/pa_container.h"
#include "base/log/ace_trace.h"
#include "base/log/event_report.h"
#include "base/log/log.h"
#include "base/utils/system_properties.h"
#include "base/utils/utils.h"
#include "base/watch_dog/watch_dog.h"
#include "core/common/ace_engine.h"
#include "core/common/platform_window.h"
#include "core/common/text_field_manager.h"
#include "core/common/window.h"
#include "frameworks/bridge/pa_backend/engine/common/js_backend_engine_loader.h"
#include "frameworks/bridge/pa_backend/pa_backend.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "adapter/common/cpp/flutter_asset_manager.h"
#include "adapter/common/cpp/flutter_task_executor.h"
namespace OHOS::Ace::Platform {
PaContainer::PaContainer(int32_t instanceId, BackendType type, void* paAbility,
std::unique_ptr<PlatformEventCallback> callback) : instanceId_(instanceId), type_(type),
paAbility_(paAbility)
{
ACE_DCHECK(callback);
auto flutterTaskExecutor = Referenced::MakeRefPtr<FlutterTaskExecutor>();
flutterTaskExecutor->InitPlatformThread();
flutterTaskExecutor->InitJsThread();
taskExecutor_ = flutterTaskExecutor;
InitializeBackend();
platformEventCallback_ = std::move(callback);
}
void PaContainer::InitializeBackend()
{
// create backend
backend_ = Backend::Create();
auto paBackend = AceType::DynamicCast<PaBackend>(backend_);
// set JS engineinit in JS thread
paBackend->SetJsEngine(Framework::JsBackendEngineLoader::Get().CreateJsBackendEngine(instanceId_));
paBackend->SetAbility(paAbility_);
ACE_DCHECK(backend_);
backend_->Initialize(type_, taskExecutor_);
}
RefPtr<PaContainer> PaContainer::GetContainer(int32_t instanceId)
{
auto container = AceEngine::Get().GetContainer(instanceId);
if (container != nullptr) {
auto aceContainer = AceType::DynamicCast<PaContainer>(container);
return aceContainer;
} else {
return nullptr;
}
}
void PaContainer::CreateContainer(int32_t instanceId, BackendType type, void* paAbility,
std::unique_ptr<PlatformEventCallback> callback)
{
auto aceContainer = AceType::MakeRefPtr<PaContainer>(instanceId, type, paAbility,
std::move(callback));
AceEngine::Get().AddContainer(instanceId, aceContainer);
auto back = aceContainer->GetBackend();
if (back) {
back->UpdateState(Backend::State::ON_CREATE);
back->SetJsMessageDispatcher(aceContainer);
}
}
bool PaContainer::RunPa(int32_t instanceId, const std::string &content, const std::string &params)
{
auto container = AceEngine::Get().GetContainer(instanceId);
if (!container) {
return false;
}
auto aceContainer = AceType::DynamicCast<PaContainer>(container);
auto back = aceContainer->GetBackend();
if (back) {
auto paBackend = AceType::DynamicCast<PaBackend>(back);
paBackend->RunPa(content, params);
return true;
}
return false;
}
void PaContainer::DestroyContainer(int32_t instanceId)
{
LOGI("DestroyContainer with id %{private}d", instanceId);
auto container = AceEngine::Get().GetContainer(instanceId);
if (!container) {
LOGE("no AceContainer with id %{private}d", instanceId);
return;
}
auto aceContainer = AceType::DynamicCast<PaContainer>(container);
auto back = aceContainer->GetBackend();
if (back) {
back->UpdateState(Backend::State::ON_DESTROY);
}
return;
}
void PaContainer::AddAssetPath(
int32_t instanceId, const std::string &packagePath, const std::vector<std::string> &paths)
{
auto container = AceType::DynamicCast<PaContainer>(AceEngine::Get().GetContainer(instanceId));
if (!container) {
return;
}
AceEngine::Get().SetPackagePath(packagePath);
for (auto path : paths) {
AceEngine::Get().SetAssetBasePath(path);
}
RefPtr<FlutterAssetManager> flutterAssetManager;
if (container->assetManager_) {
flutterAssetManager = AceType::DynamicCast<FlutterAssetManager>(container->assetManager_);
} else {
flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
container->assetManager_ = flutterAssetManager;
AceType::DynamicCast<PaBackend>(container->GetBackend())->SetAssetManager(flutterAssetManager);
}
if (flutterAssetManager && !packagePath.empty()) {
auto assetProvider = std::make_unique<FileAssetProvider>();
if (assetProvider->Initialize(packagePath, paths)) {
LOGI("Push AssetProvider to queue.");
flutterAssetManager->PushBack(std::move(assetProvider));
}
}
}
void PaContainer::Dispatch(
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
{
return;
}
void PaContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
{
return;
}
bool PaContainer::Dump(const std::vector<std::string> &params)
{
return false;
}
} // namespace OHOS::Ace::Platform

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_PA_CONTAINER_H
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_PA_CONTAINER_H
#include <memory>
#include "adapter/ohos/cpp/platform_event_callback.h"
#include "base/resource/asset_manager.h"
#include "base/thread/task_executor.h"
#include "base/utils/noncopyable.h"
#include "core/common/ace_view.h"
#include "core/common/container.h"
#include "core/common/js_message_dispatcher.h"
#include "frameworks/core/common/backend.h"
namespace OHOS::Ace::Platform {
class PaContainer : public Container, public JsMessageDispatcher {
DECLARE_ACE_TYPE(PaContainer, Container, JsMessageDispatcher);
public:
PaContainer(int32_t instanceId, BackendType type, void* paAbility,
std::unique_ptr<PlatformEventCallback> callback);
~PaContainer() override = default;
void Initialize() override {}
void Destroy() override {}
int32_t GetInstanceId() const override
{
return instanceId_;
}
RefPtr<AssetManager> GetAssetManager() const override
{
return assetManager_;
}
RefPtr<Frontend> GetFrontend() const override
{
return nullptr;
}
RefPtr<PlatformResRegister> GetPlatformResRegister() const override
{
return nullptr;
}
RefPtr<PipelineContext> GetPipelineContext() const override
{
return nullptr;
}
RefPtr<Backend> GetBackend() const
{
return backend_;
}
RefPtr<TaskExecutor> GetTaskExecutor() const override
{
return taskExecutor_;
}
void Dispatch(
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const override;
void DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override;
void DispatchSync(
const std::string &group, std::vector<uint8_t> &&data, uint8_t **resData, long &position) const override
{}
bool Dump(const std::vector<std::string>& params) override;
void OnFinish()
{
if (platformEventCallback_) {
platformEventCallback_->OnFinish();
}
}
std::string GetHostClassName() const override
{
return "";
}
static bool Register();
static void CreateContainer(int32_t instanceId, BackendType type, void* paAbility,
std::unique_ptr<PlatformEventCallback> callback);
static void DestroyContainer(int32_t instanceId);
static RefPtr<PaContainer> GetContainer(int32_t instanceId);
static bool RunPa(int32_t instanceId, const std::string &content, const std::string &params);
static void AddAssetPath(int32_t instanceId, const std::string &packagePath, const std::vector<std::string> &paths);
private:
void InitializeBackend();
void InitializeCallback();
RefPtr<TaskExecutor> taskExecutor_;
RefPtr<AssetManager> assetManager_;
RefPtr<Backend> backend_;
int32_t instanceId_ = 0;
BackendType type_ = BackendType::SERVICE;
std::unique_ptr<PlatformEventCallback> platformEventCallback_;
void *paAbility_ = nullptr;
ACE_DISALLOW_COPY_AND_MOVE(PaContainer);
};
} // namespace OHOS::Ace::Platform
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_PA_CONTAINER_H

View File

@ -29,7 +29,7 @@ template("ace_osal_ohos_source_set") {
configs = [
"//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara_config",
"$ace_root:ace_config",
"$flutter_root:flutter_config",
"$ace_flutter_engine_root:flutter_config",
]
}
include_dirs = [ "//utils/native/base/include" ]

View File

@ -29,6 +29,7 @@ namespace {
constexpr char EVENT_KEY_ERROR_TYPE[] = "ERROR_TYPE";
constexpr char EVENT_KEY_UID[] = "UID";
constexpr char EVENT_KEY_SESSIONID[] = "SESSION_ID";
constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME";
constexpr char EVENT_KEY_MESSAGE[] = "MESSAGE";
@ -37,13 +38,11 @@ constexpr char EVENT_KEY_TIME[] = "TIME";
constexpr char EVENT_KEY_JS_ERR_RAW_CODE[] = "JS_ERR_RAW_CODE";
constexpr char EVENT_KEY_REASON[] = "REASON";
constexpr char EVENT_KEY_SUMMARY[] = "SUMMARY";
constexpr char EVENT_NAME_JS_ERROR[] = "JS_ERROR";
constexpr char STATISTIC_DURATION[] = "DURATION";
constexpr int32_t MAX_PACKAGE_NAME_LENGTH = 128;
constexpr int32_t JS_CRASH_RAW_EVENT_ID = 5002;
constexpr int32_t JS_ERR_RAW_CODE = 3;
constexpr int32_t UIP_WARNING_EVENT_ID = 10257;
constexpr int32_t UIP_FREEZE_EVENT_ID = 10258;
constexpr int32_t UIP_RECOVER_EVENT_ID = 10280;
constexpr char DUMP_LOG_COMMAND[] = "B";
@ -62,12 +61,23 @@ void EventReport::SendEvent(const EventInfo& eventInfo)
if (packageName.size() > MAX_PACKAGE_NAME_LENGTH) {
StrTrim(packageName);
}
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(eventInfo.eventType),
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventInfo.eventType,
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
EVENT_KEY_ERROR_TYPE, eventInfo.errorType,
EVENT_KEY_PACKAGE_NAME, packageName);
}
void EventReport::SendJsCardRenderTimeEvent(
const std::string& sessionID,
const std::string& timeType,
uint64_t timeDelay)
{
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, timeType,
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
EVENT_KEY_SESSIONID, sessionID,
STATISTIC_DURATION, timeDelay);
}
void EventReport::SendAppStartException(AppStartExcepType type)
{
EventInfo eventInfo = {
@ -190,7 +200,7 @@ void EventReport::JsEventReport(int32_t eventType, const std::string& jsonStr)
void EventReport::JsErrReport(
int32_t uid, const std::string& packageName, const std::string& reason, const std::string& summary)
{
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(JS_CRASH_RAW_EVENT_ID),
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, EVENT_NAME_JS_ERROR,
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
EVENT_KEY_TIME, std::to_string((int32_t)std::time(nullptr)),
EVENT_KEY_UID, std::to_string(uid),
@ -204,20 +214,19 @@ void EventReport::ANRRawReport(RawEventType type, int32_t uid, const std::string
const std::string& processName, const std::string& msg)
{
int32_t pid = getpid();
int32_t eventId = 0;
std::string cmd = " ";
std::string eventName = "";
if (type == RawEventType::WARNING) {
eventId = UIP_WARNING_EVENT_ID;
eventName = "UI_BLOCK_3S";
cmd = "p=" + std::to_string(pid);
} else if (type == RawEventType::FREEZE) {
eventId = UIP_FREEZE_EVENT_ID;
eventName = "UI_BLOCK_6S";
cmd = DUMP_LOG_COMMAND;
} else {
eventId = UIP_RECOVER_EVENT_ID;
eventName = "UI_BLOCK_RECOVERED";
}
std::string eventIdStr = std::to_string(eventId);
std::string uidStr = std::to_string(uid);
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventIdStr,
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventName,
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
EVENT_KEY_UID, uidStr,
EVENT_KEY_PACKAGE_NAME, packageName,
@ -230,7 +239,7 @@ void EventReport::SendEventInner(const EventInfo& eventInfo)
{
auto packageName = AceEngine::Get().GetPackageName();
StrTrim(packageName);
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(eventInfo.eventType),
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventInfo.eventType,
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
EVENT_KEY_ERROR_TYPE, eventInfo.errorType,
EVENT_KEY_PACKAGE_NAME, packageName);

View File

@ -43,6 +43,11 @@ public:
{
return nullptr;
}
std::string GetAssetPath(const std::string& assetName) override
{
return "";
}
};
} // namespace OHOS::Ace

View File

@ -45,6 +45,11 @@ constexpr uint32_t LOG_DOMAINS[] = {
0xD003B00,
};
constexpr LogType LOG_TYPES[] = {
LOG_CORE,
LOG_APP,
};
}
// initial static member object
@ -57,8 +62,8 @@ char LogWrapper::GetSeparatorCharacter()
void LogWrapper::PrintLog(LogDomain domain, LogLevel level, const char* fmt, va_list args)
{
HiLogPrintArgs(LOG_CORE, LOG_LEVELS[static_cast<uint32_t>(level)], LOG_DOMAINS[static_cast<uint32_t>(domain)],
LOG_TAGS[static_cast<uint32_t>(domain)], fmt, args);
HiLogPrintArgs(LOG_TYPES[static_cast<uint32_t>(domain)], LOG_LEVELS[static_cast<uint32_t>(level)],
LOG_DOMAINS[static_cast<uint32_t>(domain)], LOG_TAGS[static_cast<uint32_t>(domain)], fmt, args);
}
} // namespace OHOS::Ace

View File

@ -65,6 +65,8 @@ std::string SystemProperties::paramDeviceType_ = INVALID_PARAM;
int32_t SystemProperties::mcc_ = MCC_UNDEFINED;
int32_t SystemProperties::mnc_ = MNC_UNDEFINED;
ColorMode SystemProperties::colorMode_ { ColorMode::LIGHT };
ScreenShape SystemProperties::screenShape_ { ScreenShape::NOT_ROUND };
LongScreenType SystemProperties::LongScreen_ { LongScreenType::NOT_LONG };
void SystemProperties::UpdateSurfaceStatus(int32_t width, int32_t height)
{
@ -101,7 +103,7 @@ void SystemProperties::InitDeviceTypeBySystemProperty()
void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight, int32_t orientation,
double resolution, bool isRound)
{
// SetDeviceOrientation should be eralier than deviceWidth/deviceHeight init.
// SetDeviceOrientation should be earlier than deviceWidth/deviceHeight init.
SetDeviceOrientation(orientation);
isRound_ = isRound;
@ -116,6 +118,12 @@ void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight,
releaseType_ = system::GetParameter("hw_sc.build.os.releasetype", INVALID_PARAM);
paramDeviceType_ = system::GetParameter("hw_sc.build.os.devicetype", INVALID_PARAM);
if (isRound_) {
screenShape_ = ScreenShape::ROUND;
} else {
screenShape_ = ScreenShape::NOT_ROUND;
}
InitDeviceTypeBySystemProperty();
}

View File

@ -23,9 +23,12 @@ template("libace_engine") {
"$ace_root/adapter/common/cpp/ace_res_config.cpp",
"$ace_root/adapter/common/cpp/ace_res_key_parser.cpp",
"$ace_root/adapter/common/cpp/ace_trace.cpp",
"$ace_root/adapter/common/cpp/flutter_asset_manager.cpp",
"$ace_root/adapter/common/cpp/localization.cpp",
"$ace_root/adapter/common/cpp/thread_util.cpp",
"$ace_root/adapter/preview/osal/download_manager.cpp",
"$ace_root/adapter/preview/osal/fetch_manager.cpp",
"$ace_root/adapter/preview/osal/response_data.cpp",
"ace_ability.cpp",
"ace_application_info.cpp",
"ace_container.cpp",
@ -36,18 +39,20 @@ template("libace_engine") {
configs = [
"$ace_root:ace_config",
"$flutter_root:flutter_config",
"$flutter_root:flutter_glfw_config",
"$flutter_root:icu_config_$platform",
"$ace_flutter_engine_root:flutter_config",
"$ace_flutter_engine_root:flutter_glfw_config",
"$ace_flutter_engine_root:icu_config_$platform",
"//third_party/curl:curl_config",
"//third_party/zlib:zlib_config",
]
cflags = [ "-std=c++17" ]
deps = [
"$ace_flutter_engine_root:ace_skia_$platform",
"$ace_root/frameworks/base:ace_base_$platform",
"$ace_root/frameworks/bridge:declarative_js_engine_$platform",
"$ace_root/frameworks/bridge:js_engine_$platform",
"$ace_root/frameworks/core:ace_core_$platform",
"$flutter_root:ace_skia_$platform",
"//third_party/curl:curl",
]
if (platform == "windows") {

View File

@ -30,13 +30,9 @@ std::atomic<bool> AceAbility::loopRunning_ = true;
namespace {
// JS frontend maintain the page ID self, so it's useless to pass page ID from platform
// layer, neither OpenHarmony or Windows.
// layer, neither OpenHarmony or Windows, we should delete here usage when Java delete it.
constexpr int32_t UNUSED_PAGE_ID = 1;
// Different with mobile, we don't support multi-instances in Windows, because we only want
// preivew UI effect, it doesn't make scense to create multi ability in one process.
constexpr int32_t ACE_INSTANCE_ID = 0;
constexpr char ASSET_PATH_SHARE[] = "share";
#ifdef WINDOWS_PLATFORM
constexpr char DELIMITER[] = "\\";
@ -87,12 +83,10 @@ bool AceAbility::DispatchTouchEvent(const TouchPoint& event)
std::promise<bool> touchPromise;
std::future<bool> touchFuture = touchPromise.get_future();
container->GetTaskExecutor()->PostTask(
[aceView, event, &touchPromise]() {
bool isHandled = aceView->HandleTouchEvent(event);
touchPromise.set_value(isHandled);
},
TaskExecutor::TaskType::PLATFORM);
container->GetTaskExecutor()->PostTask([aceView, event, &touchPromise]() {
bool isHandled = aceView->HandleTouchEvent(event);
touchPromise.set_value(isHandled);
}, TaskExecutor::TaskType::PLATFORM);
return touchFuture.get();
}
@ -111,33 +105,43 @@ bool AceAbility::DispatchBackPressedEvent()
std::promise<bool> backPromise;
std::future<bool> backFuture = backPromise.get_future();
container->GetTaskExecutor()->PostTask(
[container, context, &backPromise]() {
bool canBack = false;
if (context->IsLastPage()) {
LOGW("Can't back because this is the last page!");
} else {
canBack = context->CallRouterBackToPopPage();
}
backPromise.set_value(canBack);
},
TaskExecutor::TaskType::PLATFORM);
auto weak = AceType::WeakClaim(AceType::RawPtr(context));
container->GetTaskExecutor()->PostTask([weak, &backPromise]() {
auto context = weak.Upgrade();
if (context == nullptr) {
LOGW("context is nullptr.");
return;
}
bool canBack = false;
if (context->IsLastPage()) {
LOGW("Can't back because this is the last page!");
} else {
canBack = context->CallRouterBackToPopPage();
}
backPromise.set_value(canBack);
}, TaskExecutor::TaskType::PLATFORM);
return backFuture.get();
}
AceAbility::AceAbility(const AceRunArgs& runArgs) : runArgs_(runArgs)
{
SystemProperties::InitDeviceInfo(runArgs_.deviceWidth, runArgs_.deviceHeight,
runArgs_.orientation == DeviceOrientation::PORTRAIT ? 0 : 1, runArgs_.resolution, runArgs_.isRound);
SystemProperties::InitDeviceType(runArgs_.deviceType);
SystemProperties::SetColorMode(runArgs_.colorMode == OHOS::Ace::Platform::ColorMode::DARK ?
runArgs_.deviceConfig.orientation == DeviceOrientation::PORTRAIT ? 0 : 1,
runArgs_.deviceConfig.density, runArgs_.isRound);
SystemProperties::InitDeviceType(runArgs_.deviceConfig.deviceType);
SystemProperties::SetColorMode(runArgs_.deviceConfig.colorMode == OHOS::Ace::Platform::ColorMode::DARK ?
OHOS::Ace::ColorMode::DARK : OHOS::Ace::ColorMode::LIGHT);
if (runArgs_.formsEnabled) {
LOGI("CreateContainer with JS_CARD frontend");
AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS_CARD);
} else {
} else if (runArgs_.aceVersion == AceVersion::ACE_1_0) {
LOGI("CreateContainer with JS frontend");
AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS);
} else if (runArgs_.aceVersion == AceVersion::ACE_2_0) {
LOGI("CreateContainer with JSDECLARATIVE frontend");
AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::DECLARATIVE_JS);
} else {
LOGE("UnKnown frontend type");
}
}
@ -169,16 +173,32 @@ void AceAbility::InitEnv()
ACE_INSTANCE_ID, "", { runArgs_.assetPath, GetCustomAssetPath(runArgs_.assetPath).append(ASSET_PATH_SHARE) });
AceContainer::SetResourcesPathAndThemeStyle(ACE_INSTANCE_ID, runArgs_.resourcesPath,
runArgs_.themeId, runArgs_.colorMode);
runArgs_.themeId, runArgs_.deviceConfig.colorMode);
auto view = new FlutterAceView(ACE_INSTANCE_ID);
AceContainer::SetView(view, runArgs_.resolution, runArgs_.deviceWidth, runArgs_.deviceHeight);
AceContainer::SetView(view, runArgs_.deviceConfig.density, runArgs_.deviceWidth, runArgs_.deviceHeight);
AceContainer::AddRouterChangeCallback(ACE_INSTANCE_ID, runArgs_.onRouterChange);
IdleCallback idleNoticeCallback = [view](int64_t deadline) { view->ProcessIdleEvent(deadline); };
FlutterDesktopSetIdleCallback(controller_, idleNoticeCallback);
// Should make it possible to update surface changes by using viewWidth and viewHeight.
view->NotifySurfaceChanged(runArgs_.deviceWidth, runArgs_.deviceHeight);
view->NotifyDensityChanged(runArgs_.resolution);
view->NotifyDensityChanged(runArgs_.deviceConfig.density);
}
void AceAbility::OnConfigurationChanged(const DeviceConfig& newConfig)
{
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
if (!container) {
LOGE("container is null, change configuration failed.");
return;
}
if (newConfig.colorMode == runArgs_.deviceConfig.colorMode) {
LOGI("newConfig's colorMode is same as before, return.");
return;
}
container->UpdateColorMode(newConfig.colorMode);
runArgs_.deviceConfig.colorMode = newConfig.colorMode;
}
void AceAbility::Start()
@ -200,14 +220,14 @@ void AceAbility::Stop()
#ifdef USE_GLFW_WINDOW
void AdaptDeviceType(AceRunArgs& runArgs)
{
if (runArgs.deviceType == DeviceType::PHONE) {
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_PHONE;
} else if (runArgs.deviceType == DeviceType::WATCH) {
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_WATCH;
} else if (runArgs.deviceType == DeviceType::TABLET) {
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TABLE;
} else if (runArgs.deviceType == DeviceType::TV) {
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TV;
if (runArgs.deviceConfig.deviceType == DeviceType::PHONE) {
runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_PHONE;
} else if (runArgs.deviceConfig.deviceType == DeviceType::WATCH) {
runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_WATCH;
} else if (runArgs.deviceConfig.deviceType == DeviceType::TABLET) {
runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TABLE;
} else if (runArgs.deviceConfig.deviceType == DeviceType::TV) {
runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TV;
} else {
LOGE("DeviceType not supported");
}
@ -222,10 +242,10 @@ void AceAbility::RunEventLoop()
auto window = FlutterDesktopGetWindow(controller_);
int width;
int height;
FlutterDesktopGetFramebufferSize(window, &width, &height);
FlutterDesktopGetWindowSize(window, &width, &height);
if (width != runArgs_.deviceWidth || height != runArgs_.deviceHeight) {
AdaptDeviceType(runArgs_);
SurfaceChanged(runArgs_.orientation, width, height, runArgs_.resolution);
SurfaceChanged(runArgs_.deviceConfig.orientation, runArgs_.deviceConfig.density, width, height);
}
#endif
std::this_thread::sleep_for(std::chrono::milliseconds(1));
@ -254,10 +274,8 @@ void AceAbility::RunEventLoop()
}
void AceAbility::SurfaceChanged(
const DeviceOrientation& orientation, const int32_t& width, const int32_t& height, const double& resolution)
const DeviceOrientation& orientation, const double& resolution, int32_t& width, int32_t& height)
{
SystemProperties::InitDeviceInfo(
width, height, orientation == DeviceOrientation::PORTRAIT ? 0 : 1, resolution, runArgs_.isRound);
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
if (!container) {
LOGE("container is null, SurfaceChanged failed.");
@ -269,12 +287,25 @@ void AceAbility::SurfaceChanged(
LOGE("aceView is null, SurfaceChanged failed.");
return;
}
auto window = FlutterDesktopGetWindow(controller_);
// Need to change the window resolution and then change the rendering resolution. Otherwise, the image may not adapt
// to the new window after the window is modified.
auto context = container->GetPipelineContext();
if (context == nullptr) {
LOGE("context is null, SurfaceChanged failed.");
return;
}
context->GetTaskExecutor()->PostSyncTask(
[window, &width, &height]() { FlutterDesktopSetWindowSize(window, width, height); },
TaskExecutor::TaskType::PLATFORM);
SystemProperties::InitDeviceInfo(
width, height, orientation == DeviceOrientation::PORTRAIT ? 0 : 1, resolution, runArgs_.isRound);
viewPtr->NotifySurfaceChanged(width, height);
viewPtr->NotifyDensityChanged(resolution);
runArgs_.orientation = orientation;
runArgs_.deviceConfig.orientation = orientation;
runArgs_.deviceWidth = width;
runArgs_.deviceHeight = height;
runArgs_.resolution = resolution;
runArgs_.deviceConfig.density = resolution;
}
std::string AceAbility::GetJSONTree()

View File

@ -42,6 +42,7 @@ public:
static void Stop();
static bool DispatchTouchEvent(const TouchPoint& event);
static bool DispatchBackPressedEvent();
void OnConfigurationChanged(const DeviceConfig& newConfig);
explicit AceAbility(const AceRunArgs& runArgs);
~AceAbility();
@ -49,7 +50,7 @@ public:
void InitEnv();
void Start();
void SurfaceChanged(
const DeviceOrientation& orientation, const int32_t& width, const int32_t& height, const double& resolution);
const DeviceOrientation& orientation, const double& resolution, int32_t& width, int32_t& height);
std::string GetJSONTree();
std::string GetDefaultJSONTree();

View File

@ -50,13 +50,74 @@ std::vector<std::string> AceApplicationInfoImpl::GetResourceFallback(const std::
return fileList;
}
std::vector<std::string> AceApplicationInfoImpl::GetStyleResourceFallback(
const std::vector<std::string>& resourceList) const
{
std::vector<std::string> fileList;
std::string deviceConfigTag = GetCurrentDeviceResTag();
AceResConfig::MatchAndSortStyleResConfigs(resourceList, deviceConfigTag, fileList);
return fileList;
}
std::vector<std::string> AceApplicationInfoImpl::GetDeclarativeResourceFallback(
const std::set<std::string>& resourceFolderList) const
{
std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
std::vector<std::string> folderList;
AceResConfig::MatchAndSortDeclarativeResConfigs(resourceFolderList, deviceConfigTag, folderList);
return folderList;
}
std::string AceApplicationInfoImpl::GetCurrentDeviceResTag() const
{
ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
AceResConfig deviceResConfig = AceResConfig(SystemProperties::GetMcc(), SystemProperties::GetMnc(),
SystemProperties::GetDevcieOrientation(), SystemProperties::GetColorMode(), SystemProperties::GetDeviceType(),
SystemProperties::GetDevcieOrientation(), SystemProperties::GetColorMode(),
SystemProperties::GetParamDeviceType() == "tablet" ? DeviceType::TABLET : SystemProperties::GetDeviceType(),
resolutionType);
return AceResConfig::ConvertResConfigToTag(deviceResConfig);
return AceResConfig::ConvertResConfigToTag(deviceResConfig, false);
}
std::string AceApplicationInfoImpl::GetCurrentDeviceDeclarativeResTag() const
{
UErrorCode status = U_ZERO_ERROR;
icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(localeTag_), status);
ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
LongScreenType longScreenType = AceResConfig::GetLongScreenType(SystemProperties::GetResolution());
AceResConfig deviceResConfig;
if (status != U_ZERO_ERROR) {
LOGE("This localeTag is not valid.");
deviceResConfig = AceResConfig("", "", "", longScreenType, SystemProperties::GetScreenShape(),
SystemProperties::GetDevcieOrientation(), SystemProperties::GetColorMode(),
SystemProperties::GetParamDeviceType() == "tablet" ? DeviceType::TABLET : SystemProperties::GetDeviceType(),
resolutionType);
} else {
deviceResConfig = AceResConfig(locale.getLanguage(), locale.getScript(), locale.getCountry(),
longScreenType, SystemProperties::GetScreenShape(), SystemProperties::GetDevcieOrientation(),
SystemProperties::GetColorMode(), SystemProperties::GetParamDeviceType() == "tablet" ? DeviceType::TABLET :
SystemProperties::GetDeviceType(), resolutionType);
}
return AceResConfig::ConvertDeclarativeResConfigToTag(deviceResConfig);
}
double AceApplicationInfoImpl::GetTargetMediaScaleRatio(const std::string& targetResTag) const
{
std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
auto deviceConfig = AceResConfig::ConvertDeclarativeResTagToConfig(deviceConfigTag);
ResolutionType deviceResolution = (deviceConfig.resolution_ != ResolutionType::RESOLUTION_NONE) ?
deviceConfig.resolution_ : ResolutionType::RESOLUTION_MDPI;
ResolutionType targetResolution;
if (targetResTag == "default") {
targetResolution = ResolutionType::RESOLUTION_MDPI;
} else {
AceResConfig targetConfig = AceResConfig::ConvertDeclarativeResTagToConfig(targetResTag);
targetResolution = (targetConfig.resolution_ != ResolutionType::RESOLUTION_NONE) ?
targetConfig.resolution_ : ResolutionType::RESOLUTION_MDPI;
}
return static_cast<double>(deviceResolution) / static_cast<double>(targetResolution);
}
void AceApplicationInfoImpl::SetLocale(const std::string& language, const std::string& countryOrRegion,
@ -127,6 +188,12 @@ bool AceApplicationInfoImpl::GetFiles(const std::string& filePath, std::vector<s
return true;
}
bool AceApplicationInfoImpl::GetFiles(
int32_t instanceId, const std::string& filePath, std::vector<std::string>& fileList) const
{
return GetFiles(filePath, fileList);
}
bool AceApplicationInfoImpl::GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo)
{
return false;

View File

@ -29,7 +29,11 @@ public:
void ChangeLocale(const std::string& language, const std::string& countryOrRegion) override;
std::vector<std::string> GetLocaleFallback(const std::vector<std::string>& localeList) const override;
std::vector<std::string> GetResourceFallback(const std::vector<std::string>& resourceList) const override;
std::vector<std::string> GetStyleResourceFallback(const std::vector<std::string>& resourceList) const override;
std::vector<std::string> GetDeclarativeResourceFallback(
const std::set<std::string>& resourceList) const override;
bool GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const override;
bool GetFiles(int32_t instanceId, const std::string& filePath, std::vector<std::string>& fileList) const override;
bool GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo) override;
double GetLifeTime() const override;
@ -37,6 +41,10 @@ public:
std::string GetJsEngineParam(const std::string& key) const override;
std::string GetCurrentDeviceResTag() const override;
std::string GetCurrentDeviceDeclarativeResTag() const override;
double GetTargetMediaScaleRatio(const std::string& targetResTag) const override;
};
} // namespace OHOS::Ace::Platform

View File

@ -39,6 +39,7 @@
#include "core/pipeline/base/element.h"
#include "core/pipeline/pipeline_context.h"
#include "frameworks/bridge/card_frontend/card_frontend.h"
#include "frameworks/bridge/declarative_frontend/declarative_frontend.h"
#include "frameworks/bridge/js_frontend/engine/common/js_engine_loader.h"
#include "frameworks/bridge/js_frontend/js_frontend.h"
@ -50,16 +51,43 @@ namespace OHOS::Ace::Platform {
std::once_flag AceContainer::onceFlag_;
AceContainer::AceContainer(int32_t instanceId, FrontendType type) : instanceId_(instanceId), type_(type)
AceContainer::AceContainer(int32_t instanceId, FrontendType type)
: instanceId_(instanceId), messageBridge_(AceType::MakeRefPtr<PlatformBridge>()), type_(type)
{
ThemeConstants::InitDeviceType();
auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
taskExecutor_ = Referenced::MakeRefPtr<FlutterTaskExecutor>(state->GetTaskRunners());
taskExecutor_->PostTask([instanceId]() { Container::InitForThread(instanceId); }, TaskExecutor::TaskType::JS);
}
void AceContainer::Initialize()
{
InitializeFrontend();
}
void AceContainer::Destroy()
{
if (pipelineContext_ && taskExecutor_) {
taskExecutor_->PostTask([context = pipelineContext_]() { context->Destroy(); }, TaskExecutor::TaskType::UI);
}
if (frontend_ && taskExecutor_) {
taskExecutor_->PostTask(
[front = frontend_]() { front->UpdateState(Frontend::State::ON_DESTROY); }, TaskExecutor::TaskType::JS);
}
if (aceView_) {
aceView_->DecRefCount();
}
resRegister_.Reset();
assetManager_.Reset();
messageBridge_.Reset();
frontend_.Reset();
pipelineContext_.Reset();
}
void AceContainer::InitializeFrontend()
{
if (type_ == FrontendType::JS) {
@ -68,6 +96,10 @@ void AceContainer::InitializeFrontend()
jsFrontend->SetJsEngine(Framework::JsEngineLoader::Get().CreateJsEngine(GetInstanceId()));
jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
} else if (type_ == FrontendType::DECLARATIVE_JS) {
frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
declarativeFrontend->SetJsEngine(Framework::JsEngineLoader::GetDeclarative().CreateJsEngine(instanceId_));
} else if (type_ == FrontendType::JS_CARD) {
AceApplicationInfo::GetInstance().SetCardType();
frontend_ = AceType::MakeRefPtr<CardFrontend>();
@ -159,16 +191,6 @@ void AceContainer::InitializeCallback()
[context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
};
aceView_->RegisterIdleCallback(idleCallback);
auto&& viewDestoryCallback = [context = pipelineContext_](AceView::ViewReleaseCallback&& callback) {
context->GetTaskExecutor()->PostTask(
[context, callback = std::move(callback)]() {
context->GetTaskExecutor()->PostTask(
[callback = std::move(callback)]() { callback(); }, TaskExecutor::TaskType::PLATFORM);
},
TaskExecutor::TaskType::UI);
};
aceView_->RegisterViewDestroyCallback(viewDestoryCallback);
}
void AceContainer::CreateContainer(int32_t instanceId, FrontendType type)
@ -186,6 +208,7 @@ void AceContainer::CreateContainer(int32_t instanceId, FrontendType type)
#endif
auto aceContainer = AceType::MakeRefPtr<AceContainer>(instanceId, type);
AceEngine::Get().AddContainer(aceContainer->GetInstanceId(), aceContainer);
aceContainer->Initialize();
auto front = aceContainer->GetFrontend();
if (front) {
front->UpdateState(Frontend::State::ON_CREATE);
@ -200,26 +223,13 @@ void AceContainer::DestroyContainer(int32_t instanceId)
LOGE("no AceContainer with id %{private}d in AceEngine", instanceId);
return;
}
auto context = container->GetPipelineContext();
if (context) {
context->Destroy();
container->Destroy();
auto taskExecutor = container->GetTaskExecutor();
if (taskExecutor) {
taskExecutor->PostSyncTask([] { LOGI("Wait UI thread..."); }, TaskExecutor::TaskType::UI);
taskExecutor->PostSyncTask([] { LOGI("Wait JS thread..."); }, TaskExecutor::TaskType::JS);
}
AceEngine::Get().RemoveContainer(instanceId);
auto front = container->GetFrontend();
if (front) {
front->UpdateState(Frontend::State::ON_DESTROY);
}
auto taskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(container->GetTaskExecutor());
if (taskExecutor) {
taskExecutor->DestroyJsThread();
}
auto aceView = AceType::DynamicCast<AceContainer>(container)->GetAceView();
if (aceView) {
LOGI("NotifyViewDestroyed");
aceView->NotifyViewDestroyed([aceView]() { aceView->DecRefCount(); });
}
}
bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string& url, const std::string& params)
@ -233,7 +243,7 @@ bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string
auto front = container->GetFrontend();
if (front) {
auto type = front->GetType();
if ((type == FrontendType::JS) || (type == FrontendType::JS_CARD)) {
if ((type == FrontendType::JS) || (type == FrontendType::DECLARATIVE_JS) || (type == FrontendType::JS_CARD)) {
front->RunPage(pageId, url, params);
return true;
} else {
@ -249,7 +259,59 @@ void AceContainer::Dispatch(
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
{}
void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const {}
void AceContainer::FetchResponse(const ResponseData responseData, const int32_t callbackId) const
{
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(0));
if (!container) {
LOGE("FetchResponse container is null!");
return;
}
auto front = container->GetFrontend();
auto type = container->GetType();
// todo Adapting to cards and 2.0
if (type == FrontendType::JS) {
auto jsFrontend = AceType::DynamicCast<JsFrontend>(front);
if (jsFrontend) {
// todo deal with code success is 0;
jsFrontend->TransferJsResponseDataPreview(callbackId, ACTION_SUCCESS, responseData);
}
} else {
LOGE("Frontend type not supported");
return;
}
}
void AceContainer::CallCurlFunction(const RequestData requestData, const int32_t callbackId) const
{
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(ACE_INSTANCE_ID));
if (!container) {
LOGE("CallCurlFunction container is null!");
return;
}
taskExecutor_->PostTask(
[container, requestData, callbackId]() mutable {
ResponseData responseData;
if (FetchManager::GetInstance().Fetch(requestData, callbackId, responseData)) {
container->FetchResponse(responseData, callbackId);
}
},
TaskExecutor::TaskType::BACKGROUND);
}
void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
{
auto front = GetFrontend();
if (!front) {
LOGE("the front is nullptr");
return;
}
taskExecutor_->PostTask(
[front, callbackId, errorCode, errorMessage = std::move(errorMessage)]() mutable {
front->TransferJsPluginGetError(callbackId, errorCode, std::move(errorMessage));
},
TaskExecutor::TaskType::BACKGROUND);
}
bool AceContainer::Dump(const std::vector<std::string>& params)
{
@ -264,6 +326,19 @@ bool AceContainer::Dump(const std::vector<std::string>& params)
return false;
}
void AceContainer::AddRouterChangeCallback(int32_t instanceId, const OnRouterChangeCallback& onRouterChangeCallback)
{
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
if (!container) {
return;
}
if (!container->pipelineContext_) {
LOGE("container pipelineContext not init");
return;
}
container->pipelineContext_->AddRouterChangeCallback(onRouterChangeCallback);
}
void AceContainer::AddAssetPath(
int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
{
@ -294,15 +369,56 @@ void AceContainer::AddAssetPath(
}
void AceContainer::SetResourcesPathAndThemeStyle(int32_t instanceId, const std::string& resourcesPath,
const ThemeId& themeId, const ColorMode& colorMode)
const int32_t& themeId, const ColorMode& colorMode)
{
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
if (!container) {
return;
}
container->deviceResourceInfo_.deviceConfig.colorMode = static_cast<OHOS::Ace::ColorMode>(colorMode);
container->deviceResourceInfo_.packagePath = resourcesPath;
container->deviceResourceInfo_.themeId = static_cast<int32_t>(themeId);
container->resourceInfo_.deviceConfig.colorMode = static_cast<OHOS::Ace::ColorMode>(colorMode);
container->resourceInfo_.packagePath = resourcesPath;
container->resourceInfo_.themeId = themeId;
}
void AceContainer::UpdateColorMode(ColorMode newColorMode)
{
auto& deviceConfig = resourceInfo_.deviceConfig;
OHOS::Ace::ColorMode colorMode = static_cast<OHOS::Ace::ColorMode>(newColorMode);
SystemProperties::SetColorMode(colorMode);
if (deviceConfig.colorMode == colorMode) {
return;
} else {
deviceConfig.colorMode = colorMode;
if (frontend_) {
frontend_->SetColorMode(colorMode);
}
}
if (!pipelineContext_) {
return;
}
auto themeManager = pipelineContext_->GetThemeManager();
if (!themeManager) {
return;
}
themeManager->UpdateConfig(deviceConfig);
taskExecutor_->PostTask(
[weakThemeManager = WeakPtr<ThemeManager>(themeManager), colorScheme = colorScheme_,
weakContext = WeakPtr<PipelineContext>(pipelineContext_)]() {
auto themeManager = weakThemeManager.Upgrade();
auto context = weakContext.Upgrade();
if (!themeManager || !context) {
return;
}
themeManager->ReloadThemes();
themeManager->ParseSystemTheme();
themeManager->SetColorScheme(colorScheme);
context->RefreshRootBgColor();
},
TaskExecutor::TaskType::UI);
if (frontend_) {
frontend_->RebuildAllPages();
}
}
void AceContainer::SetView(FlutterAceView* view, double density, int32_t width, int32_t height)
@ -337,6 +453,7 @@ void AceContainer::AttachView(
pipelineContext_->SetRootSize(density, width, height);
pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
pipelineContext_->SetMessageBridge(messageBridge_);
pipelineContext_->SetWindowModal(windowModal_);
pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
pipelineContext_->SetIsJsCard(type_ == FrontendType::JS_CARD);
@ -346,16 +463,16 @@ void AceContainer::AttachView(
auto themeManager = pipelineContext_->GetThemeManager();
if (themeManager) {
// Init resource, load theme map.
themeManager->InitResource(deviceResourceInfo_);
themeManager->LoadSystemTheme(deviceResourceInfo_.themeId);
// get background color from theme
aceView_->SetBackgroundColor(themeManager->GetBackgroundColor());
themeManager->InitResource(resourceInfo_);
themeManager->LoadSystemTheme(resourceInfo_.themeId);
taskExecutor_->PostTask(
[themeManager, assetManager = assetManager_, colorScheme = colorScheme_]() {
[themeManager, assetManager = assetManager_, colorScheme = colorScheme_, aceView = aceView_]() {
themeManager->ParseSystemTheme();
themeManager->SetColorScheme(colorScheme);
themeManager->LoadCustomTheme(assetManager);
// get background color from theme
aceView->SetBackgroundColor(themeManager->GetBackgroundColor());
},
TaskExecutor::TaskType::UI);
}

View File

@ -23,6 +23,7 @@
#include "adapter/preview/entrance/ace_run_args.h"
#include "adapter/preview/entrance/flutter_ace_view.h"
#include "adapter/preview/osal/fetch_manager.h"
#include "base/resource/asset_manager.h"
#include "base/thread/task_executor.h"
#include "base/utils/noncopyable.h"
@ -33,6 +34,14 @@
namespace OHOS::Ace::Platform {
namespace {
// Different with mobile, we don't support multi-instances in Windows, because we only want
// preivew UI effect, it doesn't make scense to create multi ability in one process.
constexpr int32_t ACE_INSTANCE_ID = 0;
}
using OnRouterChangeCallback = bool (*)(const std::string currentRouterPath);
// AceContainer is the instance have its own pipeline and thread models, it can contains multiple pages.
class AceContainer : public Container, public JsMessageDispatcher {
DECLARE_ACE_TYPE(AceContainer, Container, JsMessageDispatcher);
@ -43,14 +52,19 @@ public:
static void AddAssetPath(int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths);
static void SetResourcesPathAndThemeStyle(int32_t instanceId, const std::string& resourcesPath,
const ThemeId& themeId, const ColorMode& colorMode);
const int32_t& themeId, const ColorMode& colorMode);
static void SetView(FlutterAceView* view, double density, int32_t width, int32_t height);
static bool RunPage(int32_t instanceId, int32_t pageId, const std::string& url, const std::string& params);
static RefPtr<AceContainer> GetContainerInstance(int32_t instanceId);
static void AddRouterChangeCallback(int32_t instanceId, const OnRouterChangeCallback& onRouterChangeCallback);
AceContainer(int32_t instanceId, FrontendType type);
~AceContainer() override = default;
void Initialize() override;
void Destroy() override;
int32_t GetInstanceId() const override
{
return instanceId_;
@ -66,6 +80,11 @@ public:
return frontend_;
}
RefPtr<PlatformBridge> GetMessageBridge() const
{
return messageBridge_;
}
RefPtr<TaskExecutor> GetTaskExecutor() const override
{
return taskExecutor_;
@ -101,13 +120,28 @@ public:
colorScheme_ = colorScheme;
}
FrontendType GetType() const
{
return type_;
}
void FetchResponse(const ResponseData responseData, const int32_t callbackId) const;
void CallCurlFunction(const RequestData requestData, const int32_t callbackId) const override;
void Dispatch(
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const override;
void DispatchSync(
const std::string& group, std::vector<uint8_t>&& data, uint8_t** resData, long& position) const override
{}
void DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override;
bool Dump(const std::vector<std::string>& params) override;
void UpdateColorMode(ColorMode newColorMode);
private:
void InitializeFrontend();
void InitializeCallback();
@ -122,10 +156,11 @@ private:
RefPtr<PlatformResRegister> resRegister_;
RefPtr<PipelineContext> pipelineContext_;
RefPtr<Frontend> frontend_;
RefPtr<PlatformBridge> messageBridge_;
FrontendType type_ { FrontendType::JSON };
WindowModal windowModal_ { WindowModal::NORMAL };
ColorScheme colorScheme_ { ColorScheme::SCHEME_LIGHT };
DeviceResourceInfo deviceResourceInfo_;
DeviceResourceInfo resourceInfo_;
static std::once_flag onceFlag_;
ACE_DISALLOW_COPY_AND_MOVE(AceContainer);

View File

@ -32,6 +32,10 @@
namespace OHOS::Ace::Platform {
using SendRenderDataCallback = bool (*)(const void*, size_t);
using SendCurrentRouterCallback = bool (*)(const std::string currentRouterPath);
constexpr uint32_t THEME_ID_LIGHT = 117440515;
constexpr uint32_t THEME_ID_DARK = 117440516;
// Keep the same with definition in base/utils/system_properties.h
enum class DeviceOrientation : int32_t {
@ -39,9 +43,9 @@ enum class DeviceOrientation : int32_t {
LANDSCAPE,
};
enum class ThemeId : int32_t {
THEME_ID_LIGHT,
THEME_ID_DARK,
enum class AceVersion {
ACE_1_0,
ACE_2_0,
};
// Keep the same with definition in base/utils/system_properties.h
@ -50,17 +54,33 @@ enum class ColorMode : int32_t {
DARK,
};
// keep same with definition in base/utils/device_config.h
struct DeviceConfig {
DeviceOrientation orientation { DeviceOrientation::PORTRAIT };
// resolution.
double density { 1.0 };
DeviceType deviceType { DeviceType::PHONE };
// Current user perference for scaling fator for fonts, relative to the base density.
// Set through by java interface, not support in previewer yet.
double fontRatio { 1.0 };
ColorMode colorMode { ColorMode::LIGHT };
};
struct ACE_PREVIEW_EXPORT AceRunArgs {
// The absolute path end of "default".
std::string assetPath;
// The absolute path of system resources.
std::string resourcesPath;
// Indecate light or dark theme. 0 is theme_light, 1 is theme_dark.
ThemeId themeId = ThemeId::THEME_ID_LIGHT;
// Indecate light or dark theme.
uint32_t themeId = THEME_ID_LIGHT;
// Light Theme contains light mode and dark mode. The dafault is light mode of light theme.
ColorMode colorMode = ColorMode::LIGHT;
DeviceConfig deviceConfig = {
.orientation = DeviceOrientation::PORTRAIT,
.density = 1.0,
.deviceType = DeviceType::PHONE,
.colorMode = ColorMode::LIGHT,
};
// Set page path to launch directly, or launch the main page in default.
std::string url;
@ -72,19 +92,18 @@ struct ACE_PREVIEW_EXPORT AceRunArgs {
int32_t viewHeight = 0;
int32_t deviceWidth = 0;
int32_t deviceHeight = 0;
double resolution = 1.0;
// Locale
std::string language = "zh";
std::string region = "CN";
std::string script = "";
DeviceOrientation orientation = DeviceOrientation::PORTRAIT;
DeviceType deviceType = DeviceType::PHONE;
AceVersion aceVersion = AceVersion::ACE_1_0;
bool formsEnabled = false;
SendRenderDataCallback onRender;
SendRenderDataCallback onRender = nullptr;
SendCurrentRouterCallback onRouterChange = nullptr;
};
} // namespace OHOS::Ace::Platform

View File

@ -96,9 +96,12 @@ bool FlutterTaskExecutor::WillRunOnCurrentThread(TaskType type) const
}
}
void FlutterTaskExecutor::DestroyJsThread()
void FlutterTaskExecutor::AddTaskObserver(Task&& callback)
{
}
void FlutterTaskExecutor::RemoveTaskObserver()
{
jsThread_.reset();
}
} // namespace OHOS::Ace

View File

@ -31,7 +31,8 @@ public:
explicit FlutterTaskExecutor(const flutter::TaskRunners& taskRunners);
~FlutterTaskExecutor() override = default;
void DestroyJsThread();
void AddTaskObserver(Task&& callback) override;
void RemoveTaskObserver() override;
bool WillRunOnCurrentThread(TaskType type) const final;
private:

View File

@ -39,6 +39,8 @@ template("ace_test") {
sources = [ "ace_tablet_test.cpp" ]
} else if (device == "card") {
sources = [ "ace_card_test.cpp" ]
} else if (device == "car") {
sources = [ "ace_car_test.cpp" ]
}
configs = [ ":ace_pc_preview_config" ]
@ -79,6 +81,12 @@ ace_test("ace_test_windows_card") {
device = "card"
}
ace_test("ace_test_windows_car") {
defines = ace_windows_defines
platform = "windows"
device = "car"
}
ace_test("ace_test_mac_phone") {
defines = ace_mac_defines
platform = "mac"
@ -108,3 +116,9 @@ ace_test("ace_test_mac_card") {
platform = "mac"
device = "card"
}
ace_test("ace_test_mac_car") {
defines = ace_mac_defines
platform = "mac"
device = "car"
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2021 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 <fstream>
#include <iostream>
#include <sstream>
#include <thread>
#include "adapter/preview/entrance/ace_ability.h"
#include "adapter/preview/entrance/ace_run_args.h"
namespace {
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
constexpr char FILE_NAME[] = "InspectorTree.txt";
constexpr char ACE_VERSION_2[] = "2.0";
constexpr char MAX_ARGS_COUNT = 2;
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
} // namespace
int main(int argc, const char* argv[])
{
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
std::string assetPath2 = "/Volumes/SSD2T/daily-test/preview/js/default_2.0";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default_2.0";
std::string assetPath2 = "D:\\Workspace\\preview\\js\\default_2.0";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.resourcesPath = resourcesPath,
.deviceConfig.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
.deviceConfig.density = 1,
.deviceConfig.deviceType = OHOS::Ace::DeviceType::CAR,
.windowTitle = "ACE Car",
.deviceWidth = 1280,
.deviceHeight = 800,
.onRender = std::move(renderCallback),
};
if (argc == MAX_ARGS_COUNT && !std::strcmp(argv[1], ACE_VERSION_2)) {
args.assetPath = assetPath2;
args.aceVersion = OHOS::Ace::Platform::AceVersion::ACE_2_0;
}
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
if (!ability) {
std::cerr << "Could not create AceAbility!" << std::endl;
return -1;
}
std::thread timer([&ability]() {
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
while (getJSONTreeTimes--) {
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
std::string jsonTreeStr = ability->GetJSONTree();
// clear all information
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
fileWriter << jsonTreeStr;
fileWriter << std::endl;
fileWriter.close();
}
});
ability->InitEnv();
std::cout << "Ace initialize done. run loop now" << std::endl;
ability->Start();
return 0;
}

View File

@ -43,20 +43,21 @@ int main()
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default_card";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
constexpr double resolution = 2;
constexpr double density = 2;
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default_card";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
constexpr double resolution = 1;
constexpr double density = 1;
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.resourcesPath = resourcesPath,
.deviceConfig.density = density,
.deviceConfig.colorMode = OHOS::Ace::Platform::ColorMode::DARK,
.windowTitle = "ACE card",
.deviceWidth = CARD_DEFAULT_WIDTH,
.deviceHeight = CARD_DEFAULT_HEIGHT,
.windowTitle = "ACE card",
.resolution = resolution,
.formsEnabled = true,
.onRender = std::move(renderCallback),
};

View File

@ -26,35 +26,47 @@ namespace {
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
constexpr char FILE_NAME[] = "InspectorTree.txt";
constexpr char ACE_VERSION_2[] = "2.0";
constexpr char MAX_ARGS_COUNT = 2;
}
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
int main()
auto&& pageCallback = [](const std::string currentPagePath) -> bool {
printf("callback currentPage:%s", currentPagePath.c_str());
return true;
};
} // namespace
int main(int argc, const char* argv[])
{
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
return true;
};
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
std::string assetPath2 = "/Volumes/SSD2T/daily-test/preview/js/default_2.0";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
constexpr double resolution = 2;
constexpr double density = 2;
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
std::string assetPath2 = "D:\\Workspace\\preview\\js\\default_2.0";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
constexpr double resolution = 1;
constexpr double density = 1;
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.resourcesPath = resourcesPath,
.deviceConfig.density = density,
.windowTitle = "ACE phone",
.deviceWidth = 360,
.deviceHeight = 750,
.windowTitle = "ACE phone",
.resolution = resolution,
.onRender = std::move(renderCallback),
.onRouterChange = std::move(pageCallback),
};
if (argc == MAX_ARGS_COUNT && !std::strcmp(argv[1], ACE_VERSION_2)) {
args.assetPath = assetPath2;
args.aceVersion = OHOS::Ace::Platform::AceVersion::ACE_2_0;
}
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
if (!ability) {
std::cerr << "Could not create AceAbility!" << std::endl;

View File

@ -26,35 +26,41 @@ namespace {
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
constexpr char FILE_NAME[] = "InspectorTree.txt";
constexpr char ACE_VERSION_2[] = "2.0";
constexpr char MAX_ARGS_COUNT = 2;
}
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
int main()
} // namespace
int main(int argc, const char* argv[])
{
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
return true;
};
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
std::string assetPath2 = "/Volumes/SSD2T/daily-test/preview/js/default_2.0";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
std::string assetPath2 = "D:\\Workspace\\preview\\js\\default_2.0";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.resourcesPath = resourcesPath,
.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
.deviceConfig.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
.deviceConfig.density = 1,
.deviceConfig.deviceType = OHOS::Ace::DeviceType::TABLET,
.windowTitle = "ACE Table",
.deviceWidth = 1280,
.deviceHeight = 800,
.windowTitle = "ACE Table",
.resolution = 1,
.deviceType = OHOS::Ace::DeviceType::TABLET,
.onRender = std::move(renderCallback),
};
if (argc == MAX_ARGS_COUNT && !std::strcmp(argv[1], ACE_VERSION_2)) {
args.assetPath = assetPath2;
args.aceVersion = OHOS::Ace::Platform::AceVersion::ACE_2_0;
}
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
if (!ability) {
std::cerr << "Could not create AceAbility!" << std::endl;

View File

@ -26,34 +26,40 @@ namespace {
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
constexpr char FILE_NAME[] = "InspectorTree.txt";
constexpr char ACE_VERSION_2[] = "2.0";
constexpr char MAX_ARGS_COUNT = 2;
}
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
int main()
} // namespace
int main(int argc, const char* argv[])
{
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
return true;
};
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
std::string assetPath2 = "/Volumes/SSD2T/daily-test/preview/js/default_2.0";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
std::string assetPath2 = "D:\\Workspace\\preview\\js\\default_2.0";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
.deviceConfig.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
.deviceConfig.density = 1,
.deviceConfig.deviceType = OHOS::Ace::DeviceType::TV,
.windowTitle = "ACE TV",
.deviceWidth = 960,
.deviceHeight = 540,
.windowTitle = "ACE TV",
.resolution = 1,
.deviceType = OHOS::Ace::DeviceType::TV,
.onRender = std::move(renderCallback),
};
if (argc == MAX_ARGS_COUNT && !std::strcmp(argv[1], ACE_VERSION_2)) {
args.assetPath = assetPath2;
args.aceVersion = OHOS::Ace::Platform::AceVersion::ACE_2_0;
}
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
if (!ability) {
std::cerr << "Could not create AceAbility!" << std::endl;

View File

@ -26,34 +26,40 @@ namespace {
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
constexpr char FILE_NAME[] = "InspectorTree.txt";
constexpr char ACE_VERSION_2[] = "2.0";
constexpr char MAX_ARGS_COUNT = 2;
}
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
int main()
} // namespace
int main(int argc, const char* argv[])
{
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
return true;
};
#ifdef MAC_PLATFORM
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
std::string assetPath2 = "/Volumes/SSD2T/daily-test/preview/js/default_2.0";
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
#else
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
std::string assetPath2 = "D:\\Workspace\\preview\\js\\default_2.0";
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
#endif
OHOS::Ace::Platform::AceRunArgs args = {
.assetPath = assetPath,
.deviceConfig.density = 2.0,
.deviceConfig.deviceType = OHOS::Ace::DeviceType::WATCH,
.windowTitle = "ACE wearable",
.isRound = true,
.deviceWidth = 466,
.deviceHeight = 466,
.windowTitle = "ACE wearable",
.resolution = 2.0,
.isRound = true,
.deviceType = OHOS::Ace::DeviceType::WATCH,
.onRender = std::move(renderCallback),
};
if (argc == MAX_ARGS_COUNT && !std::strcmp(argv[1], ACE_VERSION_2)) {
args.assetPath = assetPath2;
args.aceVersion = OHOS::Ace::Platform::AceVersion::ACE_2_0;
}
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
if (!ability) {
std::cerr << "Could not create AceAbility!" << std::endl;

View File

@ -14,6 +14,36 @@
import("//build/ohos.gni")
import("//foundation/ace/ace_engine/ace_config.gni")
template("utilsecurec_source") {
# get is_ohos_platform
forward_variables_from(invoker, "*")
ohos_source_set(target_name) {
defines += invoker.defines
sources = [ "//utils/native/base/src/securec/vsnprintf_s_p.c" ]
if (platform == "windows") {
sources += [
"//utils/native/base/src/securec/memset_s.c",
"//utils/native/base/src/securec/securecutil.c",
"//utils/native/base/src/securec/secureinput_w.c",
"//utils/native/base/src/securec/secureprintoutput_a.c",
"//utils/native/base/src/securec/secureprintoutput_w.c",
]
cflags = [ "-Wno-inconsistent-dllimport" ]
}
configs = [ "//utils/native/base:utils_config" ]
}
}
utilsecurec_source("utilsecurec_source_windows") {
defines = ace_windows_defines
platform = "windows"
}
utilsecurec_source("utilsecurec_source_mac") {
defines = ace_windows_defines
platform = "mac"
}
# build static
template("ace_osal_preview_source_set") {
# get is_ohos_platform
@ -39,10 +69,13 @@ template("ace_osal_preview_source_set") {
configs = [
"$ace_root:ace_config",
"$flutter_root:flutter_config",
"$ace_flutter_engine_root:flutter_config",
]
deps = [ "//third_party/zlib:libz" ]
deps = [
":utilsecurec_source_$platform",
"//third_party/zlib:libz",
]
}
}

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2021 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/preview/osal/fetch_manager.h"
#include <memory>
#include <mutex>
#include "curl/curl.h"
#include "adapter/preview/osal/http_constant.h"
#include "base/log/log.h"
#include "base/utils/singleton.h"
#define ACE_CURL_EASY_SET_OPTION(handle, opt, data) \
do { \
CURLcode result = curl_easy_setopt(handle, opt, data); \
if (result != CURLE_OK) { \
LOGE("Failed to set option: %{public}s, %{public}s", #opt, curl_easy_strerror(result)); \
return false; \
} \
} while (0)
namespace OHOS::Ace {
namespace {
class FetchManagerImpl final : public FetchManager, public Singleton<FetchManagerImpl> {
DECLARE_SINGLETON(FetchManagerImpl);
ACE_DISALLOW_MOVE(FetchManagerImpl);
public:
bool Fetch(const RequestData requestData, const int32_t callbackId, ResponseData& responseData) override
{
if (!Initialize()) {
return false;
}
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> handle(curl_easy_init(), &curl_easy_cleanup);
if (!handle) {
LOGE("Failed to create fetch task");
return false;
}
struct curl_slist* header = nullptr;
if (!requestData.GetHeader().empty()) {
for (auto&& [key, value] : requestData.GetHeader()) {
header = curl_slist_append(header, (key + ":" + value).c_str());
}
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HTTPHEADER, header);
}
std::string responseBody;
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEFUNCTION, OnWritingMemoryBody);
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEDATA, &responseBody);
std::string responseHeader;
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HEADERFUNCTION, OnWritingMemoryHeader);
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HEADERDATA, &responseHeader);
// Some servers don't like requests that are made without a user-agent field, so we provide one
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_USERAGENT, "libcurl-agent/1.0");
#ifdef WINDOWS_PLATFORM
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_SSL_VERIFYPEER, 0L);
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_SSL_VERIFYHOST, 0L);
#endif
std::string method = requestData.GetMethod();
if (method == HttpConstant::HTTP_METHOD_HEAD || method == HttpConstant::HTTP_METHOD_OPTIONS ||
method == HttpConstant::HTTP_METHOD_DELETE || method == HttpConstant::HTTP_METHOD_TRACE ||
method == HttpConstant::HTTP_METHOD_GET) {
SetOptionForGet(requestData, handle.get());
} else if (method == HttpConstant::HTTP_METHOD_POST || method == HttpConstant::HTTP_METHOD_PUT) {
SetOptionForPost(requestData, handle.get());
} else {
LOGE("no method match!");
responseData.SetCode(HttpConstant::ERROR);
return false;
}
CURLcode result = curl_easy_perform(handle.get());
if (result != CURLE_OK) {
LOGE("Failed to fetch, url: %{private}s, %{public}s", requestData.GetUrl().c_str(),
curl_easy_strerror(result));
return false;
}
char* ct = nullptr;
CURLcode res = curl_easy_getinfo(handle.get(), CURLINFO_CONTENT_TYPE, &ct);
if ((CURLE_OK == res) && ct) {
LOGD("fetch-preview content_type: %{public}s", ct);
}
int32_t responseCode;
curl_easy_getinfo(handle.get(), CURLINFO_RESPONSE_CODE, &responseCode);
responseData.SetCode(responseCode);
responseData.SetData(responseBody);
responseData.SetHeaders(responseHeader);
curl_slist_free_all(header);
return true;
}
bool SetOptionForGet(const RequestData requestData, CURL* curl) const
{
// refer to function buildConnectionWithParam() in HttpFetchImpl.java
LOGD("begin to set option for get and encode final url");
std::string url = requestData.GetUrl();
if (requestData.GetData() != "") {
std::size_t index = url.find(HttpConstant::URL_PARAM_SEPARATOR);
if (index != std::string::npos) {
std::string param = url.substr(index + 1);
std::string encodeIn = param + HttpConstant::URL_PARAM_DELIMITER + requestData.GetData();
char* encodeOut = curl_easy_escape(curl, encodeIn.c_str(), 0);
if (encodeOut != nullptr) {
url = url.substr(0, index + 1) + encodeOut;
curl_free(encodeOut);
}
} else {
char* encodeOut = curl_easy_escape(curl, requestData.GetData().c_str(), 0);
if (encodeOut != nullptr) {
url = url + HttpConstant::URL_PARAM_SEPARATOR + encodeOut;
curl_free(encodeOut);
}
}
}
LOGD("final url : %{public}s", url.c_str());
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_URL, url.c_str());
return true;
}
bool SetOptionForPost(const RequestData requestData, CURL* curl) const
{
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_URL, requestData.GetUrl().c_str());
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_POST, 1L);
return true;
}
private:
static size_t OnWritingMemoryBody(const void* data, size_t size, size_t memBytes, void* userData)
{
((std::string*)userData)->append((char*)data, 0, size * memBytes);
return size * memBytes;
}
static size_t OnWritingMemoryHeader(const void* data, size_t size, size_t memBytes, void* userData)
{
((std::string*)userData)->append((char*)data, 0, size * memBytes);
return size * memBytes;
}
bool Initialize()
{
if (initialized_) {
return true;
}
std::lock_guard<std::mutex> lock(mutex_);
if (initialized_) {
return true;
}
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
LOGE("Failed to initialize 'curl'");
return false;
}
initialized_ = true;
return true;
}
std::mutex mutex_;
bool initialized_ = false;
};
FetchManagerImpl::FetchManagerImpl() = default;
FetchManagerImpl::~FetchManagerImpl()
{
curl_global_cleanup();
}
} // namespace
FetchManager& FetchManager::GetInstance()
{
return Singleton<FetchManagerImpl>::GetInstance();
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_FETCH_MANAGER_H
#define FOUNDATION_ACE_ADAPTER_PREVIEW_FETCH_MANAGER_H
#include <cstdint>
#include <string>
#include "adapter/preview/osal/request_data.h"
#include "adapter/preview/osal/response_data.h"
namespace OHOS::Ace {
class FetchManager {
public:
static FetchManager& GetInstance();
virtual ~FetchManager() = default;
virtual bool Fetch(const RequestData requestData, const int32_t callbackId, ResponseData& responseData) = 0;
};
} // namespace OHOS::Ace
#endif // #ifndef FOUNDATION_ACE_ADAPTER_PREVIEW_FETCH_MANAGER_H

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_HTTPCONSTANT_H
#define FOUNDATION_ACE_ADAPTER_PREVIEW_HTTPCONSTANT_H
namespace OHOS::Ace {
class HttpConstant {
public:
static const int ERROR = -1;
static const int TIME_OUT = 30000;
static const int BUFFER_SIZE = 8192;
inline static const std::string URL_PARAM_SEPARATOR = "?";
inline static const std::string URL_PARAM_DELIMITER = "&";
inline static const std::string HTTP_METHOD_GET = "GET";
inline static const std::string HTTP_METHOD_HEAD = "HEAD";
inline static const std::string HTTP_METHOD_OPTIONS = "OPTIONS";
inline static const std::string HTTP_METHOD_TRACE = "TRACE";
inline static const std::string HTTP_METHOD_DELETE = "DELETE";
inline static const std::string HTTP_METHOD_CONNECT = "CONNECT";
inline static const std::string HTTP_METHOD_POST = "POST";
inline static const std::string HTTP_METHOD_PUT = "PUT";
};
} // namespace OHOS::Ace
#endif // #ifndef FOUNDATION_ACE_ADAPTER_PREVIEW_HTTPCONSTANT_H

View File

@ -20,12 +20,14 @@
#else
#include "securec.h"
#endif
#include <securec_p.h>
#include <thread>
namespace OHOS::Ace {
namespace {
constexpr uint32_t MAX_BUFFER_SIZE = 512;
// MAX_BUFFER_SIZE same with hilog
constexpr uint32_t MAX_BUFFER_SIZE = 4000;
constexpr uint32_t MAX_TIME_SIZE = 32;
const char* const LOGLEVELNAME[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
@ -68,28 +70,28 @@ std::string GetTimeStamp()
void LogWrapper::PrintLog(LogDomain domain, LogLevel level, const char* fmt, va_list args)
{
std::string newFmt(fmt);
StripFormatString("{public}", newFmt);
StripFormatString("{private}", newFmt);
char buf[MAX_BUFFER_SIZE];
if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, newFmt.c_str(), args) < 0) {
if (vsnprintfp_s(buf, sizeof(buf), sizeof(buf) - 1, true, newFmt.c_str(), args) < 0 && errno == EINVAL) {
return;
}
std::string newTimeFmt("%s %-6d [%-7s %7s]");
std::string newTimeFmt("[%-7s %7s] %s %-6d");
char timeBuf[MAX_BUFFER_SIZE];
#ifdef WINDOWS_PLATFORM
if (_snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(), GetTimeStamp().c_str(),
std::this_thread::get_id(), LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level)) < 0) {
if (_snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(),
LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level), GetTimeStamp().c_str(),
std::this_thread::get_id()) < 0) {
return;
}
#else
if (snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(), GetTimeStamp().c_str(),
std::this_thread::get_id(), LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level)) < 0) {
if (snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(),
LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level), GetTimeStamp().c_str(),
std::this_thread::get_id()) < 0) {
return;
}
#endif
printf("%s %s\r\n", timeBuf, buf);
printf("%s %s\r\n", timeBuf, buf);
fflush(stdout);
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_REQUESTDATA_H
#define FOUNDATION_ACE_ADAPTER_PREVIEW_REQUESTDATA_H
#include <map>
namespace OHOS::Ace {
class RequestData {
public:
const std::string GetUrl() const
{
return url_;
}
void SetUrl(const std::string url)
{
url_ = url;
}
const std::string GetData() const
{
return data_;
}
void SetData(const std::string data)
{
data_ = data;
}
const std::map<std::string, std::string> GetHeader() const
{
return header_;
}
void SetHeader(const std::map<std::string, std::string> header)
{
header_ = header;
}
const std::string GetMethod() const
{
return method_;
}
void SetMethod(const std::string method)
{
method_ = method;
}
const std::string GetEesponseType() const
{
return responseType_;
}
void SetResponseType(const std::string responseType)
{
responseType_ = responseType;
}
private:
std::string url_;
std::string data_;
std::map<std::string, std::string> header_;
std::string method_;
std::string responseType_;
};
} // namespace OHOS::Ace
#endif // #ifndef FOUNDATION_ACE_ADAPTER_PREVIEW_REQUESTDATA_H

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2021 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/preview/osal/response_data.h"
namespace OHOS::Ace {
std::unique_ptr<JsonValue> ResponseData::GetResultString() const
{
auto resultJson = JsonUtil::Create(true);
if (code_ == HTTP_OK) {
resultJson->Put(std::string("code").c_str(), ACTION_SUCCESS);
resultJson->Put(std::string("data").c_str(), GetStringValue());
} else {
resultJson->Put(std::string("code").c_str(), COMMON_ERROR_CODE);
resultJson->Put(std::string("data").c_str(), "invalid response data");
}
return resultJson;
}
std::unique_ptr<JsonValue> ResponseData::GetStringValue() const
{
auto responseJson = JsonUtil::Create(true);
responseJson->Put(std::string("code").c_str(), code_);
responseJson->Put(std::string("data").c_str(), data_.c_str());
if (code_ == HTTP_OK) {
std::string headersStr = "{";
for (auto&& [key, value] : headers_) {
headersStr += key + ":" + value + ",";
}
headersStr[headersStr.size() - 1] = '}';
responseJson->Put(std::string("headers").c_str(), headersStr.c_str());
}
return responseJson;
}
void ResponseData::SetHeaders(std::string headersStr)
{
const char separator = '\n';
size_t posSeparator = headersStr.find(separator);
while (std::string::npos != posSeparator) {
std::string header = headersStr.substr(0, posSeparator - 1);
if (header == "") {
break;
}
size_t posColon = header.find(':');
if (std::string::npos == posColon) {
headers_["null"] = "[\"" + header + "\"]";
} else {
headers_["\"" + header.substr(0, posColon) + "\""] = "[\"" + header.substr(posColon + 2) + "\"]";
}
headersStr = headersStr.substr(posSeparator + 1);
posSeparator = headersStr.find(separator);
}
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_RESPONSEDATA_H
#define FOUNDATION_ACE_ADAPTER_PREVIEW_RESPONSEDATA_H
#include <unordered_map>
#include <string>
#include "base/json/json_util.h"
namespace OHOS::Ace {
namespace {
// error code
constexpr int32_t ACTION_SUCCESS = 0;
constexpr int32_t COMMON_ERROR_CODE = 200;
// httpcode
constexpr int32_t HTTP_OK = 200;
} // namespace
class ResponseData {
public:
int32_t GetCode() const
{
return code_;
}
void SetCode(const int32_t code)
{
code_ = code;
}
std::string GetData() const
{
return data_;
}
void SetData(const std::string data)
{
data_ = data;
}
std::unordered_map<std::string, std::string> GetHeaders() const
{
return headers_;
}
void SetHeaders(std::string headersStr);
std::unique_ptr<JsonValue> GetResultString() const;
private:
int32_t code_ = COMMON_ERROR_CODE;
std::string data_;
std::unordered_map<std::string, std::string> headers_;
std::unique_ptr<JsonValue> GetStringValue() const;
};
} // namespace OHOS::Ace
#endif // #ifndef FOUNDATION_ACE_ADAPTER_PREVIEW_RESPONSEDATA_H

15
adapter/preview/osal/system_properties.cpp Executable file → Normal file
View File

@ -79,6 +79,8 @@ std::string SystemProperties::paramDeviceType_ = UNDEFINED_PARAM;
int32_t SystemProperties::mcc_ = MCC_UNDEFINED;
int32_t SystemProperties::mnc_ = MNC_UNDEFINED;
ColorMode SystemProperties::colorMode_ = ColorMode::LIGHT;
ScreenShape SystemProperties::screenShape_ { ScreenShape::NOT_ROUND };
LongScreenType SystemProperties::LongScreen_ { LongScreenType::NOT_LONG };
void SystemProperties::UpdateSurfaceStatus(int32_t width, int32_t height)
{
@ -100,7 +102,13 @@ void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight,
double resolution, bool isRound)
{
// SetDeviceOrientation should be eralier than deviceWidth/deviceHeight init.
SetDeviceOrientation(orientation);
if (orientation == ORIENTATION_PORTRAIT && orientation_ != DeviceOrientation::PORTRAIT) {
orientation_ = DeviceOrientation::PORTRAIT;
} else if (orientation == ORIENTATION_LANDSCAPE && orientation_ != DeviceOrientation::LANDSCAPE) {
orientation_ = DeviceOrientation::LANDSCAPE;
} else {
LOGW("SetDeviceOrientation, undefined orientation");
}
isRound_ = isRound;
resolution_ = resolution;
@ -109,6 +117,11 @@ void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight,
// To avoid the deviceinfor api failure due to surface width and height equal 0 in previewer.
width_ = deviceWidth_;
height_ = deviceHeight_;
if (isRound_) {
screenShape_ = ScreenShape::ROUND;
} else {
screenShape_ = ScreenShape::NOT_ROUND;
}
}
void SystemProperties::SetDeviceOrientation(int32_t orientation)

View File

@ -44,7 +44,11 @@ template("ace_base_source_set") {
# add base source file here
sources = [
"geometry/animatable_dimension.cpp",
"geometry/animatable_matrix4.cpp",
"geometry/matrix4.cpp",
"geometry/quaternion.cpp",
"geometry/transform_util.cpp",
"json/json_util.cpp",
"log/ace_trace.cpp",
"log/dump_log.cpp",
@ -56,7 +60,7 @@ template("ace_base_source_set") {
"utils/time_util.cpp",
]
if (is_standard_system) {
if (is_standard_system && !use_mingw_win && !use_mac) {
configs += [ "//third_party/curl:curl_config" ]
deps += [ "//third_party/curl:curl" ]
sources += [ "network/download_manager.cpp" ]

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2021 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 "base/geometry/animatable_dimension.h"
#include "core/event/ace_event_helper.h"
namespace OHOS::Ace {
AnimatableDimension& AnimatableDimension::operator=(const Dimension& newDimension)
{
ResetAnimatableDimension();
Dimension& dimension = *this;
dimension = newDimension;
return *this;
}
AnimatableDimension& AnimatableDimension::operator=(const AnimatableDimension& newDimension)
{
SetUnit(newDimension.Unit());
SetAnimationOption(newDimension.GetAnimationOption());
auto pipelineContext = context_.Upgrade();
if (!animationCallback_ || !pipelineContext) {
LOGD("Animatable assign without animation due to null callback or context");
SetValue(newDimension.Value());
return *this;
}
AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption();
if (explicitAnim.IsValid()) {
LOGD("Animatable assign with explicit animation, duration: %{public}d", explicitAnim.GetDuration());
SetAnimationOption(explicitAnim);
AnimateTo(newDimension.Value());
} else if (animationOption_.IsValid()) {
LOGD("Animatable assign with implicit animation, duration: %{public}d", explicitAnim.GetDuration());
AnimateTo(newDimension.Value());
} else {
LOGD("Animatable assign without animation.");
ResetController();
SetValue(newDimension.Value());
}
isFirstAssign_ = false;
return *this;
}
void AnimatableDimension::AnimateTo(double endValue)
{
if (isFirstAssign_) {
LOGD("AnimateTo with first assign. endValue: %{public}.2f", endValue);
isFirstAssign_ = false;
SetValue(endValue);
return;
}
if (NearEqual(Value(), endValue) && !evaluator_) {
LOGD("AnimateTo with same value. endValue: %{public}.2f", endValue);
return;
}
ResetController();
if (!animationController_) {
animationController_ = AceType::MakeRefPtr<Animator>(context_);
}
RefPtr<CurveAnimation<double>> animation =
AceType::MakeRefPtr<CurveAnimation<double>>(Value(), endValue, animationOption_.GetCurve());
if (evaluator_) {
animation->SetEvaluator(evaluator_);
}
animation->AddListener(std::bind(&AnimatableDimension::OnAnimationCallback, this, std::placeholders::_1));
animationController_->AddInterpolator(animation);
auto onFinishEvent = animationOption_.GetOnFinishEvent();
if (!onFinishEvent.IsEmpty()) {
animationController_->AddStopListener(
[onFinishEvent, weakContext = context_] { AceAsyncEvent<void()>::Create(onFinishEvent, weakContext)(); });
}
if (stopCallback_) {
animationController_->AddStopListener(stopCallback_);
}
animationController_->SetDuration(animationOption_.GetDuration());
animationController_->SetStartDelay(animationOption_.GetDelay());
animationController_->SetIteration(animationOption_.GetIteration());
animationController_->SetTempo(animationOption_.GetTempo());
animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
animationController_->SetFillMode(FillMode::FORWARDS);
animationController_->Play();
}
void AnimatableDimension::ResetController()
{
if (animationController_) {
if (!animationController_->IsStopped()) {
animationController_->Stop();
}
animationController_->ClearInterpolators();
animationController_->ClearAllListeners();
animationController_.Reset();
}
}
void AnimatableDimension::OnAnimationCallback(double value)
{
SetValue(value);
if (animationCallback_) {
animationCallback_();
}
}
void AnimatableDimension::MoveTo(double target)
{
SetValue(target);
isFirstAssign_ = false;
}
void AnimatableDimension::ResetAnimatableDimension()
{
isFirstAssign_ = true;
animationOption_ = AnimationOption();
animationController_ = nullptr;
context_ = nullptr;
animationCallback_ = nullptr;
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_DIMENSION_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_DIMENSION_H
#include "base/geometry/dimension.h"
#include "core/animation/animator.h"
#include "core/animation/curve_animation.h"
#include "core/components/common/properties/animation_option.h"
namespace OHOS::Ace {
using RenderNodeAnimationCallback = std::function<void()>;
/*
* AnimatableDimension is a Dimension with AnimationOption and Animator.
*/
class ACE_EXPORT AnimatableDimension : public Dimension {
public:
AnimatableDimension() = default;
~AnimatableDimension() = default;
explicit AnimatableDimension(
double value, DimensionUnit unit = DimensionUnit::PX, const AnimationOption& option = AnimationOption())
: Dimension(value, unit), animationOption_(option)
{}
explicit AnimatableDimension(const Dimension& dimension, const AnimationOption& option = AnimationOption())
: Dimension(dimension), animationOption_(option)
{}
void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
{
context_ = context;
animationCallback_ = callback;
}
const AnimationOption& GetAnimationOption() const
{
return animationOption_;
}
void SetAnimationOption(const AnimationOption& option)
{
animationOption_ = option;
}
void SetAnimationStopCallback(const RenderNodeAnimationCallback& callback)
{
stopCallback_ = callback;
}
Animator::Status GetAnimationStatus() const
{
if (!animationController_) {
return Animator::Status::IDLE;
}
return animationController_->GetStatus();
}
void SetEvaluator(const RefPtr<Evaluator<double>>& evaluator)
{
evaluator_ = evaluator;
}
AnimatableDimension& operator=(const Dimension& newDimension);
AnimatableDimension& operator=(const AnimatableDimension& newDimension);
void MoveTo(double target);
private:
void AnimateTo(double endValue);
void ResetController();
void OnAnimationCallback(double value);
void ResetAnimatableDimension();
private:
bool isFirstAssign_ = true;
AnimationOption animationOption_;
RefPtr<Animator> animationController_;
WeakPtr<PipelineContext> context_;
RenderNodeAnimationCallback animationCallback_;
RenderNodeAnimationCallback stopCallback_;
RefPtr<Evaluator<double>> evaluator_;
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_DIMENSION_H

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2021 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 "base/geometry/animatable_matrix4.h"
#include "core/event/ace_event_helper.h"
namespace OHOS::Ace {
AnimatableMatrix4& AnimatableMatrix4::operator=(const Matrix4& newMatrix4)
{
ResetAnimatableMatrix();
Matrix4& matrix4 = *this;
matrix4 = newMatrix4;
return *this;
}
AnimatableMatrix4& AnimatableMatrix4::operator=(const AnimatableMatrix4& newMatrix4)
{
SetAnimationOption(newMatrix4.GetAnimationOption());
auto pipelineContext = context_.Upgrade();
if (!animationCallback_ || !pipelineContext) {
LOGD("Animatable assign without animation due to null callback or context");
Matrix4& matrix4 = *this;
matrix4 = newMatrix4;
return *this;
}
AnimationOption explicitAnim = pipelineContext->GetExplicitAnimationOption();
if (explicitAnim.IsValid()) {
LOGD("Animatable assign with explicit animation, duration: %{public}d", explicitAnim.GetDuration());
SetAnimationOption(explicitAnim);
AnimateTo(newMatrix4);
} else if (animationOption_.IsValid()) {
LOGD("Animatable assign with implicit animation, duration: %{public}d", animationOption_.GetDuration());
AnimateTo(newMatrix4);
} else {
LOGD("Animatable assign without animation.");
ResetController();
Matrix4& matrix4 = *this;
matrix4 = newMatrix4;
}
isFirstAssign_ = false;
return *this;
}
void AnimatableMatrix4::MoveTo(const Matrix4& target)
{
Matrix4& matrix4 = *this;
matrix4 = target;
isFirstAssign_ = false;
}
void AnimatableMatrix4::AnimateTo(const Matrix4& endValue)
{
if (isFirstAssign_) {
LOGD("AnimateTo with first assign. endValue: %{public}s", endValue.ToString().c_str());
isFirstAssign_ = false;
Matrix4& matrix4 = *this;
matrix4 = endValue;
return;
}
if (*this == endValue && !evaluator_) {
LOGD("AnimateTo with same value. endValue: %{public}s", endValue.ToString().c_str());
return;
}
ResetController();
if (!animationController_) {
animationController_ = AceType::MakeRefPtr<Animator>(context_);
}
TransformOperation operationInit;
TransformOperation operationEnd;
operationInit.type_ = TransformOperationType::MATRIX;
operationEnd.type_ = TransformOperationType::MATRIX;
operationInit.matrix4_ = static_cast<Matrix4>(*this);
operationEnd.matrix4_ = endValue;
RefPtr<CurveAnimation<TransformOperation>> animation = AceType::MakeRefPtr<CurveAnimation<TransformOperation>>(
operationInit, operationEnd, animationOption_.GetCurve());
if (evaluator_) {
animation->SetEvaluator(evaluator_);
}
animation->AddListener(std::bind(&AnimatableMatrix4::OnAnimationCallback, this, std::placeholders::_1));
animationController_->AddInterpolator(animation);
auto onFinishEvent = animationOption_.GetOnFinishEvent();
if (!onFinishEvent.IsEmpty()) {
animationController_->AddStopListener(
[onFinishEvent, weakContext = context_] { AceAsyncEvent<void()>::Create(onFinishEvent, weakContext)(); });
}
if (stopCallback_) {
animationController_->AddStopListener(stopCallback_);
}
animationController_->SetDuration(animationOption_.GetDuration());
animationController_->SetStartDelay(animationOption_.GetDelay());
animationController_->SetIteration(animationOption_.GetIteration());
animationController_->SetTempo(animationOption_.GetTempo());
animationController_->SetAnimationDirection(animationOption_.GetAnimationDirection());
animationController_->SetFillMode(FillMode::FORWARDS);
animationController_->Play();
}
void AnimatableMatrix4::ResetController()
{
if (animationController_) {
if (!animationController_->IsStopped()) {
animationController_->Stop();
}
animationController_->ClearInterpolators();
animationController_->ClearAllListeners();
animationController_.Reset();
}
}
void AnimatableMatrix4::OnAnimationCallback(const TransformOperation& value)
{
Matrix4& matrix4 = *this;
matrix4 = value.matrix4_;
if (animationCallback_) {
animationCallback_();
}
}
void AnimatableMatrix4::ResetAnimatableMatrix()
{
isFirstAssign_ = true;
animationOption_ = AnimationOption();
animationController_ = nullptr;
context_ = nullptr;
animationCallback_ = nullptr;
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_MATRIX4_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_MATRIX4_H
#include "base/geometry/matrix4.h"
#include "core/animation/animator.h"
#include "core/animation/curve_animation.h"
#include "core/components/common/properties/animation_option.h"
namespace OHOS::Ace {
using RenderNodeAnimationCallback = std::function<void()>;
class ACE_EXPORT AnimatableMatrix4 : public Matrix4 {
public:
AnimatableMatrix4() = default;
~AnimatableMatrix4() = default;
explicit AnimatableMatrix4(Matrix4 matrix4, const AnimationOption& option = AnimationOption())
: Matrix4(matrix4), animationOption_(option)
{}
void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
{
context_ = context;
animationCallback_ = callback;
}
const AnimationOption& GetAnimationOption() const
{
return animationOption_;
}
void SetAnimationOption(const AnimationOption& option)
{
animationOption_ = option;
}
void SetAnimationStopCallback(const RenderNodeAnimationCallback& callback)
{
stopCallback_ = callback;
}
Animator::Status GetAnimationStatus() const
{
if (!animationController_) {
return Animator::Status::IDLE;
}
return animationController_->GetStatus();
}
AnimatableMatrix4& operator=(const Matrix4& matrix4);
AnimatableMatrix4& operator=(const AnimatableMatrix4& newMatrix4);
void MoveTo(const Matrix4& target);
void SetEvaluator(const RefPtr<Evaluator<TransformOperation>>& evaluator)
{
evaluator_ = evaluator;
}
private:
void AnimateTo(const Matrix4& endValue);
void ResetController();
void OnAnimationCallback(const TransformOperation& value);
void ResetAnimatableMatrix();
private:
bool isFirstAssign_ = true;
AnimationOption animationOption_;
RefPtr<Animator> animationController_;
WeakPtr<PipelineContext> context_;
RenderNodeAnimationCallback animationCallback_;
RenderNodeAnimationCallback stopCallback_;
RefPtr<Evaluator<TransformOperation>> evaluator_;
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ANIMATABLE_MATRIX4_H

View File

@ -22,6 +22,7 @@ enum class Axis {
VERTICAL = 0,
HORIZONTAL,
FREE,
NONE,
};
enum class RotateAxis {

View File

@ -16,14 +16,18 @@
#ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
#include <string>
#include "base/utils/macros.h"
#include "base/utils/utils.h"
#define NEAR_ZERO(value) ((value > 0.0) ? ((value - 0.0) <= 0.000001f) : ((0.0 - value) <= 0.000001f))
namespace OHOS::Ace {
enum class DimensionUnit {
/*
* Logical pixel used in Ace. It's based on frontend design width.
* Logical pixel used in Ace1.0. It's based on frontend design width.
* For example, when a frontend with 750px design width running on a
* device with 1080 pixels width, 1px represents 1.44 pixels.
*/
@ -33,7 +37,7 @@ enum class DimensionUnit {
*/
VP,
/*
* scale independent pixels, this is like VP but will be scaled by
* Scale independent pixels. This is like VP but will be scaled by
* user's font size preference.
*/
FP,
@ -42,6 +46,10 @@ enum class DimensionUnit {
* another property of the element itself.
*/
PERCENT,
/*
* logic pixels used in ACE2.0 instead of PX, and PX is the physical pixels in ACE2.0
*/
LPX,
};
/*
@ -54,7 +62,7 @@ public:
~Dimension() = default;
constexpr explicit Dimension(double value, DimensionUnit unit = DimensionUnit::PX) : value_(value), unit_(unit) {}
double Value() const
constexpr double Value() const
{
return value_;
}
@ -64,11 +72,16 @@ public:
value_ = value;
}
DimensionUnit Unit() const
constexpr DimensionUnit Unit() const
{
return unit_;
}
void SetUnit(DimensionUnit unit)
{
unit_ = unit;
}
bool IsValid() const
{
return (value_ > 0.0) && (!NearZero(value_));
@ -91,7 +104,7 @@ public:
constexpr Dimension operator/(double value) const
{
// NearZero cannot be used in a constant expression
if (value > 0.0 ? value - 0.0 <= 0.000001f : 0.0 - value <= 0.000001f) {
if (NEAR_ZERO(value)) {
return Dimension();
}
return Dimension(value_ / value, unit_);
@ -112,6 +125,9 @@ public:
*/
constexpr Dimension operator+(const Dimension& dimension) const
{
if (NEAR_ZERO(dimension.Value())) {
return *this;
}
ACE_DCHECK(unit_ == dimension.unit_);
return Dimension(value_ + dimension.value_, unit_);
}
@ -131,6 +147,9 @@ public:
*/
constexpr Dimension operator-(const Dimension& dimension) const
{
if (NEAR_ZERO(dimension.Value())) {
return *this;
}
ACE_DCHECK(unit_ == dimension.unit_);
return Dimension(value_ - dimension.value_, unit_);
}
@ -165,6 +184,12 @@ public:
return (value_ < dimension.value_);
}
std::string ToString() const
{
static std::string units[5] = {"px", "vp", "fp", "%", "lpx"};
return std::to_string(value_).append(units[static_cast<int>(unit_)]);
}
private:
double value_ = 0.0;
DimensionUnit unit_ = DimensionUnit::PX;

View File

@ -16,6 +16,7 @@
#include "base/geometry/matrix4.h"
#include <algorithm>
#include <cmath>
#include "base/utils/utils.h"
@ -23,6 +24,7 @@ namespace OHOS::Ace {
namespace {
constexpr int32_t MATRIX_LENGTH = Matrix4::DIMENSION * Matrix4::DIMENSION;
constexpr float ANGLE_UNIT = 0.017453f; // PI / 180
inline bool IsEqual(const float& left, const float& right)
{
@ -80,6 +82,33 @@ Matrix4 Matrix4::CreateRotate(float angle, float dx, float dy, float dz)
cosValue + (z * z * (1.0f - cosValue)), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
}
Matrix4 Matrix4::CreateMatrix2D(float m00, float m10, float m01, float m11, float m03, float m13)
{
return Matrix4(
m00, m01, 0.0f, m03,
m10, m11, 0.0f, m13,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
Matrix4 Matrix4::CreateSkew(float x, float y)
{
return Matrix4(
1.0f, std::tan(x * ANGLE_UNIT), 0.0f, 0.0f,
std::tan(y * ANGLE_UNIT), 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
Matrix4 Matrix4::CreatePerspective(float distance)
{
auto result = CreateIdentity();
if (GreatNotEqual(distance, 0.0f)) {
result.matrix4x4_[2][3] = -1.0f / distance;
}
return result;
}
Matrix4 Matrix4::Invert(const Matrix4& matrix)
{
Matrix4 inverted = CreateInvert(matrix);
@ -305,4 +334,85 @@ float Matrix4::operator()(int32_t row, int32_t col) const
return matrix4x4_[row][col];
}
double Matrix4::Determinant() const
{
if (this->IsIdentityMatrix()) {
return 1.0;
}
double m00 = matrix4x4_[0][0];
double m01 = matrix4x4_[0][1];
double m02 = matrix4x4_[0][2];
double m03 = matrix4x4_[0][3];
double m10 = matrix4x4_[1][0];
double m11 = matrix4x4_[1][1];
double m12 = matrix4x4_[1][2];
double m13 = matrix4x4_[1][3];
double m20 = matrix4x4_[2][0];
double m21 = matrix4x4_[2][1];
double m22 = matrix4x4_[2][2];
double m23 = matrix4x4_[2][3];
double m30 = matrix4x4_[3][0];
double m31 = matrix4x4_[3][1];
double m32 = matrix4x4_[3][2];
double m33 = matrix4x4_[3][3];
double b00 = m00 * m11 - m01 * m10;
double b01 = m00 * m12 - m02 * m10;
double b02 = m00 * m13 - m03 * m10;
double b03 = m01 * m12 - m02 * m11;
double b04 = m01 * m13 - m03 * m11;
double b05 = m02 * m13 - m03 * m12;
double b06 = m20 * m31 - m21 * m30;
double b07 = m20 * m32 - m22 * m30;
double b08 = m20 * m33 - m23 * m30;
double b09 = m21 * m32 - m22 * m31;
double b10 = m21 * m33 - m23 * m31;
double b11 = m22 * m33 - m23 * m32;
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
}
void Matrix4::Transpose()
{
std::swap(matrix4x4_[0][1], matrix4x4_[1][0]);
std::swap(matrix4x4_[0][2], matrix4x4_[2][0]);
std::swap(matrix4x4_[0][3], matrix4x4_[3][0]);
std::swap(matrix4x4_[1][2], matrix4x4_[2][1]);
std::swap(matrix4x4_[1][3], matrix4x4_[3][1]);
std::swap(matrix4x4_[2][3], matrix4x4_[3][2]);
}
void Matrix4::MapScalars(const float src[DIMENSION], float dst[DIMENSION]) const
{
float storage[DIMENSION];
float* result = (src == dst) ? storage : dst;
for (int i = 0; i < DIMENSION; i++) {
float value = 0;
for (int j = 0; j < DIMENSION; j++) {
value += matrix4x4_[j][i] * src[j];
}
result[i] = value;
}
if (storage == result) {
std::copy_n(result, DIMENSION, dst);
}
}
std::string Matrix4::ToString() const
{
std::string out;
for (auto& i : matrix4x4_) {
for (float j : i) {
out += std::to_string(j);
out += ",";
}
out += "\n";
}
return out;
}
} // namespace OHOS::Ace

View File

@ -20,11 +20,11 @@
namespace OHOS::Ace {
class ACE_EXPORT Matrix4 final {
class ACE_EXPORT Matrix4 {
public:
// Matrix dimension is 4X4.
static constexpr int32_t DIMENSION = 4;
// Crate an identity matrix.
// Create an identity matrix.
static Matrix4 CreateIdentity();
// Multiplies this matrix by another that translates coordinates by the vector (x, y, z).
static Matrix4 CreateTranslate(float x, float y, float z);
@ -32,6 +32,13 @@ public:
static Matrix4 CreateScale(float x, float y, float z);
// Multiplies this matrix by another that rotates coordinates through angle degrees about the vector (dx, dy, dz).
static Matrix4 CreateRotate(float angle, float dx, float dy, float dz);
static Matrix4 CreateMatrix2D(float m00, float m10, float m01, float m11, float m03, float m13);
// Multiplies this matrix by another that skew through angle degrees.
static Matrix4 CreateSkew(float x, float y);
// Create an perspective matrix, the distance value represents the distance between the user and the z=0 plane. not
// support percent
static Matrix4 CreatePerspective(float distance);
// Returns the inverse of this matrix. Returns the identity if this matrix cannot be inverted;
static Matrix4 Invert(const Matrix4& matrix);
@ -58,6 +65,28 @@ public:
Point operator*(const Point& point);
Matrix4& operator=(const Matrix4& matrix);
float operator[](int32_t index) const;
inline float Get(int32_t row, int32_t col) const
{
ACE_DCHECK((unsigned)row < DIMENSION);
ACE_DCHECK((unsigned)col < DIMENSION);
return matrix4x4_[col][row];
}
inline void Set(int32_t row, int32_t col, float value)
{
ACE_DCHECK((unsigned)row < DIMENSION);
ACE_DCHECK((unsigned)col < DIMENSION);
matrix4x4_[col][row] = value;
}
double Determinant() const;
void Transpose();
void MapScalars(const float src[DIMENSION], float dst[DIMENSION]) const;
inline void MapScalars(float vec[DIMENSION], int length = DIMENSION) const
{
if (length == DIMENSION) {
this->MapScalars(vec, vec);
}
}
std::string ToString() const;
private:
static Matrix4 CreateInvert(const Matrix4& matrix);

View File

@ -21,6 +21,7 @@
#include "base/geometry/size.h"
#include "base/utils/utils.h"
#include "core/components/common/properties/animation_option.h"
namespace OHOS::Ace {
@ -34,6 +35,8 @@ public:
{
deltaX_ = 0.0;
deltaY_ = 0.0;
deltaXAnimationOption_ = AnimationOption();
deltaYAnimationOption_ = AnimationOption();
}
static Offset Zero()
@ -66,14 +69,26 @@ public:
return deltaY_;
}
void SetX(double x)
void SetX(double x, const AnimationOption& option = AnimationOption())
{
deltaX_ = x;
deltaXAnimationOption_ = option;
}
void SetY(double y)
void SetY(double y, const AnimationOption& option = AnimationOption())
{
deltaY_ = y;
deltaYAnimationOption_ = option;
}
AnimationOption GetXAnimationOption() const
{
return deltaXAnimationOption_;
}
AnimationOption GetYAnimationOption() const
{
return deltaYAnimationOption_;
}
double GetDistance() const
@ -143,6 +158,8 @@ public:
private:
double deltaX_ = 0.0;
double deltaY_ = 0.0;
AnimationOption deltaXAnimationOption_;
AnimationOption deltaYAnimationOption_;
};
} // namespace OHOS::Ace

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021 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 "base/geometry/quaternion.h"
#include <cmath>
namespace OHOS::Ace {
namespace {
constexpr double KEPSILON = 1e-5;
} // namespace
Quaternion Quaternion::Slerp(const Quaternion& to, double t) const
{
if (t < 0.0 || t > 1.0) {
// https://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/index.htm
// a scalar between 0.0 (at from) and 1.0 (at to)
return *this;
}
Quaternion from = *this;
double cosHalfAngle = from.x_ * to.x_ + from.y_ * to.y_ + from.z_ * to.z_ + from.w_ * to.w_;
if (cosHalfAngle < 0.0) {
// Since the half angle is > 90 degrees, the full rotation angle would
// exceed 180 degrees. The quaternions (x, y, z, w) and (-x, -y, -z, -w)
// represent the same rotation. Flipping the orientation of either
// quaternion ensures that the half angle is less than 90 and that we are
// taking the shortest path.
from = from.flip();
cosHalfAngle = -cosHalfAngle;
}
// Ensure that acos is well behaved at the boundary.
if (cosHalfAngle > 1.0) {
cosHalfAngle = 1.0;
}
double sinHalfAngle = std::sqrt(1.0 - cosHalfAngle * cosHalfAngle);
if (sinHalfAngle < KEPSILON) {
// Quaternions share common axis and angle.
return *this;
}
double half_angle = std::acos(cosHalfAngle);
double scaleA = std::sin((1.0 - t) * half_angle) / sinHalfAngle;
double scaleB = std::sin(t * half_angle) / sinHalfAngle;
return (scaleA * from) + (scaleB * to);
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H
namespace OHOS::Ace {
class Quaternion {
public:
Quaternion() = default;
Quaternion(double x, double y, double z, double w) : x_(x), y_(y), z_(z), w_(w) {}
~Quaternion() = default;
double GetX() const
{
return x_;
}
double GetY() const
{
return y_;
}
double GetZ() const
{
return z_;
}
double GetW() const
{
return w_;
}
void SetX(double x)
{
x_ = x;
}
void SetY(double y)
{
y_ = y;
}
void SetZ(double z)
{
z_ = z;
}
void SetW(double w)
{
w_ = w;
}
Quaternion operator+(const Quaternion& q) const
{
auto x = this->x_ + q.x_;
auto y = this->y_ + q.y_;
auto z = this->z_ + q.z_;
auto w = this->w_ + q.w_;
return Quaternion(x, y, z, w);
}
Quaternion operator*(const Quaternion& q) const
{
auto x = w_ * q.x_ + x_ * q.w_ + y_ * q.z_ - z_ * q.y_;
auto y = w_ * q.y_ - x_ * q.z_ + y_ * q.w_ + z_ * q.x_;
auto z = w_ * q.z_ + x_ * q.y_ - y_ * q.x_ + z_ * q.w_;
auto w = w_ * q.w_ - x_ * q.x_ - y_ * q.y_ - z_ * q.z_;
return Quaternion(x, y, z, w);
}
Quaternion inverse() const
{
return { -x_, -y_, -z_, w_ };
}
Quaternion flip() const
{
return { -x_, -y_, -z_, -w_ };
}
// Blends with the given quaternion, |q|, via spherical linear interpolation.
// Values of |t| in the range [0, 1] will interpolate between |this| and |q|,
// and values outside that range will extrapolate beyond in either direction.
Quaternion Slerp(const Quaternion& q, double t) const;
private:
double x_ = 0.0;
double y_ = 0.0;
double z_ = 0.0;
double w_ = 0.0;
};
// |s| is an arbitrary, real constant.
inline Quaternion operator*(const Quaternion& q, double s)
{
return Quaternion(q.GetX() * s, q.GetY() * s, q.GetZ() * s, q.GetW() * s);
}
// |s| is an arbitrary, real constant.
inline Quaternion operator*(double s, const Quaternion& q)
{
return Quaternion(q.GetX() * s, q.GetY() * s, q.GetZ() * s, q.GetW() * s);
}
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_QUATERNION_H

View File

@ -134,21 +134,12 @@ public:
return rect_.Height();
}
bool NearEqual(const RRect& rrect) const
{
return rrect.GetCorner().bottomLeftRadius == corner_.bottomLeftRadius &&
rrect.GetCorner().bottomRightRadius == corner_.bottomRightRadius &&
rrect.GetCorner().topLeftRadius == corner_.topLeftRadius &&
rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.GetRect() == rect_;
}
bool operator==(const RRect& rrect) const
{
return rrect.GetCorner().bottomLeftRadius == corner_.bottomLeftRadius &&
rrect.GetCorner().bottomRightRadius == corner_.bottomRightRadius &&
rrect.GetCorner().topLeftRadius == corner_.topLeftRadius &&
rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.Height() == rect_.Height() &&
rrect.Width() == rect_.Width();
rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.GetRect() == rect_;
}
RRect& operator+=(const Offset& offset)

View File

@ -0,0 +1,654 @@
/*
* Copyright (c) 2021 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 "base/geometry/transform_util.h"
namespace OHOS::Ace {
namespace {
float Length3(const float v[3])
{
double vd[3] = { v[0], v[1], v[2] };
return static_cast<float>(std::sqrt(vd[0] * vd[0] + vd[1] * vd[1] + vd[2] * vd[2]));
}
template<int n>
float Dot(const float* a, const float* b)
{
double total = 0.0;
for (int i = 0; i < n; ++i) {
total += a[i] * b[i];
}
return static_cast<float>(total);
}
template<int n>
void Combine(float* out, const float* a, const float* b, double scaleA, double scaleB)
{
for (int i = 0; i < n; ++i) {
out[i] = static_cast<float>(a[i] * scaleA + b[i] * scaleB);
}
}
void Cross3(float out[3], const float a[3], const float b[3])
{
float x = a[1] * b[2] - a[2] * b[1];
float y = a[2] * b[0] - a[0] * b[2];
float z = a[0] * b[1] - a[1] * b[0];
out[0] = x;
out[1] = y;
out[2] = z;
}
// Returns false if the matrix cannot be normalized.
bool Normalize(Matrix4& m)
{
if (NearZero(m.Get(3, 3))) {
return false;
}
float scale = 1.0f / m.Get(3, 3);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
auto value = m.Get(i, j) * scale;
m.Set(i, j, value);
}
}
return true;
}
Matrix4 BuildPerspectiveMatrix(const DecomposedTransform& decomp)
{
Matrix4 matrix = Matrix4::CreateIdentity();
for (int i = 0; i < 4; i++) {
matrix.Set(3, i, decomp.perspective[i]);
}
return matrix;
}
Matrix4 BuildTranslationMatrix(const DecomposedTransform& decomp)
{
Matrix4 matrix = Matrix4::CreateIdentity();
float dx = decomp.translate[0];
float dy = decomp.translate[1];
float dz = decomp.translate[2];
if (NearZero(dx) && NearZero(dy) && NearZero(dz)) {
return matrix;
}
matrix.Set(0, 3, dx);
matrix.Set(1, 3, dy);
matrix.Set(2, 3, dz);
return matrix;
}
Matrix4 BuildRotationMatrix(const DecomposedTransform& decomp)
{
Matrix4 matrix4;
double x = decomp.quaternion.GetX();
double y = decomp.quaternion.GetY();
double z = decomp.quaternion.GetZ();
double w = decomp.quaternion.GetW();
matrix4.Set(0, 0, static_cast<float>(1.0 - 2.0 * (y * y + z * z)));
matrix4.Set(1, 0, static_cast<float>(2.0 * (x * y + z * w)));
matrix4.Set(2, 0, static_cast<float>(2.0 * (x * z - y * w)));
matrix4.Set(3, 0, 0);
matrix4.Set(0, 1, static_cast<float>(2.0 * (x * y - z * w)));
matrix4.Set(1, 1, static_cast<float>(1.0 - 2.0 * (x * x + z * z)));
matrix4.Set(2, 1, static_cast<float>(2.0 * (y * z + x * w)));
matrix4.Set(3, 1, 0);
matrix4.Set(0, 2, static_cast<float>(2.0 * (x * z + y * w)));
matrix4.Set(1, 2, static_cast<float>(2.0 * (y * z - x * w)));
matrix4.Set(2, 2, static_cast<float>(1.0 - 2.0 * (x * x + y * y)));
matrix4.Set(3, 2, 0);
matrix4.Set(0, 3, 0);
matrix4.Set(1, 3, 0);
matrix4.Set(2, 3, 0);
matrix4.Set(3, 3, 1);
return matrix4;
}
Matrix4 BuildSkewMatrix(const DecomposedTransform& decomp)
{
Matrix4 matrix = Matrix4::CreateIdentity();
Matrix4 temp = Matrix4::CreateIdentity();
if (decomp.skew[2]) {
temp.Set(1, 2, decomp.skew[2]);
matrix = matrix * temp;
}
if (decomp.skew[1]) {
temp.Set(1, 2, 0);
temp.Set(0, 2, decomp.skew[1]);
matrix = matrix * temp;
}
if (decomp.skew[0]) {
temp.Set(0, 2, 0);
temp.Set(0, 1, decomp.skew[0]);
matrix = matrix * temp;
}
return matrix;
}
Matrix4 BuildScaleMatrix(const DecomposedTransform& decomp)
{
Matrix4 matrix = Matrix4::CreateIdentity();
matrix.SetScale(decomp.scale[0], decomp.scale[1], decomp.scale[2]);
return matrix;
}
Matrix4 ComposeTransform(const Matrix4& perspective, const Matrix4& translation, const Matrix4& rotation,
const Matrix4& skew, const Matrix4& scale)
{
Matrix4 matrix = Matrix4::CreateIdentity();
matrix = matrix * perspective;
matrix = matrix * translation;
matrix = matrix * rotation;
matrix = matrix * skew;
matrix = matrix * scale;
return matrix;
}
} // namespace
TranslateOperation TranslateOperation::Blend(
const TranslateOperation& to, const TranslateOperation& from, float progress)
{
TranslateOperation ret;
float scaleA = progress;
float scaleB = 1 - progress;
ret.dx = to.dx * scaleA + from.dx * scaleB;
ret.dy = to.dy * scaleA + from.dy * scaleB;
ret.dz = to.dz * scaleA + from.dz * scaleB;
return ret;
}
ScaleOperation ScaleOperation::Blend(const ScaleOperation& to, const ScaleOperation& from, float progress)
{
ScaleOperation ret;
float scaleA = progress;
float scaleB = 1 - progress;
ret.scaleX = to.scaleX * scaleA + from.scaleX * scaleB;
ret.scaleY = to.scaleY * scaleA + from.scaleY * scaleB;
ret.scaleZ = to.scaleZ * scaleA + from.scaleZ * scaleB;
return ret;
}
SkewOperation SkewOperation::Blend(const SkewOperation& to, const SkewOperation& from, float progress)
{
SkewOperation ret;
float scaleA = progress;
float scaleB = 1 - progress;
ret.skewX = to.skewX * scaleA + from.skewX * scaleB;
ret.skewY = to.skewY * scaleA + from.skewY * scaleB;
return ret;
}
RotateOperation RotateOperation::Blend(const RotateOperation& to, const RotateOperation& from, float progress)
{
RotateOperation ret;
float scaleA = progress;
float scaleB = 1 - progress;
ret.angle = to.angle * scaleA + from.angle * scaleB;
ret.dx = to.dx;
ret.dy = to.dy;
ret.dz = to.dz;
// rotate vector is (0,0,0) is error
if (NearZero(ret.dx) && NearZero(ret.dy) && NearZero(ret.dz)) {
ret.dx = from.dx;
ret.dy = from.dy;
ret.dz = from.dz;
}
return ret;
}
PerspectiveOperation PerspectiveOperation::Blend(
const PerspectiveOperation& to, const PerspectiveOperation& from, float progress)
{
PerspectiveOperation ret;
ret.distance = from.distance + (to.distance - from.distance) * progress;
return ret;
}
TransformOperation TransformOperation::Blend(
const TransformOperation& to, const TransformOperation& from, float progress)
{
TransformOperation ret;
if (to.type_ == from.type_ && to.type_ == TransformOperationType::UNDEFINED) {
return ret;
} else if (to.type_ == TransformOperationType::UNDEFINED) {
ret.type_ = from.type_;
BlendInner(Create(ret.type_), from, progress, ret);
} else if (from.type_ == TransformOperationType::UNDEFINED) {
ret.type_ = to.type_;
BlendInner(to, Create(ret.type_), progress, ret);
} else if (to.type_ == from.type_) {
ret.type_ = to.type_;
BlendInner(to, from, progress, ret);
}
return ret;
}
TransformOperation TransformOperation::Create(TransformOperationType type)
{
TransformOperation ret;
ret.type_ = type;
switch (ret.type_) {
case TransformOperationType::TRANSLATE:
ret.translateOperation_ = TranslateOperation();
break;
case TransformOperationType::SCALE:
ret.scaleOperation_ = ScaleOperation();
break;
case TransformOperationType::SKEW:
ret.skewOperation_ = SkewOperation();
break;
case TransformOperationType::ROTATE:
ret.rotateOperation_ = RotateOperation();
break;
case TransformOperationType::MATRIX:
ret.matrix4_ = Matrix4::CreateIdentity();
break;
case TransformOperationType::PERSPECTIVE:
ret.perspectiveOperation_ = PerspectiveOperation();
break;
case TransformOperationType::UNDEFINED:
break;
default:
break;
}
return ret;
}
void TransformOperation::BlendInner(
const TransformOperation& to, const TransformOperation& from, float progress, TransformOperation& ret)
{
switch (ret.type_) {
case TransformOperationType::TRANSLATE:
ret.translateOperation_ =
TranslateOperation::Blend(to.translateOperation_, from.translateOperation_, progress);
break;
case TransformOperationType::SCALE:
ret.scaleOperation_ = ScaleOperation::Blend(to.scaleOperation_, from.scaleOperation_, progress);
break;
case TransformOperationType::SKEW:
ret.skewOperation_ = SkewOperation::Blend(to.skewOperation_, from.skewOperation_, progress);
break;
case TransformOperationType::ROTATE:
ret.rotateOperation_ = RotateOperation::Blend(to.rotateOperation_, from.rotateOperation_, progress);
break;
case TransformOperationType::MATRIX: {
DecomposedTransform toTransform;
DecomposedTransform fromTransform;
if (TransformUtil::DecomposeTransform(toTransform, to.matrix4_) &&
TransformUtil::DecomposeTransform(fromTransform, from.matrix4_)) {
auto result = TransformUtil::BlendDecomposedTransforms(toTransform, fromTransform, progress);
ret.matrix4_ = TransformUtil::ComposeTransform(result);
} else {
LOGE("DecomposeTransform failed");
}
break;
}
case TransformOperationType::PERSPECTIVE:
ret.perspectiveOperation_ =
PerspectiveOperation::Blend(to.perspectiveOperation_, from.perspectiveOperation_, progress);
break;
case TransformOperationType::UNDEFINED:
break;
default:
break;
}
}
std::string DecomposedTransform::ToString() const
{
std::string out;
out.append("translate: ")
.append(std::to_string(translate[0]))
.append(" ")
.append(std::to_string(translate[1]))
.append(" ")
.append(std::to_string(translate[2]))
.append("\n")
.append("scale: ")
.append(std::to_string(scale[0]))
.append(" ")
.append(std::to_string(scale[1]))
.append(" ")
.append(std::to_string(scale[2]))
.append("\n")
.append("skew: ")
.append(std::to_string(skew[0]))
.append(" ")
.append(std::to_string(skew[1]))
.append(" ")
.append(std::to_string(skew[2]))
.append("\n")
.append("perspective: ")
.append(std::to_string(perspective[0]))
.append(" ")
.append(std::to_string(perspective[1]))
.append(" ")
.append(std::to_string(perspective[2]))
.append(" ")
.append(std::to_string(perspective[3]))
.append("\n")
.append("quaternion: ")
.append(std::to_string(quaternion.GetX()))
.append(" ")
.append(std::to_string(quaternion.GetY()))
.append(" ")
.append(std::to_string(quaternion.GetZ()))
.append(" ")
.append(std::to_string(quaternion.GetW()))
.append("\n");
return out;
}
TransformOperations TransformOperations::Blend(
const TransformOperations& to, const TransformOperations& from, float progress)
{
TransformOperations result;
to.BlendInner(from, progress, result);
return result;
}
std::size_t TransformOperations::MatchingLength(const TransformOperations& to, const TransformOperations& from) const
{
auto numOperations = std::min(to.operations_.size(), from.operations_.size());
for (std::size_t i = 0; i < numOperations; i++) {
auto& first = to.operations_[i];
auto& second = from.operations_[i];
if (first.type_ != TransformOperationType::UNDEFINED || second.type_ != TransformOperationType::UNDEFINED) {
if (first.type_ != second.type_) {
return i;
}
}
}
return std::max(to.operations_.size(), from.operations_.size());
}
void TransformOperations::ParseOperationsToMatrix(std::vector<TransformOperation>& operations)
{
for (auto& operation : operations) {
ParseOperationToMatrix(operation);
}
}
void TransformOperations::ParseOperationToMatrix(TransformOperation& operation)
{
switch (operation.type_) {
case TransformOperationType::TRANSLATE: {
auto& translate = operation.translateOperation_;
float dx = translate.dx.Value();
float dy = translate.dy.Value();
float dz = translate.dz.Value();
operation.matrix4_ = Matrix4::CreateTranslate(dx, dy, dz);
break;
}
case TransformOperationType::SCALE: {
auto& scale = operation.scaleOperation_;
operation.matrix4_ = Matrix4::CreateScale(scale.scaleX, scale.scaleY, scale.scaleZ);
break;
}
case TransformOperationType::SKEW: {
auto& skew = operation.skewOperation_;
operation.matrix4_ = Matrix4::CreateSkew(skew.skewX, skew.skewY);
break;
}
case TransformOperationType::ROTATE: {
auto& rotate = operation.rotateOperation_;
operation.matrix4_ = Matrix4::CreateRotate(rotate.angle, rotate.dx, rotate.dy, rotate.dz);
break;
}
case TransformOperationType::PERSPECTIVE: {
auto& perspective = operation.perspectiveOperation_;
double distance = perspective.distance.Value();
operation.matrix4_ = Matrix4::CreatePerspective(distance);
break;
}
case TransformOperationType::MATRIX:
case TransformOperationType::UNDEFINED:
break;
}
}
void TransformOperations::BlendInner(const TransformOperations& from, float progress, TransformOperations& out) const
{
auto matchPrefix = MatchingLength(*this, from);
auto fromSize = from.operations_.size();
auto toSize = operations_.size();
// find most match type transform
for (std::size_t i = 0; i < matchPrefix; i++) {
const auto& fromTransformOperation = i >= fromSize ? TransformOperation() : from.operations_[i];
const auto& toTransformOperation = i >= toSize ? TransformOperation() : operations_[i];
out.operations_.push_back(TransformOperation::Blend(toTransformOperation, fromTransformOperation, progress));
}
// type not match
if (matchPrefix < std::max(fromSize, toSize)) {
TransformOperation fromTransformOperation;
fromTransformOperation.type_ = TransformOperationType::MATRIX;
fromTransformOperation.matrix4_ = from.ComputerRemaining(matchPrefix);
TransformOperation toTransformOperation;
toTransformOperation.type_ = TransformOperationType::MATRIX;
toTransformOperation.matrix4_ = ComputerRemaining(matchPrefix);
out.operations_.push_back(TransformOperation::Blend(toTransformOperation, fromTransformOperation, progress));
}
}
Matrix4 TransformOperations::ComputerRemaining(std::size_t startOffset) const
{
Matrix4 result = Matrix4::CreateIdentity();
for (auto i = startOffset; i < operations_.size(); i++) {
result = result * operations_[i].matrix4_;
}
return result;
}
DecomposedTransform TransformUtil::BlendDecomposedTransforms(
const DecomposedTransform& to, const DecomposedTransform& from, double progress)
{
DecomposedTransform ret;
Combine<3>(ret.translate, to.translate, from.translate, progress, 1.0 - progress);
Combine<3>(ret.scale, to.scale, from.scale, progress, 1.0 - progress);
Combine<3>(ret.skew, to.skew, from.skew, progress, 1.0 - progress);
Combine<4>(ret.perspective, to.perspective, from.perspective, progress, 1.0 - progress);
ret.quaternion = from.quaternion.Slerp(to.quaternion, progress);
return ret;
}
bool TransformUtil::DecomposeTransform(DecomposedTransform& out, const Matrix4& transform)
{
Matrix4 matrix = transform;
if (!Normalize(matrix)) {
return false;
}
Matrix4 perspectiveMatrix = matrix;
for (int i = 0; i < 3; i++) {
perspectiveMatrix.Set(3, i, 0.0);
}
perspectiveMatrix.Set(3, 3, 1.0);
if (NearZero(std::abs(perspectiveMatrix.Determinant()))) {
return false;
}
if (!NearZero(matrix.Get(3, 0)) || !NearZero(matrix.Get(3, 1)) || !NearZero(matrix.Get(3, 2))) {
float rhs[4] = { matrix.Get(3, 0), matrix.Get(3, 1), matrix.Get(3, 2), matrix.Get(3, 3) };
Matrix4 inversePerspectiveMatrix = Matrix4::Invert(perspectiveMatrix);
Matrix4 transposedInversePerspectiveMatrix = inversePerspectiveMatrix;
transposedInversePerspectiveMatrix.Transpose();
transposedInversePerspectiveMatrix.MapScalars(rhs, 4);
for (int32_t i = 0; i < 4; i++) {
out.perspective[i] = rhs[i];
}
} else {
// No perspective.
for (int i = 0; i < 3; ++i)
out.perspective[i] = 0.0;
out.perspective[3] = 1.0;
}
for (int32_t i = 0; i < 3; i++) {
out.translate[i] = matrix.Get(i, 3);
}
// Copy of matrix is stored in column major order to facilitate column-level
// operations.
float column[3][3];
for (int32_t i = 0; i < 3; i++) {
for (int32_t j = 0; j < 3; j++) {
column[i][j] = matrix.Get(j, i);
}
}
// Compute X scale factor and normalize first column.
out.scale[0] = Length3(column[0]);
if (out.scale[0] != 0.0) {
column[0][0] /= out.scale[0];
column[0][1] /= out.scale[0];
column[0][2] /= out.scale[0];
}
// Compute XY shear factor and make 2nd column orthogonal to 1st.
out.skew[0] = Dot<3>(column[0], column[1]);
Combine<3>(column[1], column[1], column[0], 1.0, -out.skew[0]);
// Now, compute Y scale and normalize 2nd column.
out.scale[1] = Length3(column[1]);
if (out.scale[1] != 0.0) {
column[1][0] /= out.scale[1];
column[1][1] /= out.scale[1];
column[1][2] /= out.scale[1];
}
out.skew[0] /= out.scale[1];
// Compute XZ and YZ shears, orthogonalize the 3rd column.
out.skew[1] = Dot<3>(column[0], column[2]);
Combine<3>(column[2], column[2], column[0], 1.0, -out.skew[1]);
out.skew[2] = Dot<3>(column[1], column[2]);
Combine<3>(column[2], column[2], column[1], 1.0, -out.skew[2]);
// Next, get Z scale and normalize the 3rd column.
out.scale[2] = Length3(column[2]);
if (out.scale[2] != 0.0) {
column[2][0] /= out.scale[2];
column[2][1] /= out.scale[2];
column[2][2] /= out.scale[2];
}
out.skew[1] /= out.scale[2];
out.skew[2] /= out.scale[2];
// At this point, the matrix is orthonormal.
// Check for a coordinate system flip. If the determinant
// is -1, then negate the matrix and the scaling factors.
// only 1 axis is flipped when the determinant is negative. Verify if it is
// correct to flip all of the scales and matrix elements, as this introduces
// rotation for the simple case of a single axis scale inversion.
float pdum3[3];
Cross3(pdum3, column[1], column[2]);
if (Dot<3>(column[0], pdum3) < 0) {
for (int i = 0; i < 3; i++) {
out.scale[i] *= -1.0;
for (int j = 0; j < 3; ++j)
column[i][j] *= -1.0;
}
}
// See https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion.
// Note: deviating from spec (http://www.w3.org/TR/css3-transforms/)
// which has a degenerate case of zero off-diagonal elements in the
// orthonormal matrix, which leads to errors in determining the sign
// of the quaternions.
double q_xx = column[0][0];
double q_xy = column[1][0];
double q_xz = column[2][0];
double q_yx = column[0][1];
double q_yy = column[1][1];
double q_yz = column[2][1];
double q_zx = column[0][2];
double q_zy = column[1][2];
double q_zz = column[2][2];
double r, s, t, x, y, z, w;
t = q_xx + q_yy + q_zz;
if (t > 0) {
r = std::sqrt(1.0 + t);
s = 0.5 / r;
w = 0.5 * r;
x = (q_zy - q_yz) * s;
y = (q_xz - q_zx) * s;
z = (q_yx - q_xy) * s;
} else if (q_xx > q_yy && q_xx > q_zz) {
r = std::sqrt(1.0 + q_xx - q_yy - q_zz);
s = 0.5 / r;
x = 0.5 * r;
y = (q_xy + q_yx) * s;
z = (q_xz + q_zx) * s;
w = (q_zy - q_yz) * s;
} else if (q_yy > q_zz) {
r = std::sqrt(1.0 - q_xx + q_yy - q_zz);
s = 0.5 / r;
x = (q_xy + q_yx) * s;
y = 0.5 * r;
z = (q_yz + q_zy) * s;
w = (q_xz - q_zx) * s;
} else {
r = std::sqrt(1.0 - q_xx - q_yy + q_zz);
s = 0.5 / r;
x = (q_xz + q_zx) * s;
y = (q_yz + q_zy) * s;
z = 0.5 * r;
w = (q_yx - q_xy) * s;
}
out.quaternion.SetX(static_cast<float>(x));
out.quaternion.SetY(static_cast<float>(y));
out.quaternion.SetZ(static_cast<float>(z));
out.quaternion.SetW(static_cast<float>(w));
return true;
}
Matrix4 TransformUtil::ComposeTransform(const struct DecomposedTransform& decomp)
{
Matrix4 perspective = BuildPerspectiveMatrix(decomp);
Matrix4 translation = BuildTranslationMatrix(decomp);
Matrix4 rotation = BuildRotationMatrix(decomp);
Matrix4 skew = BuildSkewMatrix(decomp);
Matrix4 scale = BuildScaleMatrix(decomp);
return OHOS::Ace::ComposeTransform(perspective, translation, rotation, skew, scale);
}
} // namespace OHOS::Ace

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H
#include <utility>
#include <vector>
#include "base/geometry/dimension.h"
#include "base/geometry/matrix4.h"
#include "base/geometry/quaternion.h"
namespace OHOS::Ace {
struct ACE_EXPORT TranslateOperation {
TranslateOperation() = default;
TranslateOperation(Dimension dx, Dimension dy, Dimension dz = Dimension {}) : dx(dx), dy(dy), dz(dz) {}
Dimension dx;
Dimension dy;
Dimension dz;
static TranslateOperation Blend(const TranslateOperation& to, const TranslateOperation& from, float progress);
};
struct ACE_EXPORT ScaleOperation {
ScaleOperation() = default;
ScaleOperation(float x, float y, float z) : scaleX(x), scaleY(y), scaleZ(z) {}
float scaleX = 1.0f;
float scaleY = 1.0f;
float scaleZ = 1.0f;
static ScaleOperation Blend(const ScaleOperation& to, const ScaleOperation& from, float progress);
};
struct ACE_EXPORT SkewOperation {
SkewOperation() = default;
SkewOperation(float x, float y) : skewX(x), skewY(y) {};
float skewX = 0.0f;
float skewY = 0.0f;
static SkewOperation Blend(const SkewOperation& to, const SkewOperation& from, float progress);
};
struct ACE_EXPORT RotateOperation {
RotateOperation() = default;
RotateOperation(float x, float y, float z, float angle) : dx(x), dy(y), dz(z), angle(angle) {};
float dx = 0.0f;
float dy = 0.0f;
float dz = 0.0f;
float angle = 0.0f;
static RotateOperation Blend(const RotateOperation& to, const RotateOperation& from, float progress);
};
struct ACE_EXPORT PerspectiveOperation {
PerspectiveOperation() = default;
PerspectiveOperation(const Dimension& dis) : distance(dis) {};
Dimension distance;
static PerspectiveOperation Blend(const PerspectiveOperation& to, const PerspectiveOperation& from, float progress);
};
struct ACE_EXPORT DecomposedTransform {
float translate[3] = { 0.0f, 0.0f, 0.0f };
float scale[3] = { 1.0f, 1.0f, 1.0f };
float skew[3] = { 0.0f, 0.0f, 0.0f };
float perspective[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
Quaternion quaternion;
std::string ToString() const;
};
enum class TransformOperationType {
TRANSLATE,
SCALE,
SKEW,
ROTATE,
MATRIX,
PERSPECTIVE,
UNDEFINED,
};
struct ACE_EXPORT TransformOperation {
TransformOperation() : type_(TransformOperationType::UNDEFINED) {};
TransformOperationType type_ = TransformOperationType::UNDEFINED;
Matrix4 matrix4_ = Matrix4::CreateIdentity();
union {
TranslateOperation translateOperation_;
ScaleOperation scaleOperation_;
SkewOperation skewOperation_;
RotateOperation rotateOperation_;
PerspectiveOperation perspectiveOperation_;
};
static TransformOperation Blend(const TransformOperation& to, const TransformOperation& from, float progress);
static TransformOperation Create(TransformOperationType type);
private:
static void BlendInner(
const TransformOperation& to, const TransformOperation& from, float progress, TransformOperation& out);
};
class ACE_EXPORT TransformOperations {
public:
static void ParseOperationsToMatrix(std::vector<TransformOperation>& operations);
static void ParseOperationToMatrix(TransformOperation& operations);
static TransformOperations Blend(const TransformOperations& to, const TransformOperations& from, float progress);
explicit TransformOperations(std::vector<TransformOperation> operation = std::vector<TransformOperation>())
: operations_(std::move(operation))
{}
std::vector<TransformOperation>& GetOperations()
{
return operations_;
}
const std::vector<TransformOperation>& GetOperations() const
{
return operations_;
}
Matrix4 ComputerRemaining(std::size_t startOffset) const;
protected:
std::vector<TransformOperation> operations_;
private:
std::size_t MatchingLength(const TransformOperations& to, const TransformOperations& from) const;
void BlendInner(const TransformOperations& from, float progress, TransformOperations& out) const;
};
class ACE_EXPORT TransformUtil final {
public:
static bool DecomposeTransform(DecomposedTransform& out, const Matrix4& transform);
static DecomposedTransform BlendDecomposedTransforms(
const DecomposedTransform& to, const DecomposedTransform& from, double progress);
static Matrix4 ComposeTransform(const DecomposedTransform& decomp);
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H

View File

@ -25,14 +25,14 @@ template("ace_base_i18n") {
source_set(target_name) {
defines += invoker.defines
deps = [
"$ace_flutter_engine_root:ace_libicu_$platform",
"$ace_root/frameworks/base/resource:ace_resource",
"$flutter_root:ace_libicu_$platform",
]
configs += [
":ace_base_i18n_config",
"$ace_root:ace_config",
"$flutter_root:icu_config_$platform",
"$ace_flutter_engine_root:icu_config_$platform",
]
# add base source file here

View File

@ -57,15 +57,15 @@ namespace {
#define CHECK_RETURN(status, ret) \
do { \
if (status > U_ZERO_ERROR) { \
if ((status) > U_ZERO_ERROR) { \
LOGE("status = %{public}d", static_cast<int32_t>(status)); \
return ret; \
return (ret); \
} \
} while (0)
#define CHECK_NO_RETURN(status) \
do { \
if (status > U_ZERO_ERROR) { \
if ((status) > U_ZERO_ERROR) { \
LOGE("status = %{public}d", static_cast<int32_t>(status)); \
} \
} while (0)
@ -74,6 +74,7 @@ const char JSON_PATH_CARVE = '.';
const char DEFAULT_LANGUAGE[] = "en-US";
constexpr uint32_t SEXAGENARY_CYCLE_SIZE = 60;
constexpr uint32_t GUIHAI_YEAR_RECENT = 3;
constexpr uint32_t SECONDS_IN_HOUR = 3600;
const char CHINESE_LEAP[] = u8"\u95f0";
const char CHINESE_FIRST[] = u8"\u521d";
@ -209,7 +210,7 @@ void Localization::SetLocaleImpl(const std::string& language, const std::string&
}
languageTag_.append("-").append(countryOrRegion);
fontLocale_ = languageTag_;
// Smiple chinese
// Simple chinese
if (languageTag_ == "zh-Hans-CN") {
languageTag_ = "zh-CN";
fontLocale_ = "";
@ -257,7 +258,7 @@ const std::string Localization::FormatDuration(uint32_t duration, bool needShowH
WaitingForInit();
UErrorCode status = U_ZERO_ERROR;
// duration greater than 1 hour, use hh:mm:ss;
if (!needShowHour && duration > 3600) {
if (!needShowHour && duration > SECONDS_IN_HOUR) {
needShowHour = true;
}
const char* engTimeFormat = needShowHour ? "hh:mm:ss" : "mm:ss";
@ -771,7 +772,7 @@ std::string Localization::GetErrorDescription(const std::string& errorIndex)
return "";
}
if (localJsonError && localJsonError->Contains(errorIndex)) {
if (localJsonError->Contains(errorIndex)) {
localJsonError = localJsonError->GetValue(errorIndex);
} else {
LOGE("read error json failed. error path: %{private}s.", errorIndex.c_str());

View File

@ -311,6 +311,15 @@ bool JsonValue::Replace(const char* key, const std::unique_ptr<JsonValue>& value
return true;
}
bool JsonValue::Delete(const char* key)
{
if (key == nullptr) {
return false;
}
cJSON_DeleteItemFromObject(object_, key);
return true;
}
std::string JsonValue::ToString()
{
std::string result;

View File

@ -46,7 +46,7 @@ public:
// get functions
bool GetBool() const;
bool GetBool(const std::string& key, bool defaultValue) const;
bool GetBool(const std::string& key, bool defaultValue = false) const;
int32_t GetInt() const;
int32_t GetInt(const std::string& key, int32_t defaultVal = 0) const;
uint32_t GetUInt() const;
@ -79,6 +79,9 @@ public:
bool Replace(const char* key, int32_t value);
bool Replace(const char* key, const std::unique_ptr<JsonValue>& value);
// delete functions
bool Delete(const char* key);
// serialize
std::string ToString();

View File

@ -22,20 +22,17 @@
namespace OHOS::Ace {
// eventType use int32_t type, no need enum class.
enum {
EXCEPTION_FRAMEWORK_APP_START = 951004000,
EXCEPTION_FRAMEWORK_PAGE_ROUTER = 951004001,
EXCEPTION_COMPONENT = 951004002,
EXCEPTION_API_CHANNEL = 951004003,
EXCEPTION_RENDER = 951004004,
EXCEPTION_JS = 951004005,
EXCEPTION_ANIMATION = 951004006,
EXCEPTION_EVENT = 951004007,
EXCEPTION_INTERNATIONALIZATION = 951004009,
EXCEPTION_ACCESSIBILITY = 951004010,
EXCEPTION_FORM = 951004011,
};
const std::string EXCEPTION_FRAMEWORK_APP_START = "FrameworkAppStartException";
const std::string EXCEPTION_FRAMEWORK_PAGE_ROUTER = "FrameworkPageRouterException";
const std::string EXCEPTION_COMPONENT = "ComponentException";
const std::string EXCEPTION_API_CHANNEL = "ApiChannelException";
const std::string EXCEPTION_RENDER = "RenderException";
const std::string EXCEPTION_JS = "JsException";
const std::string EXCEPTION_ANIMATION = "AnimationException";
const std::string EXCEPTION_EVENT = "EventException";
const std::string EXCEPTION_INTERNATIONALIZATION = "InternationalizationException";
const std::string EXCEPTION_ACCESSIBILITY = "AccessibilityException";
const std::string EXCEPTION_FORM = "FormException";
// EXCEPTION_FRAMEWORK_APP_START
enum class AppStartExcepType {
@ -141,7 +138,7 @@ enum class FormExcepType {
enum class RawEventType { WARNING, FREEZE, RECOVER };
struct EventInfo {
int32_t eventType = 0;
std::string eventType;
int32_t errorType = 0;
std::string pageUrl;
};
@ -149,6 +146,10 @@ struct EventInfo {
class ACE_EXPORT EventReport {
public:
static void SendEvent(const EventInfo& eventInfo);
static void SendJsCardRenderTimeEvent(
const std::string& sessionID,
const std::string& timeType,
uint64_t timeDelay);
static void SendAppStartException(AppStartExcepType type);
static void SendPageRouterException(PageRouterExcepType type, const std::string& pageUrl = "");

View File

@ -42,6 +42,8 @@
#define LOGE(fmt, ...) PRINT_LOG(ERROR, fmt, ##__VA_ARGS__)
#define LOGF(fmt, ...) PRINT_LOG(FATAL, fmt, ##__VA_ARGS__)
#define LOG_DESTROY() LOGI("destroyed")
#define PRINT_APP_LOG(level, fmt, ...) \
OHOS::Ace::LogWrapper::PrintLog(OHOS::Ace::LogDomain::JS_APP, OHOS::Ace::LogLevel::level, fmt, ##__VA_ARGS__)

View File

@ -18,13 +18,25 @@
#include <map>
#include <mutex>
#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
#include <malloc.h>
#endif
#include "base/log/dump_log.h"
#include "base/log/log.h"
#ifdef ACE_MEMORY_MONITOR
namespace OHOS::Ace {
void PurgeMallocCache()
{
#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
#if defined(__BIONIC__)
mallopt(M_PURGE, 0);
#endif
#endif
}
#ifdef ACE_MEMORY_MONITOR
class MemoryMonitorImpl : public MemoryMonitor {
public:
void Add(void* ptr) final
@ -114,7 +126,6 @@ MemoryMonitor& MemoryMonitor::GetInstance()
static MemoryMonitorImpl instance;
return instance;
}
#endif // ACE_MEMORY_MONITOR
} // namespace OHOS::Ace
#endif // ACE_MEMORY_MONITOR

View File

@ -22,10 +22,11 @@
#include "base/memory/type_info_base.h"
#include "base/utils/macros.h"
#ifdef ACE_MEMORY_MONITOR
namespace OHOS::Ace {
void PurgeMallocCache();
#ifdef ACE_MEMORY_MONITOR
class ACE_EXPORT MemoryMonitor {
public:
static MemoryMonitor& GetInstance();
@ -75,9 +76,8 @@ private:
}
};
};
#endif // ACE_MEMORY_MONITOR
} // namespace OHOS::Ace
#endif // ACE_MEMORY_MONITOR
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_MEMORY_MONITOR_H

View File

@ -22,40 +22,40 @@
// Generate 'TypeInfo' for each classes.
// And using hash code of its name for 'TypeId'.
#define DECLARE_CLASS_TYPE_INFO(classname) \
public: \
static const char* TypeName() \
{ \
return #classname; \
} \
static IdType TypeId() \
{ \
static IdType myTypeId = std::hash<std::string> {}(TypeName()); \
return myTypeId; \
} \
#define DECLARE_CLASS_TYPE_INFO(classname) \
public: \
static const char* TypeName() \
{ \
return #classname; \
} \
static TypeInfoBase::IdType TypeId() \
{ \
static TypeInfoBase::IdType myTypeId = std::hash<std::string> {}(TypeName()); \
return myTypeId; \
} \
DECLARE_CLASS_TYPE_SIZE(classname)
// Integrate it into class declaration to support 'DynamicCast'.
#define DECLARE_RELATIONSHIP_OF_CLASSES(classname, ...) DECLARE_CLASS_TYPE_INFO(classname) \
protected: \
template<class __T, class __O, class... __V> \
uintptr_t TrySafeCastById(IdType id) const \
uintptr_t TrySafeCastById(TypeInfoBase::IdType id) const \
{ \
VERIFY_DECLARED_CLASS(__T); \
uintptr_t ptr = __T::SafeCastById(id); \
return ptr != 0 ? ptr : TrySafeCastById<__O, __V...>(id); \
} \
template<class __T> \
uintptr_t TrySafeCastById(IdType id) const \
uintptr_t TrySafeCastById(TypeInfoBase::IdType id) const \
{ \
VERIFY_DECLARED_CLASS(__T); \
return __T::SafeCastById(id); \
} \
uintptr_t SafeCastById(IdType id) const override \
uintptr_t SafeCastById(TypeInfoBase::IdType id) const override \
{ \
return id == TypeId() ? reinterpret_cast<uintptr_t>(this) : TrySafeCastById<__VA_ARGS__>(id); \
} \
IdType GetTypeId() const override \
TypeInfoBase::IdType GetTypeId() const override \
{ \
return TypeId(); \
} \

View File

@ -36,6 +36,8 @@ public:
~AssetManager() override = default;
virtual RefPtr<Asset> GetAsset(const std::string& assetName) = 0;
virtual std::string GetAssetPath(const std::string& assetName) = 0;
};
} // namespace OHOS::Ace

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2021 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 FOUNDATION_ACE_ACE_ENGINE_FRAMEWORKS_BASE_RESOURCE_DATA_PROVIDER_MANAGER_H
#define FOUNDATION_ACE_ACE_ENGINE_FRAMEWORKS_BASE_RESOURCE_DATA_PROVIDER_MANAGER_H
#include <cstdint>
#include <functional>
#include <vector>
#include "base/memory/ace_type.h"
namespace OHOS::Ace {
class DataProviderRes {
public:
DataProviderRes(uint8_t* dataRes, int64_t size) : data_(dataRes, dataRes + size) {}
~DataProviderRes() = default;
const std::vector<uint8_t>& GetData()
{
return data_;
}
private:
std::vector<uint8_t> data_;
};
using DataProviderImpl = std::function<std::unique_ptr<DataProviderRes>(const std::string& uriStr)>;
class DataProviderManager : public AceType {
DECLARE_ACE_TYPE(DataProviderManager, AceType)
public:
explicit DataProviderManager(const DataProviderImpl& dataProvider) : platformImpl_(dataProvider) {}
~DataProviderManager() = default;
std::unique_ptr<DataProviderRes> GetDataProviderResFromUri(const std::string& uriStr)
{
if (platformImpl_) {
return platformImpl_(uriStr);
}
return nullptr;
}
private:
DataProviderImpl platformImpl_;
};
} // namespace OHOS::Ace
#endif // FOUNDATION_ACE_ACE_ENGINE_FRAMEWORKS_BASE_RESOURCE_DATA_PROVIDER_MANAGER_H

View File

@ -30,7 +30,6 @@ std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const s
auto clearImageDataCallback = [wp = AceType::WeakClaim(this), picName = name]() {
auto sharedImageManager = wp.Upgrade();
if (!sharedImageManager) {
LOGW("sharedImageManager upgrade fail, picName: %{private}s", picName.c_str());
return;
}
{
@ -41,6 +40,7 @@ std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const s
std::lock_guard<std::mutex> lockCancelableCallbackMap_(sharedImageManager->cancelableCallbackMapMutex_);
sharedImageManager->cancelableCallbackMap_.erase(picName);
}
LOGI("Done clean image data for %{private}s", picName.c_str());
};
return clearImageDataCallback;
}

View File

@ -64,8 +64,6 @@ void JsonUtilsTest::TearDown()
* @tc.name: JsonUtilsTest001
* @tc.desc: Check json util function for bool type value
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest001, TestSize.Level1)
{
@ -90,8 +88,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest001, TestSize.Level1)
* @tc.name: JsonUtilsTest002
* @tc.desc: Check json util function for bool type value
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest002, TestSize.Level1)
{
@ -116,8 +112,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest002, TestSize.Level1)
* @tc.name: JsonUtilsTest003
* @tc.desc: Check json util function for signed integer
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest003, TestSize.Level1)
{
@ -147,8 +141,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest003, TestSize.Level1)
* @tc.name: JsonUtilsTest004
* @tc.desc: Check json util function for unsigned integer
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest004, TestSize.Level1)
{
@ -178,8 +170,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest004, TestSize.Level1)
* @tc.name: JsonUtilsTest005
* @tc.desc: Check json util function for decimal number
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest005, TestSize.Level1)
{
@ -209,8 +199,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest005, TestSize.Level1)
* @tc.name: JsonUtilsTest006
* @tc.desc: Check json util function for string
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest006, TestSize.Level1)
{
@ -235,8 +223,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest006, TestSize.Level1)
* @tc.name: JsonUtilsTest007
* @tc.desc: Check json util function for empty string
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest007, TestSize.Level1)
{
@ -261,8 +247,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest007, TestSize.Level1)
* @tc.name: JsonUtilsTest008
* @tc.desc: Check json util function for JsonObject
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest008, TestSize.Level1)
{
@ -290,8 +274,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest008, TestSize.Level1)
* @tc.name: JsonUtilsTest009
* @tc.desc: Check json util function for incorrect JsonObject
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest009, TestSize.Level1)
{
@ -317,8 +299,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest009, TestSize.Level1)
* @tc.name: JsonUtilsTest010
* @tc.desc: Check json util function for array
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest010, TestSize.Level1)
{
@ -347,8 +327,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest010, TestSize.Level1)
* @tc.name: JsonUtilsTest011
* @tc.desc: Check json util function for empty array
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest011, TestSize.Level1)
{
@ -373,8 +351,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest011, TestSize.Level1)
* @tc.name: JsonUtilsTest012
* @tc.desc: Check json util function for empty test string
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest012, TestSize.Level1)
{
@ -397,8 +373,6 @@ HWTEST_F(JsonUtilsTest, JsonUtilsTest012, TestSize.Level1)
* @tc.name: JsonUtilsTest013
* @tc.desc: Check json util function for illegal type value
* @tc.type: FUNC
* @tc.require: AR000DAQVN
* @tc.author: luoying
*/
HWTEST_F(JsonUtilsTest, JsonUtilsTest013, TestSize.Level1)
{

View File

@ -25,13 +25,13 @@ ohos_unittest("TaskExecutorsTest") {
configs = [
"$ace_root:ace_test_config",
"$flutter_root:flutter_config",
"$ace_flutter_engine_root:flutter_config",
]
deps = [
"$ace_flutter_engine_root:ace_libicu_ohos",
"$ace_flutter_engine_root:third_party_flutter_engine_ohos",
"$ace_root/frameworks/base:ace_base_ohos",
"$flutter_root:ace_libicu_ohos",
"$flutter_root:third_party_flutter_engine_ohos",
"//third_party/googletest:gtest_main",
"//utils/native/base:utils",
]

View File

@ -18,12 +18,14 @@
#include <string>
#include "base/log/log.h"
#include "base/memory/memory_monitor.h"
#include "base/thread/thread_util.h"
namespace OHOS::Ace {
namespace {
const size_t MAX_BACKGROUND_THREADS = 8;
constexpr size_t MAX_BACKGROUND_THREADS = 8;
constexpr uint32_t PURGE_FLAG_MASK = (1 << MAX_BACKGROUND_THREADS) - 1;
void SetThreadName(uint32_t threadNo)
{
@ -141,10 +143,20 @@ void BackgroundTaskExecutor::ThreadLoop(uint32_t threadNo)
SetThreadName(threadNo);
Task task;
const uint32_t purgeFlag = (1 << (threadNo - 1));
std::unique_lock<std::mutex> lock(mutex_);
while (running_) {
if (tasks_.empty()) {
condition_.wait(lock);
if ((purgeFlags_ & purgeFlag) != purgeFlag) {
condition_.wait(lock);
continue;
}
lock.unlock();
LOGD("Purge malloc cache for background thread %{public}u", threadNo);
PurgeMallocCache();
lock.lock();
purgeFlags_ &= ~purgeFlag;
continue;
}
@ -161,4 +173,11 @@ void BackgroundTaskExecutor::ThreadLoop(uint32_t threadNo)
LOGD("Background thread is stopped");
}
void BackgroundTaskExecutor::TriggerGarbageCollection()
{
std::lock_guard<std::mutex> lock(mutex_);
purgeFlags_ = PURGE_FLAG_MASK;
condition_.notify_all();
}
} // namespace OHOS::Ace

View File

@ -34,6 +34,8 @@ public:
bool PostTask(Task&& task);
bool PostTask(const Task& task);
void TriggerGarbageCollection();
private:
BackgroundTaskExecutor();
~BackgroundTaskExecutor();
@ -48,6 +50,7 @@ private:
size_t currentThreadNum_ { 0 };
size_t maxThreadNum_ { 0 };
bool running_ { true };
uint32_t purgeFlags_ { 0 };
};
} // namespace OHOS::Ace

View File

@ -39,6 +39,7 @@ public:
GPU,
JS,
BACKGROUND,
UNKNOWN,
};
~TaskExecutor() override = default;
@ -172,10 +173,27 @@ protected:
virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const = 0;
#ifdef ACE_DEBUG
virtual bool OnPreSyncTask(TaskType type) const
{
return true;
}
virtual void OnPostSyncTask() const {}
#endif
private:
bool PostTaskAndWait(CancelableTask&& task, TaskType type) const
{
#ifdef ACE_DEBUG
bool result = false;
if (OnPreSyncTask(type)) {
result = OnPostTask(Task(task), type, 0) && task.WaitUntilComplete();
OnPostSyncTask();
}
return result;
#else
return OnPostTask(Task(task), type, 0) && task.WaitUntilComplete();
#endif
}
};

View File

@ -32,6 +32,8 @@ namespace OHOS::Ace::StringUtils {
ACE_EXPORT extern const char DEFAULT_STRING[];
ACE_EXPORT extern const std::wstring DEFAULT_WSTRING;
ACE_EXPORT extern const std::u16string DEFAULT_USTRING;
constexpr int32_t TEXT_CASE_LOWERCASR = 1;
constexpr int32_t TEXT_CASE_UPPERCASR = 2;
inline std::u16string Str8ToStr16(const std::string& str)
{
@ -106,6 +108,22 @@ inline int32_t StringToInt(const std::string& value)
}
}
inline int64_t StringToLongInt(const std::string& value)
{
errno = 0;
char* pEnd = nullptr;
int64_t result = std::strtoll(value.c_str(), &pEnd, 10);
if (pEnd == value.c_str() || errno == ERANGE) {
return 0;
} else if (result < INT64_MIN) {
return INT64_MIN;
} else if (result > INT64_MAX) {
return INT64_MAX;
} else {
return result;
}
}
inline uint32_t StringToUint(const std::string& value, uint32_t defaultErr = 0)
{
errno = 0;
@ -120,7 +138,7 @@ inline uint32_t StringToUint(const std::string& value, uint32_t defaultErr = 0)
inline double StringToDouble(const std::string& value)
{
char* pEnd = NULL;
char* pEnd = nullptr;
double result = std::strtod(value.c_str(), &pEnd);
if (pEnd == value.c_str() || errno == ERANGE) {
return 0.0;
@ -129,26 +147,44 @@ inline double StringToDouble(const std::string& value)
}
}
inline Dimension StringToDimension(const std::string& value, bool useVp = false)
inline float StringToFloat(const std::string& value)
{
char* pEnd = nullptr;
float result = std::strtof(value.c_str(), &pEnd);
if (pEnd == value.c_str() || errno == ERANGE) {
return 0.0f;
} else {
return result;
}
}
inline Dimension StringToDimensionWithUnit(const std::string& value, DimensionUnit defaultUnit = DimensionUnit::PX)
{
errno = 0;
char* pEnd = nullptr;
double result = std::strtod(value.c_str(), &pEnd);
if (pEnd == value.c_str() || errno == ERANGE) {
return Dimension(0.0, DimensionUnit::PX);
} else {
if ((pEnd) && (std::strcmp(pEnd, "%") == 0)) {
return Dimension(0.0, defaultUnit);
} else if (pEnd != nullptr) {
if (std::strcmp(pEnd, "%") == 0) {
// Parse percent, transfer from [0, 100] to [0, 1]
return Dimension(result / 100.0, DimensionUnit::PERCENT);
} else if ((pEnd) && (std::strcmp(pEnd, "px") == 0)) {
} else if (std::strcmp(pEnd, "px") == 0) {
return Dimension(result, DimensionUnit::PX);
} else if ((pEnd) && (std::strcmp(pEnd, "vp") == 0)) {
} else if (std::strcmp(pEnd, "vp") == 0) {
return Dimension(result, DimensionUnit::VP);
} else if ((pEnd) && (std::strcmp(pEnd, "fp") == 0)) {
} else if (std::strcmp(pEnd, "fp") == 0) {
return Dimension(result, DimensionUnit::FP);
} else if ((pEnd) && (std::strcmp(pEnd, "lpx") == 0)) {
return Dimension(result, DimensionUnit::LPX);
}
return Dimension(result, useVp ? DimensionUnit::VP : DimensionUnit::PX);
}
return Dimension(result, defaultUnit);
}
inline Dimension StringToDimension(const std::string& value, bool useVp = false)
{
return StringToDimensionWithUnit(value, useVp ? DimensionUnit::VP : DimensionUnit::PX);
}
inline double StringToDegree(const std::string& value)
@ -217,6 +253,13 @@ inline void StringSpliter(const std::string& source, char delimiter, std::vector
StringSpliter(source, delimiter, func, out);
}
inline void StringSpliter(const std::string& source, char delimiter, std::vector<float>& out)
{
using Func = float (*)(const std::string&);
Func func = [](const std::string& value) { return StringToFloat(value); };
StringSpliter(source, delimiter, func, out);
}
inline void StringSpliter(const std::string& source, char delimiter, std::vector<int>& out)
{
using Func = int32_t (*)(const std::string&);
@ -224,6 +267,13 @@ inline void StringSpliter(const std::string& source, char delimiter, std::vector
StringSpliter(source, delimiter, func, out);
}
inline void StringSpliter(const std::string& source, char delimiter, std::vector<Dimension>& out)
{
using Func = Dimension (*)(const std::string&);
Func func = [](const std::string& value) { return StringToDimension(value); };
StringSpliter(source, delimiter, func, out);
}
inline std::string DoubleToString(double value, int32_t precision = 2)
{
std::ostringstream result;
@ -247,6 +297,22 @@ inline std::string TrimStr(const std::string& str, char cTrim = ' ')
return str.substr(firstPos, endPos - firstPos + 1);
}
inline void TrimStrLeadingAndTrailing(std::string& str, char cTrim = ' ')
{
auto firstIndexNotOfSpace = str.find_first_not_of(" ");
if (firstIndexNotOfSpace == std::string::npos) {
str = "";
return;
}
str.erase(0, firstIndexNotOfSpace);
auto lastIndexNotOfSpace = str.find_last_not_of(" ");
if (lastIndexNotOfSpace == std::string::npos) {
str = "";
return;
}
str.erase(lastIndexNotOfSpace + 1);
}
inline void SplitStr(
const std::string& str, const std::string& sep, std::vector<std::string>& out, bool needTrim = true)
{
@ -274,6 +340,35 @@ inline void SplitStr(
}
}
inline void SplitStr(const std::string& str, const std::string& sep, std::vector<Dimension>& out, bool needTrim = true)
{
out.erase(out.begin(), out.end());
if (str.empty() || sep.empty()) {
return;
}
std::string strPart;
std::string::size_type startPos = 0;
std::string::size_type pos = str.find_first_of(sep, startPos);
while (pos != std::string::npos) {
if (pos > startPos) {
strPart = needTrim ? TrimStr(str.substr(startPos, pos - startPos)) : str.substr(startPos, pos - startPos);
if (!strPart.empty()) {
out.emplace_back(StringToDimension(std::move(strPart)));
}
}
startPos = pos + sep.size();
pos = str.find_first_of(sep, startPos);
}
if (startPos < str.size()) {
strPart = needTrim ? TrimStr(str.substr(startPos)) : str.substr(startPos);
if (!strPart.empty()) {
out.emplace_back(StringToDimension(std::move(strPart)));
}
}
}
const std::string ACE_EXPORT FormatString(const char* fmt, ...);
inline bool StartWith(const std::string& dst, const std::string& prefix)
{
return dst.compare(0, prefix.size(), prefix) == 0;
@ -284,6 +379,24 @@ inline bool EndWith(const std::string& dst, const std::string& suffix)
return (dst.size() >= suffix.size()) && dst.compare(dst.size() - suffix.size(), suffix.size(), suffix) == 0;
}
inline void TransfromStrCase(std::string& str, int32_t textCase)
{
if (str.empty()) {
return;
}
switch (textCase) {
case TEXT_CASE_LOWERCASR:
transform(str.begin(), str.end(), str.begin(), ::tolower);
break;
case TEXT_CASE_UPPERCASR:
transform(str.begin(), str.end(), str.begin(), ::toupper);
break;
default:
break;
}
}
} // namespace OHOS::Ace::StringUtils
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_UTILS_H

View File

@ -49,6 +49,18 @@ enum class ResolutionType : int32_t {
constexpr int32_t MCC_UNDEFINED = 0;
constexpr int32_t MNC_UNDEFINED = 0;
enum class LongScreenType : int32_t {
LONG = 0,
NOT_LONG,
LONG_SCREEN_UNDEFINED,
};
enum class ScreenShape : int32_t {
ROUND = 0,
NOT_ROUND,
SCREEN_SHAPE_UNDEFINED,
};
class ACE_EXPORT SystemProperties final {
public:
/*
@ -194,7 +206,9 @@ public:
static void SetColorMode(ColorMode colorMode)
{
colorMode_ = colorMode;
if (colorMode_ != colorMode) {
colorMode_ = colorMode;
}
}
static ColorMode GetColorMode()
@ -204,6 +218,11 @@ public:
static void InitMccMnc(int32_t mcc, int32_t mnc);
static ScreenShape GetScreenShape()
{
return screenShape_;
}
private:
static bool traceEnabled_;
static bool isRound_;
@ -224,6 +243,8 @@ private:
static int32_t mcc_;
static int32_t mnc_;
static ColorMode colorMode_;
static ScreenShape screenShape_;
static LongScreenType LongScreen_;
};
} // namespace OHOS::Ace

View File

@ -27,7 +27,7 @@ class ValueChangeObserver : public virtual AceType {
DECLARE_ACE_TYPE(ValueChangeObserver, AceType);
public:
virtual void OnValueChanged(bool needFireChangeEvent = true) = 0;
virtual void OnValueChanged(bool needFireChangeEvent = true, bool needFireSelectChangeEvent = true) = 0;
protected:
ValueChangeObserver() = default;
@ -65,6 +65,7 @@ public:
return;
}
preValue_ = value_;
value_ = std::move(newValue);
Notify(needFireChangeEvent);
}
@ -75,6 +76,7 @@ public:
return;
}
preValue_ = value_;
value_ = newValue;
Notify(needFireChangeEvent);
}
@ -84,6 +86,11 @@ public:
return value_;
}
const U& GetPreValue() const
{
return preValue_;
}
private:
void Notify(bool needFireChangeEvent = true)
{
@ -102,6 +109,7 @@ private:
std::list<WeakPtr<ValueChangeObserver>> observers_;
U value_;
U preValue_;
};
} // namespace OHOS::Ace

252
frameworks/bridge/BUILD.gn Executable file → Normal file
View File

@ -27,9 +27,11 @@ template("js_framework") {
defines += invoker.defines
deps = [
"$ace_flutter_engine_root:ace_skia_$platform",
"$ace_root/frameworks/base:ace_base_$platform",
"$ace_root/frameworks/core:ace_core_$platform",
"$ace_root/frameworks/core/accessibility:ace_accessibility_$platform",
"$ace_root/frameworks/core/components/theme:build_theme_code",
]
# add common source file needed by all product platform here
@ -49,6 +51,7 @@ template("js_framework") {
"common/dom/dom_div.cpp",
"common/dom/dom_divider.cpp",
"common/dom/dom_document.cpp",
"common/dom/dom_form.cpp",
"common/dom/dom_grid_column.cpp",
"common/dom/dom_grid_container.cpp",
"common/dom/dom_grid_row.cpp",
@ -80,6 +83,7 @@ template("js_framework") {
"common/dom/dom_svg_circle.cpp",
"common/dom/dom_svg_ellipse.cpp",
"common/dom/dom_svg_line.cpp",
"common/dom/dom_svg_mask.cpp",
"common/dom/dom_svg_path.cpp",
"common/dom/dom_svg_polygon.cpp",
"common/dom/dom_svg_polyline.cpp",
@ -108,6 +112,7 @@ template("js_framework") {
"js_frontend/engine/common/base_animation_bridge.cpp",
"js_frontend/engine/common/js_api_perf.cpp",
"js_frontend/engine/common/js_constants.cpp",
"js_frontend/frontend_delegate.cpp",
"js_frontend/frontend_delegate_impl.cpp",
"js_frontend/js_ace_page.cpp",
"js_frontend/js_command.cpp",
@ -125,11 +130,16 @@ template("js_framework") {
# utils
"common/utils/source_map.cpp",
"common/utils/transform_convertor.cpp",
"common/utils/utils.cpp",
# declarative js
"declarative_frontend/declarative_frontend.cpp",
"declarative_frontend/frontend_delegate_declarative.cpp",
# pa backend
"pa_backend/pa_backend.cpp",
"pa_backend/backend_delegate_impl.cpp",
]
if (!use_mingw_win && !use_mac) {
sources += [ "common/dom/dom_qrcode.cpp" ]
@ -161,12 +171,17 @@ template("js_framework") {
# add sources needed by phone and TV. wearable like watch do not need them
if (!is_wearable_product && !use_mingw_win && !use_mac) {
sources += [ "common/dom/dom_web.cpp" ]
sources += [
"common/dom/dom_rich_text.cpp",
"common/dom/dom_web.cpp",
"common/dom/dom_xcomponent.cpp",
]
}
if (!is_wearable_product && !use_mingw_win &&
!use_mac) {
sources += [ "js_frontend/engine/common/js_engine_loader.cpp" ]
sources += [ "js_frontend/engine/common/js_engine_loader.cpp",
"pa_backend/engine/common/js_backend_engine_loader.cpp" ]
}
configs = [
@ -194,12 +209,17 @@ template("js_framework") {
} else if (use_mingw_win) {
sources += [
"common/accessibility/accessibility_node_manager.cpp",
"common/inspector/inspect_badge.cpp",
"common/inspector/inspect_button.cpp",
"common/inspector/inspect_canvas.cpp",
"common/inspector/inspect_chart.cpp",
"common/inspector/inspect_dialog.cpp",
"common/inspector/inspect_div.cpp",
"common/inspector/inspect_divider.cpp",
"common/inspector/inspect_form.cpp",
"common/inspector/inspect_grid_column.cpp",
"common/inspector/inspect_grid_container.cpp",
"common/inspector/inspect_grid_row.cpp",
"common/inspector/inspect_image.cpp",
"common/inspector/inspect_image_animator.cpp",
"common/inspector/inspect_input.cpp",
@ -211,10 +231,13 @@ template("js_framework") {
"common/inspector/inspect_menu.cpp",
"common/inspector/inspect_node.cpp",
"common/inspector/inspect_option.cpp",
"common/inspector/inspect_panel.cpp",
"common/inspector/inspect_picker.cpp",
"common/inspector/inspect_picker_view.cpp",
"common/inspector/inspect_piece.cpp",
"common/inspector/inspect_popup.cpp",
"common/inspector/inspect_progress.cpp",
"common/inspector/inspect_qrcode.cpp",
"common/inspector/inspect_rating.cpp",
"common/inspector/inspect_refresh.cpp",
"common/inspector/inspect_search.cpp",
@ -222,6 +245,8 @@ template("js_framework") {
"common/inspector/inspect_slider.cpp",
"common/inspector/inspect_span.cpp",
"common/inspector/inspect_stack.cpp",
"common/inspector/inspect_stepper.cpp",
"common/inspector/inspect_stepper_item.cpp",
"common/inspector/inspect_swiper.cpp",
"common/inspector/inspect_switch.cpp",
"common/inspector/inspect_tab_bar.cpp",
@ -229,6 +254,9 @@ template("js_framework") {
"common/inspector/inspect_tabs.cpp",
"common/inspector/inspect_text.cpp",
"common/inspector/inspect_textarea.cpp",
"common/inspector/inspect_toggle.cpp",
"common/inspector/inspect_toolbar.cpp",
"common/inspector/inspect_toolbar_item.cpp",
"common/inspector/inspect_video.cpp",
"common/inspector/inspector_client.cpp",
"common/inspector/js_inspector_manager.cpp",
@ -340,6 +368,7 @@ template("js_engine") {
sources += [
#runtime
"js_frontend/engine/quickjs/animation_bridge.cpp",
"js_frontend/engine/quickjs/animator_bridge.cpp",
"js_frontend/engine/quickjs/badge_bridge.cpp",
"js_frontend/engine/quickjs/canvas_bridge.cpp",
"js_frontend/engine/quickjs/chart_bridge.cpp",
@ -355,9 +384,46 @@ template("js_engine") {
# utils
"js_frontend/engine/quickjs/qjs_utils.cpp",
]
include_dirs = [
"//foundation/ace/napi",
"//foundation/ace/napi/native_engine/impl/quickjs",
"//third_party/libuv/include",
"//third_party/quickjs",
"//utils/native/base/include",
]
deps += [ "//foundation/ace/napi:ace_napi_quickjs" ]
}
# add ark engine support
use_ark_engine = false
if (use_ark_engine && !is_standard_system && !build_public_version) {
if (target_cpu == "arm64") {
defines += [ "APP_USE_ARM64" ]
} else if (target_cpu == "arm") {
defines += [ "APP_USE_ARM" ]
}
deps += [ "//third_party/jsframework:ark_build" ]
sources += [
"js_frontend/engine/jsi/jsi_animation_bridge.cpp",
"js_frontend/engine/jsi/jsi_animator_bridge.cpp",
"js_frontend/engine/jsi/jsi_badge_bridge.cpp",
"js_frontend/engine/jsi/jsi_canvas_bridge.cpp",
"js_frontend/engine/jsi/jsi_chart_bridge.cpp",
"js_frontend/engine/jsi/jsi_clock_bridge.cpp",
"js_frontend/engine/jsi/jsi_component_api_bridge.cpp",
"js_frontend/engine/jsi/jsi_engine.cpp",
"js_frontend/engine/jsi/jsi_engine_loader.cpp",
"js_frontend/engine/jsi/jsi_group_js_bridge.cpp",
"js_frontend/engine/jsi/jsi_image_animator_bridge.cpp",
"js_frontend/engine/jsi/jsi_input_bridge.cpp",
"js_frontend/engine/jsi/jsi_list_bridge.cpp",
"js_frontend/engine/jsi/jsi_stepper_bridge.cpp",
"js_frontend/engine/jsi/jsi_utils.cpp",
]
}
configs += [ "$ace_root:ace_config" ]
print("platform: ${platform}")
@ -427,7 +493,7 @@ template("gen_obj") {
script = "$flutter_root/engine/flutter/sky/tools/objcopy_pc_mac.py"
} else if (use_mac) {
objcopy_tool = objcopy_clang
script = "$flutter_root/engine/flutter/sky/tools/objcopy_pc_mac.py"
script = "declarative_frontend/engine/tools/build_resource_to_bytecode.py"
} else if (target_cpu == "x86_64") {
objcopy_tool = objcopy_x86_64
script = "$flutter_root/engine/flutter/sky/tools/objcopy.py"
@ -462,9 +528,13 @@ template("gen_obj") {
base_output_path = get_label_info(":js_proxyclass", "target_out_dir")
jsproxyclass_obj_path = base_output_path + "/js_proxy_class.o"
base_output_path = get_label_info(":js_enumstyle", "target_out_dir")
jsenumstyle_obj_path = base_output_path + "/js_enum_style.o"
base_output_path = get_label_info(":js_mocksystemplugin", "target_out_dir")
jsmocksystemplugin_obj_path = base_output_path + "/js_mock_system_plugin.o"
gen_obj("js_proxyclass") {
input = "declarative_frontend/engine/jsproxyClass.js"
input = "declarative_frontend/engine/stateMgmt.js"
if (use_mac) {
jsproxyclass_obj_path = base_output_path + "/js_proxy_class.c"
}
@ -472,6 +542,24 @@ gen_obj("js_proxyclass") {
snapshot_dep = []
}
gen_obj("js_enum_style") {
input = "declarative_frontend/engine/jsEnumStyle.js"
if (use_mac) {
jsenumstyle_obj_path = base_output_path + "/js_enum_style.c"
}
output = jsenumstyle_obj_path
snapshot_dep = []
}
gen_obj("js_mock_system_plugin") {
input = "declarative_frontend/engine/quickjs/jsMockSystemPlugin.js"
if (use_mac) {
jsmocksystemplugin_obj_path = base_output_path + "/js_mock_system_plugin.c"
}
output = jsmocksystemplugin_obj_path
snapshot_dep = []
}
# build declarative javascript engine library
template("declarative_js_engine") {
# get is_ohos_platform, use_quickjs_engine flag.
@ -482,33 +570,82 @@ template("declarative_js_engine") {
deps = []
configs = []
is_separated_so = is_ohos_platform && !is_wearable_product
sources = [
"declarative_frontend/engine/declarative_engine_loader.cpp",
"declarative_frontend/engine/js_view_listeners.cpp",
"declarative_frontend/jsview/js_animation.cpp",
"declarative_frontend/engine/functions/js_animator_function.cpp",
"declarative_frontend/engine/functions/js_click_function.cpp",
"declarative_frontend/engine/functions/js_foreach_function.cpp",
"declarative_frontend/engine/functions/js_function.cpp",
"declarative_frontend/engine/functions/js_gesture_function.cpp",
"declarative_frontend/engine/functions/js_key_function.cpp",
"declarative_frontend/engine/functions/js_page_transition_function.cpp",
"declarative_frontend/engine/functions/js_pan_function.cpp",
"declarative_frontend/engine/functions/js_touch_function.cpp",
"declarative_frontend/engine/js_types.cpp",
"declarative_frontend/jsview/js_alert_dialog.cpp",
"declarative_frontend/jsview/js_animator.cpp",
"declarative_frontend/jsview/js_blank.cpp",
"declarative_frontend/jsview/js_button.cpp",
"declarative_frontend/jsview/js_calendar.cpp",
"declarative_frontend/jsview/js_calendar_controller.cpp",
"declarative_frontend/jsview/js_circle.cpp",
"declarative_frontend/jsview/js_column.cpp",
"declarative_frontend/jsview/js_column_split.cpp",
"declarative_frontend/jsview/js_container_base.cpp",
"declarative_frontend/jsview/js_customview_base.cpp",
"declarative_frontend/jsview/js_counter.cpp",
"declarative_frontend/jsview/js_divider.cpp",
"declarative_frontend/jsview/js_ellipse.cpp",
"declarative_frontend/jsview/js_environment.cpp",
"declarative_frontend/jsview/js_flex.cpp",
"declarative_frontend/jsview/js_flex_impl.cpp",
"declarative_frontend/jsview/js_foreach.cpp",
"declarative_frontend/jsview/js_gesture.cpp",
"declarative_frontend/jsview/js_grid.cpp",
"declarative_frontend/jsview/js_grid_container.cpp",
"declarative_frontend/jsview/js_grid_item.cpp",
"declarative_frontend/jsview/js_if_else.cpp",
"declarative_frontend/jsview/js_image.cpp",
"declarative_frontend/jsview/js_image_animator.cpp",
"declarative_frontend/jsview/js_interactable_view.cpp",
"declarative_frontend/jsview/js_lazy_foreach.cpp",
"declarative_frontend/jsview/js_list.cpp",
"declarative_frontend/jsview/js_list_item.cpp",
"declarative_frontend/jsview/js_navigation_view.cpp",
"declarative_frontend/jsview/js_navigator.cpp",
"declarative_frontend/jsview/js_page_transition.cpp",
"declarative_frontend/jsview/js_path.cpp",
"declarative_frontend/jsview/js_persistent.cpp",
"declarative_frontend/jsview/js_qrcode.cpp",
"declarative_frontend/jsview/js_rect.cpp",
"declarative_frontend/jsview/js_row.cpp",
"declarative_frontend/jsview/js_row_split.cpp",
"declarative_frontend/jsview/js_scroll.cpp",
"declarative_frontend/jsview/js_scroller.cpp",
"declarative_frontend/jsview/js_shape.cpp",
"declarative_frontend/jsview/js_shape_abstract.cpp",
"declarative_frontend/jsview/js_sliding_panel.cpp",
"declarative_frontend/jsview/js_span.cpp",
"declarative_frontend/jsview/js_stack.cpp",
"declarative_frontend/jsview/js_swiper.cpp",
"declarative_frontend/jsview/js_tab_content.cpp",
"declarative_frontend/jsview/js_tabs.cpp",
"declarative_frontend/jsview/js_text.cpp",
"declarative_frontend/jsview/js_toggle.cpp",
"declarative_frontend/jsview/js_touch_handler.cpp",
"declarative_frontend/jsview/js_view.cpp",
"declarative_frontend/jsview/js_view_abstract.cpp",
"declarative_frontend/jsview/js_view_context.cpp",
"declarative_frontend/view_stack_processor.cpp",
]
if (!is_wearable_product) {
sources += [
"declarative_frontend/jsview/js_camera.cpp",
"declarative_frontend/jsview/js_video.cpp",
]
}
#add quickjs engine support
if (use_quickjs_engine) {
defines += [ "USE_QUICKJS_ENGINE" ]
@ -520,17 +657,17 @@ template("declarative_js_engine") {
}
sources += [
"declarative_frontend/engine/quickjs/functions/qjs_click_function.cpp",
"declarative_frontend/engine/quickjs/functions/qjs_foreach_function.cpp",
"declarative_frontend/engine/quickjs/functions/qjs_function.cpp",
"declarative_frontend/engine/quickjs/functions/qjs_touch_function.cpp",
"declarative_frontend/engine/quickjs/functions/qjs_view_function.cpp",
"declarative_frontend/engine/quickjs/modules/qjs_curves_module.cpp",
"declarative_frontend/engine/quickjs/modules/qjs_module_manager.cpp",
"declarative_frontend/engine/quickjs/modules/qjs_router_module.cpp",
"declarative_frontend/engine/quickjs/qjs_bindings.cpp",
"declarative_frontend/engine/quickjs/qjs_declarative_engine.cpp",
"declarative_frontend/engine/quickjs/qjs_declarative_engine_instance.cpp",
"declarative_frontend/engine/quickjs/qjs_function_list_entries_container.cpp",
"declarative_frontend/engine/quickjs/qjs_helpers.cpp",
"declarative_frontend/engine/quickjs/qjs_object_template.cpp",
"declarative_frontend/engine/quickjs/qjs_types.cpp",
"declarative_frontend/engine/quickjs/qjs_unwrap_any.cpp",
"declarative_frontend/engine/quickjs/qjs_view_register.cpp",
]
@ -560,10 +697,16 @@ template("declarative_js_engine") {
]
}
deps += [
":gen_obj_src_js_enum_style",
":gen_obj_src_js_mock_system_plugin",
":gen_obj_src_js_proxyclass",
]
if (use_mingw_win || use_mac) {
deps += [
":gen_obj_src_js_proxyclass",
":intl_qjs_preview",
":js_framework_$platform",
]
defines += [ "_USE_MATH_DEFINES" ]
@ -573,9 +716,92 @@ template("declarative_js_engine") {
}
}
declarative_js_engine("declarative_js_engine_windows") {
defines = ace_windows_defines
is_ohos_platform = false
use_quickjs_engine = true
platform = "windows"
}
declarative_js_engine("declarative_js_engine_mac") {
defines = ace_mac_defines
is_ohos_platform = false
use_quickjs_engine = true
platform = "mac"
}
declarative_js_engine("declarative_js_engine_qjs_ohos") {
defines = ace_ohos_defines
is_ohos_platform = true
use_quickjs_engine = true
platform = "ohos"
}
# build servie backend javascript engine library
template("js_backend_engine") {
# get is_ohos_platform, use_quickjs_engine flag.
forward_variables_from(invoker, "*")
ohos_source_set(target_name) {
defines += invoker.defines
deps = []
configs = []
sources = []
#add quickjs engine support
if (use_quickjs_engine) {
deps += [ "//third_party/jsframework:jsf" ]
if (use_js_debug) {
deps += [ "//third_party/quickjs:qjs_debugger" ]
defines += [ "ENABLE_JS_DEBUG" ]
configs += [ "//third_party/quickjs:qjs_debug_config" ]
} else {
deps += [ "//third_party/quickjs:qjs" ]
}
sources += [
#runtime
"pa_backend/engine/quickjs/qjs_pa_engine_loader.cpp",
"pa_backend/engine/quickjs/qjs_pa_engine.cpp",
]
deps += [ "//foundation/ace/napi:ace_napi_quickjs" ]
}
configs += [ "$ace_root:ace_config" ]
print("platform: ${platform}")
if (is_ohos_platform) {
if (!is_wearable_product) {
deps += [ "$ace_root/adapter/common/cpp:libace" ]
} else {
deps += [ ":js_framework_$platform" ]
defines += [ "BUILT_IN_JS_ENGINE" ]
}
deps += [ ":intl_qjs" ]
if (is_standard_system) {
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
}
}
if (use_mingw_win || use_mac) {
deps += [
":intl_qjs_preview",
":js_framework_$platform",
]
defines += [ "_USE_MATH_DEFINES" ]
defines += [ "BUILT_IN_JS_ENGINE" ]
cflags = [ "-std=c++17" ]
}
}
}
js_backend_engine("js_backend_engine_ohos") {
defines = ace_ohos_defines
is_ohos_platform = true
use_quickjs_engine = true
platform = "ohos"
}

View File

@ -19,6 +19,7 @@
#include <vector>
#include "base/log/event_report.h"
#include "core/common/thread_checker.h"
#include "frameworks/bridge/common/utils/utils.h"
namespace OHOS::Ace {
@ -29,7 +30,10 @@ const char FILE_TYPE_JSON[] = ".json";
} // namespace
CardFrontend::~CardFrontend() = default;
CardFrontend::~CardFrontend()
{
LOG_DESTROY();
}
bool CardFrontend::Initialize(FrontendType type, const RefPtr<TaskExecutor>& taskExecutor)
{
@ -40,8 +44,21 @@ bool CardFrontend::Initialize(FrontendType type, const RefPtr<TaskExecutor>& tas
return true;
}
void CardFrontend::Destroy()
{
CHECK_RUN_ON(JS);
LOGI("CardFrontend Destroy begin.");
parseJsCard_.Reset();
delegate_.Reset();
eventHandler_.Reset();
LOGI("CardFrontend Destroy end.");
}
void CardFrontend::AttachPipelineContext(const RefPtr<PipelineContext>& context)
{
if (!delegate_) {
return;
}
eventHandler_ = AceType::MakeRefPtr<CardEventHandler>(delegate_);
context->RegisterEventHandler(eventHandler_);
holder_.Attach(context);
@ -108,6 +125,10 @@ const WindowConfig& CardFrontend::GetWindowConfig() const
void CardFrontend::LoadPage(const std::string& urlPath, const std::string& params)
{
CHECK_RUN_ON(JS);
if (!delegate_) {
return;
}
auto page = delegate_->CreatePage(0, urlPath);
page->SetPageParams(params);
page->SetFlushCallback([weak = WeakClaim(this)](const RefPtr<Framework::JsAcePage>& page) {
@ -129,6 +150,7 @@ void CardFrontend::LoadPage(const std::string& urlPath, const std::string& param
void CardFrontend::ParsePage(const RefPtr<PipelineContext>& context, const std::string& pageContent,
const std::string& params, const RefPtr<Framework::JsAcePage>& page)
{
CHECK_RUN_ON(JS);
auto rootBody = Framework::ParseFileData(pageContent);
if (!rootBody) {
LOGE("parse index json error");
@ -154,6 +176,7 @@ void CardFrontend::ParsePage(const RefPtr<PipelineContext>& context, const std::
void CardFrontend::OnPageLoaded(const RefPtr<Framework::JsAcePage>& page)
{
CHECK_RUN_ON(JS);
// Pop all JS command and execute them in UI thread.
auto jsCommands = std::make_shared<std::vector<RefPtr<Framework::JsCommand>>>();
page->PopAllCommands(*jsCommands);
@ -210,7 +233,9 @@ void CardFrontend::OnPageLoaded(const RefPtr<Framework::JsAcePage>& page)
if (pipelineContext->CanPushPage()) {
pipelineContext->PushPage(page->BuildPage(page->GetUrl()));
frontend->pageLoaded_ = true;
frontend->delegate_->GetJsAccessibilityManager()->SetRunningPage(page);
if (frontend->delegate_) {
frontend->delegate_->GetJsAccessibilityManager()->SetRunningPage(page);
}
}
},
TaskExecutor::TaskType::UI);
@ -230,6 +255,7 @@ void CardFrontend::UpdateData(const std::string& dataList)
void CardFrontend::UpdatePageData(const std::string& dataList)
{
CHECK_RUN_ON(JS);
if (!delegate_ || !parseJsCard_) {
LOGE("the delegate or parseJsCard is null");
EventReport::SendFormException(FormExcepType::UPDATE_PAGE_ERR);
@ -240,13 +266,22 @@ void CardFrontend::UpdatePageData(const std::string& dataList)
void CardFrontend::SetColorMode(ColorMode colorMode)
{
colorMode_ = colorMode;
if (!delegate_ || !parseJsCard_) {
LOGI("the delegate is null");
return;
}
parseJsCard_->SetColorMode(colorMode);
OnMediaFeatureUpdate();
taskExecutor_->PostTask(
[weak = AceType::WeakClaim(this), colorMode]() {
auto frontend = weak.Upgrade();
if (frontend) {
frontend->colorMode_ = colorMode;
if (!frontend->delegate_ || !frontend->parseJsCard_) {
LOGI("the delegate is null");
return;
}
frontend->parseJsCard_->SetColorMode(frontend->colorMode_);
frontend->OnMediaFeatureUpdate();
} else {
LOGE("card frontend is nullptr");
}
},
TaskExecutor::TaskType::JS);
}
void CardFrontend::RebuildAllPages()
@ -289,6 +324,7 @@ void CardFrontend::OnSurfaceChanged(int32_t width, int32_t height)
void CardFrontend::HandleSurfaceChanged(int32_t width, int32_t height)
{
CHECK_RUN_ON(JS);
if (!parseJsCard_) {
LOGE("the parser is null");
return;
@ -299,6 +335,7 @@ void CardFrontend::HandleSurfaceChanged(int32_t width, int32_t height)
void CardFrontend::OnMediaFeatureUpdate()
{
CHECK_RUN_ON(JS);
if (!delegate_ || !parseJsCard_) {
LOGE("the delegate or parser is null");
return;

View File

@ -38,6 +38,9 @@ public:
~CardFrontend() override;
bool Initialize(FrontendType type, const RefPtr<TaskExecutor>& taskExecutor) override;
void Destroy() override;
void AttachPipelineContext(const RefPtr<PipelineContext>& context) override;
void SetAssetManager(const RefPtr<AssetManager>& assetManager) override;
@ -56,6 +59,7 @@ public:
void TransferJsPluginGetError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override {}
void LoadPluginJsCode(std::string&& jsCode) const override {}
void LoadPluginJsByteCode(std::vector<uint8_t>&& jsCode, std::vector<int32_t>&& jsCodeLen) const override {}
// application lifecycle.
void UpdateState(Frontend::State state) override {}
@ -74,7 +78,6 @@ public:
foregroundFrontend_ = false;
}
// TODO(maxuchu): these life cycle function needs to be completed.
void OnActive() override {}
void OnInactive() override {}
bool OnStartContinuation() override

View File

@ -18,6 +18,7 @@
#include <string>
#include "base/log/event_report.h"
#include "core/common/thread_checker.h"
namespace OHOS::Ace::Framework {
@ -30,6 +31,12 @@ CardFrontendDelegate::CardFrontendDelegate()
#endif
}
CardFrontendDelegate::~CardFrontendDelegate()
{
CHECK_RUN_ON(JS);
LOG_DESTROY();
}
void CardFrontendDelegate::FireCardEvent(const EventMarker& eventMarker, const std::string& params)
{
if (!page_) {

View File

@ -32,7 +32,7 @@ class CardFrontendDelegate : public AceType {
public:
CardFrontendDelegate();
~CardFrontendDelegate() override = default;
~CardFrontendDelegate() override;
void FireCardEvent(const EventMarker& eventMarker, const std::string& params = "");
RefPtr<JsAcePage>& CreatePage(int32_t pageId, const std::string& url);
RefPtr<JsAcePage>& GetPage();

View File

@ -36,6 +36,39 @@ const std::string REPEAT_ITEM = "$item";
const std::string TRUE_STR = "true";
const std::string FALSE_STR = "false";
class VersionData {
public:
void AddRecord(const std::string& key, const std::string& value)
{
records_.emplace_back(StringUtils::StringToInt(key), value);
}
std::vector<std::string> GetVersionPatch()
{
std::vector<std::string> result;
int32_t sysApiVersion = StringUtils::StringToInt(SystemProperties::GetApiVersion());
if (sysApiVersion <= 0) {
LOGE("get system api version failed!");
return result;
}
std::sort(records_.begin(), records_.end(),
[](const std::pair<uint32_t, std::string>& recordA, const std::pair<uint32_t, std::string>& recordB) {
return recordA.first > recordB.first;
});
for (const auto& record : records_) {
if (record.first <= sysApiVersion) {
result.emplace_back(record.second);
}
}
// prepare patches in order of api version from smallest to largest.
std::reverse(result.begin(), result.end());
return result;
}
private:
std::vector<std::pair<int32_t, std::string>> records_;
};
std::unique_ptr<JsonValue> GetJsonValue(
const std::vector<std::string>& keys, const std::unique_ptr<JsonValue>& fileData)
{
@ -92,7 +125,7 @@ void GetAttrOptionsSeriesPoint(const std::unique_ptr<JsonValue>& jsonPoint, Poin
{ "fillColor",
[](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
const auto& valStr = child->GetString();
pointInfo.SetFillColor(Color::FromString(valStr));
pointInfo.SetFillColorString(valStr);
} },
{ "shape",
[](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
@ -110,7 +143,7 @@ void GetAttrOptionsSeriesPoint(const std::unique_ptr<JsonValue>& jsonPoint, Poin
{ "strokeColor",
[](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
auto valStr = child->GetString();
pointInfo.SetStrokeColor(Color::FromString(valStr));
pointInfo.SetStrokeColorString(valStr);
} },
{ "strokeWidth",
[](std::unique_ptr<JsonValue>& child, PointInfo& pointInfo) {
@ -277,7 +310,7 @@ void GetAttrOptions(const std::unique_ptr<JsonValue>& jsonOption, ChartOptions&
}
}
void ParseLineDash(const std::string val, SegmentInfo& segmentInfo)
void ParseLineDash(const std::string& val, SegmentInfo& segmentInfo)
{
std::vector<std::string> dash;
StringUtils::StringSpliter(val, ',', dash);
@ -292,7 +325,7 @@ void ParseLineDash(const std::string val, SegmentInfo& segmentInfo)
}
}
void ParseTextPlacement(const std::string val, TextInfo& textInfo)
void ParseTextPlacement(const std::string& val, TextInfo& textInfo)
{
if (val == "top") {
textInfo.SetPlacement(Placement::TOP);
@ -328,9 +361,9 @@ void GetAttrDataSetData(const std::unique_ptr<JsonValue>& jsonData, MainChart& d
} else if (key == "lineDash") {
ParseLineDash(val, segmentInfo);
} else if (key == "lineColor") {
segmentInfo.SetSegmentColor(Color::FromString(val));
segmentInfo.SetColorString(val);
} else if (key == "textColor") {
textInfo.SetColor(Color::FromString(val));
textInfo.SetColorString(val);
} else if (key == "value" && data->IsNumber()) {
pointInfo.SetX(static_cast<double>(i));
pointInfo.SetY(data->GetDouble());
@ -509,6 +542,53 @@ bool IsVariable(const std::string& value)
return StartWith(value, "{{") && EndWith(value, "}}");
}
bool IsJsonObject(const std::string& value)
{
if (!StartWith(value, "{") || !EndWith(value, "}")) {
return false;
}
if (IsVariable(value)) {
return false;
}
return true;
}
bool IsJsonArray(const std::string& value)
{
return StartWith(value, "[") && EndWith(value, "]");
}
std::vector<std::string> GetVecFromArrStr(const std::string& value)
{
if (value.empty() || value.length() < 2) {
return {};
}
std::string tmp = value.substr(1, value.length() - 2);
tmp.erase(std::remove(tmp.begin(), tmp.end(), '"'), tmp.end());
tmp.erase(std::remove(tmp.begin(), tmp.end(), ' '), tmp.end());
std::regex strDivider(",");
std::vector<std::string> strVec(std::sregex_token_iterator(tmp.begin(), tmp.end(), strDivider, -1),
std::sregex_token_iterator());
return strVec;
}
std::string GetArrStrFromVec(const std::vector<std::string>& vec)
{
std::string res = "[";
for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
res += "\"";
res += *iter;
res += "\",";
}
if (res.length() > 1) {
res = res.substr(0, res.length() - 1);
}
res += "]";
return res;
}
bool IsMultiVariable(const std::string& value)
{
return StartWith(value, "$f(") && EndWith(value, ")");
@ -516,8 +596,28 @@ bool IsMultiVariable(const std::string& value)
} // namespace
void JsCardParser::UpdateProps(const std::string& key, std::string value, const std::unique_ptr<JsonValue>& propsJson)
{
if (!propsJson) {
return;
}
auto propsObject = propsJson->GetValue(key);
if (!propsObject || !propsObject->IsValid()) {
return;
}
if (IsVariable(value)) {
ParseVariable(value);
}
if (!propsObject->Contains("value")) {
propsObject->Put("value", propsObject->GetValue("default")->ToString().c_str());
} else {
propsObject->Replace("value", value.c_str());
}
}
void JsCardParser::ParseAttributes(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command)
std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command,
const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
{
auto attrList = rootJson->GetValue("attr");
if (!attrList || !attrList->IsValid()) {
@ -570,31 +670,31 @@ void JsCardParser::ParseAttributes(const std::unique_ptr<JsonValue>& rootJson, i
continue;
}
if (IsVariable(value)) {
ParseVariable(value);
ParseVariable(value, dataJson, propsJson);
} else if (IsMultiVariable(value)) {
ParseMultiVariable(value);
ParseMultiVariable(value, dataJson, propsJson);
}
attrs.emplace_back(std::make_pair(key, value));
attr = attr->GetNext();
}
}
bool JsCardParser::GetShownValue(std::string& value)
bool JsCardParser::GetShownValue(
std::string& value, const std::unique_ptr<JsonValue>& datajson, const std::unique_ptr<JsonValue>& propsjson)
{
std::vector<std::string> splitResult;
StringUtils::SplitStr(value, "&&", splitResult);
bool showValue = true;
std::vector<std::pair<std::string, bool>> shownVariable;
for (const auto& splitStr : splitResult) {
if (IsVariable(splitStr)) {
auto key = splitStr;
ParseVariable(key);
showValue &= StringToBool(key);
ParseVariable(key, datajson, propsjson);
showValue = showValue && StringToBool(key);
} else if (StartWith(splitStr, "!{{") && EndWith(splitStr, "}}")) {
// !{{value}} --> {{value}}
auto key = splitStr.substr(1, splitStr.size() - 1);
ParseVariable(key);
showValue &= !StringToBool(key);
ParseVariable(key, datajson, propsjson);
showValue = showValue && !StringToBool(key);
} else {
return false;
}
@ -670,6 +770,11 @@ void JsCardParser::ResetRepeatIndexItem()
void JsCardParser::LoadResImageUrl(const std::string& jsonFile, const std::string& splitStr, std::string& value)
{
if (!resourceJson_->Contains(jsonFile)) {
return;
}
// Path only print relative path
LOGI("load res image file is %{public}s", jsonFile.c_str());
auto content = resourceJson_->GetValue(jsonFile);
if (!content || !content->IsValid()) {
LOGE("LoadResImageUrl failed, content is invalid.");
@ -694,7 +799,6 @@ void JsCardParser::GetResImageUrl(std::string& value)
value = iter->second;
return;
}
auto assetManager = assetManager_.Upgrade();
std::string imagePath;
auto jsonFile = std::string(RESOURCES_FOLDER) + "res-" + themeArray[mode] + (themeArray[mode].empty() ? "" : "-") +
GetDeviceDpi(density_) + std::string(FILE_TYPE_JSON);
@ -706,6 +810,12 @@ void JsCardParser::GetResImageUrl(std::string& value)
LoadResImageUrl(jsonFile, splitStr, imagePath);
}
if (!themeArray[mode].empty() && imagePath.empty()) {
jsonFile =
std::string(RESOURCES_FOLDER) + "res-" + themeArray[mode] + std::string(FILE_TYPE_JSON);
LoadResImageUrl(jsonFile, splitStr, imagePath);
}
if (imagePath.empty()) {
jsonFile = std::string(RESOURCES_FOLDER) + std::string(DEFAULTS_RESOURCES_JSON_FILE);
LoadResImageUrl(jsonFile, splitStr, imagePath);
@ -775,7 +885,7 @@ void JsCardParser::GetPlurals(std::string& value)
}
void JsCardParser::ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& styles)
std::vector<std::pair<std::string, std::string>>& styles, const std::unique_ptr<JsonValue>& styleJson)
{
// parse class style
auto classList = rootJson->GetValue("classList");
@ -787,7 +897,7 @@ void JsCardParser::ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32
ParseVariable(value);
}
std::string styleClass("." + value);
SelectStyle(styleClass, styleJson_, styles);
SelectStyle(styleClass, styleJson, styles);
SelectMediaQueryStyle(styleClass, styles);
styleList = styleList->GetNext();
}
@ -800,7 +910,7 @@ void JsCardParser::ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32
ParseVariable(value);
}
std::string idStyle("#" + value);
SelectStyle(idStyle, styleJson_, styles);
SelectStyle(idStyle, styleJson, styles);
SelectMediaQueryStyle(idStyle, styles);
}
@ -830,12 +940,12 @@ void JsCardParser::ParseInlineStyles(
}
}
void JsCardParser::SelectStyle(const std::string& className, const std::unique_ptr<JsonValue>& styleClass,
bool JsCardParser::SelectStyle(const std::string& className, const std::unique_ptr<JsonValue>& styleClass,
std::vector<std::pair<std::string, std::string>>& styles)
{
auto styleDetail = styleClass->GetValue(className);
if (!styleDetail || !styleDetail->IsValid()) {
return;
return false;
}
auto style = styleDetail->GetChild();
while (style && style->IsValid()) {
@ -847,6 +957,7 @@ void JsCardParser::SelectStyle(const std::string& className, const std::unique_p
styles.emplace_back(std::make_pair(key, styleValue));
style = style->GetNext();
}
return true;
}
void JsCardParser::SelectMediaQueryStyle(
@ -857,7 +968,11 @@ void JsCardParser::SelectMediaQueryStyle(
if (mediaQueryer_.MatchCondition(iter.first, mediaFeature)) {
auto mediaIter = mediaQueryStyles_.find(iter.first);
if (mediaIter != mediaQueryStyles_.end()) {
SelectStyle(styleClass, mediaIter->second, styles);
if (!SelectStyle(styleClass, mediaIter->second, styles)) {
continue;
}
LOGI("current condition is %{public}s, style class is %{public}s", mediaIter->first.c_str(),
styleClass.c_str());
}
}
}
@ -887,21 +1002,47 @@ void JsCardParser::RegisterFont(const std::string& fontFamily)
}
}
void JsCardParser::ParseEvents(const std::unique_ptr<JsonValue>& rootJson, std::vector<std::string>& events,
const RefPtr<Framework::JsAcePage>& page, int32_t nodeId)
void JsCardParser::PreUpdateMethodToAction(const std::unique_ptr<JsonValue>& rootJson)
{
auto eventList = rootJson->GetValue("events");
if (!eventList || !eventList->IsValid()) {
return;
}
auto event = eventList->GetChild();
while (event && event->IsValid()) {
auto key = event->GetKey();
auto value = event->GetString();
auto actionJson = eventJson_->GetValue(value);
auto eventAction = actionJson->ToString();
methodToAction_[key] = eventAction;
event = event->GetNext();
}
}
void JsCardParser::ParseEvents(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& eventJson,
std::vector<std::string>& events, const RefPtr<Framework::JsAcePage>& page, int32_t nodeId)
{
LOGD("ParseEvents json:%{public}s", eventJson->ToString().c_str());
auto eventList = rootJson->GetValue("events");
if (!eventList || !eventList->IsValid()) {
LOGI("ParseEvents eventList is empty or eventList->IsValid()");
return;
}
auto event = eventList->GetChild();
while (event && event->IsValid()) {
auto key = event->GetKey();
auto value = event->GetString();
events.emplace_back(key);
auto action = eventJson_->GetValue(value)->ToString();
auto eventAction = GetEventAction(action, key, nodeId);
page->AddNodeEvent(nodeId, key, eventAction);
auto actionJson = eventJson->GetValue(value);
auto eventAction = GetEventAction(actionJson->ToString(), key, nodeId);
if (actionJson->Contains("action") && actionJson->GetString("action") == "proxy") {
auto linkedEventKey = actionJson->GetString("method");
eventAction = methodToAction_[linkedEventKey];
eventJson_->Put(value.c_str(), JsonUtil::ParseJsonString(eventAction));
}
if (!key.empty() && !eventAction.empty()) {
page->AddNodeEvent(nodeId, key, eventAction);
}
event = event->GetNext();
}
}
@ -913,36 +1054,36 @@ std::string JsCardParser::GetEventAction(const std::string& action, const std::s
LOGE("GetEventAction: action detail is invalid");
return "";
}
auto child = actionDetail->GetChild();
ReplaceParam(actionDetail);
return actionDetail->ToString();
}
void JsCardParser::ReplaceParam(const std::unique_ptr<JsonValue>& node)
{
auto child = node->GetChild();
while (child && child->IsValid()) {
auto key = child->GetKey();
auto value = child->IsString() ? child->GetString() : child->ToString();
child = child->GetNext();
if (key != "params") {
auto originValue = value;
if (IsVariable(value)) {
ParseVariable(value);
actionDetail->Replace(key.c_str(), value.c_str());
}
} else {
auto jsonParamDetail = actionDetail->GetValue("params");
if (jsonParamDetail->IsValid()) {
auto pChild = jsonParamDetail->GetChild();
while (pChild->IsValid()) {
auto paramKey = pChild->GetKey();
auto paramValue = pChild->IsString() ? pChild->GetString() : child->ToString();
pChild = pChild->GetNext();
auto originParamValue = paramValue;
if (IsVariable(paramValue)) {
ParseVariable(paramValue);
jsonParamDetail->Replace(paramKey.c_str(), paramValue.c_str());
}
auto oldChild = std::move(child);
child = oldChild->GetNext();
if (IsVariable(value)) {
ParseVariable(value);
node->Replace(key.c_str(), value.c_str());
} else if (IsJsonArray(value)) {
auto strVec = GetVecFromArrStr(value);
for (auto iter = strVec.begin(); iter != strVec.end(); ++iter) {
if (IsVariable(*iter)) {
ParseVariable(*iter);
}
}
actionDetail->Replace("params", jsonParamDetail);
value = GetArrStrFromVec(strVec);
node->Replace(key.c_str(), value.c_str());
} else if (IsJsonObject(value)) {
ReplaceParam(oldChild);
node->Replace(key.c_str(), oldChild);
}
}
return actionDetail->ToString();
}
void JsCardParser::LoadMediaQueryStyle()
@ -951,19 +1092,29 @@ void JsCardParser::LoadMediaQueryStyle()
if (!media || !media->IsValid()) {
return;
}
static const std::string CONDITION_KEY = "condition";
auto mediaChild = media->GetChild();
while (mediaChild && mediaChild->IsValid()) {
auto condition = mediaChild->GetString("condition", "");
auto condition = mediaChild->GetString(CONDITION_KEY, "");
if (condition.empty()) {
mediaChild = mediaChild->GetNext();
continue;
}
// record media query style
auto mediaQueryStyle = JsonUtil::Create(true);
std::unique_ptr<JsonValue> mediaQueryStyle;
auto iter = mediaQueryStyles_.find(condition);
if (iter != mediaQueryStyles_.end()) {
// already exist same media condition
mediaQueryStyle = std::move(iter->second);
} else {
mediaQueryStyle = JsonUtil::Create(true);
}
auto child = mediaChild->GetChild();
while (child && child->IsValid()) {
mediaQueryStyle->Put(child->GetKey().c_str(), child);
if (child->GetKey() != CONDITION_KEY) {
mediaQueryStyle->Put(child->GetKey().c_str(), child);
}
child = child->GetNext();
}
@ -1033,14 +1184,14 @@ void JsCardParser::UpdateStyle(const RefPtr<JsAcePage>& page)
SetUpdateStatus(page);
}
bool JsCardParser::ParseComplexExpression(std::string& value)
bool JsCardParser::ParseComplexExpression(std::string& value, const std::unique_ptr<JsonValue>& json)
{
if (value.find('[') == std::string::npos && value.find('.') == std::string::npos) {
return false;
}
std::stack<std::string> keyStack;
auto key = value;
if (!ParseArrayExpression(key, keyStack) || keyStack.size() != 1) {
if (!ParseArrayExpression(key, keyStack, json) || keyStack.size() != 1) {
return false;
}
auto result = keyStack.top();
@ -1049,9 +1200,10 @@ bool JsCardParser::ParseComplexExpression(std::string& value)
return true;
}
bool JsCardParser::ParseArrayExpression(const std::string& expression, std::stack<std::string>& keyStack)
bool JsCardParser::ParseArrayExpression(
const std::string& expression, std::stack<std::string>& keyStack, const std::unique_ptr<JsonValue>& json)
{
auto dataJson = isRepeat_ ? repeatJson_->ToString() : dataJson_->ToString();
auto dataJson = isRepeat_ ? repeatJson_->ToString() : json->ToString();
auto dataValue = JsonUtil::ParseJsonString(dataJson);
std::string tmpKey;
for (char i : expression) {
@ -1110,10 +1262,12 @@ bool JsCardParser::ParseArrayExpression(const std::string& expression, std::stac
}
void JsCardParser::UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, const std::vector<int>& idArray)
int32_t parentId, const std::vector<int>& idArray, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson)
{
LOGD("UpdateDomNode root json: %{public}s", rootJson->ToString().c_str());
if (!page || !rootJson->IsValid()) {
LOGE("fail to CreateDomNode due to page or root is invalid");
LOGE("fail to UpdateDomNode due to page or root is invalid");
return;
}
if (rootJson->Contains("repeat") && !isRepeat_) {
@ -1137,23 +1291,45 @@ void JsCardParser::UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const
}
bool shouldShow = true;
bool hasShownAttr = false;
GetShownAttr(rootJson, shouldShow, hasShownAttr);
GetShownAttr(rootJson, dataJson, propsJson, shouldShow, hasShownAttr);
type = rootJson->GetValue("type")->GetString();
if (rootBody_->Contains(type)) {
// if rootBody contains this type, it must be a customer component.
auto customJson = rootBody_->GetValue(type);
auto customJsonTemplate = customJson->GetValue("template");
auto customJsonData = customJson->GetValue("data");
auto customJsonProps = customJson->GetValue("props");
auto customJsonStyle = customJson->GetValue("styles");
auto attrList = rootJson->GetValue("attr");
if (!attrList || !attrList->IsValid()) {
return;
}
auto attr = attrList->GetChild();
while (attr && attr->IsValid()) {
auto key = attr->GetKey();
auto value = attr->IsString() ? attr->GetString() : attr->ToString();
UpdateProps(key, value, customJsonProps);
attr = attr->GetNext();
}
ParseStyles(rootJson, selfId, customStyles_, styleJson);
UpdateDomNode(page, customJsonTemplate, parentId, idArray, customJsonData, customJsonStyle, customJsonProps);
return;
}
std::vector<std::pair<std::string, std::string>> attrs;
std::vector<std::pair<std::string, std::string>> styles;
std::vector<std::pair<std::string, std::string>> styles(customStyles_);
customStyles_.clear();
std::vector<std::string> events;
auto styleCommand = Referenced::MakeRefPtr<JsCommandUpdateDomElementStyles>(selfId);
auto attrCommand = Referenced::MakeRefPtr<JsCommandUpdateDomElementAttrs>(selfId);
auto ptr = Referenced::RawPtr(attrCommand);
if (shouldShow && hasShownAttr) {
attrs.emplace_back(std::make_pair("show", TRUE_STR));
}
ParseAttributes(rootJson, selfId, attrs, (JsCommandDomElementOperator*)ptr);
ParseAttributes(rootJson, selfId, attrs, (JsCommandDomElementOperator*)ptr, dataJson, propsJson);
if (!shouldShow && hasShownAttr) {
attrs.emplace_back(std::make_pair("show", FALSE_STR));
}
ParseStyles(rootJson, selfId, styles);
ParseStyles(rootJson, selfId, styles, styleJson);
ParseEvents(rootJson, events, page, selfId);
attrCommand->SetAttributes(std::move(attrs));
styleCommand->SetStyles(std::move(styles));
@ -1164,42 +1340,59 @@ void JsCardParser::UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const
if (childList && childList->IsValid()) {
auto child = childList->GetChild();
while (child && child->IsValid()) {
UpdateDomNode(page, child, selfId, idArray);
UpdateDomNode(page, child, selfId, idArray, dataJson, styleJson, propsJson);
child = child->GetNext();
}
}
}
void JsCardParser::ParseVariable(std::string& value)
void JsCardParser::ParseVariable(
std::string& value, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
{
// {{value}} --> value
auto variable = value.substr(2, value.size() - 4);
if (ParseComplexExpression(variable) || GetVariable(variable) || ParseSpecialVariable(variable) ||
ParseTernaryExpression(variable) || ParseLogicalExpression(variable)) {
if (GetAndParseProps(variable, propsJson) || ParseComplexExpression(variable, dataJson) ||
GetVariable(variable, dataJson) || ParseSpecialVariable(variable) ||
ParseTernaryExpression(variable, propsJson) || ParseLogicalExpression(variable, propsJson)) {
value = variable;
if (IsVariable(value)) {
ParseVariable(value, dataJson, propsJson);
}
}
}
void JsCardParser::ParseMultiVariable(std::string& value)
void JsCardParser::ParseMultiVariable(
std::string& value, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson)
{
if (value.size() < 4) {
return;
}
// $f({{key1}} {{key2}}) --> {{key1}} {{key2}}
auto variable = value.substr(3, value.size() - 4);
std::vector<std::string> splitStr;
StringUtils::SplitStr(variable, ".", splitStr);
std::string resultStr;
for (auto& split : splitStr) {
if (IsVariable(split)) {
ParseVariable(split);
value = "";
// Splicing Between Variables and constants,like variable = "my name is {{name}}, and i am from {{city}}."
while (variable.find("{{") != std::string::npos && variable.find("}}") != std::string::npos) {
int32_t startPos = variable.find("{{");
int32_t endPos = variable.find("}}");
if (endPos < startPos) {
break;
}
resultStr += (split + '.');
// var = {{name}}, after parsing, var = "tom".
std::string var = variable.substr(startPos, endPos - startPos + 2);
ParseVariable(var, dataJson, propsJson);
// after parsing, value = "my name is tom".
value += variable.substr(0, startPos) + var;
// variable = ", and i am from {{city}}."
variable = variable.substr(endPos + 2, variable.size() - endPos - 2);
}
value = resultStr.substr(0, resultStr.size() - 1);
value += variable;
}
bool JsCardParser::ParseTernaryExpression(std::string& value)
bool JsCardParser::ParseTernaryExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
{
if (value.find('?') == std::string::npos || value.find(':') == std::string::npos) {
return false;
@ -1210,14 +1403,25 @@ bool JsCardParser::ParseTernaryExpression(std::string& value)
if (flagStr.size() != 2) {
return false;
}
GetVariable(flagStr[0]);
auto flag = flagStr[0] == TRUE_STR;
bool flag = false;
if (GetAndParseProps(flagStr[0], propsJson) || GetVariable(flagStr[0])) {
flag = flagStr[0] == TRUE_STR;
}
std::vector<std::string> keyStr;
StringUtils::SplitStr(flagStr[1], ":", keyStr);
if (keyStr.size() != 2) {
return false;
}
for (auto& key : keyStr) {
if (StartWith(key, "\'") && EndWith(key, "\'")) {
key = key.substr(1, key.size() - 2);
}
if (StartWith(key, "\"") && EndWith(key, "\"")) {
key = key.substr(1, key.size() - 2);
}
}
// parse key1 and key2.
GetVariable(keyStr[0]);
GetVariable(keyStr[1]);
@ -1225,7 +1429,7 @@ bool JsCardParser::ParseTernaryExpression(std::string& value)
return true;
}
bool JsCardParser::ParseLogicalExpression(std::string& value)
bool JsCardParser::ParseLogicalExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
{
std::vector<std::string> splitStr;
if (value.find("&&") != std::string::npos) {
@ -1234,28 +1438,103 @@ bool JsCardParser::ParseLogicalExpression(std::string& value)
if (splitStr.size() != 2) {
return false;
}
GetVariable(splitStr[0]);
GetVariable(splitStr[1]);
value = (splitStr[0] == TRUE_STR && splitStr[1] == TRUE_STR) ? TRUE_STR : FALSE_STR;
return true;
if ((GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) &&
(GetAndParseProps(splitStr[1], propsJson) || GetVariable(splitStr[1]))) {
value = (splitStr[0] == TRUE_STR && splitStr[1] == TRUE_STR) ? TRUE_STR : FALSE_STR;
return true;
}
} else if (value.find("||") != std::string::npos) {
// for {{flag1 || flag2}}.
StringUtils::SplitStr(value, "||", splitStr);
if (splitStr.size() != 2) {
return false;
}
GetVariable(splitStr[0]);
GetVariable(splitStr[1]);
value = (splitStr[0] == TRUE_STR || splitStr[1] == TRUE_STR) ? TRUE_STR : FALSE_STR;
return true;
if ((GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) &&
(GetAndParseProps(splitStr[1], propsJson) || GetVariable(splitStr[1]))) {
value = (splitStr[0] == TRUE_STR || splitStr[1] == TRUE_STR) ? TRUE_STR : FALSE_STR;
return true;
}
} else if (value.find('!') != std::string::npos) {
// for {{!flag1}}.
StringUtils::SplitStr(value, "!", splitStr);
if (splitStr.size() != 1) {
return false;
}
GetVariable(splitStr[0]);
value = splitStr[0] == TRUE_STR ? FALSE_STR : TRUE_STR;
if (GetAndParseProps(splitStr[0], propsJson) || GetVariable(splitStr[0])) {
value = splitStr[0] == TRUE_STR ? FALSE_STR : TRUE_STR;
return true;
}
}
return false;
}
bool JsCardParser::GetAndParseProps(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
{
if (!propsJson) {
return false;
}
if (ParsePropsArray(value, propsJson) || ParsePropsVariable(value, propsJson)) {
return true;
}
return false;
}
bool JsCardParser::ParsePropsVariable(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
{
auto propsObject = propsJson->GetValue(value);
if (!propsObject || !propsObject->IsValid()) {
LOGI("GetAndParseProps propsObject is empty or propsObject->IsValid()");
return false;
}
auto propValueJson = propsObject->GetValue("value");
auto defaultJson = propsObject->GetValue("default");
if (propValueJson && propValueJson->IsValid()) {
value = propValueJson->IsString() ? propValueJson->GetString() : propValueJson->ToString();
} else {
// no need to check valid, the json will recover from error state
value = defaultJson->IsString() ? defaultJson->GetString() : defaultJson->ToString();
}
// after user use current value in json, need to reset back to default
propsObject->Replace(
"value", defaultJson->IsString() ? defaultJson->GetString().c_str() : defaultJson->ToString().c_str());
return true;
}
std::string GetArrayItemSubstring(const std::string& s)
{
std::string result;
auto endIndex = s.find("[");
if (endIndex != std::string::npos) {
result = s.substr(0, endIndex);
}
return result;
}
bool JsCardParser::ParsePropsArray(std::string& value, const std::unique_ptr<JsonValue>& propsJson)
{
const auto arrayParam = GetArrayItemSubstring(value);
if (arrayParam.empty()) {
return false;
}
auto propsObject = propsJson->GetValue(arrayParam);
if (!propsObject || !propsObject->IsValid()) {
LOGI("GetAndParseProps propsObject is empty or propsObject->IsValid()");
return false;
}
auto propValueJson = propsObject->GetValue("value");
auto defaultJson = propsObject->GetValue("default");
auto arrayPropJson = JsonUtil::Create(true);
if (propValueJson && propValueJson->IsValid()) {
arrayPropJson->Put(arrayParam.c_str(), propValueJson);
} else {
arrayPropJson->Put(arrayParam.c_str(), defaultJson);
}
if (ParseComplexExpression(value, arrayPropJson)) {
// after user use current value in json, need to reset back to default
propsObject->Replace(
"value", defaultJson->IsString() ? defaultJson->GetString().c_str() : defaultJson->ToString().c_str());
return true;
}
return false;
@ -1277,13 +1556,18 @@ bool JsCardParser::ParseSpecialVariable(std::string& value)
return false;
}
bool JsCardParser::GetVariable(std::string& value)
bool JsCardParser::GetVariable(std::string& value, const std::unique_ptr<JsonValue>& dataJson)
{
LOGD("GetVariable value :%{private}s dataJson:%{private}s", value.c_str(), dataJson->ToString().c_str());
auto key = value;
if (!repeatJson_->Contains(key)) {
if (!repeatJson_->Contains(key) && isRepeat_) {
return false;
}
auto dataValue = dataJson_->GetValue(key);
if (!dataJson) {
return false;
}
auto dataValue = dataJson->GetValue(key);
if (isRepeat_) {
dataValue = repeatJson_->GetValue(key);
}
@ -1292,8 +1576,9 @@ bool JsCardParser::GetVariable(std::string& value)
}
value = dataValue->IsString() ? dataValue->GetString() : dataValue->ToString();
if (IsVariable(value)) {
ParseVariable(value);
ParseVariable(value, dataJson);
}
LOGD("return value :%{private}s", value.c_str());
return true;
}
@ -1351,7 +1636,8 @@ bool JsCardParser::ParsePointOperator(
}
void JsCardParser::CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, bool isNewNode)
int32_t parentId, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& actionJson,
const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson, bool isNewNode)
{
if (!page || !rootJson->IsValid()) {
LOGE("fail to CreateDomNode due to page or root is invalid");
@ -1379,12 +1665,37 @@ void JsCardParser::CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const
}
bool shouldShow = true;
bool hasShownAttr = false;
GetShownAttr(rootJson, shouldShow, hasShownAttr);
GetShownAttr(rootJson, dataJson, propsJson, shouldShow, hasShownAttr);
type = rootJson->GetValue("type")->GetString();
if (rootBody_->Contains(type)) {
// if rootBody contains this type, it must be a customer component.
auto customJson = rootBody_->GetValue(type);
auto customJsonTemplate = customJson->GetValue("template");
auto customJsonData = customJson->GetValue("data");
auto customJsonProps = customJson->GetValue("props");
auto customJsonActions = customJson->GetValue("actions");
auto customJsonStyle = customJson->GetValue("styles");
auto attrList = rootJson->GetValue("attr");
if (!attrList || !attrList->IsValid()) {
return;
}
auto attr = attrList->GetChild();
while (attr && attr->IsValid()) {
auto key = attr->GetKey();
auto value = attr->IsString() ? attr->GetString() : attr->ToString();
UpdateProps(key, value, customJsonProps);
attr = attr->GetNext();
}
ParseStyles(rootJson, nodeId, customStyles_, styleJson);
PreUpdateMethodToAction(rootJson);
CreateDomNode(page, customJsonTemplate, parentId, customJsonData, customJsonActions, customJsonStyle,
customJsonProps, isNewNode);
return;
}
std::vector<std::pair<std::string, std::string>> attrs;
std::vector<std::pair<std::string, std::string>> styles;
std::vector<std::pair<std::string, std::string>> styles(customStyles_);
customStyles_.clear();
std::vector<std::string> events;
RefPtr<Framework::JsCommandDomElementCreator> command;
if (parentId < 0) {
command = Referenced::MakeRefPtr<Framework::JsCommandCreateDomBody>(type, nodeId);
@ -1396,13 +1707,12 @@ void JsCardParser::CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const
if (shouldShow && hasShownAttr) {
attrs.emplace_back(std::make_pair("show", TRUE_STR));
}
ParseAttributes(rootJson, nodeId, attrs, (Framework::JsCommandDomElementOperator*)ptr);
ParseAttributes(rootJson, nodeId, attrs, (Framework::JsCommandDomElementOperator*)ptr, dataJson, propsJson);
if (!shouldShow && hasShownAttr) {
attrs.emplace_back(std::make_pair("show", FALSE_STR));
}
LOGD("card nodeId: %d, parentId: %d, type: %s", nodeId, parentId, type.c_str());
ParseStyles(rootJson, nodeId, styles);
ParseEvents(rootJson, events, page, nodeId);
ParseStyles(rootJson, nodeId, styles, styleJson);
ParseEvents(rootJson, actionJson, events, page, nodeId);
command->SetAttributes(std::move(attrs));
command->SetStyles(std::move(styles));
command->AddEvents(std::move(events));
@ -1412,7 +1722,7 @@ void JsCardParser::CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const
if (childList && childList->IsValid()) {
auto child = childList->GetChild();
while (child && child->IsValid()) {
CreateDomNode(page, child, nodeId, isNewNode);
CreateDomNode(page, child, nodeId, dataJson, actionJson, styleJson, propsJson, isNewNode);
child = child->GetNext();
}
}
@ -1466,11 +1776,13 @@ void JsCardParser::GetClockConfig(const std::unique_ptr<JsonValue>& jsonDataSets
auto key = data->GetKey();
auto valStr = data->IsString() ? data->GetString() : data->ToString();
static const LinearMapNode<void (*)(std::string&, ClockConfig&, JsCardParser&)> clockConfigOperators[] = {
{ DOM_DIGIT_COLOR, [](std::string& valStr, ClockConfig& clockConfig,
JsCardParser& jsCardParser) { clockConfig.digitColor_ = Color::FromString(valStr); } },
{ DOM_DIGIT_COLOR,
[](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
clockConfig.digitColor_ = valStr;
} },
{ DOM_DIGIT_COLOR_NIGHT,
[](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
clockConfig.digitColorNight_ = Color::FromString(valStr);
clockConfig.digitColorNight_ = valStr;
} },
{ DOM_DIGIT_RADIUS_RATIO,
[](std::string& valStr, ClockConfig& clockConfig, JsCardParser& jsCardParser) {
@ -1614,18 +1926,56 @@ void JsCardParser::SetUpdateStatus(const RefPtr<Framework::JsAcePage>& page)
page->FlushCommands();
}
void JsCardParser::GetShownAttr(const std::unique_ptr<JsonValue>& rootJson, bool& shouldShow, bool& hasShownAttr)
void JsCardParser::GetShownAttr(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson, bool& shouldShow, bool& hasShownAttr)
{
GetBoolValue(rootJson, "shown", shouldShow, hasShownAttr);
GetBoolValue(rootJson, dataJson, propsJson, "shown", shouldShow, hasShownAttr);
bool blockValue = false;
bool hasBlock = false;
GetBoolValue(rootJson, BLOCK_VALUE, blockValue, hasBlock);
if (hasBlock) {
shouldShow &= blockValue;
shouldShow = shouldShow && blockValue;
hasShownAttr = true;
}
}
void JsCardParser::ParseVersionAndUpdateData()
{
LOGI("parse version info and update data field");
auto versionJson = rootBody_->GetValue("apiVersion");
if (!versionJson || !versionJson->IsValid()) {
return;
}
auto child = versionJson->GetChild();
VersionData versionData;
while (child && child->IsValid()) {
if (child->IsObject()) {
auto key = child->GetKey();
auto value = child->IsString() ? child->GetString() : child->ToString();
versionData.AddRecord(key, value);
}
child = child->GetNext();
}
auto versionPatch = versionData.GetVersionPatch();
for (const auto& patchInfo : versionPatch) {
auto patchJson = JsonUtil::ParseJsonString(patchInfo);
if (!patchJson || !patchJson->IsValid()) {
LOGW("parse version patch failed, patchInfo = %{public}s", patchInfo.c_str());
continue;
}
auto patchItem = patchJson->GetChild();
while (patchItem && patchItem->IsValid()) {
auto key = patchItem->GetKey();
if (dataJson_->Contains(key)) {
dataJson_->Replace(key.c_str(), patchItem);
} else {
dataJson_->Put(key.c_str(), patchItem);
}
patchItem = patchItem->GetNext();
}
}
}
bool JsCardParser::Initialize()
{
rootJson_ = rootBody_->GetValue("template");
@ -1641,6 +1991,8 @@ bool JsCardParser::Initialize()
LOGE("the json template is error");
return false;
}
ParseVersionAndUpdateData();
// repeatJson contains dataJson.
repeatJson_ = JsonUtil::ParseJsonString(dataJson_->ToString());
LoadMediaQueryStyle();
@ -1659,13 +2011,14 @@ void JsCardParser::CreateBlockNode(const OHOS::Ace::RefPtr<OHOS::Ace::Framework:
bool shouldShow = true;
bool hasShownAttr = false;
GetBoolValue(rootJson, "shown", shouldShow, hasShownAttr);
const char* value = shouldShow ? "true" : "false";
if (blockChild && blockChild->IsValid()) {
auto child = blockChild->GetChild();
while (child && child->IsValid()) {
if (child->Contains(BLOCK_VALUE)) {
shouldShow ? child->Replace(BLOCK_VALUE, "true") : child->Replace(BLOCK_VALUE, "false");
child->Replace(BLOCK_VALUE, value);
} else {
shouldShow ? child->Put(BLOCK_VALUE, "true") : child->Put(BLOCK_VALUE, "false");
child->Put(BLOCK_VALUE, value);
}
parsingStatus_ == ParsingStatus::UPDATE ? UpdateDomNode(page, child, parentId)
: CreateDomNode(page, child, parentId);
@ -1674,21 +2027,31 @@ void JsCardParser::CreateBlockNode(const OHOS::Ace::RefPtr<OHOS::Ace::Framework:
}
}
void JsCardParser::GetBoolValue(
const std::unique_ptr<JsonValue>& rootJson, const std::string& key, bool& shouldShow, bool& hasShownAttr)
void JsCardParser::GetBoolValue(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson, const std::string& key, bool& value, bool& hasAttr)
{
auto shown = rootJson->GetValue(key);
if (shown && shown->IsValid()) {
if (shown->IsString()) {
auto shownValue = shown->GetString();
GetShownValue(shownValue);
shouldShow = shownValue == "true";
hasShownAttr = true;
} else if (shown->IsBool()) {
shouldShow = shown->GetBool();
hasShownAttr = true;
auto result = rootJson->GetValue(key);
if (result && result->IsValid()) {
if (result->IsString()) {
auto strValue = result->GetString();
GetShownValue(strValue, dataJson, propsJson);
value = strValue == "true";
hasAttr = true;
return;
} else if (result->IsBool()) {
value = result->GetBool();
hasAttr = true;
return;
}
}
hasAttr = false;
}
void JsCardParser::SetColorMode(ColorMode colorMode)
{
LOGI("current color mode is %{public}d", colorMode);
colorMode_ = colorMode;
mediaQueryer_.SetColorMode(colorMode);
}
} // namespace OHOS::Ace::Framework

View File

@ -36,38 +36,65 @@ public:
{}
~JsCardParser() override = default;
void CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, bool isNewNode = false)
{
CreateDomNode(page, rootJson, parentId, dataJson_, eventJson_, styleJson_, nullptr, isNewNode);
}
void ParseAttributes(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command);
bool GetShownValue(std::string& value);
std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command)
{
ParseAttributes(rootJson, nodeId, attrs, command, dataJson_, nullptr);
}
void ParseEvents(const std::unique_ptr<JsonValue>& rootJson, std::vector<std::string>& events,
const RefPtr<JsAcePage>& page, int32_t nodeId)
{
ParseEvents(rootJson, eventJson_, events, page, nodeId);
}
void UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, const std::vector<int>& idArray = std::vector<int>())
{
UpdateDomNode(page, rootJson, parentId, idArray, dataJson_, styleJson_, nullptr);
}
void ParseVariable(std::string& value)
{
ParseVariable(value, dataJson_, nullptr);
}
void ParseMultiVariable(std::string& value)
{
ParseMultiVariable(value, dataJson_);
}
void ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& styles)
{
ParseStyles(rootJson, nodeId, styles, styleJson_);
}
bool GetVariable(std::string& value)
{
return GetVariable(value, dataJson_);
}
bool GetShownValue(std::string& value)
{
return GetShownValue(value, dataJson_, nullptr);
}
bool GetShownValue(
std::string& value, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson);
bool GetRepeatData(std::unique_ptr<JsonValue>& repeatValue, std::string& key);
void ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& styles);
void ParseEvents(const std::unique_ptr<JsonValue>& rootJson, std::vector<std::string>& events,
const RefPtr<JsAcePage>& page, int32_t nodeId);
void UpdatePageData(const std::string& dataList, const RefPtr<JsAcePage>& page);
void LoadImageInfo();
void UpdateStyle(const RefPtr<JsAcePage>& page);
void CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, bool isNewNode = false);
void ParseVariable(std::string& value);
void ParseMultiVariable(std::string& value);
void ParseRepeatIndexItem(const std::unique_ptr<JsonValue>& repeatValue);
void SetRepeatItemValue(uint32_t index, const std::unique_ptr<JsonValue>& repeatValue, bool hasKeyValue);
bool Initialize();
void SetColorMode(ColorMode colorMode);
const WeakPtr<PipelineContext>& GetPipelineContext() const
{
return context_;
}
void SetColorMode(ColorMode colorMode)
{
colorMode_ = colorMode;
mediaQueryer_.SetColorMode(colorMode);
}
void SetDensity(double density)
{
density_ = density;
@ -99,21 +126,43 @@ private:
void GetPlurals(std::string& value);
void ParseInlineStyles(
const std::unique_ptr<JsonValue>& rootJson, std::vector<std::pair<std::string, std::string>>& styles);
void SelectStyle(const std::string& className, const std::unique_ptr<JsonValue>& styleClass,
bool SelectStyle(const std::string& className, const std::unique_ptr<JsonValue>& styleClass,
std::vector<std::pair<std::string, std::string>>& styles);
void SelectMediaQueryStyle(const std::string& styleClass, std::vector<std::pair<std::string, std::string>>& styles);
void LoadMediaQueryStyle();
void LoadResImageUrl(const std::string& jsonFile, const std::string& splitStr, std::string& value);
void RegisterFont(const std::string& fontFamily);
std::string GetEventAction(const std::string& action, const std::string& actionType, int32_t nodeId);
bool ParseComplexExpression(std::string& value);
bool ParseTernaryExpression(std::string& value);
bool ParseLogicalExpression(std::string& value);
bool ParseArrayExpression(const std::string& expression, std::stack<std::string>& keyStack);
void UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, const std::vector<int>& idArray = std::vector<int>());
std::string GetEventAction(const std::string& action, const std::string& actionType, int32_t nodeId = 0);
bool ParsePropsVariable(std::string& value, const std::unique_ptr<JsonValue>& propsJson);
bool ParsePropsArray(std::string& value, const std::unique_ptr<JsonValue>& propsJson);
bool ParseComplexExpression(std::string& value, const std::unique_ptr<JsonValue>& json);
bool ParseTernaryExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson = nullptr);
bool ParseLogicalExpression(std::string& value, const std::unique_ptr<JsonValue>& propsJson = nullptr);
bool ParseArrayExpression(
const std::string& expression, std::stack<std::string>& keyStack, const std::unique_ptr<JsonValue>& json);
bool ParseSpecialVariable(std::string& value);
bool GetVariable(std::string& value);
void CreateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& actionJson,
const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson = nullptr,
bool isNewNode = false);
void PreUpdateMethodToAction(const std::unique_ptr<JsonValue>& rootJson);
void ParseAttributes(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& attrs, JsCommandDomElementOperator* command,
const std::unique_ptr<JsonValue>& dataJson, const std::unique_ptr<JsonValue>& propsJson);
void ParseStyles(const std::unique_ptr<JsonValue>& rootJson, int32_t nodeId,
std::vector<std::pair<std::string, std::string>>& styles, const std::unique_ptr<JsonValue>& styleJson);
void ParseVariable(std::string& value, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson = nullptr);
void ParseMultiVariable(std::string& value, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson = nullptr);
void UpdateDomNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
int32_t parentId, const std::vector<int>& idArray, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& styleJson, const std::unique_ptr<JsonValue>& propsJson);
void ParseEvents(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& eventJson,
std::vector<std::string>& events, const RefPtr<Framework::JsAcePage>& page, int32_t nodeId);
void UpdateProps(const std::string& key, std::string value, const std::unique_ptr<JsonValue>& propsJson);
bool GetAndParseProps(std::string& value, const std::unique_ptr<JsonValue>& propsJson);
bool GetVariable(std::string& value, const std::unique_ptr<JsonValue>& dataJson);
template<typename T>
void ParseSpecialAttr(const std::function<void(const std::unique_ptr<JsonValue>&, std::vector<T>&)>& function,
std::string& value, std::vector<T>& vector);
@ -126,15 +175,21 @@ private:
const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson, int32_t parentId);
void GetResourceValue(const std::string& path);
void GetClockConfig(const std::unique_ptr<JsonValue>& jsonDataSets, ClockConfig& clockConfig);
void ProcessRepeatNode(const RefPtr<Framework::JsAcePage>& page,
const std::unique_ptr<JsonValue>& rootJson, const std::string& key, int32_t parentId, bool hasKeyValue,
std::unique_ptr<JsonValue>& repeatValue);
void ProcessRepeatNode(const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson,
const std::string& key, int32_t parentId, bool hasKeyValue, std::unique_ptr<JsonValue>& repeatValue);
void SetUpdateStatus(const RefPtr<Framework::JsAcePage>& page);
void GetShownAttr(const std::unique_ptr<JsonValue>& rootJson, bool& shouldShow, bool& hasShownAttr);
void GetShownAttr(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson, bool& shouldShow, bool& hasShownAttr);
void CreateBlockNode(
const RefPtr<Framework::JsAcePage>& page, const std::unique_ptr<JsonValue>& rootJson, int32_t parentId);
void GetBoolValue(
const std::unique_ptr<JsonValue>& rootJson, const std::string& key, bool& shouldShow, bool& hasShownAttr);
void GetBoolValue(const std::unique_ptr<JsonValue>& rootJson, const std::string& key, bool& value, bool& hasAttr)
{
GetBoolValue(rootJson, dataJson_, nullptr, key, value, hasAttr);
}
void GetBoolValue(const std::unique_ptr<JsonValue>& rootJson, const std::unique_ptr<JsonValue>& dataJson,
const std::unique_ptr<JsonValue>& propsJson, const std::string& key, bool& value, bool& hasAttr);
void ParseVersionAndUpdateData();
void ReplaceParam(const std::unique_ptr<JsonValue>& node);
double density_ = 1.0;
int32_t nodeId_ = 0;
@ -154,9 +209,11 @@ private:
std::unique_ptr<JsonValue> repeatJson_;
std::unique_ptr<JsonValue> resourceJson_;
std::unordered_map<std::string, std::string> imageUrlMap_;
std::unordered_map<std::string, std::string> methodToAction_;
std::unordered_map<int32_t, std::pair<std::vector<int32_t>, int32_t>> listIdMap_;
std::unordered_map<std::string, int32_t> singleLoopMap_;
std::unordered_map<std::string, std::unique_ptr<JsonValue>> mediaQueryStyles_;
std::vector<std::pair<std::string, std::string>> customStyles_;
MediaQueryer mediaQueryer_;
// for repeat attr
@ -167,4 +224,4 @@ private:
} // namespace OHOS::Ace::Framework
#endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_CARD_FRONTEND_JS_CARD_PARSER_H
#endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_CARD_FRONTEND_JS_CARD_PARSER_H

View File

@ -210,6 +210,15 @@ const MediaQueryerRule DEVICE_TYPE_RULE(
},
2);
const MediaQueryerRule DEVICE_BRAND_RULE(
std::regex("\\(device-brand:([A-Z]+)\\)"),
[](const std::smatch& matchResults, const MediaFeature& mediaFeature, MediaError& failReason) {
static constexpr int32_t CONDITION_VALUE = 1;
auto value = matchResults[CONDITION_VALUE] == mediaFeature->GetString("device-brand", "");
return value;
},
2);
const MediaQueryerRule DARK_MODE_RULE(
std::regex("\\(dark-mode:([a-z]+)\\)"),
[](const std::smatch& matchResults, const MediaFeature& mediaFeature, MediaError& failReason) {
@ -225,6 +234,7 @@ const std::list<MediaQueryerRule> SINGLE_CONDITION_RULES = {
CSS_LEVEL3_RULE,
ORIENTATION_RULE,
DEVICE_TYPE_RULE,
DEVICE_BRAND_RULE,
SCREEN_SHAPE_RULE,
DARK_MODE_RULE,
@ -232,7 +242,6 @@ const std::list<MediaQueryerRule> SINGLE_CONDITION_RULES = {
bool ParseSingleCondition(const std::string& condition, const MediaFeature& mediaFeature, MediaError& failReason)
{
std::smatch result;
for (const auto& rule : SINGLE_CONDITION_RULES) {
std::smatch matchResults;
if (rule.Match(condition, matchResults)) {
@ -350,11 +359,13 @@ std::unique_ptr<JsonValue> MediaQueryer::GetMediaFeature() const
json->Put("aspect-ratio", aspectRatio);
json->Put("round-screen", SystemProperties::GetIsScreenRound());
json->Put("device-width", SystemProperties::GetDeviceWidth());
json->Put("device-brand", SystemProperties::GetBrand().c_str());
json->Put("device-height", SystemProperties::GetDeviceHeight());
json->Put("resolution", SystemProperties::GetResolution());
json->Put("orientation", mediaQueryInfo.GetOrientation().c_str());
json->Put("device-type", mediaQueryInfo.GetDeviceType().c_str());
json->Put("dark-mode", colorMode_ == ColorMode::DARK ? true : false);
json->Put("dark-mode", colorMode_ == ColorMode::DARK);
LOGD("current media info %{public}s", json->ToString().c_str());
return json;
}

View File

@ -208,6 +208,14 @@ void UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode>& node, Accessib
nodeInfo.height = node->GetHeight();
}
auto scaleX = manager->GetScaleX();
auto scaleY = manager->GetScaleY();
nodeInfo.top *= scaleY;
nodeInfo.left *= scaleX;
nodeInfo.width *= scaleX;
nodeInfo.height *= scaleY;
nodeInfo.isChecked = node->GetCheckedState();
nodeInfo.isEnabled = node->GetEnabledState();
nodeInfo.isFocused = node->GetFocusedState();
@ -271,6 +279,7 @@ void UpdateAccessibilityNodeInfo(const RefPtr<AccessibilityNode>& node, Accessib
}
nodeInfo.supportAction = std::move(actions);
#ifdef ACE_DEBUG
std::string actionForLog;
for (const auto& action : supportAceActions) {
@ -416,11 +425,27 @@ void JsAccessibilityManager::InitializeCallback()
LOGW("AccessibilityNodeInfo can't attach component by Id = %{public}d", nodeInfo.ID);
return false;
}
jsAccessibilityManager->UpdateNodeChildIds(node);
UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager);
if (nodeInfo.ID == 0) {
jsAccessibilityManager->UpdateViewScale();
}
auto context = jsAccessibilityManager->GetPipelineContext().Upgrade();
if (!context) {
return false;
}
context->GetTaskExecutor()->PostSyncTask(
[&jsAccessibilityManager, &node, &nodeInfo]() {
jsAccessibilityManager->UpdateNodeChildIds(node);
UpdateAccessibilityNodeInfo(node, nodeInfo, jsAccessibilityManager);
},
TaskExecutor::TaskType::UI);
return true;
};
AccessibilityAbilityClient::GetInstance().RegisterFetchNodeInfoCallback(fetchNodeInfoCallback);
if (callbackKey_.empty()) {
AccessibilityAbilityClient::GetInstance().RegisterFetchNodeInfoCallback(fetchNodeInfoCallback);
} else {
AccessibilityAbilityClient::GetInstance().RegisterFetchNodeInfoCallback(fetchNodeInfoCallback, callbackKey_);
}
auto eventHandleCallback = [weak = WeakClaim(this)](AccessibilityActionInfo& actionInfo) {
LOGD("AccessibilityActionInfo nodeId= %{public}d, action=%{public}d", actionInfo.ID, actionInfo.action);
@ -451,7 +476,11 @@ void JsAccessibilityManager::InitializeCallback()
}
return ret;
};
AccessibilityAbilityClient::GetInstance().RegisterEventHandleCallback(eventHandleCallback);
if (callbackKey_.empty()) {
AccessibilityAbilityClient::GetInstance().RegisterEventHandleCallback(eventHandleCallback);
} else {
AccessibilityAbilityClient::GetInstance().RegisterEventHandleCallback(eventHandleCallback, callbackKey_);
}
}
void JsAccessibilityManager::SendAccessibilitySyncEvent(const AccessibilityEvent& accessibilityEvent)
@ -566,9 +595,10 @@ void JsAccessibilityManager::DumpHandleEvent(const std::vector<std::string>& par
}
auto context = GetPipelineContext().Upgrade();
if (context) {
context->GetTaskExecutor()->PostTask(
[actionInfo, node, context]() { AccessibilityActionEvent(actionInfo, node, context); },
TaskExecutor::TaskType::UI);
auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
context->GetTaskExecutor()->PostTask([actionInfo, node, weakContext]() {
AccessibilityActionEvent(actionInfo, node, weakContext.Upgrade());
}, TaskExecutor::TaskType::UI);
}
}
@ -687,4 +717,18 @@ void JsAccessibilityManager::SetCardViewParams(const std::string& key, bool focu
}
}
void JsAccessibilityManager::UpdateViewScale()
{
auto context = GetPipelineContext().Upgrade();
if (!context) {
return;
}
float scaleX = 1.0;
float scaleY = 1.0;
if (context->GetViewScale(scaleX, scaleY)) {
scaleX_ = scaleX;
scaleY_ = scaleY;
}
}
} // namespace OHOS::Ace::Framework

View File

@ -41,11 +41,25 @@ public:
void DumpTree(int32_t depth, NodeId nodeID) override;
void SetCardViewParams(const std::string& key, bool focus) override;
void UpdateViewScale();
float GetScaleX() const
{
return scaleX_;
}
float GetScaleY() const
{
return scaleY_;
}
private:
void UpdateNodeChildIds(const RefPtr<AccessibilityNode>& node);
void SendAccessibilitySyncEvent(const AccessibilityEvent& accessibilityEvent);
std::string callbackKey_;
float scaleX_ = 1.0f;
float scaleY_ = 1.0f;
};
} // namespace OHOS::Ace::Framework

View File

@ -16,6 +16,7 @@
#include "frameworks/bridge/common/dom/dom_badge.h"
#include "base/log/event_report.h"
#include "core/components/declaration/badge/badge_declaration.h"
#include "frameworks/bridge/common/utils/utils.h"
namespace OHOS::Ace::Framework {
@ -23,89 +24,29 @@ namespace OHOS::Ace::Framework {
DOMBadge::DOMBadge(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
{
badgeChild_ = AceType::MakeRefPtr<BadgeComponent>();
if (IsRightToLeft()) {
badgeChild_->SetTextDirection(TextDirection::RTL);
}
}
void DOMBadge::ResetInitializedStyle()
{
InitializeStyle();
}
bool DOMBadge::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
{
static const LinearMapNode<void (*)(DOMBadge&, const std::string&)> badgeAttrOperators[] = {
{ DOM_BADGE_COUNT,
[](DOMBadge& badge, const std::string& value) { badge.badgeChild_->SetMessageCount(StringToInt(value)); } },
{ DOM_BADGE_LABEL,
[](DOMBadge& badge, const std::string& value) { badge.badgeChild_->SetBadgeLabel(value); } },
{ DOM_BADGE_MAX_COUNT,
[](DOMBadge& badge, const std::string& value) { badge.badgeChild_->SetMaxCount(StringToInt(value)); } },
{ DOM_BADGE_PLACEMENT,
[](DOMBadge& badge, const std::string& value) {
badge.badgeChild_->SetBadgePosition(ConvertStrToBadgePosition(value));
} },
{ DOM_BADGE_VISIBLE,
[](DOMBadge& badge, const std::string& value) { badge.badgeChild_->SetShowMessage(StringToBool(value)); } }
};
auto operatorIter = BinarySearchFindIndex(badgeAttrOperators, ArraySize(badgeAttrOperators), attr.first.c_str());
if (operatorIter != -1) {
badgeAttrOperators[operatorIter].value(*this, attr.second);
return true;
if (declaration_) {
declaration_->InitializeStyle();
}
return false;
}
bool DOMBadge::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
{
const static LinearMapNode<void (*)(DOMBadge&, const std::string&)> badgeOperators[] = {
{ DOM_BADGE_COLOR,
[](DOMBadge& badge, const std::string& value) {
badge.badgeChild_->SetBadgeColor(badge.ParseColor(value));
} },
{ DOM_BADGE_CIRCLE_SIZE,
[](DOMBadge& badge, const std::string& value) {
badge.badgeChild_->SetBadgeCircleSize(badge.ParseDimension(value));
} },
{ DOM_BADGE_TEXT_FONT_SIZE,
[](DOMBadge& badge, const std::string& value) {
badge.badgeChild_->SetBadgeFontSize(badge.ParseDimension(value));
} },
{ DOM_BADGE_TEXT_COLOR,
[](DOMBadge& badge, const std::string& value) {
badge.badgeChild_->SetBadgeTextColor(badge.ParseColor(value));
} },
};
auto operatorIter = BinarySearchFindIndex(badgeOperators, ArraySize(badgeOperators), style.first.c_str());
if (operatorIter != -1) {
badgeOperators[operatorIter].value(*this, style.second);
return true;
}
return false;
}
bool DOMBadge::AddSpecializedEvent(int32_t pageId, const std::string& event)
{
if (event == DOM_CLICK) {
badgeClickEvent_ = EventMarker(GetNodeIdForEvent(), event, pageId);
badgeChild_->SetClickEvent(badgeClickEvent_);
return true;
}
return false;
}
void DOMBadge::PrepareSpecializedComponent()
{
if (!boxComponent_) {
auto declaration = AceType::DynamicCast<BadgeDeclaration>(declaration_);
badgeChild_->SetDeclaration(AceType::DynamicCast<BadgeDeclaration>(declaration));
if (!boxComponent_ || !declaration) {
return;
}
badgeChild_->SetTextDirection(declaration->IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
boxComponent_->SetAlignment(Alignment::TOP_LEFT);
auto edge = boxComponent_->GetPadding();
if (edge == Edge::NONE) {
return;
}
badgeChild_->SetPadding(edge);
declaration->SetPadding(edge);
boxComponent_->SetPadding(Edge());
}
@ -123,35 +64,24 @@ void DOMBadge::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
badgeChild_->SetChild(nullptr);
}
void DOMBadge::InitializeStyle()
{
badgeTheme_ = GetTheme<BadgeTheme>();
if (!badgeTheme_) {
LOGE("badgeTheme is null");
EventReport::SendComponentException(ComponentExcepType::GET_THEME_ERR);
return;
}
badgeChild_->SetBadgeColor(badgeTheme_->GetBadgeColor());
badgeChild_->SetMessageCount(badgeTheme_->GetMessageCount());
badgeChild_->SetBadgePosition(badgeTheme_->GetBadgePosition());
badgeChild_->SetShowMessage(badgeTheme_->GetShowMessage());
badgeChild_->SetBadgeTextColor(badgeTheme_->GetBadgeTextColor());
badgeChild_->SetBadgeFontSize(badgeTheme_->GetBadgeFontSize());
}
void DOMBadge::SetBadgeConfig(const BadgeConfig& badgeConfig)
{
auto declaration = AceType::DynamicCast<BadgeDeclaration>(declaration_);
if (!declaration) {
return;
}
if (badgeConfig.badgeColor.second) {
badgeChild_->SetBadgeColor(badgeConfig.badgeColor.first);
declaration->SetBadgeColor(badgeConfig.badgeColor.first);
}
if (badgeConfig.badgeSize.second) {
badgeChild_->SetBadgeCircleSize(badgeConfig.badgeSize.first);
declaration->SetBadgeCircleSize(badgeConfig.badgeSize.first);
}
if (badgeConfig.textColor.second) {
badgeChild_->SetBadgeTextColor(badgeConfig.textColor.first);
declaration->SetBadgeTextColor(badgeConfig.textColor.first);
}
if (badgeConfig.textSize.second) {
badgeChild_->SetBadgeFontSize(badgeConfig.textSize.first);
declaration->SetBadgeFontSize(badgeConfig.textSize.first);
}
}

Some files were not shown because too many files have changed in this diff Show More