• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "ani_lattice.h"
17 
18 namespace OHOS::Rosen {
19 namespace Drawing {
20 const char* ANI_CLASS_ANI_LATTICE_NAME = "L@ohos/graphics/drawing/drawing/Lattice;";
21 
GetLatticeDividers(ani_env * env,ani_object dividersArray,uint32_t count,std::vector<int> & dividers)22 bool GetLatticeDividers(ani_env* env, ani_object dividersArray, uint32_t count, std::vector<int>& dividers)
23 {
24     ani_double aniLength;
25     if (ANI_OK != env->Object_GetPropertyByName_Double(dividersArray, "length", &aniLength)) {
26         ROSEN_LOGE("AniLattice::CreateImageLattice dividers are invalid");
27         return false;
28     }
29     uint32_t dividersSize = aniLength;
30 
31     if (dividersSize != count || dividersSize > 5) { // 5 is max value, the api limit max size
32         ROSEN_LOGE("AniLattice::CreateImageLattice dividers are invalid");
33         return false;
34     }
35     if (dividersSize != 0) {
36         dividers.reserve(dividersSize);
37         for (uint32_t i = 0; i < dividersSize; i++) {
38             ani_double divider;
39             ani_ref dividerRef;
40             if (ANI_OK != env->Object_CallMethodByName_Ref(
41                 dividersArray, "$_get", "I:Lstd/core/Object;", &dividerRef, (ani_int)i) ||
42                 ANI_OK != env->Object_CallMethodByName_Double(
43                     static_cast<ani_object>(dividerRef), "unboxed", ":D", &divider)) {
44                 ROSEN_LOGE("AniLattice::CreateImageLattice Incorrect parameter dividers type.");
45                 return false;
46             }
47             dividers.push_back(divider);
48         }
49     }
50     return true;
51 }
52 
GetLatticeRectTypes(ani_env * env,ani_object rectTypesArray,uint32_t count,std::vector<Lattice::RectType> & latticeRectTypes)53 bool GetLatticeRectTypes(ani_env* env, ani_object rectTypesArray, uint32_t count,
54     std::vector<Lattice::RectType>& latticeRectTypes)
55 {
56     ani_double aniLength;
57     if (ANI_OK != env->Object_GetPropertyByName_Double(rectTypesArray, "length", &aniLength)) {
58         ROSEN_LOGE("AniLattice::CreateImageLattice rectTypes are invalid");
59         return false;
60     }
61     uint32_t rectTypesSize = aniLength;
62 
63     if ((rectTypesSize != 0 && rectTypesSize != count) || rectTypesSize > 36) { // 36: max value, limit max size
64         ROSEN_LOGE("AniLattice::CreateImageLattice rectTypes are invalid");
65         return false;
66     }
67     if (rectTypesSize != 0) {
68         latticeRectTypes.reserve(rectTypesSize);
69         for (uint32_t i = 0; i < rectTypesSize; i++) {
70             ani_int rectType;
71             ani_ref rectTypeRef;
72             if (ANI_OK != env->Object_CallMethodByName_Ref(
73                 rectTypesArray, "$_get", "I:Lstd/core/Object;", &rectTypeRef, (ani_int)i) ||
74                 ANI_OK != env->EnumItem_GetValue_Int((ani_enum_item)rectTypeRef, &rectType)) {
75                 ROSEN_LOGE("AniLattice::CreateImageLattice Incorrect parameter dividers type.");
76                 return false;
77             }
78             if (rectType < 0 || rectType > 2) { // 2: FIXEDCOLOR
79                 ROSEN_LOGE("AniLattice::CreateImageLattice rectType is invalid");
80                 return false;
81             }
82             latticeRectTypes.push_back(static_cast<Lattice::RectType>(rectType));
83         }
84     }
85     return true;
86 }
87 
GetLatticeColors(ani_env * env,ani_object colorsArray,uint32_t count,std::vector<Color> & latticeColors)88 bool GetLatticeColors(ani_env* env, ani_object colorsArray, uint32_t count, std::vector<Color>& latticeColors)
89 {
90     ani_double aniLength;
91     if (ANI_OK != env->Object_GetPropertyByName_Double(colorsArray, "length", &aniLength)) {
92         ROSEN_LOGE("AniLattice::CreateImageLattice colors are invalid");
93         return false;
94     }
95     uint32_t colorsSize = aniLength;
96 
97     if ((colorsSize != 0 && colorsSize != count) || colorsSize > 36) { // 36: max value
98         ROSEN_LOGE("AniLattice::CreateImageLattice colors are invalid");
99         return false;
100     }
101 
102     ani_boolean isColorClass;
103     if (colorsSize != 0) {
104         latticeColors.reserve(colorsSize);
105         for (uint32_t i = 0; i < colorsSize; i++) {
106             ani_ref colorRef;
107             ani_double aniColor;
108             Drawing::ColorQuad colorQuad;
109             if (ANI_OK != env->Object_CallMethodByName_Ref(
110                 colorsArray, "$_get", "I:Lstd/core/Object;", &colorRef, (ani_int)i)) {
111                 ROSEN_LOGE("AniLattice::CreateImageLattice colors is invalid");
112                 return false;
113             }
114             if (i == 0) {
115                 ani_class colorClass;
116                 env->FindClass("L@ohos/graphics/common2D/common2D/Color;", &colorClass);
117                 env->Object_InstanceOf(static_cast<ani_object>(colorRef), colorClass, &isColorClass);
118             }
119 
120             if ((isColorClass && !GetColorQuadFromColorObj(env, static_cast<ani_object>(colorRef), colorQuad)) ||
121                 (!isColorClass && ANI_OK != env->Object_CallMethodByName_Double(
122                     static_cast<ani_object>(colorRef), "unboxed", ":D", &aniColor))) {
123                 ROSEN_LOGE("AniLattice::CreateImageLattice colors is invalid");
124                 return false;
125             }
126             colorQuad = isColorClass ? colorQuad : static_cast<Drawing::ColorQuad>(aniColor);
127             Drawing::Color drawingColor;
128             drawingColor.SetColorQuad(colorQuad);
129             latticeColors.push_back(drawingColor);
130         }
131     }
132     return true;
133 }
134 
AniInit(ani_env * env)135 ani_status AniLattice::AniInit(ani_env *env)
136 {
137     ani_class cls = nullptr;
138     ani_status ret = env->FindClass(ANI_CLASS_ANI_LATTICE_NAME, &cls);
139     if (ret != ANI_OK) {
140         ROSEN_LOGE("[ANI] can't find class: %{public}s", ANI_CLASS_ANI_LATTICE_NAME);
141         return ANI_NOT_FOUND;
142     }
143 
144     std::array methods = {
145         ani_native_function { "createImageLattice", nullptr,
146             reinterpret_cast<void*>(CreateImageLattice) },
147     };
148 
149     ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
150     if (ret != ANI_OK) {
151         ROSEN_LOGE("[ANI] bind methods fail: %{public}s", ANI_CLASS_ANI_LATTICE_NAME);
152         return ANI_NOT_FOUND;
153     }
154 
155     return ANI_OK;
156 }
157 
~AniLattice()158 AniLattice::~AniLattice()
159 {
160     m_lattice = nullptr;
161 }
162 
CreateImageLattice(ani_env * env,ani_object obj,ani_object xDivs,ani_object yDivs,ani_double fXCount,ani_double fYCount,ani_object fBounds,ani_object fRectTypes,ani_object fColors)163 ani_object AniLattice::CreateImageLattice(ani_env* env,
164     ani_object obj, ani_object xDivs, ani_object yDivs, ani_double fXCount,
165     ani_double fYCount, ani_object fBounds, ani_object fRectTypes, ani_object fColors)
166 {
167     uint32_t xCount = static_cast<uint32_t>(fXCount);
168     uint32_t yCount = static_cast<uint32_t>(fYCount);
169 
170     Lattice lat;
171     if (!GetLatticeDividers(env, xDivs, xCount, lat.fXDivs)) {
172         ROSEN_LOGE("AniLattice::CreateImageLattice xDividers are invalid");
173         AniThrowError(env, "Incorrect parameter0 type.");
174         return CreateAniUndefined(env);
175     }
176     if (!GetLatticeDividers(env, yDivs, yCount, lat.fYDivs)) {
177         ROSEN_LOGE("AniLattice::CreateImageLattice yDividers are invalid");
178         AniThrowError(env, "Incorrect parameter1 type.");
179         return CreateAniUndefined(env);
180     }
181     lat.fXCount = static_cast<int>(xCount);
182     lat.fYCount = static_cast<int>(yCount);
183 
184     Drawing::Rect drawingRect;
185     if (GetRectFromAniRectObj(env, fBounds, drawingRect)) {
186         lat.fBounds.push_back(Drawing::RectI(
187             drawingRect.left_, drawingRect.top_, drawingRect.right_, drawingRect.bottom_));
188     }
189 
190     ani_boolean isUndefined = ANI_TRUE;
191     ani_boolean isNull = ANI_TRUE;
192     env->Reference_IsUndefined(fRectTypes, &isUndefined);
193     env->Reference_IsNull(fRectTypes, &isNull);
194     uint32_t count = (xCount + 1) * (yCount + 1); // 1: grid size need + 1
195     if (!isUndefined && !isNull) {
196         if (!GetLatticeRectTypes(env, fRectTypes, count, lat.fRectTypes)) {
197             AniThrowError(env, "Incorrect parameter6 type.");
198             return CreateAniUndefined(env);
199         }
200     }
201 
202     env->Reference_IsUndefined(fColors, &isUndefined);
203     env->Reference_IsNull(fColors, &isNull);
204     if (!isUndefined && !isNull) {
205         if (!GetLatticeColors(env, fColors, count, lat.fColors)) {
206             AniThrowError(env, "Incorrect parameter7 type.");
207             return CreateAniUndefined(env);
208         }
209     }
210 
211     AniLattice* aniLattice = new AniLattice(std::make_shared<Lattice>(lat));
212     ani_object aniObj = CreateAniObjectStatic(env, ANI_CLASS_ANI_LATTICE_NAME, aniLattice);
213     return aniObj;
214 }
215 
GetLattice()216 std::shared_ptr<Lattice> AniLattice::GetLattice()
217 {
218     return m_lattice;
219 }
220 } // namespace Drawing
221 } // namespace OHOS::Rosen
222