Invert patter image to white for dark colors.
This commit is contained in:
		
							parent
							
								
									4273167aa2
								
							
						
					
					
						commit
						b6cd9c2911
					
				
					 4 changed files with 56 additions and 17 deletions
				
			
		| 
						 | 
					@ -647,6 +647,13 @@ QColor CountAverageColor(const std::vector<QColor> &colors) {
 | 
				
			||||||
	return QColor(components[0], components[1], components[2]);
 | 
						return QColor(components[0], components[1], components[2]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IsPatternInverted(
 | 
				
			||||||
 | 
							const std::vector<QColor> &background,
 | 
				
			||||||
 | 
							float64 patternOpacity) {
 | 
				
			||||||
 | 
						return (patternOpacity > 0.)
 | 
				
			||||||
 | 
							&& (CountAverageColor(background).toHsv().valueF() <= 0.3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QColor ThemeAdjustedColor(QColor original, QColor background) {
 | 
					QColor ThemeAdjustedColor(QColor original, QColor background) {
 | 
				
			||||||
	return QColor::fromHslF(
 | 
						return QColor::fromHslF(
 | 
				
			||||||
		background.hslHueF(),
 | 
							background.hslHueF(),
 | 
				
			||||||
| 
						 | 
					@ -747,7 +754,7 @@ QImage GenerateBackgroundImage(
 | 
				
			||||||
		const std::vector<QColor> &bg,
 | 
							const std::vector<QColor> &bg,
 | 
				
			||||||
		int gradientRotation,
 | 
							int gradientRotation,
 | 
				
			||||||
		float64 patternOpacity,
 | 
							float64 patternOpacity,
 | 
				
			||||||
		Fn<void(QPainter&)> drawPattern) {
 | 
							Fn<void(QPainter&,bool)> drawPattern) {
 | 
				
			||||||
	auto result = bg.empty()
 | 
						auto result = bg.empty()
 | 
				
			||||||
		? Images::GenerateGradient(size, { DefaultBackgroundColor() })
 | 
							? Images::GenerateGradient(size, { DefaultBackgroundColor() })
 | 
				
			||||||
		: Images::GenerateGradient(size, bg, gradientRotation);
 | 
							: Images::GenerateGradient(size, bg, gradientRotation);
 | 
				
			||||||
| 
						 | 
					@ -762,7 +769,7 @@ QImage GenerateBackgroundImage(
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 | 
								p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		drawPattern(p);
 | 
							drawPattern(p, IsPatternInverted(bg, patternOpacity));
 | 
				
			||||||
		if (patternOpacity < 0. && patternOpacity > -1.) {
 | 
							if (patternOpacity < 0. && patternOpacity > -1.) {
 | 
				
			||||||
			p.setCompositionMode(QPainter::CompositionMode_SourceOver);
 | 
								p.setCompositionMode(QPainter::CompositionMode_SourceOver);
 | 
				
			||||||
			p.setOpacity(1. + patternOpacity);
 | 
								p.setOpacity(1. + patternOpacity);
 | 
				
			||||||
| 
						 | 
					@ -784,7 +791,10 @@ QImage PreparePatternImage(
 | 
				
			||||||
		bg,
 | 
							bg,
 | 
				
			||||||
		gradientRotation,
 | 
							gradientRotation,
 | 
				
			||||||
		patternOpacity,
 | 
							patternOpacity,
 | 
				
			||||||
		[&](QPainter &p) {
 | 
							[&](QPainter &p, bool inverted) {
 | 
				
			||||||
 | 
								if (inverted) {
 | 
				
			||||||
 | 
									pattern = InvertPatternImage(std::move(pattern));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			p.drawImage(QRect(QPoint(), pattern.size()), pattern);
 | 
								p.drawImage(QRect(QPoint(), pattern.size()), pattern);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -792,6 +802,23 @@ QImage PreparePatternImage(
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QImage InvertPatternImage(QImage pattern) {
 | 
				
			||||||
 | 
						pattern = std::move(pattern).convertToFormat(
 | 
				
			||||||
 | 
							QImage::Format_ARGB32_Premultiplied);
 | 
				
			||||||
 | 
						const auto w = pattern.bytesPerLine() / 4;
 | 
				
			||||||
 | 
						auto ints = reinterpret_cast<uint32*>(pattern.bits());
 | 
				
			||||||
 | 
						for (auto y = 0, h = pattern.height(); y != h; ++y) {
 | 
				
			||||||
 | 
							for (auto x = 0; x != w; ++x) {
 | 
				
			||||||
 | 
								const auto value = (*ints >> 24);
 | 
				
			||||||
 | 
								*ints++ = (value << 24)
 | 
				
			||||||
 | 
									| (value << 16)
 | 
				
			||||||
 | 
									| (value << 8)
 | 
				
			||||||
 | 
									| value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pattern;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QImage PrepareBlurredBackground(QImage image) {
 | 
					QImage PrepareBlurredBackground(QImage image) {
 | 
				
			||||||
	constexpr auto kSize = 900;
 | 
						constexpr auto kSize = 900;
 | 
				
			||||||
	constexpr auto kRadius = 24;
 | 
						constexpr auto kRadius = 24;
 | 
				
			||||||
| 
						 | 
					@ -834,6 +861,8 @@ ChatThemeBackground PrepareBackgroundImage(
 | 
				
			||||||
				data.colors,
 | 
									data.colors,
 | 
				
			||||||
				data.gradientRotation,
 | 
									data.gradientRotation,
 | 
				
			||||||
				data.patternOpacity);
 | 
									data.patternOpacity);
 | 
				
			||||||
 | 
							} else if (IsPatternInverted(data.colors, data.patternOpacity)) {
 | 
				
			||||||
 | 
								prepared = InvertPatternImage(std::move(prepared));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		prepared.setDevicePixelRatio(style::DevicePixelRatio());
 | 
							prepared.setDevicePixelRatio(style::DevicePixelRatio());
 | 
				
			||||||
	} else if (data.colors.empty()) {
 | 
						} else if (data.colors.empty()) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,9 @@ struct ChatBackgroundRects {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[nodiscard]] QColor CountAverageColor(const QImage &image);
 | 
					[[nodiscard]] QColor CountAverageColor(const QImage &image);
 | 
				
			||||||
[[nodiscard]] QColor CountAverageColor(const std::vector<QColor> &colors);
 | 
					[[nodiscard]] QColor CountAverageColor(const std::vector<QColor> &colors);
 | 
				
			||||||
 | 
					[[nodiscard]] bool IsPatternInverted(
 | 
				
			||||||
 | 
						const std::vector<QColor> &background,
 | 
				
			||||||
 | 
						float64 patternOpacity);
 | 
				
			||||||
[[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background);
 | 
					[[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background);
 | 
				
			||||||
[[nodiscard]] QImage PreprocessBackgroundImage(QImage image);
 | 
					[[nodiscard]] QImage PreprocessBackgroundImage(QImage image);
 | 
				
			||||||
[[nodiscard]] std::optional<QColor> CalculateImageMonoColor(
 | 
					[[nodiscard]] std::optional<QColor> CalculateImageMonoColor(
 | 
				
			||||||
| 
						 | 
					@ -199,7 +202,8 @@ struct ChatBackgroundRects {
 | 
				
			||||||
	const std::vector<QColor> &bg,
 | 
						const std::vector<QColor> &bg,
 | 
				
			||||||
	int gradientRotation,
 | 
						int gradientRotation,
 | 
				
			||||||
	float64 patternOpacity = 1.,
 | 
						float64 patternOpacity = 1.,
 | 
				
			||||||
	Fn<void(QPainter&)> drawPattern = nullptr);
 | 
						Fn<void(QPainter&,bool)> drawPattern = nullptr);
 | 
				
			||||||
 | 
					[[nodiscard]] QImage InvertPatternImage(QImage pattern);
 | 
				
			||||||
[[nodiscard]] QImage PreparePatternImage(
 | 
					[[nodiscard]] QImage PreparePatternImage(
 | 
				
			||||||
	QImage pattern,
 | 
						QImage pattern,
 | 
				
			||||||
	const std::vector<QColor> &bg,
 | 
						const std::vector<QColor> &bg,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -722,6 +722,9 @@ void ChatBackground::setPreparedAfterPaper(QImage image) {
 | 
				
			||||||
				QImage());
 | 
									QImage());
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			image = postprocessBackgroundImage(std::move(image));
 | 
								image = postprocessBackgroundImage(std::move(image));
 | 
				
			||||||
 | 
								if (Ui::IsPatternInverted(bgColors, _paper.patternOpacity())) {
 | 
				
			||||||
 | 
									image = Ui::InvertPatternImage(std::move(image));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			setPrepared(
 | 
								setPrepared(
 | 
				
			||||||
				image,
 | 
									image,
 | 
				
			||||||
				image,
 | 
									image,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -985,6 +985,9 @@ void MainMenu::refreshMenu() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainMenu::refreshBackground() {
 | 
					void MainMenu::refreshBackground() {
 | 
				
			||||||
 | 
						if (IsFilledCover()) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	const auto fill = QSize(st::mainMenuWidth, st::mainMenuCoverHeight);
 | 
						const auto fill = QSize(st::mainMenuWidth, st::mainMenuCoverHeight);
 | 
				
			||||||
	const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c);
 | 
						const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c);
 | 
				
			||||||
	const auto background = Window::Theme::Background();
 | 
						const auto background = Window::Theme::Background();
 | 
				
			||||||
| 
						 | 
					@ -995,14 +998,14 @@ void MainMenu::refreshBackground() {
 | 
				
			||||||
		fill,
 | 
							fill,
 | 
				
			||||||
		prepared.size());
 | 
							prepared.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto backgroundImage = paper.isPattern()
 | 
						auto backgroundImage = /*paper.isPattern()
 | 
				
			||||||
		? Ui::GenerateBackgroundImage(
 | 
							? Ui::GenerateBackgroundImage(
 | 
				
			||||||
			fill * cIntRetinaFactor(),
 | 
								fill * cIntRetinaFactor(),
 | 
				
			||||||
			paper.backgroundColors(),
 | 
								paper.backgroundColors(),
 | 
				
			||||||
			paper.gradientRotation(),
 | 
								paper.gradientRotation(),
 | 
				
			||||||
			paper.patternOpacity(),
 | 
								paper.patternOpacity(),
 | 
				
			||||||
			[&](QPainter &p) { p.drawImage(rects.to, prepared, rects.from); })
 | 
								[&](QPainter &p) { p.drawImage(rects.to, prepared, rects.from); })
 | 
				
			||||||
		: QImage(
 | 
							: */QImage(
 | 
				
			||||||
			fill * cIntRetinaFactor(),
 | 
								fill * cIntRetinaFactor(),
 | 
				
			||||||
			QImage::Format_ARGB32_Premultiplied);
 | 
								QImage::Format_ARGB32_Premultiplied);
 | 
				
			||||||
	QPainter p(&backgroundImage);
 | 
						QPainter p(&backgroundImage);
 | 
				
			||||||
| 
						 | 
					@ -1019,20 +1022,20 @@ void MainMenu::refreshBackground() {
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Solid color.
 | 
						// Solid color.
 | 
				
			||||||
	if (const auto color = background->colorForFill()) {
 | 
						//if (const auto color = background->colorForFill()) {
 | 
				
			||||||
		const auto intensity = IntensityOfColor(*color);
 | 
						//	const auto intensity = IntensityOfColor(*color);
 | 
				
			||||||
		p.fillRect(QRect(QPoint(), fill), *color);
 | 
						//	p.fillRect(QRect(QPoint(), fill), *color);
 | 
				
			||||||
		if (std::abs(intensity - intensityText) < kMinDiffIntensity) {
 | 
						//	if (std::abs(intensity - intensityText) < kMinDiffIntensity) {
 | 
				
			||||||
			drawShadow(p);
 | 
						//		drawShadow(p);
 | 
				
			||||||
		}
 | 
						//	}
 | 
				
			||||||
		_background = backgroundImage;
 | 
						//	_background = backgroundImage;
 | 
				
			||||||
		return;
 | 
						//	return;
 | 
				
			||||||
	}
 | 
						//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Background image.
 | 
						// Background image.
 | 
				
			||||||
	if (!paper.isPattern()) {
 | 
						//if (!paper.isPattern()) {
 | 
				
			||||||
		p.drawImage(rects.to, prepared, rects.from);
 | 
							p.drawImage(rects.to, prepared, rects.from);
 | 
				
			||||||
	}
 | 
						//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Cut off the part of the background that is under text.
 | 
						// Cut off the part of the background that is under text.
 | 
				
			||||||
	const QRect underText(
 | 
						const QRect underText(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue