outline_segments.cpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/effects/outline_segments.h"
  8. namespace Ui {
  9. void PaintOutlineSegments(
  10. QPainter &p,
  11. QRectF ellipse,
  12. const std::vector<OutlineSegment> &segments,
  13. float64 fromFullProgress) {
  14. Expects(!segments.empty());
  15. p.setBrush(Qt::NoBrush);
  16. const auto count = std::min(int(segments.size()), kOutlineSegmentsMax);
  17. if (count == 1) {
  18. p.setPen(QPen(segments.front().brush, segments.front().width));
  19. p.drawEllipse(ellipse);
  20. return;
  21. }
  22. const auto small = 160;
  23. const auto full = arc::kFullLength;
  24. const auto separator = (full > 1.1 * small * count)
  25. ? small
  26. : (full / (count * 1.1));
  27. const auto left = full - (separator * count);
  28. const auto length = left / float64(count);
  29. const auto spin = separator * (1. - fromFullProgress);
  30. auto start = 0. + (arc::kQuarterLength + (separator / 2)) + (3. * spin);
  31. auto pen = QPen(
  32. segments.back().brush,
  33. segments.back().width,
  34. Qt::SolidLine,
  35. Qt::RoundCap);
  36. p.setPen(pen);
  37. for (auto i = 0; i != count;) {
  38. const auto &segment = segments[count - (++i)];
  39. if (!segment.width) {
  40. start += length + separator;
  41. continue;
  42. } else if (pen.brush() != segment.brush
  43. || pen.widthF() != segment.width) {
  44. pen = QPen(
  45. segment.brush,
  46. segment.width,
  47. Qt::SolidLine,
  48. Qt::RoundCap);
  49. p.setPen(pen);
  50. }
  51. const auto from = int(base::SafeRound(start));
  52. const auto till = start + length;
  53. auto added = spin;
  54. for (; i != count;) {
  55. start += length + separator;
  56. const auto &next = segments[count - (++i)];
  57. if (next.width) {
  58. --i;
  59. break;
  60. }
  61. added += (separator + length) * (1. - fromFullProgress);
  62. }
  63. p.drawArc(ellipse, from, int(base::SafeRound(till + added)) - from);
  64. }
  65. }
  66. void PaintOutlineSegments(
  67. QPainter &p,
  68. QRectF rect,
  69. float64 radius,
  70. const std::vector<OutlineSegment> &segments) {
  71. Expects(!segments.empty());
  72. p.setBrush(Qt::NoBrush);
  73. const auto count = std::min(int(segments.size()), kOutlineSegmentsMax);
  74. if (count == 1 || true) {
  75. p.setPen(QPen(segments.back().brush, segments.back().width));
  76. p.drawRoundedRect(rect, radius, radius);
  77. return;
  78. }
  79. }
  80. QLinearGradient UnreadStoryOutlineGradient(QRectF rect) {
  81. auto result = QLinearGradient(rect.topRight(), rect.bottomLeft());
  82. result.setStops({
  83. { 0., st::groupCallLive1->c },
  84. { 1., st::groupCallMuted1->c },
  85. });
  86. return result;
  87. }
  88. } // namespace Ui