Merge branch 'master' of gitee.com:openharmony/graphic_graphic_2d into added_drawing_api_in_jspath_getMatrix_getPosition_BuildFromSvg

Signed-off-by: klementievilya <klementiev.ilya@huawei-partners.com>
This commit is contained in:
klementievilya 2024-07-08 08:24:16 +00:00 committed by Gitee
commit 73a74ec7ee
502 changed files with 17850 additions and 2951 deletions

View File

@ -34,6 +34,7 @@ group("graphic_common_test") {
"frameworks/bootanimation/test:test",
"frameworks/opengl_wrapper/test:test",
"frameworks/vulkan_layers/test:test",
"rosen/graphic_test:test",
"rosen/modules/composer:test",
"rosen/modules/create_pixelmap_surface:test",
"rosen/modules/effect/test/unittest:test",

View File

@ -0,0 +1,14 @@
# Copyright (c) 2024 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.
use_external_icu = "shared"

View File

@ -12,10 +12,10 @@
# limitations under the License.
import("//build/ohos.gni")
import("common.gni")
form_components_support = true
plugin_components_support = true
use_external_icu = "shared"
defines = [
"FORM_SUPPORTED",

View File

@ -11,9 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import("common.gni")
form_components_support = false
plugin_components_support = false
use_external_icu = "shared"
defines = [ "NG_BUILD" ]

View File

@ -12,6 +12,9 @@
# limitations under the License.
# linux platform defines and configs
import("preview_common.gni")
defines = [
"LINUX_PLATFORM",
"GPU_DISABLED",

View File

@ -11,7 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# windows platform defines and configs
# mac platform defines and configs
import("preview_common.gni")
defines = [
"MAC_PLATFORM",
"SK_BUILD_FONT_MGR_FOR_PREVIEW_MAC",

View File

@ -12,6 +12,9 @@
# limitations under the License.
# windows platform defines and configs
import("preview_common.gni")
defines = [
"WINDOWS_PLATFORM",
"_USE_MATH_DEFINES",

View File

@ -0,0 +1,16 @@
# Copyright (c) 2024 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.
# previewer common defines and configs
use_external_icu = "shared"

View File

@ -203,6 +203,15 @@
]
}
},
{
"type": "so",
"name": "//foundation/graphic/graphic_2d/rosen/modules/frame_analyzer:libframe_analyzer",
"header": {
"header_files": [
],
"header_base": "//foundation/graphic/graphic_2d/rosen/modules/frame_analyzer/export"
}
},
{
"type": "so",
"name": "//foundation/graphic/graphic_2d/utils:libgraphic_utils",

View File

@ -20,3 +20,4 @@ persist.graphic.bootsound.enabled = graphics:servicectrl:0775
rosen.dirtyregiondebug.enabled = graphics:servicectrl:0775
rosen.drawingCache.enabledDfx = graphics:servicectrl:0775
bootevent.renderservice.ready = graphics:graphics:0777
persist.sys.graphic.hideNotch.status = graphics:graphics:0777

View File

@ -46,11 +46,7 @@ void BootAnimationOperation::Init(const BootAnimationConfig& config, int32_t wid
windowHeight_ = height;
duration_ = duration * DELAY_TIME_MS;
eventThread_ = std::thread(&BootAnimationOperation::StartEventHandler, this, config);
std::unique_lock<std::mutex> lock(eventMutex_);
eventCon_.wait(lock, [this] {
return mainHandler_ != nullptr;
});
eventThread_ = std::thread([this, &config] { this->StartEventHandler(config); });
}
void BootAnimationOperation::StartEventHandler(const BootAnimationConfig& config)
@ -58,25 +54,24 @@ void BootAnimationOperation::StartEventHandler(const BootAnimationConfig& config
LOGI("StartEventHandler");
runner_ = AppExecFwk::EventRunner::Create(false);
mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
mainHandler_->PostTask(std::bind(&BootAnimationOperation::InitRsDisplayNode, this));
mainHandler_->PostTask(std::bind(&BootAnimationOperation::InitRsSurfaceNode, this, config.rotateDegree));
mainHandler_->PostTask(std::bind(&BootAnimationOperation::StopBootAnimation, this), duration_);
eventCon_.notify_all();
mainHandler_->PostTask([this] { this->InitRsDisplayNode(); });
mainHandler_->PostTask([this, &config] { this->InitRsSurfaceNode(config.rotateDegree); });
mainHandler_->PostTask([this] { this->StopBootAnimation(); }, duration_);
#ifdef PLAYER_FRAMEWORK_ENABLE
if (IsBootVideoEnabled(config)) {
mainHandler_->PostTask(std::bind(&BootAnimationOperation::PlayVideo, this, config.videoDefaultPath));
mainHandler_->PostTask([this, &config] { this->PlayVideo(config.videoDefaultPath); });
runner_->Run();
LOGI("runner run has ended.");
return;
} else {
mainHandler_->PostTask(std::bind(
&BootAnimationOperation::PlaySound, this, config.soundPath));
mainHandler_->PostTask([this, &config] { this->PlaySound(config.soundPath); });
}
#else
LOGI("player framework is disabled");
#endif
mainHandler_->PostTask(
std::bind(&BootAnimationOperation::PlayPicture, this, config.picZipPath));
mainHandler_->PostTask([this, &config] { this->PlayPicture(config.picZipPath); });
runner_->Run();
LOGI("runner run has ended.");
}
void BootAnimationOperation::SetSoundEnable(bool isEnabled)
@ -153,7 +148,7 @@ void BootAnimationOperation::PlayVideo(const std::string& path)
params.resPath = path;
callback_ = {
.userData = this,
.callback = std::bind(&BootAnimationOperation::StopBootAnimation, this),
.callback = [this](void*) { this->StopBootAnimation(); },
};
params.callback = &callback_;
params.screenId = currentScreenId_;
@ -251,8 +246,7 @@ void BootAnimationOperation::StopBootAnimation()
system::SetParameter(BOOT_ANIMATION_STARTED, "true");
LOGI("set boot animation started true");
}
if (runner_ != nullptr) {
runner_->Stop();
}
runner_->Stop();
LOGI("runner has called stop.");
mainHandler_ = nullptr;
}

View File

@ -46,7 +46,7 @@ namespace {
constexpr const float OFFSET_Y_PERCENT = 0.85f;
constexpr const float HEIGHT_PERCENT = 0.05f;
constexpr const int TEXT_BLOB_OFFSET = 5;
constexpr const int FONT_SIZE = 48;
constexpr const int FONT_SIZE = 40;
constexpr const int32_t MAX_RETRY_TIMES = 5;
constexpr const int32_t WAIT_MS = 500;
constexpr const int32_t WAITING_BMS_TIMEOUT = 30;
@ -83,8 +83,8 @@ void BootCompileProgress::Init(const BootAnimationConfig& config)
SHARP_CURVE_CTLX1, SHARP_CURVE_CTLY1, SHARP_CURVE_CTLX2, SHARP_CURVE_CTLY2);
compileRunner_ = AppExecFwk::EventRunner::Create(false);
compileHandler_ = std::make_shared<AppExecFwk::EventHandler>(compileRunner_);
compileHandler_->PostTask(std::bind(&BootCompileProgress::CreateCanvasNode, this));
compileHandler_->PostTask(std::bind(&BootCompileProgress::RegisterVsyncCallback, this));
compileHandler_->PostTask([this] { this->CreateCanvasNode(); });
compileHandler_->PostTask([this] { this->RegisterVsyncCallback(); });
compileRunner_->Run();
}
@ -97,7 +97,7 @@ bool BootCompileProgress::CreateCanvasNode()
rsSurfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
if (!rsSurfaceNode_) {
LOGE("ota compile, SFNode create failed");
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
return false;
}
float positionZ = MAX_ZORDER + 1;
@ -126,12 +126,12 @@ bool BootCompileProgress::RegisterVsyncCallback()
{
if (system::GetParameter(BMS_COMPILE_STATUS, "-1") == BMS_COMPILE_STATUS_END) {
LOGI("bms compile is already done.");
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
return false;
}
if (!WaitBmsStartIfNeeded()) {
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
return false;
}
@ -140,7 +140,7 @@ bool BootCompileProgress::RegisterVsyncCallback()
while (receiver_ == nullptr) {
if (retry++ > MAX_RETRY_TIMES) {
LOGE("get vsync receiver failed");
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
return false;
}
if (retry > 1) {
@ -150,18 +150,18 @@ bool BootCompileProgress::RegisterVsyncCallback()
}
VsyncError ret = receiver_->Init();
if (ret) {
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
LOGE("init vsync receiver failed");
return false;
}
Rosen::VSyncReceiver::FrameCallback fcb = {
.userData_ = this,
.callback_ = std::bind(&BootCompileProgress::OnVsync, this),
.callback_ = [this](int64_t, void*) { this->OnVsync(); },
};
ret = receiver_->SetVSyncRate(fcb, CHANGE_FREQ);
if (ret) {
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
LOGE("set vsync rate failed");
}
@ -185,10 +185,10 @@ bool BootCompileProgress::WaitBmsStartIfNeeded()
void BootCompileProgress::OnVsync()
{
if (!isUpdateOptEnd_) {
compileHandler_->PostTask(std::bind(&BootCompileProgress::DrawCompileProgress, this));
compileHandler_->PostTask([this] { this->DrawCompileProgress(); });
} else {
LOGI("ota compile completed");
compileHandler_->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, compileRunner_));
compileRunner_->Stop();
}
}

View File

@ -42,7 +42,7 @@ void BootPicturePlayer::Play()
VsyncError ret = receiver_->Init();
if (ret) {
LOGE("vsync receiver init failed: %{public}d", ret);
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return;
}
@ -51,20 +51,20 @@ void BootPicturePlayer::Play()
imgVecSize_ = static_cast<int32_t> (imageVector_.size());
} else {
LOGE("read pic zip failed");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return;
}
ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
.userData_ = this,
.callback_ = std::bind(&BootPicturePlayer::OnVsync, this),
.callback_ = [this](int64_t, void*) { this->OnVsync(); },
};
int32_t changeFreq = static_cast<int32_t> (1000.0 / freq_ / 16);
ret = receiver_->SetVSyncRate(fcb, changeFreq);
if (ret) {
LOGE("SetVSyncRate failed: %{public}d %{public}d", ret, freq_);
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return;
} else {
LOGI("SetVSyncRate success: %{public}d, %{public}d", freq_, changeFreq);
@ -127,14 +127,14 @@ bool BootPicturePlayer::CheckFrameRateValid(int32_t frameRate)
void BootPicturePlayer::OnVsync()
{
PostTask(std::bind(&BootPicturePlayer::Draw, this));
PostTask([this] { this->Draw(); });
}
bool BootPicturePlayer::Draw()
{
if (picCurNo_ >= (imgVecSize_ - 1)) {
LOGI("play sequence frames end");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return false;
}
picCurNo_ = picCurNo_ + 1;
@ -143,13 +143,13 @@ bool BootPicturePlayer::Draw()
ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP);
if (frame == nullptr) {
LOGE("draw frame is nullptr");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return false;
}
#ifdef NEW_RENDER_CONTEXT
if (rsSurface_ == nullptr) {
LOGE("rsSurface is nullptr");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return false;
}
auto canvas = rsSurface_->GetCanvas();
@ -172,11 +172,11 @@ bool BootPicturePlayer::OnDraw(Rosen::Drawing::CoreCanvas* canvas, int32_t curNo
{
if (canvas == nullptr) {
LOGE("OnDraw canvas is nullptr");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return false;
}
if (curNo > (imgVecSize_ - 1) || curNo < 0) {
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, AppExecFwk::EventRunner::Current()));
AppExecFwk::EventRunner::Current()->Stop();
return false;
}
std::shared_ptr<ImageStruct> imgstruct = imageVector_[curNo];

View File

@ -67,9 +67,9 @@ HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_002, TestSize.
HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_003, TestSize.Level1)
{
BootAnimationController controller;
controller.isCompatible_ = true;
controller.isMultiDisplay_ = true;
BootStrategyType type = controller.GetBootType();
EXPECT_EQ(type, BootStrategyType::COMPATIBLE);
EXPECT_EQ(type, BootStrategyType::INDEPENDENT);
}
/**
@ -80,7 +80,8 @@ HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_003, TestSize.
HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_004, TestSize.Level1)
{
BootAnimationController controller;
controller.isMultiDisplay_ = true;
BootAnimationConfig config;
controller.animationConfigs_.emplace_back(config);
BootStrategyType type = controller.GetBootType();
EXPECT_EQ(type, BootStrategyType::INDEPENDENT);
}
@ -91,20 +92,6 @@ HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_004, TestSize.
* @tc.type:FUNC
*/
HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_005, TestSize.Level1)
{
BootAnimationController controller;
BootAnimationConfig config;
controller.animationConfigs_.emplace_back(config);
BootStrategyType type = controller.GetBootType();
EXPECT_EQ(type, BootStrategyType::INDEPENDENT);
}
/**
* @tc.name: BootAnimationControllerTest_006
* @tc.desc: Verify the GetBootType
* @tc.type:FUNC
*/
HWTEST_F(BootAnimationControllerTest, BootAnimationControllerTest_006, TestSize.Level1)
{
BootAnimationController controller;
BootAnimationConfig first_config;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024 Huawei Device Co., Ltd.
* Copyright (c) 2024 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
@ -31,7 +31,7 @@ namespace OHOS {
namespace {
const std::string defaultJsonConfig = R"__(
const std::string DEFAULT_JSON_CONFIG = R"__(
{
"enableAppMode" : true,
"appMode" : {
@ -93,8 +93,8 @@ bool EglSystemLayersManager::GetJsonConfig(Json::Value &configData)
}
const std::unique_ptr<Json::CharReader> reader(charReader);
JSONCPP_STRING errs;
bool ret = reader->parse(defaultJsonConfig.c_str(),
defaultJsonConfig.c_str() + static_cast<int>(defaultJsonConfig.length()), &configData, &errs);
bool ret = reader->parse(DEFAULT_JSON_CONFIG.c_str(),
DEFAULT_JSON_CONFIG.c_str() + static_cast<int>(DEFAULT_JSON_CONFIG.length()), &configData, &errs);
if (!ret) {
WLOGE("json parse error: %{private}s", errs.c_str());
return false;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024 Huawei Device Co., Ltd.
* Copyright (c) 2024 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

View File

@ -145,9 +145,16 @@ static std::vector<std::string> GetDebugLayerPaths()
WLOGD("GetDebugLayerPaths");
std::vector<std::string> layerPaths = {std::string(DEBUG_LAYERS_LIB_DIR)};
std::string pathStr(DEBUG_SANDBOX_DIR);
layerPaths.push_back(pathStr + g_bundleInfo.applicationInfo.nativeLibraryPath + "/");
std::string appLibPath = g_bundleInfo.applicationInfo.nativeLibraryPath;
if (!appLibPath.empty()) {
layerPaths.push_back(pathStr + appLibPath + "/");
}
for (auto hapModuleInfo: g_bundleInfo.hapModuleInfos) {
layerPaths.push_back(hapModuleInfo.nativeLibraryPath + "/");
if (!hapModuleInfo.nativeLibraryPath.empty()) {
layerPaths.push_back(hapModuleInfo.nativeLibraryPath + "/");
}
}
return layerPaths;
}
@ -176,11 +183,6 @@ bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
return false;
}
if (!InitBundleInfo()) {
WLOGE("Get BundleInfo failed.");
return false;
}
if (!LoadLayers()) {
WLOGE("LoadLayers failed.");
return false;
@ -194,6 +196,11 @@ bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
bool EglWrapperLayer::InitBundleInfo()
{
std::string debugHap = system::GetParameter(DEBUG_HAP_NAME, "");
if (debugHap.empty()) {
WLOGD("The parameter for debug hap name is not set!");
return false;
}
auto eglBundleMgrHelper = DelayedSingleton<AppExecFwk::EGLBundleMgrHelper>::GetInstance();
if (eglBundleMgrHelper == nullptr) {
WLOGE("eglBundleMgrHelper is null!");
@ -202,7 +209,6 @@ bool EglWrapperLayer::InitBundleInfo()
if (eglBundleMgrHelper->GetBundleInfoForSelf(
AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION, g_bundleInfo) == ERR_OK) {
std::string debugHap = system::GetParameter(DEBUG_HAP_NAME, "");
if (g_bundleInfo.name == debugHap) {
return true;
} else {
@ -279,6 +285,10 @@ bool EglWrapperLayer::LoadLayers()
return false;
}
if (!InitBundleInfo()) {
WLOGD("Get BundleInfo failed.");
}
for (int32_t i = layers.size() - 1; i >= 0; i--) {
std::string layerLib = std::string(DEBUG_LAYERS_PREFIX) + layers[i] + std::string(DEBUG_LAYERS_SUFFIX);
std::vector<std::string> allLayerPaths = GetDebugLayerPaths();

View File

@ -84,8 +84,7 @@ typedef struct OH_OnFrameAvailableListener {
OH_NativeImage* OH_NativeImage_Create(uint32_t textureId, uint32_t textureTarget);
/**
* @brief Acquire the OHNativeWindow for the OH_NativeImage. This OHNativeWindow should be released by \n
* OH_NativeWindow_DestroyNativeWindow when no longer needed.
* @brief Acquire the OHNativeWindow for the OH_NativeImage.
*
* @syscap SystemCapability.Graphic.Graphic2D.NativeImage
* @param image Indicates the pointer to a <b>OH_NativeImage</b> instance.
@ -152,6 +151,8 @@ int64_t OH_NativeImage_GetTimestamp(OH_NativeImage* image);
* @return Returns an error code, 0 is success, otherwise, failed.
* @since 9
* @version 1.0
* @deprecated since 12
* @useinstead OH_NativeImage_GetTransformMatrixV2
*/
int32_t OH_NativeImage_GetTransformMatrix(OH_NativeImage* image, float matrix[16]);

View File

@ -25,6 +25,7 @@ ohos_shared_library("cj_color_manager_ffi") {
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}

View File

@ -25,7 +25,7 @@ namespace ColorManager {
class CjColorManager : public OHOS::FFI::FFIData {
public:
explicit CjColorManager(std::shared_ptr<ColorSpace> ptr);
virtual ~CjColorManager()
~CjColorManager() override
{
colorSpaceToken_ = nullptr;
}

View File

@ -132,6 +132,7 @@ template("sendablecolorspacemanager_napi_source_set") {
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}

View File

@ -67,12 +67,14 @@ ohos_shared_library("drawing_napi_impl") {
"js_common.cpp",
"js_drawing_init.cpp",
"js_drawing_utils.cpp",
"lattice_napi/js_lattice.cpp",
"mask_filter_napi/js_mask_filter.cpp",
"matrix_napi/js_matrix.cpp",
"path_effect_napi/js_path_effect.cpp",
"path_napi/js_path.cpp",
"pen_napi/js_pen.cpp",
"region_napi/js_region.cpp",
"roundRect_napi/js_roundrect.cpp",
"sampling_options_napi/js_sampling_options.cpp",
"shadow_layer_napi/js_shadow_layer.cpp",
"text_blob_napi/js_text_blob.cpp",

View File

@ -141,7 +141,7 @@ napi_value JsBrush::SetColor(napi_env env, napi_callback_info info)
GET_COLOR_PARAM(ARGC_THREE, blue);
drawingColor = Color::ColorQuadSetARGB(alpha, red, green, blue);
} else {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect number of parameters.");
}
brush->SetColor(drawingColor);
return nullptr;
@ -260,7 +260,7 @@ napi_value JsBrush::SetBlendMode(napi_env env, napi_callback_info info)
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
int32_t mode = 0;
GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ZERO, mode);
GET_ENUM_PARAM(ARGC_ZERO, mode, 0, static_cast<int32_t>(BlendMode::LUMINOSITY));
brush->SetBlendMode(static_cast<BlendMode>(mode));
return nullptr;
@ -270,7 +270,7 @@ napi_value JsBrush::SetShadowLayer(napi_env env, napi_callback_info info)
{
JsBrush* jsBrush = CheckParamsAndGetThis<JsBrush>(env, info);
if (jsBrush == nullptr) {
ROSEN_LOGE("JsBrush::SetMaskFilter jsBrush is nullptr");
ROSEN_LOGE("JsBrush::SetShadowLayer jsBrush is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
Brush* brush = jsBrush->GetBrush();

View File

@ -17,6 +17,8 @@
#include <mutex>
#include "src/utils/SkUTF.h"
#ifdef ROSEN_OHOS
#include "pixel_map.h"
#include "pixel_map_napi.h"
@ -34,6 +36,7 @@
#include "utils/vertices.h"
#include "brush_napi/js_brush.h"
#include "font_napi/js_font.h"
#include "matrix_napi/js_matrix.h"
#include "pen_napi/js_pen.h"
#include "path_napi/js_path.h"
@ -330,14 +333,19 @@ napi_value JsCanvas::Constructor(napi_env env, napi_callback_info info)
bool JsCanvas::DeclareFuncAndCreateConstructor(napi_env env)
{
napi_property_descriptor properties[] = {
DECLARE_NAPI_FUNCTION("clear", JsCanvas::Clear),
DECLARE_NAPI_FUNCTION("drawArc", JsCanvas::DrawArc),
DECLARE_NAPI_FUNCTION("drawRect", JsCanvas::DrawRect),
DECLARE_NAPI_FUNCTION("drawCircle", JsCanvas::DrawCircle),
DECLARE_NAPI_FUNCTION("drawImage", JsCanvas::DrawImage),
DECLARE_NAPI_FUNCTION("drawColor", JsCanvas::DrawColor),
DECLARE_NAPI_FUNCTION("drawOval", JsCanvas::DrawOval),
DECLARE_NAPI_FUNCTION("drawPoint", JsCanvas::DrawPoint),
DECLARE_NAPI_FUNCTION("drawPoints", JsCanvas::DrawPoints),
DECLARE_NAPI_FUNCTION("drawPath", JsCanvas::DrawPath),
DECLARE_NAPI_FUNCTION("drawLine", JsCanvas::DrawLine),
DECLARE_NAPI_FUNCTION("drawTextBlob", JsCanvas::DrawText),
DECLARE_NAPI_FUNCTION("drawSingleCharacter", JsCanvas::DrawSingleCharacter),
DECLARE_NAPI_FUNCTION("drawPixelMapMesh", JsCanvas::DrawPixelMapMesh),
DECLARE_NAPI_FUNCTION("drawRegion", JsCanvas::DrawRegion),
DECLARE_NAPI_FUNCTION("attachPen", JsCanvas::AttachPen),
@ -347,6 +355,8 @@ bool JsCanvas::DeclareFuncAndCreateConstructor(napi_env env)
DECLARE_NAPI_FUNCTION("skew", JsCanvas::Skew),
DECLARE_NAPI_FUNCTION("rotate", JsCanvas::Rotate),
DECLARE_NAPI_FUNCTION("getSaveCount", JsCanvas::GetSaveCount),
DECLARE_NAPI_FUNCTION("getWidth", JsCanvas::GetWidth),
DECLARE_NAPI_FUNCTION("getHeight", JsCanvas::GetHeight),
DECLARE_NAPI_FUNCTION("save", JsCanvas::Save),
DECLARE_NAPI_FUNCTION("saveLayer", JsCanvas::SaveLayer),
DECLARE_NAPI_FUNCTION("restore", JsCanvas::Restore),
@ -354,6 +364,7 @@ bool JsCanvas::DeclareFuncAndCreateConstructor(napi_env env)
DECLARE_NAPI_FUNCTION("scale", JsCanvas::Scale),
DECLARE_NAPI_FUNCTION("clipPath", JsCanvas::ClipPath),
DECLARE_NAPI_FUNCTION("clipRect", JsCanvas::ClipRect),
DECLARE_NAPI_FUNCTION("concatMatrix", JsCanvas::ConcatMatrix),
DECLARE_NAPI_FUNCTION("setMatrix", JsCanvas::SetMatrix),
DECLARE_NAPI_FUNCTION("translate", JsCanvas::Translate),
};
@ -449,6 +460,66 @@ JsCanvas::~JsCanvas()
g_drawingCanvas = nullptr;
}
napi_value JsCanvas::Clear(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnClear(env, info) : nullptr;
}
napi_value JsCanvas::OnClear(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnClear canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
int32_t argb[ARGC_FOUR] = {0};
if (!ConvertFromJsColor(env, argv[ARGC_ZERO], argb, ARGC_FOUR)) {
ROSEN_LOGE("JsCanvas::OnClear Argv[0] is invalid");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. The range of color channels must be [0, 255].");
}
auto color = Color::ColorQuadSetARGB(argb[ARGC_ZERO], argb[ARGC_ONE], argb[ARGC_TWO], argb[ARGC_THREE]);
JS_CALL_DRAWING_FUNC(m_canvas->Clear(color));
return nullptr;
}
napi_value JsCanvas::DrawArc(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnDrawArc(env, info) : nullptr;
}
napi_value JsCanvas::OnDrawArc(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnDrawArc canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_THREE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
double startAngle = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, startAngle);
double sweepAngle = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, sweepAngle);
JS_CALL_DRAWING_FUNC(m_canvas->DrawArc(drawingRect, startAngle, sweepAngle));
return nullptr;
}
napi_value JsCanvas::DrawRect(napi_env env, napi_callback_info info)
{
DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
@ -641,6 +712,32 @@ napi_value JsCanvas::OnDrawColor(napi_env env, napi_callback_info info)
return nullptr;
}
napi_value JsCanvas::DrawOval(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnDrawOval(env, info) : nullptr;
}
napi_value JsCanvas::OnDrawOval(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnDrawOval canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
JS_CALL_DRAWING_FUNC(m_canvas->DrawOval(drawingRect));
return nullptr;
}
napi_value JsCanvas::DrawPoint(napi_env env, napi_callback_info info)
{
DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
@ -668,6 +765,62 @@ napi_value JsCanvas::OnDrawPoint(napi_env env, napi_callback_info info)
return nullptr;
}
static bool OnMakePoints(napi_env& env, Point* point, uint32_t size, napi_value& array)
{
for (uint32_t i = 0; i < size; i++) {
napi_value tempNumber = nullptr;
napi_get_element(env, array, i, &tempNumber);
napi_value tempValue = nullptr;
double pointX = 0.0;
double pointY = 0.0;
napi_get_named_property(env, tempNumber, "x", &tempValue);
bool isPointXOk = ConvertFromJsValue(env, tempValue, pointX);
napi_get_named_property(env, tempNumber, "y", &tempValue);
bool isPointYOk = ConvertFromJsValue(env, tempValue, pointY);
if (!(isPointXOk && isPointYOk)) {
return false;
}
point[i] = Point(pointX, pointY);
}
return true;
}
napi_value JsCanvas::DrawPoints(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnDrawPoints(env, info) : nullptr;
}
napi_value JsCanvas::OnDrawPoints(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnDrawPoints canvas is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
int32_t pointMode = 0;
GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ZERO, pointMode);
napi_value array = argv[ARGC_ONE];
uint32_t size = 0;
napi_get_array_length(env, array, &size);
Point* points = new Point[size];
if (points == nullptr) {
return nullptr;
}
if (!OnMakePoints(env, points, size, array)) {
delete [] points;
ROSEN_LOGE("JsCanvas::OnDrawPoints Argv[ARGC_ONE] is invalid");
return nullptr;
}
JS_CALL_DRAWING_FUNC(m_canvas->DrawPoints(PointMode(pointMode), size, points));
delete [] points;
return nullptr;
}
napi_value JsCanvas::DrawPath(napi_env env, napi_callback_info info)
{
DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
@ -758,6 +911,60 @@ napi_value JsCanvas::OnDrawText(napi_env env, napi_callback_info info)
return nullptr;
}
napi_value JsCanvas::DrawSingleCharacter(napi_env env, napi_callback_info info)
{
DRAWING_PERFORMANCE_TEST_JS_RETURN(nullptr);
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnDrawSingleCharacter(env, info) : nullptr;
}
napi_value JsCanvas::OnDrawSingleCharacter(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnDrawSingleCharacter canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_FOUR] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
size_t len = 0;
if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], nullptr, 0, &len) != napi_ok) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
}
if (len == 0 || len > 4) { // 4 is the maximum length of a character encoded in UTF8.
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. Input parameter0 should be single character.");
}
char str[len + 1];
if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], str, len + 1, &len) != napi_ok) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
}
JsFont* jsFont = nullptr;
GET_UNWRAP_PARAM(ARGC_ONE, jsFont);
double x = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, x);
double y = 0.0;
GET_DOUBLE_PARAM(ARGC_THREE, y);
std::shared_ptr<Font> font = jsFont->GetFont();
if (font == nullptr) {
ROSEN_LOGE("JsCanvas::OnDrawSingleCharacter font is nullptr");
return nullptr;
}
const char* currentStr = str;
int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
size_t byteLen = currentStr - str;
if (byteLen != len) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. Input parameter0 should be single character.");
}
m_canvas->DrawSingleCharacter(unicode, *font, x, y);
return nullptr;
}
napi_value JsCanvas::DrawPixelMapMesh(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
@ -1046,6 +1253,36 @@ napi_value JsCanvas::OnGetSaveCount(napi_env env, napi_callback_info info)
return CreateJsNumber(env, m_canvas->GetSaveCount());
}
napi_value JsCanvas::GetWidth(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnGetWidth(env, info) : nullptr;
}
napi_value JsCanvas::OnGetWidth(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnGetWidth canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
return CreateJsNumber(env, m_canvas->GetWidth());
}
napi_value JsCanvas::GetHeight(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnGetHeight(env, info) : nullptr;
}
napi_value JsCanvas::OnGetHeight(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnGetHeight canvas is null");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
return CreateJsNumber(env, m_canvas->GetHeight());
}
napi_value JsCanvas::ClipPath(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
@ -1303,7 +1540,7 @@ napi_value JsCanvas::OnSetMatrix(napi_env env, napi_callback_info info)
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsCanvas::OnConcatMatrix matrix is nullptr");
ROSEN_LOGE("JsCanvas::OnSetMatrix matrix is nullptr");
return nullptr;
}
@ -1336,6 +1573,34 @@ napi_value JsCanvas::OnScale(napi_env env, napi_callback_info info)
return nullptr;
}
napi_value JsCanvas::ConcatMatrix(napi_env env, napi_callback_info info)
{
JsCanvas* me = CheckParamsAndGetThis<JsCanvas>(env, info);
return (me != nullptr) ? me->OnConcatMatrix(env, info) : nullptr;
}
napi_value JsCanvas::OnConcatMatrix(napi_env env, napi_callback_info info)
{
if (m_canvas == nullptr) {
ROSEN_LOGE("JsCanvas::OnConcatMatrix canvas is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsCanvas::OnConcatMatrix matrix is nullptr");
return nullptr;
}
JS_CALL_DRAWING_FUNC(m_canvas->ConcatMatrix(*jsMatrix->GetMatrix()));
return nullptr;
}
Canvas* JsCanvas::GetCanvas()
{
return m_canvas;

View File

@ -51,21 +51,29 @@ public:
static napi_value AttachBrush(napi_env env, napi_callback_info info);
static napi_value AttachPen(napi_env env, napi_callback_info info);
static napi_value Clear(napi_env env, napi_callback_info info);
static napi_value ClipPath(napi_env env, napi_callback_info info);
static napi_value ClipRect(napi_env env, napi_callback_info info);
static napi_value ConcatMatrix(napi_env env, napi_callback_info info);
static napi_value DrawArc(napi_env env, napi_callback_info info);
static napi_value DrawCircle(napi_env env, napi_callback_info info);
static napi_value DrawColor(napi_env env, napi_callback_info info);
static napi_value DrawImage(napi_env env, napi_callback_info info);
static napi_value DrawLine(napi_env env, napi_callback_info info);
static napi_value DrawRect(napi_env env, napi_callback_info info);
static napi_value DrawOval(napi_env env, napi_callback_info info);
static napi_value DrawPoint(napi_env env, napi_callback_info info);
static napi_value DrawPoints(napi_env env, napi_callback_info info);
static napi_value DrawPath(napi_env env, napi_callback_info info);
static napi_value DrawPixelMapMesh(napi_env env, napi_callback_info info);
static napi_value DrawRegion(napi_env env, napi_callback_info info);
static napi_value DrawSingleCharacter(napi_env env, napi_callback_info info);
static napi_value DrawText(napi_env env, napi_callback_info info);
static napi_value DetachBrush(napi_env env, napi_callback_info info);
static napi_value DetachPen(napi_env env, napi_callback_info info);
static napi_value GetSaveCount(napi_env env, napi_callback_info info);
static napi_value GetWidth(napi_env env, napi_callback_info info);
static napi_value GetHeight(napi_env env, napi_callback_info info);
static napi_value Rotate(napi_env env, napi_callback_info info);
static napi_value RestoreToCount(napi_env env, napi_callback_info info);
static napi_value Restore(napi_env env, napi_callback_info info);
@ -83,19 +91,27 @@ public:
DRAWING_API void RestoreCanvas();
private:
napi_value OnClear(napi_env env, napi_callback_info info);
napi_value OnClipPath(napi_env env, napi_callback_info info);
napi_value OnClipRect(napi_env env, napi_callback_info info);
napi_value OnConcatMatrix(napi_env env, napi_callback_info info);
napi_value OnDrawArc(napi_env env, napi_callback_info info);
napi_value OnDrawCircle(napi_env env, napi_callback_info info);
napi_value OnDrawColor(napi_env env, napi_callback_info info);
napi_value OnDrawImage(napi_env env, napi_callback_info info);
napi_value OnDrawLine(napi_env env, napi_callback_info info);
napi_value OnDrawRect(napi_env env, napi_callback_info info);
napi_value OnDrawOval(napi_env env, napi_callback_info info);
napi_value OnDrawPoint(napi_env env, napi_callback_info info);
napi_value OnDrawPoints(napi_env env, napi_callback_info info);
napi_value OnDrawPath(napi_env env, napi_callback_info info);
napi_value OnDrawPixelMapMesh(napi_env env, napi_callback_info info);
napi_value OnDrawRegion(napi_env env, napi_callback_info info);
napi_value OnDrawSingleCharacter(napi_env env, napi_callback_info info);
napi_value OnDrawText(napi_env env, napi_callback_info info);
napi_value OnGetSaveCount(napi_env env, napi_callback_info info);
napi_value OnGetWidth(napi_env env, napi_callback_info info);
napi_value OnGetHeight(napi_env env, napi_callback_info info);
napi_value OnRotate(napi_env env, napi_callback_info info);
napi_value OnRestoreToCount(napi_env env, napi_callback_info info);
napi_value OnRestore(napi_env env, napi_callback_info info);

View File

@ -119,7 +119,7 @@ napi_value JsColorFilter::CreateBlendModeColorFilter(napi_env env, napi_callback
}
int32_t jsMode = 0;
GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ONE, jsMode);
GET_ENUM_PARAM(ARGC_ONE, jsMode, 0, static_cast<int32_t>(BlendMode::LUMINOSITY));
auto color = Color::ColorQuadSetARGB(argb[ARGC_ZERO], argb[ARGC_ONE], argb[ARGC_TWO], argb[ARGC_THREE]);
std::shared_ptr<ColorFilter> colorFilter = ColorFilter::CreateBlendModeColorFilter(color, BlendMode(jsMode));

View File

