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) 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() float getScaleFactor()
{ {
//xxx
return 1.0f;
return currentState->transform.getScaleFactor();
} }
bool clipToRectangle (const Rectangle<int>& r) bool clipToRectangle (const Rectangle<int>& r)
@@ -119,24 +117,23 @@ public:
void clipToPath (const Path& path, const AffineTransform& transform) 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) void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
{ {
currentState->clipToImage (sourceImage,transform);
currentState->clipToImage (sourceImage, transform);
} }
bool clipRegionIntersects (const Rectangle<int>& r) 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 Rectangle<int> getClipBounds() const
{ {
// xxx could this take into account complex clip regions? // 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 bool isClipEmpty() const
@@ -183,14 +180,16 @@ public:
void fillRect (const Rectangle<int>& r, bool /*replaceExistingContents*/) void fillRect (const Rectangle<int>& r, bool /*replaceExistingContents*/)
{ {
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
currentState->createBrush(); 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) void fillPath (const Path& p, const AffineTransform& transform)
{ {
currentState->createBrush(); currentState->createBrush();
ComSmartPtr <ID2D1Geometry> geometry (pathToPathGeometry (p, transform, currentState->origin));
ComSmartPtr <ID2D1Geometry> geometry (pathToPathGeometry (p, transform.followedBy (currentState->transform)));
if (renderingTarget != nullptr) if (renderingTarget != nullptr)
renderingTarget->FillGeometry (geometry, currentState->currentBrush); renderingTarget->FillGeometry (geometry, currentState->currentBrush);
@@ -198,10 +197,7 @@ public:
void drawImage (const Image& image, const AffineTransform& transform) 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; D2D1_SIZE_U size;
size.width = image.getWidth(); size.width = image.getWidth();
@@ -227,40 +223,37 @@ public:
void drawLine (const Line <float>& line) 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 // 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(); 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); currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
} }
void drawVerticalLine (int x, float top, float bottom) 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 // 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(); 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); currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
} }
void drawHorizontalLine (int y, float left, float right) 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 // 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(); 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); currentState->currentBrush);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
} }
void setFont (const Font& newFont) void setFont (const Font& newFont)
@@ -275,15 +268,14 @@ public:
void drawGlyph (int glyphNumber, const AffineTransform& transform) void drawGlyph (int glyphNumber, const AffineTransform& transform)
{ {
const float x = (float) currentState->origin.getX();
const float y = (float) currentState->origin.getY();
currentState->createBrush(); currentState->createBrush();
currentState->createFont(); currentState->createFont();
float hScale = currentState->font.getHorizontalScale(); 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 UINT16 glyphIndices = (UINT16) glyphNumber;
const FLOAT glyphAdvances = 0; const FLOAT glyphAdvances = 0;
@@ -305,6 +297,18 @@ public:
renderingTarget->SetTransform (D2D1::IdentityMatrix()); 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 class SavedState
{ {
@@ -323,8 +327,8 @@ public:
// bottleneck.. Can the same internal objects be shared by multiple state objects, maybe using copy-on-write? // bottleneck.. Can the same internal objects be shared by multiple state objects, maybe using copy-on-write?
setFill (owner.currentState->fillType); setFill (owner.currentState->fillType);
currentBrush = owner.currentState->currentBrush; currentBrush = owner.currentState->currentBrush;
origin = owner.currentState->origin;
clipRect = owner.currentState->clipRect; clipRect = owner.currentState->clipRect;
transform = owner.currentState->transform;
font = owner.currentState->font; font = owner.currentState->font;
currentFontFace = owner.currentState->currentFontFace; currentFontFace = owner.currentState->currentFontFace;
@@ -357,7 +361,7 @@ public:
void clipToRectangle (const Rectangle<int>& r) void clipToRectangle (const Rectangle<int>& r)
{ {
clearClip(); clearClip();
clipRect = r + origin;
clipRect = r.toFloat().transformed (transform).getSmallestIntegerContainer();
shouldClipRect = true; shouldClipRect = true;
pushClips(); pushClips();
} }
@@ -569,9 +573,6 @@ public:
{ {
if (currentBrush == 0) if (currentBrush == 0)
{ {
const int x = origin.getX();
const int y = origin.getY();
if (fillType.isColour()) if (fillType.isColour())
{ {
D2D1_COLOR_F colour = colourToD2D (fillType.colour); D2D1_COLOR_F colour = colourToD2D (fillType.colour);
@@ -610,7 +611,7 @@ public:
D2D1_BRUSH_PROPERTIES brushProps; D2D1_BRUSH_PROPERTIES brushProps;
brushProps.opacity = fillType.getOpacity(); brushProps.opacity = fillType.getOpacity();
brushProps.transform = transformToMatrix (fillType.transform);
brushProps.transform = transformToMatrix (fillType.transform.followedBy (transform));
const int numColors = fillType.gradient->getNumColours(); const int numColors = fillType.gradient->getNumColours();
@@ -633,7 +634,7 @@ public:
float r = p1.getDistanceFrom (p2); float r = p1.getDistanceFrom (p2);
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES props = 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), D2D1::Point2F (0, 0),
r, r); r, r);
@@ -648,8 +649,8 @@ public:
const Point<float>& p2 = fillType.gradient->point2; const Point<float>& p2 = fillType.gradient->point2;
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props = 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()); owner.renderingTarget->CreateLinearGradientBrush (props, brushProps, gradientStops, linearGradient.resetAndGetPointerAddress());
@@ -664,7 +665,7 @@ public:
Direct2DLowLevelGraphicsContext& owner; Direct2DLowLevelGraphicsContext& owner;
Point<int> origin;
AffineTransform transform;
Font font; Font font;
float fontHeightToEmSizeFactor; float fontHeightToEmSizeFactor;
@@ -722,12 +723,12 @@ private:
return D2D1::RectF ((float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); 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()); 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); transform.transformPoint (x, y);
return D2D1::Point2F ((FLOAT) x, (FLOAT) y); return D2D1::Point2F ((FLOAT) x, (FLOAT) y);
@@ -758,7 +759,7 @@ private:
return p; 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); Path::Iterator it (path);
@@ -771,13 +772,13 @@ private:
D2D1_BEZIER_SEGMENT seg; D2D1_BEZIER_SEGMENT seg;
transform.transformPoint (it.x1, it.y1); 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); 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); 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); sink->AddBezier (seg);
break; break;
@@ -786,7 +787,7 @@ private:
case Path::Iterator::lineTo: case Path::Iterator::lineTo:
{ {
transform.transformPoint (it.x1, it.y1); 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; break;
} }
@@ -795,10 +796,10 @@ private:
D2D1_QUADRATIC_BEZIER_SEGMENT seg; D2D1_QUADRATIC_BEZIER_SEGMENT seg;
transform.transformPoint (it.x1, it.y1); 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); 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); sink->AddQuadraticBezier (seg);
break; break;
@@ -813,14 +814,14 @@ private:
case Path::Iterator::startNewSubPath: case Path::Iterator::startNewSubPath:
{ {
transform.transformPoint (it.x1, it.y1); 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; 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; ID2D1PathGeometry* p = nullptr;
Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p); Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p);
@@ -829,13 +830,13 @@ private:
HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); HRESULT hr = p->Open (sink.resetAndGetPointerAddress());
sink->SetFillMode (D2D1_FILL_MODE_WINDING); // xxx need to check Path::isUsingNonZeroWinding() 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(); hr = sink->Close();
return p; return p;
} }
static const D2D1::Matrix3x2F transformToMatrix (const AffineTransform& transform)
static D2D1::Matrix3x2F transformToMatrix (const AffineTransform& transform)
{ {
D2D1::Matrix3x2F matrix; D2D1::Matrix3x2F matrix;
matrix._11 = transform.mat00; matrix._11 = transform.mat00;


Loading…
Cancel
Save