mirror of
https://gitee.com/openharmony/arkui_ace_engine
synced 2024-11-23 07:01:24 +00:00
!39562 组件截图:新增getSync接口
Merge pull request !39562 from 胡清云/0802_getSync
This commit is contained in:
commit
6782e5f6ea
@ -105,6 +105,7 @@ constexpr int32_t ERROR_CODE_NON_EXIST = 150003;
|
||||
|
||||
// ComponentSnapshot error code
|
||||
constexpr int32_t ERROR_CODE_COMPONENT_SNAPSHOT_IMAGE_LOAD_ERROR = 160001;
|
||||
constexpr int32_t ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT = 160002;
|
||||
|
||||
// FromHtml error code
|
||||
constexpr int32_t ERROR_CODE_FROM_HTML_CONVERT_ERROR = 170001;
|
||||
|
@ -110,6 +110,12 @@ class ComponentSnapshot {
|
||||
__JSScopeUtil__.restoreInstanceId();
|
||||
}
|
||||
}
|
||||
getSync(id, options) {
|
||||
__JSScopeUtil__.syncInstanceId(this.instanceId_);
|
||||
let pixelmap = this.ohos_componentSnapshot.getSync(id, options);
|
||||
__JSScopeUtil__.restoreInstanceId();
|
||||
return pixelmap;
|
||||
}
|
||||
}
|
||||
|
||||
class DragController {
|
||||
|
@ -3366,6 +3366,15 @@ void FrontendDelegateDeclarative::GetSnapshot(
|
||||
#endif
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> FrontendDelegateDeclarative::GetSyncSnapshot(
|
||||
const std::string& componentId, const NG::SnapshotOptions& options)
|
||||
{
|
||||
#ifdef ENABLE_ROSEN_BACKEND
|
||||
return NG::ComponentSnapshot::GetSync(componentId, options);
|
||||
#endif
|
||||
return {ERROR_CODE_INTERNAL_ERROR, nullptr};
|
||||
}
|
||||
|
||||
void FrontendDelegateDeclarative::CreateSnapshot(
|
||||
std::function<void()>&& customBuilder, NG::ComponentSnapshot::JsCallback&& callback, bool enableInspector,
|
||||
const NG::SnapshotParam& param)
|
||||
|
@ -285,6 +285,9 @@ public:
|
||||
std::function<void(std::shared_ptr<Media::PixelMap>, int32_t, std::function<void()>)>&& callback,
|
||||
bool enableInspector, const NG::SnapshotParam& param) override;
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetSyncSnapshot(const std::string& componentId,
|
||||
const NG::SnapshotOptions& options) override;
|
||||
|
||||
void AddFrameNodeToOverlay(
|
||||
const RefPtr<NG::FrameNode>& node, std::optional<int32_t> index = std::nullopt) override;
|
||||
void RemoveFrameNodeOnOverlay(const RefPtr<NG::FrameNode>& node) override;
|
||||
|
@ -1175,6 +1175,15 @@ void FrontendDelegateDeclarativeNG::GetSnapshot(
|
||||
#endif
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> FrontendDelegateDeclarativeNG::GetSyncSnapshot(
|
||||
const std::string& componentId, const NG::SnapshotOptions& options)
|
||||
{
|
||||
#ifdef ENABLE_ROSEN_BACKEND
|
||||
return NG::ComponentSnapshot::GetSync(componentId, options);
|
||||
#endif
|
||||
return {ERROR_CODE_INTERNAL_ERROR, nullptr};
|
||||
}
|
||||
|
||||
std::string FrontendDelegateDeclarativeNG::GetContentInfo(ContentInfoType type)
|
||||
{
|
||||
auto jsonContentInfo = JsonUtil::Create(true);
|
||||
|
@ -223,6 +223,9 @@ public:
|
||||
std::function<void(std::shared_ptr<Media::PixelMap>, int32_t, std::function<void()>)>&& callback,
|
||||
bool enableInspector, const NG::SnapshotParam& param) override;
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetSyncSnapshot(const std::string& componentId,
|
||||
const NG::SnapshotOptions& options) override;
|
||||
|
||||
void AddFrameNodeToOverlay(
|
||||
const RefPtr<NG::FrameNode>& node, std::optional<int32_t> index = std::nullopt) override;
|
||||
void RemoveFrameNodeOnOverlay(const RefPtr<NG::FrameNode>& node) override;
|
||||
|
@ -238,6 +238,12 @@ public:
|
||||
bool enableInspector, const NG::SnapshotParam& param)
|
||||
{}
|
||||
|
||||
virtual std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetSyncSnapshot(const std::string& componentId,
|
||||
const NG::SnapshotOptions& options)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual bool GetAssetContent(const std::string& url, std::string& content) = 0;
|
||||
virtual bool GetAssetContent(const std::string& url, std::vector<uint8_t>& content) = 0;
|
||||
virtual std::string GetAssetPath(const std::string& url) = 0;
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "transaction/rs_interfaces.h"
|
||||
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/log_wrapper.h"
|
||||
#include "base/utils/utils.h"
|
||||
#include "bridge/common/utils/utils.h"
|
||||
@ -34,6 +35,9 @@
|
||||
|
||||
namespace OHOS::Ace::NG {
|
||||
namespace {
|
||||
|
||||
constexpr std::chrono::duration<int, std::milli> SNAPSHOT_TIMEOUT_DURATION(3000);
|
||||
|
||||
class CustomizedCallback : public Rosen::SurfaceCaptureCallback {
|
||||
public:
|
||||
CustomizedCallback(ComponentSnapshot::JsCallback&& jsCallback, WeakPtr<FrameNode> node)
|
||||
@ -86,6 +90,45 @@ public:
|
||||
private:
|
||||
ComponentSnapshot::NormalCallback callback_;
|
||||
};
|
||||
|
||||
class SyncCustomizedCallback : public Rosen::SurfaceCaptureCallback {
|
||||
public:
|
||||
SyncCustomizedCallback() = default;
|
||||
~SyncCustomizedCallback() override = default;
|
||||
void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelMap) override
|
||||
{
|
||||
if (!pixelMap) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Internal error! The pixelmap returned by the system is null");
|
||||
pixelMap_ = nullptr;
|
||||
} else {
|
||||
TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"ComponentSnapshot successful! pixelMap.width=%{public}d pixelMap.height=%{public}d",
|
||||
pixelMap->GetWidth(), pixelMap->GetHeight());
|
||||
pixelMap_ = pixelMap;
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cv_.notify_all();
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetPixelMap()
|
||||
{
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
auto status = cv_.wait_for(lock, SNAPSHOT_TIMEOUT_DURATION);
|
||||
if (status == std::cv_status::timeout) {
|
||||
return { ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT, nullptr };
|
||||
}
|
||||
if (pixelMap_) {
|
||||
result = { ERROR_CODE_NO_ERROR, pixelMap_ };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
std::shared_ptr<Media::PixelMap> pixelMap_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void ProcessImageNode(const RefPtr<UINode>& node)
|
||||
@ -93,7 +136,7 @@ void ProcessImageNode(const RefPtr<UINode>& node)
|
||||
if (node->GetTag() == V2::IMAGE_ETS_TAG) {
|
||||
auto imageNode = AceType::DynamicCast<FrameNode>(node);
|
||||
if (imageNode && AceType::DynamicCast<ImagePattern>(imageNode->GetPattern())) {
|
||||
auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
|
||||
auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
|
||||
imagePattern->SetIsComponentSnapshotNode();
|
||||
imagePattern->OnVisibleAreaChange(true);
|
||||
}
|
||||
@ -111,7 +154,7 @@ bool CheckImageSuccessfullyLoad(const RefPtr<UINode>& node, int32_t& imageCount)
|
||||
imageCount++;
|
||||
auto imageNode = AceType::DynamicCast<FrameNode>(node);
|
||||
CHECK_NULL_RETURN(imageNode, false);
|
||||
auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
|
||||
auto imagePattern = AceType::DynamicCast<ImagePattern>(imageNode->GetPattern());
|
||||
CHECK_NULL_RETURN(imagePattern, false);
|
||||
auto imageLoadContext = imagePattern->GetImageLoadingContext().Upgrade();
|
||||
CHECK_NULL_RETURN(imageLoadContext, false);
|
||||
@ -179,8 +222,9 @@ void ComponentSnapshot::Get(const std::string& componentId, JsCallback&& callbac
|
||||
return;
|
||||
}
|
||||
TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"Get ComponentSnapshot key=%{public}s Id=%{public}d Tag=%{public}s RsNodeId=%{public}" PRIu64 "",
|
||||
componentId.c_str(), node->GetId(), node->GetTag().c_str(), rsNode->GetId());
|
||||
"Get ComponentSnapshot key=%{public}s options=%{public}s Id=%{public}d Tag=%{public}s "
|
||||
"RsNodeId=%{public}" PRIu64 "",
|
||||
componentId.c_str(), options.ToString().c_str(), node->GetId(), node->GetTag().c_str(), rsNode->GetId());
|
||||
auto& rsInterface = Rosen::RSInterfaces::GetInstance();
|
||||
rsInterface.TakeSurfaceCaptureForUI(rsNode, std::make_shared<CustomizedCallback>(std::move(callback), nullptr),
|
||||
options.scale, options.scale, options.waitUntilRenderFinished);
|
||||
@ -275,4 +319,54 @@ void ComponentSnapshot::BuilerTask(JsCallback&& callback, const RefPtr<FrameNode
|
||||
std::make_shared<CustomizedCallback>(std::move(callback), enableInspector ? node : nullptr),
|
||||
param.options.scale, param.options.scale, param.options.waitUntilRenderFinished);
|
||||
}
|
||||
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> ComponentSnapshot::GetSync(const std::string& componentId,
|
||||
const SnapshotOptions& options)
|
||||
{
|
||||
CHECK_RUN_ON(UI);
|
||||
ACE_SCOPED_TRACE("ComponentSnapshot::GetSyncStart_%s", componentId.c_str());
|
||||
std::pair<int32_t, std::shared_ptr<Media::PixelMap>> result(ERROR_CODE_INTERNAL_ERROR, nullptr);
|
||||
auto node = Inspector::GetFrameNodeByKey(componentId);
|
||||
if (!node) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"Can't find a component that id or key are %{public}s, Please check your parameters are correct",
|
||||
componentId.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
auto rsNode = GetRsNode(node);
|
||||
|
||||
if (node->GetIsLayoutNode()) {
|
||||
std::list<RefPtr<FrameNode>> children;
|
||||
node->GetOneDepthVisibleFrame(children);
|
||||
if (children.empty()) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"Children is empty from FrameNode(InspectorId=%{public}s Id=%{public}d)",
|
||||
componentId.c_str(), node->GetId());
|
||||
return result;
|
||||
}
|
||||
node = children.front();
|
||||
rsNode = GetRsNode(children.front());
|
||||
}
|
||||
|
||||
if (!rsNode) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"RsNode is null from FrameNode(InspectorId=%{public}s Id=%{public}d)",
|
||||
componentId.c_str(), node->GetId());
|
||||
return result;
|
||||
}
|
||||
TAG_LOGI(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"GetSync ComponentSnapshot key=%{public}s options=%{public}s Id=%{public}d Tag=%{public}s "
|
||||
"RsNodeId=%{public}" PRIu64 "",
|
||||
componentId.c_str(), options.ToString().c_str(), node->GetId(), node->GetTag().c_str(), rsNode->GetId());
|
||||
auto& rsInterface = Rosen::RSInterfaces::GetInstance();
|
||||
auto syncCallback = std::make_shared<SyncCustomizedCallback>();
|
||||
{
|
||||
ACE_SCOPED_TRACE("ComponentSnapshot::GetSync_TakeSurfaceCaptureForUI_%s_%d_%" PRIu64 "", componentId.c_str(),
|
||||
node->GetId(), rsNode->GetId());
|
||||
}
|
||||
rsInterface.TakeSurfaceCaptureForUI(rsNode, syncCallback,
|
||||
options.scale, options.scale, options.waitUntilRenderFinished);
|
||||
return syncCallback->GetPixelMap();
|
||||
}
|
||||
} // namespace OHOS::Ace::NG
|
||||
|
@ -35,6 +35,9 @@ public:
|
||||
bool flag = true);
|
||||
static void GetNormalCapture(const RefPtr<FrameNode>& frameNode, NormalCallback&& callback);
|
||||
|
||||
static std::pair<int32_t, std::shared_ptr<Media::PixelMap>> GetSync(const std::string& componentId,
|
||||
const SnapshotOptions& options);
|
||||
|
||||
private:
|
||||
static std::shared_ptr<Rosen::RSNode> GetRsNode(const RefPtr<FrameNode>& node);
|
||||
static void PostDelayedTaskOfBuiler(const RefPtr<TaskExecutor>& executor, JsCallback&& callback,
|
||||
|
@ -29,6 +29,10 @@ struct SnapshotOptions {
|
||||
bool waitUntilRenderFinished;
|
||||
explicit SnapshotOptions(float scale = DEFAULT_SNAPSHOT_SCALE, bool waitUntilRenderFinished = false)
|
||||
: scale(scale), waitUntilRenderFinished(waitUntilRenderFinished) {}
|
||||
std::string ToString() const
|
||||
{
|
||||
return "{" + std::to_string(scale) + ", " + (waitUntilRenderFinished ? "true}" : "false}");
|
||||
}
|
||||
};
|
||||
struct SnapshotParam {
|
||||
int32_t delay;
|
||||
|
@ -302,7 +302,7 @@ static napi_value JSSnapshotGet(napi_env env, napi_callback_info info)
|
||||
auto delegate = EngineHelper::GetCurrentDelegateSafely();
|
||||
if (!delegate) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"Can'nt get delegate of ace_engine. param: %{public}s",
|
||||
"Can't get delegate of ace_engine. param: %{public}s",
|
||||
componentId.c_str());
|
||||
auto callback = helper.CreateCallback(&result);
|
||||
callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
|
||||
@ -334,7 +334,7 @@ static napi_value JSSnapshotFromBuilder(napi_env env, napi_callback_info info)
|
||||
napi_value result = nullptr;
|
||||
auto delegate = EngineHelper::GetCurrentDelegateSafely();
|
||||
if (!delegate) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Can'nt get delegate of ace_engine. ");
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Can't get delegate of ace_engine. ");
|
||||
auto callback = helper.CreateCallback(&result);
|
||||
callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
|
||||
return nullptr;
|
||||
@ -353,11 +353,67 @@ static napi_value JSSnapshotFromBuilder(napi_env env, napi_callback_info info)
|
||||
return result;
|
||||
}
|
||||
|
||||
static napi_value JSSnapshotGetSync(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_escapable_handle_scope scope = nullptr;
|
||||
napi_open_escapable_handle_scope(env, &scope);
|
||||
|
||||
JsComponentSnapshot helper(env, info);
|
||||
|
||||
napi_value result = nullptr;
|
||||
|
||||
if (!helper.CheckArgs(napi_valuetype::napi_string)) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of string type.");
|
||||
napi_close_escapable_handle_scope(env, scope);
|
||||
return result;
|
||||
}
|
||||
|
||||
// parse id
|
||||
std::string componentId;
|
||||
napi_valuetype valueType = napi_null;
|
||||
GetNapiString(env, helper.GetArgv(0), componentId, valueType);
|
||||
|
||||
auto delegate = EngineHelper::GetCurrentDelegateSafely();
|
||||
if (!delegate) {
|
||||
TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
|
||||
"Can't get delegate of ace_engine. param: %{public}s",
|
||||
componentId.c_str());
|
||||
NapiThrow(env, "Delegate is null", ERROR_CODE_INTERNAL_ERROR);
|
||||
napi_close_escapable_handle_scope(env, scope);
|
||||
return result;
|
||||
}
|
||||
|
||||
NG::SnapshotOptions options;
|
||||
helper.ParseParamForGet(options);
|
||||
|
||||
auto pair = delegate->GetSyncSnapshot(componentId, options);
|
||||
|
||||
switch (pair.first) {
|
||||
case ERROR_CODE_NO_ERROR :
|
||||
#ifdef PIXEL_MAP_SUPPORTED
|
||||
result = Media::PixelMapNapi::CreatePixelMap(env, pair.second);
|
||||
#endif
|
||||
break;
|
||||
case ERROR_CODE_INTERNAL_ERROR :
|
||||
napi_get_null(env, &result);
|
||||
NapiThrow(env, "Internal error!", ERROR_CODE_INTERNAL_ERROR);
|
||||
break;
|
||||
case ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT :
|
||||
napi_get_null(env, &result);
|
||||
NapiThrow(env, "ComponentSnapshot timeout!", ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
napi_escape_handle(env, scope, result, &result);
|
||||
napi_close_escapable_handle_scope(env, scope);
|
||||
return result;
|
||||
}
|
||||
|
||||
static napi_value ComponentSnapshotExport(napi_env env, napi_value exports)
|
||||
{
|
||||
napi_property_descriptor snapshotDesc[] = {
|
||||
DECLARE_NAPI_FUNCTION("get", JSSnapshotGet),
|
||||
DECLARE_NAPI_FUNCTION("createFromBuilder", JSSnapshotFromBuilder),
|
||||
DECLARE_NAPI_FUNCTION("getSync", JSSnapshotGetSync),
|
||||
};
|
||||
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(snapshotDesc) / sizeof(snapshotDesc[0]), snapshotDesc));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user