/**
 * @file hv_mw_OsdAnimation.c
 * @brief osd MiddleWare animation c file.
 * @details This file provides the following functions: \n
 *          (1) Osd animation functions \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2024-02-20
 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author       <th>Date            <th>Change Description
 * <tr><td>zhangjing     <td>2024-02-20      <td>create
 * </table>
 */

#include "hv_comm_DataBase.h"
#include "hv_mw_PQ.h"
#include "hv_app_PQ.h"
#include "hv_mw_SystemManager.h"
#include "hv_mw_Channel_Manager.h"
#include "hv_mw_OsdComm.h"
#include "hv_mw_OsdLog.h"
#include "hv_mw_OsdInit.h"
#include "hv_mw_OsdDraw.h"
#include "hv_mw_OsdEvent.h"
#include "hv_mw_OsdOperation.h"
#include "hv_mw_OsdInterrupt.h"
#include "hv_mw_OsdAnimation.h"
#include "hv_drv_Osd.h"
#include "hv_drv_OsdLogo.h"
#include "hv_drv_OsdRotate.h"
#include "hv_drv_DpuCommon.h"

#if (HV_PROJECT_CONFIG_OSD_ANIMITION_SUPPORT == HV_CONFIG_ON)

#define ANIMATION_TIMEOUT 0
#define ANIMATION_LASTTIME 1

typedef struct _OsdAnimManager {
    /* 当前存在运行中的Animition */
    BOOL bAnimitionDoing;
    /* 当前Animition链表 */
    struct LinkedList stAnimitionList;
} OsdAnimManager;

static OsdAnimManager s_stOsdAnimData;


VOID Hv_Mw_OsdAnimInit(VOID)
{
    s_stOsdAnimData.bAnimitionDoing = HV_FALSE;
    Hv_Comm_LinkedList_Init(&s_stOsdAnimData.stAnimitionList);
}

VOID Hv_Mw_OsdAnimDefaultExecCbFn(OsdAnimition *pstAnimParam)
{
    //OSD_LOG_INFO("Default Execute Callback Function running.");
}

VOID Hv_Mw_OsdAnimDefaultFinishCbFn(OsdAnimition *pstAnimParam)
{
    //OSD_LOG_INFO("Default Finish Callback Function running.");
}

OsdAnimition *Hv_Mw_OsdAnimCreate(OsdAnimitionParam *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_RET(pstAnimParam, NULL);

    OsdAnimition *pstAnimNode = NULL;
    pstAnimNode = HV_MALLOC_OBJECT(OsdAnimition);
    HV_ASSERT_VALID_PTR_RET(pstAnimNode, NULL);

    HV_MEMCPY(pstAnimNode, pstAnimParam, sizeof(OsdAnimition));
    //pstAnimNode->usDelayTime = pstAnimParam->usDelayTime;
    //pstAnimNode->usDurationTime = pstAnimParam->usDurationTime;
    //pstAnimNode->usStart = pstAnimParam->usStart;
    //pstAnimNode->usEnd = pstAnimParam->usEnd;
    //pstAnimNode->enCurveType = pstAnimParam->enCurveType;
    //pstAnimNode->UserParam = pstAnimParam->UserParam;
    pstAnimNode->ExecuteCbFn = ((pstAnimParam->ExecuteCbFn == NULL) ? Hv_Mw_OsdAnimDefaultExecCbFn : (pstAnimParam->ExecuteCbFn));
    pstAnimNode->FinishCbFn = ((pstAnimParam->FinishCbFn == NULL) ? Hv_Mw_OsdAnimDefaultFinishCbFn : (pstAnimParam->FinishCbFn));

    pstAnimNode->bRunning = HV_FALSE;
    pstAnimNode->usRemainTime = pstAnimNode->usDurationTime;

    OSD_LOG_DEBUG("Creat animition, usDelayTime = %d, usDurationTime = %d, usRemainTime = %d, bRunning = %d",
                    pstAnimNode->usDelayTime, pstAnimNode->usDurationTime, pstAnimNode->usRemainTime, pstAnimNode->bRunning);

    /* add item to scene's ItemShowList */
    Hv_Comm_LinkedList_Init(&pstAnimNode->stNode);
    Hv_Comm_LinkedList_AddTail(&s_stOsdAnimData.stAnimitionList, &pstAnimNode->stNode);

    Hv_Mw_OsdDrawSetFrameModify(HV_TRUE);
    s_stOsdAnimData.bAnimitionDoing = HV_TRUE;

    return pstAnimNode;
}

VOID Hv_Mw_OsdAnimTerminal()
{
    UINT32 uiTimeout = 0;

    while (HV_TRUE == Hv_Mw_OsdAnimIsDoing())
    {
        Hv_Mw_OsdDoAnimition();
        uiTimeout++;
        if (uiTimeout > 0xffff)
        {
            OSD_LOG_INFO("Timeout error for animation terminal!");
            break;
        }
    }
}

BOOL Hv_Mw_OsdAnimIsExisted(OsdAnimition *pstAnimNode)
{
    HV_ASSERT_VALID_PTR_RET(pstAnimNode, HV_FALSE);

    OsdAnimition *pstTargetAnimiton = NULL;
    struct LinkedList *pstNode = NULL;
    Hv_Comm_LinkedList_ForEach(&s_stOsdAnimData.stAnimitionList, pstNode)
    {
        pstTargetAnimiton = Hv_Comm_LinkedList_Entry(pstNode, OsdAnimition, stNode);

        /* 如果找到匹配的节点指针，则返回 true */
        if ((pstAnimNode == pstTargetAnimiton) && (pstAnimNode->ucOperateType == pstTargetAnimiton->ucOperateType)) //TODO: add AnimID
        {
            OSD_LOG_DEBUG("Found node addr 0x%x", pstTargetAnimiton);
            return HV_TRUE;
        }
    }
    return HV_FALSE;
}

VOID Hv_Mw_OsdAnimDestroy(OsdAnimition *pstAnimNode)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimNode);

    if (Hv_Mw_OsdAnimIsExisted(pstAnimNode))
    {
        OSD_LOG_DEBUG("Destory AnimNode 0x%x", pstAnimNode);
        Hv_Comm_LinkedList_Del(&s_stOsdAnimData.stAnimitionList, &pstAnimNode->stNode);
        HV_FREE_OBJECT(pstAnimNode);
    }
}

BOOL Hv_Mw_OsdAnimIsDoing(VOID)
{
    return s_stOsdAnimData.bAnimitionDoing;
}

