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 "components/ui_image_view.h"
17 #include "common/image.h"
18 #include "common/typed_text.h"
19 #include "draw/draw_image.h"
20 #include "draw/draw_label.h"
21 #include "engines/gfx/gfx_engine_manager.h"
22 #include "gfx_utils/file.h"
23 #include "gfx_utils/image_info.h"
24 #include "gfx_utils/mem_api.h"
25 #include "imgdecode/cache_manager.h"
26 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
27 #include "gif_lib.h"
28 #endif
29
30 namespace OHOS {
31 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
32 class GifImageAnimator : public Animator, public AnimatorCallback {
33 public:
GifImageAnimator(UIView * view,const char * src)34 GifImageAnimator(UIView* view, const char* src)
35 : Animator(this, view, 0, true),
36 gifFileType_(nullptr),
37 imageIndex_(0),
38 delayTime_(0),
39 lastRunTime_(0),
40 deltaTime_(0),
41 gifDataSize_(0),
42 src_(src)
43 {
44 }
45
~GifImageAnimator()46 virtual ~GifImageAnimator()
47 {
48 CloseGifFile();
49 }
50
51 void Callback(UIView* view) override;
52
SetGifFileType(GifFileType * gifFileType)53 void SetGifFileType(GifFileType* gifFileType)
54 {
55 gifFileType_ = gifFileType;
56 }
57
58 uint32_t SetGifFrame(GifFileType* gifFileType, int32_t imageIndex, UIImageView* imageView) const;
59 void DealGifImageData(const GifFileType* gifFileType,
60 const GifImageDesc* gifImageDesc,
61 const SavedImage* savedImage,
62 GraphicsControlBlock gcb,
63 const ColorMapObject* colorMap) const;
64 void OpenGifFile(const char* src);
65 void CloseGifFile();
66
67 private:
GetGifFileType()68 GifFileType* GetGifFileType()
69 {
70 if (gifFileType_ == nullptr) {
71 OpenGifFile(src_);
72 }
73 return gifFileType_;
74 }
75
76 GifFileType* gifFileType_;
77 int32_t imageIndex_;
78 uint32_t delayTime_;
79 uint32_t lastRunTime_;
80 uint32_t deltaTime_;
81 uint32_t gifDataSize_;
82 uint8_t* gifImageData_ = nullptr;
83 const char* src_;
84 };
85
OpenGifFile(const char * src)86 void GifImageAnimator::OpenGifFile(const char* src)
87 {
88 int error = D_GIF_SUCCEEDED;
89 GifFileType* gifFileType = DGifOpenFileName(src, &error);
90 if (error != D_GIF_SUCCEEDED) {
91 return;
92 }
93 DGifSlurp(gifFileType);
94 /* 3 : when change single pixel to byte, the buffer should divided by 8, equal to shift right 3 bits. */
95 uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3;
96 gifDataSize_ = gifFileType->SWidth * gifFileType->SHeight * pixelByteSize;
97 gifImageData_ = static_cast<uint8_t*>(UIMalloc(gifDataSize_));
98 if (gifImageData_ == nullptr) {
99 CloseGifFile();
100 return;
101 }
102 SetGifFileType(gifFileType);
103 }
104
CloseGifFile()105 void GifImageAnimator::CloseGifFile()
106 {
107 GifFileType* gifFileType = GetGifFileType();
108 if (gifFileType != nullptr) {
109 DGifCloseFile(gifFileType, nullptr);
110 }
111 if (gifImageData_ != nullptr) {
112 UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(gifImageData_)));
113 gifImageData_ = nullptr;
114 }
115 }
116
Callback(UIView * view)117 void GifImageAnimator::Callback(UIView* view)
118 {
119 if (view == nullptr) {
120 return;
121 }
122 UIImageView* imageView = static_cast<UIImageView*>(view);
123 uint32_t curTime = GetRunTime();
124 if (curTime != 0) {
125 if (curTime + deltaTime_ - lastRunTime_ >= delayTime_) {
126 deltaTime_ = curTime + deltaTime_ - lastRunTime_ - delayTime_;
127 lastRunTime_ = curTime;
128 } else {
129 return;
130 }
131 }
132 GifFileType* gifFileType = GetGifFileType();
133 if (gifFileType != nullptr) {
134 delayTime_ = SetGifFrame(gifFileType, imageIndex_, imageView);
135 imageIndex_ = (imageIndex_ < gifFileType->ImageCount - 1) ? (imageIndex_ + 1) : 0;
136 }
137 }
138
SetGifFrame(GifFileType * gifFileType,int32_t imageIndex,UIImageView * imageView) const139 uint32_t GifImageAnimator::SetGifFrame(GifFileType* gifFileType, int32_t imageIndex, UIImageView* imageView) const
140 {
141 SavedImage* savedImage = &(gifFileType->SavedImages[imageIndex]);
142 if (savedImage == nullptr) {
143 return 0;
144 }
145 GifImageDesc* gifImageDesc = &(savedImage->ImageDesc);
146 if (gifImageDesc == nullptr) {
147 return 0;
148 }
149 GraphicsControlBlock gcb;
150 int32_t ret = DGifSavedExtensionToGCB(gifFileType, imageIndex, &gcb);
151 if (ret != GIF_OK) {
152 return 0;
153 }
154 ColorMapObject* colorMap = nullptr;
155 if (gifImageDesc->ColorMap != nullptr) {
156 colorMap = gifImageDesc->ColorMap;
157 } else {
158 colorMap = gifFileType->SColorMap;
159 }
160
161 DealGifImageData(gifFileType, gifImageDesc, savedImage, gcb, colorMap);
162 if (gifImageData_ == nullptr) {
163 return 0;
164 }
165 imageView->gifFrameFlag_ = true;
166 ImageInfo gifFrame;
167 gifFrame.header.width = gifFileType->SWidth;
168 gifFrame.header.height = gifFileType->SHeight;
169 gifFrame.header.colorMode = ARGB8888;
170 gifFrame.dataSize = gifDataSize_;
171 gifFrame.data = gifImageData_;
172 imageView->SetSrc(&gifFrame);
173
174 if (gcb.DelayTime >= 0) {
175 return static_cast<uint32_t>(gcb.DelayTime) * 10; // 10: change hundredths (1/100) of a second to millisecond
176 } else {
177 return 0;
178 }
179 }
180
DealGifImageData(const GifFileType * gifFileType,const GifImageDesc * gifImageDesc,const SavedImage * savedImage,GraphicsControlBlock gcb,const ColorMapObject * colorMap) const181 void GifImageAnimator::DealGifImageData(const GifFileType* gifFileType,
182 const GifImageDesc* gifImageDesc,
183 const SavedImage* savedImage,
184 GraphicsControlBlock gcb,
185 const ColorMapObject* colorMap) const
186 {
187 if ((gifFileType == nullptr) || (gifImageDesc == nullptr) || (savedImage == nullptr) ||
188 (savedImage->RasterBits == nullptr) || (colorMap == nullptr) || (colorMap->Colors == nullptr)) {
189 return;
190 }
191 uint8_t colorIndex = 0;
192 GifColorType* gifColorType = nullptr;
193 uint32_t index = 0;
194
195 for (int32_t x = 0; x < gifFileType->SHeight; x++) {
196 for (int32_t y = 0; y < gifFileType->SWidth; y++) {
197 bool transparentColor = true;
198 if ((x >= gifImageDesc->Top) && (x < gifImageDesc->Top + gifImageDesc->Height) &&
199 (y >= gifImageDesc->Left) && (y < gifImageDesc->Left + gifImageDesc->Width)) {
200 int32_t loc = (x - gifImageDesc->Top) * gifImageDesc->Width + (y - gifImageDesc->Left);
201 colorIndex = savedImage->RasterBits[loc];
202
203 if ((gcb.DisposalMode != DISPOSE_DO_NOT) || (gcb.TransparentColor == NO_TRANSPARENT_COLOR) ||
204 (colorIndex != gcb.TransparentColor)) {
205 transparentColor = false;
206 }
207 }
208 if (transparentColor) {
209 index += 4; // 4: skip color index, keep last frame color
210 } else {
211 gifColorType = &colorMap->Colors[colorIndex];
212 gifImageData_[index++] = gifColorType->Blue;
213 gifImageData_[index++] = gifColorType->Green;
214 gifImageData_[index++] = gifColorType->Red;
215 gifImageData_[index++] = OPA_OPAQUE;
216 }
217 }
218 }
219 }
220 #endif
221
UIImageView()222 UIImageView::UIImageView()
223 : imageWidth_(0),
224 imageHeight_(0),
225 autoEnable_(true),
226 needRefresh_(false),
227 colorFormat_(UNKNOWN),
228 blurLevel_(BlurLevel::LEVEL0),
229 algorithm_(TransformAlgorithm::BILINEAR),
230 reserve_(0)
231 {
232 style_ = &(StyleDefault::GetBackgroundTransparentStyle());
233 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
234 gifImageAnimator_ = nullptr;
235 gifFrameFlag_ = false;
236 #endif
237 }
238
~UIImageView()239 UIImageView::~UIImageView()
240 {
241 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
242 RemoveAndStopGifAnimator();
243 #endif
244 if (drawTransMap_ != nullptr) {
245 delete drawTransMap_;
246 drawTransMap_ = nullptr;
247 }
248 if (contentMatrix_ != nullptr) {
249 delete contentMatrix_;
250 contentMatrix_ = nullptr;
251 }
252 }
253
SetResizeMode(ImageResizeMode mode)254 void UIImageView::SetResizeMode(ImageResizeMode mode)
255 {
256 // when automatic adaptation is enabled only save the mode, no need to update the DrawtransMap
257 if (autoEnable_) {
258 imageResizeMode_ = mode;
259 } else if (imageResizeMode_ != mode) {
260 needRefresh_ = true;
261 ReMeasure();
262 // must update the mode, before calling UpdateDrawTransMap
263 imageResizeMode_ = mode;
264 UpdateDrawTransMap(true);
265 }
266 }
267
AdjustScaleAndTranslate(Vector3<float> & scale,Vector3<int16_t> & translate,int16_t widgetWidth,int16_t widgetHeight) const268 void UIImageView::AdjustScaleAndTranslate(Vector3<float>& scale, Vector3<int16_t>& translate,
269 int16_t widgetWidth, int16_t widgetHeight) const
270 {
271 // adjust scale
272 float ratio = 1.0f;
273 switch (imageResizeMode_) {
274 case ImageResizeMode::COVER:
275 ratio = MATH_MAX(scale.x_, scale.y_);
276 break;
277 case ImageResizeMode::CONTAIN:
278 ratio = MATH_MIN(scale.x_, scale.y_);
279 break;
280 case ImageResizeMode::CENTER: // ratio is 1.0f
281 break;
282 case ImageResizeMode::SCALE_DOWN:
283 ratio = MATH_MIN(scale.x_, scale.y_);
284 ratio = MATH_MIN(ratio, 1.0f);
285 break;
286 case ImageResizeMode::FILL: // do nothing
287 return;
288 default:
289 break;
290 }
291 if (scale.x_ != ratio) {
292 scale.x_ = ratio;
293 // 0.5: adjust the x-coordinate of the content to the center of widget
294 translate.x_ += (static_cast<float>(widgetWidth) - static_cast<float>(imageWidth_) * ratio) * 0.5f;
295 }
296 if (scale.y_ != ratio) {
297 scale.y_ = ratio;
298 // 0.5: adjust the y-coordinate of the content to the center of widget
299 translate.y_ += (static_cast<float>(widgetHeight) - static_cast<float>(imageHeight_) * ratio) * 0.5f;
300 }
301 }
302
UpdateContentMatrix()303 void UIImageView::UpdateContentMatrix()
304 {
305 Rect viewRect = GetOrigRect();
306 if (autoEnable_ || (imageResizeMode_ == ImageResizeMode::NONE) ||
307 (imageWidth_ == viewRect.GetWidth() && imageHeight_ == viewRect.GetHeight()) ||
308 imageWidth_ == 0 || imageHeight_ == 0) {
309 if (contentMatrix_ != nullptr) {
310 delete contentMatrix_;
311 contentMatrix_ = nullptr;
312 }
313 return;
314 }
315 if (contentMatrix_ == nullptr) {
316 contentMatrix_ = new Matrix4<float>();
317 if (contentMatrix_ == nullptr) {
318 GRAPHIC_LOGE("can not new contentMatrix");
319 return;
320 }
321 }
322 int16_t widgetWidth = viewRect.GetWidth() - style_->paddingLeft_ - style_->paddingRight_ -
323 style_->borderWidth_ * 2; // 2: excludes the border-left and border-right
324 int16_t widgetHeight = viewRect.GetHeight() - style_->paddingTop_ - style_->paddingBottom_ -
325 style_->borderWidth_ * 2; // 2: excludes the border-top and border-bottom
326
327 float scaleX = static_cast<float>(widgetWidth) / static_cast<float>(imageWidth_);
328 float scaleY = static_cast<float>(widgetHeight) / static_cast<float>(imageHeight_);
329 Vector3<float> scale(scaleX, scaleY, 1.0f);
330 Vector3<int16_t> translate(style_->paddingLeft_ + style_->borderWidth_,
331 style_->paddingTop_ + style_->borderWidth_, 0);
332 AdjustScaleAndTranslate(scale, translate, widgetWidth, widgetHeight);
333
334 auto scaleMatrix = Matrix4<float>::Scale(scale, Vector3<float>(viewRect.GetX(), viewRect.GetY(), 0));
335 auto translateMatrix = Matrix4<float>::Translate(Vector3<float>(translate.x_, translate.y_, 0));
336 *contentMatrix_ = translateMatrix * scaleMatrix;
337 }
338
UpdateDrawTransMap(bool updateContentMatrix)339 void UIImageView::UpdateDrawTransMap(bool updateContentMatrix)
340 {
341 auto viewRect = GetOrigRect();
342 if (updateContentMatrix || (drawTransMap_ != nullptr &&
343 (drawTransMap_->GetTransMapRect().GetX() != viewRect.GetX() ||
344 drawTransMap_->GetTransMapRect().GetY() != viewRect.GetY()))) {
345 UpdateContentMatrix();
346 }
347 // has no transformation
348 if ((contentMatrix_ == nullptr) && ((transMap_ == nullptr) || transMap_->IsInvalid())) {
349 if (drawTransMap_ != nullptr) {
350 delete drawTransMap_;
351 drawTransMap_ = nullptr;
352 }
353 return;
354 }
355 if (drawTransMap_ == nullptr) {
356 drawTransMap_ = new TransformMap();
357 if (drawTransMap_ == nullptr) {
358 GRAPHIC_LOGE("can not new drawTransMap");
359 return;
360 }
361 }
362 if (contentMatrix_ != nullptr) {
363 drawTransMap_->SetTransMapRect(Rect(viewRect.GetX(), viewRect.GetY(),
364 viewRect.GetX() + imageWidth_ - 1, viewRect.GetY() + imageHeight_ - 1));
365 } else {
366 drawTransMap_->SetTransMapRect(viewRect);
367 }
368 // only contentMatrix
369 if (transMap_ == nullptr || transMap_->IsInvalid()) {
370 if (contentMatrix_ == nullptr) {
371 GRAPHIC_LOGE("Text: UpdateDrawTransMap contentMatrix_ is nullptr");
372 return;
373 }
374 drawTransMap_->SetMatrix(*contentMatrix_);
375 return;
376 }
377 // update the transMap, now the transMap is not nullptr
378 if (!(transMap_->GetTransMapRect() == viewRect)) {
379 transMap_->SetTransMapRect(viewRect);
380 }
381 // only transMap
382 if (contentMatrix_ == nullptr) {
383 *drawTransMap_ = *transMap_;
384 return;
385 }
386 // merge the transMap and content matrix
387 auto rect = transMap_->GetTransMapRect();
388 auto translate = Matrix4<float>::Translate(Vector3<float>(-rect.GetX(), -rect.GetY(), 0));
389 auto matrix = transMap_->GetTransformMatrix() * translate;
390 matrix = matrix * (*contentMatrix_);
391 drawTransMap_->SetMatrix(matrix);
392 }
393
SetHeight(int16_t height)394 void UIImageView::SetHeight(int16_t height)
395 {
396 if (GetHeight() != height) {
397 UIView::SetHeight(height);
398 UpdateDrawTransMap(true);
399 }
400 }
401
SetWidth(int16_t width)402 void UIImageView::SetWidth(int16_t width)
403 {
404 if (GetWidth() != width) {
405 UIView::SetWidth(width);
406 UpdateDrawTransMap(true);
407 }
408 }
409
OnPreDraw(Rect & invalidatedArea) const410 bool UIImageView::OnPreDraw(Rect& invalidatedArea) const
411 {
412 if ((image_.GetSrcType() == IMG_SRC_UNKNOWN)) {
413 return true;
414 }
415
416 if ((colorFormat_ == RGB565) || (colorFormat_ == RGB888)) {
417 if (GetRect().IsContains(invalidatedArea)) {
418 return true;
419 }
420 invalidatedArea.Intersect(invalidatedArea, GetRect());
421 }
422
423 return false;
424 }
425
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea)426 void UIImageView::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
427 {
428 OpacityType opa = GetMixOpaScale();
429 BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
430 baseGfxEngine->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opa);
431 if ((imageHeight_ == 0) || (imageWidth_ == 0)) {
432 return;
433 }
434 UpdateDrawTransMap();
435 Rect viewRect = GetContentRect();
436 Rect trunc(invalidatedArea);
437 if (trunc.Intersect(trunc, viewRect)) {
438 uint8_t srcType = image_.GetSrcType();
439 if ((srcType == IMG_SRC_FILE) || (srcType == IMG_SRC_VARIABLE)) {
440 Rect cordsTmp;
441 cordsTmp.SetTop(viewRect.GetY());
442 cordsTmp.SetBottom(viewRect.GetY() + imageHeight_ - 1);
443
444 if ((drawTransMap_ == nullptr) || drawTransMap_->IsInvalid()) {
445 SetCordsTmpRect(gfxDstBuffer, viewRect, trunc, cordsTmp, opa);
446 } else if ((drawTransMap_ != nullptr) && !drawTransMap_->IsInvalid()) {
447 ImageInfo imgInfo;
448 if (srcType == IMG_SRC_FILE) {
449 CacheEntry entry;
450 RetCode ret = CacheManager::GetInstance().Open(GetPath(), *style_, entry);
451 if (ret != RetCode::OK) {
452 return;
453 }
454 imgInfo = entry.GetImageInfo();
455 } else {
456 imgInfo = *(GetImageInfo());
457 }
458 uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(imgInfo.header.colorMode);
459 TransformDataInfo imageTranDataInfo = {imgInfo.header, imgInfo.data, pxSize,
460 static_cast<BlurLevel>(blurLevel_),
461 static_cast<TransformAlgorithm>(algorithm_)};
462 OpacityType opaScale = DrawUtils::GetMixOpacity(opa, style_->imageOpa_);
463 Matrix4<float> scaleMatrix = drawTransMap_->GetScaleMatrix();
464 int16_t paddingX = style_->paddingLeft_ * scaleMatrix[0][0];
465 int16_t paddingY = style_->paddingTop_ * scaleMatrix[1][1];
466 baseGfxEngine->DrawTransform(gfxDstBuffer, trunc, {paddingX, paddingY}, Color::Black(),
467 opaScale, *drawTransMap_, imageTranDataInfo);
468 }
469 }
470 }
471 }
472
SetCordsTmpRect(BufferInfo & gfxDstBuffer,Rect & viewRect,Rect & trunc,Rect & cordsTmp,OpacityType opa)473 void UIImageView::SetCordsTmpRect(BufferInfo& gfxDstBuffer, Rect& viewRect, Rect& trunc,
474 Rect& cordsTmp, OpacityType opa)
475 {
476 while (cordsTmp.GetTop() <= viewRect.GetBottom()) {
477 cordsTmp.SetLeft(viewRect.GetX());
478 cordsTmp.SetRight(viewRect.GetX() + imageWidth_ - 1);
479 while (cordsTmp.GetLeft() <= viewRect.GetRight()) {
480 image_.DrawImage(gfxDstBuffer, cordsTmp, trunc, *style_, opa);
481 cordsTmp.SetLeft(cordsTmp.GetLeft() + imageWidth_);
482 cordsTmp.SetRight(cordsTmp.GetRight() + imageWidth_);
483 }
484 cordsTmp.SetTop(cordsTmp.GetTop() + imageHeight_);
485 cordsTmp.SetBottom(cordsTmp.GetBottom() + imageHeight_);
486 }
487 }
488
SetSrc(const char * src)489 void UIImageView::SetSrc(const char* src)
490 {
491 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
492 if (src == nullptr) {
493 return;
494 }
495 const static uint8_t IMG_BYTES_TO_CHECK = 4; // 4: check 4 bytes of image file
496 char buf[IMG_BYTES_TO_CHECK] = {0};
497 int32_t fd = open(src, O_RDONLY);
498 if (fd < 0) {
499 return;
500 }
501 if (read(fd, buf, IMG_BYTES_TO_CHECK) != IMG_BYTES_TO_CHECK) {
502 close(fd);
503 return;
504 }
505 close(fd);
506 bool updated = false;
507 RemoveAndStopGifAnimator();
508 // 0x47 0x49 0x46: GIF file's header
509 if ((static_cast<uint8_t>(buf[0]) == 0x47) && (static_cast<uint8_t>(buf[1]) == 0x49) &&
510 (static_cast<uint8_t>(buf[2]) == 0x46)) { // 2: array index of GIF file's header
511 if (gifImageAnimator_ == nullptr) {
512 gifImageAnimator_ = new GifImageAnimator(this, src);
513 if (gifImageAnimator_ == nullptr) {
514 GRAPHIC_LOGE("new GifImageAnimator fail");
515 return;
516 }
517 }
518 AddAndStartGifAnimator();
519 updated = true;
520 } else {
521 updated = image_.SetSrc(src);
522 }
523 #else
524 bool updated = image_.SetSrc(src);
525 #endif
526 if (!updated) {
527 return;
528 }
529 needRefresh_ = true;
530 if (autoEnable_ || (imageResizeMode_ != ImageResizeMode::NONE)) {
531 UIImageView::ReMeasure();
532 }
533 if (imageResizeMode_ != ImageResizeMode::NONE) {
534 UpdateDrawTransMap(true);
535 }
536 Invalidate();
537 }
538
ReMeasure()539 void UIImageView::ReMeasure()
540 {
541 if (!needRefresh_) {
542 return;
543 }
544 needRefresh_ = false;
545
546 ImageHeader header = {0};
547 image_.GetHeader(header);
548
549 imageWidth_ = header.width;
550 imageHeight_ = header.height;
551 colorFormat_ = header.colorMode;
552
553 if (autoEnable_) {
554 Invalidate();
555 Resize(imageWidth_, imageHeight_);
556 Invalidate();
557 }
558 }
559
SetSrc(const ImageInfo * src)560 void UIImageView::SetSrc(const ImageInfo* src)
561 {
562 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
563 if (!gifFrameFlag_ && (gifImageAnimator_ != nullptr)) {
564 RemoveAndStopGifAnimator();
565 }
566 gifFrameFlag_ = false;
567 #endif
568 bool updated = image_.SetSrc(src);
569 if (!updated) {
570 return;
571 }
572 needRefresh_ = true;
573 if (autoEnable_ || (imageResizeMode_ != ImageResizeMode::NONE)) {
574 UIImageView::ReMeasure();
575 }
576 if (imageResizeMode_ != ImageResizeMode::NONE) {
577 UpdateDrawTransMap(true);
578 }
579 Invalidate();
580 }
581
582 #if defined(ENABLE_GIF) && (ENABLE_GIF == 1)
AddAndStartGifAnimator()583 void UIImageView::AddAndStartGifAnimator()
584 {
585 if (gifImageAnimator_ != nullptr) {
586 gifImageAnimator_->Start();
587 }
588 }
589
RemoveAndStopGifAnimator()590 void UIImageView::RemoveAndStopGifAnimator()
591 {
592 if (gifImageAnimator_ != nullptr) {
593 gifImageAnimator_->Stop();
594 delete gifImageAnimator_;
595 gifImageAnimator_ = nullptr;
596 }
597 }
598 #endif
599 } // namespace OHOS
600