webview_helpers.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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/webview_helpers.h"
  8. #include "lang/lang_keys.h"
  9. namespace Ui {
  10. namespace {
  11. [[nodiscard]] QByteArray Serialize(const QColor &qt) {
  12. if (qt.alpha() == 255) {
  13. return '#'
  14. + QByteArray::number(qt.red(), 16).rightJustified(2, '0')
  15. + QByteArray::number(qt.green(), 16).rightJustified(2, '0')
  16. + QByteArray::number(qt.blue(), 16).rightJustified(2, '0');
  17. }
  18. return "rgba("
  19. + QByteArray::number(qt.red()) + ","
  20. + QByteArray::number(qt.green()) + ","
  21. + QByteArray::number(qt.blue()) + ","
  22. + QByteArray::number(qt.alpha() / 255.) + ")";
  23. }
  24. } // namespace
  25. QByteArray ComputeStyles(
  26. const base::flat_map<QByteArray, const style::color*> &colors,
  27. const base::flat_map<QByteArray, tr::phrase<>> &phrases,
  28. int zoom,
  29. bool nightTheme) {
  30. static const auto serialize = [](const style::color *color) {
  31. return Serialize((*color)->c);
  32. };
  33. static const auto escape = [](tr::phrase<> phrase) {
  34. const auto text = phrase(tr::now);
  35. auto result = QByteArray();
  36. for (auto i = 0; i != text.size(); ++i) {
  37. uint ucs4 = text[i].unicode();
  38. if (QChar::isHighSurrogate(ucs4) && i + 1 != text.size()) {
  39. ushort low = text[i + 1].unicode();
  40. if (QChar::isLowSurrogate(low)) {
  41. ucs4 = QChar::surrogateToUcs4(ucs4, low);
  42. ++i;
  43. }
  44. }
  45. if (ucs4 == '\'' || ucs4 == '\"' || ucs4 == '\\') {
  46. result.append('\\').append(char(ucs4));
  47. } else if (ucs4 < 32 || ucs4 > 127) {
  48. result.append('\\' + QByteArray::number(ucs4, 16) + ' ');
  49. } else {
  50. result.append(char(ucs4));
  51. }
  52. }
  53. return result;
  54. };
  55. auto result = QByteArray();
  56. for (const auto &[name, phrase] : phrases) {
  57. result += "--td-lng-"_q + name + ":'"_q + escape(phrase) + "'; "_q;
  58. }
  59. for (const auto &[name, color] : colors) {
  60. result += "--td-"_q + name + ':' + serialize(color) + ';';
  61. }
  62. result += "--td-night:"_q + (nightTheme ? "1" : "0") + ';';
  63. result += "--td-zoom-percentage:"_q
  64. + (QString::number(zoom).toUtf8() + '%')
  65. + ';';
  66. return result;
  67. }
  68. QByteArray ComputeSemiTransparentOverStyle(
  69. const QByteArray &name,
  70. const style::color &over,
  71. const style::color &bg) {
  72. const auto result = [&](const QColor &c) {
  73. return "--td-"_q + name + ':' + Serialize(c) + ';';
  74. };
  75. if (over->c.alpha() < 255) {
  76. return result(over->c);
  77. }
  78. // The most transparent color that will still give the same result.
  79. const auto r0 = bg->c.red();
  80. const auto g0 = bg->c.green();
  81. const auto b0 = bg->c.blue();
  82. const auto r1 = over->c.red();
  83. const auto g1 = over->c.green();
  84. const auto b1 = over->c.blue();
  85. const auto mina = [](int c0, int c1) {
  86. return (c0 == c1)
  87. ? 0
  88. : (c0 > c1)
  89. ? (((c0 - c1) * 255) / c0)
  90. : (((c1 - c0) * 255) / (255 - c0));
  91. };
  92. const auto rmina = mina(r0, r1);
  93. const auto gmina = mina(g0, g1);
  94. const auto bmina = mina(b0, b1);
  95. const auto a = std::max({ rmina, gmina, bmina });
  96. const auto r = (a > 0) ? ((r1 * 255 - r0 * (255 - a)) / a) : r0;
  97. const auto g = (a > 0) ? ((g1 * 255 - g0 * (255 - a)) / a) : g0;
  98. const auto b = (a > 0) ? ((b1 * 255 - b0 * (255 - a)) / a) : b0;
  99. return result(QColor(r, g, b, a));
  100. }
  101. QByteArray EscapeForAttribute(QByteArray value) {
  102. return value
  103. .replace('&', "&amp;")
  104. .replace('"', "&quot;")
  105. .replace('\'', "&#039;")
  106. .replace('<', "&lt;")
  107. .replace('>', "&gt;");
  108. }
  109. QByteArray EscapeForScriptString(QByteArray value) {
  110. return value
  111. .replace('\\', "\\\\")
  112. .replace('"', "\\\"")
  113. .replace('\'', "\\\'");
  114. }
  115. } // namespace Ui