mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
Direct2D: Always call SetTransform for gradient/image brushes
This partly reverts commit ad28684b10.
Prior to that change, getBrush() would always end up calling
SetTransform on gradient/image brushes. This is important because, when
drawing text, we combine the current brush transform with the text
transform. If we don't reset the brush transform each time, these
transforms end up accumulating across frames.
This commit is contained in:
parent
17df2b8037
commit
641497918c
2 changed files with 72 additions and 25 deletions
|
|
@ -471,19 +471,8 @@ public:
|
|||
|
||||
if (fillType.isGradient())
|
||||
{
|
||||
auto p1 = fillType.gradient->point1;
|
||||
auto p2 = fillType.gradient->point2;
|
||||
|
||||
if (transform.isOnlyTranslation())
|
||||
{
|
||||
Point<float> translation { transform.getTranslationX(), transform.getTranslationY() };
|
||||
p1 += translation;
|
||||
p2 += translation;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBrush->SetTransform (D2DUtilities::transformToMatrix (transform));
|
||||
}
|
||||
const auto p1 = fillType.gradient->point1;
|
||||
const auto p2 = fillType.gradient->point2;
|
||||
|
||||
if (fillType.gradient->isRadial)
|
||||
{
|
||||
|
|
@ -498,11 +487,8 @@ public:
|
|||
linearGradient->SetEndPoint ({ p2.x, p2.y });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBrush->SetTransform (D2DUtilities::transformToMatrix (transform));
|
||||
}
|
||||
|
||||
currentBrush->SetTransform (D2DUtilities::transformToMatrix (transform));
|
||||
currentBrush->SetOpacity (fillType.getOpacity());
|
||||
|
||||
return currentBrush;
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,13 @@ public:
|
|||
testGradientFillTransform (1.0f);
|
||||
testGradientFillTransform (1.5f);
|
||||
}
|
||||
|
||||
beginTest ("Text gradient fill transform should compose with world transform correctly");
|
||||
{
|
||||
testTextGradientFillTransform (2.0f);
|
||||
testTextGradientFillTransform (1.5f);
|
||||
testTextGradientFillTransform (1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static Image createEdgeMask (int sourceWidth,
|
||||
|
|
@ -1487,14 +1494,6 @@ public:
|
|||
return p.toFloat().transformedBy (AffineTransform::scale (scale)).roundToInt();
|
||||
};
|
||||
|
||||
const auto approximatelyEqual = [] (const Colour& a, const Colour& b)
|
||||
{
|
||||
return std::abs (a.getRed() - b.getRed()) < 2
|
||||
&& std::abs (a.getGreen() - b.getGreen()) < 2
|
||||
&& std::abs (a.getBlue() - b.getBlue()) < 2
|
||||
&& std::abs (a.getAlpha() - b.getAlpha()) < 2;
|
||||
};
|
||||
|
||||
const Point<int> centre { circleSize / 2, circleSize / 2 };
|
||||
const Point<int> brushOffset { brushTranslation, brushTranslation };
|
||||
|
||||
|
|
@ -1512,6 +1511,68 @@ public:
|
|||
expect (image.getPixelAt (blackPosition.getX(), blackPosition.getY()) == Colours::black);
|
||||
}
|
||||
}
|
||||
|
||||
void testTextGradientFillTransform (float scale)
|
||||
{
|
||||
const auto typeface = loadTypeface (FontBinaryData::Karla_Regular_Typo_Off_Offsets_Off);
|
||||
|
||||
constexpr int size = 500;
|
||||
|
||||
Image image { Image::RGB,
|
||||
roundToInt (size * scale),
|
||||
roundToInt (size * scale),
|
||||
true };
|
||||
|
||||
const auto fillCol1 = Colours::cyan;
|
||||
const auto fillCol2 = Colours::magenta;
|
||||
const auto fillColMiddle = fillCol1.interpolatedWith (fillCol2, 0.5f);
|
||||
|
||||
{
|
||||
Graphics g { image };
|
||||
g.addTransform (AffineTransform::scale (scale));
|
||||
|
||||
g.setFont (FontOptions { typeface }.withPointHeight (50));
|
||||
g.setGradientFill ({ fillCol1, { size * 0.5f - 80, 0 }, fillCol2, { size * 0.5f + 80, 0.0f }, false });
|
||||
|
||||
for (auto i = 0; i != 10; ++i)
|
||||
{
|
||||
g.drawText (String::repeatedString ("-", 100),
|
||||
Rectangle { size * 2, size }.translated (i * 50 - 500, i * 50),
|
||||
Justification::topLeft,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
const auto getPixelAtScaled = [&image, scale] (Point<int> p)
|
||||
{
|
||||
const auto scaled = p.toFloat().transformedBy (AffineTransform::scale (scale)).roundToInt();
|
||||
return image.getPixelAt (scaled.x, scaled.y);
|
||||
};
|
||||
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 15, 27 }), fillCol1));
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 485, 27 }), fillCol2));
|
||||
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 15, 77 }), fillCol1));
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 485, 77 }), fillCol2));
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 250, 77 }), fillColMiddle));
|
||||
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 15, 477 }), fillCol1));
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 485, 477 }), fillCol2));
|
||||
expect (approximatelyEqual (getPixelAtScaled ({ 250, 477 }), fillColMiddle));
|
||||
}
|
||||
|
||||
static bool approximatelyEqual (const Colour& a, const Colour& b)
|
||||
{
|
||||
return std::abs (a.getRed() - b.getRed()) < 2
|
||||
&& std::abs (a.getGreen() - b.getGreen()) < 2
|
||||
&& std::abs (a.getBlue() - b.getBlue()) < 2
|
||||
&& std::abs (a.getAlpha() - b.getAlpha()) < 2;
|
||||
}
|
||||
|
||||
static Typeface::Ptr loadTypeface (Span<const unsigned char> data)
|
||||
{
|
||||
return Typeface::createSystemTypefaceFor (data.data(), data.size());
|
||||
}
|
||||
};
|
||||
|
||||
static Direct2DGraphicsContextTests direct2DGraphicsContextTests;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue