Thank you Ken!
It seems OK for me. And I merged your patch and updated mine. Please check it! -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
# HG changeset patch # Parent 73ed2bb6def5b7eb1153ecb6961868601ad4a7c0 diff -r 73ed2bb6def5 runtime/doc/eval.txt --- a/runtime/doc/eval.txt Sun Mar 24 10:08:39 2013 +0900 +++ b/runtime/doc/eval.txt Wed Apr 03 01:57:32 2013 +0900 @@ -6348,6 +6348,7 @@ dialog_gui Compiled with GUI dialog support. diff Compiled with |vimdiff| and 'diff' support. digraphs Compiled with support for digraphs. +directx Compiled with support for 'directx'. dnd Compiled with support for the "~ register |quote_~|. dos16 16 bits DOS version of Vim. dos32 32 bits DOS (DJGPP) version of Vim. diff -r 73ed2bb6def5 runtime/doc/options.txt --- a/runtime/doc/options.txt Sun Mar 24 10:08:39 2013 +0900 +++ b/runtime/doc/options.txt Wed Apr 03 01:57:32 2013 +0900 @@ -5553,6 +5553,77 @@ this option at the default "on". Only switch it off when working with old Vi scripts. + *'renderoptions'* *'rop'* +'renderoptions' 'rop' string (default: empty) + global + {not in Vi} + {only available when compiled with GUI and DIRECTX + enabled for MS-Windows} + Select a text renderer and set its options. The options are depends + on the renderer. + + Syntax: > + set rop=type:{renderer}(,{name}:{value})* +< + Currently, only one renderer is available. + + render behavior ~ + directx Vim will draw text using DirectX (DirectWrite). It makes + drawn glyphs more beautiful than default GDI. + It requires 'encoding' is "utf-8", and only works on + MS-Windows Vista or newer version. + + Options: + name meaning type value ~ + gamma gamma float 1.0 - 2.2 (maybe) + contrast enhancedContrast float (unknown) + level clearTypeLevel float (unknown) + geom pixelGeometry int 0 - 2 (see below) + renmode renderingMode int 0 - 6 (see below) + taamode textAntialiasMode int 0 - 3 (see below) + + See this URL for detail: + http://msdn.microsoft.com/en-us/library/dd368190.aspx + + For geom: structure of a device pixel. + 0 - DWRITE_PIXEL_GEOMETRY_FLAT + 1 - DWRITE_PIXEL_GEOMETRY_RGB + 2 - DWRITE_PIXEL_GEOMETRY_BGR + + See this URL for detail: + http://msdn.microsoft.com/en-us/library/dd368114.aspx + + For renmode: method of rendering glyphs. + 0 - DWRITE_RENDERING_MODE_DEFAULT + 1 - DWRITE_RENDERING_MODE_ALIASED + 2 - DWRITE_RENDERING_MODE_GDI_CLASSIC + 3 - DWRITE_RENDERING_MODE_GDI_NATURAL + 4 - DWRITE_RENDERING_MODE_NATURAL + 5 - DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC + 6 - DWRITE_RENDERING_MODE_OUTLINE + + See this URL for detail: + http://msdn.microsoft.com/en-us/library/dd368118.aspx + + For taamode: antialiasing mode used for drawing text. + 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT + 1 - D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE + 2 - D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE + 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED + + See this URL for detail: + http://msdn.microsoft.com/en-us/library/dd368170.aspx + + Example: > + set encoding=utf-8 + set gfn=Ricty_Diminished:h12:cSHIFTJIS + set rop=type:directx +< + If select a raster font (Courier, Terminal or FixedSys) to + 'guifont', it fallbacks to be drawn by GDI automatically. + + Other render types are not supported currently. + *'report'* 'report' number (default 2) global diff -r 73ed2bb6def5 runtime/doc/various.txt --- a/runtime/doc/various.txt Sun Mar 24 10:08:39 2013 +0900 +++ b/runtime/doc/various.txt Wed Apr 03 01:57:32 2013 +0900 @@ -320,6 +320,7 @@ N *+dialog_con_gui* Support for |:confirm| with GUI and console dialog. N *+diff* |vimdiff| and 'diff' N *+digraphs* |digraphs| *E196* +m *+directx* Win32 GUI only: |'directx'| *+dnd* Support for DnD into the "~ register |quote_~|. B *+emacs_tags* |emacs-tags| files N *+eval* expression evaluation |eval.txt| diff -r 73ed2bb6def5 src/Make_cyg.mak --- a/src/Make_cyg.mak Sun Mar 24 10:08:39 2013 +0900 +++ b/src/Make_cyg.mak Wed Apr 03 01:57:32 2013 +0900 @@ -8,6 +8,7 @@ # Cygwin application use the Makefile (just like on Unix). # # GUI no or yes: set to yes if you want the GUI version (yes) +# DIRECTX no or yes: set to yes if you want use DirectWrite (no) # PERL define to path to Perl dir to get Perl support (not defined) # PERL_VER define to version of Perl being used (56) # DYNAMIC_PERL no or yes: set to yes to load the Perl DLL dynamically (yes) @@ -88,6 +89,10 @@ ARCH = i386 endif +ifndef DIRECTX +DIRECTX = no +endif + ifndef WINVER WINVER = 0x0500 endif @@ -469,6 +474,15 @@ endif ############################## +ifeq (yes, $(DIRECTX)) +# Only allow DIRECTX for a GUI build. +DEFINES += -DFEAT_DIRECTX -DDYNAMIC_DIRECTX +EXTRA_OBJS += $(OUTDIR)/gui_dwrite.o +EXTRA_LIBS += -ld2d1 -ldwrite +USE_STDCPLUS = yes +endif + +############################## ifdef XPM # Only allow XPM for a GUI build. DEFINES += -DFEAT_XPM_W32 @@ -494,11 +508,7 @@ DEFINES += -DFEAT_OLE EXTRA_OBJS += $(OUTDIR)/if_ole.o EXTRA_LIBS += -loleaut32 -ifeq (yes, $(STATIC_STDCPLUS)) -EXTRA_LIBS += -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -else -EXTRA_LIBS += -lstdc++ -endif +USE_STDCPLUS = yes endif ############################## @@ -512,6 +522,15 @@ DIRSLASH = \\ endif +############################## +ifeq (yes, $(USE_STDCPLUS)) +ifeq (yes, $(STATIC_STDCPLUS)) +EXTRA_LIBS += -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic +else +EXTRA_LIBS += -lstdc++ +endif +endif + #>>>>> end of choices ########################################################################### @@ -642,6 +661,9 @@ $(OUTDIR)/gui_w32.o: gui_w32.c gui_w48.c $(INCL) $(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o +$(OUTDIR)/gui_dwrite.o: gui_dwrite.cpp $(INCL) gui_dwrite.h + $(CC) -c $(CFLAGS) gui_dwrite.cpp -o $(OUTDIR)/gui_dwrite.o + $(OUTDIR)/if_cscope.o: if_cscope.c $(INCL) if_cscope.h $(CC) -c $(CFLAGS) if_cscope.c -o $(OUTDIR)/if_cscope.o diff -r 73ed2bb6def5 src/Make_ming.mak --- a/src/Make_ming.mak Sun Mar 24 10:08:39 2013 +0900 +++ b/src/Make_ming.mak Wed Apr 03 01:57:32 2013 +0900 @@ -31,6 +31,8 @@ OPTIMIZE=MAXSPEED # set to yes to make gvim, no for vim GUI=yes +# set to yes if you want to use DirectWrite (DirectX) +DIRECTX=no # FEATURES=[TINY | SMALL | NORMAL | BIG | HUGE] # Set to TINY to make minimal version (few features). FEATURES=BIG @@ -451,6 +453,14 @@ endif endif +# DirectWrite (DirectX) +ifeq ($(DIRECTX),yes) +# Only allow DirectWrite for a GUI build. +ifeq (yes, $(GUI)) +DEFINES += -DFEAT_DIRECTX -DDYNAMIC_DIRECTX +endif +endif + # Only allow XPM for a GUI build. ifeq (yes, $(GUI)) @@ -588,6 +598,14 @@ LIB += -lwsock32 endif endif +ifeq ($(DIRECTX),yes) +# Only allow DIRECTX for a GUI build. +ifeq (yes, $(GUI)) +OBJ += $(OUTDIR)/gui_dwrite.o +LIB += -ld2d1 -ldwrite +USE_STDCPLUS = yes +endif +endif ifdef XPM # Only allow XPM for a GUI build. ifeq (yes, $(GUI)) @@ -645,11 +663,7 @@ ifeq (yes, $(OLE)) LIB += -loleaut32 OBJ += $(OUTDIR)/if_ole.o -ifeq (yes, $(STATIC_STDCPLUS)) -LIB += -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -else -LIB += -lstdc++ -endif +USE_STDCPLUS = yes endif ifeq (yes, $(MBYTE)) @@ -673,6 +687,14 @@ DEFINES+=-DDYNAMIC_ICONV endif +ifeq (yes, $(USE_STDCPLUS)) +ifeq (yes, $(STATIC_STDCPLUS)) +LIB += -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic +else +LIB += -lstdc++ +endif +endif + all: $(TARGET) vimrun.exe xxd/xxd.exe install.exe uninstal.exe GvimExt/gvimext.dll vimrun.exe: vimrun.c @@ -746,6 +768,9 @@ $(OUTDIR)/gui_w32.o: gui_w32.c gui_w48.c $(INCL) $(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o +$(OUTDIR)/gui_dwrite.o: gui_dwrite.cpp $(INCL) gui_dwrite.h + $(CC) -c $(CFLAGS) gui_dwrite.cpp -o $(OUTDIR)/gui_dwrite.o + $(OUTDIR)/if_cscope.o: if_cscope.c $(INCL) if_cscope.h $(CC) -c $(CFLAGS) if_cscope.c -o $(OUTDIR)/if_cscope.o diff -r 73ed2bb6def5 src/Make_mvc.mak --- a/src/Make_mvc.mak Sun Mar 24 10:08:39 2013 +0900 +++ b/src/Make_mvc.mak Wed Apr 03 01:57:32 2013 +0900 @@ -24,6 +24,9 @@ # # GUI interface: GUI=yes (default is no) # +# GUI with DirectWrite(DirectX): DIRECTX=yes +# (default is no, requires GUI=yes) +# # OLE interface: OLE=yes (usually with GUI=yes) # # Multibyte support: MBYTE=yes (default is no) @@ -166,6 +169,9 @@ !else OBJDIR = .\ObjC !endif +!if "$(DIRECTX)" == "yes" +OBJDIR = $(OBJDIR)X +!endif !if "$(OLE)" == "yes" OBJDIR = $(OBJDIR)O !endif @@ -290,6 +296,13 @@ NETBEANS_LIB = WSock32.lib !endif +# DirectWrite(DirectX) +!if "$(DIRECTX)" == "yes" +DIRECTX_DEFS = -DFEAT_DIRECTX -DDYNAMIC_DIRECTX +DIRECTX_INCL = gui_dwrite.h +DIRECTX_OBJ = $(OUTDIR)\gui_dwrite.obj +!endif + !ifndef XPM # XPM is not set, use the included xpm files, depending on the architecture. !if "$(CPU)" == "AMD64" @@ -623,6 +636,12 @@ SUBSYSTEM = console !endif +!if "$(GUI)" == "yes" && "$(DIRECTX)" == "yes" +CFLAGS = $(CFLAGS) $(DIRECTX_DEFS) +GUI_INCL = $(GUI_INCL) $(DIRECTX_INCL) +GUI_OBJ = $(GUI_OBJ) $(DIRECTX_OBJ) +!endif + # iconv.dll library (dynamically loaded) !ifndef ICONV ICONV = yes @@ -1096,6 +1115,8 @@ $(OUTDIR)/gui_w32.obj: $(OUTDIR) gui_w32.c gui_w48.c $(INCL) $(GUI_INCL) +$(OUTDIR)/gui_dwrite.obj: $(OUTDIR) gui_dwrite.cpp $(INCL) $(GUI_INCL) + $(OUTDIR)/if_cscope.obj: $(OUTDIR) if_cscope.c $(INCL) $(OUTDIR)/if_lua.obj: $(OUTDIR) if_lua.c $(INCL) diff -r 73ed2bb6def5 src/eval.c --- a/src/eval.c Sun Mar 24 10:08:39 2013 +0900 +++ b/src/eval.c Wed Apr 03 01:57:32 2013 +0900 @@ -12166,6 +12166,9 @@ #ifdef FEAT_DIGRAPHS "digraphs", #endif +#ifdef FEAT_DIRECTX + "directx", +#endif #ifdef FEAT_DND "dnd", #endif diff -r 73ed2bb6def5 src/gui_dwrite.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui_dwrite.cpp Wed Apr 03 01:57:32 2013 +0900 @@ -0,0 +1,892 @@ +/* vi:set ts=8 sts=4 sw=4 noet: */ + +#define WIN32_LEAN_AND_MEAN + +#ifndef DYNAMIC_DIRECTX +# if WINVER < 0x0600 +# error WINVER must be 0x0600 or above to use DirectWrite(DirectX) +# endif +#endif + +#include <windows.h> +#include <crtdbg.h> +#include <assert.h> +#include <math.h> +#include <d2d1.h> +#include <d2d1helper.h> +#include <dwrite.h> + +#include "gui_dwrite.h" + +#ifdef __MINGW32__ +# define __maybenull SAL__maybenull +# define __in SAL__in +# define __out SAL__out +#endif + +#ifdef DYNAMIC_DIRECTX +extern "C" HINSTANCE vimLoadLib(char *name); + +typedef int (WINAPI *PGETUSERDEFAULTLOCALENAME)(LPWSTR, int); +typedef HRESULT (WINAPI *PD2D1CREATEFACTORY)(D2D1_FACTORY_TYPE, + REFIID, const D2D1_FACTORY_OPTIONS *, void **); +typedef HRESULT (WINAPI *PDWRITECREATEFACTORY)(DWRITE_FACTORY_TYPE, + REFIID, IUnknown **); + +static HINSTANCE hD2D1DLL = NULL; +static HINSTANCE hDWriteDLL = NULL; + +static PGETUSERDEFAULTLOCALENAME pGetUserDefaultLocaleName = NULL; +static PD2D1CREATEFACTORY pD2D1CreateFactory = NULL; +static PDWRITECREATEFACTORY pDWriteCreateFactory = NULL; + +#define GetUserDefaultLocaleName (*pGetUserDefaultLocaleName) +#define D2D1CreateFactory (*pD2D1CreateFactory) +#define DWriteCreateFactory (*pDWriteCreateFactory) + + static void +unload(HINSTANCE &hinst) +{ + if (hinst != NULL) + { + FreeLibrary(hinst); + hinst = NULL; + } +} +#endif // DYNAMIC_DIRECTX + +template <class T> inline void SafeRelease(T **ppT) +{ + if (*ppT) + { + (*ppT)->Release(); + *ppT = NULL; + } +} + +struct GdiTextRendererContext +{ + // const fields. + COLORREF color; + FLOAT cellWidth; + + // working fileds. + FLOAT offsetX; +}; + + static DWRITE_PIXEL_GEOMETRY +ToPixelGeometry(int value) +{ + switch (value) + { + default: + case 0: + return DWRITE_PIXEL_GEOMETRY_FLAT; + case 1: + return DWRITE_PIXEL_GEOMETRY_RGB; + case 2: + return DWRITE_PIXEL_GEOMETRY_BGR; + } +} + + static int +ToInt(DWRITE_PIXEL_GEOMETRY value) +{ + switch (value) + { + case DWRITE_PIXEL_GEOMETRY_FLAT: + return 0; + case DWRITE_PIXEL_GEOMETRY_RGB: + return 1; + case DWRITE_PIXEL_GEOMETRY_BGR: + return 2; + default: + return -1; + } +} + + static DWRITE_RENDERING_MODE +ToRenderingMode(int value) +{ + switch (value) + { + default: + case 0: + return DWRITE_RENDERING_MODE_DEFAULT; + case 1: + return DWRITE_RENDERING_MODE_ALIASED; + case 2: + return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC; + case 3: + return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL; + case 4: + return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; + case 5: + return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; + case 6: + return DWRITE_RENDERING_MODE_OUTLINE; + } +} + + static D2D1_TEXT_ANTIALIAS_MODE +ToTextAntialiasMode(int value) +{ + switch (value) + { + default: + case 0: + return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; + case 1: + return D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; + case 2: + return D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; + case 3: + return D2D1_TEXT_ANTIALIAS_MODE_ALIASED; + } +} + + static int +ToInt(DWRITE_RENDERING_MODE value) +{ + switch (value) + { + case DWRITE_RENDERING_MODE_DEFAULT: + return 0; + case DWRITE_RENDERING_MODE_ALIASED: + return 1; + case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC: + return 2; + case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL: + return 3; + case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL: + return 4; + case DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC: + return 5; + case DWRITE_RENDERING_MODE_OUTLINE: + return 6; + default: + return -1; + } +} + +class AdjustedGlyphRun : public DWRITE_GLYPH_RUN +{ +private: + FLOAT mDelta; + FLOAT *mAdjustedAdvances; + +public: + AdjustedGlyphRun( + const DWRITE_GLYPH_RUN *glyphRun, + FLOAT cellWidth) : + DWRITE_GLYPH_RUN(*glyphRun), + mDelta(0.0f), + mAdjustedAdvances(new FLOAT[glyphRun->glyphCount]) + { + assert(cellWidth != 0.0f); + for (UINT32 i = 0; i < glyphRun->glyphCount; ++i) + { + FLOAT orig = glyphRun->glyphAdvances[i]; + FLOAT adjusted = adjustToCell(orig, cellWidth); + mAdjustedAdvances[i] = adjusted; + mDelta += adjusted - orig; + } + glyphAdvances = mAdjustedAdvances; + } + + ~AdjustedGlyphRun(void) + { + delete[] mAdjustedAdvances; + } + + FLOAT getDelta(void) const + { + return mDelta; + } + + static FLOAT adjustToCell(FLOAT value, FLOAT cellWidth) + { + int cellCount = (int)floor(value / cellWidth + 0.5f); + if (cellCount < 1) + cellCount = 1; + return cellCount * cellWidth; + } +}; + +class GdiTextRenderer : public IDWriteTextRenderer +{ +public: + GdiTextRenderer( + IDWriteBitmapRenderTarget* bitmapRenderTarget, + IDWriteRenderingParams* renderingParams) : + cRefCount_(0), + pRenderTarget_(bitmapRenderTarget), + pRenderingParams_(renderingParams) + { + pRenderTarget_->AddRef(); + pRenderingParams_->AddRef(); + AddRef(); + } + + ~GdiTextRenderer() + { + SafeRelease(&pRenderTarget_); + SafeRelease(&pRenderingParams_); + } + + IFACEMETHOD(IsPixelSnappingDisabled)( + __maybenull void* clientDrawingContext, + __out BOOL* isDisabled) + { + *isDisabled = FALSE; + return S_OK; + } + + IFACEMETHOD(GetCurrentTransform)( + __maybenull void* clientDrawingContext, + __out DWRITE_MATRIX* transform) + { + //forward the render target's transform + pRenderTarget_->GetCurrentTransform(transform); + return S_OK; + } + + IFACEMETHOD(GetPixelsPerDip)( + __maybenull void* clientDrawingContext, + __out FLOAT* pixelsPerDip) + { + *pixelsPerDip = pRenderTarget_->GetPixelsPerDip(); + 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, + FLOAT baselineOriginY, + __in DWRITE_UNDERLINE const* underline, + IUnknown* clientDrawingEffect) + { + return E_NOTIMPL; + } + + IFACEMETHOD(DrawStrikethrough)( + __maybenull void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + __in DWRITE_STRIKETHROUGH const* strikethrough, + IUnknown* clientDrawingEffect) + { + return E_NOTIMPL; + } + + IFACEMETHOD(DrawInlineObject)( + __maybenull void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + IDWriteInlineObject* inlineObject, + BOOL isSideways, + BOOL isRightToLeft, + IUnknown* clientDrawingEffect) + { + return E_NOTIMPL; + } + +public: + IFACEMETHOD_(unsigned long, AddRef) () + { + return InterlockedIncrement(&cRefCount_); + } + + IFACEMETHOD_(unsigned long, Release) () + { + long newCount = InterlockedDecrement(&cRefCount_); + + if (newCount == 0) + { + delete this; + return 0; + } + return newCount; + } + + IFACEMETHOD(QueryInterface)( + IID const& riid, + void** ppvObject) + { + if (__uuidof(IDWriteTextRenderer) == riid) + { + *ppvObject = this; + } + else if (__uuidof(IDWritePixelSnapping) == riid) + { + *ppvObject = this; + } + else if (__uuidof(IUnknown) == riid) + { + *ppvObject = this; + } + else + { + *ppvObject = NULL; + return E_FAIL; + } + + return S_OK; + } + +private: + unsigned 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::DWriteContext() : + mDpiScaleX(1.f), + mDpiScaleY(1.f), + mDrawing(false), + mD2D1Factory(NULL), + mRT(NULL), + mBrush(NULL), + mDWriteFactory(NULL), + mGdiInterop(NULL), + mRenderingParams(NULL), + 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)); + _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); + + if (SUCCEEDED(hr)) + { + D2D1_RENDER_TARGET_PROPERTIES props = { + D2D1_RENDER_TARGET_TYPE_DEFAULT, + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, + 0, 0, + D2D1_RENDER_TARGET_USAGE_NONE, + D2D1_FEATURE_LEVEL_DEFAULT + }; + hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT); + _RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT); + } + + if (SUCCEEDED(hr)) + { + hr = mRT->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::Black), + &mBrush); + _RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush); + } + + if (SUCCEEDED(hr)) + { + hr = DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast<IUnknown**>(&mDWriteFactory)); + _RPT2(_CRT_WARN, "DWriteCreateFactory: hr=%p p=%p\n", hr, + mDWriteFactory); + } + + if (SUCCEEDED(hr)) + { + hr = mDWriteFactory->GetGdiInterop(&mGdiInterop); + _RPT2(_CRT_WARN, "GetGdiInterop: hr=%p p=%p\n", hr, mGdiInterop); + } + + if (SUCCEEDED(hr)) + { + hr = mDWriteFactory->CreateRenderingParams(&mRenderingParams); + _RPT2(_CRT_WARN, "CreateRenderingParams: hr=%p p=%p\n", hr, + mRenderingParams); + } +} + +DWriteContext::~DWriteContext() +{ + SafeRelease(&mTextFormat); + SafeRelease(&mRenderingParams); + SafeRelease(&mGdiInterop); + SafeRelease(&mDWriteFactory); + SafeRelease(&mBrush); + SafeRelease(&mRT); + SafeRelease(&mD2D1Factory); +} + + HRESULT +DWriteContext::SetLOGFONT(const LOGFONTW &logFont, float fontSize) +{ + // Most of this function is copy from: http://msdn.microsoft.com/en-us/library/windows/desktop/dd941783(v=vs.85).aspx + HRESULT hr = S_OK; + + IDWriteFont *font = NULL; + IDWriteFontFamily *fontFamily = NULL; + IDWriteLocalizedStrings *localizedFamilyNames = NULL; + + if (SUCCEEDED(hr)) + { + hr = mGdiInterop->CreateFontFromLOGFONT(&logFont, &font); + } + + // Get the font family to which this font belongs. + if (SUCCEEDED(hr)) + { + hr = font->GetFontFamily(&fontFamily); + } + + // Get the family names. This returns an object that encapsulates one or + // more names with the same meaning but in different languages. + if (SUCCEEDED(hr)) + { + hr = fontFamily->GetFamilyNames(&localizedFamilyNames); + } + + // Get the family name at index zero. If we were going to display the name + // we'd want to try to find one that matched the use locale, but for + // purposes of creating a text format object any language will do. + + wchar_t familyName[100]; + if (SUCCEEDED(hr)) + { + hr = localizedFamilyNames->GetString(0, familyName, + ARRAYSIZE(familyName)); + } + + if (SUCCEEDED(hr)) + { + // If no font size was passed in use the lfHeight of the LOGFONT. + 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; + } + } + } + + // The text format includes a locale name. Ideally, this would be the + // language of the text, which may or may not be the same as the primary + // language of the user. However, for our purposes the user locale will do. + wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; + if (SUCCEEDED(hr)) + { + if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0) + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + // Create the text format object. + hr = mDWriteFactory->CreateTextFormat( + familyName, + NULL, // no custom font collection + font->GetWeight(), + font->GetStyle(), + font->GetStretch(), + fontSize, + localeName, + &mTextFormat); + } + + if (SUCCEEDED(hr)) + { + 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) + { + LOGFONTW lf; + if (GetObjectW(hFont, sizeof(lf), &lf)) + { + SetFont(lf); + mLastHFont = hFont; + } + } +} + + void +DWriteContext::SetFont(const LOGFONTW &logFont) +{ + SafeRelease(&mTextFormat); + mLastHFont = NULL; + + HRESULT hr = SetLOGFONT(logFont, 0.f); + + if (SUCCEEDED(hr)) + hr = mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); + + if (SUCCEEDED(hr)) + hr = mTextFormat->SetParagraphAlignment( + DWRITE_PARAGRAPH_ALIGNMENT_CENTER); + + if (SUCCEEDED(hr)) + hr = mTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); +} + + void +DWriteContext::DrawText(HDC hdc, const WCHAR* text, int len, + int x, int y, int w, int h, int cellWidth, COLORREF color) +{ + HRESULT hr = S_OK; + IDWriteBitmapRenderTarget *bmpRT = NULL; + + // Skip when any fonts are not set. + if (mTextFormat == NULL) + return; + + // Check possibility of zero divided error. + if (cellWidth == 0 || mDpiScaleX == 0.0f || mDpiScaleX == 0.0f) + return; + + if (SUCCEEDED(hr)) + hr = mGdiInterop->CreateBitmapRenderTarget(hdc, w, h, &bmpRT); + + 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, 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); + } + + BitBlt(hdc, x, y, w, h, memdc, 0, 0, SRCCOPY); + + SafeRelease(&textLayout); + } + + SafeRelease(&bmpRT); +} + + float +DWriteContext::PixelsToDipsX(int x) +{ + return x / mDpiScaleX; +} + + float +DWriteContext::PixelsToDipsY(int y) +{ + return y / mDpiScaleY; +} + + void +DWriteContext::SetRenderingParams( + const DWriteRenderingParams *params) +{ + if (mDWriteFactory == NULL) + return; + + IDWriteRenderingParams *renderingParams = NULL; + D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode = + D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; + HRESULT hr; + if (params != NULL) + { + hr = mDWriteFactory->CreateCustomRenderingParams(params->gamma, + params->enhancedContrast, params->clearTypeLevel, + ToPixelGeometry(params->pixelGeometry), + ToRenderingMode(params->renderingMode), &renderingParams); + textAntialiasMode = ToTextAntialiasMode(params->textAntialiasMode); + } + else + hr = mDWriteFactory->CreateRenderingParams(&renderingParams); + if (SUCCEEDED(hr) && renderingParams != NULL) + { + SafeRelease(&mRenderingParams); + mRenderingParams = renderingParams; + mTextAntialiasMode = textAntialiasMode; + } +} + + DWriteRenderingParams * +DWriteContext::GetRenderingParams( + DWriteRenderingParams *params) +{ + if (params != NULL && mRenderingParams != NULL) + { + params->gamma = mRenderingParams->GetGamma(); + params->enhancedContrast = mRenderingParams->GetEnhancedContrast(); + params->clearTypeLevel = mRenderingParams->GetClearTypeLevel(); + params->pixelGeometry = ToInt(mRenderingParams->GetPixelGeometry()); + params->renderingMode = ToInt(mRenderingParams->GetRenderingMode()); + params->textAntialiasMode = mTextAntialiasMode; + } + return params; +} + +//////////////////////////////////////////////////////////////////////////// +// PUBLIC C INTERFACES + + void +DWrite_Init(void) +{ +#ifdef DYNAMIC_DIRECTX + // Load libraries. + hD2D1DLL = vimLoadLib(const_cast<char*>("d2d1.dll")); + hDWriteDLL = vimLoadLib(const_cast<char*>("dwrite.dll")); + if (hD2D1DLL == NULL || hDWriteDLL == NULL) + { + DWrite_Final(); + return; + } + // Get address of procedures. + pGetUserDefaultLocaleName = (PGETUSERDEFAULTLOCALENAME)GetProcAddress( + GetModuleHandle("kernel32.dll"), "GetUserDefaultLocaleName"); + pD2D1CreateFactory = (PD2D1CREATEFACTORY)GetProcAddress(hD2D1DLL, + "D2D1CreateFactory"); + pDWriteCreateFactory = (PDWRITECREATEFACTORY)GetProcAddress(hDWriteDLL, + "DWriteCreateFactory"); +#endif +} + + void +DWrite_Final(void) +{ +#ifdef DYNAMIC_DIRECTX + pGetUserDefaultLocaleName = NULL; + pD2D1CreateFactory = NULL; + pDWriteCreateFactory = NULL; + unload(hDWriteDLL); + unload(hD2D1DLL); +#endif +} + + DWriteContext * +DWriteContext_Open(void) +{ +#ifdef DYNAMIC_DIRECTX + if (pGetUserDefaultLocaleName == NULL || pD2D1CreateFactory == NULL + || pDWriteCreateFactory == NULL) + return NULL; +#endif + return new DWriteContext(); +} + + 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); + } +} + + 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, + int y, + int w, + int h, + int cellWidth, + COLORREF color) +{ + if (ctx != NULL) + ctx->DrawText(hdc, text, len, x, y, w, h, cellWidth, color); +} + + void +DWriteContext_EndDraw(DWriteContext *ctx) +{ + if (ctx != NULL && ctx->mRT != NULL) + { + ctx->mRT->EndDraw(); + ctx->mDrawing = false; + } +} + + void +DWriteContext_Close(DWriteContext *ctx) +{ + delete ctx; +} + + void +DWriteContext_SetRenderingParams( + DWriteContext *ctx, + const DWriteRenderingParams *params) +{ + if (ctx != NULL) + ctx->SetRenderingParams(params); +} + + DWriteRenderingParams * +DWriteContext_GetRenderingParams( + DWriteContext *ctx, + DWriteRenderingParams *params) +{ + if (ctx != NULL) + return ctx->GetRenderingParams(params); + else + return NULL; +} diff -r 73ed2bb6def5 src/gui_dwrite.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui_dwrite.h Wed Apr 03 01:57:32 2013 +0900 @@ -0,0 +1,76 @@ +/* vi:set ts=8 sts=4 sw=4 noet: */ + +#ifndef GUI_DWRITE_H +#define GUI_DWRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DWriteContext DWriteContext; + +typedef struct DWriteRenderingParams { + float gamma; + float enhancedContrast; + float clearTypeLevel; + /* + * pixelGeometry: + * 0 - DWRITE_PIXEL_GEOMETRY_FLAT + * 1 - DWRITE_PIXEL_GEOMETRY_RGB + * 2 - DWRITE_PIXEL_GEOMETRY_BGR + */ + int pixelGeometry; + /* + * renderingMode: + * 0 - DWRITE_RENDERING_MODE_DEFAULT + * 1 - DWRITE_RENDERING_MODE_ALIASED + * 2 - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC + * 3 - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL + * 4 - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL + * 5 - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC + * 6 - DWRITE_RENDERING_MODE_OUTLINE + */ + int renderingMode; + /* + * antialiasMode: + * 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT + * 1 - D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE + * 2 - D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE + * 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED + */ + int textAntialiasMode; +} DWriteRenderingParams; + +void DWrite_Init(void); +void DWrite_Final(void); + +DWriteContext *DWriteContext_Open(void); +void DWriteContext_BeginDraw(DWriteContext *ctx); +void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect); +void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); +void DWriteContext_DrawText( + DWriteContext *ctx, + HDC hdc, + const WCHAR* text, + int len, + int x, + int y, + int w, + int h, + int cellWidth, + COLORREF color); +void DWriteContext_EndDraw(DWriteContext *ctx); +void DWriteContext_Close(DWriteContext *ctx); + +void DWriteContext_SetRenderingParams( + DWriteContext *ctx, + const DWriteRenderingParams *params); + +DWriteRenderingParams *DWriteContext_GetRenderingParams( + DWriteContext *ctx, + DWriteRenderingParams *params); + +#ifdef __cplusplus +} +#endif +#endif/*GUI_DWRITE_H*/ diff -r 73ed2bb6def5 src/gui_w32.c --- a/src/gui_w32.c Sun Mar 24 10:08:39 2013 +0900 +++ b/src/gui_w32.c Wed Apr 03 01:57:32 2013 +0900 @@ -25,6 +25,145 @@ #include "vim.h" +#if defined(FEAT_DIRECTX) +# include "gui_dwrite.h" +#endif + +#if defined(FEAT_DIRECTX) +static DWriteContext *s_dwc = NULL; +static int s_directx_enabled = 0; +static int s_directx_load_attempted = 0; +# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL) + + int +directx_enabled(void) +{ + if (s_dwc != NULL) + return 1; + else if (s_directx_load_attempted) + return 0; + /* load DirectX */ + DWrite_Init(); + s_directx_load_attempted = 1; + s_dwc = DWriteContext_Open(); + return s_dwc != NULL ? 1 : 0; +} +#endif + +#ifdef FEAT_RENDER_OPTIONS + int +gui_mch_set_rendering_options(char_u *s) +{ +#ifdef FEAT_DIRECTX + int retval = FAIL; + char_u *p, *q; + + int dx_enable = 0; + int dx_flags = 0; + float dx_gamma = 0.0f; + float dx_contrast = 0.0f; + float dx_level = 0.0f; + int dx_geom = 0; + int dx_renmode = 0; + int dx_taamode = 0; + + /* parse string as rendering options. */ + for (p = s; p != NULL && *p != NUL; ) + { + char_u item[256]; + char_u name[128]; + char_u value[128]; + + copy_option_part(&p, item, sizeof(item), ","); + if (p == NULL) + break; + q = &item[0]; + copy_option_part(&q, name, sizeof(name), ":"); + if (q == NULL) + return FAIL; + copy_option_part(&q, value, sizeof(value), ":"); + + if (STRCMP(name, "type") == 0) + { + if (STRCMP(value, "directx") == 0) + dx_enable = 1; + else + return FAIL; + } + else if (STRCMP(name, "gamma") == 0) + { + dx_flags |= 1 << 0; + dx_gamma = (float)atof(value); + } + else if (STRCMP(name, "contrast") == 0) + { + dx_flags |= 1 << 1; + dx_contrast = (float)atof(value); + } + else if (STRCMP(name, "level") == 0) + { + dx_flags |= 1 << 2; + dx_level = (float)atof(value); + } + else if (STRCMP(name, "geom") == 0) + { + dx_flags |= 1 << 3; + dx_geom = atoi(value); + if (dx_geom < 0 || dx_geom > 2) + return FAIL; + } + else if (STRCMP(name, "renmode") == 0) + { + dx_flags |= 1 << 4; + dx_renmode = atoi(value); + if (dx_renmode < 0 || dx_renmode > 6) + return FAIL; + } + else if (STRCMP(name, "taamode") == 0) + { + dx_flags |= 1 << 5; + dx_taamode = atoi(value); + if (dx_taamode < 0 || dx_taamode > 3) + return FAIL; + } + else + return FAIL; + } + + /* Enable DirectX/DirectWrite */ + if (dx_enable) + { + if (!directx_enabled()) + return FAIL; + DWriteContext_SetRenderingParams(s_dwc, NULL); + if (dx_flags) + { + DWriteRenderingParams param; + DWriteContext_GetRenderingParams(s_dwc, ¶m); + if (dx_flags & (1 << 0)) + param.gamma = dx_gamma; + if (dx_flags & (1 << 1)) + param.enhancedContrast = dx_contrast; + if (dx_flags & (1 << 2)) + param.clearTypeLevel = dx_level; + if (dx_flags & (1 << 3)) + param.pixelGeometry = dx_geom; + if (dx_flags & (1 << 4)) + param.renderingMode = dx_renmode; + if (dx_flags & (1 << 5)) + param.textAntialiasMode = dx_taamode; + DWriteContext_SetRenderingParams(s_dwc, ¶m); + } + } + s_directx_enabled = dx_enable; + + return OK; +#else + return FAIL; +#endif +} +#endif + /* * These are new in Windows ME/XP, only defined in recent compilers. */ @@ -1679,6 +1818,11 @@ set_vim_var_nr(VV_WINDOWID, HandleToLong(s_hwnd)); #endif +#ifdef FEAT_RENDER_OPTIONS + if (p_rop) + (void)gui_mch_set_rendering_options(p_rop); +#endif + theend: /* Display any pending error messages */ display_errors(); @@ -2332,6 +2476,9 @@ #endif HPEN hpen, old_pen; int y; +#ifdef FEAT_DIRECTX + int font_is_ttf_or_vector = 0; +#endif #ifndef MSWIN16_FASTTEXT /* @@ -2419,6 +2566,20 @@ SetTextColor(s_hdc, gui.currFgColor); SelectFont(s_hdc, gui.currFont); +#ifdef FEAT_DIRECTX + if (IS_ENABLE_DIRECTX()) + { + TEXTMETRIC tm; + + GetTextMetrics(s_hdc, &tm); + if (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) + { + font_is_ttf_or_vector = 1; + DWriteContext_SetFont(s_dwc, (HFONT)gui.currFont); + } + } +#endif + if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width) { vim_free(padding); @@ -2453,6 +2614,14 @@ if (text[n] >= 0x80) break; +#if defined(FEAT_DIRECTX) + /* Quick hack to enable DirectWrite. To use DirectWrite (antialias), it is + * required that unicode drawing routine, currently. So this forces it + * enabled. */ + if (enc_utf8 && IS_ENABLE_DIRECTX()) + n = 0; /* Keep n < len, to enter block for unicode. */ +#endif + /* Check if the Unicode buffer exists and is big enough. Create it * with the same length as the multi-byte string, the number of wide * characters is always equal or smaller. */ @@ -2511,8 +2680,17 @@ i += utfc_ptr2len_len(text + i, len - i); ++clen; } - ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row), - foptions, pcliprect, unicodebuf, wlen, unicodepdy); +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX() && font_is_ttf_or_vector) + { + DWriteContext_DrawText(s_dwc, s_hdc, unicodebuf, wlen, + TEXT_X(col), TEXT_Y(row), FILL_X(cells), FILL_Y(1), + gui.char_width, gui.currFgColor); + } + else +#endif + ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row), + foptions, pcliprect, unicodebuf, wlen, unicodepdy); len = cells; /* used for underlining */ } else if ((enc_codepage > 0 && (int)GetACP() != enc_codepage) || enc_latin9) diff -r 73ed2bb6def5 src/gui_w48.c --- a/src/gui_w48.c Sun Mar 24 10:08:39 2013 +0900 +++ b/src/gui_w48.c Wed Apr 03 01:57:32 2013 +0900 @@ -2778,6 +2778,10 @@ out_flush(); /* make sure all output has been processed */ (void)BeginPaint(hwnd, &ps); +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_BeginDraw(s_dwc); +#endif #ifdef FEAT_MBYTE /* prevent multi-byte characters from misprinting on an invalid @@ -2793,9 +2797,20 @@ #endif if (!IsRectEmpty(&ps.rcPaint)) + { +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint); +#endif gui_redraw(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left + 1, ps.rcPaint.bottom - ps.rcPaint.top + 1); + } + +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_EndDraw(s_dwc); +#endif EndPaint(hwnd, &ps); } } @@ -3034,6 +3049,12 @@ void gui_mch_exit(int rc) { +#if defined(FEAT_DIRECTX) + DWriteContext_Close(s_dwc); + DWrite_Final(); + s_dwc = NULL; +#endif + ReleaseDC(s_textArea, s_hdc); DeleteObject(s_brush); diff -r 73ed2bb6def5 src/option.c --- a/src/option.c Sun Mar 24 10:08:39 2013 +0900 +++ b/src/option.c Wed Apr 03 01:57:32 2013 +0900 @@ -2102,6 +2102,11 @@ {"remap", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_remap, PV_NONE, {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, +#ifdef FEAT_RENDER_OPTIONS + {"renderoptions", "rop", P_STRING|P_COMMA|P_RCLR|P_VI_DEF, + (char_u *)&p_rop, PV_NONE, + {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, +#endif {"report", NULL, P_NUM|P_VI_DEF, (char_u *)&p_report, PV_NONE, {(char_u *)2L, (char_u *)0L} SCRIPTID_INIT}, @@ -6998,6 +7003,16 @@ } #endif +#if defined(FEAT_GUI) && defined(FEAT_RENDER_OPTIONS) + else if (varp == &p_rop && gui.in_use) + { + int gui_mch_set_rendering_options(char_u *); + + if (!gui_mch_set_rendering_options(p_rop)) + errmsg = e_invarg; + } +#endif + /* Options that are a list of flags. */ else { diff -r 73ed2bb6def5 src/option.h --- a/src/option.h Sun Mar 24 10:08:39 2013 +0900 +++ b/src/option.h Wed Apr 03 01:57:32 2013 +0900 @@ -661,6 +661,9 @@ EXTERN long p_rdt; /* 'redrawtime' */ #endif EXTERN int p_remap; /* 'remap' */ +#ifdef FEAT_RENDER_OPTIONS +EXTERN char_u *p_rop; /* 'renderoptions' */ +#endif EXTERN long p_report; /* 'report' */ #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) EXTERN long p_pvh; /* 'previewheight' */ diff -r 73ed2bb6def5 src/version.c --- a/src/version.c Sun Mar 24 10:08:39 2013 +0900 +++ b/src/version.c Wed Apr 03 01:57:32 2013 +0900 @@ -185,6 +185,13 @@ #else "-digraphs", #endif +#ifdef FEAT_GUI_W32 +# ifdef FEAT_DIRECTX + "+directx", +# else + "-directx", +# endif +#endif #ifdef FEAT_DND "+dnd", #else diff -r 73ed2bb6def5 src/vim.h --- a/src/vim.h Sun Mar 24 10:08:39 2013 +0900 +++ b/src/vim.h Wed Apr 03 01:57:32 2013 +0900 @@ -127,6 +127,13 @@ # endif #endif +/* Check support for rendering options */ +#ifdef FEAT_GUI +# if defined(FEAT_DIRECTX) +# define FEAT_RENDER_OPTIONS +# endif +#endif + /* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */ #if _MSC_VER >= 1400 # define _CRT_SECURE_NO_DEPRECATE