void Element::paintHighlight( Painter &p, int geometryHeight) const { const auto animms = delegate()->elementHighlightTime(this); if (!animms || animms >= st::activeFadeInDuration + st::activeFadeOutDuration) { return; } const auto top = marginTop(); const auto bottom = marginBottom(); const auto fill = qMin(top, bottom); const auto skiptop = top - fill; const auto fillheight = fill + geometryHeight + fill; const auto dt = (animms > st::activeFadeInDuration) ? (1. - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration)); const auto o = p.opacity(); p.setOpacity(o * dt); p.fillRect( 0, skiptop, width(), fillheight, st::defaultTextPalette.selectOverlay); p.setOpacity(o); }
void ServiceMessagePainter::paint(Painter &p, const HistoryService *message, const PaintContext &context, int height) { int left = 0, width = 0; message->countPositionAndSize(left, width); if (width < 1) return; uint64 fullAnimMs = App::main() ? App::main()->animActiveTimeStart(message) : 0; if (fullAnimMs > 0 && fullAnimMs <= context.ms) { int animms = context.ms - fullAnimMs; if (animms > st::activeFadeInDuration + st::activeFadeOutDuration) { App::main()->stopAnimActive(); } else { int skiph = st::msgServiceMargin.top() - st::msgServiceMargin.bottom(); textstyleSet(&st::inTextStyle); float64 dt = (animms > st::activeFadeInDuration) ? (1 - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration)); float64 o = p.opacity(); p.setOpacity(o * dt); p.fillRect(0, skiph, message->history()->width, message->height() - skiph, textstyleCurrent()->selectOverlay->b); p.setOpacity(o); } } textstyleSet(&st::serviceTextStyle); if (auto media = message->getMedia()) { height -= st::msgServiceMargin.top() + media->height(); int32 left = st::msgServiceMargin.left() + (width - media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top(); p.translate(left, top); media->draw(p, context.clip.translated(-left, -top), message->toMediaSelection(context.selection), context.ms); p.translate(-left, -top); } QRect trect(QRect(left, st::msgServiceMargin.top(), width, height).marginsAdded(-st::msgServicePadding)); paintBubble(p, left, width, message->_text, trect); if (width > message->maxWidth()) { left += (width - message->maxWidth()) / 2; width = message->maxWidth(); } p.setBrush(Qt::NoBrush); p.setPen(st::msgServiceColor); p.setFont(st::msgServiceFont); message->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false); textstyleRestore(); }
void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, const style::color &color) { float64 o = p.opacity(); p.setOpacity(o * _opacity); QPen pen(color->p), was(p.pen()); pen.setWidth(thickness); p.setPen(pen); int32 len = MinArcLength + a_arcEnd.current(); int32 from = QuarterArcLength - a_arcStart.current() - len; if (rtl()) { from = QuarterArcLength - (from - QuarterArcLength) - len; if (from < 0) from += FullArcLength; } p.setRenderHint(QPainter::HighQualityAntialiasing); p.drawArc(inner, from, len); p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setPen(was); p.setOpacity(o); }
void InfiniteRadialAnimation::draw( Painter &p, QPoint position, QSize size, int outerWidth) { const auto state = computeState(); auto o = p.opacity(); p.setOpacity(o * state.shown); const auto rect = rtlrect( position.x(), position.y(), size.width(), size.height(), outerWidth); const auto was = p.pen(); const auto brush = p.brush(); if (anim::Disabled()) { anim::DrawStaticLoading(p, rect, _st.thickness, _st.color); } else { auto pen = _st.color->p; pen.setWidth(_st.thickness); pen.setCapStyle(Qt::RoundCap); p.setPen(pen); { PainterHighQualityEnabler hq(p); p.drawArc( rect, state.arcFrom, state.arcLength); } } p.setPen(was); p.setBrush(brush); p.setOpacity(o); }
void RadialAnimation::draw( Painter &p, const QRect &inner, int32 thickness, style::color color) { const auto state = computeState(); auto o = p.opacity(); p.setOpacity(o * state.shown); auto pen = color->p; auto was = p.pen(); pen.setWidth(thickness); pen.setCapStyle(Qt::RoundCap); p.setPen(pen); { PainterHighQualityEnabler hq(p); p.drawArc(inner, state.arcFrom, state.arcLength); } p.setPen(was); p.setOpacity(o); }
void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, style::color color) { float64 o = p.opacity(); p.setOpacity(o * _opacity); QPen pen(color->p), was(p.pen()); pen.setWidth(thickness); pen.setCapStyle(Qt::RoundCap); p.setPen(pen); auto len = MinArcLength + qRound(a_arcEnd.current()); auto from = QuarterArcLength - qRound(a_arcStart.current()) - len; if (rtl()) { from = QuarterArcLength - (from - QuarterArcLength) - len; if (from < 0) from += FullArcLength; } { PainterHighQualityEnabler hq(p); p.drawArc(inner, from, len); } p.setPen(was); p.setOpacity(o); }
void HistoryPhoto::drawGrouped( Painter &p, const QRect &clip, TextSelection selection, crl::time ms, const QRect &geometry, RectParts corners, not_null<uint64*> cacheKey, not_null<QPixmap*> cache) const { _data->automaticLoad(_realParent->fullId(), _parent->data()); validateGroupedCache(geometry, corners, cacheKey, cache); const auto selected = (selection == FullSelection); const auto loaded = _data->loaded(); const auto displayLoading = _data->displayLoading(); const auto bubble = _parent->hasBubble(); if (displayLoading) { ensureAnimation(); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); } } const auto radial = isRadialAnimation(); if (!bubble) { // App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } p.drawPixmap(geometry.topLeft(), *cache); if (selected) { const auto roundRadius = ImageRoundRadius::Large; App::complexOverlayRect(p, geometry, roundRadius, corners); } const auto displayState = radial || (!loaded && !_data->loading()) || _data->waitingForAlbum(); if (displayState) { const auto radialOpacity = radial ? _animation->radial.opacity() : 1.; const auto backOpacity = (loaded && !_data->uploading()) ? radialOpacity : 1.; const auto radialSize = st::historyGroupRadialSize; const auto inner = QRect( geometry.x() + (geometry.width() - radialSize) / 2, geometry.y() + (geometry.height() - radialSize) / 2, radialSize, radialSize); p.setPen(Qt::NoPen); if (selected) { p.setBrush(st::msgDateImgBgSelected); } else if (isThumbAnimation()) { auto over = _animation->a_thumbOver.value(1.); p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over)); } else { auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); } p.setOpacity(backOpacity * p.opacity()); { PainterHighQualityEnabler hq(p); p.drawEllipse(inner); } const auto icon = [&]() -> const style::icon* { if (_data->waitingForAlbum()) { return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting); } else if (radial || _data->loading()) { if (_data->uploading() || _data->large()->location().valid()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); }(); const auto previous = [&]() -> const style::icon* { if (_data->waitingForAlbum()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; }(); p.setOpacity(backOpacity); if (icon) { if (previous && radialOpacity > 0. && radialOpacity < 1.) { PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner); } else { icon->paintInCenter(p, inner); } } p.setOpacity(1); if (radial) { const auto line = st::historyGroupRadialLine; const auto rinner = inner.marginsRemoved({ line, line, line, line }); const auto color = selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg; _animation->radial.draw(p, rinner, line, color); } } }
void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const { if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return; _data->automaticLoad(_realParent->fullId(), _parent->data()); auto selected = (selection == FullSelection); auto loaded = _data->loaded(); auto displayLoading = _data->displayLoading(); auto inWebPage = (_parent->media() != this); auto paintx = 0, painty = 0, paintw = width(), painth = height(); auto bubble = _parent->hasBubble(); auto captionw = paintw - st::msgPadding.left() - st::msgPadding.right(); if (displayLoading) { ensureAnimation(); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); } } const auto radial = isRadialAnimation(); auto rthumb = rtlrect(paintx, painty, paintw, painth, width()); if (_serviceWidth > 0) { const auto pix = [&] { if (loaded) { return _data->large()->pixCircled(_realParent->fullId(), _pixw, _pixh); } else if (_data->thumbnail()->loaded()) { return _data->thumbnail()->pixBlurredCircled(_realParent->fullId(), _pixw, _pixh); } else if (_data->thumbnailSmall()->loaded()) { return _data->thumbnailSmall()->pixBlurredCircled(_realParent->fullId(), _pixw, _pixh); } else if (const auto blurred = _data->thumbnailInline()) { return blurred->pixBlurredCircled(_realParent->fullId(), _pixw, _pixh); } else { return QPixmap(); } }(); p.drawPixmap(rthumb.topLeft(), pix); } else { if (bubble) { if (!_caption.isEmpty()) { painth -= st::mediaCaptionSkip + _caption.countHeight(captionw); if (isBubbleBottom()) { painth -= st::msgPadding.bottom(); } rthumb = rtlrect(paintx, painty, paintw, painth, width()); } } else { App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } auto inWebPage = (_parent->media() != this); auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large; auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) | ((isBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); const auto pix = [&] { if (loaded) { return _data->large()->pixSingle(_realParent->fullId(), _pixw, _pixh, paintw, painth, roundRadius, roundCorners); } else if (_data->thumbnail()->loaded()) { return _data->thumbnail()->pixBlurredSingle(_realParent->fullId(), _pixw, _pixh, paintw, painth, roundRadius, roundCorners); } else if (_data->thumbnailSmall()->loaded()) { return _data->thumbnailSmall()->pixBlurredSingle(_realParent->fullId(), _pixw, _pixh, paintw, painth, roundRadius, roundCorners); } else if (const auto blurred = _data->thumbnailInline()) { return blurred->pixBlurredSingle(_realParent->fullId(), _pixw, _pixh, paintw, painth, roundRadius, roundCorners); } else { return QPixmap(); } }(); p.drawPixmap(rthumb.topLeft(), pix); if (selected) { App::complexOverlayRect(p, rthumb, roundRadius, roundCorners); } } if (radial || (!loaded && !_data->loading())) { const auto radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1.; QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); if (selected) { p.setBrush(st::msgDateImgBgSelected); } else if (isThumbAnimation()) { auto over = _animation->a_thumbOver.value(1.); p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over)); } else { auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); } p.setOpacity(radialOpacity * p.opacity()); { PainterHighQualityEnabler hq(p); p.drawEllipse(inner); } p.setOpacity(radialOpacity); auto icon = [&]() -> const style::icon* { if (radial || _data->loading()) { if (_data->uploading() || _data->large()->location().valid()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); }(); if (icon) { icon->paintInCenter(p, inner); } p.setOpacity(1); if (radial) { QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); _animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg); } } // date if (!_caption.isEmpty()) { auto outbg = _parent->hasOutLayout(); p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); _caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection); } else if (!inWebPage) { auto fullRight = paintx + paintw; auto fullBottom = painty + painth; if (needInfoDisplay()) { _parent->drawInfo(p, fullRight, fullBottom, 2 * paintx + paintw, selected, InfoDisplayType::Image); } if (!bubble && _parent->displayRightAction()) { auto fastShareLeft = (fullRight + st::historyFastShareLeft); auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize); _parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw); } } }