diff options
author | Neil <nyamatongwe@gmail.com> | 2020-06-06 16:48:16 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2020-06-06 16:48:16 +1000 |
commit | 534e0288e56e52abe91132038e9960fba35a2fde (patch) | |
tree | f2f4cec36f4cadb43afc578f8a0cff8d0d1a2e5d | |
parent | 812caf837c14f3e51d6e2fb14c7d938f4100068e (diff) | |
download | scintilla-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.cxx | 65 |
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) { |