mcu_hi3321_watch/tjd/ui/app/main/TjdUiAppFloatWindowBlend.cpp
2025-05-26 20:15:20 +08:00

687 lines
26 KiB
C++

/*----------------------------------------------------------------------------
* Copyright (c) TJD Technologies Co., Ltd. 2024. All rights reserved.
*
* Description:
*
* Author: huangshuyi
*
* Create: 2024-7
*--------------------------------------------------------------------------*/
#include "TjdUiAppFloatWindowBlend.h"
#include "TjdUiAppIds.h"
#include "TjdUiAppMainView.h"
#include "TjdUiImageIds.h"
#include "cmath"
#include "common/image_cache_manager.h"
#include "common/screen.h"
#include "components/root_view.h"
#include "dock/vibrator_manager.h"
#include "draw/draw_utils.h"
#include "engines/gfx/lite_m_gfx_engine.h"
#include "gfx_utils/heap_base.h"
#include "imgdecode/image_load.h"
#include "sql_setting.h"
#include "sys_config.h"
#include <string>
using namespace OHOS;
#define ENABLE_PRINT_INFO 1
#if ENABLE_PRINT_INFO
#define static_print_info(...) sys_ui_log_i(__VA_ARGS__) // 一般信息打印宏控制
#define static_print_warn(...) sys_ui_log_w(__VA_ARGS__) // 警告信息打印一般常开
#define static_print_error(...) sys_ui_log_e(__VA_ARGS__) // 错误信息打印一般常开
#else
#define static_print_info(...)
#define static_print_warn(...)
#define static_print_error(...)
#endif
namespace TJD {
#define FLOAT_WINDOW_BIN_PATH TJD_IMAGE_PATH "/img_main_floatwindow.bin"
#define IMAGE_WINDOW_WIDTH 76
#define IMAGE_ICON_WIDTH (76)
#define FLOATWINDOW_IMAGE_BG_X 218
#define FLOATWINDOW_IMAGE_BG_Y 195
#define FLOATWINDOW_IMAGE_BG_WIDTH 228
#define FLOATWINDOW_IMAGE_BG_HEIGHT 250
#define FLOAT_WINDOW_VIEWID "floatWindow"
struct iconFixInfo
{
TjdUiAppViewId sliceId; //点击进入的Slice的ID
int imageId;
const char *name;
};
struct iconInfo
{
iconFixInfo fixInfo;
double angle;
Rect area;
// 默认构造函数
iconInfo() : fixInfo{TJD_APP_VIEW_INVALID, 0, nullptr}, angle(0.0), area() {}
};
static uint8_t displayNum = 4;
static bool needCycle_ = false;
static uint8_t isInit = 0;
static const iconFixInfo g_fixInfoArray[] = {
{TJD_APP_VIEW_HR, IMG_MAIN_FLOATWINDOW_HEARTRATE, "hr"},
{TJD_APP_VIEW_SPO2, IMG_MAIN_FLOATWINDOW_SPO2, "spo2"},
{TJD_APP_VIEW_SPORT, IMG_MAIN_FLOATWINDOW_SPORT, "sport"},
{TJD_APP_VIEW_PLAYER, IMG_MAIN_FLOATWINDOW_MUSIC, "music"},
{TJD_APP_VIEW_SLEEP, IMG_MAIN_FLOATWINDOW_SLEEP, "sleep"},
{TJD_APP_VIEW_STRESS, IMG_MAIN_FLOATWINDOW_PRESSURE, "pressure"},
{TJD_APP_VIEW_BREATHING, IMG_MAIN_FLOATWINDOW_BREATHE, "breathe"},
{TJD_APP_VIEW_SPORT_RECORD, IMG_MAIN_FLOATWINDOW_SPORT_RECORD, "sport_record"},
{TJD_APP_VIEW_DAILYDATA, IMG_MAIN_FLOATWINDOW_DATA, "data"},
{TJD_APP_VIEW_PHONE, IMG_MAIN_FLOATWINDOW_PHONE, "phone"},
{TJD_APP_VIEW_MESSAGE_TOTAL, IMG_MAIN_FLOATWINDOW_MESSAGE, "message"},
{TJD_APP_VIEW_WEATHER, IMG_MAIN_FLOATWINDOW_WEATHER, "weather"},
{TJD_APP_VIEW_TIMER, IMG_MAIN_FLOATWINDOW_TIMER, "timer"},
{TJD_APP_VIEW_STOPWATCH, IMG_MAIN_FLOATWINDOW_STOPWATCH, "stopwatch"},
{TJD_APP_VIEW_ALARM, IMG_MAIN_FLOATWINDOW_CLOCK, "alarm"},
{TJD_APP_VIEW_CALCULATOR, IMG_MAIN_FLOATWINDOW_CALCULATOR, "calculator"},
{TJD_APP_VIEW_CALENDAR, IMG_MAIN_FLOATWINDOW_CALENDAR, "calendar"},
{TJD_APP_VIEW_COMPASS, IMG_MAIN_FLOATWINDOW_COMPASS, "compass"},
{TJD_APP_VIEW_RECORD, IMG_MAIN_FLOATWINDOW_RECORDING, "recording"},
{TJD_APP_VIEW_CAMERA, IMG_MAIN_FLOATWINDOW_CAMERA, "camera"},
{TJD_APP_VIEW_ALBUM, IMG_MAIN_FLOATWINDOW_PHOTO, "album"},
{TJD_APP_VIEW_EBOOK, IMG_MAIN_FLOATWINDOW_BOOK, "ebook"},
{TJD_APP_VIEW_BUSINESSCARD, IMG_MAIN_FLOATWINDOW_CARD, "businesscard"},
{TJD_APP_VIEW_WALLET, IMG_MAIN_FLOATWINDOW_WALLET, "wallet"},
{TJD_APP_VIEW_VIDEO_CTRL, IMG_MAIN_FLOATWINDOW_VIDEO, "video"},
{TJD_APP_VIEW_FEMALE, IMG_MAIN_FLOATWINDOW_PHYSIOLOGY, "physiology"},
{TJD_APP_VIEW_VOICE_ASSISTANT, IMG_MAIN_FLOATWINDOW_AI, "ai"},
{TJD_APP_VIEW_GAME, IMG_MAIN_FLOATWINDOW_GAME, "game"},
{TJD_APP_VIEW_SETTING, IMG_MAIN_FLOATWINDOW_SET, "setting"},
{TJD_APP_VIEW_LUCKY_CLOVER, IMG_MAIN_FLOATWINDOW_LEFUN, "lefun"},
{TJD_APP_VIEW_LEFUN_AI, IMG_MAIN_FLOATWINDOW_LEFUNAI, "lefunai"},
{TJD_APP_VIEW_MS_GAME, IMG_MAIN_FLOATWINDOW_SOMATOSENSORY, "somatosensory"},
{TJD_APP_VIEW_ALIPAY, IMG_MAIN_FLOATWINDOW_ALIPAY, "alipay"},
{TJD_APP_VIEW_PLAY_DIAL, IMG_MAIN_FLOATWINDOW_WATCHFACE, "watchface"},
{TJD_APP_VIEW_MAIN, IMG_MAIN_FLOATWINDOW_BAIDU, "baidu"},
};
static iconInfo *iconInfoPtr = nullptr;
static void CalculatePointOnCircle(double R, double angleDegrees, double &x, double &y, uint8_t isAbsCoor)
{
double adjustedAngle = 90.0 - angleDegrees;
if (adjustedAngle < 0) {
adjustedAngle += 360.0;
}
double radians = angleDegrees * UI_PI / 180.0;
double xRelative = R * sin(radians);
double yRelative = -R * cos(radians);
if (isAbsCoor) {
x = Screen::GetInstance().GetWidth() / 2 + xRelative;
y = Screen::GetInstance().GetWidth() / 2 + yRelative;
} else {
x = xRelative;
y = yRelative;
}
}
static double CalculateIconAngle(uint16_t CycleR, uint16_t iconR)
{
double ac = iconR;
double oc = CycleR - iconR;
double aoc = asin(ac / oc);
double angleDegrees = aoc * (180.0 / UI_PI);
return angleDegrees * 2;
}
double TjdUiAppFloatWindowBlend::FindCorrectIcon(void)
{
double iconStartAngle;
double iconEndAngle;
double diffAngle = 0;
const double iconGapAngle = angleReserve - angleIcon;
for (uint8_t elem : iconList) {
// printf("icon index:%d,name:%s,angle:%f\n", elem, imageIconArray[elem].name, imageIconArray[elem].angle);
iconStartAngle = iconInfoPtr[elem].angle - angleIcon / 2;
iconEndAngle = iconInfoPtr[elem].angle + angleIcon / 2;
if (startAngle > iconStartAngle && startAngle <= iconEndAngle) {
if (startAngle > iconInfoPtr[elem].angle) {
diffAngle = -(iconEndAngle - startAngle + iconGapAngle);
} else {
diffAngle = startAngle - iconStartAngle;
}
// printf("find correct icon:%s is need correct, diff angle:%f\n", imageIconArray[elem].name, diffAngle);
return diffAngle;
}
}
return startAngle - (iconInfoPtr[iconList.front()].angle - angleIcon / 2);
}
bool TjdUiAppFloatWindowBlend::OnDrag(OHOS::UIView &view, const OHOS::DragEvent &event)
{
if (floatWindowAnimator_.GetState() != OHOS::Animator::STOP) {
StopFloatWindowAnimator();
}
if (IsFloatWindowVisible() == true) {
int16_t yDiff = event.GetDeltaY();
RefreshDelta(yDiff);
UpdateFuchuang(yDiff, 0, false);
return true;
}
return false;
}
bool TjdUiAppFloatWindowBlend::OnDragEnd(OHOS::UIView &view, const OHOS::DragEvent &event)
{
if (IsFloatWindowVisible() == true) {
OHOS::Point last = event.GetPreLastPoint();
OHOS::Point current = event.GetLastPoint();
if ((last.x == current.x) && (last.y == current.y)) {
last = current;
current = event.GetCurrentPos();
}
DragThrowAnimator(current, last, event.GetDragDirection());
}
return true;
}
bool TjdUiAppFloatWindowBlend::OnRotate(OHOS::UIView &view, const OHOS::RotateEvent &event)
{
if (floatWindowAnimator_.GetState() != OHOS::Animator::STOP) {
StopFloatWindowAnimator();
}
if (IsFloatWindowVisible() == true) {
lastRotate_ = event.GetRotate();
RefreshDelta(lastRotate_);
UpdateFuchuang(lastRotate_, 0, false);
int16_t x = FLOATWINDOW_IMAGE_BG_X + FLOATWINDOW_IMAGE_BG_WIDTH - IMAGE_WINDOW_WIDTH / 2; // 218 + 228 - 38 =
// 408
int16_t y = FLOATWINDOW_IMAGE_BG_Y + IMAGE_WINDOW_WIDTH / 2; // 195 + 38 = 230
const Point point = {x, y};
int curImageId = 0;
for (uint8_t elem : iconList) {
if (iconInfoPtr[elem].area.IsContains(point)) {
curImageId = iconInfoPtr[elem].fixInfo.imageId;
break;
}
}
if (lastImageId_ != -1 && curImageId != 0 && curImageId != lastImageId_) {
#if ENABLE_VIBRATOR
OHOS::VibratorFunc vibratorFunc = OHOS::VibratorManager::GetInstance()->GetVibratorFunc();
vibratorFunc(OHOS::VibratorType::VIBRATOR_TYPE_ONE);
#endif
}
lastImageId_ = curImageId;
return true;
}
return false;
}
bool TjdUiAppFloatWindowBlend::OnRotateEnd(OHOS::UIView &view, const OHOS::RotateEvent &event)
{
if (IsFloatWindowVisible() == true) {
DragThrowAnimator({0, 0}, {0, 0},
lastRotate_ > 0 ? OHOS::DragEvent::DIRECTION_TOP_TO_BOTTOM
: OHOS::DragEvent::DIRECTION_BOTTOM_TO_TOP);
}
return true;
}
bool TjdUiAppFloatWindowBlend::OnClick(OHOS::UIView &view, const OHOS::ClickEvent &event)
{
std::string viewId = view.GetViewId();
if (viewId == FLOAT_WINDOW_VIEWID) {
HideFloatWindow();
} else {
const Point point = {event.GetCurrentPos().x, event.GetCurrentPos().y};
for (uint8_t elem : iconList) {
if (iconInfoPtr[elem].area.IsContains(point)) {
OHOS::NativeAbility::GetInstance().ChangeSlice(iconInfoPtr[elem].fixInfo.sliceId);
break;
}
}
}
return true;
}
void TjdUiAppFloatWindowBlend::HideFloatWindow()
{
TjdUiAppMainView *mainView = TjdUiAppMainView::GetInstance();
if (mainView == nullptr) {
return;
}
SetVisible(false);
ClearBackgroundBlur();
ClearFocus();
// auto wfBase = dynamic_cast<TjdUiWfBase *>(mainView->GetViewByCardId(TJD_MAIN_PAGE_WATCH_FACE));
// if (wfBase->IsDialView()) {
// auto *dial = wfBase->GetDialViewGroup();
// if (dial != nullptr) {
// dial->OnActive();
// }
// } else {
// wfBase->OnActive();
// }
}
void TjdUiAppFloatWindowBlend::ShowFloatWindow()
{
TjdUiAppMainView *mainView = TjdUiAppMainView::GetInstance();
if (mainView == nullptr) {
return;
}
// auto wfBase = dynamic_cast<TjdUiWfBase *>(mainView->GetViewByCardId(TJD_MAIN_PAGE_WATCH_FACE));
// if (wfBase->IsDialView()) {
// auto *dial = wfBase->GetDialViewGroup();
// if (dial != nullptr) {
// dial->OnInactive();
// }
// } else {
// wfBase->OnInactive();
// }
SetVisible(true);
OHOS::RootView::GetInstance()->ClearBlurView(OHOS::RootView::GetInstance()->GetBlurView());
SetBackgroundBlur(32);
SetFullScreenBlur(false);
OHOS::FocusManager::GetInstance()->ClearFocus();
RequestFocus();
// TjdUiAppMainPageWf::GetInstance()->HideSystemViewIcon();
mainView->GetWfCommon()->HideSystemViewIcon();
}
bool TjdUiAppFloatWindowBlend::IsFloatWindowVisible(void) { return IsVisible(); }
TjdUiAppFloatWindowBlend::TjdUiAppFloatWindowBlend()
: floatWindowAnimator_(&floatWindowAnimatorCallback_, nullptr, 0, true)
{
floatWindowAnimatorCallback_.SetFloatWindowBlend(this);
uint8_t sliceNum;
isInit = 0;
const uint16_t *sliceId = sql_setting_get_floating_window_map(&sliceNum);
needCycle_ = false;
if (sliceNum <= 4) {
sliceNum = 4;
needCycle_ = true;
}
if (sliceNum == 4) {
iconInfoPtr = new iconInfo[sliceNum + 1];
} else {
iconInfoPtr = new iconInfo[sliceNum];
}
for (uint8_t i = 0; i < sliceNum; i++) {
uint8_t m = sizeof(g_fixInfoArray) / sizeof(g_fixInfoArray[0]);
uint8_t j;
for (j = 0; j < m; j++) {
if (sliceId[i] == g_fixInfoArray[j].sliceId) {
iconInfoPtr[i].fixInfo = g_fixInfoArray[j];
break;
}
}
if (j == m) {
iconInfoPtr[i].fixInfo = g_fixInfoArray[i];
}
}
if (sliceNum == 4) {
sliceNum = 5;
iconInfoPtr[4].fixInfo = iconInfoPtr[0].fixInfo;
}
SetIntercept(true);
SetViewId(FLOAT_WINDOW_VIEWID);
SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
SetDirection(1);
SetPosition(0, 0);
SetWidth(Screen::GetInstance().GetWidth());
SetHeight(Screen::GetInstance().GetHeight());
SetOnDragListener(this);
SetOnClickListener(this);
SetOnRotateListener(this);
imageFloatWindow = new UIImageView();
imageFloatWindow->SetOnClickListener(this);
imageFloatWindow->SetTouchable(true);
imageFloatWindow->SetIntercept(true);
Add(imageFloatWindow);
imageFloatWindow->SetPosition(FLOATWINDOW_IMAGE_BG_X, FLOATWINDOW_IMAGE_BG_Y);
ImageInfo *bgImgInfo;
bgImgInfo = ImageCacheManager::GetInstance().LoadOneInMultiRes(IMG_MAIN_FLOATWINDOW_BG, FLOAT_WINDOW_BIN_PATH);
finalImgInfo = new ImageInfo();
finalImgInfo->cacheNode = nullptr;
finalImgInfo->header.width = bgImgInfo->header.width;
finalImgInfo->header.height = bgImgInfo->header.height;
finalImgInfo->header.colorMode = ARGB8888;
finalImgInfo->header.compressMode = COMPRESS_MODE_NONE;
finalImgInfo->dataSize = ALIGN_BYTE(finalImgInfo->header.width, BYTE_ALIGNMENT) * finalImgInfo->header.height *
DrawUtils::GetByteSizeByColorMode(ARGB8888);
finalImgInfo->data = reinterpret_cast<uint8_t *>(ImageCacheMalloc(*finalImgInfo));
uint8_t *non_const_data = const_cast<uint8_t *>(finalImgInfo->data);
for (uint32_t i = 0; i < finalImgInfo->dataSize; i += 4) {
non_const_data[i] = 0x96;
non_const_data[i + 1] = 0x97;
non_const_data[i + 2] = 0x97;
non_const_data[i + 3] = 0x0;
}
// memset(const_cast<uint8_t*>(finalImgInfo->data), (uint32_t)0x00ffffff, finalImgInfo->dataSize / 4);
finalImgInfo->phyAddr = finalImgInfo->data;
// clang-format off
Rect dstRect(0, 0, finalImgInfo->header.width - 1, finalImgInfo->header.height - 1);
bgDstBufferInfo.mode = ARGB8888;
bgDstBufferInfo.width = bgImgInfo->header.width;
bgDstBufferInfo.height = bgImgInfo->header.height;
bgDstBufferInfo.stride = ALIGN_BYTE(bgDstBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(ARGB8888);
bgDstBufferInfo.phyAddr = const_cast<uint8_t *>(finalImgInfo->data);
bgDstBufferInfo.virAddr = const_cast<uint8_t *>(finalImgInfo->data);
bgDstBufferInfo.compressMode = COMPRESS_MODE_NONE;
bgDstBufferInfo.rect = dstRect;
bgDstBufferInfo.color = 0;
bgSrcBufferInfo.mode = (ColorMode)bgImgInfo->header.colorMode;
bgSrcBufferInfo.width = bgImgInfo->header.width;
bgSrcBufferInfo.height = bgImgInfo->header.height;
bgSrcBufferInfo.stride = ALIGN_BYTE(bgSrcBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(bgSrcBufferInfo.mode);
bgSrcBufferInfo.phyAddr = const_cast<uint8_t *>(bgImgInfo->data);
bgSrcBufferInfo.virAddr = const_cast<uint8_t *>(bgImgInfo->data);
bgSrcBufferInfo.compressMode = bgImgInfo->header.compressMode;
Rect bgSrcRect(0, 0, bgSrcBufferInfo.width - 1, bgSrcBufferInfo.height - 1);
bgSrcBufferInfo.rect = bgSrcRect;
bgSrcBufferInfo.color = 0;
BlendOption opt1;
opt1.opacity = OPA_OPAQUE;
opt1.mode = BlendMode::BLEND_SRC_OVER;
// clang-format on
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, bgSrcBufferInfo, bgSrcRect, opt1);
#if ENABLE_VGU_ENGINE
LiteMGfxEngine::GetInstance()->SyncHwDraw();
#endif
// clang-format off
arcCenterX = Screen::GetInstance().GetWidth() / 2;
arcCenterY = Screen::GetInstance().GetHeight() / 2;
arcOuterRedius = Screen::GetInstance().GetWidth() / 2 - 20;
angleIcon = CalculateIconAngle(arcOuterRedius, IMAGE_WINDOW_WIDTH / 2);
startAngle = acos(MATH_ABS((arcCenterY - FLOATWINDOW_IMAGE_BG_Y)) / (arcOuterRedius - IMAGE_WINDOW_WIDTH / 2)) * 180 / UI_PI;
endAngle = 180 + asin(MATH_ABS((arcCenterX - FLOATWINDOW_IMAGE_BG_X)) / (arcOuterRedius - IMAGE_WINDOW_WIDTH / 2)) * 180 / UI_PI;
angleReserve = (endAngle - startAngle - angleIcon) / (displayNum - 1);
// clang-format on
uint8_t cnt = sliceNum;
iconList.clear();
for (uint8_t i = 0; i < cnt; i++) {
iconList.push_back(i);
}
UpdateFuchuang(0, 0, false);
imageFloatWindow->SetSrc(finalImgInfo);
}
TjdUiAppFloatWindowBlend::~TjdUiAppFloatWindowBlend()
{
ClearFocus();
ClearBackgroundBlur();
if (finalImgInfo) {
ImageCacheFree(*finalImgInfo);
delete finalImgInfo;
finalImgInfo = nullptr;
}
if (iconInfoPtr) {
delete[] iconInfoPtr;
iconInfoPtr = nullptr;
}
}
void TjdUiAppFloatWindowBlend::UpdateFuchuang(int16_t diffy, double angle, bool isUsedAngle)
{
double angleDiff;
if (isUsedAngle) {
angleDiff = angle;
const double EPSILON = 1e-6;
if (angleDiff < EPSILON) {
diffy = -1;
} else {
diffy = 1;
}
} else {
angleDiff = diffy * 0.4;
}
if (LiteMGfxEngine::GetInstance()->IsAsyncModeEnabled()) {
LiteMGfxEngine::GetInstance()->Flush(Rect(0, 0, 0, 0));
}
Rect bgSrcRect(0, 0, bgSrcBufferInfo.width - 1, bgSrcBufferInfo.height - 1);
BlendOption opt1;
opt1.opacity = OPA_OPAQUE;
opt1.mode = BlendMode::BLEND_SRC_OVER;
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, bgSrcBufferInfo, bgSrcRect, opt1);
int16_t IconX, IconY;
double x_temp, y_temp;
int16_t iconContainerOffsetX;
int16_t iconContainerOffsetY;
iconContainerOffsetX = FLOATWINDOW_IMAGE_BG_X - arcCenterX;
iconContainerOffsetY = FLOATWINDOW_IMAGE_BG_Y - arcCenterY;
if (MATH_ABS(angleDiff) > angleReserve) {
if (angleDiff < 0) {
angleDiff = -angleReserve + 10;
} else {
angleDiff = angleReserve - 10;
}
}
for (uint8_t elem : iconList) {
BufferInfo logoBufferInfo;
ImageInfo *imgInfo = ImageCacheManager::GetInstance().LoadOneInMultiRes(iconInfoPtr[elem].fixInfo.imageId,
FLOAT_WINDOW_BIN_PATH);
logoBufferInfo.mode = (ColorMode)imgInfo->header.colorMode;
logoBufferInfo.width = imgInfo->header.width;
logoBufferInfo.height = imgInfo->header.height;
uint16_t fgWidth = imgInfo->header.width;
uint16_t fgHeight = imgInfo->header.height;
logoBufferInfo.stride =
ALIGN_BYTE(logoBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(logoBufferInfo.mode);
logoBufferInfo.phyAddr = const_cast<uint8_t *>(imgInfo->data);
logoBufferInfo.virAddr = const_cast<uint8_t *>(imgInfo->data);
logoBufferInfo.compressMode = imgInfo->header.compressMode;
Rect logoBufferInfoRect(0, 0, logoBufferInfo.width - 1, logoBufferInfo.height - 1);
BlendOption opt2;
opt2.opacity = OPA_OPAQUE;
opt2.mode = BlendMode::BLEND_SRC_ATOP;
Rect srcInDstRect;
//
if (isInit == 0) {
iconInfoPtr[elem].angle = startAngle + angleIcon / 2 + angleReserve * elem;
} else {
iconInfoPtr[elem].angle += angleDiff;
}
if (iconInfoPtr[elem].angle < startAngle - angleIcon / 2 ||
iconInfoPtr[elem].angle > endAngle + angleIcon / 2) {
// continue;
}
CalculatePointOnCircle(arcOuterRedius - IMAGE_WINDOW_WIDTH / 2, iconInfoPtr[elem].angle, x_temp, y_temp, 1);
IconX = (int16_t)x_temp - IMAGE_ICON_WIDTH / 2 - FLOATWINDOW_IMAGE_BG_X;
IconY = (int16_t)y_temp - IMAGE_ICON_WIDTH / 2 - FLOATWINDOW_IMAGE_BG_Y;
//如果图标完全超出背景图范围
if (IconX < -IMAGE_ICON_WIDTH || IconY < -IMAGE_ICON_WIDTH) {
continue;
}
uint16_t real_w, real_h;
real_w = logoBufferInfo.width;
real_h = logoBufferInfo.height;
logoBufferInfo.rect.SetX(0);
logoBufferInfo.rect.SetY(0);
if (IconX < 0) {
real_w = real_w + IconX;
logoBufferInfo.rect.SetX(MATH_ABS(IconX));
IconX = 0;
}
if (IconY < 0) {
real_h = real_h + IconY;
logoBufferInfo.rect.SetY(MATH_ABS(IconY));
IconY = 0;
}
if (real_w == 0 || real_h == 0) {
continue;
}
logoBufferInfo.rect.SetWidth(real_w);
logoBufferInfo.rect.SetHeight(real_h);
uint16_t absX = x_temp - IMAGE_ICON_WIDTH / 2;
uint16_t absY = y_temp - IMAGE_ICON_WIDTH / 2;
iconInfoPtr[elem].area.SetRect(absX, (uint16_t)absY, (uint16_t)absX + IMAGE_ICON_WIDTH - 1,
(uint16_t)absY + IMAGE_ICON_WIDTH - 1);
srcInDstRect.SetX(IconX);
srcInDstRect.SetY(IconY);
srcInDstRect.SetWidth(real_w);
srcInDstRect.SetHeight(real_h);
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, logoBufferInfo, srcInDstRect, opt2);
}
isInit = 1;
#if ENABLE_VGU_ENGINE
LiteMGfxEngine::GetInstance()->SyncHwDraw();
#endif
imageFloatWindow->Invalidate();
#if 1
if (diffy < 0) {
if ((iconInfoPtr[iconList.front()].angle + angleIcon / 2) < startAngle) {
double angleLast = iconInfoPtr[iconList.back()].angle;
iconInfoPtr[iconList.front()].angle = angleLast + angleReserve;
iconList.splice(iconList.end(), iconList, iconList.begin());
if (needCycle_ == true) {
iconInfoPtr[iconList.back()].fixInfo = iconInfoPtr[iconList.front()].fixInfo;
}
}
} else if (diffy > 0) {
auto it = iconList.begin();
std::advance(it, displayNum - 1);
if ((iconInfoPtr[*it].angle + angleIcon / 2) > endAngle) {
double angleFirst = iconInfoPtr[iconList.front()].angle;
iconInfoPtr[iconList.back()].angle = angleFirst - angleReserve;
auto lastElementIt = std::prev(iconList.end());
iconList.splice(iconList.begin(), iconList, lastElementIt);
if (needCycle_ == true) {
it = iconList.begin();
std::advance(it, displayNum - 1);
iconInfoPtr[iconList.front()].fixInfo = iconInfoPtr[iconList.back()].fixInfo;
}
}
}
#endif
}
void TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::Callback(OHOS::UIView *view)
{
if (instance_ == nullptr) {
return;
}
if (instance_->SlideOrAutoAlign_ == 1) {
curtTime_++;
if (curtTime_ <= dragTimes_) {
double f = CubicEaseOut1(startValueY_, endValueY_, curtTime_, dragTimes_);
instance_->UpdateFuchuang(0, f - previousValueY_, true);
previousValueY_ = f;
} else {
instance_->StopFloatWindowAnimator();
}
} else {
curtTime_++;
if (curtTime_ <= dragTimes_) {
bool needStopY = false;
if (startValueY__ != endValueY__) {
int16_t actY = easingFunc_(startValueY__, endValueY__, curtTime_, dragTimes_);
instance_->UpdateFuchuang(actY - previousValueY__, 0, false);
if (IsNeedReCalculateDragEnd()) {
double angle = instance_->FindCorrectIcon();
instance_->StartAutoAlignAnimator(angle);
}
previousValueY__ = actY;
} else {
needStopY = true;
}
if (needStopY) {
instance_->StopFloatWindowAnimator();
}
} else {
instance_->StopFloatWindowAnimator();
}
}
}
void TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::OnStop(OHOS::UIView &view)
{
int16_t x = FLOATWINDOW_IMAGE_BG_X + FLOATWINDOW_IMAGE_BG_WIDTH - IMAGE_WINDOW_WIDTH / 2; // 218 + 228 - 38 =
// 408
int16_t y = FLOATWINDOW_IMAGE_BG_Y + IMAGE_WINDOW_WIDTH / 2; // 195 + 38 = 230
const Point point = {x, y};
int curImageId = 0;
for (uint8_t elem : instance_->iconList) {
if (iconInfoPtr[elem].area.IsContains(point)) {
instance_->lastImageId_ = iconInfoPtr[elem].fixInfo.imageId;
break;
}
}
}
bool TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::IsNeedReCalculateDragEnd()
{
int16_t animationLess = 0;
animationLess = endValueY__ - previousValueY__;
if ((MATH_ABS(animationLess) > 10)) {
return false;
}
return true;
}
double TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::CubicEaseOut1(double startPos, double endPos,
uint16_t curTime, uint16_t durationTime)
{
if (curTime < durationTime) {
float t = static_cast<float>(curTime) / durationTime;
float x = 1.0f - powf(1.0f - t, 3.0f); // 计算1 - (1 - t)^3
return startPos + x * (endPos - startPos);
}
return endPos;
}
void TjdUiAppFloatWindowBlend::StartSlideAnimator(int16_t dragDistanceY)
{
SlideOrAutoAlign_ = 0;
int16_t dragTimes = MATH_ABS(dragDistanceY) / DRAG_TIMES_COEFFICIENT;
if (dragTimes < MIN_DRAG_TIMES) {
dragTimes = MIN_DRAG_TIMES;
}
floatWindowAnimatorCallback_.ResetCallback();
floatWindowAnimatorCallback_.SetDragStartValue(static_cast<int16_t>(0));
floatWindowAnimatorCallback_.SetDragEndValue(dragDistanceY);
floatWindowAnimatorCallback_.SetDragTimes(dragTimes * DRAG_ACC_FACTOR / GetDragACCLevel());
floatWindowAnimator_.Start();
}
void TjdUiAppFloatWindowBlend::StartAutoAlignAnimator(double diffAngle)
{
SlideOrAutoAlign_ = 1;
int16_t dragTimes = MATH_ABS(diffAngle);
if (dragTimes < MIN_DRAG_TIMES) {
dragTimes = MIN_DRAG_TIMES;
}
floatWindowAnimatorCallback_.ResetCallback();
floatWindowAnimatorCallback_.SetDragStartValue(static_cast<double>(0));
floatWindowAnimatorCallback_.SetDragEndValue(diffAngle);
floatWindowAnimatorCallback_.SetDragTimes(dragTimes);
floatWindowAnimator_.Start();
}
void TjdUiAppFloatWindowBlend::StopFloatWindowAnimator() { floatWindowAnimator_.Stop(); }
} // namespace TJD