static Status Hv_Mw_OsdDoOneAnimition(OsdAnimition *pstAnimiton)
{
    HV_ASSERT_VALID_PTR(pstAnimiton);
    HV_ASSERT_TRUE(pstAnimiton->usDurationTime >= pstAnimiton->usRemainTime);
    HV_ASSERT_TRUE(pstAnimiton->usRemainTime > 0);

    /* 更新动画运行前的延时时间 */
    if (ANIMATION_TIMEOUT == pstAnimiton->usDelayTime)
    {
        OSD_LOG_DEBUG("Anim begin.");
        pstAnimiton->bRunning = HV_TRUE;
    }
    else
    {
        pstAnimiton->usDelayTime--;
    }

    if (HV_FALSE == pstAnimiton->bRunning)
    {
        return HV_FAILURE;
    }

    /* 执行动画更新函数，更新动画运行剩余时间 */
    if (NULL != pstAnimiton->ExecuteCbFn)
    {
        pstAnimiton->ExecuteCbFn(pstAnimiton);
    }
    if (INVALID_PARAM_USHORT16 != pstAnimiton->usRemainTime)
    {
        pstAnimiton->usRemainTime--;
    }

    /* 执行动画结束函数，释放动画节点 */
    if (ANIMATION_TIMEOUT == pstAnimiton->usRemainTime)
    {
        pstAnimiton->bRunning = HV_FALSE;
        if (NULL != pstAnimiton->FinishCbFn)
        {
            /* 释放用户malloc数据 */
            pstAnimiton->FinishCbFn(pstAnimiton);
        }
        Hv_Mw_OsdAnimDestroy(pstAnimiton);
        OSD_LOG_DEBUG("Anim finish.");
    }

    OSD_LOG_DEBUG("Anim update, usDelayTime = %d, usDurationTime = %d, usRemainTime = %d, bRunning = %d",
                  pstAnimiton->usDelayTime, pstAnimiton->usDurationTime, pstAnimiton->usRemainTime, pstAnimiton->bRunning);

    return HV_SUCCESS;
}

/* 遍历所有动画节点并更新 */
Status Hv_Mw_OsdDoAnimition(VOID)
{
    OsdAnimition *pstAnimiton = NULL;
    struct LinkedList *pstNode = NULL;
    struct LinkedList *pstTempNode = NULL;
    UCHAR8 ucCount = 0;

    Hv_Comm_LinkedList_ForEachSafe(&s_stOsdAnimData.stAnimitionList, pstTempNode, pstNode)
    {
        pstAnimiton = Hv_Comm_LinkedList_Entry(pstNode, OsdAnimition, stNode);
        OSD_LOG_DEBUG("Do animition[%d], addr 0x%x", ucCount, pstAnimiton);

        Hv_Mw_OsdDoOneAnimition(pstAnimiton);

        ucCount++;
    }

    if (!Hv_Comm_LinkedList_IsEmpty(&s_stOsdAnimData.stAnimitionList))
    {
        s_stOsdAnimData.bAnimitionDoing = HV_TRUE;
    }
    else
    {
        OSD_LOG_DEBUG("All anim finished, anim list is empty!");
        s_stOsdAnimData.bAnimitionDoing = HV_FALSE;
    }

    /* 驱动osd状态机运转 */
    if (ucCount > 0)
    {
        Hv_Mw_OsdDrawSetFrameModify(HV_TRUE);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

VOID Hv_Mw_OsdAnimFinish(OsdAnimition *pstAnimNode)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimNode);

    UINT32 uiTimeout = 0;

    while (pstAnimNode->bRunning)
    {
        Hv_Mw_OsdDoOneAnimition(pstAnimNode);
        uiTimeout++;
        if (uiTimeout > 0xffff)
        {
            OSD_LOG_INFO("Timeout error for animation finish!");
            break;
        }
    }
}

VOID Hv_Mw_OsdAnimFinishAll(VOID)
{
    UINT32 uiTimeout = 0;

    while (HV_TRUE == Hv_Mw_OsdAnimIsDoing())
    {
        Hv_Mw_OsdDoAnimition();
        uiTimeout++;
        if (uiTimeout > 0xffff)
        {
            OSD_LOG_INFO("Timeout error for animation finish!");
            break;
        }
    }
}

VOID Hv_Mw_OsdAnimForceTerminal(OsdAnimition *pstAnimNode)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimNode);
    OSD_LOG_DEBUG("Force terminal anim");

    pstAnimNode->usRemainTime = ANIMATION_LASTTIME;
}

VOID Hv_Mw_OsdAnimSetAlpha(OsdUniversalAlphaType enType, UCHAR8 ucAlpha)
{
    OSD_LOG_DEBUG("osd trans = %d, alpha = %d", enType, ucAlpha);
    Hv_Drv_OsdBlend_SetUniversalAlpha(enType, ucAlpha);
}

/* 获取动态palette偏移地址，组件状态不同偏移不同因此需注意拿取动态偏移地址 */
USHORT16 Hv_Mw_OsdAnimGetCompPaletteOffset(OsdComponent stCp)
{
    HV_ASSERT_TRUE_RET(stCp.enType != OSD_CP_TYPE_NONE, 0);

    USHORT16 usPaletteOffset = 0;
    switch (stCp.enType)
    {
        case OSD_CP_TYPE_TEXT:
        {
            const OsdText *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_TEXT_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_TEXT_LIST:
        {
            const OsdTextList *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_TEXT_LIST_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_NUMBER:
        {
            const OsdNumber *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_NUMBER_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_ASCII_STRING:
        {
            const OsdAsciiString *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_ASCII_STRING_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_ICON:
        {
            const OsdIcon *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_ICON_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_ICON_LIST:
        {
            const OsdIconList *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_ICON_LIST_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->ucColorIndex;
            break;
        }
        case OSD_CP_TYPE_BMP:
        {
            const OsdBmp *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_BMP_PROP(stCp.usIndex);
            }
            usPaletteOffset = pstCpProp->usPaletteOffset;
            break;
        }
        default:
        {
            OSD_LOG_INFO("Error component for getting palette offset!");
            return 0;
        }
    }

    return usPaletteOffset;
}

/* 必须是dynamic组件 */
VOID Hv_Mw_OsdAnimSetCompPaletteOffset(OsdComponent stCp, USHORT16 usPaletteOffset)
{
    switch (stCp.enType)
    {
        case OSD_CP_TYPE_TEXT:
        {
            OsdText *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_TEXT_LIST:
        {
            OsdTextList *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_NUMBER:
        {
            OsdNumber *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_ASCII_STRING:
        {
            OsdAsciiString *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_ICON:
        {
            OsdIcon *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_ICON_LIST:
        {
            OsdIconList *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->ucColorIndex = usPaletteOffset;
            break;
        }
        case OSD_CP_TYPE_BMP:
        {
            OsdBmp *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            pstCpProp->usPaletteOffset = usPaletteOffset;
            break;
        }
        default:
        {
            OSD_LOG_INFO("Error component for setting palette offset!");
            return;
        }
    }
}

/* 获取组件原始palette颜色数据 */
VOID Hv_Mw_OsdAnimGetCompColor(USHORT16 usPaletteOffset, UINT32 *puiRGBTbl, CHAR8 ucRGBLen)
{
    HV_ASSERT_VALID_PTR_VOID(puiRGBTbl);

    HV_ASSERT_TRUE_VOID((usPaletteOffset + ucRGBLen) < 0x200);
    OSD_LOG_DEBUG("GetCpColor: usPaletteOffset = %d, ucRGBLen = %d", usPaletteOffset, ucRGBLen);

    UCHAR8 ucIdx = 0;
    for (ucIdx = 0; ucIdx < ucRGBLen; ucIdx++)
    {
        puiRGBTbl[ucIdx] = Hv_Drv_OsdPalette_GetPaletteColor(usPaletteOffset + ucIdx);
        OSD_LOG_DEBUG("[%d]:usPaletteOffset = %d, uiRGB = 0x%6x", ucIdx, usPaletteOffset + ucIdx, puiRGBTbl[ucIdx]);
    }
}

/* 必须是dynamic组件 */
VOID Hv_Mw_OsdAnimSetCompColor(OsdComponent stCp, USHORT16 usPaletteOffset, UINT32 *puiRGBTbl, CHAR8 ucRGBLen)
{
    HV_ASSERT_VALID_PTR_VOID(puiRGBTbl);
    HV_ASSERT_TRUE_VOID((usPaletteOffset + ucRGBLen) < 0x200);

    OsdWindow *pstWindow = Hv_Mw_OsdComponentGetWindow(stCp);
    HV_ASSERT_VALID_PTR_VOID(pstWindow);

    UCHAR8 ucIdx = 0;
    for (ucIdx = 0; ucIdx < ucRGBLen; ucIdx++)
    {
        Hv_Drv_OsdPalette_ChangeColor(pstWindow->ucPhyId, usPaletteOffset + ucIdx, puiRGBTbl[ucIdx]);
    }
}

UINT32 Hv_Mw_OsdAnimGetSingleColor(USHORT16 usPaletteOffset)
{
    UINT32 puiRGBTbl[1] = {0};
    CHAR8 ucRGBLen = 1;

    Hv_Mw_OsdAnimGetCompColor(usPaletteOffset, puiRGBTbl, ucRGBLen);
    return puiRGBTbl[0];
}

VOID Hv_Mw_OsdAnimSetSingleColor(OsdComponent stCp, USHORT16 usPaletteOffset, UINT32 uiRGB)
{
    UINT32 puiRGBTbl[1] = {uiRGB};
    CHAR8 ucRGBLen = 1;

    Hv_Mw_OsdAnimSetCompColor(stCp, usPaletteOffset, puiRGBTbl, ucRGBLen);

}

UCHAR8 Hv_Mw_OsdAnimGetCompNums(OsdComponent stCp)
{
    UCHAR8 ucNumber = 1;
    if (OSD_CP_TYPE_BMP_LIST == stCp.enType)
    {
        const OsdBmpList *pstCpProp = OSD_GET_BMP_LIST_PROP(stCp.usIndex);
        ucNumber = pstCpProp->ucBmpNum;
    }
    else if (OSD_CP_TYPE_ICON_LIST == stCp.enType)
    {
        const OsdIconList *pstCpProp = OSD_GET_ICON_LIST_PROP(stCp.usIndex);
        ucNumber = pstCpProp->ucIconNum;
    }
    else if (OSD_CP_TYPE_TEXT_LIST == stCp.enType)
    {
        const OsdTextList *pstCpProp = OSD_GET_TEXT_LIST_PROP(stCp.usIndex);
        ucNumber = pstCpProp->ucStringNum;
    }
    else
    {
        OSD_LOG_DEBUG("Not support cp: enType = %d", stCp.enType);
    }
    OSD_LOG_DEBUG("GetCompNums: Cp enType = %d, ucNumber = %d", stCp.enType, ucNumber);

    return ucNumber;
}

/* 从0开始计数 */
VOID Hv_Mw_OsdAnimSetCompTurns(OsdComponent stCp, CHAR8 ucCurNum)
{
    if (OSD_CP_TYPE_BMP_LIST == stCp.enType)
    {
        OsdBmpList *pstCpDynamicProp = (OsdBmpList *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
        HV_ASSERT_VALID_PTR_VOID(pstCpDynamicProp);
        pstCpDynamicProp->ucBmpCurID = ucCurNum;
    }
    else if (OSD_CP_TYPE_ICON_LIST == stCp.enType)
    {
        OsdIconList *pstCpDynamicProp = (OsdIconList *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
        HV_ASSERT_VALID_PTR_VOID(pstCpDynamicProp);
        pstCpDynamicProp->ucIconCurID = ucCurNum;
    }
    else if (OSD_CP_TYPE_TEXT_LIST == stCp.enType)
    {
        OsdTextList *pstCpDynamicProp = (OsdTextList *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
        HV_ASSERT_VALID_PTR_VOID(pstCpDynamicProp);
        pstCpDynamicProp->ucStringCurID = ucCurNum;
    }
    else
    {
        OSD_LOG_DEBUG("Not support cp: enType = %d", stCp.enType);
    }
}

USHORT16 Hv_Mw_OsdAnimGetTransparency(UCHAR8 ucTrans, UCHAR8 ucMaxTrans, UCHAR8 ucMaxRealTrans)
{
    HV_ASSERT_TRUE_RET(ucMaxTrans > 0, 0);
    HV_ASSERT_TRUE_RET(ucTrans <= ucMaxTrans, 0);
    USHORT16 usAlpha = LINEAR_MAPPING_VALUE(ucTrans, 0, ucMaxTrans, 0, ucMaxRealTrans);
    usAlpha = MIN(255, (255 * (100 - usAlpha) / 100));
    OSD_LOG_INFO("osd trans = %d, alpha = %d", ucTrans, usAlpha);
    return usAlpha;
}

VOID Hv_Mw_OsdAnimGetCompRange(OsdComponent stCp, AnimRangeParam *pstRangeParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstRangeParam);

    switch (stCp.enType)
    {
        case OSD_CP_TYPE_RECT:
        {
            const OsdRect *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_RECT_PROP(stCp.usIndex);
            }

            pstRangeParam->usX = pstCpProp->usX;
            pstRangeParam->usWidth = pstCpProp->usWidth;
            pstRangeParam->usY = pstCpProp->usY;
            pstRangeParam->usHeight = pstCpProp->usHeight;
            break;
        }
        case OSD_CP_TYPE_RECTGRID:
        {
            const OsdRectGrid *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_RECTGRID_PROP(stCp.usIndex);
            }

            pstRangeParam->usX = pstCpProp->usX;
            pstRangeParam->usWidth = pstCpProp->usWidth;
            pstRangeParam->usY = pstCpProp->usY;
            pstRangeParam->usHeight = pstCpProp->usHeight;
            break;
        }
        case OSD_CP_TYPE_LINE:
        {
            const OsdLine *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_LINE_PROP(stCp.usIndex);
            }

            pstRangeParam->usX = pstCpProp->usX;
            pstRangeParam->usWidth = pstCpProp->usWidth;
            pstRangeParam->usY = pstCpProp->usY;
            pstRangeParam->usHeight = pstCpProp->usHeight;
            break;
        }
        case OSD_CP_TYPE_LINEGRID:
        {
            const OsdLineGrid *pstCpProp = Hv_Mw_OsdComponentGetDynamicProp(stCp);
            if (NULL == pstCpProp)
            {
                pstCpProp = OSD_GET_LINEGRID_PROP(stCp.usIndex);
            }

            pstRangeParam->usX = pstCpProp->usX;
            pstRangeParam->usWidth = pstCpProp->usWidth;
            pstRangeParam->usY = pstCpProp->usY;
            pstRangeParam->usHeight = pstCpProp->usHeight;
            break;
        }
        default:
        {
            return;
        }
    }
}

/* 必须是dynamic组件 */
VOID Hv_Mw_OsdAnimSetCompRange(OsdComponent stCp, AnimRangeParam *pstRangeParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstRangeParam);

    switch (stCp.enType)
    {
        case OSD_CP_TYPE_RECT:
        {
            OsdRect *pstCpProp = (OsdRect *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usWidth)
            {
                pstCpProp->usX = pstRangeParam->usX;
                pstCpProp->usWidth = pstRangeParam->usWidth;
            }
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usHeight)
            {
                pstCpProp->usY = pstRangeParam->usY;
                pstCpProp->usHeight = pstRangeParam->usHeight;
            }
            break;
        }
        case OSD_CP_TYPE_RECTGRID:
        {
            OsdRectGrid *pstCpProp = (OsdRectGrid *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usWidth)
            {
                pstCpProp->usX = pstRangeParam->usX;
                pstCpProp->usWidth = pstRangeParam->usWidth;
            }
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usHeight)
            {
                pstCpProp->usY = pstRangeParam->usY;
                pstCpProp->usHeight = pstRangeParam->usHeight;
            }
            break;
        }
        case OSD_CP_TYPE_LINE:
        {
            OsdLine *pstCpProp = (OsdLine *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usWidth)
            {
                pstCpProp->usX = pstRangeParam->usX;
                pstCpProp->usWidth = pstRangeParam->usWidth;
            }
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usHeight)
            {
                pstCpProp->usY = pstRangeParam->usY;
                pstCpProp->usHeight = pstRangeParam->usHeight;
            }
            break;
        }
        case OSD_CP_TYPE_LINEGRID:
        {
            OsdLineGrid *pstCpProp = (OsdLineGrid *)Hv_Mw_OsdComponentGetDynamicProp(stCp);
            HV_ASSERT_VALID_PTR_VOID(pstCpProp);
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usWidth)
            {
                pstCpProp->usX = pstRangeParam->usX;
                pstCpProp->usWidth = pstRangeParam->usWidth;
            }
            if (INVALID_PARAM_USHORT16 != pstRangeParam->usHeight)
            {
                pstCpProp->usY = pstRangeParam->usY;
                pstCpProp->usHeight = pstRangeParam->usHeight;
            }
            break;
        }
        default:
        {
            return;
        }
    }

    OSD_LOG_DEBUG("SetCpSize: usX = %d, usY = %d, usWidth = %d, usHeight = %d",
                     pstRangeParam->usX, pstRangeParam->usY, pstRangeParam->usWidth, pstRangeParam->usHeight);
}

USHORT16 Hv_Mw_OsdAnimGetCompResourceSize(OsdComponent stCp)
{
    OsdComponentNode* pstNode = NULL;
    pstNode = Hv_Mw_OsdComponentGetNode(stCp);
    HV_ASSERT_VALID_PTR_RET(pstNode, 0);

    OsdResourceType enResourceType = Hv_Drv_OsdFont_GetComponentResourceType(pstNode);
    USHORT16 usResourceSize = 0;
    if (OSD_RESOURCE_TYPE_1BIT == enResourceType)
    {
        usResourceSize = 1;
    }
    else if (OSD_RESOURCE_TYPE_2BIT == enResourceType)
    {
        usResourceSize = 1 << 2;
    }
    else if (OSD_RESOURCE_TYPE_4BIT == enResourceType)
    {
        usResourceSize = 1 << 4;
    }
    else if (OSD_RESOURCE_TYPE_6BIT == enResourceType)
    {
        usResourceSize = 1 << 6;
    }
    else if (OSD_RESOURCE_TYPE_8BIT == enResourceType)
    {
        usResourceSize = 1 << 8;
    }
    else
    {
        usResourceSize = 1;
        OSD_LOG_INFO("Resource type error!");
    }

    return usResourceSize;
}

VOID Hv_Mw_OsdAnimSetItemPosition(USHORT16 usItemId, USHORT16 usX, USHORT16 usY)
{
    OsdItem* pstItem = OSD_GET_ITEM(usItemId);

    if (usX != INVALID_PARAM_USHORT16)
    {
        pstItem->usX = usX;
    }
    if (usY != INVALID_PARAM_USHORT16)
    {
        pstItem->usY = usY;
    }
    Hv_Mw_OsdItemSetPosition(usItemId, pstItem->usX, pstItem->usY);
}

USHORT16 Hv_Mw_OsdAnimCurveMapping(AnimCurveType enCurveType, AnimCurveMap *pstMapParam)
{
    HV_ASSERT_VALID_PTR_RET(pstMapParam, 0);
    HV_ASSERT_TRUE_RET(pstMapParam->usRemainTime > 0, 0);

    USHORT16 usCurValue = 0;
    USHORT16 usCurrentTime = 0;
    USHORT16 usMinValue = 0;
    USHORT16 usMaxValue = 0;

    if (pstMapParam->usStart < pstMapParam->usEnd)
    {
        usMinValue = pstMapParam->usStart;
        usMaxValue = pstMapParam->usEnd;
    }
    else
    {
        usMinValue = pstMapParam->usEnd;
        usMaxValue = pstMapParam->usStart;
    }

    switch (enCurveType)
    {
        case ANIM_CURVE_LINEAR:
        {
            if (pstMapParam->usStart < pstMapParam->usEnd)
            {
                usCurrentTime = pstMapParam->usDurationTime - pstMapParam->usRemainTime;
            }
            else
            {
                usCurrentTime = pstMapParam->usRemainTime - 1;
            }
            usCurValue = LINEAR_MAPPING_VALUE(usCurrentTime, 0, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue);
            break;
        }
        case ANIM_CURVE_EASE_IN:
        {
            usCurrentTime = pstMapParam->usDurationTime - pstMapParam->usRemainTime;
            if (pstMapParam->usStart < pstMapParam->usEnd)
            {
                usCurValue = EASE_MAPPING_VALUE(usCurrentTime, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue);
            }
            else
            {
                usCurValue = EASE2_MAPPING_VALUE(usCurrentTime, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue);
            }
            break;
        }
        case ANIM_CURVE_EASE_OUT:
        {
            usCurrentTime = pstMapParam->usRemainTime - 1;
            if (pstMapParam->usStart < pstMapParam->usEnd)
            {
                usCurValue = EASE2_MAPPING_VALUE(usCurrentTime, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue);
            }
            else
            {
                usCurValue = EASE_MAPPING_VALUE(usCurrentTime, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue);
            }
            break;
        }
        default:
        {
            break;
        }

    }

    OSD_LOG_DEBUG("CalculatePosition, usCurrentTime[%d], MaxTime[%d], usMinValue[%d], usMaxValue[%d], usCurValue:%d",
                   usCurrentTime, pstMapParam->usDurationTime - 1, usMinValue, usMaxValue, usCurValue);

    return usCurValue;
}

VOID Hv_Mw_OsdAnimUpdateScenePos(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    if (ANIM_POS_X == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        Hv_Mw_OsdSceneSetPosition(pstAnimParam->usId, usCurPos, INVALID_PARAM_USHORT16);
        OSD_LOG_DEBUG("UpdateSceneXPos, usCurPos:%d", usCurPos);
    }
    else if (ANIM_POS_Y == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        Hv_Mw_OsdSceneSetPosition(pstAnimParam->usId, INVALID_PARAM_USHORT16, usCurPos);
        OSD_LOG_DEBUG("UpdateSceneYPos, usCurPos:%d", usCurPos);
    }
    else
    {
        HV_ASSERT_VALID_PTR_VOID(pstAnimParam->UserParam);
        AnimCurveMap stXPosition = {pstAnimParam->usStart,
                                pstAnimParam->usEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurXPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stXPosition);

        AnimPosParam *pstAnimPosParam = (AnimPosParam *)pstAnimParam->UserParam;
        AnimCurveMap stYPosition = {pstAnimPosParam->usYStart,
                                pstAnimPosParam->usYEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurYPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stYPosition);

        Hv_Mw_OsdSceneSetPosition(pstAnimParam->usId, usCurXPos, usCurYPos);
        OSD_LOG_DEBUG("UpdateSceneXYPos, usXCurPos:%d, usYCurPos:%d", usCurXPos, usCurYPos);
    }
}

VOID Hv_Mw_OsdAnimUpdateSceneAlpha(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    AnimCurveMap stMapParam = {pstAnimParam->usStart,
                             pstAnimParam->usEnd,
                             pstAnimParam->usDurationTime,
                             pstAnimParam->usRemainTime};
    USHORT16 usCurAlpha = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
    Hv_Mw_OsdAnimSetAlpha(pstAnimParam->ucOperateType, usCurAlpha);
    OSD_LOG_DEBUG("SceneEnterAlphaAnimUpdate, scene usCuralpha:%d", usCurAlpha);
}

/* 支持除bmp以外的单色组件 */
VOID Hv_Mw_OsdAnimUpdateCompColor(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);
    AnimColorParam *pstAnimColorParam = (AnimColorParam *)pstAnimParam->UserParam;

    AnimCurveMap stMapParam = {0};
    UINT32 uiCurColor = 0;
    UCHAR8 ucCurR = 0;
    UCHAR8 ucCurG = 0;
    UCHAR8 ucCurB = 0;

    OsdComponent stCp = {pstAnimParam->ucElementType, pstAnimParam->usId};
    if ((pstAnimParam->usDurationTime == pstAnimParam->usRemainTime)
       && (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType))
    {
        Hv_Mw_OsdAnimSetCompPaletteOffset(stCp, pstAnimColorParam->usNewPalette);
        OSD_LOG_DEBUG("Set palette independent:  usNewPalette = %d", pstAnimColorParam->usNewPalette);
    }

    stMapParam.usDurationTime = pstAnimParam->usDurationTime;
    stMapParam.usRemainTime = pstAnimParam->usRemainTime;

    stMapParam.usStart = OSD_R(pstAnimColorParam->uiStart);
    stMapParam.usEnd = OSD_R(pstAnimColorParam->uiEnd);
    ucCurR = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

    stMapParam.usStart = OSD_G(pstAnimColorParam->uiStart);
    stMapParam.usEnd = OSD_G(pstAnimColorParam->uiEnd);
    ucCurG = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

    stMapParam.usStart = OSD_B(pstAnimColorParam->uiStart);
    stMapParam.usEnd = OSD_B(pstAnimColorParam->uiEnd);
    ucCurB = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

    uiCurColor = (((UINT32)ucCurB) << 16) | (((UINT32)ucCurG) << 8) | (((UINT32)ucCurR) << 0);
    OSD_LOG_DEBUG("UpdateCpColor: B = 0x%x, G = 0x%x, R = 0x%x, uiCurColor = 0x%06x", ucCurB, ucCurG, ucCurR, uiCurColor);

    if (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType)
    {
        Hv_Mw_OsdAnimSetSingleColor(stCp, pstAnimColorParam->usNewPalette, uiCurColor);
        OSD_LOG_DEBUG("Set CpColor independent:  usNewPalette = %d, uiCurColor = 0X%06x", pstAnimColorParam->usNewPalette, uiCurColor);
    }
    else
    {
        Hv_Mw_OsdAnimSetSingleColor(stCp, pstAnimColorParam->usOriginalPalette, uiCurColor);
        OSD_LOG_DEBUG("Set CpColor independent:  usOriginalPalette = %d, uiCurColor = 0X%06x", pstAnimColorParam->usNewPalette, uiCurColor);
    }

    if ((ANIMATION_LASTTIME == pstAnimParam->usRemainTime)
       && (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType))
    {
        Hv_Mw_OsdAnimSetCompPaletteOffset(stCp, pstAnimColorParam->usOriginalPalette);
        OSD_LOG_DEBUG("Set palette independent:  usOriginalPalette = %d", pstAnimColorParam->usOriginalPalette);
    }

}

/*ANIM_PALETTE_INDEPENDENT模式注意第一帧和最后一帧需要更改palette*/
VOID Hv_Mw_OsdAnimUpdateBmpColor(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);
    AnimColorParam *pstAnimColorParam = (AnimColorParam *)pstAnimParam->UserParam;

    AnimCurveMap stMapParam = {0};
    UCHAR8 ucCurR = 0;
    UCHAR8 ucCurG = 0;
    UCHAR8 ucCurB = 0;
    UCHAR8 ucIndex = 0;
    UINT32 uiStart = 0;
    UINT32 uiEnd = 0;

    OsdComponent stCp = {pstAnimParam->ucElementType, pstAnimParam->usId};
    UCHAR8 ucRGBLen = pstAnimColorParam->ucPaletteLen;
    UINT32 *puiRGBTbl = HV_MALLOC_OBJECT_ARRAY(UINT32, ucRGBLen);
    HV_ASSERT_VALID_PTR_VOID(puiRGBTbl);

    Hv_Mw_OsdAnimGetCompColor(pstAnimColorParam->usOriginalPalette, &puiRGBTbl[0], ucRGBLen);
    //OSD_LOG_DEBUG("Get CpColor independent: puiRGBTbl[0] = 0x%06x", puiRGBTbl[0]);

    if ((pstAnimParam->usDurationTime == pstAnimParam->usRemainTime)
       && (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType))
    {
        Hv_Mw_OsdAnimSetCompPaletteOffset(stCp, pstAnimColorParam->usNewPalette);
        OSD_LOG_DEBUG("Set palette independent:  usNewPalette = %d", pstAnimColorParam->usNewPalette);
    }

    stMapParam.usDurationTime = pstAnimParam->usDurationTime;
    stMapParam.usRemainTime = pstAnimParam->usRemainTime;

    for (ucIndex = 0; ucIndex < ucRGBLen; ucIndex++)
    {
        if (INVALID_PARAM_UINT32 != pstAnimColorParam->uiStart)
        {
            uiStart = pstAnimColorParam->uiStart;
        }
        else
        {
            uiStart = puiRGBTbl[ucIndex];
        }
        if (INVALID_PARAM_UINT32 != pstAnimColorParam->uiEnd)
        {
            uiEnd = pstAnimColorParam->uiEnd;
        }
        else
        {
            uiEnd = puiRGBTbl[ucIndex];
        }

        stMapParam.usStart = OSD_R(uiStart);
        stMapParam.usEnd = OSD_R(uiEnd);
        ucCurR = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

        stMapParam.usStart = OSD_G(uiStart);
        stMapParam.usEnd = OSD_G(uiEnd);
        ucCurG = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

        stMapParam.usStart = OSD_B(uiStart);
        stMapParam.usEnd = OSD_B(uiEnd);
        ucCurB = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);

        puiRGBTbl[ucIndex] = (((UINT32)ucCurB) << 16) | (((UINT32)ucCurG) << 8) | (((UINT32)ucCurR) << 0);
        OSD_LOG_DEBUG("UpdateBmpColor[index_%d]: B = 0x%x, G = 0x%x, R = 0x%x, uiCurColor = 0x%06x",
                       ucIndex, ucCurB, ucCurG, ucCurR, puiRGBTbl[ucIndex]);
    }

    if (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType)
    {
        Hv_Mw_OsdAnimSetCompColor(stCp, pstAnimColorParam->usNewPalette, &puiRGBTbl[0], ucRGBLen);
        OSD_LOG_DEBUG("Set CpColor independent:  usNewPalette = %d, puiRGBTbl[0] = 0x%06x", pstAnimColorParam->usNewPalette, puiRGBTbl[0]);
    }
    else
    {
        Hv_Mw_OsdAnimSetCompColor(stCp, pstAnimColorParam->usOriginalPalette, &puiRGBTbl[0], ucRGBLen);
        OSD_LOG_DEBUG("Set CpColor independent:  usOriginalPalette = %d, puiRGBTbl[0] = 0x%06x", pstAnimColorParam->usOriginalPalette, puiRGBTbl[0]);
    }

    if ((ANIMATION_LASTTIME == pstAnimParam->usRemainTime)
       && (ANIM_PALETTE_INDEPENDENT == pstAnimColorParam->ucPaletteType))
    {
        Hv_Mw_OsdAnimSetCompPaletteOffset(stCp, pstAnimColorParam->usOriginalPalette);
        OSD_LOG_DEBUG("Set palette independent:  usOriginalPalette = %d", pstAnimColorParam->usOriginalPalette);
    }

    HV_FREE_OBJECT_ARRAY(puiRGBTbl);
}

