diff --git a/modules/juce_graphics/juce_graphics.cpp b/modules/juce_graphics/juce_graphics.cpp index 7daa340bd4..d5f60660f7 100644 --- a/modules/juce_graphics/juce_graphics.cpp +++ b/modules/juce_graphics/juce_graphics.cpp @@ -114,12 +114,12 @@ namespace juce #elif JUCE_WINDOWS #include "../juce_core/native/juce_win32_ComSmartPtr.h" - #if JUCE_DIRECT2D - #include "native/juce_win32_Direct2DGraphicsContext.cpp" - #endif #include "native/juce_win32_DirectWriteTypeface.cpp" #include "native/juce_win32_DirectWriteTypeLayout.cpp" #include "native/juce_win32_Fonts.cpp" + #if JUCE_DIRECT2D + #include "native/juce_win32_Direct2DGraphicsContext.cpp" + #endif #elif JUCE_LINUX #include "native/juce_linux_Fonts.cpp" diff --git a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp index c6803d5020..1d121faada 100644 --- a/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp +++ b/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp @@ -23,36 +23,6 @@ ============================================================================== */ -class SharedD2DFactory : public DeletedAtShutdown -{ -public: - SharedD2DFactory() - { - jassertfalse; //xxx Direct2D support isn't ready for use yet! - - D2D1CreateFactory (D2D1_FACTORY_TYPE_SINGLE_THREADED, d2dFactory.resetAndGetPointerAddress()); - DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), (IUnknown**) directWriteFactory.resetAndGetPointerAddress()); - - if (directWriteFactory != nullptr) - directWriteFactory->GetSystemFontCollection (systemFonts.resetAndGetPointerAddress()); - } - - ~SharedD2DFactory() - { - clearSingletonInstance(); - } - - juce_DeclareSingleton (SharedD2DFactory, false); - - ComSmartPtr d2dFactory; - ComSmartPtr directWriteFactory; - ComSmartPtr systemFonts; -}; - -juce_ImplementSingleton (SharedD2DFactory) - - -//============================================================================== class Direct2DLowLevelGraphicsContext : public LowLevelGraphicsContext { public: @@ -68,10 +38,13 @@ public: D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(); D2D1_HWND_RENDER_TARGET_PROPERTIES propsHwnd = D2D1::HwndRenderTargetProperties (hwnd, size); - HRESULT hr = SharedD2DFactory::getInstance()->d2dFactory->CreateHwndRenderTarget (props, propsHwnd, renderingTarget.resetAndGetPointerAddress()); - // xxx check for error - - hr = renderingTarget->CreateSolidColorBrush (D2D1::ColorF::ColorF (0.0f, 0.0f, 0.0f, 1.0f), colourBrush.resetAndGetPointerAddress()); + const Direct2DFactories& factories = Direct2DFactories::getInstance(); + if (factories.d2dFactory != nullptr) + { + HRESULT hr = factories.d2dFactory->CreateHwndRenderTarget (props, propsHwnd, renderingTarget.resetAndGetPointerAddress()); + jassert (SUCCEEDED (hr)); (void) hr; + hr = renderingTarget->CreateSolidColorBrush (D2D1::ColorF::ColorF (0.0f, 0.0f, 0.0f, 1.0f), colourBrush.resetAndGetPointerAddress()); + } } ~Direct2DLowLevelGraphicsContext() @@ -115,7 +88,7 @@ public: currentState->origin.addXY (x, y); } - void addTransform (const AffineTransform& transform) + void addTransform (const AffineTransform& /*transform*/) { //xxx todo jassertfalse; @@ -123,7 +96,7 @@ public: float getScaleFactor() { - jassertfalse; //xxx + //xxx return 1.0f; } @@ -184,7 +157,7 @@ public: currentState = states.getLast(); } - void beginTransparencyLayer (float opacity) + void beginTransparencyLayer (float /*opacity*/) { jassertfalse; //xxx todo } @@ -208,7 +181,7 @@ public: { } - void fillRect (const Rectangle& r, bool replaceExistingContents) + void fillRect (const Rectangle& r, bool /*replaceExistingContents*/) { currentState->createBrush(); renderingTarget->FillRectangle (rectangleToRectF (r + currentState->origin), currentState->currentBrush); @@ -228,7 +201,7 @@ public: const int x = currentState->origin.getX(); const int y = currentState->origin.getY(); - renderingTarget->SetTransform (transformToMatrix (transform) * D2D1::Matrix3x2F::Translation (x, y)); + renderingTarget->SetTransform (transformToMatrix (transform) * D2D1::Matrix3x2F::Translation ((FLOAT) x, (FLOAT) y)); D2D1_SIZE_U size; size.width = image.getWidth(); @@ -272,8 +245,8 @@ public: x += currentState->origin.getX(); const int y = currentState->origin.getY(); - renderingTarget->DrawLine (D2D1::Point2F (x, y + top), - D2D1::Point2F (x, y + bottom), + renderingTarget->DrawLine (D2D1::Point2F ((FLOAT) x, y + top), + D2D1::Point2F ((FLOAT) x, y + bottom), currentState->currentBrush); } @@ -285,8 +258,8 @@ public: y += currentState->origin.getY(); const int x = currentState->origin.getX(); - renderingTarget->DrawLine (D2D1::Point2F (x + left, y), - D2D1::Point2F (x + right, y), + renderingTarget->DrawLine (D2D1::Point2F (x + left, (FLOAT) y), + D2D1::Point2F (x + right, (FLOAT) y), currentState->currentBrush); } @@ -302,39 +275,33 @@ public: void drawGlyph (int glyphNumber, const AffineTransform& transform) { - const float x = currentState->origin.getX(); - const float y = currentState->origin.getY(); + const float x = (float) currentState->origin.getX(); + const float y = (float) currentState->origin.getY(); currentState->createBrush(); currentState->createFont(); - float kerning = currentState->font.getExtraKerningFactor(); // xxx why does removing this line mess up the kerning?? float hScale = currentState->font.getHorizontalScale(); renderingTarget->SetTransform (D2D1::Matrix3x2F::Scale (hScale, 1) * transformToMatrix (transform) * D2D1::Matrix3x2F::Translation (x, y)); - float dpiX = 0, dpiY = 0; - SharedD2DFactory::getInstance()->d2dFactory->GetDesktopDpi (&dpiX, &dpiY); - - UINT32 glyphNum = glyphNumber; - UINT16 glyphNum1 = 0; // xxx needs a better name - what is this for? - currentState->currentFontFace->GetGlyphIndices (&glyphNum, 1, &glyphNum1); - + const UINT16 glyphIndices = (UINT16) glyphNumber; + const FLOAT glyphAdvances = 0; DWRITE_GLYPH_OFFSET offset; offset.advanceOffset = 0; offset.ascenderOffset = 0; - float glyphAdvances = 0; - - DWRITE_GLYPH_RUN glyph; - glyph.fontFace = currentState->currentFontFace; - glyph.glyphCount = 1; - glyph.glyphIndices = &glyphNum1; - glyph.isSideways = FALSE; - glyph.glyphAdvances = &glyphAdvances; - glyph.glyphOffsets = &offset; - glyph.fontEmSize = (float) currentState->font.getHeight() * dpiX / 96.0f * (1 + currentState->fontScaling) / 2; - - renderingTarget->DrawGlyphRun (D2D1::Point2F (0, 0), &glyph, currentState->currentBrush); + + DWRITE_GLYPH_RUN glyphRun; + glyphRun.fontFace = currentState->currentFontFace; + glyphRun.fontEmSize = (FLOAT) (currentState->font.getHeight() * currentState->fontHeightToEmSizeFactor); + glyphRun.glyphCount = 1; + glyphRun.glyphIndices = &glyphIndices; + glyphRun.glyphAdvances = &glyphAdvances; + glyphRun.glyphOffsets = &offset; + glyphRun.isSideways = FALSE; + glyphRun.bidiLevel = 0; + + renderingTarget->DrawGlyphRun (D2D1::Point2F (0, 0), &glyphRun, currentState->currentBrush); renderingTarget->SetTransform (D2D1::IdentityMatrix()); } @@ -344,7 +311,7 @@ public: public: SavedState (Direct2DLowLevelGraphicsContext& owner_) : owner (owner_), currentBrush (0), - fontScaling (1.0f), currentFontFace (0), + fontHeightToEmSizeFactor (1.0f), currentFontFace (0), clipsRect (false), shouldClipRect (false), clipsRectList (false), shouldClipRectList (false), clipsComplex (false), shouldClipComplex (false), @@ -572,35 +539,11 @@ public: void createFont() { - // xxx The font shouldn't be managed by the graphics context. - // The correct way to handle font lifetimes is to use a subclass of Typeface - see - // OSXTypeface and WindowsTypeface classes. D2D support could probably just be added to the - // WindowsTypeface class. - - if (currentFontFace == 0) + if (currentFontFace == nullptr) { - WindowsTypeface* systemType = dynamic_cast (font.getTypeface()); - fontScaling = systemType->getAscent(); - - BOOL fontFound; - uint32 fontIndex; - - IDWriteFontCollection* fonts = SharedD2DFactory::getInstance()->systemFonts; - - fonts->FindFamilyName (systemType->getName(), &fontIndex, &fontFound); - if (! fontFound) - fontIndex = 0; - - ComSmartPtr fontFam; - fonts->GetFontFamily (fontIndex, fontFam.resetAndGetPointerAddress()); - - ComSmartPtr font; - DWRITE_FONT_WEIGHT weight = this->font.isBold() ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL; - DWRITE_FONT_STYLE style = this->font.isItalic() ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; - fontFam->GetFirstMatchingFont (weight, DWRITE_FONT_STRETCH_NORMAL, style, font.resetAndGetPointerAddress()); - - font->CreateFontFace (localFontFace.resetAndGetPointerAddress()); - currentFontFace = localFontFace; + WindowsDirectWriteTypeface* typeface = dynamic_cast (font.getTypeface()); + currentFontFace = typeface->getIDWriteFontFace(); + fontHeightToEmSizeFactor = typeface->getFontHeightToEmSizeFactor(); } } @@ -676,7 +619,7 @@ public: for (int i = fillType.gradient->getNumColours(); --i >= 0;) { stops[i].color = colourToD2D (fillType.gradient->getColour(i)); - stops[i].position = fillType.gradient->getColourPosition(i); + stops[i].position = (FLOAT) fillType.gradient->getColourPosition(i); } owner.renderingTarget->CreateGradientStopCollection (stops.getData(), numColors, gradientStops.resetAndGetPointerAddress()); @@ -724,7 +667,7 @@ public: Point origin; Font font; - float fontScaling; + float fontHeightToEmSizeFactor; IDWriteFontFace* currentFontFace; ComSmartPtr localFontFace; @@ -787,7 +730,7 @@ private: static const D2D1_POINT_2F pointTransformed (int x, int y, const AffineTransform& transform = AffineTransform::identity) { transform.transformPoint (x, y); - return D2D1::Point2F (x, y); + return D2D1::Point2F ((FLOAT) x, (FLOAT) y); } static void rectToGeometrySink (const Rectangle& rect, ID2D1GeometrySink* sink) @@ -802,7 +745,7 @@ private: static ID2D1PathGeometry* rectListToPathGeometry (const RectangleList& clipRegion) { ID2D1PathGeometry* p = nullptr; - SharedD2DFactory::getInstance()->d2dFactory->CreatePathGeometry (&p); + Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p); ComSmartPtr sink; HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); // xxx handle error @@ -880,7 +823,7 @@ private: static ID2D1PathGeometry* pathToPathGeometry (const Path& path, const AffineTransform& transform, const Point& point) { ID2D1PathGeometry* p = nullptr; - SharedD2DFactory::getInstance()->d2dFactory->CreatePathGeometry (&p); + Direct2DFactories::getInstance().d2dFactory->CreatePathGeometry (&p); ComSmartPtr sink; HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); @@ -905,4 +848,4 @@ private: } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Direct2DLowLevelGraphicsContext); -}; +}; \ No newline at end of file diff --git a/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp b/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp index 9bf8eab6a3..708837f225 100644 --- a/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp +++ b/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp @@ -166,18 +166,19 @@ public: DWRITE_FONT_METRICS dwFontMetrics; dwFontFace->GetMetrics (&dwFontMetrics); - // All Font Metrics are in design units so we need to get designUnitsPerEm value to get the metrics - // into Em/Design Independent Pixels + // All Font Metrics are in design units so we need to get designUnitsPerEm value + // to get the metrics into Em/Design Independent Pixels designUnitsPerEm = dwFontMetrics.designUnitsPerEm; ascent = std::abs ((float) dwFontMetrics.ascent); const float totalSize = ascent + std::abs ((float) dwFontMetrics.descent); ascent /= totalSize; - unitsToHeightScaleFactor = 1.0f / (totalSize / designUnitsPerEm); - const float pathAscent = (((float) dwFontMetrics.ascent) / ((float) designUnitsPerEm)) * 1024.0f; - const float pathDescent = (((float) dwFontMetrics.descent) / ((float) designUnitsPerEm)) * 1024.0f; - const float pathTotalSize = std::abs (pathAscent) + std::abs (pathDescent); - pathTransform = AffineTransform::identity.scale (1.0f / pathTotalSize, 1.0f / pathTotalSize); + unitsToHeightScaleFactor = designUnitsPerEm / totalSize; + + const float pathAscent = (1024.0f * dwFontMetrics.ascent) / designUnitsPerEm; + const float pathDescent = (1024.0f * dwFontMetrics.descent) / designUnitsPerEm; + const float pathScale = 1.0f / (std::abs (pathAscent) + std::abs (pathDescent)); + pathTransform = AffineTransform::scale (pathScale, pathScale); } float getAscent() const { return ascent; } @@ -248,6 +249,9 @@ public: return true; } + IDWriteFontFace* getIDWriteFontFace() const noexcept { return dwFontFace; } + float getFontHeightToEmSizeFactor() const noexcept { return unitsToHeightScaleFactor; } + private: ComSmartPtr dwFontFace; float unitsToHeightScaleFactor, ascent;