aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2020-06-06 16:48:16 +1000
committerNeil <nyamatongwe@gmail.com>2020-06-06 16:48:16 +1000
commit534e0288e56e52abe91132038e9960fba35a2fde (patch)
treef2f4cec36f4cadb43afc578f8a0cff8d0d1a2e5d
parent812caf837c14f3e51d6e2fb14c7d938f4100068e (diff)
downloadscintilla-mirror-534e0288e56e52abe91132038e9960fba35a2fde.tar.gz
Implement gradients for GDI. GradientRectangle previously drew an average of the
first two stops over the whole rectangle.
-rw-r--r--win32/PlatWin.cxx65
1 files changed, 60 insertions, 5 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 342900703..ad9bc78d1 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -827,6 +827,33 @@ void DIBSection::SetSymmetric(LONG x, LONG y, DWORD value) noexcept {
SetPixel(xSymmetric, ySymmetric, value);
}
+constexpr unsigned int Proportional(unsigned char a, unsigned char b, float t) noexcept {
+ return static_cast<unsigned int>(a + t * (b - a));
+}
+
+ColourAlpha Proportional(ColourAlpha a, ColourAlpha b, float t) noexcept {
+ return ColourAlpha(
+ Proportional(a.GetRed(), b.GetRed(), t),
+ Proportional(a.GetGreen(), b.GetGreen(), t),
+ Proportional(a.GetBlue(), b.GetBlue(), t),
+ Proportional(a.GetAlpha(), b.GetAlpha(), t));
+}
+
+ColourAlpha GradientValue(const std::vector<ColourStop> &stops, float proportion) noexcept {
+ for (size_t stop = 0; stop < stops.size() - 1; stop++) {
+ // Loop through each pair of stops
+ const float positionStart = stops[stop].position;
+ const float positionEnd = stops[stop + 1].position;
+ if ((proportion >= positionStart) && (proportion <= positionEnd)) {
+ const float proportionInPair = (proportion - positionStart) /
+ (positionEnd - positionStart);
+ return Proportional(stops[stop].colour, stops[stop + 1].colour, proportionInPair);
+ }
+ }
+ // Loop should always find a value
+ return ColourAlpha();
+}
+
constexpr SIZE SizeOfRect(RECT rc) noexcept {
return { rc.right - rc.left, rc.bottom - rc.top };
}
@@ -884,11 +911,39 @@ void SurfaceGDI::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fil
}
}
-void SurfaceGDI::GradientRectangle(PRectangle rc, const std::vector<ColourStop> &stops, GradientOptions) {
- // Would be better to average start and end.
- const ColourAlpha colourAverage = stops[0].colour.MixedWith(stops[1].colour);
- AlphaRectangle(rc, 0, colourAverage.GetColour(), colourAverage.GetAlpha(),
- colourAverage.GetColour(), colourAverage.GetAlpha(), 0);
+void SurfaceGDI::GradientRectangle(PRectangle rc, const std::vector<ColourStop> &stops, GradientOptions options) {
+
+ const RECT rcw = RectFromPRectangle(rc);
+ const SIZE size = SizeOfRect(rcw);
+
+ DIBSection section(hdc, size);
+
+ if (section) {
+
+ if (options == GradientOptions::topToBottom) {
+ for (LONG y = 0; y < size.cy; y++) {
+ // Find y/height proportional colour
+ const float proportion = y / (rc.Height() - 1.0f);
+ const ColourAlpha mixed = GradientValue(stops, proportion);
+ const DWORD valFill = dwordMultiplied(mixed, mixed.GetAlpha());
+ for (LONG x = 0; x < size.cx; x++) {
+ section.SetPixel(x, y, valFill);
+ }
+ }
+ } else {
+ for (LONG x = 0; x < size.cx; x++) {
+ // Find x/width proportional colour
+ const float proportion = x / (rc.Width() - 1.0f);
+ const ColourAlpha mixed = GradientValue(stops, proportion);
+ const DWORD valFill = dwordMultiplied(mixed, mixed.GetAlpha());
+ for (LONG y = 0; y < size.cy; y++) {
+ section.SetPixel(x, y, valFill);
+ }
+ }
+ }
+
+ AlphaBlend(hdc, rcw.left, rcw.top, size.cx, size.cy, section.DC(), 0, 0, size.cx, size.cy, mergeAlpha);
+ }
}
void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {