mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
938 lines
31 KiB
C
938 lines
31 KiB
C
/*
|
|
* Copyright (C) 2010-2020 Arm Limited or its affiliates. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* Project: Arm-2D Library
|
|
* Title: arm-2d_rotation.c
|
|
* Description: APIs for tile rotation
|
|
*
|
|
* $Date: 29 April 2021
|
|
* $Revision: V.0.1.0
|
|
*
|
|
* Target Processor: Cortex-M cores
|
|
*
|
|
* -------------------------------------------------------------------- */
|
|
|
|
|
|
/*============================ INCLUDES ======================================*/
|
|
#define __ARM_2D_IMPL__
|
|
|
|
#include "arm_2d.h"
|
|
#include "__arm_2d_impl.h"
|
|
#include "math.h"
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic push
|
|
# pragma clang diagnostic ignored "-Wunknown-warning-option"
|
|
# pragma clang diagnostic ignored "-Wreserved-identifier"
|
|
# pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
|
|
# pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
|
# pragma clang diagnostic ignored "-Wcast-qual"
|
|
# pragma clang diagnostic ignored "-Wcast-align"
|
|
# pragma clang diagnostic ignored "-Wextra-semi-stmt"
|
|
# pragma clang diagnostic ignored "-Wsign-conversion"
|
|
# pragma clang diagnostic ignored "-Wunused-function"
|
|
# pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
|
|
# pragma clang diagnostic ignored "-Wdouble-promotion"
|
|
# pragma clang diagnostic ignored "-Wunused-parameter"
|
|
# pragma clang diagnostic ignored "-Wimplicit-float-conversion"
|
|
# pragma clang diagnostic ignored "-Wimplicit-int-conversion"
|
|
# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
|
# pragma clang diagnostic ignored "-Wsign-compare"
|
|
# pragma clang diagnostic ignored "-Wfloat-conversion"
|
|
# pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
# pragma clang diagnostic ignored "-Wpadded"
|
|
# pragma clang diagnostic ignored "-Wundef"
|
|
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
|
# pragma diag_suppress 174,177,188,68,513,144
|
|
#elif defined(__IS_COMPILER_GCC__)
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
|
|
#endif
|
|
|
|
#include <arm_math.h>
|
|
|
|
/*============================ MACROS ========================================*/
|
|
#undef __PI
|
|
#define __PI 3.1415926f
|
|
|
|
#define __CALIB 0.009f
|
|
/* faster ATAN */
|
|
#define FAST_ATAN_F32_1(x, xabs) \
|
|
(x * (PI / 4.0f) + 0.273f * x * (1.0f - xabs))
|
|
#define EPS_ATAN2 1e-5f
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Code Template *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
#define __API_PIXEL_AVERAGE_RESULT_GRAY8() \
|
|
( tPixel >> 8)
|
|
|
|
#define __API_PIXEL_AVERAGE_RESULT_RGB565() \
|
|
( tPixel.R >>= 8, \
|
|
tPixel.G >>= 8, \
|
|
tPixel.B >>= 8, \
|
|
__arm_2d_rgb565_pack(&tPixel));
|
|
|
|
#define __API_PIXEL_AVERAGE_RESULT_RGB888() \
|
|
( tPixel.R >>= 8, \
|
|
tPixel.G >>= 8, \
|
|
tPixel.B >>= 8, \
|
|
__arm_2d_cccn888_pack(&tPixel));
|
|
|
|
|
|
#define __API_COLOUR gray8
|
|
#define __API_INT_TYPE uint8_t
|
|
#define __API_PIXEL_AVERAGE_INIT() uint16_t tPixel = 0;
|
|
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_GRAY8
|
|
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_GRAY8
|
|
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_GRAY8
|
|
#include "__arm_2d_rotate.inc"
|
|
|
|
#define __API_COLOUR rgb565
|
|
#define __API_INT_TYPE uint16_t
|
|
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_RGB565
|
|
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_RGB565
|
|
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_RGB565
|
|
#include "__arm_2d_rotate.inc"
|
|
|
|
#define __API_COLOUR cccn888
|
|
#define __API_INT_TYPE uint32_t
|
|
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_CCCN888
|
|
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_CCCN888
|
|
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_RGB888
|
|
|
|
#include "__arm_2d_rotate.inc"
|
|
|
|
/*============================ MACROFIED FUNCTIONS ===========================*/
|
|
/*============================ TYPES =========================================*/
|
|
/*============================ GLOBAL VARIABLES ==============================*/
|
|
/*============================ PROTOTYPES ====================================*/
|
|
/*============================ LOCAL VARIABLES ===============================*/
|
|
/*============================ IMPLEMENTATION ================================*/
|
|
|
|
#if __ARM_2D_CFG_FORCED_FIXED_POINT_ROTATION__
|
|
|
|
static
|
|
void __arm_2d_rotate_regression(arm_2d_size_t * __RESTRICT ptCopySize,
|
|
arm_2d_location_t * pSrcPoint,
|
|
float fAngle,
|
|
arm_2d_location_t * tOffset,
|
|
arm_2d_location_t * center,
|
|
arm_2d_rot_linear_regr_t regrCoefs[]
|
|
)
|
|
{
|
|
#define ONE_BY_2PI_Q31 341782637.0f
|
|
#define TO_Q16(x) ((x) << 16)
|
|
|
|
int_fast16_t iHeight = ptCopySize->iHeight;
|
|
int_fast16_t iWidth = ptCopySize->iWidth;
|
|
q31_t invHeightFx = 0x7fffffff / (iHeight - 1);
|
|
int32_t AngleFx = lroundf(fAngle * ONE_BY_2PI_Q31);
|
|
q31_t cosAngleFx = arm_cos_q31(AngleFx);
|
|
q31_t sinAngleFx = arm_sin_q31(AngleFx);
|
|
arm_2d_point_fx_t tPointCornerFx[2][2];
|
|
arm_2d_point_fx_t centerQ16;
|
|
arm_2d_point_fx_t srcPointQ16;
|
|
arm_2d_point_fx_t tOffsetQ16;
|
|
arm_2d_point_fx_t tmp;
|
|
int32_t iXQ16, iYQ16;
|
|
|
|
|
|
/* Q16 conversion */
|
|
centerQ16.X = TO_Q16(center->iX);
|
|
centerQ16.Y = TO_Q16(center->iY);
|
|
|
|
srcPointQ16.X = TO_Q16(pSrcPoint->iX);
|
|
srcPointQ16.Y = TO_Q16(pSrcPoint->iY);
|
|
|
|
tOffsetQ16.X = TO_Q16(tOffset->iX);
|
|
tOffsetQ16.Y = TO_Q16(tOffset->iY);
|
|
|
|
|
|
/* (0,0) corner */
|
|
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X;
|
|
tmp.Y = srcPointQ16.Y + 0 + tOffsetQ16.Y;
|
|
|
|
iXQ16 = tmp.X - centerQ16.X;
|
|
iYQ16 = tmp.Y - centerQ16.Y;
|
|
|
|
tPointCornerFx[0][0].Y =
|
|
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
|
|
tPointCornerFx[0][0].X =
|
|
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
|
|
|
|
|
|
/* ((iWidth - 1),0) corner */
|
|
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X + TO_Q16(iWidth - 1);
|
|
iXQ16 = tmp.X - centerQ16.X;
|
|
|
|
tPointCornerFx[1][0].Y =
|
|
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
|
|
tPointCornerFx[1][0].X =
|
|
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
|
|
|
|
|
|
/* ((iWidth - 1),(iHeight - 1)) corner */
|
|
tmp.Y = srcPointQ16.Y + tOffsetQ16.Y + TO_Q16(iHeight - 1);
|
|
iYQ16 = tmp.Y - centerQ16.Y;
|
|
|
|
tPointCornerFx[1][1].Y =
|
|
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
|
|
tPointCornerFx[1][1].X =
|
|
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
|
|
|
|
|
|
/* (0,(iHeight - 1)) corner */
|
|
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X;
|
|
iXQ16 = tmp.X - centerQ16.X;
|
|
|
|
tPointCornerFx[0][1].Y =
|
|
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
|
|
tPointCornerFx[0][1].X =
|
|
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
|
|
|
|
|
|
/* regression */
|
|
int32_t slopeXFx, slopeYFx;
|
|
|
|
/* interpolation in Y direction for 1st elements column */
|
|
slopeXFx = MULTFX((tPointCornerFx[0][1].X - tPointCornerFx[0][0].X), invHeightFx);
|
|
slopeYFx = MULTFX((tPointCornerFx[0][1].Y - tPointCornerFx[0][0].Y), invHeightFx);
|
|
|
|
regrCoefs[0].slopeY = slopeYFx * 2;
|
|
regrCoefs[0].slopeX = slopeXFx * 2;
|
|
regrCoefs[0].interceptY = tPointCornerFx[0][0].Y;
|
|
regrCoefs[0].interceptX = tPointCornerFx[0][0].X;
|
|
|
|
|
|
/* interpolation in Y direction for the last elements column */
|
|
slopeXFx = MULTFX((tPointCornerFx[1][1].X - tPointCornerFx[1][0].X), invHeightFx);
|
|
slopeYFx = MULTFX((tPointCornerFx[1][1].Y - tPointCornerFx[1][0].Y), invHeightFx);
|
|
|
|
regrCoefs[1].slopeY = slopeYFx* 2;
|
|
regrCoefs[1].slopeX = slopeXFx* 2;
|
|
regrCoefs[1].interceptY = tPointCornerFx[1][0].Y;
|
|
regrCoefs[1].interceptX = tPointCornerFx[1][0].X;
|
|
}
|
|
|
|
#else
|
|
|
|
static
|
|
void __arm_2d_rotate_regression(arm_2d_size_t * __RESTRICT ptCopySize,
|
|
arm_2d_location_t * pSrcPoint,
|
|
float fAngle,
|
|
arm_2d_location_t * tOffset,
|
|
arm_2d_location_t * ptCenter,
|
|
arm_2d_rot_linear_regr_t regrCoefs[])
|
|
{
|
|
int_fast16_t iHeight = ptCopySize->iHeight;
|
|
int_fast16_t iWidth = ptCopySize->iWidth;
|
|
float invHeight = 1.0f / (float) (iHeight - 1);
|
|
float cosAngle = arm_cos_f32(fAngle);
|
|
float sinAngle = arm_sin_f32(fAngle);
|
|
arm_2d_location_t tSrcPoint;
|
|
arm_2d_point_float_t tPointCorner[2][2];
|
|
int16_t iX, iY;
|
|
|
|
|
|
|
|
tSrcPoint.iX = pSrcPoint->iX + 0 + tOffset->iX;
|
|
tSrcPoint.iY = pSrcPoint->iY + 0 + tOffset->iY;
|
|
|
|
iX = tSrcPoint.iX - ptCenter->iX;
|
|
iY = tSrcPoint.iY - ptCenter->iY;
|
|
|
|
tPointCorner[0][0].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
|
|
tPointCorner[0][0].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
|
|
|
|
tSrcPoint.iX = pSrcPoint->iX + (iWidth - 1) + tOffset->iX;
|
|
iX = tSrcPoint.iX - ptCenter->iX;
|
|
|
|
tPointCorner[1][0].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
|
|
tPointCorner[1][0].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
|
|
|
|
tSrcPoint.iY = pSrcPoint->iY + (iHeight - 1) + tOffset->iY;
|
|
iY = tSrcPoint.iY - ptCenter->iY;
|
|
|
|
tPointCorner[1][1].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
|
|
tPointCorner[1][1].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
|
|
|
|
tSrcPoint.iX = pSrcPoint->iX + 0 + tOffset->iX;
|
|
iX = tSrcPoint.iX - ptCenter->iX;
|
|
|
|
tPointCorner[0][1].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
|
|
tPointCorner[0][1].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
|
|
|
|
float slopeX, slopeY;
|
|
|
|
/* interpolation in Y direction for 1st elements column */
|
|
slopeX = (tPointCorner[0][1].fX - tPointCorner[0][0].fX) * invHeight;
|
|
slopeY = (tPointCorner[0][1].fY - tPointCorner[0][0].fY) * invHeight;
|
|
|
|
regrCoefs[0].slopeY = slopeY;
|
|
regrCoefs[0].slopeX = slopeX;
|
|
regrCoefs[0].interceptY = tPointCorner[0][0].fY;
|
|
regrCoefs[0].interceptX = tPointCorner[0][0].fX;
|
|
|
|
|
|
/* interpolation in Y direction for the last elements column */
|
|
slopeX = (tPointCorner[1][1].fX - tPointCorner[1][0].fX) * invHeight;
|
|
slopeY = (tPointCorner[1][1].fY - tPointCorner[1][0].fY) * invHeight;
|
|
|
|
regrCoefs[1].slopeY = slopeY;
|
|
regrCoefs[1].slopeX = slopeX;
|
|
regrCoefs[1].interceptY = tPointCorner[1][0].fY;
|
|
regrCoefs[1].interceptX = tPointCorner[1][0].fX;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
ARM_NONNULL(1,2,4)
|
|
static
|
|
arm_2d_point_float_t *__arm_2d_rotate_point(const arm_2d_location_t *ptLocation,
|
|
const arm_2d_location_t *ptCenter,
|
|
float fAngle,
|
|
arm_2d_point_float_t *ptOutBuffer)
|
|
{
|
|
int16_t iX = ptLocation->iX - ptCenter->iX;
|
|
int16_t iY = ptLocation->iY - ptCenter->iY;
|
|
|
|
float fX,fY;
|
|
|
|
float cosAngle = arm_cos_f32(fAngle);
|
|
float sinAngle = arm_sin_f32(fAngle);
|
|
|
|
fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
|
|
fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
|
|
|
|
|
|
#if !defined(__ARM_2D_CFG_UNSAFE_IGNORE_CALIB_IN_ROTATION_FOR_PERFORMANCE__)
|
|
if (fX > 0) {
|
|
ptOutBuffer->fX = fX + __CALIB;
|
|
} else {
|
|
ptOutBuffer->fX = fX - __CALIB;
|
|
}
|
|
if (fY > 0) {
|
|
ptOutBuffer->fY = fY + __CALIB;
|
|
} else {
|
|
ptOutBuffer->fY = fY - __CALIB;
|
|
}
|
|
#else
|
|
ptOutBuffer->fX = fX;
|
|
ptOutBuffer->fY = fY;
|
|
#endif
|
|
|
|
return ptOutBuffer;
|
|
}
|
|
|
|
|
|
static arm_2d_err_t __arm_2d_rotate_preprocess_source(arm_2d_op_rotate_t *ptThis)
|
|
{
|
|
arm_2d_tile_t *ptSource = this.Source.ptTile;
|
|
|
|
memset(ptSource, 0, sizeof(*ptSource));
|
|
|
|
ptSource->tInfo = this.Origin.ptTile->tInfo;
|
|
ptSource->bIsRoot = true;
|
|
ptSource->pchBuffer = NULL; //!< special case
|
|
|
|
arm_2d_region_t tOrigValidRegion;
|
|
if (NULL == arm_2d_tile_get_root(this.Origin.ptTile, &tOrigValidRegion, NULL)) {
|
|
return ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
//! angle validation
|
|
this.tRotate.fAngle = fmodf(this.tRotate.fAngle, ARM_2D_ANGLE(360));
|
|
|
|
//! calculate the source region
|
|
do {
|
|
arm_2d_point_float_t tPoint;
|
|
|
|
arm_2d_location_t tTopLeft = {.iX = INT16_MAX, .iY = INT16_MAX};
|
|
arm_2d_location_t tBottomRight = {.iX = INT16_MIN, .iY = INT16_MIN};
|
|
|
|
//! Top Left
|
|
arm_2d_location_t tCornerPoint = tOrigValidRegion.tLocation;
|
|
__arm_2d_rotate_point( &tCornerPoint,
|
|
&this.tRotate.tCenter,
|
|
this.tRotate.fAngle,
|
|
&tPoint);
|
|
|
|
do {
|
|
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
|
|
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
|
|
|
|
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
|
|
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
|
|
} while(0);
|
|
|
|
//! Bottom Left
|
|
tCornerPoint.iY += tOrigValidRegion.tSize.iHeight - 1;
|
|
__arm_2d_rotate_point( &tCornerPoint,
|
|
&this.tRotate.tCenter,
|
|
this.tRotate.fAngle,
|
|
&tPoint);
|
|
|
|
do {
|
|
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
|
|
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
|
|
|
|
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
|
|
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
|
|
} while(0);
|
|
|
|
//! Top Right
|
|
tCornerPoint = tOrigValidRegion.tLocation;
|
|
tCornerPoint.iX += tOrigValidRegion.tSize.iWidth - 1;
|
|
|
|
__arm_2d_rotate_point( &tCornerPoint,
|
|
&this.tRotate.tCenter,
|
|
this.tRotate.fAngle,
|
|
&tPoint);
|
|
|
|
do {
|
|
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
|
|
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
|
|
|
|
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
|
|
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
|
|
} while(0);
|
|
|
|
//! Bottom Right
|
|
tCornerPoint.iY += tOrigValidRegion.tSize.iHeight - 1;
|
|
__arm_2d_rotate_point( &tCornerPoint,
|
|
&this.tRotate.tCenter,
|
|
this.tRotate.fAngle,
|
|
&tPoint);
|
|
|
|
do {
|
|
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
|
|
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
|
|
|
|
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
|
|
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
|
|
} while(0);
|
|
|
|
//! calculate the region
|
|
this.tRotate.tDummySourceOffset = tTopLeft;
|
|
|
|
ptSource->tRegion.tSize.iHeight = tBottomRight.iY - tTopLeft.iY + 1;
|
|
ptSource->tRegion.tSize.iWidth = tBottomRight.iX - tTopLeft.iX + 1;
|
|
|
|
//this.tRotate.tTargetRegion.tSize = ptSource->tRegion.tSize;
|
|
} while(0);
|
|
|
|
return ARM_2D_ERR_NONE;
|
|
}
|
|
|
|
|
|
static void __arm_2d_rotate_preprocess_target(
|
|
arm_2d_op_rotate_t *ptThis,
|
|
const arm_2d_location_t *ptTargetCentre)
|
|
{
|
|
this.tRotate.Target.tRegion.tSize = this.Source.ptTile->tRegion.tSize;
|
|
|
|
#if 0 //!< please keep this code for understanding the original meaning
|
|
arm_2d_region_t tTargetRegion = {0};
|
|
if (NULL != this.Target.ptRegion) {
|
|
tTargetRegion = *this.Target.ptRegion;
|
|
} else {
|
|
tTargetRegion.tSize = this.Target.ptTile->tRegion.tSize;
|
|
}
|
|
#else
|
|
//! equivalent code
|
|
assert(NULL == this.Target.ptRegion);
|
|
|
|
arm_2d_region_t tTargetRegion = {
|
|
.tSize = this.Target.ptTile->tRegion.tSize,
|
|
};
|
|
#endif
|
|
|
|
this.Target.ptRegion = &this.tRotate.Target.tRegion;
|
|
|
|
this.tRotate.Target.tRegion.tLocation = tTargetRegion.tLocation;
|
|
|
|
//! align with the specified center point
|
|
do {
|
|
|
|
arm_2d_location_t tOffset = {
|
|
.iX = this.tRotate.tCenter.iX - this.tRotate.tDummySourceOffset.iX,
|
|
.iY = this.tRotate.tCenter.iY - this.tRotate.tDummySourceOffset.iY,
|
|
};
|
|
|
|
if (NULL == ptTargetCentre) {
|
|
arm_2d_location_t tTargetCenter = {
|
|
.iX = tTargetRegion.tSize.iWidth >> 1,
|
|
.iY = tTargetRegion.tSize.iHeight >> 1,
|
|
};
|
|
|
|
tOffset.iX = tTargetCenter.iX - tOffset.iX;
|
|
tOffset.iY = tTargetCenter.iY - tOffset.iY;
|
|
} else {
|
|
tOffset.iX = ptTargetCentre->iX - tOffset.iX;
|
|
tOffset.iY = ptTargetCentre->iY - tOffset.iY;
|
|
}
|
|
this.tRotate.Target.tRegion.tLocation.iX += tOffset.iX;
|
|
this.tRotate.Target.tRegion.tLocation.iY += tOffset.iY;
|
|
|
|
} while(0);
|
|
}
|
|
|
|
ARM_NONNULL(2)
|
|
arm_2d_err_t arm_2dp_gray8_tile_rotation_prepare(
|
|
arm_2d_op_rotate_t *ptOP,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_location_t tCentre,
|
|
float fAngle,
|
|
uint8_t chFillColour)
|
|
{
|
|
assert(NULL != ptSource);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
|
|
|
|
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
|
|
return ARM_2D_ERR_BUSY;
|
|
}
|
|
|
|
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_GRAY8;
|
|
|
|
this.Source.ptTile = &this.Origin.tDummySource;
|
|
this.Origin.ptTile = ptSource;
|
|
this.wMode = 0;
|
|
this.tRotate.fAngle = fAngle;
|
|
this.tRotate.tCenter = tCentre;
|
|
this.tRotate.Mask.hwColour = chFillColour;
|
|
|
|
return __arm_2d_rotate_preprocess_source(ptThis);
|
|
}
|
|
|
|
ARM_NONNULL(2)
|
|
arm_2d_err_t arm_2dp_rgb565_tile_rotation_prepare(
|
|
arm_2d_op_rotate_t *ptOP,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_location_t tCentre,
|
|
float fAngle,
|
|
uint16_t hwFillColour)
|
|
{
|
|
assert(NULL != ptSource);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
|
|
|
|
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
|
|
return ARM_2D_ERR_BUSY;
|
|
}
|
|
|
|
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_RGB565;
|
|
|
|
this.Source.ptTile = &this.Origin.tDummySource;
|
|
this.Origin.ptTile = ptSource;
|
|
this.wMode = 0;
|
|
this.tRotate.fAngle = fAngle;
|
|
this.tRotate.tCenter = tCentre;
|
|
this.tRotate.Mask.hwColour = hwFillColour;
|
|
|
|
return __arm_2d_rotate_preprocess_source(ptThis);
|
|
}
|
|
|
|
ARM_NONNULL(2)
|
|
arm_2d_err_t arm_2dp_cccn888_tile_rotation_prepare(
|
|
arm_2d_op_rotate_t *ptOP,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_location_t tCentre,
|
|
float fAngle,
|
|
uint32_t wFillColour)
|
|
{
|
|
assert(NULL != ptSource);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
|
|
|
|
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
|
|
return ARM_2D_ERR_BUSY;
|
|
}
|
|
|
|
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_RGB888;
|
|
|
|
this.Source.ptTile = &this.Origin.tDummySource;
|
|
this.Origin.ptTile = ptSource;
|
|
this.wMode = 0;
|
|
this.tRotate.fAngle = fAngle;
|
|
this.tRotate.tCenter = tCentre;
|
|
this.tRotate.Mask.hwColour = wFillColour;
|
|
|
|
return __arm_2d_rotate_preprocess_source(ptThis);
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_gray8_sw_rotate(__arm_2d_sub_task_t *ptTask)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
|
|
assert(ARM_2D_COLOUR_8BIT == OP_CORE.ptOp->Info.Colour.chScheme);
|
|
|
|
__arm_2d_impl_gray8_rotate(&(ptTask->Param.tCopyOrig),
|
|
&this.tRotate);
|
|
|
|
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_rgb565_sw_rotate(__arm_2d_sub_task_t *ptTask)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
|
|
assert(ARM_2D_COLOUR_RGB565 == OP_CORE.ptOp->Info.Colour.chScheme);
|
|
|
|
__arm_2d_impl_rgb565_rotate(&(ptTask->Param.tCopyOrig),
|
|
&this.tRotate);
|
|
|
|
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_cccn888_sw_rotate(__arm_2d_sub_task_t *ptTask)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
|
|
assert(ARM_2D_COLOUR_SZ_32BIT == OP_CORE.ptOp->Info.Colour.u3ColourSZ);
|
|
|
|
|
|
__arm_2d_impl_cccn888_rotate(&(ptTask->Param.tCopyOrig),
|
|
&this.tRotate);
|
|
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
|
|
ARM_NONNULL(2)
|
|
arm_2d_err_t arm_2dp_rgb565_tile_rotation_with_opacity_prepare(
|
|
arm_2d_op_rotate_opacity_t *ptOP,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_location_t tCentre,
|
|
float fAngle,
|
|
uint16_t hwFillColour,
|
|
uint_fast8_t chRatio)
|
|
{
|
|
assert(NULL != ptSource);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptOP);
|
|
|
|
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
|
|
return ARM_2D_ERR_BUSY;
|
|
}
|
|
|
|
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_WITH_ALPHA_RGB565;
|
|
|
|
this.Source.ptTile = &this.Origin.tDummySource;
|
|
this.Origin.ptTile = ptSource;
|
|
this.wMode = 0;
|
|
this.tRotate.fAngle = fAngle;
|
|
this.tRotate.tCenter = tCentre;
|
|
this.tRotate.Mask.hwColour = hwFillColour;
|
|
this.chRatio = chRatio;
|
|
|
|
return __arm_2d_rotate_preprocess_source((arm_2d_op_rotate_t *)ptThis);
|
|
}
|
|
|
|
ARM_NONNULL(2)
|
|
arm_2d_err_t arm_2dp_cccn888_tile_rotation_with_opacity_prepare(
|
|
arm_2d_op_rotate_opacity_t *ptOP,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_location_t tCentre,
|
|
float fAngle,
|
|
uint32_t wFillColour,
|
|
uint_fast8_t chRatio)
|
|
{
|
|
assert(NULL != ptSource);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptOP);
|
|
|
|
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
|
|
return ARM_2D_ERR_BUSY;
|
|
}
|
|
|
|
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_WITH_ALPHA_RGB888;
|
|
|
|
this.Source.ptTile = &this.Origin.tDummySource;
|
|
this.Origin.ptTile = ptSource;
|
|
this.wMode = 0;
|
|
this.tRotate.fAngle = fAngle;
|
|
this.tRotate.tCenter = tCentre;
|
|
this.tRotate.Mask.wColour = wFillColour;
|
|
this.chRatio = chRatio;
|
|
|
|
return __arm_2d_rotate_preprocess_source((arm_2d_op_rotate_t *)ptThis);
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_rgb565_sw_rotate_with_alpha(__arm_2d_sub_task_t *ptTask)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptTask->ptOP);
|
|
assert(ARM_2D_COLOUR_RGB565 == OP_CORE.ptOp->Info.Colour.chScheme);
|
|
|
|
__arm_2d_impl_rgb565_rotate_alpha( &(ptTask->Param.tCopyOrig),
|
|
&this.tRotate,
|
|
this.chRatio);
|
|
|
|
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_cccn888_sw_rotate_with_alpha(__arm_2d_sub_task_t *ptTask)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptTask->ptOP);
|
|
assert(ARM_2D_COLOUR_SZ_32BIT == OP_CORE.ptOp->Info.Colour.u3ColourSZ);
|
|
|
|
__arm_2d_impl_cccn888_rotate_alpha(&(ptTask->Param.tCopyOrig),
|
|
&this.tRotate,
|
|
this.chRatio);
|
|
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
ARM_NONNULL(2)
|
|
arm_fsm_rt_t arm_2dp_tile_rotate(arm_2d_op_rotate_t *ptOP,
|
|
const arm_2d_tile_t *ptTarget,
|
|
const arm_2d_region_t *ptRegion,
|
|
const arm_2d_location_t *ptTargetCentre)
|
|
{
|
|
assert(NULL != ptTarget);
|
|
|
|
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
|
|
arm_2d_location_t tTargetCentre;
|
|
|
|
if (!__arm_2d_op_acquire((arm_2d_op_core_t *)ptThis)) {
|
|
return arm_fsm_rt_on_going;
|
|
}
|
|
|
|
if (NULL != ptRegion) {
|
|
this.Target.ptTile = arm_2d_tile_generate_child(
|
|
ptTarget,
|
|
ptRegion,
|
|
&this.tRotate.Target.tTile,
|
|
false);
|
|
if (NULL == this.Target.ptTile) {
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
if (ARM_2D_RUNTIME_FEATURE.TREAT_OUT_OF_RANGE_AS_COMPLETE) {
|
|
tResult = arm_fsm_rt_cpl;
|
|
}
|
|
|
|
return __arm_2d_op_depose((arm_2d_op_core_t *)ptThis, tResult);
|
|
}
|
|
|
|
if (NULL != ptTargetCentre) {
|
|
tTargetCentre.iX = ptTargetCentre->iX - ptRegion->tLocation.iX;
|
|
tTargetCentre.iY = ptTargetCentre->iY - ptRegion->tLocation.iY;
|
|
|
|
ptTargetCentre = &tTargetCentre;
|
|
}
|
|
} else {
|
|
this.Target.ptTile = ptTarget;
|
|
//this.Target.ptRegion = ptRegion;
|
|
}
|
|
|
|
this.Target.ptRegion = NULL;
|
|
|
|
__arm_2d_rotate_preprocess_target(ptThis, ptTargetCentre);
|
|
return __arm_2d_op_invoke((arm_2d_op_core_t *)ptThis);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Accelerable Low Level APIs *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Draw a point whose cordinates is stored as float point. *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
#if 0
|
|
static arm_2d_region_t *__arm_2d_calculate_region( const arm_2d_point_float_t *ptLocation,
|
|
arm_2d_region_t *ptRegion)
|
|
{
|
|
assert(NULL != ptLocation);
|
|
assert(NULL != ptRegion);
|
|
|
|
/* +-----+-----+
|
|
* | P0 | P1 |
|
|
* +---- p ----+
|
|
* | P2 | -- |
|
|
* +-----+-----+
|
|
*/
|
|
|
|
arm_2d_location_t tPoints[3];
|
|
|
|
tPoints[0].iX = (int16_t)ptLocation->fX;
|
|
tPoints[2].iX = (int16_t)ptLocation->fX;
|
|
tPoints[1].iX = (int16_t)(ptLocation->fX + 0.99f);
|
|
ptRegion->tSize.iWidth = tPoints[1].iX - tPoints[0].iX + 1;
|
|
|
|
tPoints[0].iY = (int16_t)ptLocation->fY;
|
|
tPoints[2].iY = (int16_t)ptLocation->fY;
|
|
tPoints[1].iY = (int16_t)(ptLocation->fY + 0.99f);
|
|
ptRegion->tSize.iHeight = tPoints[2].iY - tPoints[0].iY + 1;
|
|
|
|
ptRegion->tLocation = tPoints[0];
|
|
|
|
return ptRegion;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Low Level IO Interfaces *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
__WEAK
|
|
def_low_lv_io(__ARM_2D_IO_ROTATE_GRAY8,
|
|
__arm_2d_gray8_sw_rotate);
|
|
|
|
__WEAK
|
|
def_low_lv_io(__ARM_2D_IO_ROTATE_RGB565,
|
|
__arm_2d_rgb565_sw_rotate);
|
|
|
|
__WEAK
|
|
def_low_lv_io(__ARM_2D_IO_ROTATE_RGB888,
|
|
__arm_2d_cccn888_sw_rotate);
|
|
|
|
|
|
__WEAK
|
|
def_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB565,
|
|
__arm_2d_rgb565_sw_rotate_with_alpha);
|
|
|
|
__WEAK
|
|
def_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB888,
|
|
__arm_2d_cccn888_sw_rotate_with_alpha);
|
|
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_GRAY8 = {
|
|
.Info = {
|
|
.Colour = {
|
|
.chScheme = ARM_2D_COLOUR_8BIT,
|
|
},
|
|
.Param = {
|
|
.bHasSource = true,
|
|
.bHasOrigin = true,
|
|
.bHasTarget = true,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_GRAY8),
|
|
.ptFillOrigLike = NULL,
|
|
},
|
|
},
|
|
};
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_RGB565 = {
|
|
.Info = {
|
|
.Colour = {
|
|
.chScheme = ARM_2D_COLOUR_RGB565,
|
|
},
|
|
.Param = {
|
|
.bHasSource = true,
|
|
.bHasOrigin = true,
|
|
.bHasTarget = true,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_RGB565),
|
|
.ptFillOrigLike = NULL,
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_RGB888 = {
|
|
.Info = {
|
|
.Colour = {
|
|
.chScheme = ARM_2D_COLOUR_RGB888,
|
|
},
|
|
.Param = {
|
|
.bHasSource = true,
|
|
.bHasOrigin = true,
|
|
.bHasTarget = true,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_RGB888),
|
|
.ptFillOrigLike = NULL,
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_WITH_ALPHA_RGB565 = {
|
|
.Info = {
|
|
.Colour = {
|
|
.chScheme = ARM_2D_COLOUR_RGB565,
|
|
},
|
|
.Param = {
|
|
.bHasSource = true,
|
|
.bHasOrigin = true,
|
|
.bHasTarget = true,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_ROTATE_WITH_ALPHA,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB565),
|
|
.ptFillOrigLike = NULL,
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_WITH_ALPHA_RGB888 = {
|
|
.Info = {
|
|
.Colour = {
|
|
.chScheme = ARM_2D_COLOUR_RGB888,
|
|
},
|
|
.Param = {
|
|
.bHasSource = true,
|
|
.bHasOrigin = true,
|
|
.bHasTarget = true,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_ROTATE_WITH_ALPHA,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB888),
|
|
.ptFillOrigLike = NULL,
|
|
},
|
|
},
|
|
};
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic pop
|
|
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
|
# pragma diag_warning 174,177,188,68,513,144
|
|
#elif defined(__IS_COMPILER_GCC__)
|
|
# pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|