/* 依次显示或消失 */
VOID Hv_Mw_OsdAnimUpdateItemSequence(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    AnimCurveMap stMapParam = {0};
    USHORT16 usCurIdx = ITEM_NONE_ID;
    UCHAR8 ucIndex = 0;

    stMapParam.usDurationTime = pstAnimParam->usDurationTime;
    stMapParam.usRemainTime = pstAnimParam->usRemainTime;
    stMapParam.usStart = pstAnimParam->usStart;
    stMapParam.usEnd = pstAnimParam->usEnd;
    usCurIdx = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
    OSD_LOG_DEBUG("usCurIdx=%d,usStart=%d,usEnd=%d", usCurIdx, pstAnimParam->usStart, pstAnimParam->usEnd);

    Hv_Mw_OsdItemShow(usCurIdx);
}

VOID Hv_Mw_OsdAnimUpdateCompList(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    AnimCurveMap stMapParam = {0};
    UCHAR8 ucCurNum = 1;
    OsdComponent stCp = COMPONENT(pstAnimParam->ucElementType, pstAnimParam->usId);

    stMapParam.usDurationTime = pstAnimParam->usDurationTime;
    stMapParam.usRemainTime = pstAnimParam->usRemainTime;
    stMapParam.usStart = pstAnimParam->usStart;
    stMapParam.usEnd = pstAnimParam->usEnd;
    ucCurNum = Hv_Mw_OsdAnimCurveMapping(ANIM_CURVE_LINEAR, &stMapParam);

    Hv_Mw_OsdComponentShow(stCp);
    Hv_Mw_OsdAnimSetCompTurns(stCp, ucCurNum);
}

