1b5a7a8b5SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet: */ 2b5a7a8b5SBram Moolenaar /* 3b5a7a8b5SBram Moolenaar * Author: MURAOKA Taro <[email protected]> 4b5a7a8b5SBram Moolenaar * 5b5a7a8b5SBram Moolenaar * Contributors: 6b5a7a8b5SBram Moolenaar * - Ken Takata 7*d7ccc4d8SBram Moolenaar * - Yasuhiro Matsumoto 8b5a7a8b5SBram Moolenaar * 9b5a7a8b5SBram Moolenaar * Copyright (C) 2013 MURAOKA Taro <[email protected]> 10b5a7a8b5SBram Moolenaar * THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. 11b5a7a8b5SBram Moolenaar */ 12b5a7a8b5SBram Moolenaar 13b5a7a8b5SBram Moolenaar #define WIN32_LEAN_AND_MEAN 14b5a7a8b5SBram Moolenaar 15b5a7a8b5SBram Moolenaar #ifndef DYNAMIC_DIRECTX 16b5a7a8b5SBram Moolenaar # if WINVER < 0x0600 17b5a7a8b5SBram Moolenaar # error WINVER must be 0x0600 or above to use DirectWrite(DirectX) 18b5a7a8b5SBram Moolenaar # endif 19b5a7a8b5SBram Moolenaar #endif 20b5a7a8b5SBram Moolenaar 21b5a7a8b5SBram Moolenaar #include <windows.h> 22b5a7a8b5SBram Moolenaar #include <crtdbg.h> 23b5a7a8b5SBram Moolenaar #include <assert.h> 24b5a7a8b5SBram Moolenaar #include <math.h> 25b5a7a8b5SBram Moolenaar #include <d2d1.h> 26b5a7a8b5SBram Moolenaar #include <d2d1helper.h> 27*d7ccc4d8SBram Moolenaar 28*d7ccc4d8SBram Moolenaar // Disable these macros to compile with old VC and newer SDK (V8.1 or later). 29*d7ccc4d8SBram Moolenaar #if defined(_MSC_VER) && (_MSC_VER < 1700) 30*d7ccc4d8SBram Moolenaar # define _COM_Outptr_ __out 31*d7ccc4d8SBram Moolenaar # define _In_reads_(s) 32*d7ccc4d8SBram Moolenaar # define _In_reads_opt_(s) 33*d7ccc4d8SBram Moolenaar # define _Maybenull_ 34*d7ccc4d8SBram Moolenaar # define _Out_writes_(s) 35*d7ccc4d8SBram Moolenaar # define _Out_writes_opt_(s) 36*d7ccc4d8SBram Moolenaar # define _Out_writes_to_(x, y) 37*d7ccc4d8SBram Moolenaar # define _Out_writes_to_opt_(x, y) 38*d7ccc4d8SBram Moolenaar # define _Outptr_ 39*d7ccc4d8SBram Moolenaar #endif 40*d7ccc4d8SBram Moolenaar 41*d7ccc4d8SBram Moolenaar #include <dwrite_2.h> 42b5a7a8b5SBram Moolenaar 43b5a7a8b5SBram Moolenaar #include "gui_dwrite.h" 44b5a7a8b5SBram Moolenaar 45b5a7a8b5SBram Moolenaar #ifdef __MINGW32__ 46b5a7a8b5SBram Moolenaar # define __maybenull SAL__maybenull 47b5a7a8b5SBram Moolenaar # define __in SAL__in 48b5a7a8b5SBram Moolenaar # define __out SAL__out 49b5a7a8b5SBram Moolenaar #endif 50b5a7a8b5SBram Moolenaar 51cc6cf9b9SBram Moolenaar #if (defined(_MSC_VER) && (_MSC_VER >= 1700)) || (__cplusplus >= 201103L) 52cc6cf9b9SBram Moolenaar # define FINAL final 53cc6cf9b9SBram Moolenaar #else 54cc6cf9b9SBram Moolenaar # define FINAL 55cc6cf9b9SBram Moolenaar #endif 56cc6cf9b9SBram Moolenaar 57b5a7a8b5SBram Moolenaar #ifdef DYNAMIC_DIRECTX 58b5a7a8b5SBram Moolenaar extern "C" HINSTANCE vimLoadLib(char *name); 59b5a7a8b5SBram Moolenaar 60b5a7a8b5SBram Moolenaar typedef int (WINAPI *PGETUSERDEFAULTLOCALENAME)(LPWSTR, int); 61b5a7a8b5SBram Moolenaar typedef HRESULT (WINAPI *PD2D1CREATEFACTORY)(D2D1_FACTORY_TYPE, 62b5a7a8b5SBram Moolenaar REFIID, const D2D1_FACTORY_OPTIONS *, void **); 63b5a7a8b5SBram Moolenaar typedef HRESULT (WINAPI *PDWRITECREATEFACTORY)(DWRITE_FACTORY_TYPE, 64b5a7a8b5SBram Moolenaar REFIID, IUnknown **); 65b5a7a8b5SBram Moolenaar 66b5a7a8b5SBram Moolenaar static HINSTANCE hD2D1DLL = NULL; 67b5a7a8b5SBram Moolenaar static HINSTANCE hDWriteDLL = NULL; 68b5a7a8b5SBram Moolenaar 69b5a7a8b5SBram Moolenaar static PGETUSERDEFAULTLOCALENAME pGetUserDefaultLocaleName = NULL; 70b5a7a8b5SBram Moolenaar static PD2D1CREATEFACTORY pD2D1CreateFactory = NULL; 71b5a7a8b5SBram Moolenaar static PDWRITECREATEFACTORY pDWriteCreateFactory = NULL; 72b5a7a8b5SBram Moolenaar 73b5a7a8b5SBram Moolenaar #define GetUserDefaultLocaleName (*pGetUserDefaultLocaleName) 74b5a7a8b5SBram Moolenaar #define D2D1CreateFactory (*pD2D1CreateFactory) 75b5a7a8b5SBram Moolenaar #define DWriteCreateFactory (*pDWriteCreateFactory) 76b5a7a8b5SBram Moolenaar 77b5a7a8b5SBram Moolenaar static void 78b5a7a8b5SBram Moolenaar unload(HINSTANCE &hinst) 79b5a7a8b5SBram Moolenaar { 80b5a7a8b5SBram Moolenaar if (hinst != NULL) 81b5a7a8b5SBram Moolenaar { 82b5a7a8b5SBram Moolenaar FreeLibrary(hinst); 83b5a7a8b5SBram Moolenaar hinst = NULL; 84b5a7a8b5SBram Moolenaar } 85b5a7a8b5SBram Moolenaar } 86b5a7a8b5SBram Moolenaar #endif // DYNAMIC_DIRECTX 87b5a7a8b5SBram Moolenaar 88b5a7a8b5SBram Moolenaar template <class T> inline void SafeRelease(T **ppT) 89b5a7a8b5SBram Moolenaar { 90b5a7a8b5SBram Moolenaar if (*ppT) 91b5a7a8b5SBram Moolenaar { 92b5a7a8b5SBram Moolenaar (*ppT)->Release(); 93b5a7a8b5SBram Moolenaar *ppT = NULL; 94b5a7a8b5SBram Moolenaar } 95b5a7a8b5SBram Moolenaar } 96b5a7a8b5SBram Moolenaar 97b5a7a8b5SBram Moolenaar static DWRITE_PIXEL_GEOMETRY 98b5a7a8b5SBram Moolenaar ToPixelGeometry(int value) 99b5a7a8b5SBram Moolenaar { 100b5a7a8b5SBram Moolenaar switch (value) 101b5a7a8b5SBram Moolenaar { 102b5a7a8b5SBram Moolenaar default: 103b5a7a8b5SBram Moolenaar case 0: 104b5a7a8b5SBram Moolenaar return DWRITE_PIXEL_GEOMETRY_FLAT; 105b5a7a8b5SBram Moolenaar case 1: 106b5a7a8b5SBram Moolenaar return DWRITE_PIXEL_GEOMETRY_RGB; 107b5a7a8b5SBram Moolenaar case 2: 108b5a7a8b5SBram Moolenaar return DWRITE_PIXEL_GEOMETRY_BGR; 109b5a7a8b5SBram Moolenaar } 110b5a7a8b5SBram Moolenaar } 111b5a7a8b5SBram Moolenaar 112b5a7a8b5SBram Moolenaar static int 113b5a7a8b5SBram Moolenaar ToInt(DWRITE_PIXEL_GEOMETRY value) 114b5a7a8b5SBram Moolenaar { 115b5a7a8b5SBram Moolenaar switch (value) 116b5a7a8b5SBram Moolenaar { 117b5a7a8b5SBram Moolenaar case DWRITE_PIXEL_GEOMETRY_FLAT: 118b5a7a8b5SBram Moolenaar return 0; 119b5a7a8b5SBram Moolenaar case DWRITE_PIXEL_GEOMETRY_RGB: 120b5a7a8b5SBram Moolenaar return 1; 121b5a7a8b5SBram Moolenaar case DWRITE_PIXEL_GEOMETRY_BGR: 122b5a7a8b5SBram Moolenaar return 2; 123b5a7a8b5SBram Moolenaar default: 124b5a7a8b5SBram Moolenaar return -1; 125b5a7a8b5SBram Moolenaar } 126b5a7a8b5SBram Moolenaar } 127b5a7a8b5SBram Moolenaar 128b5a7a8b5SBram Moolenaar static DWRITE_RENDERING_MODE 129b5a7a8b5SBram Moolenaar ToRenderingMode(int value) 130b5a7a8b5SBram Moolenaar { 131b5a7a8b5SBram Moolenaar switch (value) 132b5a7a8b5SBram Moolenaar { 133b5a7a8b5SBram Moolenaar default: 134b5a7a8b5SBram Moolenaar case 0: 135b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_DEFAULT; 136b5a7a8b5SBram Moolenaar case 1: 137b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_ALIASED; 138b5a7a8b5SBram Moolenaar case 2: 139b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC; 140b5a7a8b5SBram Moolenaar case 3: 141b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL; 142b5a7a8b5SBram Moolenaar case 4: 143b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; 144b5a7a8b5SBram Moolenaar case 5: 145b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; 146b5a7a8b5SBram Moolenaar case 6: 147b5a7a8b5SBram Moolenaar return DWRITE_RENDERING_MODE_OUTLINE; 148b5a7a8b5SBram Moolenaar } 149b5a7a8b5SBram Moolenaar } 150b5a7a8b5SBram Moolenaar 151b5a7a8b5SBram Moolenaar static D2D1_TEXT_ANTIALIAS_MODE 152b5a7a8b5SBram Moolenaar ToTextAntialiasMode(int value) 153b5a7a8b5SBram Moolenaar { 154b5a7a8b5SBram Moolenaar switch (value) 155b5a7a8b5SBram Moolenaar { 156b5a7a8b5SBram Moolenaar default: 157b5a7a8b5SBram Moolenaar case 0: 158b5a7a8b5SBram Moolenaar return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; 159b5a7a8b5SBram Moolenaar case 1: 160b5a7a8b5SBram Moolenaar return D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; 161b5a7a8b5SBram Moolenaar case 2: 162b5a7a8b5SBram Moolenaar return D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; 163b5a7a8b5SBram Moolenaar case 3: 164b5a7a8b5SBram Moolenaar return D2D1_TEXT_ANTIALIAS_MODE_ALIASED; 165b5a7a8b5SBram Moolenaar } 166b5a7a8b5SBram Moolenaar } 167b5a7a8b5SBram Moolenaar 168b5a7a8b5SBram Moolenaar static int 169b5a7a8b5SBram Moolenaar ToInt(DWRITE_RENDERING_MODE value) 170b5a7a8b5SBram Moolenaar { 171b5a7a8b5SBram Moolenaar switch (value) 172b5a7a8b5SBram Moolenaar { 173b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_DEFAULT: 174b5a7a8b5SBram Moolenaar return 0; 175b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_ALIASED: 176b5a7a8b5SBram Moolenaar return 1; 177b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC: 178b5a7a8b5SBram Moolenaar return 2; 179b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL: 180b5a7a8b5SBram Moolenaar return 3; 181b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL: 182b5a7a8b5SBram Moolenaar return 4; 183b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC: 184b5a7a8b5SBram Moolenaar return 5; 185b5a7a8b5SBram Moolenaar case DWRITE_RENDERING_MODE_OUTLINE: 186b5a7a8b5SBram Moolenaar return 6; 187b5a7a8b5SBram Moolenaar default: 188b5a7a8b5SBram Moolenaar return -1; 189b5a7a8b5SBram Moolenaar } 190b5a7a8b5SBram Moolenaar } 191b5a7a8b5SBram Moolenaar 192*d7ccc4d8SBram Moolenaar class FontCache { 193*d7ccc4d8SBram Moolenaar public: 194*d7ccc4d8SBram Moolenaar struct Item { 195*d7ccc4d8SBram Moolenaar HFONT hFont; 196*d7ccc4d8SBram Moolenaar IDWriteTextFormat* pTextFormat; 197*d7ccc4d8SBram Moolenaar DWRITE_FONT_WEIGHT fontWeight; 198*d7ccc4d8SBram Moolenaar DWRITE_FONT_STYLE fontStyle; 199*d7ccc4d8SBram Moolenaar Item() : hFont(NULL), pTextFormat(NULL) {} 200*d7ccc4d8SBram Moolenaar }; 201*d7ccc4d8SBram Moolenaar 202*d7ccc4d8SBram Moolenaar private: 203*d7ccc4d8SBram Moolenaar int mSize; 204*d7ccc4d8SBram Moolenaar Item *mItems; 205*d7ccc4d8SBram Moolenaar 206*d7ccc4d8SBram Moolenaar public: 207*d7ccc4d8SBram Moolenaar FontCache(int size = 2) : 208*d7ccc4d8SBram Moolenaar mSize(size), 209*d7ccc4d8SBram Moolenaar mItems(new Item[size]) 210*d7ccc4d8SBram Moolenaar { 211*d7ccc4d8SBram Moolenaar } 212*d7ccc4d8SBram Moolenaar 213*d7ccc4d8SBram Moolenaar ~FontCache() 214*d7ccc4d8SBram Moolenaar { 215*d7ccc4d8SBram Moolenaar for (int i = 0; i < mSize; ++i) 216*d7ccc4d8SBram Moolenaar SafeRelease(&mItems[i].pTextFormat); 217*d7ccc4d8SBram Moolenaar delete[] mItems; 218*d7ccc4d8SBram Moolenaar } 219*d7ccc4d8SBram Moolenaar 220*d7ccc4d8SBram Moolenaar bool get(HFONT hFont, Item &item) 221*d7ccc4d8SBram Moolenaar { 222*d7ccc4d8SBram Moolenaar int n = find(hFont); 223*d7ccc4d8SBram Moolenaar if (n < 0) 224*d7ccc4d8SBram Moolenaar return false; 225*d7ccc4d8SBram Moolenaar item = mItems[n]; 226*d7ccc4d8SBram Moolenaar slide(n); 227*d7ccc4d8SBram Moolenaar return true; 228*d7ccc4d8SBram Moolenaar } 229*d7ccc4d8SBram Moolenaar 230*d7ccc4d8SBram Moolenaar void put(const Item& item) 231*d7ccc4d8SBram Moolenaar { 232*d7ccc4d8SBram Moolenaar int n = find(item.hFont); 233*d7ccc4d8SBram Moolenaar if (n < 0) 234*d7ccc4d8SBram Moolenaar n = mSize - 1; 235*d7ccc4d8SBram Moolenaar if (mItems[n].pTextFormat != item.pTextFormat) 236*d7ccc4d8SBram Moolenaar { 237*d7ccc4d8SBram Moolenaar SafeRelease(&mItems[n].pTextFormat); 238*d7ccc4d8SBram Moolenaar item.pTextFormat->AddRef(); 239*d7ccc4d8SBram Moolenaar } 240*d7ccc4d8SBram Moolenaar mItems[n] = item; 241*d7ccc4d8SBram Moolenaar slide(n); 242*d7ccc4d8SBram Moolenaar } 243*d7ccc4d8SBram Moolenaar 244*d7ccc4d8SBram Moolenaar private: 245*d7ccc4d8SBram Moolenaar int find(HFONT hFont) 246*d7ccc4d8SBram Moolenaar { 247*d7ccc4d8SBram Moolenaar for (int i = 0; i < mSize; ++i) 248*d7ccc4d8SBram Moolenaar { 249*d7ccc4d8SBram Moolenaar if (mItems[i].hFont == hFont) 250*d7ccc4d8SBram Moolenaar return i; 251*d7ccc4d8SBram Moolenaar } 252*d7ccc4d8SBram Moolenaar return -1; 253*d7ccc4d8SBram Moolenaar } 254*d7ccc4d8SBram Moolenaar 255*d7ccc4d8SBram Moolenaar void slide(int nextTop) 256*d7ccc4d8SBram Moolenaar { 257*d7ccc4d8SBram Moolenaar if (nextTop == 0) 258*d7ccc4d8SBram Moolenaar return; 259*d7ccc4d8SBram Moolenaar Item tmp = mItems[nextTop]; 260*d7ccc4d8SBram Moolenaar for (int i = nextTop - 1; i >= 0; --i) 261*d7ccc4d8SBram Moolenaar mItems[i + 1] = mItems[i]; 262*d7ccc4d8SBram Moolenaar mItems[0] = tmp; 263*d7ccc4d8SBram Moolenaar } 264*d7ccc4d8SBram Moolenaar }; 265*d7ccc4d8SBram Moolenaar 266*d7ccc4d8SBram Moolenaar struct DWriteContext { 267*d7ccc4d8SBram Moolenaar HDC mHDC; 268*d7ccc4d8SBram Moolenaar bool mDrawing; 269*d7ccc4d8SBram Moolenaar bool mFallbackDC; 270*d7ccc4d8SBram Moolenaar 271*d7ccc4d8SBram Moolenaar ID2D1Factory *mD2D1Factory; 272*d7ccc4d8SBram Moolenaar 273*d7ccc4d8SBram Moolenaar ID2D1DCRenderTarget *mRT; 274*d7ccc4d8SBram Moolenaar ID2D1SolidColorBrush *mBrush; 275*d7ccc4d8SBram Moolenaar 276*d7ccc4d8SBram Moolenaar IDWriteFactory *mDWriteFactory; 277*d7ccc4d8SBram Moolenaar IDWriteFactory2 *mDWriteFactory2; 278*d7ccc4d8SBram Moolenaar 279*d7ccc4d8SBram Moolenaar IDWriteGdiInterop *mGdiInterop; 280*d7ccc4d8SBram Moolenaar IDWriteRenderingParams *mRenderingParams; 281*d7ccc4d8SBram Moolenaar 282*d7ccc4d8SBram Moolenaar FontCache mFontCache; 283*d7ccc4d8SBram Moolenaar IDWriteTextFormat *mTextFormat; 284*d7ccc4d8SBram Moolenaar DWRITE_FONT_WEIGHT mFontWeight; 285*d7ccc4d8SBram Moolenaar DWRITE_FONT_STYLE mFontStyle; 286*d7ccc4d8SBram Moolenaar 287*d7ccc4d8SBram Moolenaar D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode; 288*d7ccc4d8SBram Moolenaar 289*d7ccc4d8SBram Moolenaar // METHODS 290*d7ccc4d8SBram Moolenaar 291*d7ccc4d8SBram Moolenaar DWriteContext(); 292*d7ccc4d8SBram Moolenaar 293*d7ccc4d8SBram Moolenaar virtual ~DWriteContext(); 294*d7ccc4d8SBram Moolenaar 295*d7ccc4d8SBram Moolenaar HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, 296*d7ccc4d8SBram Moolenaar IDWriteTextFormat **ppTextFormat); 297*d7ccc4d8SBram Moolenaar 298*d7ccc4d8SBram Moolenaar HRESULT SetFontByLOGFONT(const LOGFONTW &logFont); 299*d7ccc4d8SBram Moolenaar 300*d7ccc4d8SBram Moolenaar void SetFont(HFONT hFont); 301*d7ccc4d8SBram Moolenaar 302*d7ccc4d8SBram Moolenaar void BindDC(HDC hdc, RECT *rect); 303*d7ccc4d8SBram Moolenaar 304*d7ccc4d8SBram Moolenaar void AssureDrawing(); 305*d7ccc4d8SBram Moolenaar 306*d7ccc4d8SBram Moolenaar ID2D1Brush* SolidBrush(COLORREF color); 307*d7ccc4d8SBram Moolenaar 308*d7ccc4d8SBram Moolenaar void DrawText(const WCHAR* text, int len, 309*d7ccc4d8SBram Moolenaar int x, int y, int w, int h, int cellWidth, COLORREF color, 310*d7ccc4d8SBram Moolenaar UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx); 311*d7ccc4d8SBram Moolenaar 312*d7ccc4d8SBram Moolenaar void FillRect(RECT *rc, COLORREF color); 313*d7ccc4d8SBram Moolenaar 314*d7ccc4d8SBram Moolenaar void Flush(); 315*d7ccc4d8SBram Moolenaar 316*d7ccc4d8SBram Moolenaar void SetRenderingParams( 317*d7ccc4d8SBram Moolenaar const DWriteRenderingParams *params); 318*d7ccc4d8SBram Moolenaar 319*d7ccc4d8SBram Moolenaar DWriteRenderingParams *GetRenderingParams( 320*d7ccc4d8SBram Moolenaar DWriteRenderingParams *params); 321*d7ccc4d8SBram Moolenaar }; 322*d7ccc4d8SBram Moolenaar 323b5a7a8b5SBram Moolenaar class AdjustedGlyphRun : public DWRITE_GLYPH_RUN 324b5a7a8b5SBram Moolenaar { 325b5a7a8b5SBram Moolenaar private: 326*d7ccc4d8SBram Moolenaar FLOAT &mAccum; 327b5a7a8b5SBram Moolenaar FLOAT mDelta; 328b5a7a8b5SBram Moolenaar FLOAT *mAdjustedAdvances; 329b5a7a8b5SBram Moolenaar 330b5a7a8b5SBram Moolenaar public: 331b5a7a8b5SBram Moolenaar AdjustedGlyphRun( 332b5a7a8b5SBram Moolenaar const DWRITE_GLYPH_RUN *glyphRun, 333*d7ccc4d8SBram Moolenaar FLOAT cellWidth, 334*d7ccc4d8SBram Moolenaar FLOAT &accum) : 335b5a7a8b5SBram Moolenaar DWRITE_GLYPH_RUN(*glyphRun), 336*d7ccc4d8SBram Moolenaar mAccum(accum), 337b5a7a8b5SBram Moolenaar mDelta(0.0f), 338b5a7a8b5SBram Moolenaar mAdjustedAdvances(new FLOAT[glyphRun->glyphCount]) 339b5a7a8b5SBram Moolenaar { 340b5a7a8b5SBram Moolenaar assert(cellWidth != 0.0f); 341b5a7a8b5SBram Moolenaar for (UINT32 i = 0; i < glyphRun->glyphCount; ++i) 342b5a7a8b5SBram Moolenaar { 343b5a7a8b5SBram Moolenaar FLOAT orig = glyphRun->glyphAdvances[i]; 344b5a7a8b5SBram Moolenaar FLOAT adjusted = adjustToCell(orig, cellWidth); 345b5a7a8b5SBram Moolenaar mAdjustedAdvances[i] = adjusted; 346b5a7a8b5SBram Moolenaar mDelta += adjusted - orig; 347b5a7a8b5SBram Moolenaar } 348b5a7a8b5SBram Moolenaar glyphAdvances = mAdjustedAdvances; 349b5a7a8b5SBram Moolenaar } 350b5a7a8b5SBram Moolenaar 351*d7ccc4d8SBram Moolenaar ~AdjustedGlyphRun() 352b5a7a8b5SBram Moolenaar { 353*d7ccc4d8SBram Moolenaar mAccum += mDelta; 354b5a7a8b5SBram Moolenaar delete[] mAdjustedAdvances; 355b5a7a8b5SBram Moolenaar } 356b5a7a8b5SBram Moolenaar 357b5a7a8b5SBram Moolenaar static FLOAT adjustToCell(FLOAT value, FLOAT cellWidth) 358b5a7a8b5SBram Moolenaar { 359*d7ccc4d8SBram Moolenaar int cellCount = int(floor(value / cellWidth + 0.5f)); 360b5a7a8b5SBram Moolenaar if (cellCount < 1) 361b5a7a8b5SBram Moolenaar cellCount = 1; 362b5a7a8b5SBram Moolenaar return cellCount * cellWidth; 363b5a7a8b5SBram Moolenaar } 364b5a7a8b5SBram Moolenaar }; 365b5a7a8b5SBram Moolenaar 366*d7ccc4d8SBram Moolenaar struct TextRendererContext { 367*d7ccc4d8SBram Moolenaar // const fields. 368*d7ccc4d8SBram Moolenaar COLORREF color; 369*d7ccc4d8SBram Moolenaar FLOAT cellWidth; 370*d7ccc4d8SBram Moolenaar 371*d7ccc4d8SBram Moolenaar // working fields. 372*d7ccc4d8SBram Moolenaar FLOAT offsetX; 373*d7ccc4d8SBram Moolenaar }; 374*d7ccc4d8SBram Moolenaar 375*d7ccc4d8SBram Moolenaar class TextRenderer FINAL : public IDWriteTextRenderer 376b5a7a8b5SBram Moolenaar { 377b5a7a8b5SBram Moolenaar public: 378*d7ccc4d8SBram Moolenaar TextRenderer( 379*d7ccc4d8SBram Moolenaar DWriteContext* pDWC) : 380b5a7a8b5SBram Moolenaar cRefCount_(0), 381*d7ccc4d8SBram Moolenaar pDWC_(pDWC) 382b5a7a8b5SBram Moolenaar { 383b5a7a8b5SBram Moolenaar AddRef(); 384b5a7a8b5SBram Moolenaar } 385b5a7a8b5SBram Moolenaar 386edb4f2b3SBram Moolenaar // add "virtual" to avoid a compiler warning 387*d7ccc4d8SBram Moolenaar virtual ~TextRenderer() 388b5a7a8b5SBram Moolenaar { 389b5a7a8b5SBram Moolenaar } 390b5a7a8b5SBram Moolenaar 391b5a7a8b5SBram Moolenaar IFACEMETHOD(IsPixelSnappingDisabled)( 392b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 393b5a7a8b5SBram Moolenaar __out BOOL* isDisabled) 394b5a7a8b5SBram Moolenaar { 395b5a7a8b5SBram Moolenaar *isDisabled = FALSE; 396b5a7a8b5SBram Moolenaar return S_OK; 397b5a7a8b5SBram Moolenaar } 398b5a7a8b5SBram Moolenaar 399b5a7a8b5SBram Moolenaar IFACEMETHOD(GetCurrentTransform)( 400b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 401b5a7a8b5SBram Moolenaar __out DWRITE_MATRIX* transform) 402b5a7a8b5SBram Moolenaar { 403b5a7a8b5SBram Moolenaar // forward the render target's transform 404*d7ccc4d8SBram Moolenaar pDWC_->mRT->GetTransform( 405*d7ccc4d8SBram Moolenaar reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform)); 406b5a7a8b5SBram Moolenaar return S_OK; 407b5a7a8b5SBram Moolenaar } 408b5a7a8b5SBram Moolenaar 409b5a7a8b5SBram Moolenaar IFACEMETHOD(GetPixelsPerDip)( 410b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 411b5a7a8b5SBram Moolenaar __out FLOAT* pixelsPerDip) 412b5a7a8b5SBram Moolenaar { 413*d7ccc4d8SBram Moolenaar float dpiX, unused; 414*d7ccc4d8SBram Moolenaar pDWC_->mRT->GetDpi(&dpiX, &unused); 415*d7ccc4d8SBram Moolenaar *pixelsPerDip = dpiX / 96.0f; 416b5a7a8b5SBram Moolenaar return S_OK; 417b5a7a8b5SBram Moolenaar } 418b5a7a8b5SBram Moolenaar 419b5a7a8b5SBram Moolenaar IFACEMETHOD(DrawUnderline)( 420b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 421b5a7a8b5SBram Moolenaar FLOAT baselineOriginX, 422b5a7a8b5SBram Moolenaar FLOAT baselineOriginY, 423b5a7a8b5SBram Moolenaar __in DWRITE_UNDERLINE const* underline, 424b5a7a8b5SBram Moolenaar IUnknown* clientDrawingEffect) 425b5a7a8b5SBram Moolenaar { 426b5a7a8b5SBram Moolenaar return E_NOTIMPL; 427b5a7a8b5SBram Moolenaar } 428b5a7a8b5SBram Moolenaar 429b5a7a8b5SBram Moolenaar IFACEMETHOD(DrawStrikethrough)( 430b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 431b5a7a8b5SBram Moolenaar FLOAT baselineOriginX, 432b5a7a8b5SBram Moolenaar FLOAT baselineOriginY, 433b5a7a8b5SBram Moolenaar __in DWRITE_STRIKETHROUGH const* strikethrough, 434b5a7a8b5SBram Moolenaar IUnknown* clientDrawingEffect) 435b5a7a8b5SBram Moolenaar { 436b5a7a8b5SBram Moolenaar return E_NOTIMPL; 437b5a7a8b5SBram Moolenaar } 438b5a7a8b5SBram Moolenaar 439b5a7a8b5SBram Moolenaar IFACEMETHOD(DrawInlineObject)( 440b5a7a8b5SBram Moolenaar __maybenull void* clientDrawingContext, 441b5a7a8b5SBram Moolenaar FLOAT originX, 442b5a7a8b5SBram Moolenaar FLOAT originY, 443b5a7a8b5SBram Moolenaar IDWriteInlineObject* inlineObject, 444b5a7a8b5SBram Moolenaar BOOL isSideways, 445b5a7a8b5SBram Moolenaar BOOL isRightToLeft, 446b5a7a8b5SBram Moolenaar IUnknown* clientDrawingEffect) 447b5a7a8b5SBram Moolenaar { 448b5a7a8b5SBram Moolenaar return E_NOTIMPL; 449b5a7a8b5SBram Moolenaar } 450b5a7a8b5SBram Moolenaar 451*d7ccc4d8SBram Moolenaar IFACEMETHOD(DrawGlyphRun)( 452*d7ccc4d8SBram Moolenaar __maybenull void* clientDrawingContext, 453*d7ccc4d8SBram Moolenaar FLOAT baselineOriginX, 454*d7ccc4d8SBram Moolenaar FLOAT baselineOriginY, 455*d7ccc4d8SBram Moolenaar DWRITE_MEASURING_MODE measuringMode, 456*d7ccc4d8SBram Moolenaar __in DWRITE_GLYPH_RUN const* glyphRun, 457*d7ccc4d8SBram Moolenaar __in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 458*d7ccc4d8SBram Moolenaar IUnknown* clientDrawingEffect) 459*d7ccc4d8SBram Moolenaar { 460*d7ccc4d8SBram Moolenaar TextRendererContext *context = 461*d7ccc4d8SBram Moolenaar reinterpret_cast<TextRendererContext*>(clientDrawingContext); 462*d7ccc4d8SBram Moolenaar 463*d7ccc4d8SBram Moolenaar AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth, 464*d7ccc4d8SBram Moolenaar context->offsetX); 465*d7ccc4d8SBram Moolenaar 466*d7ccc4d8SBram Moolenaar if (pDWC_->mDWriteFactory2 != NULL) 467*d7ccc4d8SBram Moolenaar { 468*d7ccc4d8SBram Moolenaar IDWriteColorGlyphRunEnumerator *enumerator = NULL; 469*d7ccc4d8SBram Moolenaar HRESULT hr = pDWC_->mDWriteFactory2->TranslateColorGlyphRun( 470*d7ccc4d8SBram Moolenaar baselineOriginX + context->offsetX, 471*d7ccc4d8SBram Moolenaar baselineOriginY, 472*d7ccc4d8SBram Moolenaar &adjustedGlyphRun, 473*d7ccc4d8SBram Moolenaar NULL, 474*d7ccc4d8SBram Moolenaar DWRITE_MEASURING_MODE_GDI_NATURAL, 475*d7ccc4d8SBram Moolenaar NULL, 476*d7ccc4d8SBram Moolenaar 0, 477*d7ccc4d8SBram Moolenaar &enumerator); 478*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 479*d7ccc4d8SBram Moolenaar { 480*d7ccc4d8SBram Moolenaar // Draw by IDWriteFactory2 for color emoji 481*d7ccc4d8SBram Moolenaar BOOL hasRun = TRUE; 482*d7ccc4d8SBram Moolenaar enumerator->MoveNext(&hasRun); 483*d7ccc4d8SBram Moolenaar while (hasRun) 484*d7ccc4d8SBram Moolenaar { 485*d7ccc4d8SBram Moolenaar const DWRITE_COLOR_GLYPH_RUN* colorGlyphRun; 486*d7ccc4d8SBram Moolenaar enumerator->GetCurrentRun(&colorGlyphRun); 487*d7ccc4d8SBram Moolenaar 488*d7ccc4d8SBram Moolenaar pDWC_->mBrush->SetColor(colorGlyphRun->runColor); 489*d7ccc4d8SBram Moolenaar pDWC_->mRT->DrawGlyphRun( 490*d7ccc4d8SBram Moolenaar D2D1::Point2F( 491*d7ccc4d8SBram Moolenaar colorGlyphRun->baselineOriginX, 492*d7ccc4d8SBram Moolenaar colorGlyphRun->baselineOriginY), 493*d7ccc4d8SBram Moolenaar &colorGlyphRun->glyphRun, 494*d7ccc4d8SBram Moolenaar pDWC_->mBrush, 495*d7ccc4d8SBram Moolenaar DWRITE_MEASURING_MODE_NATURAL); 496*d7ccc4d8SBram Moolenaar enumerator->MoveNext(&hasRun); 497*d7ccc4d8SBram Moolenaar } 498*d7ccc4d8SBram Moolenaar SafeRelease(&enumerator); 499*d7ccc4d8SBram Moolenaar return S_OK; 500*d7ccc4d8SBram Moolenaar } 501*d7ccc4d8SBram Moolenaar } 502*d7ccc4d8SBram Moolenaar 503*d7ccc4d8SBram Moolenaar // Draw by IDWriteFactory (without color emoji) 504*d7ccc4d8SBram Moolenaar pDWC_->mRT->DrawGlyphRun( 505*d7ccc4d8SBram Moolenaar D2D1::Point2F( 506*d7ccc4d8SBram Moolenaar baselineOriginX + context->offsetX, 507*d7ccc4d8SBram Moolenaar baselineOriginY), 508*d7ccc4d8SBram Moolenaar &adjustedGlyphRun, 509*d7ccc4d8SBram Moolenaar pDWC_->SolidBrush(context->color), 510*d7ccc4d8SBram Moolenaar DWRITE_MEASURING_MODE_NATURAL); 511*d7ccc4d8SBram Moolenaar return S_OK; 512*d7ccc4d8SBram Moolenaar } 513*d7ccc4d8SBram Moolenaar 514b5a7a8b5SBram Moolenaar public: 515b5a7a8b5SBram Moolenaar IFACEMETHOD_(unsigned long, AddRef) () 516b5a7a8b5SBram Moolenaar { 517b5a7a8b5SBram Moolenaar return InterlockedIncrement(&cRefCount_); 518b5a7a8b5SBram Moolenaar } 519b5a7a8b5SBram Moolenaar 520b5a7a8b5SBram Moolenaar IFACEMETHOD_(unsigned long, Release) () 521b5a7a8b5SBram Moolenaar { 522b5a7a8b5SBram Moolenaar long newCount = InterlockedDecrement(&cRefCount_); 523b5a7a8b5SBram Moolenaar 524b5a7a8b5SBram Moolenaar if (newCount == 0) 525b5a7a8b5SBram Moolenaar { 526b5a7a8b5SBram Moolenaar delete this; 527b5a7a8b5SBram Moolenaar return 0; 528b5a7a8b5SBram Moolenaar } 529b5a7a8b5SBram Moolenaar return newCount; 530b5a7a8b5SBram Moolenaar } 531b5a7a8b5SBram Moolenaar 532b5a7a8b5SBram Moolenaar IFACEMETHOD(QueryInterface)( 533b5a7a8b5SBram Moolenaar IID const& riid, 534b5a7a8b5SBram Moolenaar void** ppvObject) 535b5a7a8b5SBram Moolenaar { 536b5a7a8b5SBram Moolenaar if (__uuidof(IDWriteTextRenderer) == riid) 537b5a7a8b5SBram Moolenaar { 538b5a7a8b5SBram Moolenaar *ppvObject = this; 539b5a7a8b5SBram Moolenaar } 540b5a7a8b5SBram Moolenaar else if (__uuidof(IDWritePixelSnapping) == riid) 541b5a7a8b5SBram Moolenaar { 542b5a7a8b5SBram Moolenaar *ppvObject = this; 543b5a7a8b5SBram Moolenaar } 544b5a7a8b5SBram Moolenaar else if (__uuidof(IUnknown) == riid) 545b5a7a8b5SBram Moolenaar { 546b5a7a8b5SBram Moolenaar *ppvObject = this; 547b5a7a8b5SBram Moolenaar } 548b5a7a8b5SBram Moolenaar else 549b5a7a8b5SBram Moolenaar { 550b5a7a8b5SBram Moolenaar *ppvObject = NULL; 551b5a7a8b5SBram Moolenaar return E_FAIL; 552b5a7a8b5SBram Moolenaar } 553b5a7a8b5SBram Moolenaar 554b5a7a8b5SBram Moolenaar return S_OK; 555b5a7a8b5SBram Moolenaar } 556b5a7a8b5SBram Moolenaar 557b5a7a8b5SBram Moolenaar private: 5580106b4b8SBram Moolenaar long cRefCount_; 559*d7ccc4d8SBram Moolenaar DWriteContext* pDWC_; 560b5a7a8b5SBram Moolenaar }; 561b5a7a8b5SBram Moolenaar 562b5a7a8b5SBram Moolenaar DWriteContext::DWriteContext() : 563*d7ccc4d8SBram Moolenaar mHDC(NULL), 564b5a7a8b5SBram Moolenaar mDrawing(false), 565*d7ccc4d8SBram Moolenaar mFallbackDC(false), 566b5a7a8b5SBram Moolenaar mD2D1Factory(NULL), 567b5a7a8b5SBram Moolenaar mRT(NULL), 568b5a7a8b5SBram Moolenaar mBrush(NULL), 569b5a7a8b5SBram Moolenaar mDWriteFactory(NULL), 570*d7ccc4d8SBram Moolenaar mDWriteFactory2(NULL), 571b5a7a8b5SBram Moolenaar mGdiInterop(NULL), 572b5a7a8b5SBram Moolenaar mRenderingParams(NULL), 573*d7ccc4d8SBram Moolenaar mFontCache(8), 574b5a7a8b5SBram Moolenaar mTextFormat(NULL), 575b5a7a8b5SBram Moolenaar mFontWeight(DWRITE_FONT_WEIGHT_NORMAL), 576b5a7a8b5SBram Moolenaar mFontStyle(DWRITE_FONT_STYLE_NORMAL), 577b5a7a8b5SBram Moolenaar mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT) 578b5a7a8b5SBram Moolenaar { 579b5a7a8b5SBram Moolenaar HRESULT hr; 580b5a7a8b5SBram Moolenaar 581b5a7a8b5SBram Moolenaar hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, 582b5a7a8b5SBram Moolenaar __uuidof(ID2D1Factory), NULL, 583b5a7a8b5SBram Moolenaar reinterpret_cast<void**>(&mD2D1Factory)); 584b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); 585b5a7a8b5SBram Moolenaar 586b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 587b5a7a8b5SBram Moolenaar { 588b5a7a8b5SBram Moolenaar D2D1_RENDER_TARGET_PROPERTIES props = { 589b5a7a8b5SBram Moolenaar D2D1_RENDER_TARGET_TYPE_DEFAULT, 590b5a7a8b5SBram Moolenaar { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, 591b5a7a8b5SBram Moolenaar 0, 0, 592b5a7a8b5SBram Moolenaar D2D1_RENDER_TARGET_USAGE_NONE, 593b5a7a8b5SBram Moolenaar D2D1_FEATURE_LEVEL_DEFAULT 594b5a7a8b5SBram Moolenaar }; 595b5a7a8b5SBram Moolenaar hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT); 596b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT); 597b5a7a8b5SBram Moolenaar } 598b5a7a8b5SBram Moolenaar 599b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 600b5a7a8b5SBram Moolenaar { 601b5a7a8b5SBram Moolenaar hr = mRT->CreateSolidColorBrush( 602b5a7a8b5SBram Moolenaar D2D1::ColorF(D2D1::ColorF::Black), 603b5a7a8b5SBram Moolenaar &mBrush); 604b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush); 605b5a7a8b5SBram Moolenaar } 606b5a7a8b5SBram Moolenaar 607b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 608b5a7a8b5SBram Moolenaar { 609b5a7a8b5SBram Moolenaar hr = DWriteCreateFactory( 610b5a7a8b5SBram Moolenaar DWRITE_FACTORY_TYPE_SHARED, 611b5a7a8b5SBram Moolenaar __uuidof(IDWriteFactory), 612b5a7a8b5SBram Moolenaar reinterpret_cast<IUnknown**>(&mDWriteFactory)); 613b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "DWriteCreateFactory: hr=%p p=%p\n", hr, 614b5a7a8b5SBram Moolenaar mDWriteFactory); 615b5a7a8b5SBram Moolenaar } 616b5a7a8b5SBram Moolenaar 617b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 618b5a7a8b5SBram Moolenaar { 619*d7ccc4d8SBram Moolenaar DWriteCreateFactory( 620*d7ccc4d8SBram Moolenaar DWRITE_FACTORY_TYPE_SHARED, 621*d7ccc4d8SBram Moolenaar __uuidof(IDWriteFactory2), 622*d7ccc4d8SBram Moolenaar reinterpret_cast<IUnknown**>(&mDWriteFactory2)); 623*d7ccc4d8SBram Moolenaar _RPT1(_CRT_WARN, "IDWriteFactory2: %s\n", SUCCEEDED(hr) ? "available" : "not available"); 624*d7ccc4d8SBram Moolenaar } 625*d7ccc4d8SBram Moolenaar 626*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 627*d7ccc4d8SBram Moolenaar { 628b5a7a8b5SBram Moolenaar hr = mDWriteFactory->GetGdiInterop(&mGdiInterop); 629b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "GetGdiInterop: hr=%p p=%p\n", hr, mGdiInterop); 630b5a7a8b5SBram Moolenaar } 631b5a7a8b5SBram Moolenaar 632b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 633b5a7a8b5SBram Moolenaar { 634b5a7a8b5SBram Moolenaar hr = mDWriteFactory->CreateRenderingParams(&mRenderingParams); 635b5a7a8b5SBram Moolenaar _RPT2(_CRT_WARN, "CreateRenderingParams: hr=%p p=%p\n", hr, 636b5a7a8b5SBram Moolenaar mRenderingParams); 637b5a7a8b5SBram Moolenaar } 638b5a7a8b5SBram Moolenaar } 639b5a7a8b5SBram Moolenaar 640b5a7a8b5SBram Moolenaar DWriteContext::~DWriteContext() 641b5a7a8b5SBram Moolenaar { 642b5a7a8b5SBram Moolenaar SafeRelease(&mTextFormat); 643b5a7a8b5SBram Moolenaar SafeRelease(&mRenderingParams); 644b5a7a8b5SBram Moolenaar SafeRelease(&mGdiInterop); 645b5a7a8b5SBram Moolenaar SafeRelease(&mDWriteFactory); 646*d7ccc4d8SBram Moolenaar SafeRelease(&mDWriteFactory2); 647b5a7a8b5SBram Moolenaar SafeRelease(&mBrush); 648b5a7a8b5SBram Moolenaar SafeRelease(&mRT); 649b5a7a8b5SBram Moolenaar SafeRelease(&mD2D1Factory); 650b5a7a8b5SBram Moolenaar } 651b5a7a8b5SBram Moolenaar 652b5a7a8b5SBram Moolenaar HRESULT 653*d7ccc4d8SBram Moolenaar DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, 654*d7ccc4d8SBram Moolenaar IDWriteTextFormat **ppTextFormat) 655b5a7a8b5SBram Moolenaar { 656*d7ccc4d8SBram Moolenaar // Most of this function is copied from: https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/DirectWrite/RenderTest/TextHelpers.cpp 657b5a7a8b5SBram Moolenaar HRESULT hr = S_OK; 658*d7ccc4d8SBram Moolenaar IDWriteTextFormat *pTextFormat = NULL; 659b5a7a8b5SBram Moolenaar 660b5a7a8b5SBram Moolenaar IDWriteFont *font = NULL; 661b5a7a8b5SBram Moolenaar IDWriteFontFamily *fontFamily = NULL; 662b5a7a8b5SBram Moolenaar IDWriteLocalizedStrings *localizedFamilyNames = NULL; 663*d7ccc4d8SBram Moolenaar float fontSize = 0; 664b5a7a8b5SBram Moolenaar 665b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 666b5a7a8b5SBram Moolenaar { 667b5a7a8b5SBram Moolenaar hr = mGdiInterop->CreateFontFromLOGFONT(&logFont, &font); 668b5a7a8b5SBram Moolenaar } 669b5a7a8b5SBram Moolenaar 670b5a7a8b5SBram Moolenaar // Get the font family to which this font belongs. 671b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 672b5a7a8b5SBram Moolenaar { 673b5a7a8b5SBram Moolenaar hr = font->GetFontFamily(&fontFamily); 674b5a7a8b5SBram Moolenaar } 675b5a7a8b5SBram Moolenaar 676b5a7a8b5SBram Moolenaar // Get the family names. This returns an object that encapsulates one or 677b5a7a8b5SBram Moolenaar // more names with the same meaning but in different languages. 678b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 679b5a7a8b5SBram Moolenaar { 680b5a7a8b5SBram Moolenaar hr = fontFamily->GetFamilyNames(&localizedFamilyNames); 681b5a7a8b5SBram Moolenaar } 682b5a7a8b5SBram Moolenaar 683b5a7a8b5SBram Moolenaar // Get the family name at index zero. If we were going to display the name 684b5a7a8b5SBram Moolenaar // we'd want to try to find one that matched the use locale, but for 685b5a7a8b5SBram Moolenaar // purposes of creating a text format object any language will do. 686b5a7a8b5SBram Moolenaar 687b5a7a8b5SBram Moolenaar wchar_t familyName[100]; 688b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 689b5a7a8b5SBram Moolenaar { 690b5a7a8b5SBram Moolenaar hr = localizedFamilyNames->GetString(0, familyName, 691b5a7a8b5SBram Moolenaar ARRAYSIZE(familyName)); 692b5a7a8b5SBram Moolenaar } 693b5a7a8b5SBram Moolenaar 694b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 695b5a7a8b5SBram Moolenaar { 696*d7ccc4d8SBram Moolenaar // Use lfHeight of the LOGFONT as font size. 697*d7ccc4d8SBram Moolenaar fontSize = float(logFont.lfHeight); 698*d7ccc4d8SBram Moolenaar 699b5a7a8b5SBram Moolenaar if (fontSize < 0) 700b5a7a8b5SBram Moolenaar { 701b5a7a8b5SBram Moolenaar // Negative lfHeight represents the size of the em unit. 702b5a7a8b5SBram Moolenaar fontSize = -fontSize; 703b5a7a8b5SBram Moolenaar } 704b5a7a8b5SBram Moolenaar else 705b5a7a8b5SBram Moolenaar { 706b5a7a8b5SBram Moolenaar // Positive lfHeight represents the cell height (ascent + 707b5a7a8b5SBram Moolenaar // descent). 708b5a7a8b5SBram Moolenaar DWRITE_FONT_METRICS fontMetrics; 709b5a7a8b5SBram Moolenaar font->GetMetrics(&fontMetrics); 710b5a7a8b5SBram Moolenaar 711b5a7a8b5SBram Moolenaar // Convert the cell height (ascent + descent) from design units 712b5a7a8b5SBram Moolenaar // to ems. 713b5a7a8b5SBram Moolenaar float cellHeight = static_cast<float>( 714b5a7a8b5SBram Moolenaar fontMetrics.ascent + fontMetrics.descent) 715b5a7a8b5SBram Moolenaar / fontMetrics.designUnitsPerEm; 716b5a7a8b5SBram Moolenaar 717b5a7a8b5SBram Moolenaar // Divide the font size by the cell height to get the font em 718b5a7a8b5SBram Moolenaar // size. 719b5a7a8b5SBram Moolenaar fontSize /= cellHeight; 720b5a7a8b5SBram Moolenaar } 721b5a7a8b5SBram Moolenaar } 722b5a7a8b5SBram Moolenaar 723b5a7a8b5SBram Moolenaar // The text format includes a locale name. Ideally, this would be the 724b5a7a8b5SBram Moolenaar // language of the text, which may or may not be the same as the primary 725b5a7a8b5SBram Moolenaar // language of the user. However, for our purposes the user locale will do. 726b5a7a8b5SBram Moolenaar wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; 727b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 728b5a7a8b5SBram Moolenaar { 729b5a7a8b5SBram Moolenaar if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0) 730b5a7a8b5SBram Moolenaar hr = HRESULT_FROM_WIN32(GetLastError()); 731b5a7a8b5SBram Moolenaar } 732b5a7a8b5SBram Moolenaar 733b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 734b5a7a8b5SBram Moolenaar { 735b5a7a8b5SBram Moolenaar // Create the text format object. 736b5a7a8b5SBram Moolenaar hr = mDWriteFactory->CreateTextFormat( 737b5a7a8b5SBram Moolenaar familyName, 738b5a7a8b5SBram Moolenaar NULL, // no custom font collection 739b5a7a8b5SBram Moolenaar font->GetWeight(), 740b5a7a8b5SBram Moolenaar font->GetStyle(), 741b5a7a8b5SBram Moolenaar font->GetStretch(), 742b5a7a8b5SBram Moolenaar fontSize, 743b5a7a8b5SBram Moolenaar localeName, 744*d7ccc4d8SBram Moolenaar &pTextFormat); 745b5a7a8b5SBram Moolenaar } 746b5a7a8b5SBram Moolenaar 747b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 748*d7ccc4d8SBram Moolenaar hr = pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); 749*d7ccc4d8SBram Moolenaar 750*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 751*d7ccc4d8SBram Moolenaar hr = pTextFormat->SetParagraphAlignment( 752*d7ccc4d8SBram Moolenaar DWRITE_PARAGRAPH_ALIGNMENT_CENTER); 753*d7ccc4d8SBram Moolenaar 754*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 755*d7ccc4d8SBram Moolenaar hr = pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 756b5a7a8b5SBram Moolenaar 757b5a7a8b5SBram Moolenaar SafeRelease(&localizedFamilyNames); 758b5a7a8b5SBram Moolenaar SafeRelease(&fontFamily); 759b5a7a8b5SBram Moolenaar SafeRelease(&font); 760b5a7a8b5SBram Moolenaar 761*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 762*d7ccc4d8SBram Moolenaar *ppTextFormat = pTextFormat; 763*d7ccc4d8SBram Moolenaar else 764*d7ccc4d8SBram Moolenaar SafeRelease(&pTextFormat); 765*d7ccc4d8SBram Moolenaar 766*d7ccc4d8SBram Moolenaar return hr; 767*d7ccc4d8SBram Moolenaar } 768*d7ccc4d8SBram Moolenaar 769*d7ccc4d8SBram Moolenaar HRESULT 770*d7ccc4d8SBram Moolenaar DWriteContext::SetFontByLOGFONT(const LOGFONTW &logFont) 771*d7ccc4d8SBram Moolenaar { 772*d7ccc4d8SBram Moolenaar HRESULT hr = S_OK; 773*d7ccc4d8SBram Moolenaar IDWriteTextFormat *pTextFormat = NULL; 774*d7ccc4d8SBram Moolenaar 775*d7ccc4d8SBram Moolenaar hr = CreateTextFormatFromLOGFONT(logFont, &pTextFormat); 776*d7ccc4d8SBram Moolenaar 777*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 778*d7ccc4d8SBram Moolenaar { 779*d7ccc4d8SBram Moolenaar SafeRelease(&mTextFormat); 780*d7ccc4d8SBram Moolenaar mTextFormat = pTextFormat; 781*d7ccc4d8SBram Moolenaar mFontWeight = static_cast<DWRITE_FONT_WEIGHT>(logFont.lfWeight); 782*d7ccc4d8SBram Moolenaar mFontStyle = logFont.lfItalic ? DWRITE_FONT_STYLE_ITALIC 783*d7ccc4d8SBram Moolenaar : DWRITE_FONT_STYLE_NORMAL; 784*d7ccc4d8SBram Moolenaar } 785*d7ccc4d8SBram Moolenaar 786b5a7a8b5SBram Moolenaar return hr; 787b5a7a8b5SBram Moolenaar } 788b5a7a8b5SBram Moolenaar 789b5a7a8b5SBram Moolenaar void 790b5a7a8b5SBram Moolenaar DWriteContext::SetFont(HFONT hFont) 791b5a7a8b5SBram Moolenaar { 792*d7ccc4d8SBram Moolenaar FontCache::Item item; 793*d7ccc4d8SBram Moolenaar if (mFontCache.get(hFont, item)) 794b5a7a8b5SBram Moolenaar { 795*d7ccc4d8SBram Moolenaar if (item.pTextFormat != NULL) 796*d7ccc4d8SBram Moolenaar { 797*d7ccc4d8SBram Moolenaar item.pTextFormat->AddRef(); 798*d7ccc4d8SBram Moolenaar SafeRelease(&mTextFormat); 799*d7ccc4d8SBram Moolenaar mTextFormat = item.pTextFormat; 800*d7ccc4d8SBram Moolenaar mFontWeight = item.fontWeight; 801*d7ccc4d8SBram Moolenaar mFontStyle = item.fontStyle; 802*d7ccc4d8SBram Moolenaar mFallbackDC = false; 803*d7ccc4d8SBram Moolenaar } 804*d7ccc4d8SBram Moolenaar else 805*d7ccc4d8SBram Moolenaar mFallbackDC = true; 806*d7ccc4d8SBram Moolenaar return; 807*d7ccc4d8SBram Moolenaar } 808*d7ccc4d8SBram Moolenaar 809*d7ccc4d8SBram Moolenaar HRESULT hr = E_FAIL; 810b5a7a8b5SBram Moolenaar LOGFONTW lf; 811b5a7a8b5SBram Moolenaar if (GetObjectW(hFont, sizeof(lf), &lf)) 812*d7ccc4d8SBram Moolenaar hr = SetFontByLOGFONT(lf); 813*d7ccc4d8SBram Moolenaar 814*d7ccc4d8SBram Moolenaar item.hFont = hFont; 815*d7ccc4d8SBram Moolenaar if (SUCCEEDED(hr)) 816b5a7a8b5SBram Moolenaar { 817*d7ccc4d8SBram Moolenaar item.pTextFormat = mTextFormat; 818*d7ccc4d8SBram Moolenaar item.fontWeight = mFontWeight; 819*d7ccc4d8SBram Moolenaar item.fontStyle = mFontStyle; 820b5a7a8b5SBram Moolenaar } 821*d7ccc4d8SBram Moolenaar mFontCache.put(item); 822b5a7a8b5SBram Moolenaar } 823b5a7a8b5SBram Moolenaar 824b5a7a8b5SBram Moolenaar void 825*d7ccc4d8SBram Moolenaar DWriteContext::BindDC(HDC hdc, RECT *rect) 826b5a7a8b5SBram Moolenaar { 827*d7ccc4d8SBram Moolenaar Flush(); 828*d7ccc4d8SBram Moolenaar mRT->BindDC(hdc, rect); 829*d7ccc4d8SBram Moolenaar mRT->SetTransform(D2D1::IdentityMatrix()); 830*d7ccc4d8SBram Moolenaar mHDC = hdc; 831b5a7a8b5SBram Moolenaar } 832b5a7a8b5SBram Moolenaar 833b5a7a8b5SBram Moolenaar void 834*d7ccc4d8SBram Moolenaar DWriteContext::AssureDrawing() 835b5a7a8b5SBram Moolenaar { 836*d7ccc4d8SBram Moolenaar if (mDrawing == false) 837b5a7a8b5SBram Moolenaar { 838*d7ccc4d8SBram Moolenaar mRT->BeginDraw(); 839*d7ccc4d8SBram Moolenaar mDrawing = true; 840*d7ccc4d8SBram Moolenaar } 841*d7ccc4d8SBram Moolenaar } 842*d7ccc4d8SBram Moolenaar 843*d7ccc4d8SBram Moolenaar ID2D1Brush* 844*d7ccc4d8SBram Moolenaar DWriteContext::SolidBrush(COLORREF color) 845*d7ccc4d8SBram Moolenaar { 846*d7ccc4d8SBram Moolenaar mBrush->SetColor(D2D1::ColorF(UINT32(GetRValue(color)) << 16 | 847*d7ccc4d8SBram Moolenaar UINT32(GetGValue(color)) << 8 | UINT32(GetBValue(color)))); 848*d7ccc4d8SBram Moolenaar return mBrush; 849*d7ccc4d8SBram Moolenaar } 850*d7ccc4d8SBram Moolenaar 851*d7ccc4d8SBram Moolenaar void 852*d7ccc4d8SBram Moolenaar DWriteContext::DrawText(const WCHAR* text, int len, 853*d7ccc4d8SBram Moolenaar int x, int y, int w, int h, int cellWidth, COLORREF color, 854*d7ccc4d8SBram Moolenaar UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx) 855*d7ccc4d8SBram Moolenaar { 856*d7ccc4d8SBram Moolenaar if (mFallbackDC) 857*d7ccc4d8SBram Moolenaar { 858*d7ccc4d8SBram Moolenaar Flush(); 859*d7ccc4d8SBram Moolenaar ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx); 860*d7ccc4d8SBram Moolenaar return; 861*d7ccc4d8SBram Moolenaar } 862*d7ccc4d8SBram Moolenaar 863*d7ccc4d8SBram Moolenaar AssureDrawing(); 864*d7ccc4d8SBram Moolenaar 865*d7ccc4d8SBram Moolenaar HRESULT hr; 866b5a7a8b5SBram Moolenaar IDWriteTextLayout *textLayout = NULL; 867b5a7a8b5SBram Moolenaar 868*d7ccc4d8SBram Moolenaar hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat, 869*d7ccc4d8SBram Moolenaar FLOAT(w), FLOAT(h), &textLayout); 870b5a7a8b5SBram Moolenaar 871b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr)) 872b5a7a8b5SBram Moolenaar { 873*d7ccc4d8SBram Moolenaar DWRITE_TEXT_RANGE textRange = { 0, UINT32(len) }; 874b5a7a8b5SBram Moolenaar textLayout->SetFontWeight(mFontWeight, textRange); 875b5a7a8b5SBram Moolenaar textLayout->SetFontStyle(mFontStyle, textRange); 876b5a7a8b5SBram Moolenaar 877*d7ccc4d8SBram Moolenaar TextRenderer renderer(this); 878*d7ccc4d8SBram Moolenaar TextRendererContext context = { color, FLOAT(cellWidth), 0.0f }; 879*d7ccc4d8SBram Moolenaar textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y)); 880b5a7a8b5SBram Moolenaar } 881b5a7a8b5SBram Moolenaar 882b5a7a8b5SBram Moolenaar SafeRelease(&textLayout); 883b5a7a8b5SBram Moolenaar } 884b5a7a8b5SBram Moolenaar 885*d7ccc4d8SBram Moolenaar void 886*d7ccc4d8SBram Moolenaar DWriteContext::FillRect(RECT *rc, COLORREF color) 887*d7ccc4d8SBram Moolenaar { 888*d7ccc4d8SBram Moolenaar AssureDrawing(); 889*d7ccc4d8SBram Moolenaar mRT->FillRectangle( 890*d7ccc4d8SBram Moolenaar D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top), 891*d7ccc4d8SBram Moolenaar FLOAT(rc->right), FLOAT(rc->bottom)), 892*d7ccc4d8SBram Moolenaar SolidBrush(color)); 893b5a7a8b5SBram Moolenaar } 894b5a7a8b5SBram Moolenaar 895*d7ccc4d8SBram Moolenaar void 896*d7ccc4d8SBram Moolenaar DWriteContext::Flush() 897b5a7a8b5SBram Moolenaar { 898*d7ccc4d8SBram Moolenaar if (mDrawing) 899*d7ccc4d8SBram Moolenaar { 900*d7ccc4d8SBram Moolenaar mRT->EndDraw(); 901*d7ccc4d8SBram Moolenaar mDrawing = false; 902b5a7a8b5SBram Moolenaar } 903b5a7a8b5SBram Moolenaar } 904b5a7a8b5SBram Moolenaar 905b5a7a8b5SBram Moolenaar void 906b5a7a8b5SBram Moolenaar DWriteContext::SetRenderingParams( 907b5a7a8b5SBram Moolenaar const DWriteRenderingParams *params) 908b5a7a8b5SBram Moolenaar { 909b5a7a8b5SBram Moolenaar if (mDWriteFactory == NULL) 910b5a7a8b5SBram Moolenaar return; 911b5a7a8b5SBram Moolenaar 912b5a7a8b5SBram Moolenaar IDWriteRenderingParams *renderingParams = NULL; 913b5a7a8b5SBram Moolenaar D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode = 914b5a7a8b5SBram Moolenaar D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; 915b5a7a8b5SBram Moolenaar HRESULT hr; 916b5a7a8b5SBram Moolenaar if (params != NULL) 917b5a7a8b5SBram Moolenaar { 918b5a7a8b5SBram Moolenaar hr = mDWriteFactory->CreateCustomRenderingParams(params->gamma, 919b5a7a8b5SBram Moolenaar params->enhancedContrast, params->clearTypeLevel, 920b5a7a8b5SBram Moolenaar ToPixelGeometry(params->pixelGeometry), 921b5a7a8b5SBram Moolenaar ToRenderingMode(params->renderingMode), &renderingParams); 922b5a7a8b5SBram Moolenaar textAntialiasMode = ToTextAntialiasMode(params->textAntialiasMode); 923b5a7a8b5SBram Moolenaar } 924b5a7a8b5SBram Moolenaar else 925b5a7a8b5SBram Moolenaar hr = mDWriteFactory->CreateRenderingParams(&renderingParams); 926b5a7a8b5SBram Moolenaar if (SUCCEEDED(hr) && renderingParams != NULL) 927b5a7a8b5SBram Moolenaar { 928b5a7a8b5SBram Moolenaar SafeRelease(&mRenderingParams); 929b5a7a8b5SBram Moolenaar mRenderingParams = renderingParams; 930b5a7a8b5SBram Moolenaar mTextAntialiasMode = textAntialiasMode; 931*d7ccc4d8SBram Moolenaar 932*d7ccc4d8SBram Moolenaar Flush(); 933*d7ccc4d8SBram Moolenaar mRT->SetTextRenderingParams(mRenderingParams); 934*d7ccc4d8SBram Moolenaar mRT->SetTextAntialiasMode(mTextAntialiasMode); 935b5a7a8b5SBram Moolenaar } 936b5a7a8b5SBram Moolenaar } 937b5a7a8b5SBram Moolenaar 938b5a7a8b5SBram Moolenaar DWriteRenderingParams * 939b5a7a8b5SBram Moolenaar DWriteContext::GetRenderingParams( 940b5a7a8b5SBram Moolenaar DWriteRenderingParams *params) 941b5a7a8b5SBram Moolenaar { 942b5a7a8b5SBram Moolenaar if (params != NULL && mRenderingParams != NULL) 943b5a7a8b5SBram Moolenaar { 944b5a7a8b5SBram Moolenaar params->gamma = mRenderingParams->GetGamma(); 945b5a7a8b5SBram Moolenaar params->enhancedContrast = mRenderingParams->GetEnhancedContrast(); 946b5a7a8b5SBram Moolenaar params->clearTypeLevel = mRenderingParams->GetClearTypeLevel(); 947b5a7a8b5SBram Moolenaar params->pixelGeometry = ToInt(mRenderingParams->GetPixelGeometry()); 948b5a7a8b5SBram Moolenaar params->renderingMode = ToInt(mRenderingParams->GetRenderingMode()); 949b5a7a8b5SBram Moolenaar params->textAntialiasMode = mTextAntialiasMode; 950b5a7a8b5SBram Moolenaar } 951b5a7a8b5SBram Moolenaar return params; 952b5a7a8b5SBram Moolenaar } 953b5a7a8b5SBram Moolenaar 954b5a7a8b5SBram Moolenaar //////////////////////////////////////////////////////////////////////////// 955b5a7a8b5SBram Moolenaar // PUBLIC C INTERFACES 956b5a7a8b5SBram Moolenaar 957b5a7a8b5SBram Moolenaar void 958b5a7a8b5SBram Moolenaar DWrite_Init(void) 959b5a7a8b5SBram Moolenaar { 960b5a7a8b5SBram Moolenaar #ifdef DYNAMIC_DIRECTX 961b5a7a8b5SBram Moolenaar // Load libraries. 962b5a7a8b5SBram Moolenaar hD2D1DLL = vimLoadLib(const_cast<char*>("d2d1.dll")); 963b5a7a8b5SBram Moolenaar hDWriteDLL = vimLoadLib(const_cast<char*>("dwrite.dll")); 964b5a7a8b5SBram Moolenaar if (hD2D1DLL == NULL || hDWriteDLL == NULL) 965b5a7a8b5SBram Moolenaar { 966b5a7a8b5SBram Moolenaar DWrite_Final(); 967b5a7a8b5SBram Moolenaar return; 968b5a7a8b5SBram Moolenaar } 969b5a7a8b5SBram Moolenaar // Get address of procedures. 970b5a7a8b5SBram Moolenaar pGetUserDefaultLocaleName = (PGETUSERDEFAULTLOCALENAME)GetProcAddress( 971b5a7a8b5SBram Moolenaar GetModuleHandle("kernel32.dll"), "GetUserDefaultLocaleName"); 972b5a7a8b5SBram Moolenaar pD2D1CreateFactory = (PD2D1CREATEFACTORY)GetProcAddress(hD2D1DLL, 973b5a7a8b5SBram Moolenaar "D2D1CreateFactory"); 974b5a7a8b5SBram Moolenaar pDWriteCreateFactory = (PDWRITECREATEFACTORY)GetProcAddress(hDWriteDLL, 975b5a7a8b5SBram Moolenaar "DWriteCreateFactory"); 976b5a7a8b5SBram Moolenaar #endif 977b5a7a8b5SBram Moolenaar } 978b5a7a8b5SBram Moolenaar 979b5a7a8b5SBram Moolenaar void 980b5a7a8b5SBram Moolenaar DWrite_Final(void) 981b5a7a8b5SBram Moolenaar { 982b5a7a8b5SBram Moolenaar #ifdef DYNAMIC_DIRECTX 983b5a7a8b5SBram Moolenaar pGetUserDefaultLocaleName = NULL; 984b5a7a8b5SBram Moolenaar pD2D1CreateFactory = NULL; 985b5a7a8b5SBram Moolenaar pDWriteCreateFactory = NULL; 986b5a7a8b5SBram Moolenaar unload(hDWriteDLL); 987b5a7a8b5SBram Moolenaar unload(hD2D1DLL); 988b5a7a8b5SBram Moolenaar #endif 989b5a7a8b5SBram Moolenaar } 990b5a7a8b5SBram Moolenaar 991b5a7a8b5SBram Moolenaar DWriteContext * 992b5a7a8b5SBram Moolenaar DWriteContext_Open(void) 993b5a7a8b5SBram Moolenaar { 994b5a7a8b5SBram Moolenaar #ifdef DYNAMIC_DIRECTX 995b5a7a8b5SBram Moolenaar if (pGetUserDefaultLocaleName == NULL || pD2D1CreateFactory == NULL 996b5a7a8b5SBram Moolenaar || pDWriteCreateFactory == NULL) 997b5a7a8b5SBram Moolenaar return NULL; 998b5a7a8b5SBram Moolenaar #endif 999b5a7a8b5SBram Moolenaar return new DWriteContext(); 1000b5a7a8b5SBram Moolenaar } 1001b5a7a8b5SBram Moolenaar 1002b5a7a8b5SBram Moolenaar void 1003b5a7a8b5SBram Moolenaar DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect) 1004b5a7a8b5SBram Moolenaar { 1005*d7ccc4d8SBram Moolenaar if (ctx != NULL) 1006*d7ccc4d8SBram Moolenaar ctx->BindDC(hdc, rect); 1007b5a7a8b5SBram Moolenaar } 1008b5a7a8b5SBram Moolenaar 1009b5a7a8b5SBram Moolenaar void 1010b5a7a8b5SBram Moolenaar DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont) 1011b5a7a8b5SBram Moolenaar { 1012b5a7a8b5SBram Moolenaar if (ctx != NULL) 1013b5a7a8b5SBram Moolenaar ctx->SetFont(hFont); 1014b5a7a8b5SBram Moolenaar } 1015b5a7a8b5SBram Moolenaar 1016b5a7a8b5SBram Moolenaar void 1017b5a7a8b5SBram Moolenaar DWriteContext_DrawText( 1018b5a7a8b5SBram Moolenaar DWriteContext *ctx, 1019b5a7a8b5SBram Moolenaar const WCHAR* text, 1020b5a7a8b5SBram Moolenaar int len, 1021b5a7a8b5SBram Moolenaar int x, 1022b5a7a8b5SBram Moolenaar int y, 1023b5a7a8b5SBram Moolenaar int w, 1024b5a7a8b5SBram Moolenaar int h, 1025b5a7a8b5SBram Moolenaar int cellWidth, 1026*d7ccc4d8SBram Moolenaar COLORREF color, 1027*d7ccc4d8SBram Moolenaar UINT fuOptions, 1028*d7ccc4d8SBram Moolenaar CONST RECT *lprc, 1029*d7ccc4d8SBram Moolenaar CONST INT * lpDx) 1030b5a7a8b5SBram Moolenaar { 1031b5a7a8b5SBram Moolenaar if (ctx != NULL) 1032*d7ccc4d8SBram Moolenaar ctx->DrawText(text, len, x, y, w, h, cellWidth, color, 1033*d7ccc4d8SBram Moolenaar fuOptions, lprc, lpDx); 1034b5a7a8b5SBram Moolenaar } 1035b5a7a8b5SBram Moolenaar 1036b5a7a8b5SBram Moolenaar void 1037*d7ccc4d8SBram Moolenaar DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color) 1038b5a7a8b5SBram Moolenaar { 1039*d7ccc4d8SBram Moolenaar if (ctx != NULL) 1040*d7ccc4d8SBram Moolenaar ctx->FillRect(rc, color); 1041b5a7a8b5SBram Moolenaar } 1042*d7ccc4d8SBram Moolenaar 1043*d7ccc4d8SBram Moolenaar void 1044*d7ccc4d8SBram Moolenaar DWriteContext_Flush(DWriteContext *ctx) 1045*d7ccc4d8SBram Moolenaar { 1046*d7ccc4d8SBram Moolenaar if (ctx != NULL) 1047*d7ccc4d8SBram Moolenaar ctx->Flush(); 1048b5a7a8b5SBram Moolenaar } 1049b5a7a8b5SBram Moolenaar 1050b5a7a8b5SBram Moolenaar void 1051b5a7a8b5SBram Moolenaar DWriteContext_Close(DWriteContext *ctx) 1052b5a7a8b5SBram Moolenaar { 1053b5a7a8b5SBram Moolenaar delete ctx; 1054b5a7a8b5SBram Moolenaar } 1055b5a7a8b5SBram Moolenaar 1056b5a7a8b5SBram Moolenaar void 1057b5a7a8b5SBram Moolenaar DWriteContext_SetRenderingParams( 1058b5a7a8b5SBram Moolenaar DWriteContext *ctx, 1059b5a7a8b5SBram Moolenaar const DWriteRenderingParams *params) 1060b5a7a8b5SBram Moolenaar { 1061b5a7a8b5SBram Moolenaar if (ctx != NULL) 1062b5a7a8b5SBram Moolenaar ctx->SetRenderingParams(params); 1063b5a7a8b5SBram Moolenaar } 1064b5a7a8b5SBram Moolenaar 1065b5a7a8b5SBram Moolenaar DWriteRenderingParams * 1066b5a7a8b5SBram Moolenaar DWriteContext_GetRenderingParams( 1067b5a7a8b5SBram Moolenaar DWriteContext *ctx, 1068b5a7a8b5SBram Moolenaar DWriteRenderingParams *params) 1069b5a7a8b5SBram Moolenaar { 1070b5a7a8b5SBram Moolenaar if (ctx != NULL) 1071b5a7a8b5SBram Moolenaar return ctx->GetRenderingParams(params); 1072b5a7a8b5SBram Moolenaar else 1073b5a7a8b5SBram Moolenaar return NULL; 1074b5a7a8b5SBram Moolenaar } 1075