diff options
Diffstat (limited to 'win32/ScintillaWin.cxx')
-rw-r--r-- | win32/ScintillaWin.cxx | 180 |
1 files changed, 146 insertions, 34 deletions
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index d1f450479..a3c141aff 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -24,6 +24,9 @@ #include <richedit.h> #include <windowsx.h> +#include <d2d1.h> +#include <dwrite.h> + #include "Platform.h" #include "ILexer.h" @@ -54,6 +57,7 @@ #include "Editor.h" #include "ScintillaBase.h" #include "UniConversion.h" +#include "PlatWin.h" #ifdef SCI_LEXER #include "ExternalLexer.h" @@ -87,11 +91,6 @@ #define SC_WIN_IDLE 5001 -// Functions imported from PlatWin -extern bool IsNT(); -extern void Platform_Initialise(void *hInstance); -extern void Platform_Finalise(); - typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT); // GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables. @@ -197,6 +196,8 @@ class ScintillaWin : static HINSTANCE hInstance; + ID2D1HwndRenderTarget *pRenderTarget; + ScintillaWin(HWND hwnd); ScintillaWin(const ScintillaWin &); virtual ~ScintillaWin(); @@ -204,6 +205,8 @@ class ScintillaWin : virtual void Initialise(); virtual void Finalise(); + void EnsureRenderTarget(); + void DropRenderTarget(); HWND MainHWND(); static sptr_t DirectFunction( @@ -350,6 +353,8 @@ ScintillaWin::ScintillaWin(HWND hwnd) { sysCaretWidth = 0; sysCaretHeight = 0; + pRenderTarget = 0; + keysAlwaysUnicode = false; caret.period = ::GetCaretBlinkTime(); @@ -384,12 +389,46 @@ void ScintillaWin::Finalise() { ScintillaBase::Finalise(); SetTicking(false); SetIdle(false); + DropRenderTarget(); ::RevokeDragDrop(MainHWND()); if (SUCCEEDED(hrOle)) { ::OleUninitialize(); } } +void ScintillaWin::EnsureRenderTarget() { + if (pD2DFactory && !pRenderTarget) { + RECT rc; + HWND hw = MainHWND(); + GetClientRect(hw, &rc); + + D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); + + // Create a Direct2D render target. +#if 1 + pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties(), + D2D1::HwndRenderTargetProperties(hw, size), + &pRenderTarget); +#else + pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT , + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), + 96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), + D2D1::HwndRenderTargetProperties(hw, size), + &pRenderTarget); +#endif + } +} + +void ScintillaWin::DropRenderTarget() { + if (pRenderTarget) { + pRenderTarget->Release(); + pRenderTarget = 0; + } +} + HWND ScintillaWin::MainHWND() { return reinterpret_cast<HWND>(wMain.GetID()); } @@ -505,18 +544,35 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { pps = &ps; ::BeginPaint(MainHWND(), pps); } - AutoSurface surfaceWindow(pps->hdc, this); - if (surfaceWindow) { - rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); - PRectangle rcClient = GetClientRectangle(); - paintingAllText = rcPaint.Contains(rcClient); - if (paintingAllText) { - //Platform::DebugPrintf("Performing full text paint\n"); - } else { - //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom); + if (technology == SC_TECHNOLOGY_DEFAULT) { + AutoSurface surfaceWindow(pps->hdc, this); + if (surfaceWindow) { + rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); + PRectangle rcClient = GetClientRectangle(); + paintingAllText = rcPaint.Contains(rcClient); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + } + } else { + EnsureRenderTarget(); + AutoSurface surfaceWindow(pRenderTarget, this); + if (surfaceWindow) { + pRenderTarget->BeginDraw(); + rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); + PRectangle rcClient = GetClientRectangle(); + paintingAllText = rcPaint.Contains(rcClient); + if (paintingAllText) { + //Platform::DebugPrintf("Performing full text paint\n"); + } else { + //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom); + } + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + HRESULT hr = pRenderTarget->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) { + DropRenderTarget(); + } } - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); } if (hRgnUpdate) { ::DeleteRgn(hRgnUpdate); @@ -674,6 +730,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam break; case WM_SIZE: { + DropRenderTarget(); //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam)); ChangeSize(); } @@ -1085,6 +1142,22 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case SCI_GETKEYSUNICODE: return keysAlwaysUnicode; + + case SCI_SETTECHNOLOGY: + if ((wParam == SC_TECHNOLOGY_DEFAULT) || (wParam == SC_TECHNOLOGY_DIRECTWRITE)) { + if (technology != static_cast<int>(wParam)) { + if (static_cast<int>(wParam) == SC_TECHNOLOGY_DIRECTWRITE) { + if (!LoadD2D()) + // Failed to load Direct2D or DirectWrite so no effect + return 0; + } + technology = wParam; + // Invalidate all cached information including layout. + DropGraphics(true); + InvalidateStyleRedraw(); + } + } + break; #ifdef SCI_LEXER case SCI_LOADLEXERLIBRARY: @@ -1196,11 +1269,12 @@ bool ScintillaWin::PaintContains(PRectangle rc) { return contains; } -void ScintillaWin::ScrollText(int linesToMove) { +void ScintillaWin::ScrollText(int /* linesToMove */) { //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove); - ::ScrollWindow(MainHWND(), 0, - vs.lineHeight * linesToMove, 0, 0); - ::UpdateWindow(MainHWND()); + //::ScrollWindow(MainHWND(), 0, + // vs.lineHeight * linesToMove, 0, 0); + //::UpdateWindow(MainHWND()); + Redraw(); } void ScintillaWin::UpdateSystemCaret() { @@ -2085,9 +2159,9 @@ void ScintillaWin::ImeStartComposition() { // The logfont for the IME is recreated here. int styleHere = (pdoc->StyleAt(sel.MainCaret())) & 31; LOGFONTA lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""}; - int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel; - if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1 - sizeZoomed = 2; + int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER; + if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 + sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; AutoSurface surface(this); int deviceHeight = sizeZoomed; if (surface) { @@ -2095,7 +2169,7 @@ void ScintillaWin::ImeStartComposition() { } // The negative is to allow for leading lf.lfHeight = -(abs(deviceHeight)); - lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL; + lf.lfWeight = vs.styles[styleHere].weight; lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0); lf.lfCharSet = DEFAULT_CHARSET; lf.lfFaceName[0] = '\0'; @@ -2290,7 +2364,9 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) { HorizontalScrollTo(xPos); } -void ScintillaWin::RealizeWindowPalette(bool inBackGround) { +void ScintillaWin::RealizeWindowPalette(bool) { + // No support for palette with D2D +/* RefreshStyleData(); HDC hdc = ::GetDC(MainHWND()); // Select a stock font to prevent warnings from BoundsChecker @@ -2303,6 +2379,7 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) { surfaceWindow->Release(); } ::ReleaseDC(MainHWND(), hdc); +*/ } /** @@ -2310,9 +2387,13 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) { * This paint will not be abandoned. */ void ScintillaWin::FullPaint() { - HDC hdc = ::GetDC(MainHWND()); - FullPaintDC(hdc); - ::ReleaseDC(MainHWND(), hdc); + if (technology == SC_TECHNOLOGY_DEFAULT) { + HDC hdc = ::GetDC(MainHWND()); + FullPaintDC(hdc); + ::ReleaseDC(MainHWND(), hdc); + } else { + FullPaintDC(0); + } } /** @@ -2323,10 +2404,24 @@ void ScintillaWin::FullPaintDC(HDC hdc) { paintState = painting; rcPaint = GetClientRectangle(); paintingAllText = true; - AutoSurface surfaceWindow(hdc, this); - if (surfaceWindow) { - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); + if (technology == SC_TECHNOLOGY_DEFAULT) { + AutoSurface surfaceWindow(hdc, this); + if (surfaceWindow) { + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + } + } else { + EnsureRenderTarget(); + AutoSurface surfaceWindow(pRenderTarget, this); + if (surfaceWindow) { + pRenderTarget->BeginDraw(); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + HRESULT hr = pRenderTarget->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) { + DropRenderTarget(); + } + } } paintState = notPainting; } @@ -2698,14 +2793,31 @@ sptr_t PASCAL ScintillaWin::CTWndProc( } else if (iMessage == WM_PAINT) { PAINTSTRUCT ps; ::BeginPaint(hWnd, &ps); - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(sciThis->technology); if (surfaceWindow) { - surfaceWindow->Init(ps.hdc, hWnd); + ID2D1HwndRenderTarget *pCTRenderTarget = 0; + RECT rc; + GetClientRect(hWnd, &rc); + // Create a Direct2D render target. + if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) { + surfaceWindow->Init(ps.hdc, hWnd); + } else { + pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties(), + D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)), + &pCTRenderTarget); + surfaceWindow->Init(pCTRenderTarget, hWnd); + pCTRenderTarget->BeginDraw(); + } surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage); surfaceWindow->SetDBCSMode(sciThis->ct.codePage); sciThis->ct.PaintCT(surfaceWindow); + if (pCTRenderTarget) + pCTRenderTarget->EndDraw(); surfaceWindow->Release(); delete surfaceWindow; + if (pCTRenderTarget) + pCTRenderTarget->Release(); } ::EndPaint(hWnd, &ps); return 0; |