aboutsummaryrefslogtreecommitdiffhomepage
path: root/win32/PlatWin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win32/PlatWin.cxx')
-rw-r--r--win32/PlatWin.cxx1214
1 files changed, 1030 insertions, 184 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 4d937ac81..3317dc0d3 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -26,6 +26,8 @@
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>
+#include <d2d1.h>
+#include <dwrite.h>
#include "Platform.h"
#include "UniConversion.h"
@@ -195,6 +197,88 @@ void Palette::Allocate(Window &) {
}
}
+IDWriteFactory *pIDWriteFactory = 0;
+ID2D1Factory *pD2DFactory = 0;
+
+bool LoadD2D() {
+ static bool triedLoadingD2D = false;
+ static HMODULE hDLLD2D = 0;
+ static HMODULE hDLLDWrite = 0;
+ if (!triedLoadingD2D) {
+ typedef HRESULT (WINAPI *D2D1CFSig)(D2D1_FACTORY_TYPE factoryType, REFIID riid,
+ CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, IUnknown **factory);
+ typedef HRESULT (WINAPI *DWriteCFSig)(DWRITE_FACTORY_TYPE factoryType, REFIID iid,
+ IUnknown **factory);
+
+ hDLLD2D = ::LoadLibrary(TEXT("D2D1.DLL"));
+ if (hDLLD2D) {
+ D2D1CFSig fnD2DCF = (D2D1CFSig)::GetProcAddress(hDLLD2D, "D2D1CreateFactory");
+ if (fnD2DCF) {
+ // A single threaded factory as Scintilla always draw on the GUI thread
+ fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ __uuidof(ID2D1Factory),
+ 0,
+ reinterpret_cast<IUnknown**>(&pD2DFactory));
+ }
+ }
+ hDLLDWrite = ::LoadLibrary(TEXT("DWRITE.DLL"));
+ if (hDLLDWrite) {
+ DWriteCFSig fnDWCF = (DWriteCFSig)::GetProcAddress(hDLLDWrite, "DWriteCreateFactory");
+ if (fnDWCF) {
+ fnDWCF(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown**>(&pIDWriteFactory));
+ }
+ }
+ }
+ triedLoadingD2D = true;
+ return pIDWriteFactory && pD2DFactory;
+}
+
+struct FormatAndMetrics {
+ int technology;
+ HFONT hfont;
+ IDWriteTextFormat *pTextFormat;
+ int extraFontFlag;
+ FLOAT yAscent;
+ FLOAT yDescent;
+ FormatAndMetrics(HFONT hfont_, int extraFontFlag_) :
+ technology(SCWIN_TECH_GDI), hfont(hfont_), pTextFormat(0), extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1) {
+ }
+ FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_) :
+ technology(SCWIN_TECH_DIRECTWRITE), hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) {
+ }
+ ~FormatAndMetrics() {
+ if (hfont)
+ ::DeleteObject(hfont);
+ if (pTextFormat)
+ pTextFormat->Release();
+ pTextFormat = 0;
+ extraFontFlag = 0;
+ yAscent = 2;
+ yDescent = 1;
+ }
+ HFONT HFont();
+};
+
+HFONT FormatAndMetrics::HFont() {
+ if (technology == SCWIN_TECH_GDI) {
+ return hfont;
+ } else {
+ LOGFONTW lf;
+ memset(&lf, 0, sizeof(lf));
+
+ HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE);
+ if (SUCCEEDED(hr)) {
+ lf.lfWeight = pTextFormat->GetFontWeight();
+ lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC;
+ lf.lfHeight = -static_cast<int>(pTextFormat->GetFontSize());
+ return ::CreateFontIndirectW(&lf);
+ }
+ }
+ return 0;
+}
+
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
@@ -216,11 +300,28 @@ static BYTE Win32MapFontQuality(int extraFontFlag) {
}
}
-static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+static D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) {
+ switch (extraFontFlag & SC_EFF_QUALITY_MASK) {
+
+ case SC_EFF_QUALITY_NON_ANTIALIASED:
+ return D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
+
+ case SC_EFF_QUALITY_ANTIALIASED:
+ return D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
+
+ case SC_EFF_QUALITY_LCD_OPTIMIZED:
+ return D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+
+ default:
+ return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
+ }
+}
+
+static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) {
memset(&lf, 0, sizeof(lf));
// The negative is to allow for leading
- lf.lfHeight = -(abs(size));
- lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
+ lf.lfHeight = -(abs(static_cast<int>(size + 0.5)));
+ lf.lfWeight = weight;
lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
lf.lfCharSet = static_cast<BYTE>(characterSet);
lf.lfQuality = Win32MapFontQuality(extraFontFlag);
@@ -232,71 +333,111 @@ static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int
* If one font is the same as another, its hash will be the same, but if the hash is the
* same then they may still be different.
*/
-static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+static int HashFont(const FontParameters &fp) {
return
- size ^
- (characterSet << 10) ^
- ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
- (bold ? 0x10000000 : 0) ^
- (italic ? 0x20000000 : 0) ^
- faceName[0];
+ static_cast<int>(fp.size) ^
+ (fp.characterSet << 10) ^
+ ((fp.extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
+ ((fp.weight/100) << 12) ^
+ (fp.italic ? 0x20000000 : 0) ^
+ (fp.technology << 15) ^
+ fp.faceName[0];
}
class FontCached : Font {
FontCached *next;
int usage;
+ float size;
LOGFONTA lf;
+ int technology;
int hash;
- FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ FontCached(const FontParameters &fp);
~FontCached() {}
- bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ bool SameAs(const FontParameters &fp);
virtual void Release();
static FontCached *first;
public:
- static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ static FontID FindOrCreate(const FontParameters &fp);
static void ReleaseId(FontID fid_);
};
FontCached *FontCached::first = 0;
-FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) :
- next(0), usage(0), hash(0) {
- SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
- hash = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
- fid = ::CreateFontIndirectA(&lf);
+FontCached::FontCached(const FontParameters &fp) :
+ next(0), usage(0), size(1.0), hash(0) {
+ SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag);
+ technology = fp.technology;
+ hash = HashFont(fp);
+ fid = 0;
+ if (technology == SCWIN_TECH_GDI) {
+ HFONT hfont = ::CreateFontIndirectA(&lf);
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag));
+ } else {
+ IDWriteTextFormat *pTextFormat;
+ const int faceSize = 200;
+ WCHAR wszFace[faceSize];
+ UTF16FromUTF8(fp.faceName, strlen(fp.faceName)+1, wszFace, faceSize);
+ FLOAT fHeight = fp.size;
+ DWRITE_FONT_STYLE style = fp.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
+ HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL,
+ static_cast<DWRITE_FONT_WEIGHT>(fp.weight),
+ style,
+ DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat);
+ if (SUCCEEDED(hr)) {
+ pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
+
+ const int maxLines = 2;
+ DWRITE_LINE_METRICS lineMetrics[maxLines];
+ UINT32 lineCount = 0;
+ FLOAT yAscent = 1.0f;
+ FLOAT yDescent = 1.0f;
+ IDWriteTextLayout *pTextLayout = 0;
+ hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat,
+ 100.0f, 100.0f, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount);
+ if (SUCCEEDED(hr)) {
+ yAscent = lineMetrics[0].baseline;
+ yDescent = lineMetrics[0].height - lineMetrics[0].baseline;
+ }
+ pTextLayout->Release();
+ }
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, yAscent, yDescent));
+ }
+ }
usage = 1;
}
-bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+bool FontCached::SameAs(const FontParameters &fp) {
return
- (lf.lfHeight == -(abs(size_))) &&
- (lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) &&
- (lf.lfItalic == static_cast<BYTE>(italic_ ? 1 : 0)) &&
- (lf.lfCharSet == characterSet_) &&
- (lf.lfQuality == Win32MapFontQuality(extraFontFlag_)) &&
- 0 == strcmp(lf.lfFaceName,faceName_);
+ (size == fp.size) &&
+ (lf.lfWeight == fp.weight) &&
+ (lf.lfItalic == static_cast<BYTE>(fp.italic ? 1 : 0)) &&
+ (lf.lfCharSet == fp.characterSet) &&
+ (lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) &&
+ (technology == fp.technology) &&
+ 0 == strcmp(lf.lfFaceName,fp.faceName);
}
void FontCached::Release() {
- if (fid)
- ::DeleteObject(fid);
+ delete reinterpret_cast<FormatAndMetrics *>(fid);
fid = 0;
}
-FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+FontID FontCached::FindOrCreate(const FontParameters &fp) {
FontID ret = 0;
::EnterCriticalSection(&crPlatformLock);
- int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ int hashFind = HashFont(fp);
for (FontCached *cur=first; cur; cur=cur->next) {
if ((cur->hash == hashFind) &&
- cur->SameAs(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_)) {
+ cur->SameAs(fp)) {
cur->usage++;
ret = cur->fid;
}
}
if (ret == 0) {
- FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ FontCached *fc = new FontCached(fp);
if (fc) {
fc->next = first;
first = fc;
@@ -335,35 +476,62 @@ Font::~Font() {
#define FONTS_CACHED
-void Font::Create(const char *faceName, int characterSet, int size,
- bool bold, bool italic, int extraFontFlag) {
+void Font::Create(const FontParameters &fp) {
Release();
-#ifndef FONTS_CACHED
- LOGFONT lf;
- SetLogFont(lf, faceName, characterSet, size, bold, italic, extraFontFlag);
- fid = ::CreateFontIndirect(&lf);
-#else
- if (faceName)
- fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic, extraFontFlag);
-#endif
+ if (fp.faceName)
+ fid = FontCached::FindOrCreate(fp);
}
void Font::Release() {
-#ifndef FONTS_CACHED
- if (fid)
- ::DeleteObject(fid);
-#else
if (fid)
FontCached::ReleaseId(fid);
-#endif
fid = 0;
}
+// Buffer to hold strings and string position arrays without always allocating on heap.
+// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
+// when less than safe size otherwise allocate on heap and free automatically.
+template<typename T, int lengthStandard>
+class VarBuffer {
+ T bufferStandard[lengthStandard];
+public:
+ T *buffer;
+ VarBuffer(size_t length) : buffer(0) {
+ if (length > lengthStandard) {
+ buffer = new T[length];
+ } else {
+ buffer = bufferStandard;
+ }
+ }
+ ~VarBuffer() {
+ if (buffer != bufferStandard) {
+ delete []buffer;
+ buffer = 0;
+ }
+ }
+};
+
+const int stackBufferLength = 10000;
+class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
+public:
+ int tlen;
+ TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
+ VarBuffer<wchar_t, stackBufferLength>(len) {
+ if (unicodeMode) {
+ tlen = UTF16FromUTF8(s, len, buffer, len);
+ } else {
+ // Support Asian string display in 9x English
+ tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
+ }
+ }
+};
+typedef VarBuffer<XYPOSITION, stackBufferLength> TextPositions;
+
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
-class SurfaceImpl : public Surface {
+class SurfaceGDI : public Surface {
bool unicodeMode;
HDC hdc;
bool hdcOwned;
@@ -386,12 +554,12 @@ class SurfaceImpl : public Surface {
void BrushColor(ColourAllocated back);
void SetFont(Font &font_);
- // Private so SurfaceImpl objects can not be copied
- SurfaceImpl(const SurfaceImpl &);
- SurfaceImpl &operator=(const SurfaceImpl &);
+ // Private so SurfaceGDI objects can not be copied
+ SurfaceGDI(const SurfaceGDI &);
+ SurfaceGDI &operator=(const SurfaceGDI &);
public:
- SurfaceImpl();
- virtual ~SurfaceImpl();
+ SurfaceGDI();
+ virtual ~SurfaceGDI();
void Init(WindowID wid);
void Init(SurfaceID sid, WindowID wid);
@@ -415,19 +583,19 @@ public:
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Point from, Surface &surfaceSource);
- void DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions);
- void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
- void MeasureWidths(Font &font_, const char *s, int len, int *positions);
- int WidthText(Font &font_, const char *s, int len);
- int WidthChar(Font &font_, char ch);
- int Ascent(Font &font_);
- int Descent(Font &font_);
- int InternalLeading(Font &font_);
- int ExternalLeading(Font &font_);
- int Height(Font &font_);
- int AverageCharWidth(Font &font_);
+ void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
@@ -441,7 +609,7 @@ public:
} //namespace Scintilla
#endif
-SurfaceImpl::SurfaceImpl() :
+SurfaceGDI::SurfaceGDI() :
unicodeMode(false),
hdc(0), hdcOwned(false),
pen(0), penOld(0),
@@ -459,11 +627,11 @@ SurfaceImpl::SurfaceImpl() :
win9xACPSame = false;
}
-SurfaceImpl::~SurfaceImpl() {
+SurfaceGDI::~SurfaceGDI() {
Release();
}
-void SurfaceImpl::Release() {
+void SurfaceGDI::Release() {
if (penOld) {
::SelectObject(reinterpret_cast<HDC>(hdc), penOld);
::DeleteObject(pen);
@@ -501,33 +669,33 @@ void SurfaceImpl::Release() {
}
}
-bool SurfaceImpl::Initialised() {
+bool SurfaceGDI::Initialised() {
return hdc != 0;
}
-void SurfaceImpl::Init(WindowID) {
+void SurfaceGDI::Init(WindowID) {
Release();
hdc = ::CreateCompatibleDC(NULL);
hdcOwned = true;
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::Init(SurfaceID sid, WindowID) {
+void SurfaceGDI::Init(SurfaceID sid, WindowID) {
Release();
hdc = reinterpret_cast<HDC>(sid);
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
+void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID) {
Release();
- hdc = ::CreateCompatibleDC(static_cast<SurfaceImpl *>(surface_)->hdc);
+ hdc = ::CreateCompatibleDC(static_cast<SurfaceGDI *>(surface_)->hdc);
hdcOwned = true;
- bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceImpl *>(surface_)->hdc, width, height);
+ bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceGDI *>(surface_)->hdc, width, height);
bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::PenColour(ColourAllocated fore) {
+void SurfaceGDI::PenColour(ColourAllocated fore) {
if (pen) {
::SelectObject(hdc, penOld);
::DeleteObject(pen);
@@ -538,7 +706,7 @@ void SurfaceImpl::PenColour(ColourAllocated fore) {
penOld = static_cast<HPEN>(::SelectObject(reinterpret_cast<HDC>(hdc), pen));
}
-void SurfaceImpl::BrushColor(ColourAllocated back) {
+void SurfaceGDI::BrushColor(ColourAllocated back) {
if (brush) {
::SelectObject(hdc, brushOld);
::DeleteObject(brush);
@@ -551,46 +719,48 @@ void SurfaceImpl::BrushColor(ColourAllocated back) {
brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
}
-void SurfaceImpl::SetFont(Font &font_) {
+void SurfaceGDI::SetFont(Font &font_) {
if (font_.GetID() != font) {
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
+ PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_GDI);
if (fontOld) {
- ::SelectObject(hdc, font_.GetID());
+ ::SelectObject(hdc, pfm->hfont);
} else {
- fontOld = static_cast<HFONT>(::SelectObject(hdc, font_.GetID()));
+ fontOld = static_cast<HFONT>(::SelectObject(hdc, pfm->hfont));
}
- font = reinterpret_cast<HFONT>(font_.GetID());
+ font = reinterpret_cast<HFONT>(pfm->hfont);
}
}
-int SurfaceImpl::LogPixelsY() {
+int SurfaceGDI::LogPixelsY() {
return ::GetDeviceCaps(hdc, LOGPIXELSY);
}
-int SurfaceImpl::DeviceHeightFont(int points) {
+int SurfaceGDI::DeviceHeightFont(int points) {
return ::MulDiv(points, LogPixelsY(), 72);
}
-void SurfaceImpl::MoveTo(int x_, int y_) {
+void SurfaceGDI::MoveTo(int x_, int y_) {
::MoveToEx(hdc, x_, y_, 0);
}
-void SurfaceImpl::LineTo(int x_, int y_) {
+void SurfaceGDI::LineTo(int x_, int y_) {
::LineTo(hdc, x_, y_);
}
-void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Polygon(hdc, reinterpret_cast<POINT *>(pts), npts);
}
-void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
+void SurfaceGDI::FillRectangle(PRectangle rc, ColourAllocated back) {
// Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
// There is no need to allocate a brush either.
RECT rcw = RectFromPRectangle(rc);
@@ -598,10 +768,10 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL);
}
-void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+void SurfaceGDI::FillRectangle(PRectangle rc, Surface &surfacePattern) {
HBRUSH br;
- if (static_cast<SurfaceImpl &>(surfacePattern).bitmap)
- br = ::CreatePatternBrush(static_cast<SurfaceImpl &>(surfacePattern).bitmap);
+ if (static_cast<SurfaceGDI &>(surfacePattern).bitmap)
+ br = ::CreatePatternBrush(static_cast<SurfaceGDI &>(surfacePattern).bitmap);
else // Something is wrong so display in red
br = ::CreateSolidBrush(RGB(0xff, 0, 0));
RECT rcw = RectFromPRectangle(rc);
@@ -609,7 +779,7 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
::DeleteObject(br);
}
-void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::RoundRect(hdc,
@@ -645,7 +815,7 @@ static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) {
return converter.val;
}
-void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+void SurfaceGDI::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
if (AlphaBlendFn && rc.Width() > 0) {
HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
@@ -704,7 +874,7 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated
}
}
-void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
if (AlphaBlendFn && rc.Width() > 0) {
HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
if (rc.Width() > width)
@@ -743,58 +913,21 @@ void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsi
}
}
-void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+void SurfaceGDI::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
::BitBlt(hdc,
rc.left, rc.top, rc.Width(), rc.Height(),
- static_cast<SurfaceImpl &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
+ static_cast<SurfaceGDI &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
}
-// Buffer to hold strings and string position arrays without always allocating on heap.
-// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
-// when less than safe size otherwise allocate on heap and free automatically.
-template<typename T, int lengthStandard>
-class VarBuffer {
- T bufferStandard[lengthStandard];
-public:
- T *buffer;
- VarBuffer(size_t length) : buffer(0) {
- if (length > lengthStandard) {
- buffer = new T[length];
- } else {
- buffer = bufferStandard;
- }
- }
- ~VarBuffer() {
- if (buffer != bufferStandard) {
- delete []buffer;
- buffer = 0;
- }
- }
-};
+typedef VarBuffer<int, stackBufferLength> TextPositionsI;
-const int stackBufferLength = 10000;
-class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
-public:
- int tlen;
- TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
- VarBuffer<wchar_t, stackBufferLength>(len) {
- if (unicodeMode) {
- tlen = UTF16FromUTF8(s, len, buffer, len);
- } else {
- // Support Asian string display in 9x English
- tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
- }
- }
-};
-typedef VarBuffer<int, stackBufferLength> TextPositions;
-
-void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) {
+void SurfaceGDI::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions) {
SetFont(font_);
RECT rcw = RectFromPRectangle(rc);
SIZE sz={0,0};
@@ -838,21 +971,21 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const ch
}
}
-void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
}
-void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
}
-void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore) {
// Avoid drawing spaces in transparent mode
for (int i=0;i<len;i++) {
@@ -866,7 +999,7 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con
}
}
-int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+XYPOSITION SurfaceGDI::WidthText(Font &font_, const char *s, int len) {
SetFont(font_);
SIZE sz={0,0};
if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
@@ -878,13 +1011,13 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
return sz.cx;
}
-void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
SetFont(font_);
SIZE sz={0,0};
int fit = 0;
if (unicodeMode) {
const TextWide tbuf(s, len, unicodeMode, codePage);
- TextPositions poses(tbuf.tlen);
+ TextPositionsI poses(tbuf.tlen);
fit = tbuf.tlen;
if (!::GetTextExtentExPointW(hdc, tbuf.buffer, tbuf.tlen, maxWidthMeasure, &fit, poses.buffer, &sz)) {
// Likely to have failed because on Windows 9x where function not available
@@ -928,19 +1061,19 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
int startOffset = 0;
while (len > 0) {
int lenBlock = Platform::Minimum(len, maxLenText);
- if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, positions, &sz)) {
+ TextPositionsI poses(len);
+ if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, poses.buffer, &sz)) {
// Eeek - a NULL DC or other foolishness could cause this.
return;
} else if (fit < lenBlock) {
// For some reason, such as an incomplete DBCS character
// Not all the positions are filled in so make them equal to end.
- for (int i=fit;i<lenBlock;i++)
- positions[i] = positions[fit-1];
- } else if (startOffset > 0) {
- for (int i=0;i<lenBlock;i++)
- positions[i] += startOffset;
+ for (int i = fit;i<lenBlock;i++)
+ poses.buffer[i] = poses.buffer[fit-1];
}
- startOffset = positions[lenBlock-1];
+ for (int i=0;i<lenBlock;i++)
+ positions[i] = poses.buffer[i] + startOffset;
+ startOffset = poses.buffer[lenBlock-1];
len -= lenBlock;
positions += lenBlock;
s += lenBlock;
@@ -948,7 +1081,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
} else {
// Support Asian string display in 9x English
const TextWide tbuf(s, len, unicodeMode, codePage);
- TextPositions poses(tbuf.tlen);
+ TextPositionsI poses(tbuf.tlen);
for (int widthSS=0; widthSS<tbuf.tlen; widthSS++) {
::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
poses.buffer[widthSS] = sz.cx;
@@ -970,56 +1103,56 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
}
}
-int SurfaceImpl::WidthChar(Font &font_, char ch) {
+XYPOSITION SurfaceGDI::WidthChar(Font &font_, char ch) {
SetFont(font_);
SIZE sz;
::GetTextExtentPoint32A(hdc, &ch, 1, &sz);
return sz.cx;
}
-int SurfaceImpl::Ascent(Font &font_) {
+XYPOSITION SurfaceGDI::Ascent(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmAscent;
}
-int SurfaceImpl::Descent(Font &font_) {
+XYPOSITION SurfaceGDI::Descent(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmDescent;
}
-int SurfaceImpl::InternalLeading(Font &font_) {
+XYPOSITION SurfaceGDI::InternalLeading(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmInternalLeading;
}
-int SurfaceImpl::ExternalLeading(Font &font_) {
+XYPOSITION SurfaceGDI::ExternalLeading(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmExternalLeading;
}
-int SurfaceImpl::Height(Font &font_) {
+XYPOSITION SurfaceGDI::Height(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmHeight;
}
-int SurfaceImpl::AverageCharWidth(Font &font_) {
+XYPOSITION SurfaceGDI::AverageCharWidth(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmAveCharWidth;
}
-int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
+int SurfaceGDI::SetPalette(Palette *pal, bool inBackGround) {
if (paletteOld) {
::SelectPalette(hdc, paletteOld, TRUE);
}
@@ -1033,28 +1166,705 @@ int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
return changes;
}
-void SurfaceImpl::SetClip(PRectangle rc) {
+void SurfaceGDI::SetClip(PRectangle rc) {
::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::FlushCachedState() {
+void SurfaceGDI::FlushCachedState() {
pen = 0;
brush = 0;
font = 0;
}
-void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+void SurfaceGDI::SetUnicodeMode(bool unicodeMode_) {
unicodeMode=unicodeMode_;
}
-void SurfaceImpl::SetDBCSMode(int codePage_) {
+void SurfaceGDI::SetDBCSMode(int codePage_) {
// No action on window as automatically handled by system.
codePage = codePage_;
win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP());
}
-Surface *Surface::Allocate() {
- return new SurfaceImpl;
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class SurfaceD2D : public Surface {
+ bool unicodeMode;
+ int x, y;
+
+ int codePage;
+
+ ID2D1RenderTarget *pRenderTarget;
+ bool ownRenderTarget;
+ int clipsActive;
+
+ IDWriteTextFormat *pTextFormat;
+ FLOAT yAscent;
+ FLOAT yDescent;
+
+ ID2D1SolidColorBrush *pBrush;
+
+ int logPixelsY;
+ float dpiScaleX;
+ float dpiScaleY;
+
+ void SetFont(Font &font_);
+
+ // Private so SurfaceD2D objects can not be copied
+ SurfaceD2D(const SurfaceD2D &);
+ SurfaceD2D &operator=(const SurfaceD2D &);
+public:
+ SurfaceD2D();
+ virtual ~SurfaceD2D();
+
+ void SetScale();
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+
+ void Release();
+ bool Initialised();
+
+ HRESULT FlushDrawing();
+
+ void PenColour(ColourAllocated fore);
+ void D2DPenColour(ColourAllocated fore, int alpha=255);
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+ void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
+
+ int SetPalette(Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage_);
+};
+
+#ifdef SCI_NAMESPACE
+} //namespace Scintilla
+#endif
+
+SurfaceD2D::SurfaceD2D() :
+ unicodeMode(false),
+ x(0), y(0) {
+
+ codePage = 0;
+
+ pRenderTarget = NULL;
+ ownRenderTarget = false;
+ clipsActive = 0;
+
+ // From selected font
+ pTextFormat = NULL;
+ yAscent = 2;
+ yDescent = 1;
+
+ pBrush = NULL;
+
+ logPixelsY = 72;
+ dpiScaleX = 1.0;
+ dpiScaleY = 1.0;
+}
+
+SurfaceD2D::~SurfaceD2D() {
+ Release();
+}
+
+void SurfaceD2D::Release() {
+ if (pBrush) {
+ pBrush->Release();
+ pBrush = 0;
+ }
+ if (pRenderTarget) {
+ while (clipsActive) {
+ pRenderTarget->PopAxisAlignedClip();
+ clipsActive--;
+ }
+ if (ownRenderTarget) {
+ pRenderTarget->Release();
+ }
+ pRenderTarget = 0;
+ }
+}
+
+void SurfaceD2D::SetScale() {
+ HDC hdcMeasure = ::CreateCompatibleDC(NULL);
+ logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY);
+ dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / 96.0f;
+ dpiScaleY = logPixelsY / 96.0f;
+ ::DeleteDC(hdcMeasure);
+}
+
+bool SurfaceD2D::Initialised() {
+ return pRenderTarget != 0;
+}
+
+HRESULT SurfaceD2D::FlushDrawing() {
+ return pRenderTarget->Flush();
+}
+
+void SurfaceD2D::Init(WindowID /* wid */) {
+ Release();
+ SetScale();
+}
+
+void SurfaceD2D::Init(SurfaceID sid, WindowID) {
+ Release();
+ SetScale();
+ pRenderTarget = reinterpret_cast<ID2D1HwndRenderTarget *>(sid);
+}
+
+void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) {
+ Release();
+ SetScale();
+ SurfaceD2D *psurfOther = static_cast<SurfaceD2D *>(surface_);
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL;
+ HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget(
+ D2D1::SizeF(width, height), &pCompatibleRenderTarget);
+ if (SUCCEEDED(hr)) {
+ pRenderTarget = pCompatibleRenderTarget;
+ pRenderTarget->BeginDraw();
+ ownRenderTarget = true;
+ }
+}
+
+void SurfaceD2D::PenColour(ColourAllocated fore) {
+ D2DPenColour(fore);
+}
+
+void SurfaceD2D::D2DPenColour(ColourAllocated fore, int alpha) {
+ if (pRenderTarget) {
+ D2D_COLOR_F col;
+ col.r = (fore.AsLong() & 0xff) / 255.0;
+ col.g = ((fore.AsLong() & 0xff00) >> 8) / 255.0;
+ col.b = (fore.AsLong() >> 16) / 255.0;
+ col.a = alpha / 255.0;
+ if (pBrush) {
+ pBrush->SetColor(col);
+ } else {
+ HRESULT hr = pRenderTarget->CreateSolidColorBrush(col, &pBrush);
+ if (!SUCCEEDED(hr) && pBrush) {
+ pBrush->Release();
+ pBrush = 0;
+ }
+ }
+ }
+}
+
+void SurfaceD2D::SetFont(Font &font_) {
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
+ PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_DIRECTWRITE);
+ pTextFormat = pfm->pTextFormat;
+ yAscent = pfm->yAscent;
+ yDescent = pfm->yDescent;
+ if (pRenderTarget) {
+ pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfm->extraFontFlag));
+ }
+}
+
+int SurfaceD2D::LogPixelsY() {
+ return logPixelsY;
+}
+
+int SurfaceD2D::DeviceHeightFont(int points) {
+ return ::MulDiv(points, LogPixelsY(), 72);
+}
+
+void SurfaceD2D::MoveTo(int x_, int y_) {
+ x = x_;
+ y = y_;
+}
+
+static int Delta(int difference) {
+ if (difference < 0)
+ return -1;
+ else if (difference > 0)
+ return 1;
+ else
+ return 0;
+}
+
+static int RoundFloat(float f) {
+ return int(f+0.5);
+}
+
+void SurfaceD2D::LineTo(int x_, int y_) {
+ if (pRenderTarget) {
+ int xDiff = x_ - x;
+ int xDelta = Delta(xDiff);
+ int yDiff = y_ - y;
+ int yDelta = Delta(yDiff);
+ if ((xDiff == 0) || (yDiff == 0)) {
+ // Horizontal or vertical lines can be more precisely drawn as a filled rectangle
+ int xEnd = x_ - xDelta;
+ int left = Platform::Minimum(x, xEnd);
+ int width = abs(x - xEnd) + 1;
+ int yEnd = y_ - yDelta;
+ int top = Platform::Minimum(y, yEnd);
+ int height = abs(y - yEnd) + 1;
+ D2D1_RECT_F rectangle1 = D2D1::RectF(left, top, left+width, top+height);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ } else if ((abs(xDiff) == abs(yDiff))) {
+ // 45 degree slope
+ pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5),
+ D2D1::Point2F(x_ + 0.5 - xDelta, y_ + 0.5 - yDelta), pBrush);
+ } else {
+ // Line has a different slope so difficult to avoid last pixel
+ pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5),
+ D2D1::Point2F(x_ + 0.5, y_ + 0.5), pBrush);
+ }
+ x = x_;
+ y = y_;
+ }
+}
+
+void SurfaceD2D::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ ID2D1Factory *pFactory = 0;
+ pRenderTarget->GetFactory(&pFactory);
+ ID2D1PathGeometry *geometry=0;
+ HRESULT hr = pFactory->CreatePathGeometry(&geometry);
+ if (SUCCEEDED(hr)) {
+ ID2D1GeometrySink *sink = 0;
+ hr = geometry->Open(&sink);
+ if (SUCCEEDED(hr)) {
+ sink->BeginFigure(D2D1::Point2F(pts[0].x + 0.5f, pts[0].y + 0.5f), D2D1_FIGURE_BEGIN_FILLED);
+ for (size_t i=1; i<static_cast<size_t>(npts); i++) {
+ sink->AddLine(D2D1::Point2F(pts[i].x + 0.5f, pts[i].y + 0.5f));
+ }
+ sink->EndFigure(D2D1_FIGURE_END_CLOSED);
+ sink->Close();
+ sink->Release();
+
+ D2DPenColour(back);
+ pRenderTarget->FillGeometry(geometry,pBrush);
+ D2DPenColour(fore);
+ pRenderTarget->DrawGeometry(geometry,pBrush);
+ }
+
+ geometry->Release();
+ }
+ }
+}
+
+void SurfaceD2D::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2DPenColour(back);
+ D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left) + 0.5, rc.top+0.5, RoundFloat(rc.right) - 0.5, rc.bottom-0.5);
+ D2DPenColour(back);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ D2DPenColour(fore);
+ pRenderTarget->DrawRectangle(&rectangle1, pBrush);
+ }
+}
+
+void SurfaceD2D::FillRectangle(PRectangle rc, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2DPenColour(back);
+ D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left), rc.top, RoundFloat(rc.right), rc.bottom);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ }
+}
+
+void SurfaceD2D::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfacePattern);
+ surfOther.FlushDrawing();
+ ID2D1Bitmap *pBitmap = NULL;
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
+ surfOther.pRenderTarget);
+ HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
+ if (SUCCEEDED(hr)) {
+ ID2D1BitmapBrush *pBitmapBrush = NULL;
+ D2D1_BITMAP_BRUSH_PROPERTIES brushProperties =
+ D2D1::BitmapBrushProperties(D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP,
+ D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
+ // Create the bitmap brush.
+ hr = pRenderTarget->CreateBitmapBrush(pBitmap, brushProperties, &pBitmapBrush);
+ pBitmap->Release();
+ if (SUCCEEDED(hr)) {
+ pRenderTarget->FillRectangle(
+ D2D1::RectF(rc.left, rc.top, rc.right, rc.bottom),
+ pBitmapBrush);
+ pBitmapBrush->Release();
+ }
+ }
+}
+
+void SurfaceD2D::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
+ D2D1::RectF(rc.left+1.0, rc.top+1.0, rc.right-1.0, rc.bottom-1.0),
+ 8, 8);
+ D2DPenColour(back);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+
+ D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
+ D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5),
+ 8, 8);
+ D2DPenColour(fore);
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
+ }
+}
+
+void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
+ if (pRenderTarget) {
+ D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
+ D2D1::RectF(rc.left+1.0, rc.top+1.0, rc.right-1.0, rc.bottom-1.0),
+ cornerSize, cornerSize);
+ D2DPenColour(fill, alphaFill);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+
+ D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
+ D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5),
+ cornerSize, cornerSize);
+ D2DPenColour(outline, alphaOutline);
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
+ }
+}
+
+void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+ if (pRenderTarget) {
+ if (rc.Width() > width)
+ rc.left += (rc.Width() - width) / 2;
+ rc.right = rc.left + width;
+ if (rc.Height() > height)
+ rc.top += (rc.Height() - height) / 2;
+ rc.bottom = rc.top + height;
+
+ std::vector<unsigned char> image(height * width * 4);
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ unsigned char *pixel = &image[0] + (y*width+x) * 4;
+ unsigned char alpha = pixelsImage[3];
+ // Input is RGBA, output is BGRA with premultiplied alpha
+ pixel[2] = (*pixelsImage++) * alpha / 255;
+ pixel[1] = (*pixelsImage++) * alpha / 255;
+ pixel[0] = (*pixelsImage++) * alpha / 255;
+ pixel[3] = *pixelsImage++;
+ }
+ }
+
+ ID2D1Bitmap *bitmap = 0;
+ D2D1_SIZE_U size = D2D1::SizeU(width, height);
+ D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0};
+ HRESULT hr = pRenderTarget->CreateBitmap(size, &image[0],
+ width * 4, &props, &bitmap);
+ if (SUCCEEDED(hr)) {
+ D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
+ pRenderTarget->DrawBitmap(bitmap, rcDestination);
+ }
+ bitmap->Release();
+ }
+}
+
+void SurfaceD2D::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FLOAT radius = rc.Width() / 2.0f - 1.0f;
+ D2D1_ELLIPSE ellipse = D2D1::Ellipse(
+ D2D1::Point2F((rc.left + rc.right) / 2.0f, (rc.top + rc.bottom) / 2.0f),
+ radius,radius);
+
+ PenColour(back);
+ pRenderTarget->FillEllipse(ellipse, pBrush);
+ PenColour(fore);
+ pRenderTarget->DrawEllipse(ellipse, pBrush);
+ }
+}
+
+void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+ SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfaceSource);
+ surfOther.FlushDrawing();
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
+ surfOther.pRenderTarget);
+ ID2D1Bitmap *pBitmap = NULL;
+ HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
+ if (SUCCEEDED(hr)) {
+ D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
+ D2D1_RECT_F rcSource = {from.x, from.y, from.x + rc.Width(), from.y + rc.Height()};
+ pRenderTarget->DrawBitmap(pBitmap, rcDestination, 1.0f,
+ D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, rcSource);
+ pRenderTarget->Flush();
+ pBitmap->Release();
+ }
+}
+
+void SurfaceD2D::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT) {
+ SetFont(font_);
+ RECT rcw = RectFromPRectangle(rc);
+
+ // Use Unicode calls
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ if (pRenderTarget && pTextFormat && pBrush) {
+
+ // Explicitly creating a text layout appears a little faster
+ IDWriteTextLayout *pTextLayout;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat,
+ rc.Width(), rc.Height(), &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ D2D1_POINT_2F origin = {rc.left, ybase-yAscent};
+ pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE);
+ } else {
+ D2D1_RECT_F layoutRect = D2D1::RectF(
+ static_cast<FLOAT>(rcw.left) / dpiScaleX,
+ static_cast<FLOAT>(ybase-yAscent) / dpiScaleY,
+ static_cast<FLOAT>(rcw.right + 1) / dpiScaleX,
+ static_cast<FLOAT>(rcw.bottom) / dpiScaleY);
+ pRenderTarget->DrawText(tbuf.buffer, tbuf.tlen, pTextFormat, layoutRect, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE);
+ }
+ }
+}
+
+void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FillRectangle(rc, back);
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
+ }
+}
+
+void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FillRectangle(rc, back);
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
+ }
+}
+
+void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore) {
+ // Avoid drawing spaces in transparent mode
+ for (int i=0;i<len;i++) {
+ if (s[i] != ' ') {
+ if (pRenderTarget) {
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, 0);
+ }
+ return;
+ }
+ }
+}
+
+XYPOSITION SurfaceD2D::WidthText(Font &font_, const char *s, int len) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.widthIncludingTrailingWhitespace;
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
+ SetFont(font_);
+ int fit = 0;
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ TextPositions poses(tbuf.tlen);
+ fit = tbuf.tlen;
+ const int clusters = 1000;
+ DWRITE_CLUSTER_METRICS clusterMetrics[clusters];
+ UINT32 count = 0;
+ if (pIDWriteFactory && pTextFormat) {
+ SetFont(font_);
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 10000.0, 1000.0, &pTextLayout);
+ if (!SUCCEEDED(hr))
+ return;
+ // For now, assuming WCHAR == cluster
+ pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count);
+ FLOAT position = 0.0f;
+ size_t ti=0;
+ for (size_t ci=0;ci<count;ci++) {
+ position += clusterMetrics[ci].width;
+ for (size_t inCluster=0; inCluster<clusterMetrics[ci].length; inCluster++) {
+ //poses.buffer[ti++] = int(position + 0.5);
+ poses.buffer[ti++] = position;
+ }
+ }
+ PLATFORM_ASSERT(ti == static_cast<size_t>(tbuf.tlen));
+ pTextLayout->Release();
+ }
+ if (unicodeMode) {
+ // Map the widths given for UTF-16 characters back onto the UTF-8 input string
+ int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ int i=0;
+ while (ui<fit) {
+ unsigned char uch = us[i];
+ unsigned int lenChar = 1;
+ if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
+ lenChar = 4;
+ ui++;
+ } else if (uch >= (0x80 + 0x40 + 0x20)) {
+ lenChar = 3;
+ } else if (uch >= (0x80)) {
+ lenChar = 2;
+ }
+ for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
+ positions[i++] = poses.buffer[ui];
+ }
+ ui++;
+ }
+ int lastPos = 0;
+ if (i > 0)
+ lastPos = positions[i-1];
+ while (i<len) {
+ positions[i++] = lastPos;
+ }
+ } else if (codePage == 0) {
+
+ // One character per position
+ PLATFORM_ASSERT(len == tbuf.tlen);
+ for (size_t kk=0;kk<static_cast<size_t>(len);kk++) {
+ positions[kk] = poses.buffer[kk];
+ }
+
+ } else {
+
+ // May be more than one byte per position
+ int ui = 0;
+ for (int i=0;i<len;) {
+ if (::IsDBCSLeadByteEx(codePage, s[i])) {
+ positions[i] = poses.buffer[ui];
+ positions[i+1] = poses.buffer[ui];
+ i += 2;
+ } else {
+ positions[i] = poses.buffer[ui];
+ i++;
+ }
+
+ ui++;
+ }
+ }
+}
+
+XYPOSITION SurfaceD2D::WidthChar(Font &font_, char ch) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ const WCHAR wch = ch;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(&wch, 1, pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.widthIncludingTrailingWhitespace;
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+XYPOSITION SurfaceD2D::Ascent(Font &font_) {
+ SetFont(font_);
+ return ceil(yAscent);
+}
+
+XYPOSITION SurfaceD2D::Descent(Font &font_) {
+ SetFont(font_);
+ return ceil(yDescent);
+}
+
+XYPOSITION SurfaceD2D::InternalLeading(Font &) {
+ return 0;
+}
+
+XYPOSITION SurfaceD2D::ExternalLeading(Font &) {
+ return 1;
+}
+
+XYPOSITION SurfaceD2D::Height(Font &font_) {
+ return Ascent(font_) + Descent(font_);
+}
+
+XYPOSITION SurfaceD2D::AverageCharWidth(Font &font_) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ const WCHAR wszAllAlpha[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(wszAllAlpha, wcslen(wszAllAlpha), pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.width / wcslen(wszAllAlpha);
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+int SurfaceD2D::SetPalette(Palette *, bool) {
+ return 0;
+}
+
+void SurfaceD2D::SetClip(PRectangle rc) {
+ if (pRenderTarget) {
+ D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom};
+ pRenderTarget->PushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED);
+ clipsActive++;
+ }
+}
+
+void SurfaceD2D::FlushCachedState() {
+}
+
+void SurfaceD2D::SetUnicodeMode(bool unicodeMode_) {
+ unicodeMode=unicodeMode_;
+}
+
+void SurfaceD2D::SetDBCSMode(int codePage_) {
+ // No action on window as automatically handled by system.
+ codePage = codePage_;
+}
+
+Surface *Surface::Allocate(int technology) {
+ if (technology == SCWIN_TECH_GDI)
+ return new SurfaceGDI;
+ else
+ return new SurfaceD2D;
}
Window::~Window() {
@@ -1092,8 +1902,7 @@ void Window::SetPositionRelative(PRectangle rc, Window w) {
#ifdef MONITOR_DEFAULTTONULL
// We're using the stub functionality of MultiMon.h to decay gracefully on machines
// (ie, pre Win2000, Win95) that do not support the newer functions.
- RECT rcMonitor;
- memcpy(&rcMonitor, &rc, sizeof(rcMonitor)); // RECT and Rectangle are the same really.
+ RECT rcMonitor = {rc.left, rc.top, rc.right, rc.bottom};
MONITORINFO mi = {0};
mi.cbSize = sizeof(mi);
@@ -1365,6 +2174,7 @@ ListBox::~ListBox() {
class ListBoxX : public ListBox {
int lineHeight;
FontID fontCopy;
+ int technology;
RGBAImageSet images;
LineToItem lti;
HWND lb;
@@ -1407,7 +2217,7 @@ class ListBoxX : public ListBox {
static const Point ImageInset; // Padding around image
public:
- ListBoxX() : lineHeight(10), fontCopy(0), lb(0), unicodeMode(false),
+ ListBoxX() : lineHeight(10), fontCopy(0), technology(0), lb(0), unicodeMode(false),
desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8),
parent(NULL), ctrlID(0), doubleClickAction(NULL), doubleClickActionData(NULL),
widestItem(NULL), maxCharWidth(1), resizeHit(0), wheelDelta(0) {
@@ -1419,7 +2229,7 @@ public:
}
}
virtual void SetFont(Font &font);
- virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
+ virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_);
virtual void SetAverageCharWidth(int width);
virtual void SetVisibleRows(int rows);
virtual int GetVisibleRows() const;
@@ -1454,12 +2264,13 @@ ListBox *ListBox::Allocate() {
return lb;
}
-void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_) {
+void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_, int technology_) {
parent = &parent_;
ctrlID = ctrlID_;
location = location_;
lineHeight = lineHeight_;
unicodeMode = unicodeMode_;
+ technology = technology_;
HWND hwndParent = reinterpret_cast<HWND>(parent->GetID());
HINSTANCE hinstanceParent = GetWindowInstance(hwndParent);
// Window created as popup so not clipped within parent client area
@@ -1471,17 +2282,19 @@ void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHei
hinstanceParent,
this);
- ::MapWindowPoints(hwndParent, NULL, reinterpret_cast<POINT*>(&location), 1);
+ POINT locationw = {location.x, location.y};
+ ::MapWindowPoints(hwndParent, NULL, &locationw, 1);
+ location = Point(locationw.x, locationw.y);
}
void ListBoxX::SetFont(Font &font) {
- LOGFONT lf;
- if (0 != ::GetObject(font.GetID(), sizeof(lf), &lf)) {
+ if (font.GetID()) {
if (fontCopy) {
::DeleteObject(fontCopy);
fontCopy = 0;
}
- fontCopy = ::CreateFontIndirect(&lf);
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font.GetID());
+ fontCopy = pfm->HFont();
::SendMessage(lb, WM_SETFONT, reinterpret_cast<WPARAM>(fontCopy), 0);
}
}
@@ -1650,16 +2463,46 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
// Draw the image, if any
RGBAImage *pimage = images.Get(pixId);
if (pimage) {
- Surface *surfaceItem = Surface::Allocate();
+ Surface *surfaceItem = Surface::Allocate(technology);
if (surfaceItem) {
- surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
- int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
- PRectangle rcImage(left, pDrawItem->rcItem.top,
- left + images.GetWidth(), pDrawItem->rcItem.bottom);
- surfaceItem->DrawRGBAImage(rcImage,
- pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
- delete surfaceItem;
- ::SetTextAlign(pDrawItem->hDC, TA_TOP);
+ if (technology == SCWIN_TECH_GDI) {
+ surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
+ delete surfaceItem;
+ ::SetTextAlign(pDrawItem->hDC, TA_TOP);
+ } else {
+ D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE),
+ 0,
+ 0,
+ D2D1_RENDER_TARGET_USAGE_NONE,
+ D2D1_FEATURE_LEVEL_DEFAULT
+ );
+ ID2D1DCRenderTarget *pDCRT = 0;
+ HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT);
+ RECT rcWindow;
+ GetClientRect(pDrawItem->hwndItem, &rcWindow);
+ hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow);
+ if (SUCCEEDED(hr)) {
+ surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
+ pDCRT->BeginDraw();
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
+ delete surfaceItem;
+ pDCRT->EndDraw();
+ pDCRT->Release();
+ }
+ }
}
}
}
@@ -1726,7 +2569,9 @@ void ListBoxX::SetList(const char *list, char separator, char typesep) {
}
void ListBoxX::AdjustWindowRect(PRectangle *rc) const {
- ::AdjustWindowRectEx(reinterpret_cast<RECT*>(rc), WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
+ RECT rcw = {rc->left, rc->top, rc->right, rc->bottom };
+ ::AdjustWindowRectEx(&rcw, WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
+ *rc = PRectangle(rcw.left, rcw.top, rcw.right, rcw.bottom);
}
int ListBoxX::ItemHeight() const {
@@ -1767,8 +2612,9 @@ void ListBoxX::SetRedraw(bool on) {
void ListBoxX::ResizeToCursor() {
PRectangle rc = GetPosition();
- Point pt;
- ::GetCursorPos(reinterpret_cast<POINT*>(&pt));
+ POINT ptw;
+ ::GetCursorPos(&ptw);
+ Point pt(ptw.x, ptw.y);
pt.x += dragOffset.x;
pt.y += dragOffset.y;