diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-11-26 14:29:32 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-11-26 14:29:32 +0100 |
commit | d7ccc4d81dbcfa3ac0352bacea6e294fc9e33fda (patch) | |
tree | 3f61bdfbadc4f376a8a4bc03dc91eb34958eef37 /src/gui_dwrite.cpp | |
parent | fb1db0e3550355e10ac86c4a4af21209c5456a66 (diff) | |
download | vim-git-d7ccc4d81dbcfa3ac0352bacea6e294fc9e33fda.tar.gz |
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.cpp | 666 |
1 files changed, 416 insertions, 250 deletions
diff --git a/src/gui_dwrite.cpp b/src/gui_dwrite.cpp index 9873c6728..bd76383c5 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 |