@ -21,6 +21,8 @@
#include "native_value.h"
#include "draw/blend_mode.h"
#include "draw/clip.h"
#include "draw/core_canvas.h"
#include "draw/path.h"
#include "draw/pen.h"
#include "effect/mask_filter.h"
#include "text/font_types.h"
@ -119,6 +121,12 @@ static const std::vector<struct JsEnumInt> g_blurType = {
{ "INNER", static_cast<int32_t>(BlurType::INNER) },
};
static const std::vector<struct JsEnumInt> g_rectType = {
{ "DEFAULT", static_cast<int32_t>(Lattice::RectType::DEFAULT) },
{ "TRANSPARENT", static_cast<int32_t>(Lattice::RectType::TRANSPARENT) },
{ "FIXEDCOLOR", static_cast<int32_t>(Lattice::RectType::FIXEDCOLOR) },
};
static const std::vector<struct JsEnumInt> g_fontMetricsFlags = {
{ "UNDERLINE_THICKNESS_VALID", static_cast<int32_t>(
Drawing::FontMetrics::FontMetricsFlags::UNDERLINE_THICKNESS_IS_VALID_FLAG) },
@ -131,6 +139,37 @@ static const std::vector<struct JsEnumInt> g_fontMetricsFlags = {
{ "BOUNDS_INVALID", static_cast<int32_t>(Drawing::FontMetrics::FontMetricsFlags::BOUNDS_INVALID_FLAG) },
};
static const std::vector<struct JsEnumInt> g_fontEdging = {
{ "FONT_EDGING_ALIAS", static_cast<int32_t>(FontEdging::ALIAS) },
{ "FONT_EDGING_ANTI_ALIAS", static_cast<int32_t>(FontEdging::ANTI_ALIAS) },
{ "FONT_EDGING_SUBPIXEL_ANTI_ALIAS", static_cast<int32_t>(FontEdging::SUBPIXEL_ANTI_ALIAS) },
};
static const std::vector<struct JsEnumInt> g_fontHinting = {
{ "FONT_HINTING_NONE", static_cast<int32_t>(FontHinting::NONE) },
{ "FONT_HINTING_SLIGHT", static_cast<int32_t>(FontHinting::SLIGHT) },
{ "FONT_HINTING_NORMAL", static_cast<int32_t>(FontHinting::NORMAL) },
{ "FONT_HINTING_FULL", static_cast<int32_t>(FontHinting::FULL) },
};
static const std::vector<struct JsEnumInt> g_pointMode = {
{ "POINT_MODE_POINTS", static_cast<int32_t>(PointMode::POINTS_POINTMODE) },
{ "POINT_MODE_LINES", static_cast<int32_t>(PointMode::LINES_POINTMODE) },
{ "POINT_MODE_POLYGON", static_cast<int32_t>(PointMode::POLYGON_POINTMODE) },
};
static const std::vector<struct JsEnumInt> g_pathDirection = {
{ "PATH_DIRECTION_CW", static_cast<int32_t>(PathDirection::CW_DIRECTION) },
{ "PATH_DIRECTION_CCW", static_cast<int32_t>(PathDirection::CCW_DIRECTION) },
};
static const std::vector<struct JsEnumInt> g_pathFillType = {
{ "PATH_FILL_TYPE_WINDING", 0 }, // 0: PathFillType::WINDING, conflict with define WINDING
{ "PATH_FILL_TYPE_EVEN_ODD", static_cast<int32_t>(PathFillType::EVENTODD) },
{ "PATH_FILL_TYPE_INVERSE_WINDING", static_cast<int32_t>(PathFillType::INVERSE_WINDING) },
{ "PATH_FILL_TYPE_INVERSE_EVEN_ODD", static_cast<int32_t>(PathFillType::INVERSE_EVENTODD) },
};
static const std::map<std::string_view, const std::vector<struct JsEnumInt>&> g_intEnumClassMap = {
{ "BlendMode", g_blendMode },
{ "TextEncoding", g_textEncoding },
@ -140,7 +179,13 @@ static const std::map<std::string_view, const std::vector<struct JsEnumInt>&> g_
{ "JoinStyle", g_joinStyle },
{ "CapStyle", g_capStyle },
{ "BlurType", g_blurType },
{ "RectType", g_rectType },
{ "FontMetricsFlags", g_fontMetricsFlags },
{ "FontEdging", g_fontEdging },
{ "FontHinting", g_fontHinting },
{ "PointMode", g_pointMode },
{ "PathDirection", g_pathDirection },
{ "PathFillType", g_pathFillType },
};
napi_value JsEnum::JsEnumIntInit(napi_env env, napi_value exports)

View File

@ -15,6 +15,8 @@
#include "js_font.h"
#include "src/utils/SkUTF.h"
#include "native_value.h"
#include "js_drawing_utils.h"
@ -35,9 +37,13 @@ napi_value JsFont::Init(napi_env env, napi_value exportObj)
DECLARE_NAPI_FUNCTION("getTypeface", JsFont::GetTypeface),
DECLARE_NAPI_FUNCTION("getSize", JsFont::GetSize),
DECLARE_NAPI_FUNCTION("getMetrics", JsFont::GetMetrics),
DECLARE_NAPI_FUNCTION("measureSingleCharacter", JsFont::MeasureSingleCharacter),
DECLARE_NAPI_FUNCTION("measureText", JsFont::MeasureText),
DECLARE_NAPI_FUNCTION("setScaleX", JsFont::SetScaleX),
DECLARE_NAPI_FUNCTION("setSkewX", JsFont::SetSkewX),
DECLARE_NAPI_FUNCTION("setEdging", JsFont::SetEdging),
DECLARE_NAPI_FUNCTION("setHinting", JsFont::SetHinting),
DECLARE_NAPI_FUNCTION("countText", JsFont::CountText),
};
napi_value constructor = nullptr;
@ -84,6 +90,10 @@ napi_value JsFont::Constructor(napi_env env, napi_callback_info info)
std::shared_ptr<Font> font = std::make_shared<Font>();
font->SetTypeface(JsTypeface::LoadZhCnTypeface());
JsFont *jsFont = new(std::nothrow) JsFont(font);
if (!jsFont) {
ROSEN_LOGE("Failed to create JsFont");
return nullptr;
}
status = napi_wrap(env, jsThis, jsFont,
JsFont::Destructor, nullptr, nullptr);
@ -175,6 +185,12 @@ napi_value JsFont::GetMetrics(napi_env env, napi_callback_info info)
return (me != nullptr) ? me->OnGetMetrics(env, info) : nullptr;
}
napi_value JsFont::MeasureSingleCharacter(napi_env env, napi_callback_info info)
{
JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
return (me != nullptr) ? me->OnMeasureSingleCharacter(env, info) : nullptr;
}
napi_value JsFont::MeasureText(napi_env env, napi_callback_info info)
{
JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
@ -193,6 +209,24 @@ napi_value JsFont::SetSkewX(napi_env env, napi_callback_info info)
return (me != nullptr) ? me->OnSetSkewX(env, info) : nullptr;
}
napi_value JsFont::SetEdging(napi_env env, napi_callback_info info)
{
JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
return (me != nullptr) ? me->OnSetEdging(env, info) : nullptr;
}
napi_value JsFont::SetHinting(napi_env env, napi_callback_info info)
{
JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
return (me != nullptr) ? me->OnSetHinting(env, info) : nullptr;
}
napi_value JsFont::CountText(napi_env env, napi_callback_info info)
{
JsFont* me = CheckParamsAndGetThis<JsFont>(env, info);
return (me != nullptr) ? me->OnCountText(env, info) : nullptr;
}
napi_value JsFont::OnEnableSubpixel(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
@ -311,6 +345,39 @@ napi_value JsFont::OnGetTypeface(napi_env env, napi_callback_info info)
return JsTypeface::CreateJsTypeface(env, typeface);
}
napi_value JsFont::OnMeasureSingleCharacter(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
ROSEN_LOGE("JsFont::OnMeasureSingleCharacter font is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
size_t len = 0;
if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], nullptr, 0, &len) != napi_ok) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
}
if (len == 0 || len > 4) { // 4 is the maximum length of a character encoded in UTF8.
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. Input parameter0 should be single character.");
}
char str[len + 1];
if (napi_get_value_string_utf8(env, argv[ARGC_ZERO], str, len + 1, &len) != napi_ok) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
}
const char* currentStr = str;
int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
size_t byteLen = currentStr - str;
if (byteLen != len) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. Input parameter0 should be single character.");
}
return GetDoubleAndConvertToJsValue(env, m_font->MeasureSingleCharacter(unicode));
}
napi_value JsFont::OnMeasureText(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
@ -373,6 +440,60 @@ napi_value JsFont::OnSetSkewX(napi_env env, napi_callback_info info)
return nullptr;
}
napi_value JsFont::OnSetEdging(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
ROSEN_LOGE("JsFont::OnSetEdging font is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
int32_t fontEdging = 0;
GET_ENUM_PARAM(ARGC_ZERO, fontEdging, 0, static_cast<int32_t>(FontEdging::SUBPIXEL_ANTI_ALIAS));
JS_CALL_DRAWING_FUNC(m_font->SetEdging(static_cast<FontEdging>(fontEdging)));
return nullptr;
}
napi_value JsFont::OnSetHinting(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
ROSEN_LOGE("JsFont::OnSetHinting font is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
int32_t fontHinting = 0;
GET_ENUM_PARAM(ARGC_ZERO, fontHinting, 0, static_cast<int32_t>(FontHinting::FULL));
JS_CALL_DRAWING_FUNC(m_font->SetHinting(static_cast<FontHinting>(fontHinting)));
return nullptr;
}
napi_value JsFont::OnCountText(napi_env env, napi_callback_info info)
{
if (m_font == nullptr) {
ROSEN_LOGE("JsFont::OnCountText font is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
std::string text = "";
if (!ConvertFromJsValue(env, argv[ARGC_ZERO], text)) {
ROSEN_LOGE("JsFont::OnCountText Argv[ARGC_ZERO] is invalid");
return nullptr;
}
double textSize = m_font->CountText(text.c_str(), text.length(), TextEncoding::UTF8);
return GetDoubleAndConvertToJsValue(env, textSize);
}
std::shared_ptr<Font> JsFont::GetFont()
{
return m_font;

View File

@ -43,9 +43,13 @@ public:
static napi_value GetTypeface(napi_env env, napi_callback_info info);
static napi_value GetSize(napi_env env, napi_callback_info info);
static napi_value GetMetrics(napi_env env, napi_callback_info info);
static napi_value MeasureSingleCharacter(napi_env env, napi_callback_info info);
static napi_value MeasureText(napi_env env, napi_callback_info info);
static napi_value SetScaleX(napi_env env, napi_callback_info info);
static napi_value SetSkewX(napi_env env, napi_callback_info info);
static napi_value SetEdging(napi_env env, napi_callback_info info);
static napi_value SetHinting(napi_env env, napi_callback_info info);
static napi_value CountText(napi_env env, napi_callback_info info);
std::shared_ptr<Font> GetFont();
void SetFont(std::shared_ptr<Font> font);
@ -59,9 +63,13 @@ private:
napi_value OnGetTypeface(napi_env env, napi_callback_info info);
napi_value OnGetSize(napi_env env, napi_callback_info info);
napi_value OnGetMetrics(napi_env env, napi_callback_info info);
napi_value OnMeasureSingleCharacter(napi_env env, napi_callback_info info);
napi_value OnMeasureText(napi_env env, napi_callback_info info);
napi_value OnSetScaleX(napi_env env, napi_callback_info info);
napi_value OnSetSkewX(napi_env env, napi_callback_info info);
napi_value OnSetEdging(napi_env env, napi_callback_info info);
napi_value OnSetHinting(napi_env env, napi_callback_info info);
napi_value OnCountText(napi_env env, napi_callback_info info);
static thread_local napi_ref constructor_;
std::shared_ptr<Font> m_font = nullptr;

View File

@ -21,11 +21,13 @@
#include "enum_napi/js_enum.h"
#include "font_napi/js_font.h"
#include "font_napi/js_typeface.h"
#include "lattice_napi/js_lattice.h"
#include "mask_filter_napi/js_mask_filter.h"
#include "path_effect_napi/js_path_effect.h"
#include "path_napi/js_path.h"
#include "pen_napi/js_pen.h"
#include "region_napi/js_region.h"
#include "roundRect_napi/js_roundrect.h"
#include "sampling_options_napi/js_sampling_options.h"
#include "shadow_layer_napi/js_shadow_layer.h"
#include "text_blob_napi/js_text_blob.h"
@ -46,8 +48,10 @@ napi_value DrawingInit(napi_env env, napi_value exportObj)
JsBrush::Init(env, exportObj);
JsSamplingOptions::Init(env, exportObj);
JsMaskFilter::Init(env, exportObj);
JsLattice::Init(env, exportObj);
JsPathEffect::Init(env, exportObj);
JsRegion::Init(env, exportObj);
JsRoundRect::Init(env, exportObj);
JsShadowLayer::Init(env, exportObj);
JsMatrix::Init(env, exportObj);
return exportObj;

View File

@ -115,6 +115,19 @@ bool ConvertFromJsRect(napi_env env, napi_value jsValue, double* ltrb, size_t si
return true;
}
bool ConvertFromJsIRect(napi_env env, napi_value jsValue, int32_t* ltrb, size_t size)
{
napi_value tempValue = nullptr;
for (size_t idx = 0; idx < size; idx++) {
int32_t* curEdge = ltrb + idx;
napi_get_named_property(env, jsValue, g_ltrbString[idx], &tempValue);
if (napi_get_value_int32(env, tempValue, curEdge) != napi_ok) {
return false;
}
}
return true;
}
napi_value GetFontMetricsAndConvertToJsValue(napi_env env, FontMetrics* metrics)
{
napi_value objValue = nullptr;

View File

@ -165,6 +165,8 @@ constexpr size_t ARGC_FOUR = 4;
constexpr size_t ARGC_FIVE = 5;
constexpr size_t ARGC_SIX = 6;
constexpr size_t ARGC_SEVEN = 7;
constexpr size_t ARGC_EIGHT = 8;
constexpr size_t ARGC_NINE = 9;
constexpr int NUMBER_TWO = 2;
enum class DrawingErrorCode : int32_t {
@ -330,6 +332,8 @@ bool ConvertFromJsColor(napi_env env, napi_value jsValue, int32_t* argb, size_t
bool ConvertFromJsRect(napi_env env, napi_value jsValue, double* ltrb, size_t size);
bool ConvertFromJsIRect(napi_env env, napi_value jsValue, int32_t* ltrb, size_t size);
inline bool ConvertFromJsNumber(napi_env env, napi_value jsValue, int32_t& value, int32_t lo, int32_t hi)
{
return napi_get_value_int32(env, jsValue, &value) == napi_ok && value >= lo && value <= hi;

View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 2024 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 "js_lattice.h"
#include "js_drawing_utils.h"
#include "native_value.h"
namespace OHOS::Rosen {
namespace Drawing {
const std::string CLASS_NAME = "Lattice";
thread_local napi_ref JsLattice::constructor_ = nullptr;
napi_value JsLattice::Init(napi_env env, napi_value exportObj)
{
napi_property_descriptor properties[] = {
DECLARE_NAPI_STATIC_FUNCTION("createImageLattice", JsLattice::CreateImageLattice),
};
napi_value constructor = nullptr;
napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
sizeof(properties) / sizeof(properties[0]), properties, &constructor);
if (status != napi_ok) {
ROSEN_LOGE("JsLattice::Init failed to define lattice class");
return nullptr;
}
status = napi_create_reference(env, constructor, 1, &constructor_);
if (status != napi_ok) {
ROSEN_LOGE("JsLattice::Init failed to create reference of constructor");
return nullptr;
}
status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
if (status != napi_ok) {
ROSEN_LOGE("JsLattice::Init failed to set constructor");
return nullptr;
}
status = napi_define_properties(env, exportObj, sizeof(properties) / sizeof(properties[0]), properties);
if (status != napi_ok) {
ROSEN_LOGE("JsLattice::Init failed to define static function");
return nullptr;
}
return exportObj;
}
void JsLattice::Finalizer(napi_env env, void* data, void* hint)
{
std::unique_ptr<JsLattice>(static_cast<JsLattice*>(data));
}
JsLattice::~JsLattice()
{
if (m_lattice != nullptr) {
if (m_lattice->fXDivs != nullptr) {
delete[] m_lattice->fXDivs;
}
if (m_lattice->fXDivs != nullptr) {
delete[] m_lattice->fYDivs;
}
if (m_lattice->fRectTypes != nullptr) {
delete[] m_lattice->fRectTypes;
}
if (m_lattice->fColors != nullptr) {
delete[] m_lattice->fColors;
}
m_lattice = nullptr;
}
}
napi_value JsLattice::Constructor(napi_env env, napi_callback_info info)
{
size_t argCount = 0;
napi_value jsThis = nullptr;
napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
if (status != napi_ok) {
ROSEN_LOGE("JsLattice::Constructor failed to napi_get_cb_info");
return nullptr;
}
JsLattice *jsLattice = new(std::nothrow) JsLattice();
if (jsLattice == nullptr) {
return nullptr;
}
status = napi_wrap(env, jsThis, jsLattice, JsLattice::Destructor, nullptr, nullptr);
if (status != napi_ok) {
delete jsLattice;
ROSEN_LOGE("JsLattice::Constructor failed to wrap native instance");
return nullptr;
}
return jsThis;
}
void JsLattice::Destructor(napi_env env, void *nativeObject, void *finalize)
{
(void)finalize;
if (nativeObject != nullptr) {
JsLattice *napi = reinterpret_cast<JsLattice *>(nativeObject);
delete napi;
}
}
bool GetLatticeDividers(napi_env env, napi_value dividersArray, uint32_t count, int** dividers)
{
uint32_t dividersSize = 0;
napi_get_array_length(env, dividersArray, &dividersSize);
if (dividersSize != count || dividersSize > 5) { // 5: max value
ROSEN_LOGE("JsLattice::CreateImageLattice dividers are invalid");
return false;
}
if (dividersSize != 0) {
auto divs = new int[dividersSize];
for (uint32_t i = 0; i < dividersSize; i++) {
napi_value tempDiv = nullptr;
napi_get_element(env, dividersArray, i, &tempDiv);
int div = 0;
if (napi_get_value_int32(env, tempDiv, &div) != napi_ok) {
ROSEN_LOGE("JsLattice::CreateImageLattice divider is invalid");
delete []divs;
return false;
}
divs[i] = div;
}
*dividers = divs;
}
return true;
}
bool GetLatticeRectTypes(napi_env env, napi_value rectTypesArray, uint32_t count,
Lattice::RectType** latticeRectTypes)
{
uint32_t rectTypesSize = 0;
napi_get_array_length(env, rectTypesArray, &rectTypesSize);
if ((rectTypesSize != 0 && rectTypesSize != count) || rectTypesSize > 36) { // 36: max value
ROSEN_LOGE("JsLattice::CreateImageLattice rectTypes are invalid");
return false;
}
if (rectTypesSize != 0) {
auto rectTypes = new Lattice::RectType[rectTypesSize];
for (uint32_t i = 0; i < rectTypesSize; i++) {
napi_value tempType = nullptr;
napi_get_element(env, rectTypesArray, i, &tempType);
int rectType = 0;
if (napi_get_value_int32(env, tempType, &rectType) != napi_ok ||
rectType < 0 || rectType > 2) { // 2: FIXEDCOLOR
ROSEN_LOGE("JsLattice::CreateImageLattice rectType is invalid");
delete []rectTypes;
return false;
}
rectTypes[i] = static_cast<Lattice::RectType>(rectType);
}
*latticeRectTypes = rectTypes;
}
return true;
}
bool GetLatticeColors(napi_env env, napi_value colorsArray, uint32_t count, Color** latticeColors)
{
uint32_t colorsSize = 0;
napi_get_array_length(env, colorsArray, &colorsSize);
if ((colorsSize != 0 && colorsSize != count) || colorsSize > 36) { // 36: max value
ROSEN_LOGE("JsLattice::CreateImageLattice colors are invalid");
return false;
}
if (colorsSize != 0) {
auto colors = new Color[colorsSize];
for (uint32_t i = 0; i < colorsSize; i++) {
napi_value tempColor = nullptr;
napi_get_element(env, colorsArray, i, &tempColor);
Drawing::Color drawingColor;
int32_t argb[ARGC_FOUR] = {0};
if (!ConvertFromJsColor(env, tempColor, argb, ARGC_FOUR)) {
ROSEN_LOGE("JsLattice::CreateImageLattice colors is invalid");
delete []colors;
return false;
}
drawingColor = Color::ColorQuadSetARGB(
argb[ARGC_ZERO], argb[ARGC_ONE], argb[ARGC_TWO], argb[ARGC_THREE]);
colors[i] = drawingColor;
}
*latticeColors = colors;
}
return true;
}
napi_value JsLattice::CreateImageLattice(napi_env env, napi_callback_info info)
{
size_t argc = ARGC_SEVEN;
napi_value argv[ARGC_SEVEN] = {nullptr};
CHECK_PARAM_NUMBER_WITH_OPTIONAL_PARAMS(argv, argc, ARGC_FOUR, ARGC_SEVEN);
uint32_t xCount = 0;
GET_UINT32_PARAM(ARGC_TWO, xCount);
uint32_t yCount = 0;
GET_UINT32_PARAM(ARGC_THREE, yCount);
int* xDividers = nullptr;
if (!GetLatticeDividers(env, argv[ARGC_ZERO], xCount, &xDividers)) {
ROSEN_LOGE("JsLattice::CreateImageLattice xDividers are invalid");
delete xDividers;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter0 type.");
}
int* yDividers = nullptr;
if (!GetLatticeDividers(env, argv[ARGC_ONE], yCount, &yDividers)) {
ROSEN_LOGE("JsLattice::CreateImageLattice yDividers are invalid");
delete xDividers;
delete yDividers;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter1 type.");
}
Lattice lat;
lat.fXDivs = xDividers;
lat.fYDivs = yDividers;
lat.fXCount = xCount;
lat.fYCount = yCount;
lat.fBounds = nullptr;
lat.fRectTypes = nullptr;
lat.fColors = nullptr;
if (argc >= ARGC_FIVE) {
napi_valuetype valueType = napi_undefined;
if (napi_typeof(env, argv[ARGC_FOUR], &valueType) != napi_ok ||
(valueType != napi_null && valueType != napi_object)) {
delete xDividers;
delete yDividers;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect CreateImageLattice parameter5 type.");
}
int32_t ltrb[ARGC_FOUR] = {0};
if (valueType == napi_object) {
if (!ConvertFromJsIRect(env, argv[ARGC_FOUR], ltrb, ARGC_FOUR)) {
delete xDividers;
delete yDividers;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter5 type. The type of left, top, right and bottom must be number.");
}
lat.fBounds = new Drawing::RectI(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
}
}
if (argc >= ARGC_SIX) {
int count = (xCount + 1) * (yCount + 1); // 1: grid size need + 1
Lattice::RectType* latticeRectTypes = nullptr;
if (!GetLatticeRectTypes(env, argv[ARGC_FIVE], count, &latticeRectTypes)) {
delete xDividers;
delete yDividers;
delete latticeRectTypes;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter6 type.");
}
lat.fRectTypes = latticeRectTypes;
if (argc == ARGC_SEVEN) {
Color* latticeColors = nullptr;
if (!GetLatticeColors(env, argv[ARGC_SIX], count, &latticeColors)) {
delete xDividers;
delete yDividers;
delete latticeRectTypes;
delete latticeColors;
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Incorrect parameter7 type.");
}
lat.fColors = latticeColors;
}
}
return JsLattice::Create(env, std::make_shared<Lattice>(lat));
}
napi_value JsLattice::Create(napi_env env, std::shared_ptr<Lattice> lattice)
{
napi_value objValue = nullptr;
napi_create_object(env, &objValue);
if (objValue == nullptr || lattice == nullptr) {
ROSEN_LOGE("JsLattice::Create object is null!");
return nullptr;
}
std::unique_ptr<JsLattice> jsLattice = std::make_unique<JsLattice>(lattice);
napi_wrap(env, objValue, jsLattice.release(), JsLattice::Finalizer, nullptr, nullptr);
if (objValue == nullptr) {
ROSEN_LOGE("JsLattice::Create object value is null!");
return nullptr;
}
return objValue;
}
std::shared_ptr<Lattice> JsLattice::GetLattice()
{
return m_lattice;
}
} // namespace Drawing
} // namespace OHOS::Rosen

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ROSEN_JS_LATTICE_H
#define OHOS_ROSEN_JS_LATTICE_H
#include <native_engine/native_engine.h>
#include <native_engine/native_value.h>
#include "draw/core_canvas.h"
namespace OHOS::Rosen {
namespace Drawing {
class JsLattice final {
public:
explicit JsLattice(std::shared_ptr<Lattice> lattice = nullptr) : m_lattice(lattice) {}
~JsLattice();
static napi_value Init(napi_env env, napi_value exportObj);
static void Finalizer(napi_env env, void* data, void* hint);
static napi_value Constructor(napi_env env, napi_callback_info info);
static void Destructor(napi_env env, void *nativeObject, void *finalize);
static napi_value CreateImageLattice(napi_env env, napi_callback_info info);
std::shared_ptr<Lattice> GetLattice();
private:
static napi_value Create(napi_env env, std::shared_ptr<Lattice> lattice);
std::shared_ptr<Lattice> m_lattice = nullptr;
static thread_local napi_ref constructor_;
};
} // namespace Drawing
} // namespace OHOS::Rosen
#endif // OHOS_ROSEN_JS_LATTICE_H

View File

@ -103,7 +103,7 @@ napi_value JsMaskFilter::CreateBlurMaskFilter(napi_env env, napi_callback_info i
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
int32_t blurType = 0;
GET_INT32_CHECK_GE_ZERO_PARAM(ARGC_ZERO, blurType);
GET_ENUM_PARAM(ARGC_ZERO, blurType, 0, static_cast<int32_t>(BlurType::INNER));
double sigma = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, sigma);

View File

@ -27,6 +27,14 @@ napi_value JsMatrix::Init(napi_env env, napi_value exportObj)
DECLARE_NAPI_FUNCTION("preRotate", JsMatrix::PreRotate),
DECLARE_NAPI_FUNCTION("preScale", JsMatrix::PreScale),
DECLARE_NAPI_FUNCTION("preTranslate", JsMatrix::PreTranslate),
DECLARE_NAPI_FUNCTION("setRotate", JsMatrix::SetRotate),
DECLARE_NAPI_FUNCTION("setScale", JsMatrix::SetScale),
DECLARE_NAPI_FUNCTION("setTranslate", JsMatrix::SetTranslate),
DECLARE_NAPI_FUNCTION("setMatrix", JsMatrix::SetMatrix),
DECLARE_NAPI_FUNCTION("preConcat", JsMatrix::PreConcat),
DECLARE_NAPI_FUNCTION("matrixIsEqual", JsMatrix::MatrixIsEqual),
DECLARE_NAPI_FUNCTION("invert", JsMatrix::Invert),
DECLARE_NAPI_FUNCTION("isIdentity", JsMatrix::IsIdentity),
};
napi_value constructor = nullptr;
@ -110,7 +118,6 @@ napi_value JsMatrix::OnPreRotate(napi_env env, napi_callback_info info)
GET_DOUBLE_PARAM(ARGC_TWO, py);
JS_CALL_DRAWING_FUNC(m_matrix->PreRotate(degree, px, py));
return nullptr;
}
@ -140,7 +147,6 @@ napi_value JsMatrix::OnPreScale(napi_env env, napi_callback_info info)
GET_DOUBLE_PARAM(ARGC_THREE, py);
JS_CALL_DRAWING_FUNC(m_matrix->PreScale(sx, sy, px, py));
return nullptr;
}
@ -166,10 +172,227 @@ napi_value JsMatrix::OnPreTranslate(napi_env env, napi_callback_info info)
GET_DOUBLE_PARAM(ARGC_ONE, dy);
JS_CALL_DRAWING_FUNC(m_matrix->PreTranslate(dx, dy));
return nullptr;
}
napi_value JsMatrix::SetRotate(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnSetRotate(env, info) : nullptr;
}
napi_value JsMatrix::OnSetRotate(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnSetRotate matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_THREE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
double degree = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, degree);
double px = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, px);
double py = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, py);
JS_CALL_DRAWING_FUNC(m_matrix->Rotate(degree, px, py));
return nullptr;
}
napi_value JsMatrix::SetScale(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnSetScale(env, info) : nullptr;
}
napi_value JsMatrix::OnSetScale(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnSetScale matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_FOUR] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
double sx = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, sx);
double sy = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, sy);
double px = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, px);
double py = 0.0;
GET_DOUBLE_PARAM(ARGC_THREE, py);
JS_CALL_DRAWING_FUNC(m_matrix->Scale(sx, sy, px, py));
return nullptr;
}
napi_value JsMatrix::SetTranslate(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnSetTranslate(env, info) : nullptr;
}
napi_value JsMatrix::OnSetTranslate(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnSetTranslate matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
double dx = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, dx);
double dy = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, dy);
JS_CALL_DRAWING_FUNC(m_matrix->Translate(dx, dy));
return nullptr;
}
napi_value JsMatrix::SetMatrix(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnSetMatrix(env, info) : nullptr;
}
napi_value JsMatrix::OnSetMatrix(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnSetMatrix matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_NINE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_NINE);
double scaleX = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, scaleX);
double skewX = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, skewX);
double transX = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, transX);
double skewY = 0.0;
GET_DOUBLE_PARAM(ARGC_THREE, skewY);
double scaleY = 0.0;
GET_DOUBLE_PARAM(ARGC_FOUR, scaleY);
double transY = 0.0;
GET_DOUBLE_PARAM(ARGC_FIVE, transY);
double persp0 = 0.0;
GET_DOUBLE_PARAM(ARGC_SIX, persp0);
double persp1 = 0.0;
GET_DOUBLE_PARAM(ARGC_SEVEN, persp1);
double persp2 = 0.0;
GET_DOUBLE_PARAM(ARGC_EIGHT, persp2);
m_matrix->SetMatrix(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2);
return nullptr;
}
napi_value JsMatrix::PreConcat(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnPreConcat(env, info) : nullptr;
}
napi_value JsMatrix::OnPreConcat(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnPreConcat matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsMatrix::OnPreConcat matrix is nullptr");
return nullptr;
}
m_matrix->PreConcat(*jsMatrix->GetMatrix());
return nullptr;
}
napi_value JsMatrix::MatrixIsEqual(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnMatrixIsEqual(env, info) : nullptr;
}
napi_value JsMatrix::OnMatrixIsEqual(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnMatrixIsEqual matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsMatrix::OnMatrixIsEqual matrix is nullptr");
return CreateJsValue(env, false);
}
return CreateJsValue(env, m_matrix->operator == (*jsMatrix->GetMatrix()));
}
napi_value JsMatrix::Invert(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnInvert(env, info) : nullptr;
}
napi_value JsMatrix::OnInvert(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnInvert matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsMatrix::OnPreConcat matrix is nullptr");
return nullptr;
}
return CreateJsValue(env, m_matrix->Invert(*jsMatrix->GetMatrix()));
}
napi_value JsMatrix::IsIdentity(napi_env env, napi_callback_info info)
{
JsMatrix* me = CheckParamsAndGetThis<JsMatrix>(env, info);
return (me != nullptr) ? me->OnIsIdentity(env, info) : nullptr;
}
napi_value JsMatrix::OnIsIdentity(napi_env env, napi_callback_info info)
{
if (m_matrix == nullptr) {
ROSEN_LOGE("JsMatrix::OnIsIdentity matrix is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
return CreateJsValue(env, m_matrix->IsIdentity());
}
JsMatrix::~JsMatrix()
{
m_matrix = nullptr;

View File

@ -35,6 +35,14 @@ public:
static napi_value PreRotate(napi_env env, napi_callback_info info);
static napi_value PreScale(napi_env env, napi_callback_info info);
static napi_value PreTranslate(napi_env env, napi_callback_info info);
static napi_value SetRotate(napi_env env, napi_callback_info info);
static napi_value SetScale(napi_env env, napi_callback_info info);
static napi_value SetTranslate(napi_env env, napi_callback_info info);
static napi_value PreConcat(napi_env env, napi_callback_info info);
static napi_value MatrixIsEqual(napi_env env, napi_callback_info info);
static napi_value Invert(napi_env env, napi_callback_info info);
static napi_value IsIdentity(napi_env env, napi_callback_info info);
static napi_value SetMatrix(napi_env env, napi_callback_info info);
std::shared_ptr<Matrix> GetMatrix();
private:
@ -42,6 +50,14 @@ private:
napi_value OnPreRotate(napi_env env, napi_callback_info info);
napi_value OnPreScale(napi_env env, napi_callback_info info);
napi_value OnPreTranslate(napi_env env, napi_callback_info info);
napi_value OnSetRotate(napi_env env, napi_callback_info info);
napi_value OnSetScale(napi_env env, napi_callback_info info);
napi_value OnSetTranslate(napi_env env, napi_callback_info info);
napi_value OnPreConcat(napi_env env, napi_callback_info info);
napi_value OnMatrixIsEqual(napi_env env, napi_callback_info info);
napi_value OnInvert(napi_env env, napi_callback_info info);
napi_value OnIsIdentity(napi_env env, napi_callback_info info);
napi_value OnSetMatrix(napi_env env, napi_callback_info info);
static thread_local napi_ref constructor_;
std::shared_ptr<Matrix> m_matrix = nullptr;

View File

@ -105,10 +105,10 @@ napi_value JsPathEffect::CreateDashPathEffect(napi_env env, napi_callback_info i
uint32_t arrayLength = 0;
if ((napi_get_array_length(env, argv[ARGC_ZERO], &arrayLength) != napi_ok)) {
ROSEN_LOGE("JsPathEffect::CreateDashPathEffect count of intervals is not even : %{public}u", arrayLength);
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid array length params.");
}
if (arrayLength % NUMBER_TWO || arrayLength < NUMBER_TWO) { // arrayLength must be an even number greater than 0
ROSEN_LOGE("JsPathEffect::CreateDashPathEffect count of intervals is not even : %{public}u", arrayLength);
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"parameter array length verification failed.");
}

View File

@ -18,6 +18,8 @@
#include "native_value.h"
#include "js_drawing_utils.h"
#include "matrix_napi/js_matrix.h"
#include "roundRect_napi/js_roundrect.h"
#include "matrix_napi/js_matrix.h"
@ -33,6 +35,16 @@ napi_value JsPath::Init(napi_env env, napi_value exportObj)
DECLARE_NAPI_FUNCTION("arcTo", JsPath::ArcTo),
DECLARE_NAPI_FUNCTION("quadTo", JsPath::QuadTo),
DECLARE_NAPI_FUNCTION("cubicTo", JsPath::CubicTo),
DECLARE_NAPI_FUNCTION("addOval", JsPath::AddOval),
DECLARE_NAPI_FUNCTION("addCircle", JsPath::AddCircle),
DECLARE_NAPI_FUNCTION("addArc", JsPath::AddArc),
DECLARE_NAPI_FUNCTION("addRect", JsPath::AddRect),
DECLARE_NAPI_FUNCTION("addRoundRect", JsPath::AddRoundRect),
DECLARE_NAPI_FUNCTION("addPath", JsPath::AddPath),
DECLARE_NAPI_FUNCTION("transform", JsPath::Transform),
DECLARE_NAPI_FUNCTION("contains", JsPath::Contains),
DECLARE_NAPI_FUNCTION("setFillType", JsPath::SetFillType),
DECLARE_NAPI_FUNCTION("getBounds", JsPath::GetBounds),
DECLARE_NAPI_FUNCTION("close", JsPath::Close),
DECLARE_NAPI_FUNCTION("reset", JsPath::Reset),
DECLARE_NAPI_FUNCTION("getLength", JsPath::GetLength),
@ -138,6 +150,66 @@ napi_value JsPath::CubicTo(napi_env env, napi_callback_info info)
return (me != nullptr) ? me->OnCubicTo(env, info) : nullptr;
}
napi_value JsPath::AddOval(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddOval(env, info) : nullptr;
}
napi_value JsPath::AddCircle(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddCircle(env, info) : nullptr;
}
napi_value JsPath::AddArc(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddArc(env, info) : nullptr;
}
napi_value JsPath::AddRect(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddRect(env, info) : nullptr;
}
napi_value JsPath::AddRoundRect(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddRoundRect(env, info) : nullptr;
}
napi_value JsPath::AddPath(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnAddPath(env, info) : nullptr;
}
napi_value JsPath::Transform(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnTransform(env, info) : nullptr;
}
napi_value JsPath::Contains(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnContains(env, info) : nullptr;
}
napi_value JsPath::SetFillType(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnSetFillType(env, info) : nullptr;
}
napi_value JsPath::GetBounds(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnGetBounds(env, info) : nullptr;
}
napi_value JsPath::Close(napi_env env, napi_callback_info info)
{
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
@ -152,7 +224,6 @@ napi_value JsPath::Reset(napi_env env, napi_callback_info info)
napi_value JsPath::GetLength(napi_env env, napi_callback_info info)
{
ROSEN_LOGE("liyan JsPath::GetLength");
JsPath* me = CheckParamsAndGetThis<JsPath>(env, info);
return (me != nullptr) ? me->OnGetLength(env, info) : nullptr;
}
@ -318,18 +389,11 @@ napi_value JsPath::OnGetLength(napi_env env, napi_callback_info info)
ROSEN_LOGE("JsPath::OnGetLength path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
size_t argc = ARGC_ONE;
napi_value argv[ARGC_ONE] = { nullptr };
napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
if (status != napi_ok || argc < ARGC_ONE) {
ROSEN_LOGE("JsPath::OnGetLength Argc is invalid: %{public}zu", argc);
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
bool forceClosed = false;
if (!(ConvertFromJsValue(env, argv[0], forceClosed))) {
ROSEN_LOGE("JsPath::OnGetLength Argv is invalid");
return NapiGetUndefined(env);
}
GET_BOOLEAN_PARAM(ARGC_ZERO, forceClosed);
double len = m_path->GetLength(forceClosed);
return CreateJsNumber(env, len);
}
@ -431,6 +495,230 @@ napi_value JsPath::OnBuildFromSVGString(napi_env env, napi_callback_info info)
return CreateJsNumber(env, result);
}
napi_value JsPath::OnAddOval(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddOval path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_THREE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
Drawing::Rect drawingRect;
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
uint32_t start = 0;
GET_UINT32_PARAM(ARGC_ONE, start);
int32_t jsDirection = 0;
GET_ENUM_PARAM(ARGC_TWO, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
JS_CALL_DRAWING_FUNC(m_path->AddOval(drawingRect, start, static_cast<PathDirection>(jsDirection)));
return nullptr;
}
napi_value JsPath::OnAddCircle(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddCircle path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_FOUR] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_FOUR);
double px1 = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, px1);
double py1 = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, py1);
double radius = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, radius);
int32_t jsDirection = 0;
GET_ENUM_PARAM(ARGC_THREE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
JS_CALL_DRAWING_FUNC(m_path->AddCircle(px1, py1, radius, static_cast<PathDirection>(jsDirection)));
return nullptr;
}
napi_value JsPath::OnAddArc(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddArc path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_THREE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
Drawing::Rect drawingRect;
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
double startDeg = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, startDeg);
double sweepDeg = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, sweepDeg);
JS_CALL_DRAWING_FUNC(m_path->AddArc(drawingRect, startDeg, sweepDeg));
return nullptr;
}
napi_value JsPath::OnAddRect(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddRect path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
Drawing::Rect drawingRect;
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
int32_t jsDirection = 0;
GET_ENUM_PARAM(ARGC_ONE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
JS_CALL_DRAWING_FUNC(m_path->AddRect(drawingRect, static_cast<PathDirection>(jsDirection)));
return nullptr;
}
napi_value JsPath::OnAddRoundRect(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddRoundRect path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
JsRoundRect* jsRoundRect = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsRoundRect);
int32_t jsDirection = 0;
GET_ENUM_PARAM(ARGC_ONE, jsDirection, 0, static_cast<int32_t>(PathDirection::CCW_DIRECTION));
JS_CALL_DRAWING_FUNC(m_path->AddRoundRect(jsRoundRect->GetRoundRect(), static_cast<PathDirection>(jsDirection)));
return nullptr;
}
napi_value JsPath::OnAddPath(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnAddPath path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
JsPath* jsPath = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsPath);
if (jsPath->GetPath() == nullptr) {
ROSEN_LOGE("JsPath::OnAddPath path is nullptr");
return nullptr;
}
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ONE, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsPath::OnAddPath Matrix is nullptr");
return nullptr;
}
JS_CALL_DRAWING_FUNC(m_path->AddPath(*jsPath->GetPath(), *jsMatrix->GetMatrix()));
return nullptr;
}
napi_value JsPath::OnTransform(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnTransform path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
JsMatrix* jsMatrix = nullptr;
GET_UNWRAP_PARAM(ARGC_ZERO, jsMatrix);
if (jsMatrix->GetMatrix() == nullptr) {
ROSEN_LOGE("JsPath::OnAddPath Matrix is nullptr");
return nullptr;
}
JS_CALL_DRAWING_FUNC(m_path->Transform(*jsMatrix->GetMatrix()));
return nullptr;
}
napi_value JsPath::OnContains(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnContains path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_TWO] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_TWO);
double x = 0.0;
GET_DOUBLE_PARAM(ARGC_ZERO, x);
double y = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, y);
return CreateJsValue(env, m_path->Contains(x, y));
}
napi_value JsPath::OnSetFillType(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnSetFillType path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
napi_value argv[ARGC_ONE] = {nullptr};
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_ONE);
int32_t jsFillType = 0;
GET_ENUM_PARAM(ARGC_ZERO, jsFillType, 0, static_cast<int32_t>(PathFillType::INVERSE_EVENTODD));
JS_CALL_DRAWING_FUNC(m_path->SetFillStyle(static_cast<PathFillType>(jsFillType)));
return nullptr;
}
napi_value JsPath::OnGetBounds(napi_env env, napi_callback_info info)
{
if (m_path == nullptr) {
ROSEN_LOGE("JsPath::OnGetBounds path is nullptr");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
auto bounds = m_path->GetBounds();
std::shared_ptr<Rect> rect = std::make_shared<Rect>(bounds.GetLeft(),
bounds.GetTop(), bounds.GetRight(), bounds.GetBottom());
if (!rect) {
ROSEN_LOGE("JsPath::OnGetBounds return value is invalid");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
}
return GetRectAndConvertToJsValue(env, rect);
}
Path* JsPath::GetPath()
{
return m_path;

View File

@ -37,6 +37,16 @@ public:
static napi_value ArcTo(napi_env env, napi_callback_info info);
static napi_value QuadTo(napi_env env, napi_callback_info info);
static napi_value CubicTo(napi_env env, napi_callback_info info);
static napi_value AddOval(napi_env env, napi_callback_info info);
static napi_value AddCircle(napi_env env, napi_callback_info info);
static napi_value AddArc(napi_env env, napi_callback_info info);
static napi_value AddRect(napi_env env, napi_callback_info info);
static napi_value AddRoundRect(napi_env env, napi_callback_info info);
static napi_value AddPath(napi_env env, napi_callback_info info);
static napi_value Transform(napi_env env, napi_callback_info info);
static napi_value Contains(napi_env env, napi_callback_info info);
static napi_value SetFillType(napi_env env, napi_callback_info info);
static napi_value GetBounds(napi_env env, napi_callback_info info);
static napi_value Close(napi_env env, napi_callback_info info);
static napi_value Reset(napi_env env, napi_callback_info info);
static napi_value GetLength(napi_env env, napi_callback_info info);
@ -51,6 +61,16 @@ private:
napi_value OnArcTo(napi_env env, napi_callback_info info);
napi_value OnQuadTo(napi_env env, napi_callback_info info);
napi_value OnCubicTo(napi_env env, napi_callback_info info);
napi_value OnAddOval(napi_env env, napi_callback_info info);
napi_value OnAddCircle(napi_env env, napi_callback_info info);
napi_value OnAddArc(napi_env env, napi_callback_info info);
napi_value OnAddRect(napi_env env, napi_callback_info info);
napi_value OnAddRoundRect(napi_env env, napi_callback_info info);
napi_value OnAddPath(napi_env env, napi_callback_info info);
napi_value OnTransform(napi_env env, napi_callback_info info);
napi_value OnContains(napi_env env, napi_callback_info info);
napi_value OnSetFillType(napi_env env, napi_callback_info info);
napi_value OnGetBounds(napi_env env, napi_callback_info info);
napi_value OnClose(napi_env env, napi_callback_info info);
napi_value OnReset(napi_env env, napi_callback_info info);
napi_value OnGetLength(napi_env env, napi_callback_info info);

View File

@ -220,7 +220,8 @@ napi_value JsPen::SetAlpha(napi_env env, napi_callback_info info)
int32_t alpha = 0;
if (!ConvertFromJsNumber(env, argv[ARGC_ZERO], alpha, 0, Color::RGB_MAX)) {
ROSEN_LOGE("JsPen::SetAlpha Argv[0] is invalid");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Parameter verification failed. The alpha range must be [0, 255].");
}
pen->SetAlpha(alpha);

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2024 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 "js_roundrect.h"
#include "../js_drawing_utils.h"
#include "native_value.h"
#include "../js_common.h"
namespace OHOS::Rosen {
namespace Drawing {
thread_local napi_ref JsRoundRect::constructor_ = nullptr;
const std::string CLASS_NAME = "RoundRect";
napi_value JsRoundRect::Init(napi_env env, napi_value exportObj)
{
napi_property_descriptor properties[] = {
};
napi_value constructor = nullptr;
napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
sizeof(properties) / sizeof(properties[0]), properties, &constructor);
if (status != napi_ok) {
ROSEN_LOGE("JsRoundRect::Init Failed to define RoundRect class");
return nullptr;
}
status = napi_create_reference(env, constructor, 1, &constructor_);
if (status != napi_ok) {
ROSEN_LOGE("JsRoundRect::Init Failed to create reference of constructor");
return nullptr;
}
status = napi_set_named_property(env, exportObj, CLASS_NAME.c_str(), constructor);
if (status != napi_ok) {
ROSEN_LOGE("JsRoundRect::Init Failed to set constructor");
return nullptr;
}
return exportObj;
}
napi_value JsRoundRect::Constructor(napi_env env, napi_callback_info info)
{
size_t argCount = ARGC_THREE;
napi_value jsThis = nullptr;
napi_value argv[ARGC_THREE] = {nullptr};
napi_status status = napi_get_cb_info(env, info, &argCount, argv, &jsThis, nullptr);
if (status != napi_ok) {
ROSEN_LOGE("JsRoundRect::Constructor failed to napi_get_cb_info");
return nullptr;
}
CHECK_PARAM_NUMBER_WITHOUT_OPTIONAL_PARAMS(argv, ARGC_THREE);
napi_valuetype valueType = napi_undefined;
if (argv[0] == nullptr || napi_typeof(env, argv[0], &valueType) != napi_ok || valueType != napi_object) {
ROSEN_LOGE("JsRoundRect::Constructor Argv[0] is invalid");
return NapiGetUndefined(env);
}
double ltrb[ARGC_FOUR] = {0};
if (!ConvertFromJsRect(env, argv[ARGC_ZERO], ltrb, ARGC_FOUR)) {
return NapiThrowError(env, DrawingErrorCode::ERROR_INVALID_PARAM,
"Incorrect parameter0 type. The type of left, top, right and bottom must be number.");
}
Drawing::Rect drawingRect = Drawing::Rect(ltrb[ARGC_ZERO], ltrb[ARGC_ONE], ltrb[ARGC_TWO], ltrb[ARGC_THREE]);
double xRad = 0.0;
GET_DOUBLE_PARAM(ARGC_ONE, xRad);
double yRad = 0.0;
GET_DOUBLE_PARAM(ARGC_TWO, yRad);
JsRoundRect* jsRoundRect = new(std::nothrow) JsRoundRect(drawingRect, xRad, yRad);
if (jsRoundRect == nullptr) {
ROSEN_LOGE("JsRoundRect::Constructor Failed");
return nullptr;
}
status = napi_wrap(env, jsThis, jsRoundRect,
JsRoundRect::Destructor, nullptr, nullptr);
if (status != napi_ok) {
delete jsRoundRect;
ROSEN_LOGE("JsRoundRect::Constructor Failed to wrap native instance");
return nullptr;
}
return jsThis;
}
void JsRoundRect::Destructor(napi_env env, void* nativeObject, void* finalize)
{
(void)finalize;
if (nativeObject != nullptr) {
JsRoundRect* napi = reinterpret_cast<JsRoundRect*>(nativeObject);
delete napi;
}
}
const RoundRect& JsRoundRect::GetRoundRect()
{
return m_roundRect;
}
} // namespace Drawing
} // namespace OHOS::Rosen

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ROSEN_JS_ROUNDRECT_H
#define OHOS_ROSEN_JS_ROUNDRECT_H
#include <memory>
#include <native_engine/native_engine.h>
#include <native_engine/native_value.h>
#include "utils/round_rect.h"
namespace OHOS::Rosen {
namespace Drawing {
class JsRoundRect final {
public:
explicit JsRoundRect(const Drawing::Rect& rect, float x, float y)
: m_roundRect(rect, x, y) {};
~JsRoundRect() {};
static napi_value Init(napi_env env, napi_value exportObj);
static napi_value Constructor(napi_env env, napi_callback_info info);
static void Destructor(napi_env env, void* nativeObject, void* finalize);
const RoundRect& GetRoundRect();
private:
static thread_local napi_ref constructor_;
RoundRect m_roundRect;
};
} // namespace Drawing
} // namespace OHOS::Rosen
#endif // OHOS_ROSEN_JS_ROUNDRECT_H

View File

@ -171,7 +171,7 @@ napi_value ColorPickerNapi::Constructor(napi_env env, napi_callback_info info)
IMG_JS_NO_ARGS(env, info, status, thisVar);
IMG_NAPI_CHECK_RET(IMG_IS_READY(status, thisVar), undefineVar);
ColorPickerNapi* pColorPickerNapi = new ColorPickerNapi();
ColorPickerNapi* pColorPickerNapi = new (std::nothrow) ColorPickerNapi();
IMG_NAPI_CHECK_RET(IMG_NOT_NULL(pColorPickerNapi), undefineVar);
@ -197,7 +197,8 @@ void ColorPickerNapi::Destructor(napi_env env, void* nativeObject, void* finaliz
ColorPickerNapi *pColorPickerNapi = reinterpret_cast<ColorPickerNapi*>(nativeObject);
if (IMG_NOT_NULL(pColorPickerNapi)) {
pColorPickerNapi->~ColorPickerNapi();
delete pColorPickerNapi;
nativeObject = nullptr;
}
}

View File

@ -53,7 +53,7 @@ struct FilterAsyncContext {
// param
FilterNapi* filterNapi = nullptr;
bool forceCPU = false;
bool forceCPU = true;
std::shared_ptr<Media::PixelMap> dstPixelMap_;
};
@ -385,7 +385,6 @@ napi_value FilterNapi::GetPixelMapAsync(napi_env env, napi_callback_info info)
EFFECT_LOG_I("FilterNapi: GetPixelMapAsync parse forceCPU failed");
}
}
ctx->forceCPU = false;
if (argc >= NUM_1) {
if (Media::ImageNapiUtils::getType(env, argv[argc - 1]) == napi_function) {

View File

@ -25,6 +25,7 @@ ohos_shared_library("hdr_capability_utils") {
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
@ -57,6 +58,7 @@ ohos_shared_library("hdrcapability_napi") {
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}

View File

@ -43,9 +43,20 @@ ohos_shared_library("text_napi") {
":text_config",
]
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
deps = [ ":text_napi_impl" ]
external_deps = [ "napi:ace_napi" ]
external_deps = [
"hilog:libhilog",
"napi:ace_napi",
]
relative_install_dir = "module/graphics"
part_name = "graphic_2d"
subsystem_name = "graphic"
@ -68,6 +79,13 @@ ohos_shared_library("text_napi_impl") {
":text_config",
]
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
deps = [
"$graphic_2d_root/interfaces/kits/napi/graphic/drawing:drawing_napi_impl",
"$graphic_2d_root/rosen/modules/2d_graphics:2d_graphics",

View File

@ -148,6 +148,7 @@ void ParsePartTextStyle(napi_env env, napi_value argValue, TextStyle& textStyle)
GetDecorationFromJS(env, argValue, "decoration", textStyle);
SetTextStyleBaseType(env, argValue, textStyle);
ReceiveFontFeature(env, argValue, textStyle);
ReceiveFontVariation(env, argValue, textStyle);
napi_get_named_property(env, argValue, "ellipsis", &tempValue);
std::string text = "";
if (tempValue != nullptr && ConvertFromJsValue(env, tempValue, text)) {
@ -215,6 +216,42 @@ void ReceiveFontFeature(napi_env env, napi_value argValue, TextStyle& textStyle)
return;
}
void ReceiveFontVariation(napi_env env, napi_value argValue, TextStyle& textStyle)
{
napi_value allVariationValue = nullptr;
napi_get_named_property(env, argValue, "fontVariations", &allVariationValue);
uint32_t arrayLength = 0;
if (napi_get_array_length(env, allVariationValue, &arrayLength) != napi_ok ||
!arrayLength) {
ROSEN_LOGE("The parameter of font variations is unvaild");
return;
}
for (uint32_t further = 0; further < arrayLength; further++) {
napi_value singleElementValue;
if (napi_get_element(env, allVariationValue, further, &singleElementValue) != napi_ok) {
ROSEN_LOGE("This parameter of the font variations is unvaild");
break;
}
napi_value variationElement;
std::string axis;
if (napi_get_named_property(env, singleElementValue, "axis", &variationElement) != napi_ok ||
!ConvertFromJsValue(env, variationElement, axis)) {
ROSEN_LOGE("This time that the axis of parameter in font variations is unvaild");
break;
}
int value = 0;
if (napi_get_named_property(env, singleElementValue, "value", &variationElement) != napi_ok ||
!ConvertFromJsValue(env, variationElement, value)) {
ROSEN_LOGE("This time that the value of parameter in font variations is unvaild");
break;
}
textStyle.fontVariations.SetAxisValue(axis, value);
}
return;
}
void SetTextStyleBaseType(napi_env env, napi_value argValue, TextStyle& textStyle)
{
SetDoubleValueFromJS(env, argValue, "letterSpacing", textStyle.letterSpacing);

View File

@ -481,6 +481,8 @@ void SetTextStyleBaseType(napi_env env, napi_value argValue, TextStyle& textStyl
void ReceiveFontFeature(napi_env env, napi_value argValue, TextStyle& textStyle);
void ReceiveFontVariation(napi_env env, napi_value argValue, TextStyle& textStyle);
size_t GetParamLen(napi_env env, napi_value param);
bool GetFontMetricsFromJS(napi_env env, napi_value argValue, Drawing::FontMetrics& fontMetrics);

View File

@ -178,7 +178,6 @@ napi_value JsParagraph::OnPaint(napi_env env, napi_callback_info info)
napi_value JsParagraph::PaintOnPath(napi_env env, napi_callback_info info)
{
ROSEN_LOGE("liyan JsParagraph::PaintOnPath");
JsParagraph* me = CheckParamsAndGetThis<JsParagraph>(env, info);
return (me != nullptr) ? me->OnPaintOnPath(env, info) : nullptr;
}

View File

@ -34,6 +34,7 @@ ohos_shared_library("uieffect_napi") {
sanitize = {
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
include_dirs = [

View File

@ -0,0 +1,19 @@
# Copyright (c) 2024 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.
import("//foundation/graphic/graphic_2d/graphic_config.gni")
group("test") {
testonly = true
deps = [ "graphic_test:test" ]
}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2024 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.
import("//foundation/graphic/graphic_2d/graphic_config.gni")
group("test") {
testonly = true
deps = [ "test_template:unittest" ]
}

View File

@ -0,0 +1,50 @@
# Copyright (c) 2024 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.
import("//build/test.gni")
import("//foundation/graphic/graphic_2d/graphic_config.gni")
module_output_path = "graphic_2d/rosen/graphic_test/graphic_test"
group("unittest") {
testonly = true
deps = [ ":RSGraphicTestTemplateTest" ]
}
## Build RSGraphicTestTemplateTest
ohos_unittest("RSGraphicTestTemplateTest") {
module_out_path = module_output_path
sources = [ "test_template.cpp" ]
deps = [ "$graphic_2d_root/rosen/graphic_test/graphic_test_framework:rs_graphic_test_main" ]
defines = []
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"init:libbegetutil",
]
defines += gpu_defines
cflags = [
"-Wall",
"-Werror",
"-g3",
"-Dprivate=public",
"-Dprotected=public",
]
subsystem_name = "graphic"
part_name = "graphic_2d"
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2024 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 "rs_graphic_test.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS::Rosen {
class TestTemplateTest : public RSGraphicTest {
public:
// called before each tests
void BeforeEach() override
{
auto size = GetScreenSize();
SetSurfaceBounds({0, 0, size.x_ / 2.0f, size.y_ / 2.0f});
SetSurfaceColor(RSColor(0xffff0000));
}
// called after each tests
void AfterEach() override {}
};
/*
* @tc.name: GRAPHIC_TEST_MACRO_TEST
* @tc.desc: GRAPHIC_TEST with derived test class, will take surface capture
* @tc.type: FUNC
*/
GRAPHIC_TEST(TestTemplateTest, CONTENT_DISPLAY_TEST, GRAPHIC_TEST_MACRO_TEST)
{
auto testNode = RSCanvasNode::Create();
testNode->SetBounds({0, 0, 500, 700});
testNode->SetFrame({0, 0, 500, 700});
testNode->SetBackgroundColor(0xffffff00);
GetRootNode()->AddChild(testNode);
// created node should be registered to preserve ref_count
RegisterNode(testNode);
}
/*
* @tc.name: GRAPHIC_TEST_MACRO_TEST
* @tc.desc: GRAPHIC_TEST with default test class, will take surface capture
* @tc.type: FUNC
*/
GRAPHIC_TEST(CONTENT_DISPLAY_TEST, GRAPHIC_TEST_MACRO_TEST)
{
auto testNode = RSCanvasNode::Create();
testNode->SetBounds({0, 0, 500, 700});
testNode->SetFrame({0, 0, 500, 700});
testNode->SetBackgroundColor(0xffffff00);
GetRootNode()->AddChild(testNode);
// created node should be registered to preserve ref_count
RegisterNode(testNode);
}
/*
* @tc.name: GRAPHIC_TEST_N_MACRO_TEST
* @tc.desc: GRAPHIC_TEST with derived test class, will not take surface capture
* @tc.type: FUNC
*/
GRAPHIC_N_TEST(TestTemplateTest, CONTENT_DISPLAY_TEST, GRAPHIC_TEST_N_MACRO_TEST)
{
auto testNode = RSCanvasNode::Create();
testNode->SetBounds({0, 0, 500, 700});
testNode->SetFrame({0, 0, 500, 700});
testNode->SetBackgroundColor(0xffffff00);
GetRootNode()->AddChild(testNode);
// created node should be registered to preserve ref_count
RegisterNode(testNode);
}
/*
* @tc.name: GRAPHIC_TEST_N_MACRO_TEST
* @tc.desc: GRAPHIC_TEST with default test class, will not take surface capture
* @tc.type: FUNC
*/
GRAPHIC_N_TEST(CONTENT_DISPLAY_TEST, GRAPHIC_TEST_N_MACRO_TEST)
{
auto testNode = RSCanvasNode::Create();
testNode->SetBounds({0, 0, 500, 700});
testNode->SetFrame({0, 0, 500, 700});
testNode->SetBackgroundColor(0xffffff00);
GetRootNode()->AddChild(testNode);
// created node should be registered to preserve ref_count
RegisterNode(testNode);
}
}

View File

@ -0,0 +1,127 @@
# Copyright (c) 2024 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.
import("//build/test.gni")
import("//foundation/graphic/graphic_2d/graphic_config.gni")
import("../../modules/render_service_base/config.gni")
config("rs_graphic_test_config") {
include_dirs = [
"include",
"$graphic_2d_root/rosen/modules",
"$graphic_2d_root/rosen/modules/render_service_client/core",
"$graphic_2d_root/rosen/modules/render_service_base/include",
"$graphic_2d_root/rosen/modules/2d_engine/rosen_text/export/rosen_text",
"$graphic_2d_root/rosen/modules/2d_graphics",
"$graphic_2d_root/rosen/modules/2d_graphics/include",
"$graphic_2d_root/rosen/modules/utils",
]
defines = rs_common_define
}
ohos_source_set("rs_graphic_test_src") {
defines = []
defines += gpu_defines
sanitize = {
cfi = true
cfi_cross_dso = true
debug = false
}
testonly = true
sources = [
"src/rs_graphic_rootnode.cpp",
"src/rs_graphic_test.cpp",
"src/rs_graphic_test_director.cpp",
"src/rs_graphic_test_ext.cpp",
"src/rs_graphic_test_utils.cpp",
"src/rs_parameter_parse.cpp",
]
cflags = [
"-Wno-pointer-arith",
"-Wno-missing-field-initializers",
"-Wno-c++11-narrowing",
]
cflags_cc = [
"-fvisibility-inlines-hidden",
"-std=c++17",
]
public_configs = [ ":rs_graphic_test_config" ]
deps = [
"$rosen_root/modules/2d_graphics:2d_graphics",
"$rosen_root/modules/platform:eventhandler",
"$rosen_root/modules/platform:hilog",
"$rosen_root/modules/platform:ipc_core",
]
public_deps = [
"$rosen_root/modules/render_service_base:librender_service_base",
"$rosen_root/modules/render_service_client:librender_service_client",
"//third_party/googletest:gtest",
]
public_external_deps = [
"graphic_surface:surface",
"hilog:libhilog",
"image_framework:image_native",
"libpng:libpng",
"window_manager:libdm",
"zlib:libz",
]
part_name = "graphic_2d"
subsystem_name = "graphic"
}
ohos_shared_library("rs_graphic_test") {
branch_protector_ret = "pac_ret"
sanitize = {
cfi = true
cfi_cross_dso = true
debug = false
}
testonly = true
public_deps = [
":rs_graphic_test_src",
"//third_party/googletest:gtest_main",
]
part_name = "graphic_2d"
subsystem_name = "graphic"
}
ohos_shared_library("rs_graphic_test_main") {
branch_protector_ret = "pac_ret"
sanitize = {
cfi = true
cfi_cross_dso = true
debug = false
}
testonly = true
sources = [ "src/rs_graphic_test_main.cpp" ]
public_deps = [ ":rs_graphic_test_src" ]
external_deps = [ "hilog:libhilog" ]
part_name = "graphic_2d"
subsystem_name = "graphic"
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_LOG_H
#define RS_GRAPHIC_LOG_H
#include <hilog/log.h>
#undef LOG_DOMAIN
#define LOG_DOMAIN 0xD001402
#undef LOG_TAG
#define LOG_TAG "RSGraphicTest"
#define LOGI(format, ...) \
HILOG_INFO(LOG_CORE, "%{public}s: " format, __func__, ##__VA_ARGS__)
#define LOGD(format, ...) \
HILOG_DEBUG(LOG_CORE, "%{public}s: " format, __func__, ##__VA_ARGS__)
#define LOGE(format, ...) \
HILOG_ERROR(LOG_CORE, "%{public}s: " format, __func__, ##__VA_ARGS__)
#define LOGW(format, ...) \
HILOG_WARN(LOG_CORE, "%{public}s: " format, __func__, ##__VA_ARGS__)
#define LOGF(format, ...) \
HILOG_FATAL(LOG_CORE, "%{public}s: " format, __func__, ##__VA_ARGS__)
#endif // RS_GRAPHIC_LOG_H

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_ROOTNODE_H
#define RS_GRAPHIC_ROOTNODE_H
#include "ui/rs_canvas_node.h"
#include "ui/rs_surface_node.h"
namespace OHOS {
namespace Rosen {
class RSGraphicRootNode final {
public:
RSGraphicRootNode();
void AddChild(std::shared_ptr<RSNode> child, int index = -1);
void RemoveChild(std::shared_ptr<RSNode> child);
void ClearChildren();
private:
void SetTestSurface(std::shared_ptr<OHOS::Rosen::RSSurfaceNode> node);
void ResetTestSurface();
std::shared_ptr<OHOS::Rosen::RSSurfaceNode> screenSurfaceNode_;
std::shared_ptr<OHOS::Rosen::RSSurfaceNode> testSurfaceNode_;
friend class RSGraphicTestDirector;
friend class RSGraphicTest;
};
} // namespace Rosen
} // namespace OHOS
#endif // RS_GRAPHIC_ROOTNODE_H

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_TEST_H
#define RS_GRAPHIC_TEST_H
#include "common/rs_color.h"
#include "common/rs_rect.h"
#include "rs_graphic_rootnode.h"
#include "rs_graphic_test_ext.h"
#include "ui/rs_canvas_node.h"
#include "ui/rs_surface_node.h"
namespace OHOS {
namespace Rosen {
class RSGraphicRootNode;
class RSGraphicTest : public testing::Test {
public:
std::shared_ptr<RSGraphicRootNode> GetRootNode() const;
Vector2f GetScreenSize() const;
void SetSurfaceBounds(const Vector4f& bounds);
void SetSurfaceColor(const RSColor& color);
void RegisterNode(std::shared_ptr<RSNode> node);
// overrides gtest functions
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp() override final;
void TearDown() override final;
// user functions
virtual void BeforeEach() {};
virtual void AfterEach() {};
private:
bool shouldRunTest_ = true;
Vector4f surfaceBounds_;
std::vector<std::shared_ptr<RSNode>> nodes_;
static uint32_t imageWriteId_;
};
} // namespace Rosen
} // namespace OHOS
#endif // RS_GRAPHIC_TEST_H

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_TEST_DIRECTOR_H
#define RS_GRAPHIC_TEST_DIRECTOR_H
#include "common/rs_rect.h"
#include "pixel_map.h"
#include "rs_graphic_rootnode.h"
#include "ui/rs_display_node.h"
#include "ui/rs_ui_director.h"
namespace OHOS {
namespace Rosen {
class RSGraphicTestDirector {
public:
~RSGraphicTestDirector();
void Run();
void FlushMessage();
std::shared_ptr<Media::PixelMap> TakeScreenCaptureAndWait(int ms);
void ResetImagePath();
std::shared_ptr<RSGraphicRootNode> GetRootNode() const;
Vector2f GetScreenSize() const;
void SetSurfaceBounds(const Vector4f& bounds);
void SetSurfaceColor(const RSColor& color);
static RSGraphicTestDirector& Instance();
private:
ScreenId screenId_ = 0;
RectF screenBounds_;
std::shared_ptr<RSGraphicRootNode> rootNode_;
std::shared_ptr<RSUIDirector> rsUiDirector_;
std::shared_ptr<OHOS::AppExecFwk::EventRunner> runner_;
std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler_;
friend class RSGraphicTest;
};
} // namespace Rosen
} // namespace OHOS
#endif // RS_GRAPHIC_TEST_DIRECTOR_H

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_TEST_EXT_H
#define RS_GRAPHIC_TEST_EXT_H
#include "gtest/gtest.h"
#include "rs_graphic_log.h"
namespace OHOS {
namespace Rosen {
enum RSGraphicTestType {
FRAMEWORK_TEST,
ANIMATION_TEST,
CONTENT_DISPLAY_TEST,
SCREEN_MANAGER_TEST,
HARDWARE_PRESENT_TEST,
DRAWING_TEST,
LTPO_TEST,
TEXT_TEST,
PIXMAP_TEST,
SYMBOL_TEST,
};
enum class RSGraphicTestMode : uint8_t {
AUTOMATIC = 0x01,
MANUAL = 0x02,
ALL = 0x01 | 0x02,
};
struct TestDefInfo {
std::string testCaseName;
std::string testName;
RSGraphicTestType testType;
RSGraphicTestMode testMode;
};
class TestDefManager {
private:
TestDefManager() {};
std::map<std::string, TestDefInfo> testInfos_;
public:
static TestDefManager& Instance();
bool Regist(const char* testCaseName, const char* testName, RSGraphicTestType type, RSGraphicTestMode mode);
const TestDefInfo* GetTestInfo(const char* testCaseName, const char* testName) const;
std::vector<const TestDefInfo*> GetTestInfosByType(RSGraphicTestType type) const;
};
} // namespace Rosen
} // namespace OHOS
#define GRAPHIC_TEST_PARAMS(test_case_name, test_name, test_type, test_mode) \
bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = \
OHOS::Rosen::TestDefManager::Instance().Regist(#test_case_name, #test_name, test_type, test_mode); \
TEST_F(test_case_name, test_name)
#define GRAPHIC_TEST_2(test_type, test_name) \
GRAPHIC_TEST_PARAMS(RSGraphicTest, test_name, test_type, RSGraphicTestMode::AUTOMATIC)
#define GRAPHIC_TEST_3(test_case_name, test_type, test_name) \
GRAPHIC_TEST_PARAMS(test_case_name, test_name, test_type, RSGraphicTestMode::AUTOMATIC)
#define GRAPHIC_N_TEST_2(test_type, test_name) \
GRAPHIC_TEST_PARAMS(RSGraphicTest, test_name, test_type, RSGraphicTestMode::MANUAL)
#define GRAPHIC_N_TEST_3(test_case_name, test_type, test_name) \
GRAPHIC_TEST_PARAMS(test_case_name, test_name, test_type, RSGraphicTestMode::MANUAL)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define GRAPHIC_TEST(...) GET_MACRO(__VA_ARGS__, GRAPHIC_TEST_3, GRAPHIC_TEST_2)(__VA_ARGS__)
#define GRAPHIC_N_TEST(...) GET_MACRO(__VA_ARGS__, GRAPHIC_N_TEST_3, GRAPHIC_N_TEST_2)(__VA_ARGS__)
#endif // RS_GRAPHIC_TEST_EXT_H

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 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 RS_GRAPHIC_TEST_UTILS_H
#define RS_GRAPHIC_TEST_UTILS_H
#include "pixel_map.h"
#include <chrono>
#include <string>
#include <thread>
using WriteToPngParam = struct {
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t bitDepth;
const uint8_t *data;
};
bool WriteToPngWithPixelMap(const std::string& fileName, OHOS::Media::PixelMap& pixelMap);
void WaitTimeout(int ms);
#endif // RS_GRAPHIC_TEST_UTILS_H

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 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 RS_PARAMETER_PARSE_H
#define RS_PARAMETER_PARSE_H
#include <string>
#include <unordered_set>
#include "rs_graphic_test_ext.h"
namespace OHOS {
namespace Rosen {
class RSParameterParse {
private:
RSParameterParse() {}
public:
static const RSParameterParse& Instance();
static void Parse(int argc, char **argv);
std::string imageSavePath = "/data/local/rs_graphic_tests/";
int testCaseWaitTime = 1000; //ms
int surfaceCaptureWaitTime = 1000; //ms
int manualTestWaitTime = 1500; //ms
std::unordered_set<RSGraphicTestType> filterTestTypes = {};
RSGraphicTestMode runTestMode = RSGraphicTestMode::ALL;
};
} // namespace Rosen
} // namespace OHOS
#endif // RS_PARAMETER_PARSE_H

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 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 "rs_graphic_rootnode.h"
#include "transaction/rs_interfaces.h"
namespace OHOS {
namespace Rosen {
RSGraphicRootNode::RSGraphicRootNode()
{
RSSurfaceNodeConfig config;
config.SurfaceNodeName = "TestScreenSurface";
screenSurfaceNode_ = RSSurfaceNode::Create(config);
}
void RSGraphicRootNode::SetTestSurface(
std::shared_ptr<OHOS::Rosen::RSSurfaceNode> node)
{
testSurfaceNode_ = node;
screenSurfaceNode_->AddChild(testSurfaceNode_, -1);
}
void RSGraphicRootNode::ResetTestSurface()
{
screenSurfaceNode_->RemoveChild(testSurfaceNode_);
testSurfaceNode_ = nullptr;
}
void RSGraphicRootNode::AddChild(std::shared_ptr<RSNode> child, int index)
{
if (testSurfaceNode_) {
testSurfaceNode_->AddChild(child, index);
}
}
void RSGraphicRootNode::RemoveChild(std::shared_ptr<RSNode> child)
{
if (testSurfaceNode_) {
testSurfaceNode_->RemoveChild(child);
}
}
void RSGraphicRootNode::ClearChildren()
{
if (testSurfaceNode_) {
testSurfaceNode_->ClearChildren();
}
}
} // namespace Rosen
} // namespace OHOS

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2024 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 "rs_graphic_test.h"
#include "rs_graphic_test_director.h"
#include "rs_graphic_test_utils.h"
#include "rs_parameter_parse.h"
#include "ui/rs_root_node.h"
#include "ui/rs_surface_node.h"
#include <thread>
#include <chrono>
#include <filesystem>
namespace OHOS {
namespace Rosen {
namespace {
constexpr uint32_t SURFACE_COLOR = 0xffffffff;
bool ShouldRunCurrentTest()
{
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
const auto& extInfo = ::OHOS::Rosen::TestDefManager::Instance().GetTestInfo(
testInfo->test_case_name(), testInfo->name());
const auto& params = RSParameterParse::Instance();
if (!extInfo) {
LOGE("RSGraphicTest no testinfo %{public}s-%{public}s",
testInfo->test_case_name(), testInfo->name());
return false;
}
if (!params.filterTestTypes.empty() && params.filterTestTypes.count(extInfo->testType) == 0) {
return false;
}
if (params.runTestMode != RSGraphicTestMode::ALL && extInfo->testMode != params.runTestMode) {
return false;
}
return true;
}
}
uint32_t RSGraphicTest::imageWriteId_ = 0;
void RSGraphicTest::SetUpTestCase()
{
imageWriteId_ = 0;
}
void RSGraphicTest::TearDownTestCase()
{
return;
}
void RSGraphicTest::SetUp()
{
shouldRunTest_ = ShouldRunCurrentTest();
if (!shouldRunTest_) {
GTEST_SKIP();
return;
}
RSSurfaceNodeConfig config;
config.SurfaceNodeName = "TestSurface";
auto testSurface = RSSurfaceNode::Create(config, false);
testSurface->SetBounds({0, 0, GetScreenSize()[0], GetScreenSize()[1]});
testSurface->SetFrame({0, 0, GetScreenSize()[0], GetScreenSize()[1]});
testSurface->SetBackgroundColor(SURFACE_COLOR);
GetRootNode()->SetTestSurface(testSurface);
BeforeEach();
}
void RSGraphicTest::TearDown()
{
if (!shouldRunTest_) {
return;
}
RSGraphicTestDirector::Instance().FlushMessage();
WaitTimeout(RSParameterParse::Instance().testCaseWaitTime);
const ::testing::TestInfo* const testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
const auto& extInfo = ::OHOS::Rosen::TestDefManager::Instance().GetTestInfo(
testInfo->test_case_name(), testInfo->name());
bool isManualTest = false;
if (extInfo) {
isManualTest = (extInfo->testMode == RSGraphicTestMode::MANUAL);
} else {
LOGE("RSGraphicTest no testinfo %{public}s-%{public}s", testInfo->test_case_name(), testInfo->name());
}
if (isManualTest) {
WaitTimeout(RSParameterParse::Instance().manualTestWaitTime);
} else {
auto pixelMap = RSGraphicTestDirector::Instance().TakeScreenCaptureAndWait(
RSParameterParse::Instance().surfaceCaptureWaitTime);
if (pixelMap) {
std::string filename = RSParameterParse::Instance().imageSavePath;
filename += testInfo->test_case_name() + std::string("_");
filename += testInfo->name() + std::string(".png");
if (std::filesystem::exists(filename)) {
LOGW("RSGraphicTest file exists %{public}s", filename.c_str());
}
if (!WriteToPngWithPixelMap(filename, *pixelMap)) {
LOGE("RSGraphicTest::TearDown write image failed %{public}s-%{public}s",
testInfo->test_case_name(), testInfo->name());
}
}
}
AfterEach();
GetRootNode()->ResetTestSurface();
RSGraphicTestDirector::Instance().FlushMessage();
WaitTimeout(RSParameterParse::Instance().testCaseWaitTime);
++imageWriteId_;
}
void RSGraphicTest::RegisterNode(std::shared_ptr<RSNode> node)
{
nodes_.push_back(node);
}
std::shared_ptr<RSGraphicRootNode> RSGraphicTest::GetRootNode() const
{
return RSGraphicTestDirector::Instance().GetRootNode();
}
Vector2f RSGraphicTest::GetScreenSize() const
{
return RSGraphicTestDirector::Instance().GetScreenSize();
}
void RSGraphicTest::SetSurfaceBounds(const Vector4f& bounds)
{
RSGraphicTestDirector::Instance().SetSurfaceBounds(bounds);
}
void RSGraphicTest::SetSurfaceColor(const RSColor& color)
{
RSGraphicTestDirector::Instance().SetSurfaceColor(color);
}
} // namespace Rosen
} // namespace OHOS

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2024 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 "display_manager.h"
#include "rs_graphic_test_director.h"
#include "rs_parameter_parse.h"
#include "transaction/rs_interfaces.h"
#include "ui/rs_root_node.h"
#include "ui/rs_surface_node.h"
#include "ui/rs_ui_director.h"
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <filesystem>
namespace OHOS {
namespace Rosen {
namespace {
constexpr float TOP_LEVEL_Z = 1000000.0f;
constexpr uint32_t SCREEN_COLOR = 0;
class TestSurfaceCaptureCallback : public SurfaceCaptureCallback {
public:
void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
{
{
std::unique_lock lock(mutex_);
ready_ = true;
pixelMap_ = pixelMap;
}
cv_.notify_all();
if (pixelMap == nullptr) {
LOGE("RSGraphicTestDirector pixelMap == nullptr");
}
}
void Wait(int ms)
{
std::unique_lock lock(mutex_);
cv_.wait_for(lock, std::chrono::milliseconds(ms), [&] { return ready_; });
}
std::mutex mutex_;
std::condition_variable cv_;
bool ready_ = false;
std::shared_ptr<Media::PixelMap> pixelMap_;
};
}
RSGraphicTestDirector& RSGraphicTestDirector::Instance()
{
static RSGraphicTestDirector instance;
return instance;
}
RSGraphicTestDirector::~RSGraphicTestDirector()
{
rootNode_->screenSurfaceNode_->RemoveFromTree();
rsUiDirector_->SendMessages();
sleep(1);
}
void RSGraphicTestDirector::Run()
{
rsUiDirector_ = RSUIDirector::Create();
rsUiDirector_->Init();
auto runner = OHOS::AppExecFwk::EventRunner::Create(true);
auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
rsUiDirector_->SetUITaskRunner(
[handler](const std::function<void()>& task, uint32_t delay) { handler->PostTask(task); });
runner->Run();
screenId_ = RSInterfaces::GetInstance().GetDefaultScreenId();
auto defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
Vector4f defaultScreenBounds = {0, 0, defaultDisplay->GetWidth(), defaultDisplay->GetHeight()};
screenBounds_ = defaultScreenBounds;
rootNode_ = std::make_shared<RSGraphicRootNode>();
rootNode_->screenSurfaceNode_->SetBounds(defaultScreenBounds);
rootNode_->screenSurfaceNode_->SetFrame(defaultScreenBounds);
rootNode_->screenSurfaceNode_->SetBackgroundColor(SCREEN_COLOR);
rootNode_->screenSurfaceNode_->AttachToDisplay(screenId_);
rootNode_->screenSurfaceNode_->SetPositionZ(TOP_LEVEL_Z);
rsUiDirector_->SetRSSurfaceNode(rootNode_->screenSurfaceNode_);
rsUiDirector_->SendMessages();
sleep(1);
ResetImagePath();
}
void RSGraphicTestDirector::FlushMessage()
{
rsUiDirector_->SendMessages();
}
std::shared_ptr<Media::PixelMap> RSGraphicTestDirector::TakeScreenCaptureAndWait(int ms)
{
auto callback = std::make_shared<TestSurfaceCaptureCallback>();
if (!RSInterfaces::GetInstance().TakeSurfaceCapture(rootNode_->screenSurfaceNode_->GetId(), callback)) {
return nullptr;
}
callback->Wait(ms);
return callback->pixelMap_;
}
void RSGraphicTestDirector::ResetImagePath()
{
namespace fs = std::filesystem;
const auto& path = RSParameterParse::Instance().imageSavePath;
if (!fs::exists(path)) {
if (!fs::create_directories(path)) {
LOGE("RSGraphicTestDirector create dir failed %{public}s", path.c_str());
}
} else {
if (!fs::is_directory(path) || !fs::is_empty(path)) {
LOGE("RSGraphicTestDirector path is not dir or not empty %{public}s", path.c_str());
}
}
}
std::shared_ptr<RSGraphicRootNode> RSGraphicTestDirector::GetRootNode() const
{
return rootNode_;
}
Vector2f RSGraphicTestDirector::GetScreenSize() const
{
return {screenBounds_.GetWidth(), screenBounds_.GetHeight()};
}
void RSGraphicTestDirector::SetSurfaceBounds(const Vector4f& bounds)
{
if (rootNode_->testSurfaceNode_) {
rootNode_->testSurfaceNode_->SetBounds(bounds);
}
}
void RSGraphicTestDirector::SetSurfaceColor(const RSColor& color)
{
if (rootNode_->testSurfaceNode_) {
rootNode_->testSurfaceNode_->SetBackgroundColor(color.AsRgbaInt());
}
}
} // namespace Rosen
} // namespace OHOS

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 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 "rs_graphic_test_ext.h"
namespace OHOS {
namespace Rosen {
namespace {
std::string GetTestName(const char* testCaseName, const char* testName)
{
return std::string(testCaseName) + "_" + testName;
}
}
TestDefManager& TestDefManager::Instance()
{
static TestDefManager instance;
return instance;
}
bool TestDefManager::Regist(const char* testCaseName, const char* testName,
RSGraphicTestType type, RSGraphicTestMode mode)
{
const auto& name = GetTestName(testCaseName, testName);
if (testInfos_.find(name) != testInfos_.end()) {
LOGE("TestDefManager::Regist duplicate name %{public}s", name.c_str());
return false;
}
testInfos_.emplace(name, TestDefInfo {testCaseName, testName, type, mode});
return true;
}
const TestDefInfo* TestDefManager::GetTestInfo(const char* testCaseName, const char* testName) const
{
const auto& it = testInfos_.find(GetTestName(testCaseName, testName));
if (it != testInfos_.end()) {
return &it->second;
}
return nullptr;
}
std::vector<const TestDefInfo*> TestDefManager::GetTestInfosByType(RSGraphicTestType type) const
{
std::vector<const TestDefInfo*> infos;
for (const auto& it: testInfos_) {
if (it.second.testType == type) {
infos.push_back(&it.second);
}
}
return infos;
}
} // namespace Rosen
} // namespace OHOS

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024 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 "rs_graphic_test.h"
#include "rs_graphic_test_director.h"
#include "rs_parameter_parse.h"
using namespace OHOS;
using namespace OHOS::Rosen;
int main(int argc, char **argv)
{
RSParameterParse::Parse(argc, argv);
RSGraphicTestDirector::Instance().Run();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2024 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 "png.h"
#include "rs_graphic_log.h"
#include "rs_graphic_test_utils.h"
static bool WriteToPng(const std::string &filename, const WriteToPngParam &param)
{
if (filename.empty()) {
LOGI("RSBaseRenderUtil::WriteToPng filename is empty");
return false;
}
LOGI("RSBaseRenderUtil::WriteToPng filename = %{public}s", filename.c_str());
png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (pngStruct == nullptr) {
return false;
}
png_infop pngInfo = png_create_info_struct(pngStruct);
if (pngInfo == nullptr) {
png_destroy_write_struct(&pngStruct, nullptr);
return false;
}
FILE *fp = fopen(filename.c_str(), "wb");
if (fp == nullptr) {
png_destroy_write_struct(&pngStruct, &pngInfo);
LOGE("WriteToPng file: %s open file failed, errno: %d", filename.c_str(), errno);
return false;
}
png_init_io(pngStruct, fp);
// set png header
png_set_IHDR(pngStruct, pngInfo,
param.width, param.height,
param.bitDepth,
PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
png_set_packing(pngStruct); // set packing info
png_write_info(pngStruct, pngInfo); // write to header
for (uint32_t i = 0; i < param.height; i++) {
png_write_row(pngStruct, param.data + (i * param.stride));
}
png_write_end(pngStruct, pngInfo);
// free
png_destroy_write_struct(&pngStruct, &pngInfo);
int ret = fclose(fp);
return ret == 0;
}
bool WriteToPngWithPixelMap(const std::string& fileName, OHOS::Media::PixelMap& pixelMap)
{
constexpr int bitDepth = 8;
WriteToPngParam param;
param.width = static_cast<uint32_t>(pixelMap.GetWidth());
param.height = static_cast<uint32_t>(pixelMap.GetHeight());
param.data = pixelMap.GetPixels();
param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
param.bitDepth = bitDepth;
return WriteToPng(fileName, param);
}
void WaitTimeout(int ms)
{
auto time = std::chrono::milliseconds(ms);
std::this_thread::sleep_for(time);
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 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 "rs_parameter_parse.h"
namespace OHOS {
namespace Rosen {
const RSParameterParse& RSParameterParse::Instance()
{
static RSParameterParse instance;
return instance;
}
void RSParameterParse::Parse(int argc, char **argv)
{
return;
}
} // namespace Rosen
} // namespace OHOS

View File

@ -107,6 +107,8 @@ float Typography::DetectIndents(size_t index)
void Typography::Layout(double width)
{
std::unique_lock lock(g_layoutMutex);
lineMetrics_.reset();
lineMetricsStyles_.clear();
return paragraph_->Layout(width);
}
@ -304,14 +306,17 @@ bool Typography::GetLineInfo(int lineNumber, bool oneLine, bool includeWhitespac
std::vector<LineMetrics> Typography::GetLineMetrics()
{
std::vector<LineMetrics> lineMetrics;
if (lineMetrics_) {
return lineMetrics_.value();
}
if (paragraph_ != nullptr) {
lineMetrics_.emplace();
auto metrics = paragraph_->GetLineMetrics();
lineMetricsStyles_.reserve(std::accumulate(metrics.begin(), metrics.end(), 0,
[](const int a, const skia::textlayout::LineMetrics& b) { return a + b.fLineMetrics.size(); }));
for (const skt::LineMetrics& skLineMetrics : metrics) {
LineMetrics& line = lineMetrics.emplace_back();
LineMetrics& line = lineMetrics_->emplace_back();
if (!skLineMetrics.fLineMetrics.empty()) {
const auto &skmFontMetrics = skLineMetrics.fLineMetrics.begin()->second.font_metrics;
line.firstCharMetrics = skmFontMetrics;
@ -340,7 +345,7 @@ std::vector<LineMetrics> Typography::GetLineMetrics()
}
}
}
return lineMetrics;
return lineMetrics_.value();
}
bool Typography::GetLineMetricsAt(int lineNumber, LineMetrics* lineMetrics)

View File

@ -74,6 +74,7 @@ public:
private:
std::unique_ptr<SPText::Paragraph> paragraph_ = nullptr;
std::vector<TextStyle> lineMetricsStyles_;
std::optional<std::vector<LineMetrics>> lineMetrics_;
};
} // namespace AdapterTxt
} // namespace Rosen

View File

@ -25,9 +25,13 @@ namespace OHOS {
namespace Rosen {
namespace TextEngine {
struct SymbolNode {
struct NodeLayerInfo {
Drawing::Path path;
Drawing::DrawingSColor color;
};
struct SymbolNode {
std::vector<NodeLayerInfo> pathsInfo;
Vector4f nodeBoundary;
Drawing::DrawingHMSymbolData symbolData;
int animationIndex = 0;

View File

@ -105,7 +105,6 @@ struct TypographyStyle {
bool customTextStyle = false;
TextHeightBehavior textHeightBehavior = TextHeightBehavior::ALL;
bool hintingIsOn = false;
bool ellipsizedForNDK = false;
};
} // namespace Rosen
} // namespace OHOS

View File

@ -19,27 +19,101 @@ namespace OHOS {
namespace Rosen {
namespace SPText {
static void MergePath(RSPath& multPath, const std::vector<RSGroupInfo>& groupInfos, std::vector<RSPath>& pathLayers)
/**
* @brief Obtain the group id to layer
* @param groupIds (output paramer) the index of groupIds if layer index, the groupIds[index] is the group index
* @param renderGroup the renderGroup info of symbol
* @param index the renderGroup index
*/
static void GetLayersGroupId(std::vector<size_t>& groupIds, const RSRenderGroup& renderGroup, size_t index)
{
for (auto& groupInfo : renderGroup.groupInfos) {
for (auto& j : groupInfo.layerIndexes) {
if (j < groupIds.size()) {
groupIds[j] = index;
}
}
for (auto& j : groupInfo.maskIndexes) {
if (j < groupIds.size()) {
groupIds[j] = index;
}
}
}
}
/**
* @brief Merge the mask paths.
* @param maskIndexes the indexes of maskLayer of group informations
* @param pathLayers the path data of layers on symbol, the value of maskIndexes < pathLayers.size
* @param pathsColorIndex the start pathsColor position for merging mask pathh
* @param pathsColor (output paramer) the result of the merge
*/
static void MergeMaskPath(const std::vector<size_t>& maskIndexes, std::vector<RSPath>& pathLayers,
size_t pathsColorIndex, std::vector<TextEngine::NodeLayerInfo>& pathsColor)
{
RSPath maskPath;
for (size_t maskIndex : maskIndexes) {
if (maskIndex < pathLayers.size()) {
maskPath.AddPath(pathLayers[maskIndex]);
}
}
if (!maskPath.IsValid()) {
return;
}
for (size_t j = pathsColorIndex; j < pathsColor.size(); j++) {
Drawing::Path outPath;
bool isOk = outPath.Op(pathsColor[j].path, maskPath, Drawing::PathOp::DIFFERENCE);
pathsColor[j].path = isOk ? outPath : pathsColor[j].path;
}
}
/**
* @brief Merge the paths of Group by layer color.
* @param groupInfos a group informations of dynamic drawing
* @param pathLayers the path data of layers on symbol
* @param groupIndexes the indexes list of groups on colorGroups, the groupIndexes.size == pathLayers.size, \n
* groupIndexes.size == pathLayers.size, groupIndexes[groupIndexes.size - 1] < colorGroups.size
* @param pathsColor (output paramer) the result of the merge, where each merged path corresponds to a specific color
* @param colorGroups the groups informations of static drawing, include color data
*/
static void MergePathByLayerColor(const std::vector<RSGroupInfo>& groupInfos,
std::vector<RSPath>& pathLayers, const std::vector<size_t>& groupIndexes,
std::vector<TextEngine::NodeLayerInfo>& pathsColor, const std::vector<RSRenderGroup>& colorGroups)
{
size_t pathsColorIndex = 0;
RSSColor color = {0, 0, 0, 0}; // default color with 0 alpha
for (const auto& groupInfo : groupInfos) {
RSPath pathTemp;
for (auto k : groupInfo.layerIndexes) {
if (k >= pathLayers.size()) {
TextEngine::NodeLayerInfo tempLayer;
size_t currentIndex = 0; // the current layerindex, that effective index of tempLayer
bool isFirst = true;
for (auto& layerIndex: groupInfo.layerIndexes) {
if (layerIndex >= pathLayers.size() || layerIndex >= groupIndexes.size()) {
continue;
}
pathTemp.AddPath(pathLayers[k]);
}
for (size_t h : groupInfo.maskIndexes) {
if (h >= pathLayers.size()) {
if (isFirst) { // initialize tempLayer
auto groupIndex = groupIndexes[layerIndex];
tempLayer.color = groupIndex < colorGroups.size() ? colorGroups[groupIndex].color : color;
tempLayer.path.AddPath(pathLayers[layerIndex]);
currentIndex = layerIndex;
isFirst = false;
continue;
}
RSPath outPath;
auto isOk = outPath.Op(pathTemp, pathLayers[h], RSPathOp::DIFFERENCE);
if (isOk) {
pathTemp = outPath;
// If the groupIndex of two paths is different, updata pathsColor and tempLayer
if (groupIndexes[currentIndex] != groupIndexes[layerIndex]) {
pathsColor.push_back(tempLayer);
tempLayer.path.Reset();
auto groupIndex = groupIndexes[layerIndex];
tempLayer.color = groupIndex < colorGroups.size() ? colorGroups[groupIndex].color : color;
currentIndex = layerIndex;
}
tempLayer.path.AddPath(pathLayers[layerIndex]);
}
multPath.AddPath(pathTemp);
pathsColor.push_back(tempLayer);
if (!groupInfo.maskIndexes.empty()) {
MergeMaskPath(groupInfo.maskIndexes, pathLayers, pathsColorIndex, pathsColor);
}
pathsColorIndex = pathsColor.size();
}
}
@ -92,24 +166,28 @@ void SymbolNodeBuild::AddHierarchicalAnimation(RSHMSymbolData &symbolData, const
RSHMSymbol::PathOutlineDecompose(symbolData.path_, paths);
std::vector<RSPath> pathLayers;
RSHMSymbol::MultilayerPath(symbolData.symbolInfo_.layers, paths, pathLayers);
RSSColor color;
size_t i = 0;
auto renderGroups = symbolData.symbolInfo_.renderGroups;
// Obtain the group id of layer
std::vector<size_t> groupIds(pathLayers.size(), pathLayers.size());
for (size_t idx = 0; idx < symbolData.symbolInfo_.renderGroups.size(); idx++) {
GetLayersGroupId(groupIds, symbolData.symbolInfo_.renderGroups[idx], idx);
}
// Splitting animation nodes information
for (auto& groupSetting: groupSettings) {
RSPath multPath;
RSPath maskPath;
bool isMask = IsMaskLayer(maskPath, groupSetting.groupInfos, pathLayers);
TextEngine::SymbolNode symbolNode;
TextEngine::NodeLayerInfo maskPath;
bool isMask = IsMaskLayer(maskPath.path, groupSetting.groupInfos, pathLayers);
if (!isMask) {
MergePath(multPath, groupSetting.groupInfos, pathLayers);
if (i < renderGroups.size()) {
color = renderGroups[i].color;
i++;
}
MergePathByLayerColor(groupSetting.groupInfos, pathLayers, groupIds, symbolNode.pathsInfo,
symbolData.symbolInfo_.renderGroups);
} else {
multPath = maskPath;
symbolNode.pathsInfo.push_back(maskPath);
}
TextEngine::SymbolNode symbolNode = {multPath, color, nodeBounds, symbolData,
groupSetting.animationIndex, isMask};
symbolNode.nodeBoundary = nodeBounds;
symbolNode.symbolData = symbolData;
symbolNode.animationIndex = groupSetting.animationIndex;
symbolNode.isMask = isMask;
symbolAnimationConfig->symbolNodes.push_back(symbolNode);
}
symbolAnimationConfig->numNodes = symbolAnimationConfig->symbolNodes.size();

View File

@ -48,7 +48,7 @@ public:
// set common subtype of symbol animation attribute
void SetCommonSubType(Drawing::DrawingCommonSubType commonSubType);
bool operator ==(HMSymbolTxt const &sym) const;
bool operator ==(HMSymbolTxt const &symbol) const;
std::vector<RSSColor> GetRenderColor() const;

View File

@ -406,6 +406,25 @@ void OH_Drawing_CanvasDrawArc(OH_Drawing_Canvas*, const OH_Drawing_Rect*, float
*/
void OH_Drawing_CanvasDrawRoundRect(OH_Drawing_Canvas*, const OH_Drawing_RoundRect*);
/**
* @brief Draws a single character.
*
* @syscap SystemCapability.Graphic.Graphic2D.NativeDrawing
* @param OH_Drawing_Canvas Indicates the pointer to an <b>OH_Drawing_Canvas</b> object.
* @param str Indicates the single character encoded in UTF-8.
* @param OH_Drawing_Font Indicates the pointer to an <b>OH_Drawing_Font</b> object.
* @param x Indicates the horizontal offset applied to the single character.
* @param y Indicates the vertical offset applied to the single character.
* @return Returns the error code.
* Returns {@link OH_DRAWING_SUCCESS} if the operation is successful.
* Returns {@link OH_DRAWING_ERROR_INVALID_PARAMETER} if any of canvas, str
* and font is nullptr or strlen(str) is 0.
* @since 12
* @version 1.0
*/
OH_Drawing_ErrorCode OH_Drawing_CanvasDrawSingleCharacter(OH_Drawing_Canvas* canvas, const char* str,
const OH_Drawing_Font* font, float x, float y);
/**
* @brief Draws a textblob.
*

View File

@ -240,6 +240,23 @@ uint32_t OH_Drawing_FontTextToGlyphs(const OH_Drawing_Font*, const void* text, u
*/
void OH_Drawing_FontGetWidths(const OH_Drawing_Font*, const uint16_t* glyphs, int count, float* widths);
/**
* @brief Measures the width of a single character.
*
* @syscap SystemCapability.Graphic.Graphic2D.NativeDrawing
* @param font Indicates the pointer to an <b>OH_Drawing_Font</b> object.
* @param str Indicates the single character encoded in UTF-8.
* @param textWidth Indicates the width of the single character.
* @return Returns the error code.
* Returns {@link OH_DRAWING_SUCCESS} if the operation is successful.
* Returns {@link OH_DRAWING_ERROR_INVALID_PARAMETER} if any of font, str
* and textWidth is nullptr or strlen(str) is 0.
* @since 12
* @version 1.0
*/
OH_Drawing_ErrorCode OH_Drawing_FontMeasureSingleCharacter(const OH_Drawing_Font* font, const char* str,
float* textWidth);
/**
* @brief Measures the width of text.
*

View File

@ -93,8 +93,18 @@ void OH_Drawing_DisableFontCollectionFallback(OH_Drawing_FontCollection*);
* @version 1.0
*/
void OH_Drawing_DisableFontCollectionSystemFont(OH_Drawing_FontCollection*);
/**
* @brief Clear font caches.
*
* @syscap SystemCapability.Graphic.Graphic2D.NativeDrawing
* @param OH_Drawing_FontCollection Indicates the pointer to an <b>OH_Drawing_FontCollection</b> object.
* @since 12
* @version 1.0
*/
void OH_Drawing_ClearFontCaches(OH_Drawing_FontCollection*);
#ifdef __cplusplus
}
#endif
/** @} */
#endif
#endif

View File

@ -1980,6 +1980,18 @@ void OH_Drawing_TypographyHandlerAddSymbol(OH_Drawing_TypographyCreate*, uint32_
*/
void OH_Drawing_TextStyleAddFontFeature(OH_Drawing_TextStyle*, const char* tag, int value);
/**
* @brief Add font variation.
*
* @syscap SystemCapability.Graphic.Graphic2D.NativeDrawing
* @param OH_Drawing_TextStyle Indicates the pointer to an <b>OH_Drawing_TextStyle</b> object.
* @param char* Indicates the pointer to font variation axis.
* @param float Indicates the font variation value to set.
* @since 12
* @version 1.0
*/
void OH_Drawing_TextStyleAddFontVariation(OH_Drawing_TextStyle*, const char* /* axis */, const float /* value */);
/**
* @brief Get all font features.
*

View File

@ -14,6 +14,9 @@
*/
#include "drawing_canvas.h"
#include "src/utils/SkUTF.h"
#include "drawing_canvas_utils.h"
#include "image_pixel_map_mdk.h"
#include "native_pixel_map.h"
@ -100,6 +103,11 @@ static const SamplingOptions& CastToSamplingOptions(const OH_Drawing_SamplingOpt
return reinterpret_cast<const SamplingOptions&>(cSamplingOptions);
}
static const Font& CastToFont(const OH_Drawing_Font& cFont)
{
return reinterpret_cast<const Font&>(cFont);
}
OH_Drawing_Canvas* OH_Drawing_CanvasCreate()
{
return (OH_Drawing_Canvas*)new Canvas;
@ -485,6 +493,26 @@ void OH_Drawing_CanvasDrawRoundRect(OH_Drawing_Canvas* cCanvas, const OH_Drawing
canvas->DrawRoundRect(CastToRoundRect(*cRoundRect));
}
OH_Drawing_ErrorCode OH_Drawing_CanvasDrawSingleCharacter(OH_Drawing_Canvas* cCanvas, const char* str,
const OH_Drawing_Font* cFont, float x, float y)
{
if (str == nullptr || cFont == nullptr) {
return OH_DRAWING_ERROR_INVALID_PARAMETER;
}
Canvas* canvas = CastToCanvas(cCanvas);
if (canvas == nullptr) {
return OH_DRAWING_ERROR_INVALID_PARAMETER;
}
size_t len = strlen(str);
if (len == 0) {
return OH_DRAWING_ERROR_INVALID_PARAMETER;
}
const char* currentStr = str;
int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
canvas->DrawSingleCharacter(unicode, CastToFont(*cFont), x, y);
return OH_DRAWING_SUCCESS;
}
void OH_Drawing_CanvasDrawTextBlob(OH_Drawing_Canvas* cCanvas, const OH_Drawing_TextBlob* cTextBlob, float x, float y)
{
if (cTextBlob == nullptr) {

View File

@ -15,7 +15,7 @@
#include "drawing_font.h"
#include "drawing_canvas_utils.h"
#include "src/utils/SkUTF.h"
#include "drawing_canvas_utils.h"
#include "text/font.h"
@ -230,6 +230,22 @@ void OH_Drawing_FontGetWidths(const OH_Drawing_Font* cFont, const uint16_t* glyp
CastToFont(*cFont).GetWidths(glyphs, count, widths);
}
OH_Drawing_ErrorCode OH_Drawing_FontMeasureSingleCharacter(const OH_Drawing_Font* cFont, const char* str,
float* textWidth)
{
if (cFont == nullptr || str == nullptr || textWidth == nullptr) {
return OH_DRAWING_ERROR_INVALID_PARAMETER;
}
size_t len = strlen(str);
if (len == 0) {
return OH_DRAWING_ERROR_INVALID_PARAMETER;
}
const char* currentStr = str;
int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
*textWidth = CastToFont(*cFont).MeasureSingleCharacter(unicode);
return OH_DRAWING_SUCCESS;
}
OH_Drawing_ErrorCode OH_Drawing_FontMeasureText(const OH_Drawing_Font* cFont, const void* text, size_t byteLength,
OH_Drawing_TextEncoding encoding, OH_Drawing_Rect* bounds, float* textWidth)
{

View File

@ -116,4 +116,22 @@ void OH_Drawing_DisableFontCollectionSystemFont(OH_Drawing_FontCollection* fontC
ConvertToFontCollection<OHOS::Rosen::AdapterTextEngine::FontCollection>(fontCollection)->DisableSystemFont();
#endif
#endif
}
}
void OH_Drawing_ClearFontCaches(OH_Drawing_FontCollection* fontCollection)
{
if (!fontCollection) {
return;
}
if (FontCollectionMgr::GetInstance().Find(fontCollection)) {
ConvertToFontCollection<OHOS::Rosen::AdapterTxt::FontCollection>(fontCollection)->ClearCaches();
return;
}
if (objectMgr->HasObject(fontCollection)) {
ConvertToFontCollection<OHOS::Rosen::AdapterTxt::FontCollection>(fontCollection)->ClearCaches();
return;
}
return;
}

View File

@ -253,6 +253,10 @@ void OH_Drawing_PathAddRoundRect(OH_Drawing_Path* cPath,
void OH_Drawing_PathAddOvalWithInitialPoint(OH_Drawing_Path* cPath,
const OH_Drawing_Rect* oval, uint32_t start, OH_Drawing_PathDirection dir)
{
if (dir < PATH_DIRECTION_CW || dir > PATH_DIRECTION_CCW) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
if (oval == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return;
@ -303,6 +307,10 @@ void OH_Drawing_PathAddPath(OH_Drawing_Path* cPath,
void OH_Drawing_PathAddPathWithMatrixAndMode(OH_Drawing_Path* cPath,
const OH_Drawing_Path* src, const OH_Drawing_Matrix* cMatrix, OH_Drawing_PathAddMode mode)
{
if (mode < PATH_ADD_MODE_APPEND || mode > PATH_ADD_MODE_EXTEND) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
Path* path = CastToPath(cPath);
if (path == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
@ -323,6 +331,10 @@ void OH_Drawing_PathAddPathWithMatrixAndMode(OH_Drawing_Path* cPath,
void OH_Drawing_PathAddPathWithMode(OH_Drawing_Path* cPath, const OH_Drawing_Path* src, OH_Drawing_PathAddMode mode)
{
if (mode < PATH_ADD_MODE_APPEND || mode > PATH_ADD_MODE_EXTEND) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
Path* path = CastToPath(cPath);
if (path == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
@ -339,6 +351,10 @@ void OH_Drawing_PathAddPathWithMode(OH_Drawing_Path* cPath, const OH_Drawing_Pat
void OH_Drawing_PathAddPathWithOffsetAndMode(OH_Drawing_Path* cPath,
const OH_Drawing_Path* src, float dx, float dy, OH_Drawing_PathAddMode mode)
{
if (mode < PATH_ADD_MODE_APPEND || mode > PATH_ADD_MODE_EXTEND) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
Path* path = CastToPath(cPath);
if (path == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
@ -354,6 +370,10 @@ void OH_Drawing_PathAddPathWithOffsetAndMode(OH_Drawing_Path* cPath,
void OH_Drawing_PathAddOval(OH_Drawing_Path* cPath, const OH_Drawing_Rect* oval, OH_Drawing_PathDirection dir)
{
if (dir < PATH_DIRECTION_CW || dir > PATH_DIRECTION_CCW) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
if (oval == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return;
@ -387,6 +407,10 @@ void OH_Drawing_PathAddPolygon(OH_Drawing_Path* cPath, const OH_Drawing_Point2D*
void OH_Drawing_PathAddCircle(OH_Drawing_Path* cPath, float x, float y, float radius, OH_Drawing_PathDirection dir)
{
if (dir < PATH_DIRECTION_CW || dir > PATH_DIRECTION_CCW) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
if (radius <= 0) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
@ -544,6 +568,10 @@ bool OH_Drawing_PathGetPositionTangent(OH_Drawing_Path* cPath, bool forceClosed,
bool OH_Drawing_PathOp(OH_Drawing_Path* cPath, const OH_Drawing_Path* src, OH_Drawing_PathOpMode op)
{
if (op < PATH_OP_MODE_DIFFERENCE || op > PATH_OP_MODE_REVERSE_DIFFERENCE) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return false;
}
Path* path = CastToPath(cPath);
Path* srcPath = CastToPath(const_cast<OH_Drawing_Path*>(src));
if (path == nullptr || srcPath == nullptr) {
@ -556,6 +584,10 @@ bool OH_Drawing_PathOp(OH_Drawing_Path* cPath, const OH_Drawing_Path* src, OH_Dr
bool OH_Drawing_PathGetMatrix(OH_Drawing_Path* cPath, bool forceClosed,
float distance, OH_Drawing_Matrix* cMatrix, OH_Drawing_PathMeasureMatrixFlags flag)
{
if (flag < GET_POSITION_MATRIX || flag > GET_POSITION_AND_TANGENT_MATRIX) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return false;
}
Path* path = CastToPath(cPath);
Matrix* matrix = CastToMatrix(cMatrix);
if (path == nullptr || matrix == nullptr) {

View File

@ -235,6 +235,10 @@ OH_Drawing_PenLineCapStyle OH_Drawing_PenGetCap(const OH_Drawing_Pen* cPen)
void OH_Drawing_PenSetCap(OH_Drawing_Pen* cPen, OH_Drawing_PenLineCapStyle cCap)
{
if (cCap < LINE_FLAT_CAP || cCap > LINE_ROUND_CAP) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
Pen* pen = CastToPen(cPen);
if (pen == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
@ -257,6 +261,10 @@ OH_Drawing_PenLineJoinStyle OH_Drawing_PenGetJoin(const OH_Drawing_Pen* cPen)
void OH_Drawing_PenSetJoin(OH_Drawing_Pen* cPen, OH_Drawing_PenLineJoinStyle cJoin)
{
if (cJoin < LINE_MITER_JOIN || cJoin > LINE_BEVEL_JOIN) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return;
}
Pen* pen = CastToPen(cPen);
if (pen == nullptr) {
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;

View File

@ -61,6 +61,10 @@ bool OH_Drawing_RegionOp(OH_Drawing_Region* cRegion, const OH_Drawing_Region* cD
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return false;
}
if (op < REGION_OP_MODE_DIFFERENCE || op > REGION_OP_MODE_REPLACE) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return false;
}
return region->Op(*dst, static_cast<RegionOp>(op));
}

View File

@ -43,7 +43,7 @@ using namespace OHOS::Rosen;
#define ERROR_NULL_FONT_BUFFER 6
#define ERROR_BUFFER_SIZE_ZERO 7
#define ERROR_NULL_FONT_COLLECTION 8
#define ERROR_REGISTER_FAILED 9
#define ERROR_FILE_CORRUPTION 9
#ifdef BUILD_NON_SDK_VER
static bool StdFilesystemExists(const std::string &p, std::error_code &ec)
@ -72,9 +72,15 @@ static uint32_t LoadFromFontCollection(OH_Drawing_FontCollection* fontCollection
}
auto fc = ConvertToOriginalText<FontCollection>(fontCollection);
#ifndef USE_GRAPHIC_TEXT_GINE
fc->LoadFontFromList(data, dataLength, familyName);
auto face = fc->LoadFontFromList(data, dataLength, familyName);
if (face == nullptr) {
return ERROR_FILE_CORRUPTION;
}
#else
fc->LoadFont(familyName, data, dataLength);
auto face = fc->LoadFont(familyName, data, dataLength);
if (face == nullptr) {
return ERROR_FILE_CORRUPTION;
}
#endif
return 0;
}
@ -150,4 +156,4 @@ uint32_t OH_Drawing_RegisterFontBuffer(OH_Drawing_FontCollection* fontCollection
const std::string familyName = fontFamily;
return LoadFromFontCollection(fontCollection, familyName, fontBuffer, length);
}
}

View File

@ -15,6 +15,7 @@
#include "drawing_sampling_options.h"
#include "utils/sampling_options.h"
#include "drawing_canvas_utils.h"
using namespace OHOS;
using namespace Rosen;
@ -27,6 +28,10 @@ static SamplingOptions* CastToSamplingOptions(OH_Drawing_SamplingOptions* cSampl
OH_Drawing_SamplingOptions* OH_Drawing_SamplingOptionsCreate(OH_Drawing_FilterMode fm, OH_Drawing_MipmapMode mm)
{
if (mm < MIPMAP_MODE_NONE || mm > MIPMAP_MODE_LINEAR) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
return (OH_Drawing_SamplingOptions*)new SamplingOptions(static_cast<FilterMode>(fm), static_cast<MipmapMode>(mm));
}

View File

@ -66,6 +66,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateLinearGradient(const OH_Dr
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {
@ -88,6 +92,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateLinearGradientWithLocalMat
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {
@ -110,6 +118,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateRadialGradient(const OH_Dr
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {
@ -130,6 +142,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateRadialGradientWithLocalMat
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {
@ -150,6 +166,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateSweepGradient(const OH_Dra
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {
@ -170,6 +190,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateImageShader(OH_Drawing_Ima
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (tileX < CLAMP || tileX > DECAL || tileY < CLAMP || tileY > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
if (cMatrix == nullptr) {
Matrix matrix;
return (OH_Drawing_ShaderEffect*)new ShaderEffect(ShaderEffect::ShaderEffectType::IMAGE, CastToImage(*cImage),
@ -188,6 +212,10 @@ OH_Drawing_ShaderEffect* OH_Drawing_ShaderEffectCreateTwoPointConicalGradient(co
g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
return nullptr;
}
if (cTileMode < CLAMP || cTileMode > DECAL) {
g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
return nullptr;
}
std::vector<ColorQuad> colorsVector;
std::vector<scalar> posVector;
for (uint32_t i = 0; i < size; i++) {

View File

@ -1094,14 +1094,6 @@ void OH_Drawing_SetTypographyTextEllipsisModal(OH_Drawing_TypographyStyle* style
#else
ConvertToOriginalText<TypographyStyle>(style)->ellipsisModal = rosenEllipsisModal;
#endif
if (!ConvertToOriginalText<TypographyStyle>(style)->ellipsizedForNDK) {
#ifndef USE_GRAPHIC_TEXT_GINE
ConvertToOriginalText<TypographyStyle>(style)->ellipsis_ = TypographyStyle::ELLIPSIS;
#else
ConvertToOriginalText<TypographyStyle>(style)->ellipsis = TypographyStyle::ELLIPSIS;
#endif
ConvertToOriginalText<TypographyStyle>(style)->ellipsizedForNDK = true;
}
}
double OH_Drawing_TypographyGetLineHeight(OH_Drawing_Typography* typography, int lineNumber)
@ -1875,7 +1867,6 @@ void OH_Drawing_SetTypographyTextEllipsis(OH_Drawing_TypographyStyle* style, con
#else
ConvertToOriginalText<TypographyStyle>(style)->ellipsis = u16Ellipsis;
#endif
ConvertToOriginalText<TypographyStyle>(style)->ellipsizedForNDK = true;
}
void OH_Drawing_TextStyleSetBackgroundRect(OH_Drawing_TextStyle* style, const OH_Drawing_RectStyle_Info* rectStyleInfo,
@ -3474,4 +3465,15 @@ void OH_Drawing_TypographyDestroyTextBox(OH_Drawing_TextBox* textBox)
}
delete textRectArr;
textRectArr = nullptr;
}
void OH_Drawing_TextStyleAddFontVariation(OH_Drawing_TextStyle* style, const char* axis, const float value)
{
if (style == nullptr || axis == nullptr) {
return;
}
TextStyle* convertStyle = ConvertToOriginalText<TextStyle>(style);
if (convertStyle) {
convertStyle->fontVariations.SetAxisValue(axis, value);
}
}

View File

@ -39,6 +39,7 @@ class DRAWING_API Font {
public:
Font();
Font(std::shared_ptr<Typeface> typeface, scalar size, scalar scaleX, scalar skewX);
Font(const Font& font);
virtual ~Font() = default;
/**
@ -148,7 +149,7 @@ public:
* @brief Returns Typeface if set, or nullptr.
* @return Typeface if previously set, nullptr otherwise.
*/
std::shared_ptr<Typeface> GetTypeface();
std::shared_ptr<Typeface> GetTypeface() const;
/**
* @brief Get font edge pixels pattern.
@ -238,6 +239,20 @@ public:
*/
scalar MeasureText(const void* text, size_t byteLength, TextEncoding encoding, Rect* bounds = nullptr) const;
/**
* @brief Measure the width of a single character.
* @param unicode unicode encoding of a single character.
* @return The width of a single character.
*/
scalar MeasureSingleCharacter(int32_t unicode) const;
/**
* @brief Gets a font where you can draw a single character.
* @param unicode unicode encoding of a single character.
* @return A pointer to font, if nullptr is returned, get failed.
*/
std::shared_ptr<Font> GetFallbackFont(int32_t unicode) const;
int CountText(const void* text, size_t byteLength, TextEncoding encoding) const;
template<typename T>

View File

@ -62,7 +62,7 @@ public:
static bool GetDrawingTestSkiaEnabled();
static bool GetDrawingTestRecordingEnabled();
static unsigned long long GetUpTime(bool addCount = true);
static long long GetUpTime(bool addCount = true);
static void SetCaculateSwitch(bool start = true);

View File

@ -334,6 +334,29 @@ void CoreCanvas::DrawTextBlob(const TextBlob* blob, const scalar x, const scalar
DRAW_API_WITH_PAINT_LOOPER(DrawTextBlob, blob, x, y);
}
void CoreCanvas::DrawSingleCharacter(int32_t unicode, const Font& font, scalar x, scalar y)
{
std::function<void(int, const Font&)> drawSingleCharacterProc = [&](int currentGlyph, const Font& currentFont) {
TextBlobBuilder textBlobBuilder;
const TextBlobBuilder::RunBuffer& runBuffer = textBlobBuilder.AllocRunPos(currentFont, 1);
runBuffer.glyphs[0] = currentGlyph;
runBuffer.pos[0] = 0;
runBuffer.pos[1] = 0;
std::shared_ptr<TextBlob> textBlob = textBlobBuilder.Make();
DrawTextBlob(textBlob.get(), x, y);
};
uint16_t glyph = font.UnicharToGlyph(unicode);
if (glyph != 0) {
drawSingleCharacterProc(glyph, font);
} else {
std::shared_ptr<Font> fallbackFont = font.GetFallbackFont(unicode);
if (fallbackFont) {
uint16_t fallbackGlyph = fallbackFont->UnicharToGlyph(unicode);
drawSingleCharacterProc(fallbackGlyph, *fallbackFont);
}
}
}
void CoreCanvas::DrawSymbol(const DrawingHMSymbolData& symbol, Point locate)
{
DRAW_API_WITH_PAINT(DrawSymbol, symbol, locate);

View File

@ -61,7 +61,6 @@ enum class QuadAAFlags {
ALL_QUADAAFLAGS = 15,
};
const int DIVES_SIZE = 2;
#undef TRANSPARENT
struct Lattice {
enum RectType : uint8_t {
@ -69,13 +68,13 @@ struct Lattice {
TRANSPARENT,
FIXEDCOLOR,
};
int fXDivs[DIVES_SIZE];
int fYDivs[DIVES_SIZE];
RectType fRectTypes = RectType::DEFAULT;
int* fXDivs = nullptr;
int* fYDivs = nullptr;
RectType* fRectTypes = nullptr;
int fXCount;
int fYCount;
RectI fBounds;
Color fColors;
RectI* fBounds = nullptr;
Color* fColors = nullptr;
};
enum CacheType : uint8_t {
@ -468,6 +467,21 @@ public:
*/
virtual void DrawTextBlob(const TextBlob* blob, const scalar x, const scalar y);
/**
* @brief blob contains glyphs, their positions, and paint attributes specific to text:
* Typeface, text size, text scale x, text skew x, anti-alias, fake bold,
* font embedded bitmaps, pen/brush full hinting spacing, LCD text, linear text,
* and subpixel text. TextEncoding must be set to TextEncoding::GLYPH_ID.
* Elements of pen/brush: anti-alias, BlendMode, color including alpha,
* ColorFilter, MaskFilter, PathEffect, Shader, and Brush::Style; apply to blob.
* If attach pen to draw text, set Pen::Cap, Pen::Join, and stroke width;
* apply to Path created from blob.
* @param blob glyphs, positions, and their paints' text size, typeface, and so on
* @param x horizontal offset applied to blob
* @param y vertical offset applied to blob
*/
void DrawSingleCharacter(int32_t unicode, const Font& font, scalar x, scalar y);
// symbol
virtual void DrawSymbol(const DrawingHMSymbolData& symbol, Point locate);

View File

@ -371,6 +371,16 @@ std::unique_ptr<FontImpl> ImplFactory::CreateFontImpl(std::shared_ptr<Typeface>
return EngineImplFactory::CreateFont(typeface, size, scaleX, skewX);
}
std::unique_ptr<FontImpl> ImplFactory::CreateFontImpl(const Font& font)
{
#ifdef ENABLE_DDGR_OPTIMIZE
if (SystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
return DDGRImplFactory::CreateFont(font);
}
#endif
return EngineImplFactory::CreateFont(font);
}
std::unique_ptr<TextBlobBuilderImpl> ImplFactory::CreateTextBlobBuilderImpl()
{
#ifdef ENABLE_DDGR_OPTIMIZE

View File

@ -93,6 +93,7 @@ public:
static std::unique_ptr<FontImpl> CreateFontImpl();
static std::unique_ptr<FontImpl> CreateFontImpl(std::shared_ptr<Typeface> typeface,
scalar size, scalar scaleX, scalar skewX);
static std::unique_ptr<FontImpl> CreateFontImpl(const Font& font);
static std::unique_ptr<TextBlobBuilderImpl> CreateTextBlobBuilderImpl();
static std::shared_ptr<FontMgrImpl> CreateDefaultFontMgrImpl();
#ifndef USE_TEXGINE

View File

@ -51,7 +51,7 @@ public:
virtual void GetWidths(const uint16_t glyphs[], int count, scalar widths[]) const = 0;
virtual void GetWidths(const uint16_t glyphs[], int count, scalar widths[], Rect bounds[]) const = 0;
virtual scalar GetSize() const = 0;
virtual std::shared_ptr<Typeface> GetTypeface() = 0;
virtual std::shared_ptr<Typeface> GetTypeface() const = 0;
virtual FontEdging GetEdging() const = 0;
virtual FontHinting GetHinting() const = 0;

View File

@ -563,22 +563,29 @@ void SkiaCanvas::DrawImageLattice(const Image* image, const Lattice& lattice, co
return;
}
}
const SkCanvas::Lattice::RectType skRectType =
static_cast<const SkCanvas::Lattice::RectType>(lattice.fRectTypes);
SkIRect skCenter = SkIRect::MakeLTRB(lattice.fBounds.GetLeft(), lattice.fBounds.GetTop(),
lattice.fBounds.GetRight(), lattice.fBounds.GetBottom());
const SkIRect* skBounds = reinterpret_cast<const SkIRect*>(lattice.fBounds);
int count = (lattice.fXCount + 1) * (lattice.fYCount + 1);
std::vector<SkCanvas::Lattice::RectType> skRectTypes = {};
if (lattice.fRectTypes != nullptr) {
skRectTypes.resize(count);
for (int i = 0; i < count; ++i) {
skRectTypes[i] = static_cast<SkCanvas::Lattice::RectType>(lattice.fRectTypes[i]);
}
}
std::vector<SkColor> skColors = {};
if (lattice.fColors != nullptr) {
skColors.resize(count);
for (int i = 0; i < count; ++i) {
skColors[i] = static_cast<SkColor>(lattice.fColors[i].CastToColorQuad());
}
}
SkCanvas::Lattice skLattice = {lattice.fXDivs, lattice.fYDivs,
skRectTypes.empty() ? nullptr : skRectTypes.data(),
lattice.fXCount, lattice.fYCount, skBounds,
skColors.empty() ? nullptr : skColors.data()};
SkColor color = lattice.fColors.CastToColorQuad();
const int xdivs[] = {lattice.fXDivs[0], lattice.fXDivs[1]};
const int ydivs[] = {lattice.fYDivs[0], lattice.fYDivs[1]};
SkCanvas::Lattice skLattice = {xdivs, ydivs,
&skRectType,
lattice.fXCount, lattice.fYCount,
&skCenter, &color};
const SkRect* skDst = reinterpret_cast<const SkRect*>(&dst);
SkFilterMode skFilterMode = static_cast<SkFilterMode>(filter);
skPaint_ = defaultPaint_;

View File

@ -208,11 +208,11 @@ void SkiaCanvasAutoCache::ShowDrawResult(const SkRect& bound)
#ifdef OPINC_ENABLE_FEATURE_DEBUG
std::vector<SkRect>& drawAreaRects = drawAreaRects_;
LOGD("opinc draw result %d, canvas w%d h%d, opNum%d, percent%d, cal%d, "
"node[%.2f %.2f %.2f %.2f] bound[%.2f %.2f %.2f %.2f] reject[%.2f %.2f %.2f %.2f]"
"bound[%.2f %.2f %.2f %.2f] unionDrawArea[%.2f %.2f %.2f %.2f]"
"rect num %d not support %d",
opCanCache_, proxy()->imageInfo().width(), proxy()->imageInfo().height(),
totalOpNums_, percent_, calNotSupport_,
bound.x(), bound.y(), bound.width(), bound().height(),
bound.x(), bound.y(), bound.width(), bound.height(),
unionDrawArea_.x(), unionDrawArea_.y(), unionDrawArea_.width(), unionDrawArea_.height(),
static_cast<int>(drawAreaRects.size()), static_cast<int>(debugNotSupportOps_.size()));
for (uint32_t i = 0; i < drawAreaRects.size(); i++) {

View File

@ -44,6 +44,18 @@ SkiaFont::SkiaFont(std::shared_ptr<Typeface> typeface, scalar size, scalar scale
skFont_ = SkFont(skiaTypeface->GetTypeface(), size, scaleX, skewX);
}
SkiaFont::SkiaFont(const Font& font) noexcept
{
auto skiaFont = font.GetImpl<SkiaFont>();
if (!skiaFont) {
skFont_ = SkFont();
LOGD("skiaFont nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
return;
}
typeface_ = skiaFont->typeface_;
skFont_ = skiaFont->skFont_;
}
void SkiaFont::SetEdging(FontEdging edging)
{
skFont_.setEdging(static_cast<SkFont::Edging>(edging));
@ -161,7 +173,7 @@ scalar SkiaFont::GetSize() const
return skFont_.getSize();
}
std::shared_ptr<Typeface> SkiaFont::GetTypeface()
std::shared_ptr<Typeface> SkiaFont::GetTypeface() const
{
return typeface_;
}

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