This is an automated email from the git hooks/post-receive script. thansen pushed a commit to branch master in repository aseprite.
commit a2e33ffbca0f8d86e6469e495ba0ced445a26537 Author: David Capello <[email protected]> Date: Tue Sep 15 10:57:43 2015 -0300 Use iterators to improve Timeline drawing performance With this change we avoid calling several times LayerImage::cel() to draw each cel. --- src/app/ui/timeline.cpp | 143 +++++++++++++++++++++++++++++++----------------- src/app/ui/timeline.h | 7 ++- 2 files changed, 99 insertions(+), 51 deletions(-) diff --git a/src/app/ui/timeline.cpp b/src/app/ui/timeline.cpp index 1faafe6..498d02d 100644 --- a/src/app/ui/timeline.cpp +++ b/src/app/ui/timeline.cpp @@ -105,6 +105,17 @@ enum { PART_FRAME_TAG, }; +struct Timeline::DrawCelData { + CelIterator begin; + CelIterator end; + CelIterator it; + CelIterator prevIt; // Previous Cel to "it" + CelIterator nextIt; // Next Cel to "it" + CelIterator activeIt; // Active Cel iterator + CelIterator firstLink; // First link to the active cel + CelIterator lastLink; // Last link to the active cel +}; + Timeline::Timeline() : Widget(kGenericWidget) , m_context(UIContext::instance()) @@ -890,6 +901,7 @@ void Timeline::onPaint(ui::PaintEvent& ev) } // Draw each visible layer. + DrawCelData data; for (layer=last_layer; layer>=first_layer; --layer) { { IntersectClip clip(g, getLayerHeadersBounds()); @@ -897,27 +909,73 @@ void Timeline::onPaint(ui::PaintEvent& ev) drawLayer(g, layer); } - // Get the first CelIterator to be drawn (it is the first cel with cel->frame >= first_frame) - CelIterator it, end; - Layer* layerPtr = m_layers[layer]; - if (layerPtr->isImage()) { - it = static_cast<LayerImage*>(layerPtr)->getCelBegin(); - end = static_cast<LayerImage*>(layerPtr)->getCelEnd(); - for (; it != end && (*it)->frame() < first_frame; ++it) - ; - } - IntersectClip clip(g, getCelsBounds()); if (!clip) continue; + // Get the first CelIterator to be drawn (it is the first cel with cel->frame >= first_frame) + LayerImage* layerPtr = static_cast<LayerImage*>(m_layers[layer]); + data.begin = layerPtr->getCelBegin(); + data.end = layerPtr->getCelEnd(); + data.it = layerPtr->findFirstCelIteratorAfter(first_frame); + if (data.it != data.begin) + --data.it; + + data.prevIt = data.end; + data.nextIt = (data.it != data.end ? data.it+1: data.end); + + // Calculate link range for the active cel + data.firstLink = data.end; + data.lastLink = data.end; + + if (layerPtr == m_layer) { + data.activeIt = layerPtr->findCelIterator(m_frame); + if (data.activeIt != data.end) { + data.firstLink = data.activeIt; + data.lastLink = data.activeIt; + + ObjectId imageId = (*data.activeIt)->image()->id(); + + auto it2 = data.activeIt; + if (it2 != data.begin) { + do { + --it2; + if ((*it2)->image()->id() == imageId) { + data.firstLink = it2; + if ((*data.firstLink)->frame() < first_frame) + break; + } + } while (it2 != data.begin); + } + + it2 = data.activeIt; + while (it2 != data.end) { + if ((*it2)->image()->id() == imageId) { + data.lastLink = it2; + if ((*data.lastLink)->frame() > last_frame) + break; + } + ++it2; + } + } + } + else + data.activeIt = data.end; + // Draw every visible cel for each layer. for (frame=first_frame; frame<=last_frame; ++frame) { - Cel* cel = (layerPtr->isImage() && it != end && (*it)->frame() == frame ? *it: NULL); - drawCel(g, layer, frame, cel); + Cel* cel = + (data.it != data.end && + (*data.it)->frame() == frame ? *data.it: nullptr); - if (cel) - ++it; // Go to next cel + drawCel(g, layer, frame, cel, &data); + + if (cel) { + data.prevIt = data.it; + data.it = data.nextIt; // Point to next cel + if (data.nextIt != data.end) + ++data.nextIt; + } } } @@ -1303,10 +1361,10 @@ void Timeline::drawLayer(ui::Graphics* g, LayerIndex layerIdx) } } -void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Cel* cel) +void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Cel* cel, DrawCelData* data) { SkinTheme::Styles& styles = skinTheme()->styles; - Layer* layer = m_layers[layerIndex]; + LayerImage* layer = static_cast<LayerImage*>(m_layers[layerIndex]); Image* image = (cel ? cel->image(): NULL); bool is_hover = (m_hot.part == PART_CEL && m_hot.layer == layerIndex && @@ -1330,8 +1388,13 @@ void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Ce style = styles.timelineEmptyFrame(); } else { - Cel* left = (layer->isImage() ? layer->cel(frame-1): NULL); - Cel* right = (layer->isImage() ? layer->cel(frame+1): NULL); + // Calculate which cel is next to this one (in previous and next + // frame). + Cel* left = (data->prevIt != data->end ? *data->prevIt: nullptr); + Cel* right = (data->nextIt != data->end ? *data->nextIt: nullptr); + if (left && left->frame() != frame-1) left = nullptr; + if (right && right->frame() != frame+1) right = nullptr; + ObjectId leftImg = (left ? left->image()->id(): 0); ObjectId rightImg = (right ? right->image()->id(): 0); fromLeft = (leftImg == cel->image()->id()); @@ -1349,44 +1412,22 @@ void Timeline::drawCel(ui::Graphics* g, LayerIndex layerIndex, frame_t frame, Ce drawPart(g, bounds, NULL, style, is_active, is_hover); // Draw decorators to link the activeCel with its links. - if (layer == m_layer) { - Cel* activeCel = m_layer->cel(m_frame); - if (activeCel) - drawCelLinkDecorators(g, bounds, cel, activeCel, frame, is_active, is_hover); - } + if (data->activeIt != data->end) + drawCelLinkDecorators(g, bounds, cel, frame, is_active, is_hover, data); } void Timeline::drawCelLinkDecorators(ui::Graphics* g, const gfx::Rect& bounds, - Cel* cel, Cel* activeCel, frame_t frame, bool is_active, bool is_hover) + Cel* cel, frame_t frame, bool is_active, bool is_hover, + DrawCelData* data) { SkinTheme::Styles& styles = skinTheme()->styles; - ObjectId imageId = activeCel->image()->id(); - - // Link in some cel at the left side - bool left = false; - for (frame_t fr=frame-1; fr>=0; --fr) { - Cel* c = m_layer->cel(fr); - if (c && c->image()->id() == imageId) { - left = true; - break; - } - } + ObjectId imageId = (*data->activeIt)->image()->id(); - // Link in some cel at the right side - bool right = false; - for (frame_t fr=frame+1; fr<m_sprite->totalFrames(); ++fr) { - Cel* c = m_layer->cel(fr); - if (c && c->image()->id() == imageId) { - right = true; - break; - } - } + // Links at the left or right side + bool left = (data->firstLink != data->end ? frame > (*data->firstLink)->frame(): false); + bool right = (data->lastLink != data->end ? frame < (*data->lastLink)->frame(): false); - if (!cel || cel->image()->id() != imageId) { - if (left && right) - drawPart(g, bounds, NULL, styles.timelineBothLinks(), is_active, is_hover); - } - else { + if (cel && cel->image()->id() == imageId) { if (left) { Cel* prevCel = m_layer->cel(cel->frame()-1); if (!prevCel || prevCel->image()->id() != imageId) @@ -1398,6 +1439,10 @@ void Timeline::drawCelLinkDecorators(ui::Graphics* g, const gfx::Rect& bounds, drawPart(g, bounds, NULL, styles.timelineRightLink(), is_active, is_hover); } } + else { + if (left && right) + drawPart(g, bounds, NULL, styles.timelineBothLinks(), is_active, is_hover); + } } void Timeline::drawFrameTags(ui::Graphics* g) diff --git a/src/app/ui/timeline.h b/src/app/ui/timeline.h index 94d3852..e3b85de 100644 --- a/src/app/ui/timeline.h +++ b/src/app/ui/timeline.h @@ -138,6 +138,8 @@ namespace app { void onCancel(Context* ctx) override; private: + struct DrawCelData; + struct Hit { int part; LayerIndex layer; @@ -193,9 +195,10 @@ namespace app { void drawHeader(ui::Graphics* g); void drawHeaderFrame(ui::Graphics* g, frame_t frame); void drawLayer(ui::Graphics* g, LayerIndex layerIdx); - void drawCel(ui::Graphics* g, LayerIndex layerIdx, frame_t frame, Cel* cel); + void drawCel(ui::Graphics* g, LayerIndex layerIdx, frame_t frame, Cel* cel, DrawCelData* data); void drawCelLinkDecorators(ui::Graphics* g, const gfx::Rect& bounds, - Cel* cel, Cel* activeCel, frame_t frame, bool is_active, bool is_hover); + Cel* cel, frame_t frame, bool is_active, bool is_hover, + DrawCelData* data); void drawFrameTags(ui::Graphics* g); void drawRangeOutline(ui::Graphics* g); void drawPaddings(ui::Graphics* g); -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

