Browse Source

Direct2DRenderer: added transformations.

tags/2021-05-28
jules 13 years ago
parent
commit
7cd30ec175
1 changed files with 60 additions and 59 deletions
  1. +60
    -59
      modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp

+ 60
- 59
modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp View File

@@ -85,19 +85,17 @@ public:
void setOrigin (int x, int y)
{
currentState->origin.addXY (x, y);
addTransform (AffineTransform::translation ((float) x, (float) y));
}
void addTransform (const AffineTransform& /*transform*/)
void addTransform (const AffineTransform& transform)
{
//xxx todo
jassertfalse;
currentState->transform = transform.followedBy (currentState->transform);
}
float getScaleFactor()
{
//xxx
return 1.0f;
return currentState->transform.getScaleFactor();
}
bool clipToRectangle (const Rectangle<int>& r)
@@ -119,24 +117,23 @@ public:
void clipToPath (const Path& path, const AffineTransform& transform)
{
currentState->clipToPath (pathToPathGeometry (path, transform, currentState->origin));
currentState->clipToPath (pathToPathGeometry (path, transform));
}
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
{
currentState->clipToImage (sourceImage,transform);
currentState->clipToImage (sourceImage, transform);
}
bool clipRegionIntersects (const Rectangle<int>& r)
{
const Rectangle<int> r2 (r + currentState->origin);
return currentState->clipRect.intersects (r2);
return currentState->clipRect.intersects (r.toFloat().transformed (currentState->transform).getSmallestIntegerContainer());
}
Rectangle<int> getClipBounds() const
{
// xxx could this take into account complex clip regions?
return currentState->clipRect - currentState->origin;
return currentState->clipRect.toFloat().transformed (currentState->transform.inverted()).getSmallestIntegerContainer();
}
bool isClipEmpty() const
@@ -183,14 +180,16 @@ public:
void fillRect (const Rectangle<int>& r, bool /*replaceExistingContents*/)
{
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
currentState->createBrush();
renderingTarget->FillRectangle (rectangleToRectF (r + currentState->origin), currentState->currentBrush);
renderingTarget->FillRectangle (rectangleToRectF (r), currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
}
void fillPath (const Path& p, const AffineTransform& transform)
{
currentState->createBrush();
ComSmartPtr <ID2D1Geometry> geometry (pathToPathGeometry (p, transform, currentState->origin));
ComSmartPtr <ID2D1Geometry> geometry (pathToPathGeometry (p, transform.followedBy (currentState->transform)));
if (renderingTarget != nullptr)
renderingTarget->FillGeometry (geometry, currentState->currentBrush);
@@ -198,10 +197,7 @@ public:
void drawImage (const Image& image, const AffineTransform& transform)
{
const int x = currentState->origin.getX();
const int y = currentState->origin.getY();
renderingTarget->SetTransform (transformToMatrix (transform) * D2D1::Matrix3x2F::Translation ((FLOAT) x, (FLOAT) y));
renderingTarget->SetTransform (transformToMatrix (transform.followedBy (currentState->transform)));
D2D1_SIZE_U size;
size.width = image.getWidth();
@@ -227,40 +223,37 @@ public:
void drawLine (const Line <float>& line)
{
// xxx doesn't seem to be correctly aligned, may need nudging by 0.5 to match the software renderer's behaviour
const Line<float> l (line.getStart() + currentState->origin.toFloat(),
line.getEnd() + currentState->origin.toFloat());
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
currentState->createBrush();
renderingTarget->DrawLine (D2D1::Point2F (l.getStartX(), l.getStartY()),
D2D1::Point2F (l.getEndX(), l.getEndY()),
renderingTarget->DrawLine (D2D1::Point2F (line.getStartX(), line.getStartY()),
D2D1::Point2F (line.getEndX(), line.getEndY()),
currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
}
void drawVerticalLine (int x, float top, float bottom)
{
// xxx doesn't seem to be correctly aligned, may need nudging by 0.5 to match the software renderer's behaviour
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
currentState->createBrush();
x += currentState->origin.getX();
const int y = currentState->origin.getY();
renderingTarget->DrawLine (D2D1::Point2F ((FLOAT) x, y + top),
D2D1::Point2F ((FLOAT) x, y + bottom),
renderingTarget->DrawLine (D2D1::Point2F ((FLOAT) x, top),
D2D1::Point2F ((FLOAT) x, bottom),
currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
}
void drawHorizontalLine (int y, float left, float right)
{
// xxx doesn't seem to be correctly aligned, may need nudging by 0.5 to match the software renderer's behaviour
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
currentState->createBrush();
y += currentState->origin.getY();
const int x = currentState->origin.getX();
renderingTarget->DrawLine (D2D1::Point2F (x + left, (FLOAT) y),
D2D1::Point2F (x + right, (FLOAT) y),
renderingTarget->DrawLine (D2D1::Point2F (left, (FLOAT) y),
D2D1::Point2F (right, (FLOAT) y),
currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
}
void setFont (const Font& newFont)
@@ -275,15 +268,14 @@ public:
void drawGlyph (int glyphNumber, const AffineTransform& transform)
{
const float x = (float) currentState->origin.getX();
const float y = (float) currentState->origin.getY();
currentState->createBrush();
currentState->createFont();
float hScale = currentState->font.getHorizontalScale();
renderingTarget->SetTransform (D2D1::Matrix3x2F::Scale (hScale, 1) * transformToMatrix (transform) * D2D1::Matrix3x2F::Translation (x, y));
renderingTarget->SetTransform (transformToMatrix (AffineTransform::scale (hScale, 1.0f)
.followedBy (transform)
.followedBy (currentState->transform)));
const UINT16 glyphIndices = (UINT16) glyphNumber;
const FLOAT glyphAdvances = 0;
@@ -305,6 +297,18 @@ public:
renderingTarget->SetTransform (D2D1::IdentityMatrix());
}
bool drawTextLayout (const AttributedString& text, const Rectangle<float>& area)
{
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
const Direct2DFactories& factories = Direct2DFactories::getInstance();
DirectWriteTypeLayout::drawToD2DContext (text, area, renderingTarget, factories.directWriteFactory,
factories.d2dFactory, factories.systemFonts);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
return true;
}
//==============================================================================
class SavedState
{
@@ -323,8 +327,8 @@ public:
// bottleneck.. Can the same internal objects be shared by multiple state objects, maybe using copy-on-write?
setFill (owner.currentState->fillType);
currentBrush = owner.currentState->currentBrush;
origin = owner.currentState->origin;
clipRect = owner.currentState->clipRect;
transform = owner.currentState->transform;
font = owner.currentState->font;
currentFontFace = owner.currentState->currentFontFace;
@@ -357,7 +361,7 @@ public:
void clipToRectangle (const Rectangle<int>& r)
{
clearClip();
clipRect = r + origin;
clipRect = r.toFloat().transformed (transform).getSmallestIntegerContainer();
shouldClipRect = true;
pushClips();
}
@@ -569,9 +573,6 @@ public:
{
if (currentBrush == 0)
{
const int x = origin.getX();
const int y = origin.getY();
if (fillType.isColour())
{
D2D1_COLOR_F colour = colourToD2D (fillType.colour);
@@ -610,7 +611,7 @@ public:
D2D1_BRUSH_PROPERTIES brushProps;
brushProps.opacity = fillType.getOpacity();
brushProps.transform = transformToMatrix (fillType.transform);
brushProps.transform = transformToMatrix (fillType.transform.followedBy (transform));
const int numColors = fillType.gradient->getNumColours();
@@ -633,7 +634,7 @@ public:
float r = p1.getDistanceFrom (p2);
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES props =
D2D1::RadialGradientBrushProperties (D2D1::Point2F (p1.getX() + x, p1.getY() + y),
D2D1::RadialGradientBrushProperties (D2D1::Point2F (p1.x, p1.y),
D2D1::Point2F (0, 0),
r, r);
@@ -648,8 +649,8 @@ public:
const Point<float>& p2 = fillType.gradient->point2;
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props =
D2D1::LinearGradientBrushProperties (D2D1::Point2F (p1.getX() + x, p1.getY() + y),
D2D1::Point2F (p2.getX() + x, p2.getY() + y));
D2D1::LinearGradientBrushProperties (D2D1::Point2F (p1.x, p1.y),
D2D1::Point2F (p2.x, p2.y));
owner.renderingTarget->CreateLinearGradientBrush (props, brushProps, gradientStops, linearGradient.resetAndGetPointerAddress());
@@ -664,7 +665,7 @@ public:
Direct2DLowLevelGraphicsContext& owner;
Point<int> origin;
AffineTransform transform;
Font font;
float fontHeightToEmSizeFactor;
@@ -722,12 +723,12 @@ private:
return D2D1::RectF ((float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
}
static const D2D1_COLOR_F colourToD2D (const Colour& c)
static D2D1_COLOR_F colourToD2D (const Colour& c)
{
return D2D1::ColorF::ColorF (c.getFloatRed(), c.getFloatGreen(), c.getFloatBlue(), c.getFloatAlpha());
}
static const D2D1_POINT_2F pointTransformed (int x, int y, const AffineTransform& transform = AffineTransform::identity)
static D2D1_POINT_2F pointTransformed (int x, int y, const AffineTransform& transform)
{
transform.transformPoint (x, y);
return D2D1::Point2F ((FLOAT) x, (FLOAT) y);
@@ -758,7 +759,7 @@ private:
return p;
}
static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const AffineTransform& transform, int x, int y)
static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const AffineTransform& transform)
{
Path::Iterator it (path);
@@ -771,13 +772,13 @@ private:
D2D1_BEZIER_SEGMENT seg;
transform.transformPoint (it.x1, it.y1);
seg.point1 = D2D1::Point2F (it.x1 + x, it.y1 + y);
seg.point1 = D2D1::Point2F (it.x1, it.y1);
transform.transformPoint (it.x2, it.y2);
seg.point2 = D2D1::Point2F (it.x2 + x, it.y2 + y);
seg.point2 = D2D1::Point2F (it.x2, it.y2);
transform.transformPoint(it.x3, it.y3);
seg.point3 = D2D1::Point2F (it.x3 + x, it.y3 + y);
seg.point3 = D2D1::Point2F (it.x3, it.y3);
sink->AddBezier (seg);
break;
@@ -786,7 +787,7 @@ private:
case Path::Iterator::lineTo:
{
transform.transformPoint (it.x1, it.y1);
sink->AddLine (D2D1::Point2F (it.x1 + x, it.y1 + y));
sink->AddLine (D2D1::Point2F (it.x1, it.y1));
break;
}
@@ -795,10 +796,10 @@ private:
D2D1_QUADRATIC_BEZIER_SEGMENT seg;
transform.transformPoint (it.x1, it.y1);
seg.point1 = D2D1::Point2F (it.x1 + x, it.y1 + y);
seg.point1 = D2D1::Point2F (it.x1, it.y1);
transform.transformPoint (it.x2, it.y2);
seg.point2 = D2D1::Point2F (it.x2 + x, it.y2 + y);
seg.point2 = D2D1::Point2F (it.x2, it.y2);
sink->AddQuadraticBezier (seg);
break;
@@ -813,14 +814,14 @@ private:
case Path::Iterator::startNewSubPath:
{
transform.transformPoint (it.x1, it.y1);
sink->BeginFigure (D2D1::Point2F (it.x1 + x, it.y1 + y), D2D1_FIGURE_BEGIN_FILLED);
sink->BeginFigure (D2D1::Point2F (it.x1, it.y1), D2D1_FIGURE_BEGIN_FILLED);
break;
}
}
}
}
static ID2D1PathGeometry* pathToPathGeometry (const Path& path, const AffineTransform& transform, const Point<int>& point)
static ID2D1PathGeometry* pathToPathGeometry (const Path& path, const AffineTransform& transform)
{
ID2D1PathGeometry* p = nullptr;
Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p);
@@ -829,13 +830,13 @@ private:
HRESULT hr = p->Open (sink.resetAndGetPointerAddress());
sink->SetFillMode (D2D1_FILL_MODE_WINDING); // xxx need to check Path::isUsingNonZeroWinding()
pathToGeometrySink (path, sink, transform, point.getX(), point.getY());
pathToGeometrySink (path, sink, transform);
hr = sink->Close();
return p;
}
static const D2D1::Matrix3x2F transformToMatrix (const AffineTransform& transform)
static D2D1::Matrix3x2F transformToMatrix (const AffineTransform& transform)
{
D2D1::Matrix3x2F matrix;
matrix._11 = transform.mat00;


Loading…
Cancel
Save