VOID Hv_Mw_OsdAnimUpdateCompSize(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam->UserParam);

    /* 为了当前组件放在list头部，以便绘制时能更新到 */
    OsdComponent stCp = {pstAnimParam->ucElementType, pstAnimParam->usId};
    Hv_Mw_OsdComponentShow(stCp);

    /* 保存动画开始前初始化是组件数据 */
    AnimRangeParam *pstAnimUserParam = (AnimRangeParam *)pstAnimParam->UserParam;
    AnimRangeParam stRangeParam = {INVALID_PARAM_USHORT16, INVALID_PARAM_USHORT16, INVALID_PARAM_USHORT16,INVALID_PARAM_USHORT16};
    AnimCurveMap stMapParam = {0};
    USHORT16 usCurWidth = 0;
    USHORT16 usCurHeight = 0;

    stMapParam.usDurationTime = pstAnimParam->usDurationTime;
    stMapParam.usRemainTime = pstAnimParam->usRemainTime;
    switch (pstAnimParam->ucOperateType)
    {
        case ANIM_SIZE_LR_EXPAND:
        case ANIM_SIZE_RL_COLLAPSE:
        {
            stMapParam.usStart = pstAnimParam->usStart;
            stMapParam.usEnd = pstAnimParam->usEnd;
            usCurWidth = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
            stRangeParam.usX = pstAnimUserParam->usX;
            stRangeParam.usWidth = usCurWidth;
            break;
        }
        case ANIM_SIZE_LR_COLLAPSE:
        case ANIM_SIZE_RL_EXPAND:
        {
            stMapParam.usStart = pstAnimParam->usStart;
            stMapParam.usEnd = pstAnimParam->usEnd;
            usCurWidth = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
            stRangeParam.usX = pstAnimUserParam->usX + pstAnimUserParam->usWidth - usCurWidth;
            stRangeParam.usWidth = usCurWidth;
            break;
        }
        case ANIM_SIZE_TB_EXPAND:
        case ANIM_SIZE_BT_COLLAPSE:
        {
            stMapParam.usStart = pstAnimParam->usStart;
            stMapParam.usEnd = pstAnimParam->usEnd;
            usCurHeight = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
            stRangeParam.usY = pstAnimUserParam->usY;
            stRangeParam.usHeight = usCurHeight;
            break;
        }
        case ANIM_SIZE_TB_COLLAPSE:
        case ANIM_SIZE_BT_EXPAND:
        {
            stMapParam.usStart = pstAnimParam->usStart;
            stMapParam.usEnd = pstAnimParam->usEnd;
            usCurHeight = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stMapParam);
            stRangeParam.usY = pstAnimUserParam->usY + pstAnimUserParam->usHeight - usCurHeight;
            stRangeParam.usHeight = usCurHeight;
            break;
        }
        default:
        {
            return;
        }
    }

    OSD_LOG_DEBUG("usX=%d,usY=%d,usWidth=%d,usHeight=%d",
                    stRangeParam.usX, stRangeParam.usY, stRangeParam.usWidth, stRangeParam.usHeight);

    Hv_Mw_OsdAnimSetCompRange(stCp, &stRangeParam);
}

VOID Hv_Mw_OsdAnimUpdateCompPos(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    /* 为了当前组件放在list头部，以便绘制时能更新到 */
    OsdComponent stCp = {pstAnimParam->ucElementType, pstAnimParam->usId};
    if ( (OSD_CP_TYPE_RECT == pstAnimParam->ucElementType)
       || (OSD_CP_TYPE_RECTGRID == pstAnimParam->ucElementType)
       || (OSD_CP_TYPE_LINE == pstAnimParam->ucElementType)
       || (OSD_CP_TYPE_LINEGRID == pstAnimParam->ucElementType))
    {
        Hv_Mw_OsdComponentShow(stCp);
    }
    else
    {
        Hv_Mw_OsdComponentShow(stCp);
    }

    if (ANIM_POS_X == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        Hv_Mw_OsdComponentSetPosition(stCp, usCurPos, INVALID_PARAM_USHORT16, HV_FALSE);
        OSD_LOG_DEBUG("UpdateCpXPos, usCurPos:%d", usCurPos);
    }
    else if (ANIM_POS_Y == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        Hv_Mw_OsdComponentSetPosition(stCp, INVALID_PARAM_USHORT16, usCurPos, HV_FALSE);
        OSD_LOG_DEBUG("UpdateCpYPos, usCurPos:%d", usCurPos);
    }
    else
    {
        HV_ASSERT_VALID_PTR_VOID(pstAnimParam->UserParam);
        AnimCurveMap stXPosition = {pstAnimParam->usStart,
                                pstAnimParam->usEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurXPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stXPosition);

        AnimPosParam *pstAnimPosParam = (AnimPosParam *)pstAnimParam->UserParam;
        AnimCurveMap stYPosition = {pstAnimPosParam->usYStart,
                                pstAnimPosParam->usYEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurYPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stYPosition);

        Hv_Mw_OsdComponentSetPosition(stCp, usCurXPos, usCurYPos, HV_FALSE);
        OSD_LOG_DEBUG("UpdateCpXYPos, usXCurPos:%d, usYCurPos:%d", usCurXPos, usCurYPos);
    }
}

