painter.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "styles/style_basic.h"
  9. #include <QtCore/QPoint>
  10. #include <QtGui/QPainter>
  11. namespace Ui::Text {
  12. struct SpoilerMess;
  13. } // namespace Ui::Text
  14. class Painter : public QPainter {
  15. public:
  16. explicit Painter(QPaintDevice *device) : QPainter(device) {
  17. }
  18. void drawTextLeft(int x, int y, int outerw, const QString &text, int textWidth = -1) {
  19. QFontMetrics m(fontMetrics());
  20. if (style::RightToLeft() && textWidth < 0) textWidth = m.horizontalAdvance(text);
  21. const auto result = style::FindAdjustResult(font());
  22. const auto ascent = result ? result->iascent : m.ascent();
  23. drawText(style::RightToLeft() ? (outerw - x - textWidth) : x, y + ascent, text);
  24. }
  25. void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1) {
  26. QFontMetrics m(fontMetrics());
  27. if (!style::RightToLeft() && textWidth < 0) textWidth = m.horizontalAdvance(text);
  28. const auto result = style::FindAdjustResult(font());
  29. const auto ascent = result ? result->iascent : m.ascent();
  30. drawText(style::RightToLeft() ? x : (outerw - x - textWidth), y + ascent, text);
  31. }
  32. void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix, const QRect &from) {
  33. drawPixmap(QPoint(style::RightToLeft() ? (outerw - x - (from.width() / pix.devicePixelRatio())) : x, y), pix, from);
  34. }
  35. void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) {
  36. return drawPixmapLeft(p.x(), p.y(), outerw, pix, from);
  37. }
  38. void drawPixmapLeft(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) {
  39. drawPixmap(QRect(style::RightToLeft() ? (outerw - x - w) : x, y, w, h), pix, from);
  40. }
  41. void drawPixmapLeft(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) {
  42. return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
  43. }
  44. void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix) {
  45. drawPixmap(QPoint(style::RightToLeft() ? (outerw - x - (pix.width() / pix.devicePixelRatio())) : x, y), pix);
  46. }
  47. void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix) {
  48. return drawPixmapLeft(p.x(), p.y(), outerw, pix);
  49. }
  50. void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from) {
  51. drawPixmap(QPoint(style::RightToLeft() ? x : (outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
  52. }
  53. void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) {
  54. return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
  55. }
  56. void drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) {
  57. drawPixmap(QRect(style::RightToLeft() ? x : (outerw - x - w), y, w, h), pix, from);
  58. }
  59. void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) {
  60. return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
  61. }
  62. void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix) {
  63. drawPixmap(QPoint(style::RightToLeft() ? x : (outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
  64. }
  65. void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix) {
  66. return drawPixmapRight(p.x(), p.y(), outerw, pix);
  67. }
  68. void setTextPalette(const style::TextPalette &palette) {
  69. _textPalette = &palette;
  70. }
  71. void restoreTextPalette() {
  72. _textPalette = nullptr;
  73. }
  74. [[nodiscard]] const style::TextPalette &textPalette() const {
  75. return _textPalette ? *_textPalette : st::defaultTextPalette;
  76. }
  77. void setInactive(bool inactive) {
  78. _inactive = inactive;
  79. }
  80. [[nodiscard]] bool inactive() const {
  81. return _inactive;
  82. }
  83. void setTextSpoilerMess(not_null<Ui::Text::SpoilerMess*> mess) {
  84. _spoilerMess = mess;
  85. }
  86. void restoreTextSpoilerMess() {
  87. _spoilerMess = nullptr;
  88. }
  89. [[nodiscard]] Ui::Text::SpoilerMess *textSpoilerMess() const {
  90. return _spoilerMess;
  91. }
  92. private:
  93. const style::TextPalette *_textPalette = nullptr;
  94. Ui::Text::SpoilerMess *_spoilerMess = nullptr;
  95. bool _inactive = false;
  96. };
  97. class PainterHighQualityEnabler {
  98. public:
  99. PainterHighQualityEnabler(QPainter &p) : _painter(p) {
  100. static constexpr QPainter::RenderHint Hints[] = {
  101. QPainter::Antialiasing,
  102. QPainter::SmoothPixmapTransform,
  103. QPainter::TextAntialiasing
  104. };
  105. const auto hints = _painter.renderHints();
  106. for (const auto hint : Hints) {
  107. if (!(hints & hint)) {
  108. _hints |= hint;
  109. }
  110. }
  111. if (_hints) {
  112. _painter.setRenderHints(_hints);
  113. }
  114. }
  115. PainterHighQualityEnabler(
  116. const PainterHighQualityEnabler &other) = delete;
  117. PainterHighQualityEnabler &operator=(
  118. const PainterHighQualityEnabler &other) = delete;
  119. ~PainterHighQualityEnabler() {
  120. if (_hints && _painter.isActive()) {
  121. _painter.setRenderHints(_hints, false);
  122. }
  123. }
  124. private:
  125. QPainter &_painter;
  126. QPainter::RenderHints _hints;
  127. };
  128. class ScopedPainterOpacity {
  129. public:
  130. ScopedPainterOpacity(QPainter &p, float64 nowOpacity)
  131. : _painter(p)
  132. , _wasOpacity(p.opacity()) {
  133. if (_wasOpacity != nowOpacity) {
  134. _painter.setOpacity(nowOpacity);
  135. }
  136. }
  137. ScopedPainterOpacity(
  138. const ScopedPainterOpacity &other) = delete;
  139. ScopedPainterOpacity &operator=(
  140. const ScopedPainterOpacity &other) = delete;
  141. ~ScopedPainterOpacity() {
  142. if (_painter.isActive()) {
  143. _painter.setOpacity(_wasOpacity);
  144. }
  145. }
  146. private:
  147. QPainter &_painter;
  148. const float64 _wasOpacity;
  149. };