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