/* 包括item和其cursor,不支持font类V方向移动 */
VOID Hv_Mw_OsdAnimUpdateItemPos(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    if (ANIM_POS_X == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        //Hv_Mw_OsdItemSetPosition(pstAnimParam->usId, usCurPos, INVALID_PARAM_USHORT16);
        Hv_Mw_OsdAnimSetItemPosition(pstAnimParam->usId, usCurPos, INVALID_PARAM_USHORT16);
        OSD_LOG_DEBUG("UpdateCpXPos, usCurPos:%d", usCurPos);
    }
    else if (ANIM_POS_Y == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        //Hv_Mw_OsdItemSetPosition(pstAnimParam->usId, INVALID_PARAM_USHORT16, usCurPos);
        Hv_Mw_OsdAnimSetItemPosition(pstAnimParam->usId, INVALID_PARAM_USHORT16, usCurPos);
        OSD_LOG_DEBUG("UpdateCpYPos, usCurPos:%d", usCurPos);
    }
    else
    {
        HV_ASSERT_VALID_PTR_VOID(pstAnimParam->UserParam);
        AnimCurveMap stXPosition = {pstAnimParam->usStart,
                                pstAnimParam->usEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurXPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stXPosition);

        AnimPosParam *pstAnimPosParam = (AnimPosParam *)pstAnimParam->UserParam;
        AnimCurveMap stYPosition = {pstAnimPosParam->usYStart,
                                pstAnimPosParam->usYEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurYPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stYPosition);

        //Hv_Mw_OsdItemSetPosition(pstAnimParam->usId, usCurXPos, usCurYPos);
        Hv_Mw_OsdAnimSetItemPosition(pstAnimParam->usId, usCurXPos, usCurYPos);
        OSD_LOG_DEBUG("UpdateCpXYPos, usXCurPos:%d, usYCurPos:%d", usCurXPos, usCurYPos);
    }
}

VOID Hv_Mw_OsdAnimUpdateCursorPos(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    if (ANIM_POS_X == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        /* pstAnimParam->usId存放ucCursorId，pstAnimParam->ucElementType存放ucItemState */
        Hv_Mw_OsdCursorSetPositon(pstAnimParam->usId, usCurPos, INVALID_PARAM_USHORT16, pstAnimParam->ucElementType);
        OSD_LOG_DEBUG("UpdateCpXPos, usCurPos:%d", usCurPos);
    }
    else if (ANIM_POS_Y == pstAnimParam->ucOperateType)
    {
        AnimCurveMap stPosition = {pstAnimParam->usStart,
                               pstAnimParam->usEnd,
                               pstAnimParam->usDurationTime,
                               pstAnimParam->usRemainTime};
        USHORT16 usCurPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stPosition);
        /* pstAnimParam->usId存放ucCursorId，pstAnimParam->ucElementType存放ucItemState */
        Hv_Mw_OsdCursorSetPositon(pstAnimParam->usId, INVALID_PARAM_USHORT16, usCurPos, pstAnimParam->ucElementType);
        OSD_LOG_DEBUG("UpdateCpYPos, usCurPos:%d", usCurPos);
    }
    else
    {
        HV_ASSERT_VALID_PTR_VOID(pstAnimParam->UserParam);
        AnimCurveMap stXPosition = {pstAnimParam->usStart,
                                pstAnimParam->usEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurXPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stXPosition);

        AnimPosParam *pstAnimPosParam = (AnimPosParam *)pstAnimParam->UserParam;
        AnimCurveMap stYPosition = {pstAnimPosParam->usYStart,
                                pstAnimPosParam->usYEnd,
                                pstAnimParam->usDurationTime,
                                pstAnimParam->usRemainTime};
        USHORT16 usCurYPos = Hv_Mw_OsdAnimCurveMapping(pstAnimParam->enCurveType, &stYPosition);

        /* pstAnimParam->usId存放ucCursorId，pstAnimParam->ucElementType存放ucItemState */
        Hv_Mw_OsdCursorSetPositon(pstAnimParam->usId, usCurXPos, usCurYPos, pstAnimParam->ucElementType);
        OSD_LOG_DEBUG("UpdateCpXYPos, usXCurPos:%d, usYCurPos:%d", usCurXPos, usCurYPos);
    }
}

#if (HV_CONFIG_ON == HV_PROJECT_CONFIG_OSD_MARQUEE)
VOID Hv_Mw_OsdComponentInitMarquee(OsdComponent stCp)
{
    OsdComponentNode *pstCpNode = Hv_Mw_OsdComponentGetNode(stCp);
    HV_ASSERT_VALID_PTR_VOID(pstCpNode);

    /* 为组件初始化跑马灯 */
    pstCpNode->enMarqueeType = 1;
    pstCpNode->bStartAfterCreate = 1;
    Hv_Drv_OsdFont_StartMarquee(pstCpNode);
    //Hv_Mw_OsdOpsForceRedraw(HV_TRUE);
}

VOID Hv_Mw_OsdAnimUpdateMarquee(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    if (!Hv_Drv_OsdFont_NeedMarquee())
    {
        OSD_LOG_DEBUG("No need marquee");
        pstAnimParam->usRemainTime = ANIMATION_LASTTIME;
    }

    Hv_Drv_OsdFont_MarqueeStep();
}

VOID Hv_Mw_OsdAnimFinishMarquee(OsdAnimition *pstAnimParam)
{
    HV_ASSERT_VALID_PTR_VOID(pstAnimParam);

    OsdComponent stCp = {pstAnimParam->ucElementType, pstAnimParam->usId};
    OsdComponentNode *pstCpNode = Hv_Mw_OsdComponentGetNode(stCp);

    if (NULL != pstCpNode)
    {
        Hv_Drv_OsdFont_ResetMarquee(pstCpNode);
    }
}

#if (HV_CONFIG_ON == HV_OSD_CONFIG_MARQUEE_AUTO_CHECK_EXCESS)
static OsdAnimition *s_pstAutoMarqueeAnim = NULL;
VOID Hv_Mw_OsdCheckAutoMarquee(VOID)
{
    if (Hv_Drv_OsdFont_NeedMarquee())
    {
        if (NULL == s_pstAutoMarqueeAnim)
        {
            OSD_LOG_DEBUG("auto start marquee");
            OsdAnimitionParam stAnimParam = {0};
            /* 创建动画 */
            stAnimParam.usDelayTime = 0;
            stAnimParam.usDurationTime = INVALID_PARAM_USHORT16;
            stAnimParam.ucOperateType = ANIM_MARQUEE_AUTO;
            stAnimParam.ExecuteCbFn = Hv_Mw_OsdAnimUpdateMarquee;
            //stAnimParam.FinishCbFn = Hv_Mw_OsdAnimFinishMarquee;

            s_pstAutoMarqueeAnim = Hv_Mw_OsdAnimCreate(&stAnimParam);
            HV_ASSERT_VALID_PTR_VOID(s_pstAutoMarqueeAnim);
        }
    }
    else
    {
        if (NULL != s_pstAutoMarqueeAnim)
        {
            OSD_LOG_DEBUG("auto terminal marquee");
            Hv_Mw_OsdAnimForceTerminal(s_pstAutoMarqueeAnim);
            s_pstAutoMarqueeAnim = NULL;
        }
    }
}
#endif

#endif

#endif
