| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- // This file is part of Desktop App Toolkit,
- // a set of libraries for developing nice desktop applications.
- //
- // For license and copyright information please follow this link:
- // https://github.com/desktop-app/legal/blob/master/LEGAL
- //
- #include "ui/effects/panel_animation.h"
- #include "ui/effects/animation_value.h"
- #include "ui/ui_utility.h"
- #include <QtGui/QPainter>
- namespace Ui {
- void RoundShadowAnimation::start(int frameWidth, int frameHeight, float64 devicePixelRatio) {
- Expects(!started());
- _frameWidth = frameWidth;
- _frameHeight = frameHeight;
- _frame = QImage(_frameWidth, _frameHeight, QImage::Format_ARGB32_Premultiplied);
- _frame.setDevicePixelRatio(devicePixelRatio);
- _frameIntsPerLine = (_frame.bytesPerLine() >> 2);
- _frameInts = reinterpret_cast<uint32*>(_frame.bits());
- _frameIntsPerLineAdded = _frameIntsPerLine - _frameWidth;
- Assert(_frame.depth() == static_cast<int>(sizeof(uint32) << 3));
- Assert(_frame.bytesPerLine() == (_frameIntsPerLine << 2));
- Assert(_frameIntsPerLineAdded >= 0);
- }
- void RoundShadowAnimation::setShadow(const style::Shadow &st) {
- _shadow.extend = st.extend * style::DevicePixelRatio();
- _shadow.left = cloneImage(st.left);
- if (_shadow.valid()) {
- _shadow.topLeft = cloneImage(st.topLeft);
- _shadow.top = cloneImage(st.top);
- _shadow.topRight = cloneImage(st.topRight);
- _shadow.right = cloneImage(st.right);
- _shadow.bottomRight = cloneImage(st.bottomRight);
- _shadow.bottom = cloneImage(st.bottom);
- _shadow.bottomLeft = cloneImage(st.bottomLeft);
- Assert(!_shadow.topLeft.isNull()
- && !_shadow.top.isNull()
- && !_shadow.topRight.isNull()
- && !_shadow.right.isNull()
- && !_shadow.bottomRight.isNull()
- && !_shadow.bottom.isNull()
- && !_shadow.bottomLeft.isNull());
- } else {
- _shadow.topLeft =
- _shadow.top =
- _shadow.topRight =
- _shadow.right =
- _shadow.bottomRight =
- _shadow.bottom =
- _shadow.bottomLeft = QImage();
- }
- }
- void RoundShadowAnimation::setCornerMasks(
- const std::array<QImage, 4> &corners) {
- setCornerMask(_topLeft, corners[0]);
- setCornerMask(_topRight, corners[1]);
- setCornerMask(_bottomLeft, corners[2]);
- setCornerMask(_bottomRight, corners[3]);
- }
- void RoundShadowAnimation::setCornerMask(Corner &corner, const QImage &image) {
- Expects(!started());
- corner.image = image;
- if (corner.valid()) {
- corner.width = corner.image.width();
- corner.height = corner.image.height();
- corner.bytes = corner.image.constBits();
- corner.bytesPerPixel = (corner.image.depth() >> 3);
- corner.bytesPerLineAdded = corner.image.bytesPerLine() - corner.width * corner.bytesPerPixel;
- Assert(corner.image.depth() == (corner.bytesPerPixel << 3));
- Assert(corner.bytesPerLineAdded >= 0);
- } else {
- corner.width = corner.height = 0;
- }
- }
- QImage RoundShadowAnimation::cloneImage(const style::icon &source) {
- if (source.empty()) return QImage();
- auto result = QImage(
- source.size() * style::DevicePixelRatio(),
- QImage::Format_ARGB32_Premultiplied);
- result.setDevicePixelRatio(style::DevicePixelRatio());
- result.fill(Qt::transparent);
- {
- QPainter p(&result);
- source.paint(p, 0, 0, source.width());
- }
- return result;
- }
- void RoundShadowAnimation::paintCorner(Corner &corner, int left, int top) {
- auto mask = corner.bytes;
- auto bytesPerPixel = corner.bytesPerPixel;
- auto bytesPerLineAdded = corner.bytesPerLineAdded;
- auto frameInts = _frameInts + top * _frameIntsPerLine + left;
- auto frameIntsPerLineAdd = _frameIntsPerLine - corner.width;
- for (auto y = 0; y != corner.height; ++y) {
- for (auto x = 0; x != corner.width; ++x) {
- auto alpha = static_cast<uint32>(*mask) + 1;
- *frameInts = anim::unshifted(anim::shifted(*frameInts) * alpha);
- ++frameInts;
- mask += bytesPerPixel;
- }
- frameInts += frameIntsPerLineAdd;
- mask += bytesPerLineAdded;
- }
- }
- void RoundShadowAnimation::paintShadow(int left, int top, int right, int bottom) {
- paintShadowCorner(left, top, _shadow.topLeft);
- paintShadowCorner(right - _shadow.topRight.width(), top, _shadow.topRight);
- paintShadowCorner(right - _shadow.bottomRight.width(), bottom - _shadow.bottomRight.height(), _shadow.bottomRight);
- paintShadowCorner(left, bottom - _shadow.bottomLeft.height(), _shadow.bottomLeft);
- paintShadowVertical(left, top + _shadow.topLeft.height(), bottom - _shadow.bottomLeft.height(), _shadow.left);
- paintShadowVertical(right - _shadow.right.width(), top + _shadow.topRight.height(), bottom - _shadow.bottomRight.height(), _shadow.right);
- paintShadowHorizontal(left + _shadow.topLeft.width(), right - _shadow.topRight.width(), top, _shadow.top);
- paintShadowHorizontal(left + _shadow.bottomLeft.width(), right - _shadow.bottomRight.width(), bottom - _shadow.bottom.height(), _shadow.bottom);
- }
- void RoundShadowAnimation::paintShadowCorner(int left, int top, const QImage &image) {
- auto imageWidth = image.width();
- auto imageHeight = image.height();
- auto imageInts = reinterpret_cast<const uint32*>(image.constBits());
- auto imageIntsPerLine = (image.bytesPerLine() >> 2);
- auto imageIntsPerLineAdded = imageIntsPerLine - imageWidth;
- if (left < 0) {
- auto shift = -base::take(left);
- imageWidth -= shift;
- imageInts += shift;
- }
- if (top < 0) {
- auto shift = -base::take(top);
- imageHeight -= shift;
- imageInts += shift * imageIntsPerLine;
- }
- if (left + imageWidth > _frameWidth) {
- imageWidth = _frameWidth - left;
- }
- if (top + imageHeight > _frameHeight) {
- imageHeight = _frameHeight - top;
- }
- if (imageWidth < 0 || imageHeight < 0) return;
- auto frameInts = _frameInts + top * _frameIntsPerLine + left;
- auto frameIntsPerLineAdd = _frameIntsPerLine - imageWidth;
- for (auto y = 0; y != imageHeight; ++y) {
- for (auto x = 0; x != imageWidth; ++x) {
- auto source = *frameInts;
- auto shadowAlpha = qMax(_frameAlpha - int(source >> 24), 0);
- *frameInts = anim::unshifted(anim::shifted(source) * 256 + anim::shifted(*imageInts) * shadowAlpha);
- ++frameInts;
- ++imageInts;
- }
- frameInts += frameIntsPerLineAdd;
- imageInts += imageIntsPerLineAdded;
- }
- }
- void RoundShadowAnimation::paintShadowVertical(int left, int top, int bottom, const QImage &image) {
- auto imageWidth = image.width();
- auto imageInts = reinterpret_cast<const uint32*>(image.constBits());
- if (left < 0) {
- auto shift = -base::take(left);
- imageWidth -= shift;
- imageInts += shift;
- }
- if (top < 0) top = 0;
- accumulate_min(bottom, _frameHeight);
- accumulate_min(imageWidth, _frameWidth - left);
- if (imageWidth < 0 || bottom <= top) return;
- auto frameInts = _frameInts + top * _frameIntsPerLine + left;
- auto frameIntsPerLineAdd = _frameIntsPerLine - imageWidth;
- for (auto y = top; y != bottom; ++y) {
- for (auto x = 0; x != imageWidth; ++x) {
- auto source = *frameInts;
- auto shadowAlpha = _frameAlpha - (source >> 24);
- *frameInts = anim::unshifted(anim::shifted(source) * 256 + anim::shifted(*imageInts) * shadowAlpha);
- ++frameInts;
- ++imageInts;
- }
- frameInts += frameIntsPerLineAdd;
- imageInts -= imageWidth;
- }
- }
- void RoundShadowAnimation::paintShadowHorizontal(int left, int right, int top, const QImage &image) {
- auto imageHeight = image.height();
- auto imageInts = reinterpret_cast<const uint32*>(image.constBits());
- auto imageIntsPerLine = (image.bytesPerLine() >> 2);
- if (top < 0) {
- auto shift = -base::take(top);
- imageHeight -= shift;
- imageInts += shift * imageIntsPerLine;
- }
- if (left < 0) left = 0;
- accumulate_min(right, _frameWidth);
- accumulate_min(imageHeight, _frameHeight - top);
- if (imageHeight < 0 || right <= left) return;
- auto frameInts = _frameInts + top * _frameIntsPerLine + left;
- auto frameIntsPerLineAdd = _frameIntsPerLine - (right - left);
- for (auto y = 0; y != imageHeight; ++y) {
- auto imagePattern = anim::shifted(*imageInts);
- for (auto x = left; x != right; ++x) {
- auto source = *frameInts;
- auto shadowAlpha = _frameAlpha - (source >> 24);
- *frameInts = anim::unshifted(anim::shifted(source) * 256 + imagePattern * shadowAlpha);
- ++frameInts;
- }
- frameInts += frameIntsPerLineAdd;
- imageInts += imageIntsPerLine;
- }
- }
- void PanelAnimation::setFinalImage(QImage &&finalImage, QRect inner) {
- Expects(!started());
- const auto pixelRatio = style::DevicePixelRatio();
- _finalImage = PixmapFromImage(
- std::move(finalImage).convertToFormat(
- QImage::Format_ARGB32_Premultiplied));
- Assert(!_finalImage.isNull());
- _finalWidth = _finalImage.width();
- _finalHeight = _finalImage.height();
- Assert(!(_finalWidth % pixelRatio));
- Assert(!(_finalHeight % pixelRatio));
- _finalInnerLeft = inner.x();
- _finalInnerTop = inner.y();
- _finalInnerWidth = inner.width();
- _finalInnerHeight = inner.height();
- Assert(!(_finalInnerLeft % pixelRatio));
- Assert(!(_finalInnerTop % pixelRatio));
- Assert(!(_finalInnerWidth % pixelRatio));
- Assert(!(_finalInnerHeight % pixelRatio));
- _finalInnerRight = _finalInnerLeft + _finalInnerWidth;
- _finalInnerBottom = _finalInnerTop + _finalInnerHeight;
- Assert(QRect(0, 0, _finalWidth, _finalHeight).contains(inner));
- setStartWidth();
- setStartHeight();
- setStartAlpha();
- setStartFadeTop();
- createFadeMask();
- setWidthDuration();
- setHeightDuration();
- setAlphaDuration();
- if (!_skipShadow) {
- setShadow(_st.shadow);
- }
- auto checkCorner = [this, inner](Corner &corner) {
- if (!corner.valid()) return;
- if ((_startWidth >= 0 && _startWidth < _finalWidth)
- || (_startHeight >= 0 && _startHeight < _finalHeight)) {
- Assert(corner.width <= inner.width());
- Assert(corner.height <= inner.height());
- }
- };
- checkCorner(_topLeft);
- checkCorner(_topRight);
- checkCorner(_bottomLeft);
- checkCorner(_bottomRight);
- }
- void PanelAnimation::setStartWidth() {
- _startWidth = qRound(_st.startWidth * _finalInnerWidth);
- if (_startWidth >= 0) Assert(_startWidth <= _finalInnerWidth);
- }
- void PanelAnimation::setStartHeight() {
- _startHeight = qRound(_st.startHeight * _finalInnerHeight);
- if (_startHeight >= 0) Assert(_startHeight <= _finalInnerHeight);
- }
- void PanelAnimation::setStartAlpha() {
- _startAlpha = qRound(_st.startOpacity * 255);
- Assert(_startAlpha >= 0 && _startAlpha < 256);
- }
- void PanelAnimation::setStartFadeTop() {
- _startFadeTop = qRound(_st.startFadeTop * _finalInnerHeight);
- }
- void PanelAnimation::createFadeMask() {
- auto resultHeight = qRound(_finalImage.height() * _st.fadeHeight);
- if (auto remove = (resultHeight % style::DevicePixelRatio())) {
- resultHeight -= remove;
- }
- auto finalAlpha = qRound(_st.fadeOpacity * 255);
- Assert(finalAlpha >= 0 && finalAlpha < 256);
- auto result = QImage(style::DevicePixelRatio(), resultHeight, QImage::Format_ARGB32_Premultiplied);
- auto ints = reinterpret_cast<uint32*>(result.bits());
- auto intsPerLineAdded = (result.bytesPerLine() >> 2) - style::DevicePixelRatio();
- auto up = (_origin == PanelAnimation::Origin::BottomLeft || _origin == PanelAnimation::Origin::BottomRight);
- auto from = up ? resultHeight : 0, to = resultHeight - from, delta = up ? -1 : 1;
- auto fadeFirstAlpha = up ? (finalAlpha + 1) : 1;
- auto fadeLastAlpha = up ? 1 : (finalAlpha + 1);
- _fadeFirst = QBrush(QColor(_st.fadeBg->c.red(), _st.fadeBg->c.green(), _st.fadeBg->c.blue(), (_st.fadeBg->c.alpha() * fadeFirstAlpha) >> 8));
- _fadeLast = QBrush(QColor(_st.fadeBg->c.red(), _st.fadeBg->c.green(), _st.fadeBg->c.blue(), (_st.fadeBg->c.alpha() * fadeLastAlpha) >> 8));
- for (auto y = from; y != to; y += delta) {
- auto alpha = static_cast<uint32>(finalAlpha * y) / resultHeight;
- auto value = (0xFFU << 24) | (alpha << 16) | (alpha << 8) | alpha;
- for (auto x = 0; x != style::DevicePixelRatio(); ++x) {
- *ints++ = value;
- }
- ints += intsPerLineAdded;
- }
- _fadeMask = PixmapFromImage(style::colorizeImage(result, _st.fadeBg));
- _fadeHeight = _fadeMask.height();
- }
- void PanelAnimation::setSkipShadow(bool skipShadow) {
- Assert(!started());
- _skipShadow = skipShadow;
- }
- void PanelAnimation::setWidthDuration() {
- _widthDuration = _st.widthDuration;
- Assert(_widthDuration >= 0.);
- Assert(_widthDuration <= 1.);
- }
- void PanelAnimation::setHeightDuration() {
- Assert(!started());
- _heightDuration = _st.heightDuration;
- Assert(_heightDuration >= 0.);
- Assert(_heightDuration <= 1.);
- }
- void PanelAnimation::setAlphaDuration() {
- Assert(!started());
- _alphaDuration = _st.opacityDuration;
- Assert(_alphaDuration >= 0.);
- Assert(_alphaDuration <= 1.);
- }
- void PanelAnimation::start() {
- Assert(!_finalImage.isNull());
- RoundShadowAnimation::start(_finalWidth, _finalHeight, _finalImage.devicePixelRatio());
- auto checkCorner = [this](const Corner &corner) {
- if (!corner.valid()) return;
- if (_startWidth >= 0) Assert(corner.width <= _startWidth);
- if (_startHeight >= 0) Assert(corner.height <= _startHeight);
- Assert(corner.width <= _finalInnerWidth);
- Assert(corner.height <= _finalInnerHeight);
- };
- checkCorner(_topLeft);
- checkCorner(_topRight);
- checkCorner(_bottomLeft);
- checkCorner(_bottomRight);
- }
- auto PanelAnimation::computeState(float64 dt, float64 opacity) const
- -> PaintState {
- auto &transition = anim::easeOutCirc;
- if (dt < _alphaDuration) {
- opacity *= transition(1., dt / _alphaDuration);
- }
- const auto widthProgress = (_startWidth < 0 || dt >= _widthDuration)
- ? 1.
- : transition(1., dt / _widthDuration);
- const auto heightProgress = (_startHeight < 0 || dt >= _heightDuration)
- ? 1.
- : transition(1., dt / _heightDuration);
- const auto frameWidth = (widthProgress < 1.)
- ? anim::interpolate(_startWidth, _finalInnerWidth, widthProgress)
- : _finalInnerWidth;
- const auto frameHeight = (heightProgress < 1.)
- ? anim::interpolate(_startHeight, _finalInnerHeight, heightProgress)
- : _finalInnerHeight;
- const auto ratio = style::DevicePixelRatio();
- return {
- .opacity = opacity,
- .widthProgress = widthProgress,
- .heightProgress = heightProgress,
- .fade = transition(1., dt),
- .width = frameWidth / ratio,
- .height = frameHeight / ratio,
- };
- }
- auto PanelAnimation::paintFrame(
- QPainter &p,
- int x,
- int y,
- int outerWidth,
- float64 dt,
- float64 opacity)
- -> PaintState {
- Assert(started());
- Assert(dt >= 0.);
- const auto pixelRatio = style::DevicePixelRatio();
- const auto state = computeState(dt, opacity);
- opacity = state.opacity;
- _frameAlpha = anim::interpolate(1, 256, opacity);
- const auto frameWidth = state.width * pixelRatio;
- const auto frameHeight = state.height * pixelRatio;
- auto frameLeft = (_origin == Origin::TopLeft || _origin == Origin::BottomLeft) ? _finalInnerLeft : (_finalInnerRight - frameWidth);
- auto frameTop = (_origin == Origin::TopLeft || _origin == Origin::TopRight) ? _finalInnerTop : (_finalInnerBottom - frameHeight);
- auto frameRight = frameLeft + frameWidth;
- auto frameBottom = frameTop + frameHeight;
- auto fadeTop = (_fadeHeight > 0) ? std::clamp(anim::interpolate(_startFadeTop, _finalInnerHeight, state.fade), 0, frameHeight) : frameHeight;
- if (auto decrease = (fadeTop % pixelRatio)) {
- fadeTop -= decrease;
- }
- auto fadeBottom = (fadeTop < frameHeight) ? std::min(fadeTop + _fadeHeight, frameHeight) : frameHeight;
- auto fadeSkipLines = 0;
- if (_origin == Origin::BottomLeft || _origin == Origin::BottomRight) {
- fadeTop = frameHeight - fadeTop;
- fadeBottom = frameHeight - fadeBottom;
- qSwap(fadeTop, fadeBottom);
- fadeSkipLines = fadeTop + _fadeHeight - fadeBottom;
- }
- fadeTop += frameTop;
- fadeBottom += frameTop;
- if (opacity < 1.) {
- _frame.fill(Qt::transparent);
- }
- {
- QPainter p(&_frame);
- p.setOpacity(opacity);
- auto painterFrameLeft = frameLeft / pixelRatio;
- auto painterFrameTop = frameTop / pixelRatio;
- auto painterFadeBottom = fadeBottom / pixelRatio;
- p.drawPixmap(painterFrameLeft, painterFrameTop, _finalImage, frameLeft, frameTop, frameWidth, frameHeight);
- if (_fadeHeight) {
- if (frameTop != fadeTop) {
- p.fillRect(painterFrameLeft, painterFrameTop, frameWidth, fadeTop - frameTop, _fadeFirst);
- }
- if (fadeTop != fadeBottom) {
- auto painterFadeTop = fadeTop / pixelRatio;
- auto painterFrameWidth = frameWidth / pixelRatio;
- p.drawPixmap(painterFrameLeft, painterFadeTop, painterFrameWidth, painterFadeBottom - painterFadeTop, _fadeMask, 0, fadeSkipLines, pixelRatio, fadeBottom - fadeTop);
- }
- if (fadeBottom != frameBottom) {
- p.fillRect(painterFrameLeft, painterFadeBottom, frameWidth, frameBottom - fadeBottom, _fadeLast);
- }
- }
- }
- // Draw corners
- paintCorner(_topLeft, frameLeft, frameTop);
- paintCorner(_topRight, frameRight - _topRight.width, frameTop);
- paintCorner(_bottomLeft, frameLeft, frameBottom - _bottomLeft.height);
- paintCorner(_bottomRight, frameRight - _bottomRight.width, frameBottom - _bottomRight.height);
- // Draw shadow upon the transparent
- auto outerLeft = frameLeft;
- auto outerTop = frameTop;
- auto outerRight = frameRight;
- auto outerBottom = frameBottom;
- if (_shadow.valid()) {
- outerLeft -= _shadow.extend.left();
- outerTop -= _shadow.extend.top();
- outerRight += _shadow.extend.right();
- outerBottom += _shadow.extend.bottom();
- }
- if (pixelRatio > 1) {
- if (auto skipLeft = (outerLeft % pixelRatio)) {
- outerLeft -= skipLeft;
- }
- if (auto skipTop = (outerTop % pixelRatio)) {
- outerTop -= skipTop;
- }
- if (auto skipRight = (outerRight % pixelRatio)) {
- outerRight += (pixelRatio - skipRight);
- }
- if (auto skipBottom = (outerBottom % pixelRatio)) {
- outerBottom += (pixelRatio - skipBottom);
- }
- }
- if (opacity == 1.) {
- // Fill above the frame top with transparent.
- auto fillTopInts = (_frameInts + outerTop * _frameIntsPerLine + outerLeft);
- auto fillWidth = (outerRight - outerLeft) * sizeof(uint32);
- for (auto fillTop = frameTop - outerTop; fillTop != 0; --fillTop) {
- memset(fillTopInts, 0, fillWidth);
- fillTopInts += _frameIntsPerLine;
- }
- // Fill to the left and to the right of the frame with transparent.
- auto fillLeft = (frameLeft - outerLeft) * sizeof(uint32);
- auto fillRight = (outerRight - frameRight) * sizeof(uint32);
- if (fillLeft || fillRight) {
- auto fillInts = _frameInts + frameTop * _frameIntsPerLine;
- for (auto y = frameTop; y != frameBottom; ++y) {
- memset(fillInts + outerLeft, 0, fillLeft);
- memset(fillInts + frameRight, 0, fillRight);
- fillInts += _frameIntsPerLine;
- }
- }
- // Fill below the frame bottom with transparent.
- auto fillBottomInts = (_frameInts + frameBottom * _frameIntsPerLine + outerLeft);
- for (auto fillBottom = outerBottom - frameBottom; fillBottom != 0; --fillBottom) {
- memset(fillBottomInts, 0, fillWidth);
- fillBottomInts += _frameIntsPerLine;
- }
- }
- if (_shadow.valid()) {
- paintShadow(outerLeft, outerTop, outerRight, outerBottom);
- }
- // Debug
- //frameInts = _frameInts;
- //auto pattern = anim::shifted((static_cast<uint32>(0xFF) << 24) | (static_cast<uint32>(0xFF) << 16) | (static_cast<uint32>(0xFF) << 8) | static_cast<uint32>(0xFF));
- //for (auto y = 0; y != _finalHeight; ++y) {
- // for (auto x = 0; x != _finalWidth; ++x) {
- // auto source = *frameInts;
- // auto sourceAlpha = (source >> 24);
- // *frameInts = anim::unshifted(anim::shifted(source) * 256 + pattern * (256 - sourceAlpha));
- // ++frameInts;
- // }
- // frameInts += _frameIntsPerLineAdded;
- //}
- p.drawImage(style::rtlpoint(x + (outerLeft / pixelRatio), y + (outerTop / pixelRatio), outerWidth), _frame, QRect(outerLeft, outerTop, outerRight - outerLeft, outerBottom - outerTop));
- return state;
- }
- } // namespace Ui
|