LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d - XL2dSprite.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 331 389 85.1 %
Date: 2024-05-12 00:16:13 Functions: 39 40 97.5 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XL2dSprite.h"
      24             : 
      25             : #include "XLResourceCache.h"
      26             : #include "XLTemporaryResource.h"
      27             : #include "XLTexture.h"
      28             : #include "XLDirector.h"
      29             : #include "XLFrameInfo.h"
      30             : #include "XL2dFrameContext.h"
      31             : #include "XL2dCommandList.h"
      32             : 
      33             : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
      34             : 
      35       23456 : Sprite::Sprite() {
      36       23456 :         _blendInfo = core::BlendInfo(core::BlendFactor::SrcAlpha, core::BlendFactor::OneMinusSrcAlpha, core::BlendOp::Add,
      37             :                         core::BlendFactor::Zero, core::BlendFactor::One, core::BlendOp::Add);
      38       23456 :         _materialInfo.setBlendInfo(_blendInfo);
      39       23456 :         _materialInfo.setDepthInfo(core::DepthInfo(false, true, core::CompareOp::Less));
      40       23456 :         _applyMode = DoNotApply;
      41       23456 : }
      42             : 
      43       23544 : Sprite::~Sprite() { }
      44             : 
      45       21965 : bool Sprite::init() {
      46       21965 :         return Sprite::init(core::SolidTextureName);
      47             : }
      48             : 
      49       23450 : bool Sprite::init(StringView textureName) {
      50       23450 :         if (!DynamicStateNode::init()) {
      51           0 :                 return false;
      52             :         }
      53             : 
      54       23450 :         _textureName = textureName.str<Interface>();
      55       23450 :         initVertexes();
      56       23450 :         return true;
      57             : }
      58             : 
      59           6 : bool Sprite::init(Rc<Texture> &&texture) {
      60           6 :         if (!DynamicStateNode::init()) {
      61           0 :                 return false;
      62             :         }
      63             : 
      64           6 :         if (texture) {
      65           6 :                 _texture = move(texture);
      66           6 :                 _isTextureLoaded = _texture->isLoaded();
      67             :         }
      68             : 
      69           6 :         initVertexes();
      70           6 :         return true;
      71             : }
      72             : 
      73          12 : void Sprite::setTexture(StringView textureName) {
      74          12 :         if (!_running) {
      75           6 :                 if (_texture) {
      76           0 :                         _texture = nullptr;
      77           0 :                         _materialDirty = true;
      78             :                 }
      79           6 :                 _textureName = textureName.str<Interface>();
      80             :         } else {
      81           6 :                 if (textureName.empty()) {
      82           0 :                         if (_texture) {
      83           0 :                                 if (_running) {
      84           0 :                                         _texture->onExit(_frameContext);
      85             :                                 }
      86           0 :                                 _texture = nullptr;
      87           0 :                                 _materialDirty = true;
      88             :                         }
      89           6 :                 } else if (!_texture || _texture->getName() != textureName) {
      90           6 :                         if (auto &cache = _director->getResourceCache()) {
      91           6 :                                 if (auto tex = cache->acquireTexture(textureName)) {
      92           6 :                                         setTexture(move(tex));
      93           6 :                                 }
      94             :                         }
      95             :                 }
      96             :         }
      97          12 : }
      98             : 
      99        1481 : void Sprite::setTexture(Rc<Texture> &&tex) {
     100        1481 :         if (_texture) {
     101          16 :                 if (!tex) {
     102           0 :                         if (_running) {
     103           0 :                                 _texture->onExit(_frameContext);
     104             :                         }
     105           0 :                         _texture = nullptr;
     106           0 :                         _textureName.clear();
     107           0 :                         _materialDirty = true;
     108           0 :                         _isTextureLoaded = false;
     109          16 :                 } else if (_texture->getName() != tex->getName()) {
     110          16 :                         if (_running) {
     111          16 :                                 _texture->onExit(_frameContext);
     112             :                         }
     113          16 :                         _texture = move(tex);
     114          16 :                         if (_running) {
     115          16 :                                 _texture->onEnter(_frameContext);
     116             :                         }
     117          16 :                         _isTextureLoaded = _texture->isLoaded();
     118          16 :                         if (_isTextureLoaded && _textureLoadedCallback) {
     119           0 :                                 _textureLoadedCallback();
     120             :                         }
     121          16 :                         _textureName = _texture->getName().str<Interface>();
     122          16 :                         updateBlendAndDepth();
     123          16 :                         _materialDirty = true;
     124             :                 }
     125             :         } else {
     126        1465 :                 if (tex) {
     127        1465 :                         _texture = move(tex);
     128        1465 :                         if (_running) {
     129           0 :                                 _texture->onEnter(_frameContext);
     130             :                         }
     131        1465 :                         _isTextureLoaded = _texture->isLoaded();
     132        1465 :                         if (_isTextureLoaded && _textureLoadedCallback) {
     133           0 :                                 _textureLoadedCallback();
     134             :                         }
     135        1465 :                         _textureName = _texture->getName().str<Interface>();
     136        1465 :                         updateBlendAndDepth();
     137        1465 :                         _materialDirty = true;
     138             :                 }
     139             :         }
     140        1481 : }
     141             : 
     142          18 : const Rc<Texture> &Sprite::getTexture() const {
     143          18 :         return _texture;
     144             : }
     145             : 
     146         750 : void Sprite::setLinearGradient(Rc<LinearGradient> &&g) {
     147         750 :         _linearGradient = move(g);
     148         750 : }
     149             : 
     150           6 : const Rc<LinearGradient> &Sprite::getLinearGradient() const {
     151           6 :         return _linearGradient;
     152             : }
     153             : 
     154           6 : void Sprite::setTextureRect(const Rect &rect) {
     155           6 :         if (!_textureRect.equals(rect)) {
     156           6 :                 _textureRect = rect;
     157           6 :                 _vertexesDirty = true;
     158             :         }
     159           6 : }
     160             : 
     161      247190 : bool Sprite::visitDraw(FrameInfo &frame, NodeFlags parentFlags) {
     162      247190 :         if (_texture) {
     163      247190 :                 auto loaded = _texture->isLoaded();
     164      247190 :                 if (loaded != _isTextureLoaded && loaded) {
     165       20813 :                         onTextureLoaded();
     166       20813 :                         _isTextureLoaded = loaded;
     167             :                 }
     168             :         }
     169      247190 :         return DynamicStateNode::visitDraw(frame, parentFlags);
     170             : }
     171             : 
     172      142982 : void Sprite::draw(FrameInfo &frame, NodeFlags flags) {
     173      142982 :         if (!_texture || !_texture->isLoaded()) {
     174          10 :                 return;
     175             :         }
     176             : 
     177      142972 :         if (_autofit != Autofit::None) {
     178       23602 :                 auto size = _texture->getExtent();
     179       23602 :                 if (_targetTextureSize != size) {
     180       16168 :                         _targetTextureSize = size;
     181       16168 :                         _vertexesDirty = true;
     182             :                 }
     183             :         }
     184             : 
     185      142972 :         if (checkVertexDirty()) {
     186       36612 :                 updateVertexes();
     187       36612 :                 _vertexesDirty = false;
     188             :         }
     189             : 
     190      142972 :         if (_vertexColorDirty) {
     191       35764 :                 updateVertexesColor();
     192       35764 :                 _vertexColorDirty = false;
     193             :         }
     194             : 
     195      142972 :         if (_materialDirty) {
     196       19658 :                 updateBlendAndDepth();
     197             : 
     198       19658 :                 auto info = getMaterialInfo();
     199       19658 :                 _materialId = frame.currentContext->context->getMaterial(info);
     200       19658 :                 if (_materialId == 0) {
     201          66 :                         _materialId = frame.currentContext->context->acquireMaterial(info, getMaterialImages(), nullptr, isMaterialRevokable());
     202          66 :                         if (_materialId == 0) {
     203           0 :                                 log::warn("Sprite", "Material for sprite with texture '", _texture->getName(), "' not found");
     204             :                         }
     205             :                 }
     206       19658 :                 _materialDirty = false;
     207             :         }
     208             : 
     209      143925 :         for (auto &it : _pendingDependencies) {
     210         953 :                 emplace_ordered(frame.currentContext->waitDependencies, move(it));
     211             :         }
     212             : 
     213      142972 :         if (_linearGradient) {
     214         370 :                 auto context = frame.contextStack.back();
     215             : 
     216         370 :                 DrawStateValues state;
     217             :                 // copy current state
     218         370 :                 auto stateId = context->getCurrentState();
     219         370 :                 if (stateId != StateIdNone) {
     220         370 :                         state = *context->getState(stateId);
     221             :                 }
     222             : 
     223         370 :                 auto newData = Rc<StateData>::create(dynamic_cast<StateData *>(state.data ? state.data.get() : nullptr));
     224         370 :                 auto transform = frame.modelTransformStack.back();
     225         370 :                 transform.scale(_contentSize.width, _contentSize.height, 1.0f);
     226             : 
     227         370 :                 newData->transform = transform;
     228         370 :                 newData->gradient = _linearGradient->pop();
     229         370 :                 state.data = newData;
     230             : 
     231         370 :                 auto newStateId = context->addState(state);
     232             : 
     233         370 :                 context->stateStack.push_back(newStateId);
     234         370 :         }
     235             : 
     236      142972 :         pushCommands(frame, flags);
     237             : 
     238      142972 :         if (_linearGradient) {
     239         370 :                 frame.contextStack.back()->stateStack.pop_back();
     240             :         }
     241             : 
     242      142972 :         _pendingDependencies.clear();
     243             : }
     244             : 
     245       23444 : void Sprite::onEnter(Scene *scene) {
     246       23444 :         Node::onEnter(scene);
     247             : 
     248       23444 :         if (!_textureName.empty()) {
     249       23444 :                 if (!_texture || _texture->getName() != _textureName) {
     250       21979 :                         if (auto &cache = _director->getResourceCache()) {
     251       21979 :                                 _texture = cache->acquireTexture(_textureName);
     252       21979 :                                 if (_texture) {
     253       21979 :                                         updateBlendAndDepth();
     254             :                                 }
     255       21979 :                                 _materialDirty = true;
     256             :                         }
     257             :                 }
     258             :         }
     259             : 
     260       23444 :         if (_texture) {
     261       23444 :                 _texture->onEnter(_frameContext);
     262             :         }
     263       23444 : }
     264             : 
     265       23444 : void Sprite::onExit() {
     266       23444 :         if (_texture) {
     267       23444 :                 _texture->onExit(_frameContext);
     268             :         }
     269       23444 :         Node::onExit();
     270       23444 : }
     271             : 
     272       27763 : void Sprite::onContentSizeDirty() {
     273       27763 :         _vertexesDirty = true;
     274       27763 :         Node::onContentSizeDirty();
     275       27763 : }
     276             : 
     277       20813 : void Sprite::onTextureLoaded() {
     278       20813 :         if (_textureLoadedCallback) {
     279           6 :                 _textureLoadedCallback();
     280             :         }
     281       20813 : }
     282             : 
     283        2890 : void Sprite::setColorMode(const core::ColorMode &mode) {
     284        2890 :         if (_colorMode != mode) {
     285        2890 :                 _colorMode = mode;
     286        2890 :                 _materialDirty = true;
     287             :         }
     288        2890 : }
     289             : 
     290          12 : void Sprite::setBlendInfo(const core::BlendInfo &info) {
     291          12 :         if (_blendInfo != info) {
     292          12 :                 _blendInfo = info;
     293          12 :                 _materialInfo.setBlendInfo(info);
     294          12 :                 _materialDirty = true;
     295             :         }
     296          12 : }
     297             : 
     298          12 : void Sprite::setLineWidth(float value) {
     299          12 :         if (_materialInfo.getLineWidth() != value) {
     300          12 :                 _materialInfo.setLineWidth(value);
     301          12 :                 _materialDirty = true;
     302             :         }
     303          12 : }
     304             : 
     305        7244 : void Sprite::setRenderingLevel(RenderingLevel level) {
     306        7244 :         if (_renderingLevel != level) {
     307        1507 :                 _renderingLevel = level;
     308        1507 :                 if (_running) {
     309          42 :                         updateBlendAndDepth();
     310             :                 }
     311             :         }
     312        7244 : }
     313             : 
     314        1465 : void Sprite::setNormalized(bool value) {
     315        1465 :         if (_normalized != value) {
     316        1465 :                 _normalized = value;
     317             :         }
     318        1465 : }
     319             : 
     320       16178 : void Sprite::setAutofit(Autofit autofit) {
     321       16178 :         if (_autofit != autofit) {
     322       16168 :                 _autofit = autofit;
     323       16168 :                 _vertexesDirty = true;
     324             :         }
     325       16178 : }
     326             : 
     327           6 : void Sprite::setAutofitPosition(const Vec2 &vec) {
     328           6 :         if (_autofitPos != vec) {
     329           6 :                 _autofitPos = vec;
     330           6 :                 if (_autofit != Autofit::None) {
     331           0 :                         _vertexesDirty = true;
     332             :                 }
     333             :         }
     334           6 : }
     335             : 
     336          10 : void Sprite::setSamplerIndex(uint16_t idx) {
     337          10 :         if (_samplerIdx != idx) {
     338          10 :                 _samplerIdx = idx;
     339          10 :                 _materialDirty = true;
     340             :         }
     341          10 : }
     342             : 
     343           6 : void Sprite::setTextureLoadedCallback(Function<void()> &&cb) {
     344           6 :         _textureLoadedCallback = move(cb);
     345           6 : }
     346             : 
     347           0 : void Sprite::pushShadowCommands(FrameInfo &frame, NodeFlags flags, const Mat4 &t, SpanView<TransformVertexData> data) {
     348           0 :         auto p = new (memory::pool::palloc(frame.pool->getPool(), sizeof(TransformVertexData) * data.size())) TransformVertexData();
     349           0 :         for (auto &it : data) {
     350           0 :                 p->transform = it.transform;
     351           0 :                 p->data = it.data;
     352           0 :                 ++ p;
     353             :         }
     354             : 
     355           0 :         FrameContextHandle2d *handle = static_cast<FrameContextHandle2d *>(frame.currentContext);
     356           0 :         handle->shadows->pushShadowArray(makeSpanView(p, data.size()), handle->getCurrentState(), frame.depthStack.back());
     357           0 : }
     358             : 
     359       52163 : void Sprite::pushCommands(FrameInfo &frame, NodeFlags flags) {
     360       52163 :         auto data = _vertexes.pop();
     361       52163 :         Mat4 newMV;
     362       52163 :         if (_normalized) {
     363           0 :                 auto &modelTransform = frame.modelTransformStack.back();
     364           0 :                 newMV.m[12] = floorf(modelTransform.m[12]);
     365           0 :                 newMV.m[13] = floorf(modelTransform.m[13]);
     366           0 :                 newMV.m[14] = floorf(modelTransform.m[14]);
     367             :         } else {
     368       52163 :                 newMV = frame.modelTransformStack.back();
     369             :         }
     370             : 
     371       52163 :         FrameContextHandle2d *handle = static_cast<FrameContextHandle2d *>(frame.currentContext);
     372             : 
     373       52163 :         if (_depthIndex > 0.0f) {
     374           0 :                 TransformVertexData transformData{newMV, data};
     375           0 :                 pushShadowCommands(frame, flags, newMV, makeSpanView(&transformData, 1));
     376           0 :         }
     377      104326 :         handle->commands->pushVertexArray(data.get(), frame.viewProjectionStack.back() * newMV,
     378       52163 :                         frame.zPath, _materialId, handle->getCurrentState(), _realRenderingLevel, frame.depthStack.back() * _displayedColor.a, _commandFlags);
     379       52163 : }
     380             : 
     381       19658 : MaterialInfo Sprite::getMaterialInfo() const {
     382       19658 :         MaterialInfo ret;
     383       19658 :         ret.images[0] = _texture->getIndex();
     384       19658 :         ret.samplers[0] = _samplerIdx;
     385       19658 :         ret.colorModes[0] = _colorMode;
     386       19658 :         ret.pipeline = _materialInfo;
     387       19658 :         return ret;
     388             : }
     389             : 
     390          66 : Vector<core::MaterialImage> Sprite::getMaterialImages() const {
     391          66 :         Vector<core::MaterialImage> ret;
     392          66 :         ret.emplace_back(_texture->getMaterialImage());
     393          66 :         return ret;
     394           0 : }
     395             : 
     396          66 : bool Sprite::isMaterialRevokable() const {
     397          66 :         return _texture && _texture->getTemporary();
     398             : }
     399             : 
     400     1657613 : void Sprite::updateColor() {
     401     1657613 :         if (_tmpColor != _displayedColor) {
     402       86884 :                 _vertexColorDirty = true;
     403       86884 :                 if (_tmpColor.a != _displayedColor.a) {
     404       31735 :                         if (_displayedColor.a == 1.0f || _tmpColor.a == 1.0f) {
     405       25309 :                                 updateBlendAndDepth();
     406             :                         }
     407             :                 }
     408       86884 :                 _tmpColor = _displayedColor;
     409             :         }
     410     1657613 : }
     411             : 
     412         185 : void Sprite::updateVertexesColor() {
     413         185 :         _vertexes.updateColor(_displayedColor);
     414         185 : }
     415             : 
     416        5908 : void Sprite::initVertexes() {
     417        5908 :         _vertexes.init(4, 6);
     418        5908 :         _vertexesDirty = true;
     419        5908 : }
     420             : 
     421          76 : void Sprite::updateVertexes() {
     422          76 :         _vertexes.clear();
     423             : 
     424          76 :         auto texExtent = _texture->getExtent();
     425          76 :         auto texSize = Size2(texExtent.width, texExtent.height);
     426             : 
     427          76 :         texSize = Size2(texSize.width * _textureRect.size.width, texSize.height * _textureRect.size.height);
     428             : 
     429          76 :         Rect contentRect;
     430          76 :         Rect textureRect;
     431             : 
     432          76 :         if (!getAutofitParams(_autofit, _autofitPos, _contentSize, Size2(texSize.width, texSize.height), contentRect, textureRect)) {
     433          26 :                 texSize = Size2(1.0f, 1.0f);
     434          26 :                 contentRect = Rect(0.0f, 0.0f, _contentSize.width, _contentSize.height);
     435          26 :                 textureRect = _textureRect;
     436             :         } else {
     437          50 :                 textureRect = Rect(
     438          50 :                         _textureRect.origin.x + textureRect.origin.x / texSize.width,
     439          50 :                         _textureRect.origin.y + textureRect.origin.y / texSize.height,
     440          50 :                         textureRect.size.width / texSize.width,
     441          50 :                         textureRect.size.height / texSize.height);
     442             :         }
     443             : 
     444          76 :         _vertexes.addQuad()
     445          76 :                 .setGeometry(Vec4(contentRect.origin.x, contentRect.origin.y, 0.0f, 1.0f), contentRect.size)
     446          76 :                 .setTextureRect(textureRect, 1.0f, 1.0f, _flippedX, _flippedY, _rotated)
     447          76 :                 .setColor(_displayedColor);
     448             : 
     449          76 :         _vertexColorDirty = false;
     450          76 : }
     451             : 
     452       68469 : void Sprite::updateBlendAndDepth() {
     453       68469 :         bool shouldBlendColors = false;
     454       68469 :         bool shouldWriteDepth = false;
     455             : 
     456       68469 :         _realRenderingLevel = getRealRenderingLevel();
     457       68469 :         switch (_realRenderingLevel) {
     458           0 :         case RenderingLevel::Default:
     459           0 :                 break;
     460       19396 :         case RenderingLevel::Solid:
     461       19396 :                 shouldWriteDepth = true;
     462       19396 :                 shouldBlendColors = false;
     463       19396 :                 break;
     464        4244 :         case RenderingLevel::Surface:
     465        4244 :                 shouldBlendColors = true;
     466        4244 :                 shouldWriteDepth = false;
     467        4244 :                 break;
     468       44829 :         case RenderingLevel::Transparent:
     469       44829 :                 shouldBlendColors = true;
     470       44829 :                 shouldWriteDepth = false;
     471       44829 :                 break;
     472             :         }
     473             : 
     474       68469 :         if (shouldBlendColors) {
     475       49073 :                 if (!_blendInfo.enabled) {
     476          34 :                         _blendInfo.enabled = 1;
     477          34 :                         _materialDirty = true;
     478             :                 }
     479             :         } else {
     480       19396 :                 if (_blendInfo.enabled) {
     481       18081 :                         _blendInfo.enabled = 0;
     482       18081 :                         _materialDirty = true;
     483             :                 }
     484             :         }
     485             : 
     486       68469 :         _materialInfo.setBlendInfo(_blendInfo);
     487             : 
     488       68469 :         auto depth = _materialInfo.getDepthInfo();
     489       68469 :         if (shouldWriteDepth) {
     490       19396 :                 if (!depth.writeEnabled) {
     491       18081 :                         depth.writeEnabled = 1;
     492       18081 :                         _materialDirty = true;
     493             :                 }
     494             :         } else {
     495       49073 :                 if (depth.writeEnabled) {
     496          34 :                         depth.writeEnabled = 0;
     497          34 :                         _materialDirty = true;
     498             :                 }
     499             :         }
     500       68469 :         if (_realRenderingLevel == RenderingLevel::Surface || _realRenderingLevel == RenderingLevel::Transparent) {
     501       49073 :                 if (depth.compare != toInt(core::CompareOp::LessOrEqual)) {
     502       23472 :                         depth.compare = toInt(core::CompareOp::LessOrEqual);
     503       23472 :                         _materialDirty = true;
     504             :                 }
     505             :         } else {
     506       19396 :                 if (depth.compare != toInt(core::CompareOp::Less)) {
     507       18075 :                         depth.compare = toInt(core::CompareOp::Less);
     508       18075 :                         _materialDirty = true;
     509             :                 }
     510             :         }
     511       68469 :         _materialInfo.setDepthInfo(depth);
     512       68469 : }
     513             : 
     514       11820 : RenderingLevel Sprite::getRealRenderingLevel() const {
     515       11820 :         auto level = _renderingLevel;
     516       11820 :         if (level == RenderingLevel::Default) {
     517        9154 :                 RenderingLevel parentLevel = RenderingLevel::Default;
     518        9154 :                 auto p = _parent;
     519       32176 :                 while (p) {
     520       23022 :                         if (auto s = dynamic_cast<Sprite *>(p)) {
     521       12052 :                                 if (s->getRenderingLevel() != RenderingLevel::Default) {
     522        8800 :                                         parentLevel = std::max(s->getRenderingLevel(), parentLevel);
     523             :                                 }
     524             :                         }
     525       23022 :                         p = p->getParent();
     526             :                 }
     527        9154 :                 if (_displayedColor.a < 1.0f || !_texture || _materialInfo.getLineWidth() != 0.0f) {
     528        8970 :                         level = RenderingLevel::Transparent;
     529         184 :                 } else if (_colorMode.getMode() == core::ColorMode::Solid) {
     530         184 :                         if (_texture->hasAlpha()) {
     531           0 :                                 level = RenderingLevel::Transparent;
     532             :                         } else {
     533         184 :                                 level = RenderingLevel::Solid;
     534             :                         }
     535             :                 } else {
     536           0 :                         auto alphaMapping = _colorMode.getA();
     537           0 :                         switch (alphaMapping) {
     538           0 :                         case core::ComponentMapping::Identity:
     539           0 :                                 if (_texture->hasAlpha()) {
     540           0 :                                         level = RenderingLevel::Transparent;
     541             :                                 } else {
     542           0 :                                         level = RenderingLevel::Solid;
     543             :                                 }
     544           0 :                                 break;
     545           0 :                         case core::ComponentMapping::Zero:
     546           0 :                                 level = RenderingLevel::Transparent;
     547           0 :                                 break;
     548           0 :                         case core::ComponentMapping::One:
     549           0 :                                 level = RenderingLevel::Solid;
     550           0 :                                 break;
     551           0 :                         default:
     552           0 :                                 level = RenderingLevel::Transparent;
     553           0 :                                 break;
     554             :                         }
     555             :                 }
     556        9154 :                 level = std::max(level, parentLevel);
     557             :         }
     558       11820 :         return level;
     559             : }
     560             : 
     561       98099 : bool Sprite::checkVertexDirty() const {
     562       98099 :         return _vertexesDirty;
     563             : }
     564             : 
     565          76 : bool Sprite::getAutofitParams(Autofit autofit, const Vec2 &autofitPos, const Size2 &contentSize, const Size2 &texSize,
     566             :                 Rect &contentRect, Rect &textureRect) {
     567             : 
     568          76 :         contentRect = Rect(Vec2::ZERO, contentSize);
     569             : 
     570          76 :         float scale = 1.0f;
     571          76 :         switch (autofit) {
     572          26 :         case Autofit::None:
     573          26 :                 return false;
     574             :                 break;
     575          10 :         case Autofit::Width: scale = texSize.width / contentSize.width; break;
     576          10 :         case Autofit::Height: scale = texSize.height / contentSize.height; break;
     577          20 :         case Autofit::Contain: scale = std::max(texSize.width / contentSize.width, texSize.height / contentSize.height); break;
     578          10 :         case Autofit::Cover: scale = std::min(texSize.width / contentSize.width, texSize.height / contentSize.height); break;
     579             :         }
     580             : 
     581          50 :         contentRect = Rect(Vec2::ZERO, contentSize);
     582          50 :         textureRect = Rect(0, 0, texSize.width, texSize.height);
     583             : 
     584          50 :         auto texSizeInView = Size2(texSize.width / scale, texSize.height / scale);
     585          50 :         if (texSizeInView.width < contentSize.width) {
     586          20 :                 contentRect.size.width -= (contentSize.width - texSizeInView.width);
     587          20 :                 contentRect.origin.x = (contentSize.width - texSizeInView.width) * autofitPos.x;
     588          30 :         } else if (texSizeInView.width > contentSize.width) {
     589           0 :                 textureRect.origin.x = (textureRect.size.width - contentSize.width * scale) * autofitPos.x;
     590           0 :                 textureRect.size.width = contentSize.width * scale;
     591             :         }
     592             : 
     593          50 :         if (texSizeInView.height < contentSize.height) {
     594          10 :                 contentRect.size.height -= (contentSize.height - texSizeInView.height);
     595          10 :                 contentRect.origin.y = (contentSize.height - texSizeInView.height) * autofitPos.y;
     596          40 :         } else if (texSizeInView.height > contentSize.height) {
     597          20 :                 textureRect.origin.y = (textureRect.size.height - contentSize.height * scale) * autofitPos.y;
     598          20 :                 textureRect.size.height = contentSize.height * scale;
     599             :         }
     600             : 
     601          50 :         return true;
     602             : }
     603             : 
     604             : }

Generated by: LCOV version 1.14