1/* 2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "gfx_utils/transform.h" 17 18#include "gfx_utils/graphic_math.h" 19namespace OHOS { 20constexpr uint8_t VERTEX_NUM_MIN = 3; 21 22TransformMap::TransformMap() 23{ 24 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f, 1.0f, 1.0f), Vector3<float>(0, 0, 0)); 25 rotate_ = Matrix4<float>::Rotate(0, Vector3<float>(0, 0, 0), Vector3<float>(0, 0, 0)); 26 shear_ = Matrix4<float>::Shear(Vector2<float>(0, 0), Vector2<float>(0, 0), Vector2<float>(0, 0)); 27 translate_ = Matrix4<float>::Translate(Vector3<float>(0, 0, 0)); 28 trans_[ROTATE] = &rotate_; 29 trans_[SCALE] = &scale_; 30 trans_[SHEAR] = &shear_; 31 trans_[TRANSLATE] = &translate_; 32 opOrder_[ROTATE] = ROTATE; 33 opOrder_[SCALE] = SCALE; 34 opOrder_[SHEAR] = SHEAR; 35 opOrder_[TRANSLATE] = TRANSLATE; 36 37 UpdateMap(); 38} 39 40TransformMap::TransformMap(const Rect& rect) 41{ 42 rect_ = rect; 43 polygon_ = rect; 44 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f, 1.0f, 1.0f), Vector3<float>(0, 0, 0)); 45 rotate_ = Matrix4<float>::Rotate(0, Vector3<float>(0, 0, 0), Vector3<float>(0, 0, 0)); 46 shear_ = Matrix4<float>::Shear(Vector2<float>(0, 0), Vector2<float>(0, 0), Vector2<float>(0, 0)); 47 translate_ = Matrix4<float>::Translate(Vector3<float>(0, 0, 0)); 48 trans_[ROTATE] = &rotate_; 49 trans_[SCALE] = &scale_; 50 trans_[SHEAR] = &shear_; 51 trans_[TRANSLATE] = &translate_; 52 opOrder_[ROTATE] = ROTATE; 53 opOrder_[SCALE] = SCALE; 54 opOrder_[SHEAR] = SHEAR; 55 opOrder_[TRANSLATE] = TRANSLATE; 56 57 UpdateMap(); 58} 59 60bool TransformMap::GetClockWise() const 61{ 62 int16_t count = 0; 63 64 uint8_t vertexNum = polygon_.GetVertexNum(); 65 if (vertexNum < VERTEX_NUM_MIN) { 66 return false; 67 } 68 69 for (uint8_t i = 0; i < vertexNum; i++) { 70 uint8_t j = (i + 1) % vertexNum; // 1: the next vertex 71 uint8_t k = (i + 2) % vertexNum; // 2: the after next vertex 72 int32_t c = (static_cast<int32_t>(polygon_[j].x_ - polygon_[i].x_) * (polygon_[k].y_ - polygon_[j].y_)) - 73 (static_cast<int32_t>(polygon_[j].y_ - polygon_[i].y_) * (polygon_[k].x_ - polygon_[j].x_)); 74 if (c < 0) { 75 count--; 76 } else if (c > 0) { 77 count++; 78 } 79 } 80 if (count > 0) { 81 return true; 82 } 83 return false; 84} 85 86void TransformMap::SetTransMapRect(const Rect& rect) 87{ 88 rect_ = rect; 89 polygon_ = rect; 90 if (isInternalMatrix_) { 91 UpdateMap(); 92 } else { 93 SetMatrix(matrixOrig_); 94 } 95} 96 97void TransformMap::Scale(const Vector2<float>& scale, const Vector2<float>& pivot) 98{ 99 Scale(Vector3<float>(scale.x_, scale.y_, 1.0f), Vector3<float>(pivot.x_, pivot.y_, 0)); 100} 101 102void TransformMap::Scale(const Vector3<float>& scale, const Vector3<float>& pivot) 103{ 104 scaleCoeff_ = scale; 105 scalePivot_ = pivot; 106 AddOp(SCALE); 107 UpdateMap(); 108} 109 110bool TransformMap::IsInvalid() const 111{ 112 if (isInvalid_ || isIdentity_) { 113 return true; 114 } 115 116 for (uint8_t i = 0; i < polygon_.GetVertexNum(); i++) { 117 if (polygon_[i].x_ != 0 || polygon_[i].y_ != 0) { 118 return false; 119 } 120 } 121 return true; 122} 123 124void TransformMap::Rotate(int16_t angle, const Vector2<float>& pivot) 125{ 126 Rotate(angle, Vector3<float>(pivot.x_, pivot.y_, 0), Vector3<float>(pivot.x_, pivot.y_, 1.0f)); 127} 128 129void TransformMap::Rotate(int16_t angle, const Vector3<float>& rotatePivotStart, const Vector3<float>& rotatePivotEnd) 130{ 131 angle_ = angle; 132 rotatePivotStart_ = rotatePivotStart; 133 rotatePivotEnd_ = rotatePivotEnd; 134 AddOp(ROTATE); 135 UpdateMap(); 136} 137 138void TransformMap::Translate(const Vector2<int16_t>& trans) 139{ 140 Translate(Vector3<int16_t>(trans.x_, trans.y_, 0)); 141} 142 143void TransformMap::Translate(const Vector3<int16_t>& trans) 144{ 145 translate_ = Matrix4<float>::Translate(Vector3<float>(trans.x_, trans.y_, trans.z_)); 146 AddOp(TRANSLATE); 147 UpdateMap(); 148} 149 150void TransformMap::Translate(const Vector2<float>& trans) 151{ 152 Translate(Vector3<float>(trans.x_, trans.y_, 0)); 153} 154 155void TransformMap::Translate(const Vector3<float>& trans) 156{ 157 translate_ = Matrix4<float>::Translate(trans); 158 AddOp(TRANSLATE); 159 UpdateMap(); 160} 161 162void TransformMap::Shear(const Vector2<float>& shearX, const Vector2<float>& shearY, const Vector2<float>& shearZ) 163{ 164 shearX_ = shearX; 165 shearY_ = shearY; 166 shearZ_ = shearZ; 167 AddOp(SHEAR); 168 UpdateMap(); 169} 170 171Point TransformMap::GetOrigPoint(const Point& point, const Rect& relativeRect) 172{ 173 Rect rect = Rect(point.x, point.y, point.x, point.y); 174 Rect rectTemp = rect_; 175 Polygon polygonTemp = polygon_; 176 short rectX = relativeRect.GetX(); 177 short rectY = relativeRect.GetY(); 178 179 rect_ = rect; 180 polygon_ = rect; 181 trans_[ROTATE] = &rotate_; 182 trans_[SCALE] = &scale_; 183 trans_[SHEAR] = &shear_; 184 trans_[TRANSLATE] = &translate_; 185 rotate_ = Matrix4<float>::Rotate( 186 angle_, Vector3<float>(rotatePivotStart_.x_ + rectX, rotatePivotStart_.y_ + rectY, rotatePivotStart_.z_), 187 Vector3<float>(rotatePivotEnd_.x_ + rectX, rotatePivotEnd_.y_ + rectY, rotatePivotEnd_.z_)); 188 scale_ = Matrix4<float>::Scale(Vector3<float>(1.0f / scaleCoeff_.x_, 1.0f / scaleCoeff_.y_, scaleCoeff_.z_), 189 Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_)); 190 191 shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_); 192 shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rectX, -rectY, 0)); 193 shear_ = Matrix4<float>::Translate(Vector3<float>(rectX, rectY, 0)) * shear_; 194 matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) * 195 (*trans_[opOrder_[ROTATE]]); 196 197 float x = rectX + cameraPosition_.x_; 198 float y = rectY + cameraPosition_.y_; 199 float z = 0; 200 Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z)); 201 Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z)); 202 Matrix4<float> perspectiveMatrix; 203 perspectiveMatrix[2][2] = 0; // 2 : index 204 if (!FloatEqual(cameraDistance_, 0)) { 205 perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index 206 } 207 perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera); 208 matrix_ = perspectiveMatrix_ * matrix_; 209 SetMatrix(matrix_, true); 210 Rect r = polygon_.MakeAABB(); 211 rect_ = rectTemp; 212 polygon_ = polygonTemp; 213 scale_ = Matrix4<float>::Scale(scaleCoeff_, 214 Vector3<float>(scalePivot_.x_ + rectX, scalePivot_.y_ + rectY, scalePivot_.z_)); 215 return {r.GetRight(), r.GetBottom()}; 216} 217 218bool TransformMap::operator==(const TransformMap& other) const 219{ 220 if (rotate_ == other.rotate_ && translate_ == other.translate_ && scale_ == other.scale_ && 221 rect_ == other.rect_ && matrix_ == other.matrix_) { 222 return true; 223 } 224 return false; 225} 226 227void TransformMap::SetCameraDistance(int16_t distance) 228{ 229 cameraDistance_ = distance; 230 UpdateMap(); 231} 232 233void TransformMap::SetCameraPosition(const Vector2<float>& position) 234{ 235 cameraPosition_ = position; 236 UpdateMap(); 237} 238 239bool TransformMap::Is3DTransform() const 240{ 241 return is3d_; 242} 243 244void TransformMap::UpdateMap() 245{ 246 trans_[ROTATE] = &rotate_; 247 trans_[SCALE] = &scale_; 248 trans_[SHEAR] = &shear_; 249 trans_[TRANSLATE] = &translate_; 250 rotate_ = 251 Matrix4<float>::Rotate(angle_, 252 Vector3<float>(rotatePivotStart_.x_ + rect_.GetX(), rotatePivotStart_.y_ + rect_.GetY(), 253 rotatePivotStart_.z_), 254 Vector3<float>(rotatePivotEnd_.x_ + rect_.GetX(), rotatePivotEnd_.y_ + rect_.GetY(), rotatePivotEnd_.z_)); 255 256 scale_ = Matrix4<float>::Scale(scaleCoeff_, 257 Vector3<float>(scalePivot_.x_ + rect_.GetX(), scalePivot_.y_ + rect_.GetY(), scalePivot_.z_)); 258 259 shear_ = Matrix4<float>::Shear(shearX_, shearY_, shearZ_); 260 shear_ = shear_ * Matrix4<float>::Translate(Vector3<float>(-rect_.GetX(), -rect_.GetY(), 0)); 261 shear_ = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0)) * shear_; 262 263 matrix_ = (*trans_[opOrder_[TRANSLATE]]) * (*trans_[opOrder_[SHEAR]]) * (*trans_[opOrder_[SCALE]]) * 264 (*trans_[opOrder_[ROTATE]]); 265 266 float x = rect_.GetX() + cameraPosition_.x_; 267 float y = rect_.GetY() + cameraPosition_.y_; 268 float z = 0; 269 Matrix4<float> translateFromCamera = Matrix4<float>::Translate(Vector3<float>(-x, -y, -z)); 270 Matrix4<float> translateToCamera = Matrix4<float>::Translate(Vector3<float>(x, y, z)); 271 Matrix4<float> perspectiveMatrix; 272 perspectiveMatrix[2][2] = 0; // 2 : index 273 if (!FloatEqual(cameraDistance_, 0)) { 274 perspectiveMatrix[2][3] = -1.0f / cameraDistance_; // 2 3 : index 275 } 276 perspectiveMatrix_ = translateToCamera * (perspectiveMatrix * translateFromCamera); 277 matrix_ = perspectiveMatrix_ * matrix_; 278 SetMatrix(matrix_, true); 279} 280 281void TransformMap::SetMatrix(const Matrix4<float>& matrix, bool isInternalMatrix) 282{ 283 isInternalMatrix_ = isInternalMatrix; 284 polygon_ = rect_; 285 matrixOrig_ = matrix; 286 uint8_t vertexNum = polygon_.GetVertexNum(); 287 Vector4<float> imgPoint4; 288 is3d_ = false; 289 for (uint8_t i = 0; i < vertexNum; i++) { 290 Vector4<float> point(polygon_[i].x_, polygon_[i].y_, 0, 1.0f); 291 imgPoint4 = matrix * point; 292 if (!FloatEqual(imgPoint4.w_, 1)) { 293 is3d_ = true; 294 } 295 if (!FloatEqual(imgPoint4.w_, 0)) { 296 imgPoint4.x_ /= imgPoint4.w_; 297 imgPoint4.y_ /= imgPoint4.w_; 298 } 299 if (imgPoint4.x_ < COORD_MIN) { 300 polygon_[i].x_ = COORD_MIN; 301 } else if (imgPoint4.x_ > COORD_MAX) { 302 polygon_[i].x_ = COORD_MAX; 303 } else { 304 polygon_[i].x_ = MATH_ROUND(imgPoint4.x_); 305 } 306 307 if (imgPoint4.y_ < COORD_MIN) { 308 polygon_[i].y_ = COORD_MIN; 309 } else if (imgPoint4.y_ > COORD_MAX) { 310 polygon_[i].y_ = COORD_MAX; 311 } else { 312 polygon_[i].y_ = MATH_ROUND(imgPoint4.y_); 313 } 314 } 315 isIdentity_ = IsIdentity(const_cast<Matrix4<float>&>(matrix)); 316 Matrix4<float> translate = Matrix4<float>::Translate(Vector3<float>(rect_.GetX(), rect_.GetY(), 0)); 317 matrix_ = matrix * translate; 318 /* 0 1 2 3 : index of matrix */ 319 Matrix3<float> matrix3(matrix_[0][0], matrix_[0][1], matrix_[0][3], 320 matrix_[1][0], matrix_[1][1], matrix_[1][3], 321 matrix_[3][0], matrix_[3][1], matrix_[3][3]); 322 invMatrix_ = matrix3.Inverse(); 323} 324 325void TransformMap::AddOp(uint8_t op) 326{ 327 uint8_t index = 0; 328 for (; index < TRANS_NUM; index++) { 329 if (opOrder_[index] == op) { 330 break; 331 } 332 } 333 for (; index < TRANSLATE; index++) { 334 opOrder_[index] = opOrder_[index + 1]; 335 } 336 opOrder_[TRANSLATE] = op; 337} 338 339void Rotate(const Vector2<int16_t>& point, int16_t angle, const Vector2<int16_t>& pivot, Vector2<int16_t>& out) 340{ 341 float sinma = Sin(angle); 342 float cosma = Sin(angle + 90); // 90: cos 343 344 int16_t xt = point.x_ - pivot.x_; 345 int16_t yt = point.y_ - pivot.y_; 346 347 /* 0.5: round up */ 348 float temp = cosma * xt - sinma * yt; 349 out.x_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.x_; 350 temp = sinma * xt + cosma * yt; 351 out.y_ = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f)) + pivot.y_; 352} 353 354void Rotate(const Line& origLine, int16_t angle, const Vector2<int16_t>& pivot, Line& out) 355{ 356 Vector2<int16_t> pt1 = origLine[0]; 357 Vector2<int16_t> pt2 = origLine[1]; 358 359 Rotate(pt1, angle, pivot, out[1]); // 1: the first point of line 360 Rotate(pt2, angle, pivot, out[2]); // 2: the second point of line 361} 362 363void Rotate(const Rect& origRect, int16_t angle, const Vector2<int16_t>& pivot, Polygon& out) 364{ 365 Vector2<int16_t> pt1 = {origRect.GetLeft(), origRect.GetTop()}; 366 Vector2<int16_t> pt2 = {origRect.GetRight(), origRect.GetTop()}; 367 Vector2<int16_t> pt3 = {origRect.GetRight(), origRect.GetBottom()}; 368 Vector2<int16_t> pt4 = {origRect.GetLeft(), origRect.GetBottom()}; 369 370 Rotate(pt1, angle, pivot, out[1]); // 1: the first point 371 Rotate(pt2, angle, pivot, out[2]); // 2: the second point 372 Rotate(pt3, angle, pivot, out[3]); // 3: the third point 373 Rotate(pt4, angle, pivot, out[4]); // 4: the fourth point 374 375 out.SetVertexNum(4); // 4: number of vertex 376} 377} // namespace OHOS 378