1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-11 23:54:18 +00:00

TextLayout: added support for using the AttributedString::getLineSpacing value in DirectWrite

This commit is contained in:
jules 2015-11-24 17:53:11 +00:00
parent 6fcde1eccc
commit d833ab5e33
2 changed files with 56 additions and 51 deletions

View file

@ -198,7 +198,7 @@ public:
void fillPath (const Path& p, const AffineTransform& transform)
{
currentState->createBrush();
ComSmartPtr <ID2D1Geometry> geometry (pathToPathGeometry (p, transform.followedBy (currentState->transform)));
ComSmartPtr<ID2D1Geometry> geometry (pathToPathGeometry (p, transform.followedBy (currentState->transform)));
if (renderingTarget != nullptr)
renderingTarget->FillGeometry (geometry, currentState->currentBrush);
@ -220,7 +220,7 @@ public:
bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
{
ComSmartPtr <ID2D1Bitmap> tempBitmap;
ComSmartPtr<ID2D1Bitmap> tempBitmap;
renderingTarget->CreateBitmap (size, bd.data, bd.lineStride, bp, tempBitmap.resetAndGetPointerAddress());
if (tempBitmap != nullptr)
renderingTarget->DrawBitmap (tempBitmap);
@ -286,7 +286,7 @@ public:
{
renderingTarget->SetTransform (transformToMatrix (currentState->transform));
DirectWriteTypeLayout::drawToD2DContext (text, area, renderingTarget, factories->directWriteFactory,
DirectWriteTypeLayout::drawToD2DContext (text, area, *renderingTarget, factories->directWriteFactory,
factories->d2dFactory, factories->systemFonts);
renderingTarget->SetTransform (D2D1::IdentityMatrix());
@ -654,38 +654,38 @@ public:
Font font;
float fontHeightToEmSizeFactor;
IDWriteFontFace* currentFontFace;
ComSmartPtr <IDWriteFontFace> localFontFace;
ComSmartPtr<IDWriteFontFace> localFontFace;
FillType fillType;
Image image;
ComSmartPtr <ID2D1Bitmap> bitmap; // xxx needs a better name - what is this for??
ComSmartPtr<ID2D1Bitmap> bitmap; // xxx needs a better name - what is this for??
Rectangle<int> clipRect;
bool clipsRect, shouldClipRect;
ComSmartPtr <ID2D1Geometry> complexClipGeometry;
ComSmartPtr<ID2D1Geometry> complexClipGeometry;
D2D1_LAYER_PARAMETERS complexClipLayerParams;
ComSmartPtr <ID2D1Layer> complexClipLayer;
ComSmartPtr<ID2D1Layer> complexClipLayer;
bool clipsComplex, shouldClipComplex;
ComSmartPtr <ID2D1Geometry> rectListGeometry;
ComSmartPtr<ID2D1Geometry> rectListGeometry;
D2D1_LAYER_PARAMETERS rectListLayerParams;
ComSmartPtr <ID2D1Layer> rectListLayer;
ComSmartPtr<ID2D1Layer> rectListLayer;
bool clipsRectList, shouldClipRectList;
Image maskImage;
D2D1_LAYER_PARAMETERS imageMaskLayerParams;
ComSmartPtr <ID2D1Layer> bitmapMaskLayer;
ComSmartPtr <ID2D1Bitmap> maskBitmap;
ComSmartPtr <ID2D1BitmapBrush> bitmapMaskBrush;
ComSmartPtr<ID2D1Layer> bitmapMaskLayer;
ComSmartPtr<ID2D1Bitmap> maskBitmap;
ComSmartPtr<ID2D1BitmapBrush> bitmapMaskBrush;
bool clipsBitmap, shouldClipBitmap;
ID2D1Brush* currentBrush;
ComSmartPtr <ID2D1BitmapBrush> bitmapBrush;
ComSmartPtr <ID2D1LinearGradientBrush> linearGradient;
ComSmartPtr <ID2D1RadialGradientBrush> radialGradient;
ComSmartPtr <ID2D1GradientStopCollection> gradientStops;
ComSmartPtr<ID2D1BitmapBrush> bitmapBrush;
ComSmartPtr<ID2D1LinearGradientBrush> linearGradient;
ComSmartPtr<ID2D1RadialGradientBrush> radialGradient;
ComSmartPtr<ID2D1GradientStopCollection> gradientStops;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SavedState)
@ -695,8 +695,8 @@ public:
private:
SharedResourcePointer<Direct2DFactories> factories;
HWND hwnd;
ComSmartPtr <ID2D1HwndRenderTarget> renderingTarget;
ComSmartPtr <ID2D1SolidColorBrush> colourBrush;
ComSmartPtr<ID2D1HwndRenderTarget> renderingTarget;
ComSmartPtr<ID2D1SolidColorBrush> colourBrush;
Rectangle<int> bounds;
SavedState* currentState;
@ -734,7 +734,7 @@ private:
ID2D1PathGeometry* p = nullptr;
factories->d2dFactory->CreatePathGeometry (&p);
ComSmartPtr <ID2D1GeometrySink> sink;
ComSmartPtr<ID2D1GeometrySink> sink;
HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); // xxx handle error
sink->SetFillMode (D2D1_FILL_MODE_WINDING);
@ -812,7 +812,7 @@ private:
ID2D1PathGeometry* p = nullptr;
factories->d2dFactory->CreatePathGeometry (&p);
ComSmartPtr <ID2D1GeometrySink> sink;
ComSmartPtr<ID2D1GeometrySink> sink;
HRESULT hr = p->Open (sink.resetAndGetPointerAddress());
sink->SetFillMode (D2D1_FILL_MODE_WINDING); // xxx need to check Path::isUsingNonZeroWinding()

View file

@ -125,7 +125,7 @@ namespace DirectWriteTypeLayout
const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent);
const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight;
glyphRunLayout->font = getFontForRun (glyphRun, glyphRun->fontEmSize / fontHeightToEmSizeFactor);
glyphRunLayout->font = getFontForRun (*glyphRun, glyphRun->fontEmSize / fontHeightToEmSizeFactor);
glyphRunLayout->colour = getColourOf (static_cast<ID2D1SolidColorBrush*> (clientDrawingEffect));
const Point<float> lineOrigin (layout->getLine (currentLine).lineOrigin);
@ -169,16 +169,16 @@ namespace DirectWriteTypeLayout
return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a);
}
Font getFontForRun (DWRITE_GLYPH_RUN const* glyphRun, float fontHeight)
Font getFontForRun (const DWRITE_GLYPH_RUN& glyphRun, float fontHeight)
{
for (int i = 0; i < attributedString.getNumAttributes(); ++i)
if (const Font* font = attributedString.getAttribute(i)->getFont())
if (WindowsDirectWriteTypeface* wt = dynamic_cast<WindowsDirectWriteTypeface*> (font->getTypeface()))
if (wt->getIDWriteFontFace() == glyphRun->fontFace)
if (wt->getIDWriteFontFace() == glyphRun.fontFace)
return font->withHeight (fontHeight);
ComSmartPtr<IDWriteFont> dwFont;
HRESULT hr = fontCollection.GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress());
HRESULT hr = fontCollection.GetFontFromFontFace (glyphRun.fontFace, dwFont.resetAndGetPointerAddress());
jassert (dwFont != nullptr);
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
@ -206,7 +206,7 @@ namespace DirectWriteTypeLayout
return dwFontMetrics.designUnitsPerEm / totalHeight;
}
void setTextFormatProperties (const AttributedString& text, IDWriteTextFormat* const format)
void setTextFormatProperties (const AttributedString& text, IDWriteTextFormat& format)
{
DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
DWRITE_WORD_WRAPPING wrapType = DWRITE_WORD_WRAPPING_WRAP;
@ -232,7 +232,7 @@ namespace DirectWriteTypeLayout
// This must be set correctly and manually when using RTL Scripts (Hebrew, Arabic)
if (text.getReadingDirection() == AttributedString::rightToLeft)
{
format->SetReadingDirection (DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
format.SetReadingDirection (DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
switch (text.getJustification().getOnlyHorizontalFlags())
{
@ -242,12 +242,12 @@ namespace DirectWriteTypeLayout
}
}
format->SetTextAlignment (alignment);
format->SetWordWrapping (wrapType);
format.SetTextAlignment (alignment);
format.SetWordWrapping (wrapType);
}
void addAttributedRange (const AttributedString::Attribute& attr, IDWriteTextLayout* textLayout,
const int textLen, ID2D1RenderTarget* const renderTarget, IDWriteFontCollection& fontCollection)
void addAttributedRange (const AttributedString::Attribute& attr, IDWriteTextLayout& textLayout,
const int textLen, ID2D1RenderTarget& renderTarget, IDWriteFontCollection& fontCollection)
{
DWRITE_TEXT_RANGE range;
range.startPosition = attr.range.getStart();
@ -279,31 +279,31 @@ namespace DirectWriteTypeLayout
break;
}
textLayout->SetFontFamilyName (familyName.toWideCharPointer(), range);
textLayout->SetFontWeight (dwFont->GetWeight(), range);
textLayout->SetFontStretch (dwFont->GetStretch(), range);
textLayout->SetFontStyle (dwFont->GetStyle(), range);
textLayout.SetFontFamilyName (familyName.toWideCharPointer(), range);
textLayout.SetFontWeight (dwFont->GetWeight(), range);
textLayout.SetFontStretch (dwFont->GetStretch(), range);
textLayout.SetFontStyle (dwFont->GetStyle(), range);
const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (*dwFont);
textLayout->SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range);
textLayout.SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range);
}
if (const Colour* const colour = attr.getColour())
{
ComSmartPtr<ID2D1SolidColorBrush> d2dBrush;
renderTarget->CreateSolidColorBrush (D2D1::ColorF (D2D1::ColorF (colour->getFloatRed(),
colour->getFloatGreen(),
colour->getFloatBlue(),
colour->getFloatAlpha())),
d2dBrush.resetAndGetPointerAddress());
renderTarget.CreateSolidColorBrush (D2D1::ColorF (colour->getFloatRed(),
colour->getFloatGreen(),
colour->getFloatBlue(),
colour->getFloatAlpha()),
d2dBrush.resetAndGetPointerAddress());
// We need to call SetDrawingEffect with a legimate brush to get DirectWrite to break text based on colours
textLayout->SetDrawingEffect (d2dBrush, range);
textLayout.SetDrawingEffect (d2dBrush, range);
}
}
bool setupLayout (const AttributedString& text, const float maxWidth, const float maxHeight,
ID2D1RenderTarget* const renderTarget, IDWriteFactory& directWriteFactory,
ID2D1RenderTarget& renderTarget, IDWriteFactory& directWriteFactory,
IDWriteFontCollection& fontCollection, ComSmartPtr<IDWriteTextLayout>& textLayout)
{
// To add color to text, we need to create a D2D render target
@ -333,7 +333,7 @@ namespace DirectWriteTypeLayout
defaultFont.getHeight() * defaultFontHeightToEmSizeFactor,
L"en-us", dwTextFormat.resetAndGetPointerAddress());
setTextFormatProperties (text, dwTextFormat);
setTextFormatProperties (text, *dwTextFormat);
{
DWRITE_TRIMMING trimming = { DWRITE_TRIMMING_GRANULARITY_CHARACTER, 0, 0 };
@ -353,7 +353,7 @@ namespace DirectWriteTypeLayout
const int numAttributes = text.getNumAttributes();
for (int i = 0; i < numAttributes; ++i)
addAttributedRange (*text.getAttribute (i), textLayout, textLen, renderTarget, fontCollection);
addAttributedRange (*text.getAttribute (i), *textLayout, textLen, renderTarget, fontCollection);
return true;
}
@ -375,7 +375,7 @@ namespace DirectWriteTypeLayout
ComSmartPtr<IDWriteTextLayout> dwTextLayout;
if (! setupLayout (text, layout.getWidth(), layout.getHeight(), renderTarget,
if (! setupLayout (text, layout.getWidth(), layout.getHeight(), *renderTarget,
directWriteFactory, fontCollection, dwTextLayout))
return;
@ -393,15 +393,20 @@ namespace DirectWriteTypeLayout
hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount);
int lastLocation = 0;
const int numLines = jmin ((int) actualLineCount, layout.getNumLines());
float yAdjustment = 0;
const float extraLineSpacing = text.getLineSpacing();
for (int i = 0; i < numLines; ++i)
{
layout.getLine(i).stringRange = Range<int> (lastLocation, (int) lastLocation + dwLineMetrics[i].length);
TextLayout::Line& line = layout.getLine (i);
line.stringRange = Range<int> (lastLocation, (int) lastLocation + dwLineMetrics[i].length);
line.lineOrigin.y += yAdjustment;
yAdjustment += extraLineSpacing;
lastLocation += dwLineMetrics[i].length;
}
}
void drawToD2DContext (const AttributedString& text, const Rectangle<float>& area, ID2D1RenderTarget* const renderTarget,
void drawToD2DContext (const AttributedString& text, const Rectangle<float>& area, ID2D1RenderTarget& renderTarget,
IDWriteFactory& directWriteFactory, IDWriteFontCollection& fontCollection)
{
ComSmartPtr<IDWriteTextLayout> dwTextLayout;
@ -410,11 +415,11 @@ namespace DirectWriteTypeLayout
directWriteFactory, fontCollection, dwTextLayout))
{
ComSmartPtr<ID2D1SolidColorBrush> d2dBrush;
renderTarget->CreateSolidColorBrush (D2D1::ColorF (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f)),
d2dBrush.resetAndGetPointerAddress());
renderTarget.CreateSolidColorBrush (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f),
d2dBrush.resetAndGetPointerAddress());
renderTarget->DrawTextLayout (D2D1::Point2F ((float) area.getX(), (float) area.getY()),
dwTextLayout, d2dBrush, D2D1_DRAW_TEXT_OPTIONS_CLIP);
renderTarget.DrawTextLayout (D2D1::Point2F ((float) area.getX(), (float) area.getY()),
dwTextLayout, d2dBrush, D2D1_DRAW_TEXT_OPTIONS_CLIP);
}
}
}