summaryrefslogtreecommitdiffstats
path: root/src/gui_dwrite.cpp
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-11-26 14:29:32 +0100
committerBram Moolenaar <Bram@vim.org>2017-11-26 14:29:32 +0100
commitd7ccc4d81dbcfa3ac0352bacea6e294fc9e33fda (patch)
tree3f61bdfbadc4f376a8a4bc03dc91eb34958eef37 /src/gui_dwrite.cpp
parentfb1db0e3550355e10ac86c4a4af21209c5456a66 (diff)
patch 8.0.1343: MS-Windows: does not show colored emojisv8.0.1343
Problem: MS-Windows: does not show colored emojis. Solution: Implement colored emojis. Improve drawing speed. Make 'taamode' work. (Taro Muraoka, Yasuhiro Matsumoto, Ken Takata, close #2375)
Diffstat (limited to 'src/gui_dwrite.cpp')
-rw-r--r--src/gui_dwrite.cpp666
1 files changed, 416 insertions, 250 deletions
diff --git a/src/gui_dwrite.cpp b/src/gui_dwrite.cpp
index 9873c67283..bd76383c5a 100644
--- a/src/gui_dwrite.cpp
+++ b/src/gui_dwrite.cpp
@@ -4,6 +4,7 @@
*
* Contributors:
* - Ken Takata
+ * - Yasuhiro Matsumoto
*
* Copyright (C) 2013 MURAOKA Taro <koron.kaoriya@gmail.com>
* THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE.
@@ -23,7 +24,21 @@
#include <math.h>
#include <d2d1.h>
#include <d2d1helper.h>
-#include <dwrite.h>
+
+// Disable these macros to compile with old VC and newer SDK (V8.1 or later).
+#if defined(_MSC_VER) && (_MSC_VER < 1700)
+# define _COM_Outptr_ __out
+# define _In_reads_(s)
+# define _In_reads_opt_(s)
+# define _Maybenull_
+# define _Out_writes_(s)
+# define _Out_writes_opt_(s)
+# define _Out_writes_to_(x, y)
+# define _Out_writes_to_opt_(x, y)
+# define _Outptr_
+#endif
+
+#include <dwrite_2.h>
#include "gui_dwrite.h"
@@ -79,16 +94,6 @@ template <class T> inline void SafeRelease(T **ppT)
}
}
-struct GdiTextRendererContext
-{
- // const fields.
- COLORREF color;
- FLOAT cellWidth;
-
- // working fields.
- FLOAT offsetX;
-};
-
static DWRITE_PIXEL_GEOMETRY
ToPixelGeometry(int value)
{
@@ -184,17 +189,151 @@ ToInt(DWRITE_RENDERING_MODE value)
}
}
+class FontCache {
+public:
+ struct Item {
+ HFONT hFont;
+ IDWriteTextFormat* pTextFormat;
+ DWRITE_FONT_WEIGHT fontWeight;
+ DWRITE_FONT_STYLE fontStyle;
+ Item() : hFont(NULL), pTextFormat(NULL) {}
+ };
+
+private:
+ int mSize;
+ Item *mItems;
+
+public:
+ FontCache(int size = 2) :
+ mSize(size),
+ mItems(new Item[size])
+ {
+ }
+
+ ~FontCache()
+ {
+ for (int i = 0; i < mSize; ++i)
+ SafeRelease(&mItems[i].pTextFormat);
+ delete[] mItems;
+ }
+
+ bool get(HFONT hFont, Item &item)
+ {
+ int n = find(hFont);
+ if (n < 0)
+ return false;
+ item = mItems[n];
+ slide(n);
+ return true;
+ }
+
+ void put(const Item& item)
+ {
+ int n = find(item.hFont);
+ if (n < 0)
+ n = mSize - 1;
+ if (mItems[n].pTextFormat != item.pTextFormat)
+ {
+ SafeRelease(&mItems[n].pTextFormat);
+ item.pTextFormat->AddRef();
+ }
+ mItems[n] = item;
+ slide(n);
+ }
+
+private:
+ int find(HFONT hFont)
+ {
+ for (int i = 0; i < mSize; ++i)
+ {
+ if (mItems[i].hFont == hFont)
+ return i;
+ }
+ return -1;
+ }
+
+ void slide(int nextTop)
+ {
+ if (nextTop == 0)
+ return;
+ Item tmp = mItems[nextTop];
+ for (int i = nextTop - 1; i >= 0; --i)
+ mItems[i + 1] = mItems[i];
+ mItems[0] = tmp;
+ }
+};
+
+struct DWriteContext {
+ HDC mHDC;
+ bool mDrawing;
+ bool mFallbackDC;
+
+ ID2D1Factory *mD2D1Factory;
+
+ ID2D1DCRenderTarget *mRT;
+ ID2D1SolidColorBrush *mBrush;
+
+ IDWriteFactory *mDWriteFactory;
+ IDWriteFactory2 *mDWriteFactory2;
+
+ IDWriteGdiInterop *mGdiInterop;
+ IDWriteRenderingParams *mRenderingParams;
+
+ FontCache mFontCache;
+ IDWriteTextFormat *mTextFormat;
+ DWRITE_FONT_WEIGHT mFontWeight;
+ DWRITE_FONT_STYLE mFontStyle;
+
+ D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
+
+ // METHODS
+
+ DWriteContext();
+
+ virtual ~DWriteContext();
+
+ HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
+ IDWriteTextFormat **ppTextFormat);
+
+ HRESULT SetFontByLOGFONT(const LOGFONTW &logFont);
+
+ void SetFont(HFONT hFont);
+
+ void BindDC(HDC hdc, RECT *rect);
+
+ void AssureDrawing();
+
+ ID2D1Brush* SolidBrush(COLORREF color);
+
+ void DrawText(const WCHAR* text, int len,
+ int x, int y, int w, int h, int cellWidth, COLORREF color,
+ UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx);
+
+ void FillRect(RECT *rc, COLORREF color);
+
+ void Flush();
+
+ void SetRenderingParams(
+ const DWriteRenderingParams *params);
+
+ DWriteRenderingParams *GetRenderingParams(
+ DWriteRenderingParams *params);
+};
+
class AdjustedGlyphRun : public DWRITE_GLYPH_RUN
{
private:
+ FLOAT &mAccum;
FLOAT mDelta;
FLOAT *mAdjustedAdvances;
public:
AdjustedGlyphRun(
const DWRITE_GLYPH_RUN *glyphRun,
- FLOAT cellWidth) :
+ FLOAT cellWidth,
+ FLOAT &accum) :
DWRITE_GLYPH_RUN(*glyphRun),
+ mAccum(accum),
mDelta(0.0f),
mAdjustedAdvances(new FLOAT[glyphRun->glyphCount])
{
@@ -209,45 +348,44 @@ public:
glyphAdvances = mAdjustedAdvances;
}
- ~AdjustedGlyphRun(void)
+ ~AdjustedGlyphRun()
{
+ mAccum += mDelta;
delete[] mAdjustedAdvances;
}
- FLOAT getDelta(void) const
- {
- return mDelta;
- }
-
static FLOAT adjustToCell(FLOAT value, FLOAT cellWidth)
{
- int cellCount = (int)floor(value / cellWidth + 0.5f);
+ int cellCount = int(floor(value / cellWidth + 0.5f));
if (cellCount < 1)
cellCount = 1;
return cellCount * cellWidth;
}
};
-class GdiTextRenderer FINAL : public IDWriteTextRenderer
+struct TextRendererContext {
+ // const fields.
+ COLORREF color;
+ FLOAT cellWidth;
+
+ // working fields.
+ FLOAT offsetX;
+};
+
+class TextRenderer FINAL : public IDWriteTextRenderer
{
public:
- GdiTextRenderer(
- IDWriteBitmapRenderTarget* bitmapRenderTarget,
- IDWriteRenderingParams* renderingParams) :
+ TextRenderer(
+ DWriteContext* pDWC) :
cRefCount_(0),
- pRenderTarget_(bitmapRenderTarget),
- pRenderingParams_(renderingParams)
+ pDWC_(pDWC)
{
- pRenderTarget_->AddRef();
- pRenderingParams_->AddRef();
AddRef();
}
// add "virtual" to avoid a compiler warning
- virtual ~GdiTextRenderer()
+ virtual ~TextRenderer()
{
- SafeRelease(&pRenderTarget_);
- SafeRelease(&pRenderingParams_);
}
IFACEMETHOD(IsPixelSnappingDisabled)(
@@ -263,7 +401,8 @@ public:
__out DWRITE_MATRIX* transform)
{
// forward the render target's transform
- pRenderTarget_->GetCurrentTransform(transform);
+ pDWC_->mRT->GetTransform(
+ reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
return S_OK;
}
@@ -271,43 +410,12 @@ public:
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip)
{
- *pixelsPerDip = pRenderTarget_->GetPixelsPerDip();
+ float dpiX, unused;
+ pDWC_->mRT->GetDpi(&dpiX, &unused);
+ *pixelsPerDip = dpiX / 96.0f;
return S_OK;
}
- IFACEMETHOD(DrawGlyphRun)(
- __maybenull void* clientDrawingContext,
- FLOAT baselineOriginX,
- FLOAT baselineOriginY,
- DWRITE_MEASURING_MODE measuringMode,
- __in DWRITE_GLYPH_RUN const* glyphRun,
- __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
- IUnknown* clientDrawingEffect)
- {
- HRESULT hr = S_OK;
-
- GdiTextRendererContext *context =
- reinterpret_cast<GdiTextRendererContext*>(clientDrawingContext);
-
- AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth);
-
- // Pass on the drawing call to the render target to do the real work.
- RECT dirtyRect = {0};
-
- hr = pRenderTarget_->DrawGlyphRun(
- baselineOriginX + context->offsetX,
- baselineOriginY,
- measuringMode,
- &adjustedGlyphRun,
- pRenderingParams_,
- context->color,
- &dirtyRect);
-
- context->offsetX += adjustedGlyphRun.getDelta();
-
- return hr;
- }
-
IFACEMETHOD(DrawUnderline)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
@@ -340,6 +448,69 @@ public:
return E_NOTIMPL;
}
+ IFACEMETHOD(DrawGlyphRun)(
+ __maybenull void* clientDrawingContext,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_MEASURING_MODE measuringMode,
+ __in DWRITE_GLYPH_RUN const* glyphRun,
+ __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
+ IUnknown* clientDrawingEffect)
+ {
+ TextRendererContext *context =
+ reinterpret_cast<TextRendererContext*>(clientDrawingContext);
+
+ AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth,
+ context->offsetX);
+
+ if (pDWC_->mDWriteFactory2 != NULL)
+ {
+ IDWriteColorGlyphRunEnumerator *enumerator = NULL;
+ HRESULT hr = pDWC_->mDWriteFactory2->TranslateColorGlyphRun(
+ baselineOriginX + context->offsetX,
+ baselineOriginY,
+ &adjustedGlyphRun,
+ NULL,
+ DWRITE_MEASURING_MODE_GDI_NATURAL,
+ NULL,
+ 0,
+ &enumerator);
+ if (SUCCEEDED(hr))
+ {
+ // Draw by IDWriteFactory2 for color emoji
+ BOOL hasRun = TRUE;
+ enumerator->MoveNext(&hasRun);
+ while (hasRun)
+ {
+ const DWRITE_COLOR_GLYPH_RUN* colorGlyphRun;
+ enumerator->GetCurrentRun(&colorGlyphRun);
+
+ pDWC_->mBrush->SetColor(colorGlyphRun->runColor);
+ pDWC_->mRT->DrawGlyphRun(
+ D2D1::Point2F(
+ colorGlyphRun->baselineOriginX,
+ colorGlyphRun->baselineOriginY),
+ &colorGlyphRun->glyphRun,
+ pDWC_->mBrush,
+ DWRITE_MEASURING_MODE_NATURAL);
+ enumerator->MoveNext(&hasRun);
+ }
+ SafeRelease(&enumerator);
+ return S_OK;
+ }
+ }
+
+ // Draw by IDWriteFactory (without color emoji)
+ pDWC_->mRT->DrawGlyphRun(
+ D2D1::Point2F(
+ baselineOriginX + context->offsetX,
+ baselineOriginY),
+ &adjustedGlyphRun,
+ pDWC_->SolidBrush(context->color),
+ DWRITE_MEASURING_MODE_NATURAL);
+ return S_OK;
+ }
+
public:
IFACEMETHOD_(unsigned long, AddRef) ()
{
@@ -385,80 +556,28 @@ public:
private:
long cRefCount_;
- IDWriteBitmapRenderTarget* pRenderTarget_;
- IDWriteRenderingParams* pRenderingParams_;
-};
-
-struct DWriteContext {
- FLOAT mDpiScaleX;
- FLOAT mDpiScaleY;
- bool mDrawing;
-
- ID2D1Factory *mD2D1Factory;
-
- ID2D1DCRenderTarget *mRT;
- ID2D1SolidColorBrush *mBrush;
-
- IDWriteFactory *mDWriteFactory;
- IDWriteGdiInterop *mGdiInterop;
- IDWriteRenderingParams *mRenderingParams;
- IDWriteTextFormat *mTextFormat;
-
- HFONT mLastHFont;
- DWRITE_FONT_WEIGHT mFontWeight;
- DWRITE_FONT_STYLE mFontStyle;
-
- D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
-
- // METHODS
-
- DWriteContext();
-
- virtual ~DWriteContext();
-
- HRESULT SetLOGFONT(const LOGFONTW &logFont, float fontSize);
-
- void SetFont(HFONT hFont);
-
- void SetFont(const LOGFONTW &logFont);
-
- void DrawText(HDC hdc, const WCHAR* text, int len,
- int x, int y, int w, int h, int cellWidth, COLORREF color);
-
- float PixelsToDipsX(int x);
-
- float PixelsToDipsY(int y);
-
- void SetRenderingParams(
- const DWriteRenderingParams *params);
-
- DWriteRenderingParams *GetRenderingParams(
- DWriteRenderingParams *params);
+ DWriteContext* pDWC_;
};
DWriteContext::DWriteContext() :
- mDpiScaleX(1.f),
- mDpiScaleY(1.f),
+ mHDC(NULL),
mDrawing(false),
+ mFallbackDC(false),
mD2D1Factory(NULL),
mRT(NULL),
mBrush(NULL),
mDWriteFactory(NULL),
+ mDWriteFactory2(NULL),
mGdiInterop(NULL),
mRenderingParams(NULL),
+ mFontCache(8),
mTextFormat(NULL),
- mLastHFont(NULL),
mFontWeight(DWRITE_FONT_WEIGHT_NORMAL),
mFontStyle(DWRITE_FONT_STYLE_NORMAL),
mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
{
HRESULT hr;
- HDC screen = ::GetDC(0);
- mDpiScaleX = ::GetDeviceCaps(screen, LOGPIXELSX) / 96.0f;
- mDpiScaleY = ::GetDeviceCaps(screen, LOGPIXELSY) / 96.0f;
- ::ReleaseDC(0, screen);
-
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory), NULL,
reinterpret_cast<void**>(&mD2D1Factory));
@@ -497,6 +616,15 @@ DWriteContext::DWriteContext() :
if (SUCCEEDED(hr))
{
+ DWriteCreateFactory(
+ DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory2),
+ reinterpret_cast<IUnknown**>(&mDWriteFactory2));
+ _RPT1(_CRT_WARN, "IDWriteFactory2: %s\n", SUCCEEDED(hr) ? "available" : "not available");
+ }
+
+ if (SUCCEEDED(hr))
+ {
hr = mDWriteFactory->GetGdiInterop(&mGdiInterop);
_RPT2(_CRT_WARN, "GetGdiInterop: hr=%p p=%p\n", hr, mGdiInterop);
}
@@ -515,20 +643,24 @@ DWriteContext::~DWriteContext()
SafeRelease(&mRenderingParams);
SafeRelease(&mGdiInterop);
SafeRelease(&mDWriteFactory);
+ SafeRelease(&mDWriteFactory2);
SafeRelease(&mBrush);
SafeRelease(&mRT);
SafeRelease(&mD2D1Factory);
}
HRESULT
-DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize)
+DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
+ IDWriteTextFormat **ppTextFormat)
{
- // Most of this function is copy from: http://msdn.microsoft.com/en-us/library/windows/desktop/dd941783(v=vs.85).aspx
+ // Most of this function is copied from: https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/DirectWrite/RenderTest/TextHelpers.cpp
HRESULT hr = S_OK;
+ IDWriteTextFormat *pTextFormat = NULL;
IDWriteFont *font = NULL;
IDWriteFontFamily *fontFamily = NULL;
IDWriteLocalizedStrings *localizedFamilyNames = NULL;
+ float fontSize = 0;
if (SUCCEEDED(hr))
{
@@ -561,33 +693,30 @@ DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize)
if (SUCCEEDED(hr))
{
- // If no font size was passed in use the lfHeight of the LOGFONT.
- if (fontSize == 0)
+ // Use lfHeight of the LOGFONT as font size.
+ fontSize = float(logFont.lfHeight);
+
+ if (fontSize < 0)
{
- // Convert from pixels to DIPs.
- fontSize = PixelsToDipsY(logFont.lfHeight);
- if (fontSize < 0)
- {
- // Negative lfHeight represents the size of the em unit.
- fontSize = -fontSize;
- }
- else
- {
- // Positive lfHeight represents the cell height (ascent +
- // descent).
- DWRITE_FONT_METRICS fontMetrics;
- font->GetMetrics(&fontMetrics);
-
- // Convert the cell height (ascent + descent) from design units
- // to ems.
- float cellHeight = static_cast<float>(
- fontMetrics.ascent + fontMetrics.descent)
- / fontMetrics.designUnitsPerEm;
-
- // Divide the font size by the cell height to get the font em
- // size.
- fontSize /= cellHeight;
- }
+ // Negative lfHeight represents the size of the em unit.
+ fontSize = -fontSize;
+ }
+ else
+ {
+ // Positive lfHeight represents the cell height (ascent +
+ // descent).
+ DWRITE_FONT_METRICS fontMetrics;
+ font->GetMetrics(&fontMetrics);
+
+ // Convert the cell height (ascent + descent) from design units
+ // to ems.
+ float cellHeight = static_cast<float>(
+ fontMetrics.ascent + fontMetrics.descent)
+ / fontMetrics.designUnitsPerEm;
+
+ // Divide the font size by the cell height to get the font em
+ // size.
+ fontSize /= cellHeight;
}
}
@@ -612,123 +741,165 @@ DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize)
font->GetStretch(),
fontSize,
localeName,
- &mTextFormat);
+ &pTextFormat);
}
if (SUCCEEDED(hr))
+ hr = pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
+
+ if (SUCCEEDED(hr))
+ hr = pTextFormat->SetParagraphAlignment(
+ DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
+
+ if (SUCCEEDED(hr))
+ hr = pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
+
+ SafeRelease(&localizedFamilyNames);
+ SafeRelease(&fontFamily);
+ SafeRelease(&font);
+
+ if (SUCCEEDED(hr))
+ *ppTextFormat = pTextFormat;
+ else
+ SafeRelease(&pTextFormat);
+
+ return hr;
+}
+
+ HRESULT
+DWriteContext::SetFontByLOGFONT(const LOGFONTW &logFont)
+{
+ HRESULT hr = S_OK;
+ IDWriteTextFormat *pTextFormat = NULL;
+
+ hr = CreateTextFormatFromLOGFONT(logFont, &pTextFormat);
+
+ if (SUCCEEDED(hr))
{
+ SafeRelease(&mTextFormat);
+ mTextFormat = pTextFormat;
mFontWeight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight);
mFontStyle = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC
: DWRITE_FONT_STYLE_NORMAL;
}
- SafeRelease(&localizedFamilyNames);
- SafeRelease(&fontFamily);
- SafeRelease(&font);
-
return hr;
}
void
DWriteContext::SetFont(HFONT hFont)
{
- if (mLastHFont != hFont)
+ FontCache::Item item;
+ if (mFontCache.get(hFont, item))
{
- LOGFONTW lf;
- if (GetObjectW(hFont, sizeof(lf), &lf))
+ if (item.pTextFormat != NULL)
{
- SetFont(lf);
- mLastHFont = hFont;
+ item.pTextFormat->AddRef();
+ SafeRelease(&mTextFormat);
+ mTextFormat = item.pTextFormat;
+ mFontWeight = item.fontWeight;
+ mFontStyle = item.fontStyle;
+ mFallbackDC = false;
}
+ else
+ mFallbackDC = true;
+ return;
}
+
+ HRESULT hr = E_FAIL;
+ LOGFONTW lf;
+ if (GetObjectW(hFont, sizeof(lf), &lf))
+ hr = SetFontByLOGFONT(lf);
+
+ item.hFont = hFont;
+ if (SUCCEEDED(hr))
+ {
+ item.pTextFormat = mTextFormat;
+ item.fontWeight = mFontWeight;
+ item.fontStyle = mFontStyle;
+ }
+ mFontCache.put(item);
}
void
-DWriteContext::SetFont(const LOGFONTW &logFont)
+DWriteContext::BindDC(HDC hdc, RECT *rect)
{
- SafeRelease(&mTextFormat);
- mLastHFont = NULL;
-
- HRESULT hr = SetLOGFONT(logFont, 0.f);
-
- if (SUCCEEDED(hr))
- hr = mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
+ Flush();
+ mRT->BindDC(hdc, rect);
+ mRT->SetTransform(D2D1::IdentityMatrix());
+ mHDC = hdc;
+}
- if (SUCCEEDED(hr))
- hr = mTextFormat->SetParagraphAlignment(
- DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
+ void
+DWriteContext::AssureDrawing()
+{
+ if (mDrawing == false)
+ {
+ mRT->BeginDraw();
+ mDrawing = true;
+ }
+}
- if (SUCCEEDED(hr))
- hr = mTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
+ ID2D1Brush*
+DWriteContext::SolidBrush(COLORREF color)
+{
+ mBrush->SetColor(D2D1::ColorF(UINT32(GetRValue(color)) << 16 |
+ UINT32(GetGValue(color)) << 8 | UINT32(GetBValue(color))));
+ return mBrush;
}
void
-DWriteContext::DrawText(HDC hdc, const WCHAR* text, int len,
- int x, int y, int w, int h, int cellWidth, COLORREF color)
+DWriteContext::DrawText(const WCHAR* text, int len,
+ int x, int y, int w, int h, int cellWidth, COLORREF color,
+ UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx)
{
- HRESULT hr = S_OK;
- IDWriteBitmapRenderTarget *bmpRT = NULL;
-
- // Skip when any fonts are not set.
- if (mTextFormat == NULL)
+ if (mFallbackDC)
+ {
+ Flush();
+ ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx);
return;
+ }
- // Check possibility of zero divided error.
- if (cellWidth == 0 || mDpiScaleX == 0.0f || mDpiScaleY == 0.0f)
- return;
+ AssureDrawing();
- if (SUCCEEDED(hr))
- hr = mGdiInterop->CreateBitmapRenderTarget(hdc, w, h, &bmpRT);
+ HRESULT hr;
+ IDWriteTextLayout *textLayout = NULL;
+
+ hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
+ FLOAT(w), FLOAT(h), &textLayout);
if (SUCCEEDED(hr))
{
- IDWriteTextLayout *textLayout = NULL;
-
- HDC memdc = bmpRT->GetMemoryDC();
- BitBlt(memdc, 0, 0, w, h, hdc, x, y, SRCCOPY);
-
- hr = mDWriteFactory->CreateGdiCompatibleTextLayout(
- text, len, mTextFormat, PixelsToDipsX(w),
- PixelsToDipsY(h), mDpiScaleX, NULL, TRUE, &textLayout);
-
- if (SUCCEEDED(hr))
- {
- DWRITE_TEXT_RANGE textRange = { 0, (UINT32)len };
- textLayout->SetFontWeight(mFontWeight, textRange);
- textLayout->SetFontStyle(mFontStyle, textRange);
- }
-
- if (SUCCEEDED(hr))
- {
- GdiTextRenderer *renderer = new GdiTextRenderer(bmpRT,
- mRenderingParams);
- GdiTextRendererContext data = {
- color,
- PixelsToDipsX(cellWidth),
- 0.0f
- };
- textLayout->Draw(&data, renderer, 0, 0);
- SafeRelease(&renderer);
- }
+ DWRITE_TEXT_RANGE textRange = { 0, UINT32(len) };
+ textLayout->SetFontWeight(mFontWeight, textRange);
+ textLayout->SetFontStyle(mFontStyle, textRange);
- BitBlt(hdc, x, y, w, h, memdc, 0, 0, SRCCOPY);
-
- SafeRelease(&textLayout);
+ TextRenderer renderer(this);
+ TextRendererContext context = { color, FLOAT(cellWidth), 0.0f };
+ textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y));
}
- SafeRelease(&bmpRT);
+ SafeRelease(&textLayout);
}
- float
-DWriteContext::PixelsToDipsX(int x)
+ void
+DWriteContext::FillRect(RECT *rc, COLORREF color)
{
- return x / mDpiScaleX;
+ AssureDrawing();
+ mRT->FillRectangle(
+ D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
+ FLOAT(rc->right), FLOAT(rc->bottom)),
+ SolidBrush(color));
}
- float
-DWriteContext::PixelsToDipsY(int y)
+ void
+DWriteContext::Flush()
{
- return y / mDpiScaleY;
+ if (mDrawing)
+ {
+ mRT->EndDraw();
+ mDrawing = false;
+ }
}
void
@@ -757,6 +928,10 @@ DWriteContext::SetRenderingParams(
SafeRelease(&mRenderingParams);
mRenderingParams = renderingParams;
mTextAntialiasMode = textAntialiasMode;
+
+ Flush();
+ mRT->SetTextRenderingParams(mRenderingParams);
+ mRT->SetTextAntialiasMode(mTextAntialiasMode);
}
}
@@ -825,39 +1000,22 @@ DWriteContext_Open(void)
}
void
-DWriteContext_BeginDraw(DWriteContext *ctx)
-{
- if (ctx != NULL && ctx->mRT != NULL)
- {
- ctx->mRT->BeginDraw();
- ctx->mRT->SetTransform(D2D1::IdentityMatrix());
- ctx->mDrawing = true;
- }
-}
-
- void
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect)
{
- if (ctx != NULL && ctx->mRT != NULL)
- {
- ctx->mRT->BindDC(hdc, rect);
- ctx->mRT->SetTextAntialiasMode(ctx->mTextAntialiasMode);
- }
+ if (ctx != NULL)
+ ctx->BindDC(hdc, rect);
}
void
DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont)
{
if (ctx != NULL)
- {
ctx->SetFont(hFont);
- }
}
void
DWriteContext_DrawText(
DWriteContext *ctx,
- HDC hdc,
const WCHAR* text,
int len,
int x,
@@ -865,20 +1023,28 @@ DWriteContext_DrawText(
int w,
int h,
int cellWidth,
- COLORREF color)
+ COLORREF color,
+ UINT fuOptions,
+ CONST RECT *lprc,
+ CONST INT * lpDx)
{
if (ctx != NULL)
- ctx->DrawText(hdc, text, len, x, y, w, h, cellWidth, color);
+ ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
+ fuOptions, lprc, lpDx);
}
void
-DWriteContext_EndDraw(DWriteContext *ctx)
+DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color)
{
- if (ctx != NULL && ctx->mRT != NULL)
- {
- ctx->mRT->EndDraw();
- ctx->mDrawing = false;
- }
+ if (ctx != NULL)
+ ctx->FillRect(rc, color);
+}
+
+ void
+DWriteContext_Flush(DWriteContext *ctx)
+{
+ if (ctx != NULL)
+ ctx->Flush();
}
void