From 39493b4121ff1eb9c723363f3c94ee6daaeeaaae Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Mon, 1 Aug 2011 19:13:04 +1000 Subject: Experimental Direct2D and DirectWrite platform layer. --- win32/PlatWin.cxx | 884 +++++++++++++++++++++++++++++-------------------- win32/ScintillaWin.cxx | 118 ++++++- 2 files changed, 627 insertions(+), 375 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 6a2f103ba..2ba4ed374 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "Platform.h" #include "UniConversion.h" @@ -195,6 +197,30 @@ void Palette::Allocate(Window &) { } } +static IDWriteFactory *pIDWriteFactory = 0; + +static void EnsureDWriteFactory() { + // Construct + if (!pIDWriteFactory) { + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&pIDWriteFactory)); + } +} + +struct FormatAndBaseline { + IDWriteTextFormat *pTextFormat; + FLOAT baseline; + FormatAndBaseline(IDWriteTextFormat *pTextFormat_, FLOAT baseline_) : + pTextFormat(pTextFormat_), baseline(baseline_) { + } + ~FormatAndBaseline() { + pTextFormat->Release(); + pTextFormat = 0; + baseline = 1; + } +}; + #ifndef CLEARTYPE_QUALITY #define CLEARTYPE_QUALITY 5 #endif @@ -264,7 +290,51 @@ FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool 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); + fid = 0; + EnsureDWriteFactory(); + if (pIDWriteFactory) { +#ifdef OLD_CODE + HFONT fontSave = static_cast(::SelectObject(hdc, font_.GetID())); + DWORD sizeOLTM = ::GetOutlineTextMetrics(hdc, NULL, NULL); + std::vector vOLTM(sizeOLTM); + LPOUTLINETEXTMETRIC potm = reinterpret_cast(&vOLTM[0]); + DWORD worked = ::GetOutlineTextMetrics(hdc, sizeOLTM, potm); + ::SelectObject(hdc, fontSave); + if (!worked) + return; + const WCHAR *pwcFamily = reinterpret_cast(&vOLTM[reinterpret_cast(potm->otmpFamilyName)]); + //const WCHAR *pwcFace = reinterpret_cast(&vOLTM[reinterpret_cast(potm->otmpFaceName)]); + FLOAT fHeight = potm->otmTextMetrics.tmHeight * 72.0f / 96.0f; + bool italics = potm->otmTextMetrics.tmItalic != 0; + bool bold = potm->otmTextMetrics.tmWeight >= FW_BOLD; +#endif + IDWriteTextFormat *pTextFormat; + const int faceSize = 200; + WCHAR wszFace[faceSize]; + UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); + FLOAT fHeight = size_; + HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL, + bold_ ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR, + italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat); + if (SUCCEEDED(hr)) { + const int maxLines = 2; + DWRITE_LINE_METRICS lineMetrics[maxLines]; + UINT32 lineCount = 0; + FLOAT baseline = 1.0f; + IDWriteTextLayout *pTextLayout = 0; + HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, + 100.0f, 100.0f, &pTextLayout); + if (SUCCEEDED(hr)) { + hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); + if (SUCCEEDED(hr)) { + baseline = lineMetrics[0].baseline; + } + pTextLayout->Release(); + } + fid = reinterpret_cast(new FormatAndBaseline(pTextFormat, baseline)); + } + } usage = 1; } @@ -279,8 +349,7 @@ bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, boo } void FontCached::Release() { - if (fid) - ::DeleteObject(fid); + delete reinterpret_cast(fid); fid = 0; } @@ -338,24 +407,13 @@ Font::~Font() { void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) { 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 } void Font::Release() { -#ifndef FONTS_CACHED - if (fid) - ::DeleteObject(fid); -#else if (fid) FontCached::ReleaseId(fid); -#endif fid = 0; } @@ -367,23 +425,26 @@ class SurfaceImpl : public Surface { bool unicodeMode; HDC hdc; bool hdcOwned; - HPEN pen; - HPEN penOld; - HBRUSH brush; - HBRUSH brushOld; - HFONT font; - HFONT fontOld; - HBITMAP bitmap; - HBITMAP bitmapOld; - HPALETTE paletteOld; int maxWidthMeasure; int maxLenText; + int x, y; int codePage; // If 9x OS and current code page is same as ANSI code page. bool win9xACPSame; - void BrushColor(ColourAllocated back); + ID2D1RenderTarget *pRenderTarget; + bool ownRenderTarget; + bool needsEndDraw; + int clipsActive; + + IDWriteTextFormat *pTextFormat; + FLOAT baseline; + ID2D1SolidColorBrush *pBrush; + float dpiScaleX; + float dpiScaleY; + bool hasBegun; + void SetFont(Font &font_); // Private so SurfaceImpl objects can not be copied @@ -393,13 +454,18 @@ public: SurfaceImpl(); virtual ~SurfaceImpl(); + void SetDWrite(HDC hdc); 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_); @@ -441,14 +507,12 @@ public: } //namespace Scintilla #endif +#pragma comment(lib, "d2d1.lib") +#pragma comment(lib, "dwrite.lib") + SurfaceImpl::SurfaceImpl() : unicodeMode(false), - hdc(0), hdcOwned(false), - pen(0), penOld(0), - brush(0), brushOld(0), - font(0), fontOld(0), - bitmap(0), bitmapOld(0), - paletteOld(0) { + hdc(0), hdcOwned(false) { // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels maxWidthMeasure = IsNT() ? INT_MAX : 30000; // There appears to be a 16 bit string length limit in GDI on NT and a limit of @@ -457,6 +521,17 @@ SurfaceImpl::SurfaceImpl() : codePage = 0; win9xACPSame = false; + + pRenderTarget = NULL; + ownRenderTarget = false; + needsEndDraw = false; + clipsActive = 0; + pTextFormat = NULL; + baseline = 1.0f; + pBrush = NULL; + dpiScaleX = 1.0; + dpiScaleY = 1.0; + hasBegun = false; } SurfaceImpl::~SurfaceImpl() { @@ -464,102 +539,107 @@ SurfaceImpl::~SurfaceImpl() { } void SurfaceImpl::Release() { - if (penOld) { - ::SelectObject(reinterpret_cast(hdc), penOld); - ::DeleteObject(pen); - penOld = 0; - } - pen = 0; - if (brushOld) { - ::SelectObject(reinterpret_cast(hdc), brushOld); - ::DeleteObject(brush); - brushOld = 0; - } - brush = 0; - if (fontOld) { - // Fonts are not deleted as they are owned by a Font object - ::SelectObject(reinterpret_cast(hdc), fontOld); - fontOld = 0; - } - font = 0; - if (bitmapOld) { - ::SelectObject(reinterpret_cast(hdc), bitmapOld); - ::DeleteObject(bitmap); - bitmapOld = 0; - } - bitmap = 0; - if (paletteOld) { - // Palettes are not deleted as they are owned by a Palette object - ::SelectPalette(reinterpret_cast(hdc), - reinterpret_cast(paletteOld), TRUE); - paletteOld = 0; - } if (hdcOwned) { ::DeleteDC(reinterpret_cast(hdc)); hdc = 0; hdcOwned = false; } + + if (pBrush) { + pBrush->Release(); + pBrush = 0; + } + if (pRenderTarget) { + while (clipsActive) { + pRenderTarget->PopAxisAlignedClip(); + clipsActive--; + } + if (ownRenderTarget) { + pRenderTarget->Release(); + } + pRenderTarget = 0; + } +} + +// Ensures have pIDWriteFactory, and pRenderTarget +// If any fail, pRenderTarget will be NULL +void SurfaceImpl::SetDWrite(HDC hdc) { + // Construct + EnsureDWriteFactory(); + dpiScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + dpiScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; } bool SurfaceImpl::Initialised() { - return hdc != 0; + return pRenderTarget != 0; +} + +HRESULT SurfaceImpl::FlushDrawing() { + return pRenderTarget->Flush(); } -void SurfaceImpl::Init(WindowID) { +void SurfaceImpl::Init(WindowID wid) { Release(); hdc = ::CreateCompatibleDC(NULL); hdcOwned = true; ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); + RECT rc; + ::GetClientRect(reinterpret_cast(wid), &rc); + SetDWrite(hdc); } void SurfaceImpl::Init(SurfaceID sid, WindowID) { Release(); - hdc = reinterpret_cast(sid); + hdc = ::CreateCompatibleDC(NULL); + hdcOwned = true; + pRenderTarget = reinterpret_cast(sid); ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); + SetDWrite(hdc); } void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) { Release(); - hdc = ::CreateCompatibleDC(static_cast(surface_)->hdc); + hdc = ::CreateCompatibleDC(NULL); // Just for measurement hdcOwned = true; - bitmap = ::CreateCompatibleBitmap(static_cast(surface_)->hdc, width, height); - bitmapOld = static_cast(::SelectObject(hdc, bitmap)); - ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); -} - -void SurfaceImpl::PenColour(ColourAllocated fore) { - if (pen) { - ::SelectObject(hdc, penOld); - ::DeleteObject(pen); - pen = 0; - penOld = 0; + SurfaceImpl *psurfOther = static_cast(surface_); + ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL; + HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget( + D2D1::SizeF(width, height), &pCompatibleRenderTarget); + if (SUCCEEDED(hr)) { + pRenderTarget = pCompatibleRenderTarget; + pRenderTarget->BeginDraw(); + ownRenderTarget = true; + needsEndDraw = true; } - pen = ::CreatePen(0,1,fore.AsLong()); - penOld = static_cast(::SelectObject(reinterpret_cast(hdc), pen)); } -void SurfaceImpl::BrushColor(ColourAllocated back) { - if (brush) { - ::SelectObject(hdc, brushOld); - ::DeleteObject(brush); - brush = 0; - brushOld = 0; +void SurfaceImpl::PenColour(ColourAllocated fore) { + D2DPenColour(fore); +} + +void SurfaceImpl::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; + } + } } - // Only ever want pure, non-dithered brushes - ColourAllocated colourNearest = ::GetNearestColor(hdc, back.AsLong()); - brush = ::CreateSolidBrush(colourNearest.AsLong()); - brushOld = static_cast(::SelectObject(hdc, brush)); } void SurfaceImpl::SetFont(Font &font_) { - if (font_.GetID() != font) { - if (fontOld) { - ::SelectObject(hdc, font_.GetID()); - } else { - fontOld = static_cast(::SelectObject(hdc, font_.GetID())); - } - font = reinterpret_cast(font_.GetID()); - } + FormatAndBaseline *pfabl = reinterpret_cast(font_.GetID()); + pTextFormat = pfabl->pTextFormat; + baseline = pfabl->baseline; } int SurfaceImpl::LogPixelsY() { @@ -571,142 +651,156 @@ int SurfaceImpl::DeviceHeightFont(int points) { } void SurfaceImpl::MoveTo(int x_, int y_) { - ::MoveToEx(hdc, x_, y_, 0); + x = x_; + y = y_; +} + +static int Delta(int difference) { + if (difference < 0) + return -1; + else if (difference > 0) + return 1; + else + return 0; } void SurfaceImpl::LineTo(int x_, int y_) { - ::LineTo(hdc, x_, 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 SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { - PenColour(fore); - BrushColor(back); - ::Polygon(hdc, reinterpret_cast(pts), npts); + 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(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 SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { - PenColour(fore); - BrushColor(back); - ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); + if (pRenderTarget) { + D2DPenColour(back); + D2D1_RECT_F rectangle1 = D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5); + D2DPenColour(back); + pRenderTarget->FillRectangle(&rectangle1, pBrush); + D2DPenColour(fore); + pRenderTarget->DrawRectangle(&rectangle1, pBrush); + } } void SurfaceImpl::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); - ::SetBkColor(hdc, back.AsLong()); - ::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL); + if (pRenderTarget) { + D2DPenColour(back); + D2D1_RECT_F rectangle1 = D2D1::RectF(rc.left, rc.top, rc.right, rc.bottom); + pRenderTarget->FillRectangle(&rectangle1, pBrush); + } } void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { - HBRUSH br; - if (static_cast(surfacePattern).bitmap) - br = ::CreatePatternBrush(static_cast(surfacePattern).bitmap); - else // Something is wrong so display in red - br = ::CreateSolidBrush(RGB(0xff, 0, 0)); - RECT rcw = RectFromPRectangle(rc); - ::FillRect(hdc, &rcw, br); - ::DeleteObject(br); + SurfaceImpl &surfOther = static_cast(surfacePattern); + surfOther.FlushDrawing(); + ID2D1Bitmap *pBitmap = NULL; + ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast( + 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 SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { - PenColour(fore); - BrushColor(back); - ::RoundRect(hdc, - rc.left + 1, rc.top, - rc.right - 1, rc.bottom, - 8, 8); -} - -// Plot a point into a DWORD buffer symetrically to all 4 qudrants -static void AllFour(DWORD *pixels, int width, int height, int x, int y, DWORD val) { - pixels[y*width+x] = val; - pixels[y*width+width-1-x] = val; - pixels[(height-1-y)*width+x] = val; - pixels[(height-1-y)*width+width-1-x] = val; -} - -#ifndef AC_SRC_OVER -#define AC_SRC_OVER 0x00 -#endif -#ifndef AC_SRC_ALPHA -#define AC_SRC_ALPHA 0x01 -#endif + 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); -static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) { - union { - byte pixVal[4]; - DWORD val; - } converter; - converter.pixVal[0] = b; - converter.pixVal[1] = g; - converter.pixVal[2] = r; - converter.pixVal[3] = a; - return converter.val; + 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 SurfaceImpl::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)); - int width = rc.Width(); - int height = rc.Height(); - // Ensure not distorted too much by corners when small - cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2); - BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}; - void *image = 0; - HBITMAP hbmMem = CreateDIBSection(reinterpret_cast(hMemDC), &bpih, - DIB_RGB_COLORS, &image, NULL, 0); - - HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); - - DWORD valEmpty = dwordFromBGRA(0,0,0,0); - DWORD valFill = dwordFromBGRA( - static_cast(GetBValue(fill.AsLong()) * alphaFill / 255), - static_cast(GetGValue(fill.AsLong()) * alphaFill / 255), - static_cast(GetRValue(fill.AsLong()) * alphaFill / 255), - static_cast(alphaFill)); - DWORD valOutline = dwordFromBGRA( - static_cast(GetBValue(outline.AsLong()) * alphaOutline / 255), - static_cast(GetGValue(outline.AsLong()) * alphaOutline / 255), - static_cast(GetRValue(outline.AsLong()) * alphaOutline / 255), - static_cast(alphaOutline)); - DWORD *pixels = reinterpret_cast(image); - for (int y=0; yFillRoundedRectangle(roundedRectFill, pBrush); - AlphaBlendFn(reinterpret_cast(hdc), rc.left, rc.top, width, height, hMemDC, 0, 0, width, height, merge); - - SelectBitmap(hMemDC, hbmOld); - ::DeleteObject(hbmMem); - ::DeleteDC(hMemDC); - } else { - BrushColor(outline); - RECT rcw = RectFromPRectangle(rc); - FrameRect(hdc, &rcw, brush); + 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 SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { - if (AlphaBlendFn && rc.Width() > 0) { - HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast(hdc)); + if (pRenderTarget) { if (rc.Width() > width) rc.left += (rc.Width() - width) / 2; rc.right = rc.left + width; @@ -714,15 +808,10 @@ void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsi rc.top += (rc.Height() - height) / 2; rc.bottom = rc.top + height; - BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}; - unsigned char *image = 0; - HBITMAP hbmMem = CreateDIBSection(reinterpret_cast(hMemDC), &bpih, - DIB_RGB_COLORS, reinterpret_cast(&image), NULL, 0); - HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); - - for (int y=height-1; y>=0; y--) { + std::vector image(height * width * 4); + for (int y=0; y(hdc), rc.left, rc.top, rc.Width(), rc.Height(), hMemDC, 0, 0, width, height, merge); - - SelectBitmap(hMemDC, hbmOld); - ::DeleteObject(hbmMem); - ::DeleteDC(hMemDC); + 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 SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { - PenColour(fore); - BrushColor(back); - ::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); + 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 SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { - ::BitBlt(hdc, - rc.left, rc.top, rc.Width(), rc.Height(), - static_cast(surfaceSource).hdc, from.x, from.y, SRCCOPY); + SurfaceImpl &surfOther = static_cast(surfaceSource); + surfOther.FlushDrawing(); + ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast( + 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(); + } } // Buffer to hold strings and string position arrays without always allocating on heap. @@ -794,62 +905,48 @@ public: }; typedef VarBuffer TextPositions; -void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) { +void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT) { SetFont(font_); RECT rcw = RectFromPRectangle(rc); - SIZE sz={0,0}; - int pos = 0; - int x = rc.left; - - // Text drawing may fail if the text is too big. - // If it does fail, slice up into segments and draw each segment. - const int maxSegmentLength = 0x200; - - if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) { - // Use ANSI calls - int lenDraw = Platform::Minimum(len, maxLenText); - if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s, lenDraw, NULL)) { - while (lenDraw > pos) { - int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos); - if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s+pos, seglen, NULL)) { - PLATFORM_ASSERT(false); - return; - } - ::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz); - x += sz.cx; - pos += seglen; - } - } - } else { - // Use Unicode calls - const TextWide tbuf(s, len, unicodeMode, codePage); - if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL)) { - while (tbuf.tlen > pos) { - int seglen = Platform::Minimum(maxSegmentLength, tbuf.tlen - pos); - if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer+pos, seglen, NULL)) { - PLATFORM_ASSERT(false); - return; - } - ::GetTextExtentPoint32W(hdc, tbuf.buffer+pos, seglen, &sz); - x += sz.cx; - pos += seglen; - } + + // 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()+2, rc.Height(), &pTextLayout); + if (SUCCEEDED(hr)) { + D2D1_POINT_2F origin = {rc.left, ybase-baseline}; + pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush); + } else { + D2D1_RECT_F layoutRect = D2D1::RectF( + static_cast(rcw.left) / dpiScaleX, + static_cast(ybase-baseline) / dpiScaleY, + static_cast(rcw.right + 1) / dpiScaleX, + static_cast(rcw.bottom) / dpiScaleY); + pRenderTarget->DrawText(tbuf.buffer, tbuf.tlen, pTextFormat, layoutRect, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE); } } } void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int 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); + if (pRenderTarget) { + FillRectangle(rc, back); + D2DPenColour(fore); + DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE); + } } void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int 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); + if (pRenderTarget) { + FillRectangle(rc, back); + D2DPenColour(fore); + DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED); + } } void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, @@ -857,44 +954,63 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con // Avoid drawing spaces in transparent mode for (int i=0;iCreateTextLayout(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 sz.cx; + return int(width + 0.5); } void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) { SetFont(font_); - SIZE sz={0,0}; int fit = 0; - if (unicodeMode) { - const TextWide tbuf(s, len, unicodeMode, codePage); - TextPositions 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 - // So measure the character widths by measuring each initial substring - // Turns a linear operation into a qudratic but seems fast enough on test files - for (int widthSS=0; widthSS < tbuf.tlen; widthSS++) { - ::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz); - poses.buffer[widthSS] = sz.cx; + 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(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(s); @@ -921,39 +1037,17 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi while (i 0) { - int lenBlock = Platform::Minimum(len, maxLenText); - if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, positions, &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 0) { - for (int i=0;i(len);kk++) { + positions[kk] = poses.buffer[kk]; } + } else { - // Support Asian string display in 9x English - const TextWide tbuf(s, len, unicodeMode, codePage); - TextPositions poses(tbuf.tlen); - for (int widthSS=0; widthSSCreateTextLayout(&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); } int SurfaceImpl::Ascent(Font &font_) { + FLOAT ascent = 1.0; SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmAscent; + if (pIDWriteFactory && pTextFormat) { + SetFont(font_); + // Create a layout + IDWriteTextLayout *pTextLayout = 0; + HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); + if (SUCCEEDED(hr)) { + DWRITE_TEXT_METRICS textMetrics; + pTextLayout->GetMetrics(&textMetrics); + ascent = textMetrics.layoutHeight; + const int clusters = 20; + DWRITE_CLUSTER_METRICS clusterMetrics[clusters]; + UINT32 count = 0; + pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count); + //height = pTextLayout->GetMaxHeight(); + FLOAT minWidth = 0; + hr = pTextLayout->DetermineMinWidth(&minWidth); + const int maxLines = 2; + DWRITE_LINE_METRICS lineMetrics[maxLines]; + UINT32 lineCount = 0; + hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); + if (SUCCEEDED(hr)) { + ascent = lineMetrics[0].baseline; + } + pTextLayout->Release(); + } + } + return int(ascent + 0.5); } int SurfaceImpl::Descent(Font &font_) { + FLOAT descent = 1.0; SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmDescent; + if (pIDWriteFactory && pTextFormat) { + // Create a layout + IDWriteTextLayout *pTextLayout = 0; + HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); + if (SUCCEEDED(hr)) { + const int maxLines = 2; + DWRITE_LINE_METRICS lineMetrics[maxLines]; + UINT32 lineCount = 0; + hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); + if (SUCCEEDED(hr)) { + descent = lineMetrics[0].height - lineMetrics[0].baseline; + } + pTextLayout->Release(); + } + } + return int(descent + 0.5); } -int SurfaceImpl::InternalLeading(Font &font_) { - SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmInternalLeading; +int SurfaceImpl::InternalLeading(Font &) { + return 0; } -int SurfaceImpl::ExternalLeading(Font &font_) { - SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmExternalLeading; +int SurfaceImpl::ExternalLeading(Font &) { + return 1; } int SurfaceImpl::Height(Font &font_) { + FLOAT height = 1.0; SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmHeight; + if (pIDWriteFactory && pTextFormat) { + // Create a layout + IDWriteTextLayout *pTextLayout = 0; + HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); + if (SUCCEEDED(hr)) { + const int maxLines = 2; + DWRITE_LINE_METRICS lineMetrics[maxLines]; + UINT32 lineCount = 0; + hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); + if (SUCCEEDED(hr)) { + height = lineMetrics[0].height; + } + pTextLayout->Release(); + } + } + // Truncating rather than rounding as otherwise too much space. + return int(height); } int SurfaceImpl::AverageCharWidth(Font &font_) { + FLOAT width = 1.0; SetFont(font_); - TEXTMETRIC tm; - ::GetTextMetrics(hdc, &tm); - return tm.tmAveCharWidth; + 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 SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) { - if (paletteOld) { - ::SelectPalette(hdc, paletteOld, TRUE); - } - paletteOld = 0; - int changes = 0; - if (pal->allowRealization) { - paletteOld = ::SelectPalette(hdc, - reinterpret_cast(pal->hpal), inBackGround); - changes = ::RealizePalette(hdc); - } - return changes; +int SurfaceImpl::SetPalette(Palette *, bool) { + return 0; } void SurfaceImpl::SetClip(PRectangle rc) { - ::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); + if (pRenderTarget) { + D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom}; + pRenderTarget->PushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED); + clipsActive++; + } } void SurfaceImpl::FlushCachedState() { - pen = 0; - brush = 0; - font = 0; } void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { @@ -1651,6 +1806,8 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { if (pimage) { Surface *surfaceItem = Surface::Allocate(); if (surfaceItem) { + // TODO: Need a DC RenderTarget here + /* surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem); int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x; PRectangle rcImage(left, pDrawItem->rcItem.top, @@ -1658,6 +1815,7 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { surfaceItem->DrawRGBAImage(rcImage, pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels()); delete surfaceItem; + */ ::SetTextAlign(pDrawItem->hDC, TA_TOP); } } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 9925a64bb..28e48596b 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -24,6 +24,9 @@ #include #include +#include +#include + #include "Platform.h" #include "ILexer.h" @@ -197,6 +200,10 @@ class ScintillaWin : static HINSTANCE hInstance; + IDWriteFactory *pIDWriteFactory; + ID2D1Factory *pD2DFactory; + ID2D1HwndRenderTarget *pRenderTarget; + ScintillaWin(HWND hwnd); ScintillaWin(const ScintillaWin &); virtual ~ScintillaWin(); @@ -204,6 +211,8 @@ class ScintillaWin : virtual void Initialise(); virtual void Finalise(); + void EnsureRenderTarget(); + void DropRenderTarget(); HWND MainHWND(); static sptr_t DirectFunction( @@ -350,6 +359,10 @@ ScintillaWin::ScintillaWin(HWND hwnd) { sysCaretWidth = 0; sysCaretHeight = 0; + pIDWriteFactory = 0; + pD2DFactory = 0; + pRenderTarget = 0; + keysAlwaysUnicode = false; caret.period = ::GetCaretBlinkTime(); @@ -378,18 +391,69 @@ void ScintillaWin::Initialise() { ::GetProcAddress(commctrl32, "_TrackMouseEvent"); } } + + if (!pIDWriteFactory) { + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory), + reinterpret_cast(&pIDWriteFactory)); + } + if (!pD2DFactory) { + D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory); + } } void ScintillaWin::Finalise() { ScintillaBase::Finalise(); SetTicking(false); SetIdle(false); + DropRenderTarget(); + if (pIDWriteFactory) { + pIDWriteFactory->Release(); + pIDWriteFactory = 0; + } + if (pD2DFactory) { + pD2DFactory->Release(); + pD2DFactory = 0; + } ::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(wMain.GetID()); } @@ -505,8 +569,11 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { pps = &ps; ::BeginPaint(MainHWND(), pps); } - AutoSurface surfaceWindow(pps->hdc, this); + //AutoSurface surfaceWindow(pps->hdc, this); + 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); @@ -517,6 +584,10 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { } Paint(surfaceWindow, rcPaint); surfaceWindow->Release(); + HRESULT hr = pRenderTarget->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) { + DropRenderTarget(); + } } if (hRgnUpdate) { ::DeleteRgn(hRgnUpdate); @@ -674,6 +745,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(); } @@ -1189,11 +1261,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() { @@ -2283,7 +2356,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 @@ -2296,6 +2371,7 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) { surfaceWindow->Release(); } ::ReleaseDC(MainHWND(), hdc); +*/ } /** @@ -2303,23 +2379,30 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) { * This paint will not be abandoned. */ void ScintillaWin::FullPaint() { - HDC hdc = ::GetDC(MainHWND()); - FullPaintDC(hdc); - ::ReleaseDC(MainHWND(), hdc); + //HDC hdc = ::GetDC(MainHWND()); + //FullPaintDC(hdc); + //::ReleaseDC(MainHWND(), hdc); + FullPaintDC(0); } /** * Redraw all of text area on the specified DC. * This paint will not be abandoned. */ -void ScintillaWin::FullPaintDC(HDC hdc) { +void ScintillaWin::FullPaintDC(HDC) { paintState = painting; rcPaint = GetClientRectangle(); paintingAllText = true; - AutoSurface surfaceWindow(hdc, this); + 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; } @@ -2693,10 +2776,21 @@ sptr_t PASCAL ScintillaWin::CTWndProc( ::BeginPaint(hWnd, &ps); Surface *surfaceWindow = Surface::Allocate(); if (surfaceWindow) { - surfaceWindow->Init(ps.hdc, hWnd); + ID2D1HwndRenderTarget *pCTRenderTarget = 0; + RECT rc; + GetClientRect(hWnd, &rc); + // Create a Direct2D render target. + sciThis->pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties(), + D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)), + &pCTRenderTarget); + //surfaceWindow->Init(ps.hdc, hWnd); + surfaceWindow->Init(pCTRenderTarget, hWnd); surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage); surfaceWindow->SetDBCSMode(sciThis->ct.codePage); + pCTRenderTarget->BeginDraw(); sciThis->ct.PaintCT(surfaceWindow); + pCTRenderTarget->EndDraw(); surfaceWindow->Release(); delete surfaceWindow; } -- cgit v1.2.3 From d689117719f2cec9c74aec96cfc59700e1421957 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Tue, 2 Aug 2011 11:24:48 +1000 Subject: Allow floating point text positioning. --- include/Platform.h | 51 +++++++++++++++++--------------- src/Editor.cxx | 10 ++++--- src/PositionCache.cxx | 14 ++++----- src/PositionCache.h | 10 +++---- win32/PlatWin.cxx | 81 +++++++++++++++++++++++++++------------------------ 5 files changed, 88 insertions(+), 78 deletions(-) diff --git a/include/Platform.h b/include/Platform.h index b0f3de0dc..d4c6bbfec 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -9,6 +9,9 @@ #ifndef PLATFORM_H #define PLATFORM_H +#define XYPOSITION float +//#define XYPOSITION int + // PLAT_GTK = GTK+ on Linux or Win32 // PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32 // PLAT_WIN = Win32 API on Win32 OS @@ -76,10 +79,10 @@ typedef void *IdlerID; */ class Point { public: - int x; - int y; + XYPOSITION x; + XYPOSITION y; - explicit Point(int x_=0, int y_=0) : x(x_), y(y_) { + explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { } // Other automatically defined methods (assignment, copy constructor, destructor) are fine @@ -94,12 +97,12 @@ public: */ class PRectangle { public: - int left; - int top; - int right; - int bottom; + XYPOSITION left; + XYPOSITION top; + XYPOSITION right; + XYPOSITION bottom; - PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) : + PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : left(left_), top(top_), right(right_), bottom(bottom_) { } @@ -121,14 +124,14 @@ public: return (right > other.left) && (left < other.right) && (bottom > other.top) && (top < other.bottom); } - void Move(int xDelta, int yDelta) { + void Move(XYPOSITION xDelta, XYPOSITION yDelta) { left += xDelta; top += yDelta; right += xDelta; bottom += yDelta; } - int Width() { return right - left; } - int Height() { return bottom - top; } + XYPOSITION Width() { return right - left; } + XYPOSITION Height() { return bottom - top; } bool Empty() { return (Height() <= 0) || (Width() <= 0); } @@ -300,7 +303,7 @@ public: Font(); virtual ~Font(); - virtual void Create(const char *faceName, int characterSet, int size, + virtual void Create(const char *faceName, int characterSet, float size, bool bold, bool italic, int extraFontFlag=0); virtual void Release(); @@ -349,18 +352,18 @@ public: virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; - virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; - virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; - virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0; - virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0; - virtual int WidthText(Font &font_, const char *s, int len)=0; - virtual int WidthChar(Font &font_, char ch)=0; - virtual int Ascent(Font &font_)=0; - virtual int Descent(Font &font_)=0; - virtual int InternalLeading(Font &font_)=0; - virtual int ExternalLeading(Font &font_)=0; - virtual int Height(Font &font_)=0; - virtual int AverageCharWidth(Font &font_)=0; + virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; + virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; + virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore)=0; + virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0; + virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0; + virtual XYPOSITION WidthChar(Font &font_, char ch)=0; + virtual XYPOSITION Ascent(Font &font_)=0; + virtual XYPOSITION Descent(Font &font_)=0; + virtual XYPOSITION InternalLeading(Font &font_)=0; + virtual XYPOSITION ExternalLeading(Font &font_)=0; + virtual XYPOSITION Height(Font &font_)=0; + virtual XYPOSITION AverageCharWidth(Font &font_)=0; virtual int SetPalette(Palette *pal, bool inBackGround)=0; virtual void SetClip(PRectangle rc)=0; diff --git a/src/Editor.cxx b/src/Editor.cxx index 452666be7..f44279bbd 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2216,7 +2216,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou // Layout the line, determining the position of each character, // with an extra element at the end for the end of the line. int startseg = 0; // Start of the current segment, in char. number - int startsegx = 0; // Start of the current segment, in pixels + XYPOSITION startsegx = 0; // Start of the current segment, in pixels ll->positions[0] = 0; unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars; bool lastSegItalics = false; @@ -2902,8 +2902,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // draw strings that are completely past the right side of the window. if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { // Clip to line rectangle, since may have a huge position which will not work with some platforms - rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left); - rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right); + if (rcSegment.left < rcLine.left) + rcSegment.left = rcLine.left; + if (rcSegment.right > rcLine.right) + rcSegment.right = rcLine.right; int styleMain = ll->styles[i]; const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc); @@ -3379,7 +3381,7 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS const int spaceWidth = static_cast(vsDraw.styles[ll->EndLineStyle()].spaceWidth); const int virtualOffset = posCaret.VirtualSpace() * spaceWidth; if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { - int xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; + XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; if (ll->wrapIndent != 0) { int lineStart = ll->LineStart(subLine); if (lineStart != 0) // Wrapped diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 2105c292f..614e6b8bf 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -86,7 +86,7 @@ void LineLayout::Resize(int maxLineLength_) { indicators = new char[maxLineLength_ + 1]; // Extra position allocated as sometimes the Windows // GetTextExtentExPoint API writes an extra element. - positions = new int[maxLineLength_ + 1 + 1]; + positions = new XYPOSITION[maxLineLength_ + 1 + 1]; maxLineLength = maxLineLength_; } } @@ -503,15 +503,15 @@ PositionCacheEntry::PositionCacheEntry() : } void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_, - unsigned int len_, int *positions_, unsigned int clock_) { + unsigned int len_, XYPOSITION *positions_, unsigned int clock_) { Clear(); styleNumber = styleNumber_; len = len_; clock = clock_; if (s_ && positions_) { - positions = new short[len + (len + 1) / 2]; + positions = new XYPOSITION[len + (len + 1) / 2]; for (unsigned int i=0; i(positions_[i]); + positions[i] = static_cast(positions_[i]); } memcpy(reinterpret_cast(positions + len), s_, len); } @@ -530,7 +530,7 @@ void PositionCacheEntry::Clear() { } bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_, - unsigned int len_, int *positions_) const { + unsigned int len_, XYPOSITION *positions_) const { if ((styleNumber == styleNumber_) && (len == len_) && (memcmp(reinterpret_cast(positions + len), s_, len)== 0)) { for (unsigned int i=0; i BreakFinder::lengthStartSubdivision) { // Break up into segments unsigned int startSegment = 0; - int xStartSegment = 0; + XYPOSITION xStartSegment = 0; while (startSegment < len) { unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision); surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment); diff --git a/src/PositionCache.h b/src/PositionCache.h index c6076ea20..280446627 100644 --- a/src/PositionCache.h +++ b/src/PositionCache.h @@ -41,7 +41,7 @@ public: unsigned char *styles; int styleBitsSet; char *indicators; - int *positions; + XYPOSITION *positions; char bracePreviousStyles[2]; // Hotspot support @@ -103,13 +103,13 @@ class PositionCacheEntry { unsigned int styleNumber:8; unsigned int len:8; unsigned int clock:16; - short *positions; + XYPOSITION *positions; public: PositionCacheEntry(); ~PositionCacheEntry(); - void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_, unsigned int clock); + void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock); void Clear(); - bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_) const; + bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const; static int Hash(unsigned int styleNumber_, const char *s, unsigned int len); bool NewerThan(const PositionCacheEntry &other) const; void ResetClock(); @@ -155,7 +155,7 @@ public: void SetSize(size_t size_); size_t GetSize() const { return size; } void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, - const char *s, unsigned int len, int *positions, Document *pdoc); + const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); }; inline bool IsSpaceOrTab(int ch) { diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 2ba4ed374..d4a015cf9 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -273,20 +273,20 @@ class FontCached : Font { int usage; LOGFONTA lf; int hash; - FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_); + FontCached(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); ~FontCached() {} - bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_); + bool SameAs(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); 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 char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); static void ReleaseId(FontID fid_); }; FontCached *FontCached::first = 0; -FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) : +FontCached::FontCached(const char *faceName_, int characterSet_, float 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_); @@ -338,7 +338,7 @@ FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool usage = 1; } -bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) { +bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_) { return (lf.lfHeight == -(abs(size_))) && (lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) && @@ -353,7 +353,7 @@ void FontCached::Release() { fid = 0; } -FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) { +FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_) { FontID ret = 0; ::EnterCriticalSection(&crPlatformLock); int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_); @@ -404,7 +404,7 @@ Font::~Font() { #define FONTS_CACHED -void Font::Create(const char *faceName, int characterSet, int size, +void Font::Create(const char *faceName, int characterSet, float size, bool bold, bool italic, int extraFontFlag) { Release(); if (faceName) @@ -481,19 +481,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); @@ -664,6 +664,10 @@ static int Delta(int difference) { return 0; } +static int RoundFloat(float f) { + return int(f+0.5); +} + void SurfaceImpl::LineTo(int x_, int y_) { if (pRenderTarget) { int xDiff = x_ - x; @@ -726,7 +730,7 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllo void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { D2DPenColour(back); - D2D1_RECT_F rectangle1 = D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5); + 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); @@ -737,7 +741,7 @@ void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAlloc void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { if (pRenderTarget) { D2DPenColour(back); - D2D1_RECT_F rectangle1 = D2D1::RectF(rc.left, rc.top, rc.right, rc.bottom); + D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left), rc.top, RoundFloat(rc.right), rc.bottom); pRenderTarget->FillRectangle(&rectangle1, pBrush); } } @@ -903,9 +907,9 @@ public: } } }; -typedef VarBuffer TextPositions; +typedef VarBuffer TextPositions; -void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT) { +void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT) { SetFont(font_); RECT rcw = RectFromPRectangle(rc); @@ -919,7 +923,7 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const ch rc.Width()+2, rc.Height(), &pTextLayout); if (SUCCEEDED(hr)) { D2D1_POINT_2F origin = {rc.left, ybase-baseline}; - pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush); + pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE); } else { D2D1_RECT_F layoutRect = D2D1::RectF( static_cast(rcw.left) / dpiScaleX, @@ -931,7 +935,7 @@ 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 SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -940,7 +944,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch } } -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -949,7 +953,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const c } } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::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(tbuf.tlen)); @@ -1064,7 +1069,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi } } -int SurfaceImpl::WidthChar(Font &font_, char ch) { +XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { FLOAT width = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { @@ -1082,7 +1087,7 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) { return int(width + 0.5); } -int SurfaceImpl::Ascent(Font &font_) { +XYPOSITION SurfaceImpl::Ascent(Font &font_) { FLOAT ascent = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { @@ -1114,7 +1119,7 @@ int SurfaceImpl::Ascent(Font &font_) { return int(ascent + 0.5); } -int SurfaceImpl::Descent(Font &font_) { +XYPOSITION SurfaceImpl::Descent(Font &font_) { FLOAT descent = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { @@ -1135,15 +1140,15 @@ int SurfaceImpl::Descent(Font &font_) { return int(descent + 0.5); } -int SurfaceImpl::InternalLeading(Font &) { +XYPOSITION SurfaceImpl::InternalLeading(Font &) { return 0; } -int SurfaceImpl::ExternalLeading(Font &) { +XYPOSITION SurfaceImpl::ExternalLeading(Font &) { return 1; } -int SurfaceImpl::Height(Font &font_) { +XYPOSITION SurfaceImpl::Height(Font &font_) { FLOAT height = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { @@ -1165,7 +1170,7 @@ int SurfaceImpl::Height(Font &font_) { return int(height); } -int SurfaceImpl::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { FLOAT width = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { -- cgit v1.2.3 From f1312ec5dae1622c262a3a98526e8c59734b2477 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Tue, 2 Aug 2011 12:08:06 +1000 Subject: Implemented floating point text positioning for Cocoa. --- cocoa/PlatCocoa.h | 24 +++++++++++----------- cocoa/PlatCocoa.mm | 40 +++++++++++++++++++++--------------- cocoa/ScintillaTest/AppController.mm | 2 +- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/cocoa/PlatCocoa.h b/cocoa/PlatCocoa.h index 0e3c5f2e2..7f6a59705 100644 --- a/cocoa/PlatCocoa.h +++ b/cocoa/PlatCocoa.h @@ -96,20 +96,20 @@ public: void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage); void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource); - void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, + void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION 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, + void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION 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 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(Scintilla::Palette *pal, bool inBackGround); void SetClip(PRectangle rc); diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm index 75803e33b..1972fa7a9 100644 --- a/cocoa/PlatCocoa.mm +++ b/cocoa/PlatCocoa.mm @@ -156,7 +156,7 @@ static int FontCharacterSet(Font &f) { /** * Creates a CTFontRef with the given properties. */ -void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic, +void Font::Create(const char *faceName, int characterSet, float size, bool bold, bool italic, int /* extraFontFlag */) { Release(); @@ -507,6 +507,9 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) if (gc) { FillColour(back); + // Snap rectangle boundaries to nearest int + rc.left = lround(rc.left); + rc.right = lround(rc.right); CGRect rect = PRectangleToCGRect(rc); CGContextFillRect(gc, rect); } @@ -641,7 +644,10 @@ void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, C { if ( gc ) { ColourDesired colour( fill.AsLong() ); - + + // Snap rectangle boundaries to nearest int + rc.left = lround(rc.left); + rc.right = lround(rc.right); // Set the Fill color to match CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 ); CGRect rect = PRectangleToCGRect( rc ); @@ -836,7 +842,7 @@ void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSou //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { FillRectangle(rc, back); @@ -845,7 +851,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { CGContextSaveGState(gc); @@ -913,7 +919,7 @@ CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet) } } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore) { CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); @@ -943,7 +949,7 @@ static size_t utf8LengthFromLead(unsigned char uch) { //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) +void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) { CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); textLayout->setText (reinterpret_cast(s), len, encoding, *reinterpret_cast(font_.GetID())); @@ -962,7 +968,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi size_t codeUnits = (lenChar < 4) ? 1 : 2; CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL); for (unsigned int bytePos=0; (bytePos(lround(xPosition)); + positions[i++] = xPosition; } ui += codeUnits; } @@ -978,20 +984,20 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi size_t lenChar = Platform::IsDBCSLeadByte(codePage, s[i]) ? 2 : 1; CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL); for (unsigned int bytePos=0; (bytePos(lround(xPosition)); + positions[i++] = xPosition; } ui++; } } else { // Single byte encoding for (int i=0;i(lround(xPosition)); + positions[i] = xPosition; } } } -int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { +XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { if (font_.GetID()) { CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); @@ -1002,7 +1008,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { return 1; } -int SurfaceImpl::WidthChar(Font &font_, char ch) { +XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { char str[2] = { ch, '\0' }; if (font_.GetID()) { @@ -1019,7 +1025,7 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) { const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -int SurfaceImpl::Ascent(Font &font_) { +XYPOSITION SurfaceImpl::Ascent(Font &font_) { if (!font_.GetID()) return 1; @@ -1028,7 +1034,7 @@ int SurfaceImpl::Ascent(Font &font_) { } -int SurfaceImpl::Descent(Font &font_) { +XYPOSITION SurfaceImpl::Descent(Font &font_) { if (!font_.GetID()) return 1; @@ -1037,11 +1043,11 @@ int SurfaceImpl::Descent(Font &font_) { } -int SurfaceImpl::InternalLeading(Font &) { +XYPOSITION SurfaceImpl::InternalLeading(Font &) { return 0; } -int SurfaceImpl::ExternalLeading(Font &font_) { +XYPOSITION SurfaceImpl::ExternalLeading(Font &font_) { if (!font_.GetID()) return 1; @@ -1050,13 +1056,13 @@ int SurfaceImpl::ExternalLeading(Font &font_) { } -int SurfaceImpl::Height(Font &font_) { +XYPOSITION SurfaceImpl::Height(Font &font_) { int ht = Ascent(font_) + Descent(font_); return ht; } -int SurfaceImpl::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { if (!font_.GetID()) return 1; diff --git a/cocoa/ScintillaTest/AppController.mm b/cocoa/ScintillaTest/AppController.mm index 4c8801a33..fbcdad9a8 100644 --- a/cocoa/ScintillaTest/AppController.mm +++ b/cocoa/ScintillaTest/AppController.mm @@ -116,7 +116,7 @@ const char user_keywords[] = // Definition of own keywords, not used by MySQL. [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords]; // Colors and styles for various syntactic elements. First the default style. - [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Andale Mono"]; + [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Helvetica"]; // [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font. [mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14]; [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]]; -- cgit v1.2.3 From 46a0809b348e8c7c67fa1631e16eee016e23ff4c Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Tue, 2 Aug 2011 13:22:10 +1000 Subject: Use SEMI_BOLD for bold as Segoe UI looks better at semi bold than bold. Allow fractional font sizes by multiplying by 1000. --- win32/PlatWin.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index d4a015cf9..9e9ead409 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -313,8 +313,10 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, bo WCHAR wszFace[faceSize]; UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); FLOAT fHeight = size_; + if (fHeight > 2000) + fHeight = fHeight / 1000.0f; HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL, - bold_ ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR, + bold_ ? DWRITE_FONT_WEIGHT_SEMI_BOLD : DWRITE_FONT_WEIGHT_REGULAR, italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat); if (SUCCEEDED(hr)) { -- cgit v1.2.3 From d3c506ee2553d7f1da5907f4d5f9589d26b175a9 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Wed, 3 Aug 2011 11:19:33 +1000 Subject: Fixed some warnings. --- win32/PlatWin.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 9e9ead409..acbb5f62d 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -514,7 +514,8 @@ public: SurfaceImpl::SurfaceImpl() : unicodeMode(false), - hdc(0), hdcOwned(false) { + hdc(0), hdcOwned(false), + x(0), y(0), { // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels maxWidthMeasure = IsNT() ? INT_MAX : 30000; // There appears to be a 16 bit string length limit in GDI on NT and a limit of -- cgit v1.2.3 From f3787820600bc07008841b82037e90032619bdaa Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 13:41:35 +1000 Subject: Implement APIs for fractional font sizes and a range of weights. --- include/Platform.h | 2 +- include/Scintilla.h | 8 +++++++ include/Scintilla.iface | 19 +++++++++++++++++ src/Editor.cxx | 18 ++++++++++++++-- src/Style.cxx | 20 ++++++++--------- src/Style.h | 8 +++---- src/ViewStyle.cxx | 12 +++++------ win32/PlatWin.cxx | 57 +++++++++++++++++++++++++------------------------ win32/ScintillaWin.cxx | 8 +++---- 9 files changed, 97 insertions(+), 55 deletions(-) diff --git a/include/Platform.h b/include/Platform.h index d4c6bbfec..d23a932e4 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -304,7 +304,7 @@ public: virtual ~Font(); virtual void Create(const char *faceName, int characterSet, float size, - bool bold, bool italic, int extraFontFlag=0); + int weight, bool italic, int extraFontFlag=0); virtual void Release(); FontID GetID() { return fid; } diff --git a/include/Scintilla.h b/include/Scintilla.h index 34e4f793d..c7b9944d8 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -221,6 +221,14 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_STYLEGETCHANGEABLE 2492 #define SCI_STYLEGETHOTSPOT 2493 #define SCI_STYLESETCASE 2060 +#define SC_FONT_SIZE_MULTIPLIER 100 +#define SCI_STYLESETSIZEFRACTIONAL 2061 +#define SCI_STYLEGETSIZEFRACTIONAL 2062 +#define SC_WEIGHT_NORMAL 400 +#define SC_WEIGHT_SEMIBOLD 600 +#define SC_WEIGHT_BOLD 700 +#define SCI_STYLESETWEIGHT 2063 +#define SCI_STYLEGETWEIGHT 2064 #define SCI_STYLESETCHARACTERSET 2066 #define SCI_STYLESETHOTSPOT 2409 #define SCI_SETSELFORE 2067 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 36ead0ece..c604f621a 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -482,6 +482,25 @@ get bool StyleGetHotSpot=2493(int style,) # Set a style to be mixed case, or to force upper or lower case. set void StyleSetCase=2060(int style, int caseForce) +val SC_FONT_SIZE_MULTIPLIER=100 + +# Set the size of characters of a style. Size is in points multiplied by 100. +set void StyleSetSizeFractional=2061(int style, int caseForce) + +# Get the weight of characters of a style in points multiplied by 100 +get int StyleGetSizeFractional=2062(int style,) + +enu FontWeight=SC_WEIGHT_ +val SC_WEIGHT_NORMAL=400 +val SC_WEIGHT_SEMIBOLD=600 +val SC_WEIGHT_BOLD=700 + +# Get the weight of characters of a style. +set void StyleSetWeight=2063(int style, int weight) + +# Get the weight of characters of a style. +get int StyleGetWeight=2064(int style,) + # Set the character set of the font in a style. set void StyleSetCharacterSet=2066(int style, int characterSet) diff --git a/src/Editor.cxx b/src/Editor.cxx index f44279bbd..7261ac7d2 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -6981,7 +6981,10 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].back.desired = ColourDesired(lParam); break; case SCI_STYLESETBOLD: - vs.styles[wParam].bold = lParam != 0; + vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; + break; + case SCI_STYLESETWEIGHT: + vs.styles[wParam].weight = lParam; break; case SCI_STYLESETITALIC: vs.styles[wParam].italic = lParam != 0; @@ -6990,6 +6993,9 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].eolFilled = lParam != 0; break; case SCI_STYLESETSIZE: + vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER; + break; + case SCI_STYLESETSIZEFRACTIONAL: vs.styles[wParam].size = lParam; break; case SCI_STYLESETFONT: @@ -7027,12 +7033,16 @@ sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPar case SCI_STYLEGETBACK: return vs.styles[wParam].back.desired.AsLong(); case SCI_STYLEGETBOLD: - return vs.styles[wParam].bold ? 1 : 0; + return vs.styles[wParam].weight > SC_WEIGHT_NORMAL; + case SCI_STYLEGETWEIGHT: + return vs.styles[wParam].weight; case SCI_STYLEGETITALIC: return vs.styles[wParam].italic ? 1 : 0; case SCI_STYLEGETEOLFILLED: return vs.styles[wParam].eolFilled ? 1 : 0; case SCI_STYLEGETSIZE: + return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER; + case SCI_STYLEGETSIZEFRACTIONAL: return vs.styles[wParam].size; case SCI_STYLEGETFONT: if (!vs.styles[wParam].fontName) @@ -8150,9 +8160,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_STYLESETFORE: case SCI_STYLESETBACK: case SCI_STYLESETBOLD: + case SCI_STYLESETWEIGHT: case SCI_STYLESETITALIC: case SCI_STYLESETEOLFILLED: case SCI_STYLESETSIZE: + case SCI_STYLESETSIZEFRACTIONAL: case SCI_STYLESETFONT: case SCI_STYLESETUNDERLINE: case SCI_STYLESETCASE: @@ -8166,9 +8178,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_STYLEGETFORE: case SCI_STYLEGETBACK: case SCI_STYLEGETBOLD: + case SCI_STYLEGETWEIGHT: case SCI_STYLEGETITALIC: case SCI_STYLEGETEOLFILLED: case SCI_STYLEGETSIZE: + case SCI_STYLEGETSIZEFRACTIONAL: case SCI_STYLEGETFONT: case SCI_STYLEGETUNDERLINE: case SCI_STYLEGETCASE: diff --git a/src/Style.cxx b/src/Style.cxx index fc250f0bc..0a38cd6a5 100644 --- a/src/Style.cxx +++ b/src/Style.cxx @@ -33,7 +33,7 @@ void FontAlias::ClearFont() { } bool FontSpecification::EqualTo(const FontSpecification &other) const { - return bold == other.bold && + return weight == other.weight && italic == other.italic && size == other.size && characterSet == other.characterSet && @@ -56,18 +56,18 @@ void FontMeasurements::Clear() { Style::Style() : FontSpecification() { Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), - Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT, - false, false, false, false, caseMixed, true, true, false); + Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, 0, SC_CHARSET_DEFAULT, + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); } Style::Style(const Style &source) : FontSpecification(), FontMeasurements() { Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), 0, 0, 0, - false, false, false, false, caseMixed, true, true, false); + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); fore.desired = source.fore.desired; back.desired = source.back.desired; characterSet = source.characterSet; - bold = source.bold; + weight = source.weight; italic = source.italic; size = source.size; eolFilled = source.eolFilled; @@ -86,11 +86,11 @@ Style &Style::operator=(const Style &source) { return * this; Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), 0, 0, SC_CHARSET_DEFAULT, - false, false, false, false, caseMixed, true, true, false); + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); fore.desired = source.fore.desired; back.desired = source.back.desired; characterSet = source.characterSet; - bold = source.bold; + weight = source.weight; italic = source.italic; size = source.size; eolFilled = source.eolFilled; @@ -103,13 +103,13 @@ Style &Style::operator=(const Style &source) { void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_, const char *fontName_, int characterSet_, - bool bold_, bool italic_, bool eolFilled_, + int weight_, bool italic_, bool eolFilled_, bool underline_, ecaseForced caseForce_, bool visible_, bool changeable_, bool hotspot_) { fore.desired = fore_; back.desired = back_; characterSet = characterSet_; - bold = bold_; + weight = weight_; italic = italic_; size = size_; fontName = fontName_; @@ -130,7 +130,7 @@ void Style::ClearTo(const Style &source) { source.size, source.fontName, source.characterSet, - source.bold, + source.weight, source.italic, source.eolFilled, source.underline, diff --git a/src/Style.h b/src/Style.h index 29122b0a4..0e706d322 100644 --- a/src/Style.h +++ b/src/Style.h @@ -14,16 +14,16 @@ namespace Scintilla { struct FontSpecification { const char *fontName; - bool bold; + int weight; bool italic; int size; int characterSet; int extraFontFlag; FontSpecification() : fontName(0), - bold(false), + weight(SC_WEIGHT_NORMAL), italic(false), - size(10), + size(10 * SC_FONT_SIZE_MULTIPLIER), characterSet(0), extraFontFlag(0) { } @@ -77,7 +77,7 @@ public: void Clear(ColourDesired fore_, ColourDesired back_, int size_, const char *fontName_, int characterSet_, - bool bold_, bool italic_, bool eolFilled_, + int weight_, bool italic_, bool eolFilled_, bool underline_, ecaseForced caseForce_, bool visible_, bool changeable_, bool hotspot_); void ClearTo(const Style &source); diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 9ba69b1ce..b46cd9eb4 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -88,12 +88,12 @@ FontRealised::~FontRealised() { void FontRealised::Realise(Surface &surface, int zoomLevel) { PLATFORM_ASSERT(fontName); - sizeZoomed = size + zoomLevel; - if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1 - sizeZoomed = 2; + sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER; + if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 + sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; int deviceHeight = surface.DeviceHeightFont(sizeZoomed); - font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag); + font.Create(fontName, characterSet, deviceHeight, weight, italic, extraFontFlag); ascent = surface.Ascent(font); descent = surface.Descent(font); @@ -457,9 +457,9 @@ void ViewStyle::EnsureStyle(size_t index) { void ViewStyle::ResetDefaultStyle() { styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0), ColourDesired(0xff,0xff,0xff), - Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()), + Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()), SC_CHARSET_DEFAULT, - false, false, false, false, Style::caseMixed, true, true, false); + SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false); } void ViewStyle::ClearStyles() { diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index acbb5f62d..b22cd10a1 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -242,11 +242,13 @@ static BYTE Win32MapFontQuality(int extraFontFlag) { } } -static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) { +const int fontSizeMultiplier = 100; + +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(size/fontSizeMultiplier))); + lf.lfWeight = weight; lf.lfItalic = static_cast(italic ? 1 : 0); lf.lfCharSet = static_cast(characterSet); lf.lfQuality = Win32MapFontQuality(extraFontFlag); @@ -258,12 +260,12 @@ 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 char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) { return - size ^ + static_cast((size / fontSizeMultiplier)) ^ (characterSet << 10) ^ ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^ - (bold ? 0x10000000 : 0) ^ + ((weight/100) << 12) ^ (italic ? 0x20000000 : 0) ^ faceName[0]; } @@ -271,25 +273,26 @@ static int HashFont(const char *faceName, int characterSet, int size, bool bold, class FontCached : Font { FontCached *next; int usage; + float size; LOGFONTA lf; int hash; - FontCached(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); + FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_); ~FontCached() {} - bool SameAs(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); + bool SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_); virtual void Release(); static FontCached *first; public: - static FontID FindOrCreate(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_); + static FontID FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_); static void ReleaseId(FontID fid_); }; FontCached *FontCached::first = 0; -FontCached::FontCached(const char *faceName_, int characterSet_, float 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_); +FontCached::FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_) : + next(0), usage(0), size(1.0), hash(0) { + SetLogFont(lf, faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); + hash = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); fid = 0; EnsureDWriteFactory(); if (pIDWriteFactory) { @@ -312,11 +315,9 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, bo const int faceSize = 200; WCHAR wszFace[faceSize]; UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); - FLOAT fHeight = size_; - if (fHeight > 2000) - fHeight = fHeight / 1000.0f; + FLOAT fHeight = size_ / fontSizeMultiplier; HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL, - bold_ ? DWRITE_FONT_WEIGHT_SEMI_BOLD : DWRITE_FONT_WEIGHT_REGULAR, + static_cast(weight_), italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat); if (SUCCEEDED(hr)) { @@ -325,7 +326,7 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, bo UINT32 lineCount = 0; FLOAT baseline = 1.0f; IDWriteTextLayout *pTextLayout = 0; - HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, + hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 100.0f, 100.0f, &pTextLayout); if (SUCCEEDED(hr)) { hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); @@ -340,10 +341,10 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, bo usage = 1; } -bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_) { +bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_) { return - (lf.lfHeight == -(abs(size_))) && - (lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) && + (size == size_) && + (lf.lfWeight == weight_) && (lf.lfItalic == static_cast(italic_ ? 1 : 0)) && (lf.lfCharSet == characterSet_) && (lf.lfQuality == Win32MapFontQuality(extraFontFlag_)) && @@ -355,19 +356,19 @@ void FontCached::Release() { fid = 0; } -FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, bool bold_, bool italic_, int extraFontFlag_) { +FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_) { FontID ret = 0; ::EnterCriticalSection(&crPlatformLock); - int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_); + int hashFind = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); for (FontCached *cur=first; cur; cur=cur->next) { if ((cur->hash == hashFind) && - cur->SameAs(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_)) { + cur->SameAs(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_)) { cur->usage++; ret = cur->fid; } } if (ret == 0) { - FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_); + FontCached *fc = new FontCached(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); if (fc) { fc->next = first; first = fc; @@ -407,10 +408,10 @@ Font::~Font() { #define FONTS_CACHED void Font::Create(const char *faceName, int characterSet, float size, - bool bold, bool italic, int extraFontFlag) { + int weight, bool italic, int extraFontFlag) { Release(); if (faceName) - fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic, extraFontFlag); + fid = FontCached::FindOrCreate(faceName, characterSet, size, weight, italic, extraFontFlag); } void Font::Release() { @@ -515,7 +516,7 @@ public: SurfaceImpl::SurfaceImpl() : unicodeMode(false), hdc(0), hdcOwned(false), - x(0), y(0), { + x(0), y(0) { // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels maxWidthMeasure = IsNT() ? INT_MAX : 30000; // There appears to be a 16 bit string length limit in GDI on NT and a limit of diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 28e48596b..6bc770eed 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -2151,9 +2151,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) { @@ -2161,7 +2161,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(vs.styles[styleHere].italic ? 1 : 0); lf.lfCharSet = DEFAULT_CHARSET; lf.lfFaceName[0] = '\0'; -- cgit v1.2.3 From 505a8527964a09b139ed3ef13923b7c8c3b42228 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 14:18:37 +1000 Subject: Move scaling of font to pixels up into platform-independent code. --- src/ViewStyle.cxx | 4 ++-- win32/PlatWin.cxx | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index b46cd9eb4..b722f8d02 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -92,8 +92,8 @@ void FontRealised::Realise(Surface &surface, int zoomLevel) { if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; - int deviceHeight = surface.DeviceHeightFont(sizeZoomed); - font.Create(fontName, characterSet, deviceHeight, weight, italic, extraFontFlag); + float deviceHeight = surface.DeviceHeightFont(sizeZoomed); + font.Create(fontName, characterSet, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag); ascent = surface.Ascent(font); descent = surface.Descent(font); diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index b22cd10a1..b0fbd2543 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -242,12 +242,10 @@ static BYTE Win32MapFontQuality(int extraFontFlag) { } } -const int fontSizeMultiplier = 100; - 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(static_cast(size/fontSizeMultiplier))); + lf.lfHeight = -(abs(static_cast(size))); lf.lfWeight = weight; lf.lfItalic = static_cast(italic ? 1 : 0); lf.lfCharSet = static_cast(characterSet); @@ -262,7 +260,7 @@ static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, flo */ static int HashFont(const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) { return - static_cast((size / fontSizeMultiplier)) ^ + static_cast(size) ^ (characterSet << 10) ^ ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^ ((weight/100) << 12) ^ @@ -315,7 +313,7 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in const int faceSize = 200; WCHAR wszFace[faceSize]; UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); - FLOAT fHeight = size_ / fontSizeMultiplier; + FLOAT fHeight = size_; HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL, static_cast(weight_), italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, -- cgit v1.2.3 From d7d7eab8c6553f8798f6ea1730cd2ea0cd33564b Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 19:38:46 +1000 Subject: Avoid warnings about unavailable warnings. --- cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj index 7765983a8..5ec9eb93a 100644 --- a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj +++ b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj @@ -955,7 +955,7 @@ SCI_LEXER, ); GCC_VERSION = com.apple.compilers.llvmgcc42; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; @@ -984,7 +984,7 @@ SCI_LEXER, ); GCC_VERSION = com.apple.compilers.llvmgcc42; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; -- cgit v1.2.3 From 83a58ae4efb07e4d2de8cb21e5cca86a26f138ce Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 19:39:15 +1000 Subject: Support a range of weights on Cocoa. --- cocoa/PlatCocoa.mm | 2 +- cocoa/QuartzTextStyleAttribute.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm index 1972fa7a9..0965409c1 100644 --- a/cocoa/PlatCocoa.mm +++ b/cocoa/PlatCocoa.mm @@ -156,7 +156,7 @@ static int FontCharacterSet(Font &f) { /** * Creates a CTFontRef with the given properties. */ -void Font::Create(const char *faceName, int characterSet, float size, bool bold, bool italic, +void Font::Create(const char *faceName, int characterSet, float size, int weight, bool italic, int /* extraFontFlag */) { Release(); diff --git a/cocoa/QuartzTextStyleAttribute.h b/cocoa/QuartzTextStyleAttribute.h index 33c49281c..b9698645e 100644 --- a/cocoa/QuartzTextStyleAttribute.h +++ b/cocoa/QuartzTextStyleAttribute.h @@ -16,12 +16,13 @@ class QuartzFont { public: /** Create a font style from a name. */ - QuartzFont( const char* name, size_t length, float size, bool bold, bool italic ) + QuartzFont( const char* name, size_t length, float size, int weight, bool italic ) { assert( name != NULL && length > 0 && name[length] == '\0' ); CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman); assert(fontName != NULL); + bool bold = weight > SC_WEIGHT_NORMAL; if (bold || italic) { -- cgit v1.2.3 From ea07369a205b6a273e3c4b0e70ab16a93f6d9d9a Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 20:13:19 +1000 Subject: Implement fractional widths and range of weights for GTK+. --- gtk/PlatGTK.cxx | 132 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index b8ee6b385..9f24e1b1d 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -94,7 +94,7 @@ enum encodingType { singleByte, UTF8, dbcs}; struct LOGFONT { int size; - bool bold; + int weight; bool italic; int characterSet; char faceName[300]; @@ -445,10 +445,10 @@ static void GenerateFontSpecStrings(const char *fontName, int characterSet, #endif -static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int size, bool bold, bool italic) { +static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) { memset(&lf, 0, sizeof(lf)); lf.size = size; - lf.bold = bold; + lf.weight = weight; lf.italic = italic; lf.characterSet = characterSet; strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1); @@ -459,11 +459,11 @@ static void SetLogFont(LOGFONT &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) { +static int HashFont(const char *faceName, int characterSet, int size, int weight, bool italic) { return size ^ (characterSet << 10) ^ - (bold ? 0x10000000 : 0) ^ + ((weight / 100) << 12) ^ (italic ? 0x20000000 : 0) ^ faceName[0]; } @@ -473,32 +473,32 @@ class FontCached : Font { int usage; LOGFONT lf; int hash; - FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_); + FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); ~FontCached() {} - bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_); + bool SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); virtual void Release(); static FontID CreateNewFont(const char *fontName, int characterSet, - int size, bool bold, bool italic); + float size, int weight, bool italic); static FontCached *first; public: - static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_); + static FontID FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); static void ReleaseId(FontID fid_); }; FontCached *FontCached::first = 0; -FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) : +FontCached::FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) : next(0), usage(0), hash(0) { - ::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_); - hash = HashFont(faceName_, characterSet_, size_, bold_, italic_); - fid = CreateNewFont(faceName_, characterSet_, size_, bold_, italic_); + ::SetLogFont(lf, faceName_, characterSet_, size_, weight_, italic_); + hash = HashFont(faceName_, characterSet_, size_, weight_, italic_); + fid = CreateNewFont(faceName_, characterSet_, size_, weight_, italic_); usage = 1; } -bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) { +bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) { return lf.size == size_ && - lf.bold == bold_ && + lf.weight == weight_ && lf.italic == italic_ && lf.characterSet == characterSet_ && 0 == strcmp(lf.faceName, faceName_); @@ -510,19 +510,19 @@ void FontCached::Release() { fid = 0; } -FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) { +FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) { FontID ret = 0; FontMutexLock(); - int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_); + int hashFind = HashFont(faceName_, characterSet_, size_, weight_, italic_); for (FontCached *cur = first; cur; cur = cur->next) { if ((cur->hash == hashFind) && - cur->SameAs(faceName_, characterSet_, size_, bold_, italic_)) { + cur->SameAs(faceName_, characterSet_, size_, weight_, italic_)) { cur->usage++; ret = cur->fid; } } if (ret == 0) { - FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_); + FontCached *fc = new FontCached(faceName_, characterSet_, size_, weight_, italic_); if (fc) { fc->next = first; first = fc; @@ -563,13 +563,13 @@ static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) { #endif FontID FontCached::CreateNewFont(const char *fontName, int characterSet, - int size, bool bold, bool italic) { + float size, int weight, bool italic) { if (fontName[0] == '!') { PangoFontDescription *pfd = pango_font_description_new(); if (pfd) { pango_font_description_set_family(pfd, fontName+1); - pango_font_description_set_size(pfd, size * PANGO_SCALE); - pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); + pango_font_description_set_size(pfd, pango_units_from_double(size)); + pango_font_description_set_weight(pfd, static_cast(weight)); pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); return new FontHandle(pfd, characterSet); } @@ -638,7 +638,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, sizeof(fontspec) - 1, spec, foundary, faceName, - bold ? "-bold" : "-medium", + (weight > 400) ? "-bold" : "-medium", italic ? "-i" : "-r", size * 10, charset); @@ -654,7 +654,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, sizeof(fontspec) - 1, ",%s%s%s-o-*-*-*-%0d-*-*-*-*-%s", foundary, faceName, - bold ? "-bold" : "-medium", + (weight > 400) ? "-bold" : "-medium", size * 10, charset); } @@ -688,7 +688,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, sizeof(fontspec) - 1, "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s", foundary, faceName, - bold ? "-bold" : "-medium", + (weight > 400) ? "-bold" : "-medium", italic ? "-i" : "-r", size * 10, charset); @@ -699,7 +699,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, sizeof(fontspec) - 1, "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s", foundary, faceName, - bold ? "-bold" : "-medium", + (weight > 400) ? "-bold" : "-medium", italic ? "-o" : "-r", size * 10, charset); @@ -729,10 +729,10 @@ Font::Font() : fid(0) {} Font::~Font() {} -void Font::Create(const char *faceName, int characterSet, int size, - bool bold, bool italic, int) { +void Font::Create(const char *faceName, int characterSet, float size, + int weight, bool italic, int) { Release(); - fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic); + fid = FontCached::FindOrCreate(faceName, characterSet, size, weight, italic); } void Font::Release() { @@ -792,19 +792,19 @@ public: void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); - void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore); - 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 DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore); + 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); @@ -1581,7 +1581,7 @@ static size_t UTF8CharLength(const char *s) { const int maxLengthTextRun = 10000; -void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore) { PenColour(fore); #ifdef USE_CAIRO @@ -1589,7 +1589,7 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char #else if (gc && drawable) { #endif - int xText = rc.left; + XYPOSITION xText = rc.left; if (PFont(font_)->pfd) { char *utfForm = 0; bool useGFree = false; @@ -1685,20 +1685,20 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char } } -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { FillRectangle(rc, back); DrawTextBase(rc, font_, ybase, s, len, fore); } // On GTK+, exactly same as DrawTextNoClip -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { FillRectangle(rc, back); DrawTextBase(rc, font_, ybase, s, len, fore); } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, +void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore) { // Avoid drawing spaces in transparent mode for (int i=0;ipfd) { @@ -1904,7 +1904,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi } } -int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { +XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { if (font_.GetID()) { if (PFont(font_)->pfd) { char *utfForm = 0; @@ -1938,7 +1938,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { } else { delete []utfForm; } - return PANGO_PIXELS(pos.width); + return pango_units_to_double(pos.width); } #ifndef DISABLE_GDK_FONT if (et == UTF8) { @@ -1958,7 +1958,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { } } -int SurfaceImpl::WidthChar(Font &font_, char ch) { +XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { if (font_.GetID()) { if (PFont(font_)->pfd) { return WidthText(font_, &ch, 1); @@ -1990,7 +1990,7 @@ const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; #endif -int SurfaceImpl::Ascent(Font &font_) { +XYPOSITION SurfaceImpl::Ascent(Font &font_) { if (!(font_.GetID())) return 1; #ifdef FAST_WAY @@ -2000,7 +2000,7 @@ int SurfaceImpl::Ascent(Font &font_) { PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, PFont(font_)->pfd, pango_context_get_language(pcontext)); PFont(font_)->ascent = - PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); + pango_units_to_double(pango_font_metrics_get_ascent(metrics)); pango_font_metrics_unref(metrics); ascent = PFont(font_)->ascent; } @@ -2028,7 +2028,7 @@ int SurfaceImpl::Ascent(Font &font_) { #endif } -int SurfaceImpl::Descent(Font &font_) { +XYPOSITION SurfaceImpl::Descent(Font &font_) { if (!(font_.GetID())) return 1; #ifdef FAST_WAY @@ -2036,7 +2036,7 @@ int SurfaceImpl::Descent(Font &font_) { if (PFont(font_)->pfd) { PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, PFont(font_)->pfd, pango_context_get_language(pcontext)); - int descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); + int descent = pango_units_to_double(pango_font_metrics_get_descent(metrics)); pango_font_metrics_unref(metrics); return descent; } @@ -2059,19 +2059,19 @@ int SurfaceImpl::Descent(Font &font_) { #endif } -int SurfaceImpl::InternalLeading(Font &) { +XYPOSITION SurfaceImpl::InternalLeading(Font &) { return 0; } -int SurfaceImpl::ExternalLeading(Font &) { +XYPOSITION SurfaceImpl::ExternalLeading(Font &) { return 0; } -int SurfaceImpl::Height(Font &font_) { +XYPOSITION SurfaceImpl::Height(Font &font_) { return Ascent(font_) + Descent(font_); } -int SurfaceImpl::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { return WidthChar(font_, 'n'); } @@ -2855,7 +2855,7 @@ void Menu::Show(Point pt, Window &) { pt.y = screenHeight - requisition.height; } gtk_menu_popup(widget, NULL, NULL, MenuPositionFunc, - reinterpret_cast((pt.y << 16) | pt.x), 0, + reinterpret_cast((static_cast(pt.y) << 16) | static_cast(pt.x)), 0, gtk_get_current_event_time()); } @@ -2976,7 +2976,7 @@ bool Platform::IsDBCSLeadByte(int codePage, char ch) { // Shift_jis return ((uch >= 0x81) && (uch <= 0x9F)) || ((uch >= 0xE0) && (uch <= 0xFC)); - // Lead bytes F0 to FC may be a Microsoft addition. + // Lead bytes F0 to FC may be a Microsoft addition. case 936: // GBK return (uch >= 0x81) && (uch <= 0xFE); -- cgit v1.2.3 From a87f9b8b42dc830045972b772d61009f45bbf551 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 21:28:48 +1000 Subject: Dynamically loading Direct2D and DirectWrite at run time so can run on Windows XP. --- win32/PlatWin.cxx | 51 ++++++++++++++++++++++++++++++++++---------------- win32/PlatWin.h | 13 +++++++++++++ win32/ScintillaWin.cxx | 29 +++------------------------- 3 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 win32/PlatWin.h diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index b0fbd2543..a1ae68b82 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -197,15 +197,42 @@ void Palette::Allocate(Window &) { } } -static IDWriteFactory *pIDWriteFactory = 0; - -static void EnsureDWriteFactory() { - // Construct - if (!pIDWriteFactory) { - DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&pIDWriteFactory)); +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(&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(&pIDWriteFactory)); + } + } } + triedLoadingD2D = true; + return pIDWriteFactory && pD2DFactory; } struct FormatAndBaseline { @@ -292,7 +319,6 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in SetLogFont(lf, faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); hash = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); fid = 0; - EnsureDWriteFactory(); if (pIDWriteFactory) { #ifdef OLD_CODE HFONT fontSave = static_cast(::SelectObject(hdc, font_.GetID())); @@ -508,9 +534,6 @@ public: } //namespace Scintilla #endif -#pragma comment(lib, "d2d1.lib") -#pragma comment(lib, "dwrite.lib") - SurfaceImpl::SurfaceImpl() : unicodeMode(false), hdc(0), hdcOwned(false), @@ -563,11 +586,7 @@ void SurfaceImpl::Release() { } } -// Ensures have pIDWriteFactory, and pRenderTarget -// If any fail, pRenderTarget will be NULL void SurfaceImpl::SetDWrite(HDC hdc) { - // Construct - EnsureDWriteFactory(); dpiScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; dpiScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; } diff --git a/win32/PlatWin.h b/win32/PlatWin.h new file mode 100644 index 000000000..dc3f8e432 --- /dev/null +++ b/win32/PlatWin.h @@ -0,0 +1,13 @@ +// Scintilla source code edit control +/** @file PlatWin.h + ** Implementation of platform facilities on Windows. + **/ +// Copyright 1998-2011 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +extern bool IsNT(); +extern void Platform_Initialise(void *hInstance); +extern void Platform_Finalise(); +extern bool LoadD2D(); +extern ID2D1Factory *pD2DFactory; +extern IDWriteFactory *pIDWriteFactory; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 6bc770eed..f49b2bace 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -57,6 +57,7 @@ #include "Editor.h" #include "ScintillaBase.h" #include "UniConversion.h" +#include "PlatWin.h" #ifdef SCI_LEXER #include "ExternalLexer.h" @@ -90,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. @@ -200,8 +196,6 @@ class ScintillaWin : static HINSTANCE hInstance; - IDWriteFactory *pIDWriteFactory; - ID2D1Factory *pD2DFactory; ID2D1HwndRenderTarget *pRenderTarget; ScintillaWin(HWND hwnd); @@ -359,8 +353,6 @@ ScintillaWin::ScintillaWin(HWND hwnd) { sysCaretWidth = 0; sysCaretHeight = 0; - pIDWriteFactory = 0; - pD2DFactory = 0; pRenderTarget = 0; keysAlwaysUnicode = false; @@ -392,14 +384,7 @@ void ScintillaWin::Initialise() { } } - if (!pIDWriteFactory) { - DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&pIDWriteFactory)); - } - if (!pD2DFactory) { - D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory); - } + LoadD2D(); } void ScintillaWin::Finalise() { @@ -407,14 +392,6 @@ void ScintillaWin::Finalise() { SetTicking(false); SetIdle(false); DropRenderTarget(); - if (pIDWriteFactory) { - pIDWriteFactory->Release(); - pIDWriteFactory = 0; - } - if (pD2DFactory) { - pD2DFactory->Release(); - pD2DFactory = 0; - } ::RevokeDragDrop(MainHWND()); if (SUCCEEDED(hrOle)) { ::OleUninitialize(); @@ -2780,7 +2757,7 @@ sptr_t PASCAL ScintillaWin::CTWndProc( RECT rc; GetClientRect(hWnd, &rc); // Create a Direct2D render target. - sciThis->pD2DFactory->CreateHwndRenderTarget( + pD2DFactory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)), &pCTRenderTarget); -- cgit v1.2.3 From 04bbe265db17b079603a35fdb8afdfcac6a35ff9 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 21:44:33 +1000 Subject: Remove unused field. --- win32/PlatWin.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index a1ae68b82..6e1f3f3be 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -462,7 +462,6 @@ class SurfaceImpl : public Surface { ID2D1RenderTarget *pRenderTarget; bool ownRenderTarget; - bool needsEndDraw; int clipsActive; IDWriteTextFormat *pTextFormat; @@ -549,7 +548,6 @@ SurfaceImpl::SurfaceImpl() : pRenderTarget = NULL; ownRenderTarget = false; - needsEndDraw = false; clipsActive = 0; pTextFormat = NULL; baseline = 1.0f; @@ -630,7 +628,6 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) pRenderTarget = pCompatibleRenderTarget; pRenderTarget->BeginDraw(); ownRenderTarget = true; - needsEndDraw = true; } } -- cgit v1.2.3 From b120dee8b3f38d061f605091388369f7c36df431 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 21:55:07 +1000 Subject: Ensure deallocation. --- win32/ScintillaWin.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index f49b2bace..28a630246 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -2770,6 +2770,7 @@ sptr_t PASCAL ScintillaWin::CTWndProc( pCTRenderTarget->EndDraw(); surfaceWindow->Release(); delete surfaceWindow; + pCTRenderTarget->Release(); } ::EndPaint(hWnd, &ps); return 0; -- cgit v1.2.3 From 9151b95f3336b1a078f757d87fd432e9e3b9b29e Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 21:55:27 +1000 Subject: Match new argument types to Font::Create. --- src/CallTip.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CallTip.cxx b/src/CallTip.cxx index cdc30fcbc..6fd11730d 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -273,7 +273,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, inCallTipMode = true; posStartCallTip = pos; int deviceHeight = surfaceMeasure->DeviceHeightFont(size); - font.Create(faceName, characterSet, deviceHeight, false, false); + font.Create(faceName, characterSet, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! int numLines = 1; -- cgit v1.2.3 From e37e73270f08346b400059a6debf0729b498bebf Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 23:01:57 +1000 Subject: Autocompletion lists work with Direct2D. --- win32/PlatWin.cxx | 80 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 6e1f3f3be..fdfd44d79 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -246,8 +246,25 @@ struct FormatAndBaseline { pTextFormat = 0; baseline = 1; } + HFONT HFont(); }; +HFONT FormatAndBaseline::HFont() { + LOGFONTW lf; + memset(&lf, 0, sizeof(lf)); + const int familySize = 200; + WCHAR fontFamilyName[familySize]; + + HRESULT hr = pTextFormat->GetFontFamilyName(fontFamilyName, familySize); + if (SUCCEEDED(hr)) { + lf.lfWeight = pTextFormat->GetFontWeight(); + lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC; + lf.lfHeight = -static_cast(pTextFormat->GetFontSize()); + return ::CreateFontIndirect(&lf); + } + return 0; +} + #ifndef CLEARTYPE_QUALITY #define CLEARTYPE_QUALITY 5 #endif @@ -1270,8 +1287,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); @@ -1648,17 +1664,19 @@ void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHei hinstanceParent, this); - ::MapWindowPoints(hwndParent, NULL, reinterpret_cast(&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); + FormatAndBaseline *pfabl = reinterpret_cast(font.GetID()); + fontCopy = pfabl->HFont(); ::SendMessage(lb, WM_SETFONT, reinterpret_cast(fontCopy), 0); } } @@ -1829,17 +1847,36 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { if (pimage) { Surface *surfaceItem = Surface::Allocate(); if (surfaceItem) { - // TODO: Need a DC RenderTarget here - /* - 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 (pD2DFactory) { + 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; + ::SetTextAlign(pDrawItem->hDC, TA_TOP); + pDCRT->EndDraw(); + pDCRT->Release(); + } + } } } } @@ -1906,7 +1943,9 @@ void ListBoxX::SetList(const char *list, char separator, char typesep) { } void ListBoxX::AdjustWindowRect(PRectangle *rc) const { - ::AdjustWindowRectEx(reinterpret_cast(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 { @@ -1947,8 +1986,9 @@ void ListBoxX::SetRedraw(bool on) { void ListBoxX::ResizeToCursor() { PRectangle rc = GetPosition(); - Point pt; - ::GetCursorPos(reinterpret_cast(&pt)); + POINT ptw; + ::GetCursorPos(&ptw); + Point pt(ptw.x, ptw.y); pt.x += dragOffset.x; pt.y += dragOffset.y; -- cgit v1.2.3 From 6eac1bd38534dfce8c890b24c59261bbf14a6c2b Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 7 Aug 2011 23:07:01 +1000 Subject: Add a new XYACCUMULATOR which is more precise than XYPOSITION for keeping track over long lines. Using typedefs rather than #defines so goes into namespace. --- include/Platform.h | 7 ++++--- src/Editor.cxx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/Platform.h b/include/Platform.h index d23a932e4..6ba87aa7b 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -9,9 +9,6 @@ #ifndef PLATFORM_H #define PLATFORM_H -#define XYPOSITION float -//#define XYPOSITION int - // PLAT_GTK = GTK+ on Linux or Win32 // PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32 // PLAT_WIN = Win32 API on Win32 OS @@ -62,6 +59,10 @@ namespace Scintilla { #endif +typedef float XYPOSITION; +typedef double XYACCUMULATOR; +//#define XYPOSITION int + // Underlying the implementation of the platform classes are platform specific types. // Sometimes these need to be passed around by client code so they are defined here diff --git a/src/Editor.cxx b/src/Editor.cxx index 7261ac7d2..42e52a711 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2216,7 +2216,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou // Layout the line, determining the position of each character, // with an extra element at the end for the end of the line. int startseg = 0; // Start of the current segment, in char. number - XYPOSITION startsegx = 0; // Start of the current segment, in pixels + XYACCUMULATOR startsegx = 0; // Start of the current segment, in pixels ll->positions[0] = 0; unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars; bool lastSegItalics = false; -- cgit v1.2.3 From cc4163e9e3e5f94c4b56fea3794fa1fc49f8c129 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Mon, 8 Aug 2011 11:38:28 +1000 Subject: Make compile in narrow mode. --- win32/PlatWin.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index fdfd44d79..804fd66e1 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -260,7 +260,7 @@ HFONT FormatAndBaseline::HFont() { lf.lfWeight = pTextFormat->GetFontWeight(); lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC; lf.lfHeight = -static_cast(pTextFormat->GetFontSize()); - return ::CreateFontIndirect(&lf); + return ::CreateFontIndirectW(&lf); } return 0; } -- cgit v1.2.3 From 05f1d735da51d6f71fda7f3554a80b95c9241809 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Mon, 8 Aug 2011 11:38:58 +1000 Subject: Fix tab positioning to make indent guides and tab characters align. --- src/Editor.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Editor.cxx b/src/Editor.cxx index 42e52a711..f5649ce11 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2237,7 +2237,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou if (vstyle.styles[ll->styles[charInLine]].visible) { if (isControl) { if (ll->chars[charInLine] == '\t') { - ll->positions[charInLine + 1] = ((((startsegx + 2) / + ll->positions[charInLine + 1] = ((((static_cast(startsegx) + 2) / tabWidth) + 1) * tabWidth) - startsegx; } else if (controlCharSymbol < 32) { if (ctrlCharWidth[ll->chars[charInLine]] == 0) { -- cgit v1.2.3 From e2526b144a7837403d04f82548c591e19149c9a5 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Mon, 8 Aug 2011 11:42:22 +1000 Subject: Removed old code. --- win32/PlatWin.cxx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 804fd66e1..13a1de70d 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -337,21 +337,6 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in hash = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); fid = 0; if (pIDWriteFactory) { -#ifdef OLD_CODE - HFONT fontSave = static_cast(::SelectObject(hdc, font_.GetID())); - DWORD sizeOLTM = ::GetOutlineTextMetrics(hdc, NULL, NULL); - std::vector vOLTM(sizeOLTM); - LPOUTLINETEXTMETRIC potm = reinterpret_cast(&vOLTM[0]); - DWORD worked = ::GetOutlineTextMetrics(hdc, sizeOLTM, potm); - ::SelectObject(hdc, fontSave); - if (!worked) - return; - const WCHAR *pwcFamily = reinterpret_cast(&vOLTM[reinterpret_cast(potm->otmpFamilyName)]); - //const WCHAR *pwcFace = reinterpret_cast(&vOLTM[reinterpret_cast(potm->otmpFaceName)]); - FLOAT fHeight = potm->otmTextMetrics.tmHeight * 72.0f / 96.0f; - bool italics = potm->otmTextMetrics.tmItalic != 0; - bool bold = potm->otmTextMetrics.tmWeight >= FW_BOLD; -#endif IDWriteTextFormat *pTextFormat; const int faceSize = 200; WCHAR wszFace[faceSize]; -- cgit v1.2.3 From 89c252e9ff39f33bcf573e38a27d8821cb64279a Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Wed, 10 Aug 2011 10:41:03 +1000 Subject: Using safe sizes for ascent and descent which work for tallest characters. Fix HFONT conversion for use in autocompletion lists. --- win32/PlatWin.cxx | 124 ++++++++++++++++-------------------------------------- 1 file changed, 37 insertions(+), 87 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 13a1de70d..5726e6fb2 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -235,27 +235,27 @@ bool LoadD2D() { return pIDWriteFactory && pD2DFactory; } -struct FormatAndBaseline { +struct FormatAndMetrics { IDWriteTextFormat *pTextFormat; - FLOAT baseline; - FormatAndBaseline(IDWriteTextFormat *pTextFormat_, FLOAT baseline_) : - pTextFormat(pTextFormat_), baseline(baseline_) { + FLOAT yAscent; + FLOAT yDescent; + FormatAndMetrics(IDWriteTextFormat *pTextFormat_, FLOAT yAscent_, FLOAT yDescent_) : + pTextFormat(pTextFormat_), yAscent(yAscent_), yDescent(yDescent_) { } - ~FormatAndBaseline() { + ~FormatAndMetrics() { pTextFormat->Release(); pTextFormat = 0; - baseline = 1; + yAscent = 2; + yDescent = 1; } HFONT HFont(); }; -HFONT FormatAndBaseline::HFont() { +HFONT FormatAndMetrics::HFont() { LOGFONTW lf; memset(&lf, 0, sizeof(lf)); - const int familySize = 200; - WCHAR fontFamilyName[familySize]; - HRESULT hr = pTextFormat->GetFontFamilyName(fontFamilyName, familySize); + HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE); if (SUCCEEDED(hr)) { lf.lfWeight = pTextFormat->GetFontWeight(); lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC; @@ -342,26 +342,31 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in WCHAR wszFace[faceSize]; UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); FLOAT fHeight = size_; + DWRITE_FONT_STYLE style = italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL, static_cast(weight_), - italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, + 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 baseline = 1.0f; + 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)) { - baseline = lineMetrics[0].baseline; + yAscent = lineMetrics[0].baseline; + yDescent = lineMetrics[0].height - lineMetrics[0].baseline; } pTextLayout->Release(); } - fid = reinterpret_cast(new FormatAndBaseline(pTextFormat, baseline)); + fid = reinterpret_cast(new FormatAndMetrics(pTextFormat, yAscent, yDescent)); } } usage = 1; @@ -378,7 +383,7 @@ bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, i } void FontCached::Release() { - delete reinterpret_cast(fid); + delete reinterpret_cast(fid); fid = 0; } @@ -467,7 +472,9 @@ class SurfaceImpl : public Surface { int clipsActive; IDWriteTextFormat *pTextFormat; - FLOAT baseline; + FLOAT yAscent; + FLOAT yDescent; + ID2D1SolidColorBrush *pBrush; float dpiScaleX; float dpiScaleY; @@ -552,7 +559,8 @@ SurfaceImpl::SurfaceImpl() : ownRenderTarget = false; clipsActive = 0; pTextFormat = NULL; - baseline = 1.0f; + yAscent = 2; + yDescent = 1; pBrush = NULL; dpiScaleX = 1.0; dpiScaleY = 1.0; @@ -657,9 +665,10 @@ void SurfaceImpl::D2DPenColour(ColourAllocated fore, int alpha) { } void SurfaceImpl::SetFont(Font &font_) { - FormatAndBaseline *pfabl = reinterpret_cast(font_.GetID()); + FormatAndMetrics *pfabl = reinterpret_cast(font_.GetID()); pTextFormat = pfabl->pTextFormat; - baseline = pfabl->baseline; + yAscent = pfabl->yAscent; + yDescent = pfabl->yDescent; } int SurfaceImpl::LogPixelsY() { @@ -940,14 +949,16 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, c // Explicitly creating a text layout appears a little faster IDWriteTextLayout *pTextLayout; HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, - rc.Width()+2, rc.Height(), &pTextLayout); + rc.Width(), rc.Height(), &pTextLayout); + // Could be an option for SC_EFF_QUALITY_ANTIALIASED: + //pRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); if (SUCCEEDED(hr)) { - D2D1_POINT_2F origin = {rc.left, ybase-baseline}; + 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(rcw.left) / dpiScaleX, - static_cast(ybase-baseline) / dpiScaleY, + static_cast(ybase-yAscent) / dpiScaleY, static_cast(rcw.right + 1) / dpiScaleX, static_cast(rcw.bottom) / dpiScaleY); pRenderTarget->DrawText(tbuf.buffer, tbuf.tlen, pTextFormat, layoutRect, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE); @@ -1108,56 +1119,13 @@ XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { } XYPOSITION SurfaceImpl::Ascent(Font &font_) { - FLOAT ascent = 1.0; SetFont(font_); - if (pIDWriteFactory && pTextFormat) { - SetFont(font_); - // Create a layout - IDWriteTextLayout *pTextLayout = 0; - HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); - if (SUCCEEDED(hr)) { - DWRITE_TEXT_METRICS textMetrics; - pTextLayout->GetMetrics(&textMetrics); - ascent = textMetrics.layoutHeight; - const int clusters = 20; - DWRITE_CLUSTER_METRICS clusterMetrics[clusters]; - UINT32 count = 0; - pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count); - //height = pTextLayout->GetMaxHeight(); - FLOAT minWidth = 0; - hr = pTextLayout->DetermineMinWidth(&minWidth); - const int maxLines = 2; - DWRITE_LINE_METRICS lineMetrics[maxLines]; - UINT32 lineCount = 0; - hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); - if (SUCCEEDED(hr)) { - ascent = lineMetrics[0].baseline; - } - pTextLayout->Release(); - } - } - return int(ascent + 0.5); + return ceil(yAscent); } XYPOSITION SurfaceImpl::Descent(Font &font_) { - FLOAT descent = 1.0; SetFont(font_); - if (pIDWriteFactory && pTextFormat) { - // Create a layout - IDWriteTextLayout *pTextLayout = 0; - HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); - if (SUCCEEDED(hr)) { - const int maxLines = 2; - DWRITE_LINE_METRICS lineMetrics[maxLines]; - UINT32 lineCount = 0; - hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); - if (SUCCEEDED(hr)) { - descent = lineMetrics[0].height - lineMetrics[0].baseline; - } - pTextLayout->Release(); - } - } - return int(descent + 0.5); + return ceil(yDescent); } XYPOSITION SurfaceImpl::InternalLeading(Font &) { @@ -1169,25 +1137,7 @@ XYPOSITION SurfaceImpl::ExternalLeading(Font &) { } XYPOSITION SurfaceImpl::Height(Font &font_) { - FLOAT height = 1.0; - SetFont(font_); - if (pIDWriteFactory && pTextFormat) { - // Create a layout - IDWriteTextLayout *pTextLayout = 0; - HRESULT hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 1000.0, 1000.0, &pTextLayout); - if (SUCCEEDED(hr)) { - const int maxLines = 2; - DWRITE_LINE_METRICS lineMetrics[maxLines]; - UINT32 lineCount = 0; - hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount); - if (SUCCEEDED(hr)) { - height = lineMetrics[0].height; - } - pTextLayout->Release(); - } - } - // Truncating rather than rounding as otherwise too much space. - return int(height); + return Ascent(font_) + Descent(font_); } XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { @@ -1660,7 +1610,7 @@ void ListBoxX::SetFont(Font &font) { ::DeleteObject(fontCopy); fontCopy = 0; } - FormatAndBaseline *pfabl = reinterpret_cast(font.GetID()); + FormatAndMetrics *pfabl = reinterpret_cast(font.GetID()); fontCopy = pfabl->HFont(); ::SendMessage(lb, WM_SETFONT, reinterpret_cast(fontCopy), 0); } -- cgit v1.2.3 From 305b3107ba2abd43e3ed635916c3cad52dc605fe Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Wed, 10 Aug 2011 11:08:32 +1000 Subject: Implemented text quality parameter. --- win32/PlatWin.cxx | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 5726e6fb2..8a198eb4b 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -237,14 +237,16 @@ bool LoadD2D() { struct FormatAndMetrics { IDWriteTextFormat *pTextFormat; + int extraFontFlag; FLOAT yAscent; FLOAT yDescent; - FormatAndMetrics(IDWriteTextFormat *pTextFormat_, FLOAT yAscent_, FLOAT yDescent_) : - pTextFormat(pTextFormat_), yAscent(yAscent_), yDescent(yDescent_) { + FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_) : + pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) { } ~FormatAndMetrics() { pTextFormat->Release(); pTextFormat = 0; + extraFontFlag = 0; yAscent = 2; yDescent = 1; } @@ -286,6 +288,23 @@ static BYTE Win32MapFontQuality(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 @@ -366,7 +385,7 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in } pTextLayout->Release(); } - fid = reinterpret_cast(new FormatAndMetrics(pTextFormat, yAscent, yDescent)); + fid = reinterpret_cast(new FormatAndMetrics(pTextFormat, extraFontFlag_, yAscent, yDescent)); } } usage = 1; @@ -669,6 +688,9 @@ void SurfaceImpl::SetFont(Font &font_) { pTextFormat = pfabl->pTextFormat; yAscent = pfabl->yAscent; yDescent = pfabl->yDescent; + if (pRenderTarget) { + pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfabl->extraFontFlag)); + } } int SurfaceImpl::LogPixelsY() { @@ -950,8 +972,6 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, c IDWriteTextLayout *pTextLayout; HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, rc.Width(), rc.Height(), &pTextLayout); - // Could be an option for SC_EFF_QUALITY_ANTIALIASED: - //pRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); if (SUCCEEDED(hr)) { D2D1_POINT_2F origin = {rc.left, ybase-yAscent}; pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE); -- cgit v1.2.3 From 8bf7c53bd47fa32dd162d9db1063545537b1bb5f Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Wed, 10 Aug 2011 23:56:59 +1000 Subject: Implement 'technology' concept which will allow GDI and Direct2D/DirectWrite to run at the same time for different windows and operations. --- include/Platform.h | 38 +++++++++++++++++++++--- include/Scintilla.h | 4 +++ include/Scintilla.iface | 9 ++++++ src/AutoComplete.cxx | 4 +-- src/AutoComplete.h | 2 +- src/CallTip.cxx | 8 +++-- src/CallTip.h | 2 +- src/Editor.cxx | 76 +++++++++++++++++++++++++++++++++++------------- src/Editor.h | 8 +++-- src/ScintillaBase.cxx | 3 +- src/ViewStyle.cxx | 10 ++++--- src/ViewStyle.h | 3 +- win32/PlatWin.cxx | 77 +++++++++++++++++++++++++------------------------ win32/ScintillaWin.cxx | 12 +++++++- 14 files changed, 177 insertions(+), 79 deletions(-) diff --git a/include/Platform.h b/include/Platform.h index 6ba87aa7b..499e78e5d 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -291,6 +291,37 @@ public: /** * Font management. */ + +struct FontParameters { + const char *faceName; + float size; + int weight; + bool italic; + int extraFontFlag; + int technology; + int characterSet; + + FontParameters( + const char *faceName_, + float size_=10, + int weight_=400, + bool italic_=false, + int extraFontFlag_=0, + int technology_=0, + int characterSet_=0) : + + faceName(faceName_), + size(size_), + weight(weight_), + italic(italic_), + extraFontFlag(extraFontFlag_), + technology(technology_), + characterSet(characterSet_) + { + } + +}; + class Font { protected: FontID fid; @@ -304,8 +335,7 @@ public: Font(); virtual ~Font(); - virtual void Create(const char *faceName, int characterSet, float size, - int weight, bool italic, int extraFontFlag=0); + virtual void Create(const FontParameters &fp); virtual void Release(); FontID GetID() { return fid; } @@ -329,7 +359,7 @@ private: public: Surface() {} virtual ~Surface() {} - static Surface *Allocate(); + static Surface *Allocate(int technology); virtual void Init(WindowID wid)=0; virtual void Init(SurfaceID sid, WindowID wid)=0; @@ -443,7 +473,7 @@ public: static ListBox *Allocate(); virtual void SetFont(Font &font)=0; - virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0; + virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; virtual void SetAverageCharWidth(int width)=0; virtual void SetVisibleRows(int rows)=0; virtual int GetVisibleRows() const=0; diff --git a/include/Scintilla.h b/include/Scintilla.h index c7b9944d8..0aec0c8df 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -827,6 +827,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_REGISTERRGBAIMAGE 2627 #define SCI_SCROLLTOSTART 2628 #define SCI_SCROLLTOEND 2629 +#define SC_TECHNOLOGY_DEFAULT 0 +#define SC_TECHNOLOGY_DIRECTWRITE 0 +#define SCI_SETTECHNOLOGY 2630 +#define SCI_GETTECHNOLOGY 2631 #define SCI_STARTRECORD 3001 #define SCI_STOPRECORD 3002 #define SCI_SETLEXER 4001 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index c604f621a..a578bf3fc 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2194,6 +2194,15 @@ fun void ScrollToStart=2628(,) # Scroll to end of document. fun void ScrollToEnd=2629(,) +val SC_TECHNOLOGY_DEFAULT=0 +val SC_TECHNOLOGY_DIRECTWRITE=0 + +# Set the technolgy used. +set void SetTechnology=2630(int technology,) + +# Get the tech. +get int GetTechnology=2631(,) + # Start notifying the container of all key presses and commands. fun void StartRecord=3001(,) diff --git a/src/AutoComplete.cxx b/src/AutoComplete.cxx index f6a291fe9..2752ef0c9 100644 --- a/src/AutoComplete.cxx +++ b/src/AutoComplete.cxx @@ -50,11 +50,11 @@ bool AutoComplete::Active() const { void AutoComplete::Start(Window &parent, int ctrlID, int position, Point location, int startLen_, - int lineHeight, bool unicodeMode) { + int lineHeight, bool unicodeMode, int technology) { if (active) { Cancel(); } - lb->Create(parent, ctrlID, location, lineHeight, unicodeMode); + lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology); lb->Clear(); active = true; startLen = startLen_; diff --git a/src/AutoComplete.h b/src/AutoComplete.h index f48cb0551..aefab120a 100644 --- a/src/AutoComplete.h +++ b/src/AutoComplete.h @@ -40,7 +40,7 @@ public: /// Display the auto completion list positioned to be near a character position void Start(Window &parent, int ctrlID, int position, Point location, - int startLen_, int lineHeight, bool unicodeMode); + int startLen_, int lineHeight, bool unicodeMode, int technology); /// The stop chars are characters which, when typed, cause the auto completion list to disappear void SetStopChars(const char *stopChars_); diff --git a/src/CallTip.cxx b/src/CallTip.cxx index 6fd11730d..0e1e80cc1 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -255,14 +255,15 @@ void CallTip::MouseClick(Point pt) { PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, const char *faceName, int size, - int codePage_, int characterSet, Window &wParent) { + int codePage_, int characterSet, + int technology, Window &wParent) { clickPlace = 0; delete []val; val = 0; val = new char[strlen(defn) + 1]; strcpy(val, defn); codePage = codePage_; - Surface *surfaceMeasure = Surface::Allocate(); + Surface *surfaceMeasure = Surface::Allocate(technology); if (!surfaceMeasure) return PRectangle(); surfaceMeasure->Init(wParent.GetID()); @@ -273,7 +274,8 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, inCallTipMode = true; posStartCallTip = pos; int deviceHeight = surfaceMeasure->DeviceHeightFont(size); - font.Create(faceName, characterSet, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false); + FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet); + font.Create(fp); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! int numLines = 1; diff --git a/src/CallTip.h b/src/CallTip.h index a9ba82eb8..e437f3309 100644 --- a/src/CallTip.h +++ b/src/CallTip.h @@ -62,7 +62,7 @@ public: /// Setup the calltip and return a rectangle of the area required. PRectangle CallTipStart(int pos, Point pt, const char *defn, const char *faceName, int size, int codePage_, - int characterSet, Window &wParent); + int characterSet, int technology, Window &wParent); void CallTipCancel(); diff --git a/src/Editor.cxx b/src/Editor.cxx index f5649ce11..74698a13d 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -102,7 +102,8 @@ Editor::Editor() { ctrlID = 0; stylesValid = false; - + technology = SC_TECHNOLOGY_DEFAULT; + printMagnification = 0; printColourMode = SC_PRINT_NORMAL; printWrapState = eWrapWord; @@ -168,11 +169,11 @@ Editor::Editor() { additionalCaretsVisible = true; virtualSpaceOptions = SCVS_NONE; - pixmapLine = Surface::Allocate(); - pixmapSelMargin = Surface::Allocate(); - pixmapSelPattern = Surface::Allocate(); - pixmapIndentGuide = Surface::Allocate(); - pixmapIndentGuideHighlight = Surface::Allocate(); + pixmapLine = 0; + pixmapSelMargin = 0; + pixmapSelPattern = 0; + pixmapIndentGuide = 0; + pixmapIndentGuideHighlight = 0; targetStart = 0; targetEnd = 0; @@ -226,12 +227,7 @@ Editor::~Editor() { pdoc->RemoveWatcher(this, 0); pdoc->Release(); pdoc = 0; - DropGraphics(); - delete pixmapLine; - delete pixmapSelMargin; - delete pixmapSelPattern; - delete pixmapIndentGuide; - delete pixmapIndentGuideHighlight; + DropGraphics(true); } void Editor::Finalise() { @@ -239,17 +235,50 @@ void Editor::Finalise() { CancelModes(); } -void Editor::DropGraphics() { - pixmapLine->Release(); - pixmapSelMargin->Release(); - pixmapSelPattern->Release(); - pixmapIndentGuide->Release(); - pixmapIndentGuideHighlight->Release(); +void Editor::DropGraphics(bool freeObjects) { + if (freeObjects) { + delete pixmapLine; + pixmapLine = 0; + delete pixmapSelMargin; + pixmapSelMargin = 0; + delete pixmapSelPattern; + pixmapSelPattern = 0; + delete pixmapIndentGuide; + pixmapIndentGuide = 0; + delete pixmapIndentGuideHighlight; + pixmapIndentGuideHighlight = 0; + } else { + if (pixmapLine) + pixmapLine->Release(); + if (pixmapSelMargin) + pixmapSelMargin->Release(); + if (pixmapSelPattern) + pixmapSelPattern->Release(); + if (pixmapIndentGuide) + pixmapIndentGuide->Release(); + if (pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight->Release(); + } +} + +void Editor::AllocateGraphics() { + if (!pixmapLine) + pixmapLine = Surface::Allocate(technology); + if (!pixmapSelMargin) + pixmapSelMargin = Surface::Allocate(technology); + if (!pixmapSelPattern) + pixmapSelPattern = Surface::Allocate(technology); + if (!pixmapIndentGuide) + pixmapIndentGuide = Surface::Allocate(technology); + if (!pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight = Surface::Allocate(technology); } void Editor::InvalidateStyleData() { stylesValid = false; - DropGraphics(); + vs.technology = technology; + DropGraphics(false); + AllocateGraphics(); palette.Release(); llc.Invalidate(LineLayout::llInvalid); posCache.Clear(); @@ -3926,7 +3955,7 @@ void Editor::SetScrollBars() { } void Editor::ChangeSize() { - DropGraphics(); + DropGraphics(false); SetScrollBars(); if (wrapState != eWrapNone) { PRectangle rcTextArea = GetClientRectangle(); @@ -9218,6 +9247,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETIDENTIFIER: return GetCtrlID(); + case SCI_SETTECHNOLOGY: + // No action by default + break; + + case SCI_GETTECHNOLOGY: + return technology; + default: return DefWndProc(iMessage, wParam, lParam); } diff --git a/src/Editor.h b/src/Editor.h index f1a500b74..7a30fdf3f 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -131,6 +131,7 @@ protected: // ScintillaBase subclass needs access to much of Editor * When a style attribute is changed, this cache is flushed. */ bool stylesValid; ViewStyle vs; + int technology; Point sizeRGBAImage; Palette palette; @@ -279,7 +280,8 @@ protected: // ScintillaBase subclass needs access to much of Editor void InvalidateStyleRedraw(); virtual void RefreshColourPalette(Palette &pal, bool want); void RefreshStyleData(); - void DropGraphics(); + void DropGraphics(bool freeObjects); + void AllocateGraphics(); virtual PRectangle GetClientRectangle(); PRectangle GetTextRectangle(); @@ -574,7 +576,7 @@ private: public: AutoSurface(Editor *ed) : surf(0) { if (ed->wMain.GetID()) { - surf = Surface::Allocate(); + surf = Surface::Allocate(ed->technology); if (surf) { surf->Init(ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); @@ -584,7 +586,7 @@ public: } AutoSurface(SurfaceID sid, Editor *ed) : surf(0) { if (ed->wMain.GetID()) { - surf = Surface::Allocate(); + surf = Surface::Allocate(ed->technology); if (surf) { surf->Init(sid, ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index da6b03e0d..247f34c4e 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -222,7 +222,7 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { } } ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(), - lenEntered, vs.lineHeight, IsUnicodeMode()); + lenEntered, vs.lineHeight, IsUnicodeMode(), technology); PRectangle rcClient = GetClientRectangle(); Point pt = LocationFromPosition(sel.MainCaret() - lenEntered); @@ -419,6 +419,7 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) { vs.styles[ctStyle].sizeZoomed, CodePage(), vs.styles[ctStyle].characterSet, + vs.technology, wMain); // If the call-tip window would be out of the client // space, adjust so it displays above the text. diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index b722f8d02..08164f648 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -86,14 +86,15 @@ FontRealised::~FontRealised() { frNext = 0; } -void FontRealised::Realise(Surface &surface, int zoomLevel) { +void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) { PLATFORM_ASSERT(fontName); sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER; if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; float deviceHeight = surface.DeviceHeightFont(sizeZoomed); - font.Create(fontName, characterSet, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag); + FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet); + font.Create(fp); ascent = surface.Ascent(font); descent = surface.Descent(font); @@ -102,7 +103,7 @@ void FontRealised::Realise(Surface &surface, int zoomLevel) { aveCharWidth = surface.AverageCharWidth(font); spaceWidth = surface.WidthChar(font, ' '); if (frNext) { - frNext->Realise(surface, zoomLevel); + frNext->Realise(surface, zoomLevel, technology); } } @@ -239,6 +240,7 @@ void ViewStyle::Init(size_t stylesSize_) { indicators[2].under = false; indicators[2].fore = ColourDesired(0xff, 0, 0); + technology = SC_TECHNOLOGY_DEFAULT; lineHeight = 1; maxAscent = 1; maxDescent = 1; @@ -388,7 +390,7 @@ void ViewStyle::Refresh(Surface &surface) { CreateFont(styles[j]); } - frFirst->Realise(surface, zoomLevel); + frFirst->Realise(surface, zoomLevel, technology); for (unsigned int k=0; kFind(styles[k]); diff --git a/src/ViewStyle.h b/src/ViewStyle.h index b038a9b54..b15b9163c 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -48,7 +48,7 @@ public: FontRealised *frNext; FontRealised(const FontSpecification &fs); virtual ~FontRealised(); - void Realise(Surface &surface, int zoomLevel); + void Realise(Surface &surface, int zoomLevel, int technology); FontRealised *Find(const FontSpecification &fs); void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent); }; @@ -67,6 +67,7 @@ public: Style *styles; LineMarker markers[MARKER_MAX + 1]; Indicator indicators[INDIC_MAX + 1]; + int technology; int lineHeight; unsigned int maxAscent; unsigned int maxDescent; diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 8a198eb4b..6304d2e5e 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -321,14 +321,14 @@ static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, flo * 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, float size, int weight, bool italic, int extraFontFlag) { +static int HashFont(const FontParameters &fp) { return - static_cast(size) ^ - (characterSet << 10) ^ - ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^ - ((weight/100) << 12) ^ - (italic ? 0x20000000 : 0) ^ - faceName[0]; + static_cast(fp.size) ^ + (fp.characterSet << 10) ^ + ((fp.extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^ + ((fp.weight/100) << 12) ^ + (fp.italic ? 0x20000000 : 0) ^ + fp.faceName[0]; } class FontCached : Font { @@ -337,33 +337,33 @@ class FontCached : Font { float size; LOGFONTA lf; int hash; - FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_); + FontCached(const FontParameters &fp); ~FontCached() {} - bool SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_); + bool SameAs(const FontParameters &fp); virtual void Release(); static FontCached *first; public: - static FontID FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, 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_, float size_, int weight_, bool italic_, int extraFontFlag_) : +FontCached::FontCached(const FontParameters &fp) : next(0), usage(0), size(1.0), hash(0) { - SetLogFont(lf, faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); - hash = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); + SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag); + hash = HashFont(fp); fid = 0; if (pIDWriteFactory) { IDWriteTextFormat *pTextFormat; const int faceSize = 200; WCHAR wszFace[faceSize]; - UTF16FromUTF8(faceName_, strlen(faceName_)+1, wszFace, faceSize); - FLOAT fHeight = size_; - DWRITE_FONT_STYLE style = italic_ ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; + 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(weight_), + static_cast(fp.weight), style, DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat); if (SUCCEEDED(hr)) { @@ -385,20 +385,20 @@ FontCached::FontCached(const char *faceName_, int characterSet_, float size_, in } pTextLayout->Release(); } - fid = reinterpret_cast(new FormatAndMetrics(pTextFormat, extraFontFlag_, yAscent, yDescent)); + fid = reinterpret_cast(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, yAscent, yDescent)); } } usage = 1; } -bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_) { +bool FontCached::SameAs(const FontParameters &fp) { return - (size == size_) && - (lf.lfWeight == weight_) && - (lf.lfItalic == static_cast(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(fp.italic ? 1 : 0)) && + (lf.lfCharSet == fp.characterSet) && + (lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) && + 0 == strcmp(lf.lfFaceName,fp.faceName); } void FontCached::Release() { @@ -406,19 +406,19 @@ void FontCached::Release() { fid = 0; } -FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_, int extraFontFlag_) { +FontID FontCached::FindOrCreate(const FontParameters &fp) { FontID ret = 0; ::EnterCriticalSection(&crPlatformLock); - int hashFind = HashFont(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); + int hashFind = HashFont(fp); for (FontCached *cur=first; cur; cur=cur->next) { if ((cur->hash == hashFind) && - cur->SameAs(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_)) { + cur->SameAs(fp)) { cur->usage++; ret = cur->fid; } } if (ret == 0) { - FontCached *fc = new FontCached(faceName_, characterSet_, size_, weight_, italic_, extraFontFlag_); + FontCached *fc = new FontCached(fp); if (fc) { fc->next = first; first = fc; @@ -457,11 +457,10 @@ Font::~Font() { #define FONTS_CACHED -void Font::Create(const char *faceName, int characterSet, float size, - int weight, bool italic, int extraFontFlag) { +void Font::Create(const FontParameters &fp) { Release(); - if (faceName) - fid = FontCached::FindOrCreate(faceName, characterSet, size, weight, italic, extraFontFlag); + if (fp.faceName) + fid = FontCached::FindOrCreate(fp); } void Font::Release() { @@ -1203,7 +1202,7 @@ void SurfaceImpl::SetDBCSMode(int codePage_) { win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP()); } -Surface *Surface::Allocate() { +Surface *Surface::Allocate(int /* technology */) { return new SurfaceImpl; } @@ -1514,6 +1513,7 @@ ListBox::~ListBox() { class ListBoxX : public ListBox { int lineHeight; FontID fontCopy; + int technology; RGBAImageSet images; LineToItem lti; HWND lb; @@ -1555,7 +1555,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) { @@ -1567,7 +1567,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; @@ -1602,12 +1602,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(parent->GetID()); HINSTANCE hinstanceParent = GetWindowInstance(hwndParent); // Window created as popup so not clipped within parent client area @@ -1800,7 +1801,7 @@ 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) { if (pD2DFactory) { D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties( diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 28a630246..b3b9d1bb0 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -1127,6 +1127,16 @@ 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(wParam)) { + technology = wParam; + // Invalidate all cached information including layout. + InvalidateStyleRedraw(); + } + } + break; #ifdef SCI_LEXER case SCI_LOADLEXERLIBRARY: @@ -2751,7 +2761,7 @@ 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) { ID2D1HwndRenderTarget *pCTRenderTarget = 0; RECT rc; -- cgit v1.2.3 From ea0e865831c66451139e116f0e709df58319c437 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 11 Aug 2011 10:32:39 +1000 Subject: Implemented parallel stacks for GDI and DirectWrite. GDI works but DirectWrite does not draw well and eventuall crashes. --- include/Scintilla.h | 2 +- include/Scintilla.iface | 2 +- src/FontQuality.h | 3 + win32/PlatWin.cxx | 875 ++++++++++++++++++++++++++++++++++++++++++------ win32/ScintillaWin.cxx | 53 +-- 5 files changed, 813 insertions(+), 122 deletions(-) diff --git a/include/Scintilla.h b/include/Scintilla.h index 0aec0c8df..c8ffba04e 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -828,7 +828,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SCROLLTOSTART 2628 #define SCI_SCROLLTOEND 2629 #define SC_TECHNOLOGY_DEFAULT 0 -#define SC_TECHNOLOGY_DIRECTWRITE 0 +#define SC_TECHNOLOGY_DIRECTWRITE 1 #define SCI_SETTECHNOLOGY 2630 #define SCI_GETTECHNOLOGY 2631 #define SCI_STARTRECORD 3001 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index a578bf3fc..c5b58caae 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2195,7 +2195,7 @@ fun void ScrollToStart=2628(,) fun void ScrollToEnd=2629(,) val SC_TECHNOLOGY_DEFAULT=0 -val SC_TECHNOLOGY_DIRECTWRITE=0 +val SC_TECHNOLOGY_DIRECTWRITE=1 # Set the technolgy used. set void SetTechnology=2630(int technology,) diff --git a/src/FontQuality.h b/src/FontQuality.h index 2c8d548a8..dc6f28b4c 100644 --- a/src/FontQuality.h +++ b/src/FontQuality.h @@ -10,3 +10,6 @@ #define SC_EFF_QUALITY_NON_ANTIALIASED 1 #define SC_EFF_QUALITY_ANTIALIASED 2 #define SC_EFF_QUALITY_LCD_OPTIMIZED 3 + +#define SCWIN_TECH_GDI 0 +#define SCWIN_TECH_DIRECTWRITE 0 diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 6304d2e5e..54b455111 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -236,14 +236,21 @@ bool LoadD2D() { } struct FormatAndMetrics { + HFONT hfont; IDWriteTextFormat *pTextFormat; int extraFontFlag; FLOAT yAscent; FLOAT yDescent; FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_) : - pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) { + hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) { + } + FormatAndMetrics(HFONT hfont_, int extraFontFlag_) : + hfont(hfont_), pTextFormat(0), extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1) { } ~FormatAndMetrics() { + if (hfont) + ::DeleteObject(hfont); + if (pTextFormat) pTextFormat->Release(); pTextFormat = 0; extraFontFlag = 0; @@ -328,6 +335,7 @@ static int HashFont(const FontParameters &fp) { ((fp.extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^ ((fp.weight/100) << 12) ^ (fp.italic ? 0x20000000 : 0) ^ + (fp.technology << 15) ^ fp.faceName[0]; } @@ -336,6 +344,7 @@ class FontCached : Font { int usage; float size; LOGFONTA lf; + int technology; int hash; FontCached(const FontParameters &fp); ~FontCached() {} @@ -353,9 +362,13 @@ FontCached *FontCached::first = 0; 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 (pIDWriteFactory) { + if (technology == SCWIN_TECH_GDI) { + HFONT hfont = ::CreateFontIndirectA(&lf); + fid = reinterpret_cast(new FormatAndMetrics(hfont, fp.extraFontFlag)); + } else { IDWriteTextFormat *pTextFormat; const int faceSize = 200; WCHAR wszFace[faceSize]; @@ -398,6 +411,7 @@ bool FontCached::SameAs(const FontParameters &fp) { (lf.lfItalic == static_cast(fp.italic ? 1 : 0)) && (lf.lfCharSet == fp.characterSet) && (lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) && + (technology == fp.technology) && 0 == strcmp(lf.lfFaceName,fp.faceName); } @@ -469,11 +483,708 @@ void Font::Release() { 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 +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 { +public: + int tlen; + TextWide(const char *s, int len, bool unicodeMode, int codePage=0) : + VarBuffer(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 TextPositions; + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class SurfaceGDI : public Surface { + bool unicodeMode; + HDC hdc; + bool hdcOwned; + HPEN pen; + HPEN penOld; + HBRUSH brush; + HBRUSH brushOld; + HFONT font; + HFONT fontOld; + HBITMAP bitmap; + HBITMAP bitmapOld; + HPALETTE paletteOld; + int maxWidthMeasure; + int maxLenText; + + int codePage; + // If 9x OS and current code page is same as ANSI code page. + bool win9xACPSame; + + void BrushColor(ColourAllocated back); + void SetFont(Font &font_); + + // Private so SurfaceGDI objects can not be copied + SurfaceGDI(const SurfaceGDI &); + SurfaceGDI &operator=(const SurfaceGDI &); +public: + SurfaceGDI(); + virtual ~SurfaceGDI(); + + void Init(WindowID wid); + void Init(SurfaceID sid, WindowID wid); + void InitPixMap(int width, int height, Surface *surface_, WindowID wid); + + void Release(); + bool Initialised(); + void PenColour(ColourAllocated fore); + 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 + +SurfaceGDI::SurfaceGDI() : + unicodeMode(false), + hdc(0), hdcOwned(false), + pen(0), penOld(0), + brush(0), brushOld(0), + font(0), fontOld(0), + bitmap(0), bitmapOld(0), + paletteOld(0) { + // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels + maxWidthMeasure = IsNT() ? INT_MAX : 30000; + // There appears to be a 16 bit string length limit in GDI on NT and a limit of + // 8192 characters on Windows 95. + maxLenText = IsNT() ? 65535 : 8192; + + codePage = 0; + win9xACPSame = false; +} + +SurfaceGDI::~SurfaceGDI() { + Release(); +} + +void SurfaceGDI::Release() { + if (penOld) { + ::SelectObject(reinterpret_cast(hdc), penOld); + ::DeleteObject(pen); + penOld = 0; + } + pen = 0; + if (brushOld) { + ::SelectObject(reinterpret_cast(hdc), brushOld); + ::DeleteObject(brush); + brushOld = 0; + } + brush = 0; + if (fontOld) { + // Fonts are not deleted as they are owned by a Font object + ::SelectObject(reinterpret_cast(hdc), fontOld); + fontOld = 0; + } + font = 0; + if (bitmapOld) { + ::SelectObject(reinterpret_cast(hdc), bitmapOld); + ::DeleteObject(bitmap); + bitmapOld = 0; + } + bitmap = 0; + if (paletteOld) { + // Palettes are not deleted as they are owned by a Palette object + ::SelectPalette(reinterpret_cast(hdc), + reinterpret_cast(paletteOld), TRUE); + paletteOld = 0; + } + if (hdcOwned) { + ::DeleteDC(reinterpret_cast(hdc)); + hdc = 0; + hdcOwned = false; + } +} + +bool SurfaceGDI::Initialised() { + return hdc != 0; +} + +void SurfaceGDI::Init(WindowID) { + Release(); + hdc = ::CreateCompatibleDC(NULL); + hdcOwned = true; + ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); +} + +void SurfaceGDI::Init(SurfaceID sid, WindowID) { + Release(); + hdc = reinterpret_cast(sid); + ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); +} + +void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID) { + Release(); + hdc = ::CreateCompatibleDC(static_cast(surface_)->hdc); + hdcOwned = true; + bitmap = ::CreateCompatibleBitmap(static_cast(surface_)->hdc, width, height); + bitmapOld = static_cast(::SelectObject(hdc, bitmap)); + ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); +} + +void SurfaceGDI::PenColour(ColourAllocated fore) { + if (pen) { + ::SelectObject(hdc, penOld); + ::DeleteObject(pen); + pen = 0; + penOld = 0; + } + pen = ::CreatePen(0,1,fore.AsLong()); + penOld = static_cast(::SelectObject(reinterpret_cast(hdc), pen)); +} + +void SurfaceGDI::BrushColor(ColourAllocated back) { + if (brush) { + ::SelectObject(hdc, brushOld); + ::DeleteObject(brush); + brush = 0; + brushOld = 0; + } + // Only ever want pure, non-dithered brushes + ColourAllocated colourNearest = ::GetNearestColor(hdc, back.AsLong()); + brush = ::CreateSolidBrush(colourNearest.AsLong()); + brushOld = static_cast(::SelectObject(hdc, brush)); +} + +void SurfaceGDI::SetFont(Font &font_) { + if (font_.GetID() != font) { + FormatAndMetrics *pfm = reinterpret_cast(font_.GetID()); + if (fontOld) { + ::SelectObject(hdc, pfm->hfont); + } else { + fontOld = static_cast(::SelectObject(hdc, pfm->hfont)); + } + font = reinterpret_cast(pfm->hfont); + } +} + +int SurfaceGDI::LogPixelsY() { + return ::GetDeviceCaps(hdc, LOGPIXELSY); +} + +int SurfaceGDI::DeviceHeightFont(int points) { + return ::MulDiv(points, LogPixelsY(), 72); +} + +void SurfaceGDI::MoveTo(int x_, int y_) { + ::MoveToEx(hdc, x_, y_, 0); +} + +void SurfaceGDI::LineTo(int x_, int y_) { + ::LineTo(hdc, x_, y_); +} + +void SurfaceGDI::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { + PenColour(fore); + BrushColor(back); + ::Polygon(hdc, reinterpret_cast(pts), npts); +} + +void SurfaceGDI::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { + PenColour(fore); + BrushColor(back); + ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); +} + +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); + ::SetBkColor(hdc, back.AsLong()); + ::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL); +} + +void SurfaceGDI::FillRectangle(PRectangle rc, Surface &surfacePattern) { + HBRUSH br; + if (static_cast(surfacePattern).bitmap) + br = ::CreatePatternBrush(static_cast(surfacePattern).bitmap); + else // Something is wrong so display in red + br = ::CreateSolidBrush(RGB(0xff, 0, 0)); + RECT rcw = RectFromPRectangle(rc); + ::FillRect(hdc, &rcw, br); + ::DeleteObject(br); +} + +void SurfaceGDI::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { + PenColour(fore); + BrushColor(back); + ::RoundRect(hdc, + rc.left + 1, rc.top, + rc.right - 1, rc.bottom, + 8, 8); +} + +// Plot a point into a DWORD buffer symetrically to all 4 qudrants +static void AllFour(DWORD *pixels, int width, int height, int x, int y, DWORD val) { + pixels[y*width+x] = val; + pixels[y*width+width-1-x] = val; + pixels[(height-1-y)*width+x] = val; + pixels[(height-1-y)*width+width-1-x] = val; +} + +#ifndef AC_SRC_OVER +#define AC_SRC_OVER 0x00 +#endif +#ifndef AC_SRC_ALPHA +#define AC_SRC_ALPHA 0x01 +#endif + +static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) { + union { + byte pixVal[4]; + DWORD val; + } converter; + converter.pixVal[0] = b; + converter.pixVal[1] = g; + converter.pixVal[2] = r; + converter.pixVal[3] = a; + return converter.val; +} + +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)); + int width = rc.Width(); + int height = rc.Height(); + // Ensure not distorted too much by corners when small + cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2); + BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}; + void *image = 0; + HBITMAP hbmMem = CreateDIBSection(reinterpret_cast(hMemDC), &bpih, + DIB_RGB_COLORS, &image, NULL, 0); + + HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); + + DWORD valEmpty = dwordFromBGRA(0,0,0,0); + DWORD valFill = dwordFromBGRA( + static_cast(GetBValue(fill.AsLong()) * alphaFill / 255), + static_cast(GetGValue(fill.AsLong()) * alphaFill / 255), + static_cast(GetRValue(fill.AsLong()) * alphaFill / 255), + static_cast(alphaFill)); + DWORD valOutline = dwordFromBGRA( + static_cast(GetBValue(outline.AsLong()) * alphaOutline / 255), + static_cast(GetGValue(outline.AsLong()) * alphaOutline / 255), + static_cast(GetRValue(outline.AsLong()) * alphaOutline / 255), + static_cast(alphaOutline)); + DWORD *pixels = reinterpret_cast(image); + for (int y=0; y(hdc), rc.left, rc.top, width, height, hMemDC, 0, 0, width, height, merge); + + SelectBitmap(hMemDC, hbmOld); + ::DeleteObject(hbmMem); + ::DeleteDC(hMemDC); + } else { + BrushColor(outline); + RECT rcw = RectFromPRectangle(rc); + FrameRect(hdc, &rcw, brush); + } +} + +void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { + if (AlphaBlendFn && rc.Width() > 0) { + HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast(hdc)); + 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; + + BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}; + unsigned char *image = 0; + HBITMAP hbmMem = CreateDIBSection(reinterpret_cast(hMemDC), &bpih, + DIB_RGB_COLORS, reinterpret_cast(&image), NULL, 0); + HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); + + for (int y=height-1; y>=0; y--) { + for (int x=0; x(hdc), rc.left, rc.top, rc.Width(), rc.Height(), hMemDC, 0, 0, width, height, merge); + + SelectBitmap(hMemDC, hbmOld); + ::DeleteObject(hbmMem); + ::DeleteDC(hMemDC); + + } +} + +void SurfaceGDI::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { + PenColour(fore); + BrushColor(back); + ::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); +} + +void SurfaceGDI::Copy(PRectangle rc, Point from, Surface &surfaceSource) { + ::BitBlt(hdc, + rc.left, rc.top, rc.Width(), rc.Height(), + static_cast(surfaceSource).hdc, from.x, from.y, SRCCOPY); +} + +typedef VarBuffer TextPositionsI; + +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}; + int pos = 0; + int x = rc.left; + + // Text drawing may fail if the text is too big. + // If it does fail, slice up into segments and draw each segment. + const int maxSegmentLength = 0x200; + + if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) { + // Use ANSI calls + int lenDraw = Platform::Minimum(len, maxLenText); + if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s, lenDraw, NULL)) { + while (lenDraw > pos) { + int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos); + if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s+pos, seglen, NULL)) { + PLATFORM_ASSERT(false); + return; + } + ::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz); + x += sz.cx; + pos += seglen; + } + } + } else { + // Use Unicode calls + const TextWide tbuf(s, len, unicodeMode, codePage); + if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL)) { + while (tbuf.tlen > pos) { + int seglen = Platform::Minimum(maxSegmentLength, tbuf.tlen - pos); + if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer+pos, seglen, NULL)) { + PLATFORM_ASSERT(false); + return; + } + ::GetTextExtentPoint32W(hdc, tbuf.buffer+pos, seglen, &sz); + x += sz.cx; + pos += seglen; + } + } + } +} + +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 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 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(s); + int i=0; + while (ui= (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 0) + lastPos = positions[i-1]; + while (i 0) { + int lenBlock = Platform::Minimum(len, maxLenText); + 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;iallowRealization) { + paletteOld = ::SelectPalette(hdc, + reinterpret_cast(pal->hpal), inBackGround); + changes = ::RealizePalette(hdc); + } + return changes; +} + +void SurfaceGDI::SetClip(PRectangle rc) { + ::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); +} + +void SurfaceGDI::FlushCachedState() { + pen = 0; + brush = 0; + font = 0; +} + +void SurfaceGDI::SetUnicodeMode(bool unicodeMode_) { + unicodeMode=unicodeMode_; +} + +void SurfaceGDI::SetDBCSMode(int codePage_) { + // No action on window as automatically handled by system. + codePage = codePage_; + win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP()); +} + #ifdef SCI_NAMESPACE namespace Scintilla { #endif -class SurfaceImpl : public Surface { +class SurfaceD2D : public Surface { bool unicodeMode; HDC hdc; bool hdcOwned; @@ -500,12 +1211,12 @@ class SurfaceImpl : public Surface { void SetFont(Font &font_); - // Private so SurfaceImpl objects can not be copied - SurfaceImpl(const SurfaceImpl &); - SurfaceImpl &operator=(const SurfaceImpl &); + // Private so SurfaceD2D objects can not be copied + SurfaceD2D(const SurfaceD2D &); + SurfaceD2D &operator=(const SurfaceD2D &); public: - SurfaceImpl(); - virtual ~SurfaceImpl(); + SurfaceD2D(); + virtual ~SurfaceD2D(); void SetDWrite(HDC hdc); void Init(WindowID wid); @@ -560,7 +1271,7 @@ public: } //namespace Scintilla #endif -SurfaceImpl::SurfaceImpl() : +SurfaceD2D::SurfaceD2D() : unicodeMode(false), hdc(0), hdcOwned(false), x(0), y(0) { @@ -585,11 +1296,11 @@ SurfaceImpl::SurfaceImpl() : hasBegun = false; } -SurfaceImpl::~SurfaceImpl() { +SurfaceD2D::~SurfaceD2D() { Release(); } -void SurfaceImpl::Release() { +void SurfaceD2D::Release() { if (hdcOwned) { ::DeleteDC(reinterpret_cast(hdc)); hdc = 0; @@ -612,20 +1323,20 @@ void SurfaceImpl::Release() { } } -void SurfaceImpl::SetDWrite(HDC hdc) { +void SurfaceD2D::SetDWrite(HDC hdc) { dpiScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; dpiScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; } -bool SurfaceImpl::Initialised() { +bool SurfaceD2D::Initialised() { return pRenderTarget != 0; } -HRESULT SurfaceImpl::FlushDrawing() { +HRESULT SurfaceD2D::FlushDrawing() { return pRenderTarget->Flush(); } -void SurfaceImpl::Init(WindowID wid) { +void SurfaceD2D::Init(WindowID wid) { Release(); hdc = ::CreateCompatibleDC(NULL); hdcOwned = true; @@ -635,7 +1346,7 @@ void SurfaceImpl::Init(WindowID wid) { SetDWrite(hdc); } -void SurfaceImpl::Init(SurfaceID sid, WindowID) { +void SurfaceD2D::Init(SurfaceID sid, WindowID) { Release(); hdc = ::CreateCompatibleDC(NULL); hdcOwned = true; @@ -644,11 +1355,11 @@ void SurfaceImpl::Init(SurfaceID sid, WindowID) { SetDWrite(hdc); } -void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) { +void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) { Release(); hdc = ::CreateCompatibleDC(NULL); // Just for measurement hdcOwned = true; - SurfaceImpl *psurfOther = static_cast(surface_); + SurfaceD2D *psurfOther = static_cast(surface_); ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL; HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget( D2D1::SizeF(width, height), &pCompatibleRenderTarget); @@ -659,11 +1370,11 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) } } -void SurfaceImpl::PenColour(ColourAllocated fore) { +void SurfaceD2D::PenColour(ColourAllocated fore) { D2DPenColour(fore); } -void SurfaceImpl::D2DPenColour(ColourAllocated fore, int alpha) { +void SurfaceD2D::D2DPenColour(ColourAllocated fore, int alpha) { if (pRenderTarget) { D2D_COLOR_F col; col.r = (fore.AsLong() & 0xff) / 255.0; @@ -682,25 +1393,25 @@ void SurfaceImpl::D2DPenColour(ColourAllocated fore, int alpha) { } } -void SurfaceImpl::SetFont(Font &font_) { - FormatAndMetrics *pfabl = reinterpret_cast(font_.GetID()); - pTextFormat = pfabl->pTextFormat; - yAscent = pfabl->yAscent; - yDescent = pfabl->yDescent; +void SurfaceD2D::SetFont(Font &font_) { + FormatAndMetrics *pfm = reinterpret_cast(font_.GetID()); + pTextFormat = pfm->pTextFormat; + yAscent = pfm->yAscent; + yDescent = pfm->yDescent; if (pRenderTarget) { - pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfabl->extraFontFlag)); + pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfm->extraFontFlag)); } } -int SurfaceImpl::LogPixelsY() { +int SurfaceD2D::LogPixelsY() { return ::GetDeviceCaps(hdc, LOGPIXELSY); } -int SurfaceImpl::DeviceHeightFont(int points) { +int SurfaceD2D::DeviceHeightFont(int points) { return ::MulDiv(points, LogPixelsY(), 72); } -void SurfaceImpl::MoveTo(int x_, int y_) { +void SurfaceD2D::MoveTo(int x_, int y_) { x = x_; y = y_; } @@ -718,7 +1429,7 @@ static int RoundFloat(float f) { return int(f+0.5); } -void SurfaceImpl::LineTo(int x_, int y_) { +void SurfaceD2D::LineTo(int x_, int y_) { if (pRenderTarget) { int xDiff = x_ - x; int xDelta = Delta(xDiff); @@ -748,7 +1459,7 @@ void SurfaceImpl::LineTo(int x_, int y_) { } } -void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { +void SurfaceD2D::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { ID2D1Factory *pFactory = 0; pRenderTarget->GetFactory(&pFactory); @@ -777,7 +1488,7 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllo } } -void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { +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); @@ -788,7 +1499,7 @@ void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAlloc } } -void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { +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); @@ -796,8 +1507,8 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { } } -void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { - SurfaceImpl &surfOther = static_cast(surfacePattern); +void SurfaceD2D::FillRectangle(PRectangle rc, Surface &surfacePattern) { + SurfaceD2D &surfOther = static_cast(surfacePattern); surfOther.FlushDrawing(); ID2D1Bitmap *pBitmap = NULL; ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast( @@ -820,7 +1531,7 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { } } -void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { +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), @@ -836,7 +1547,7 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl } } -void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, +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( @@ -853,7 +1564,7 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated } } -void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) { +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; @@ -889,7 +1600,7 @@ void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsi } } -void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { +void SurfaceD2D::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { FLOAT radius = rc.Width() / 2.0f - 1.0f; D2D1_ELLIPSE ellipse = D2D1::Ellipse( @@ -903,8 +1614,8 @@ void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated b } } -void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { - SurfaceImpl &surfOther = static_cast(surfaceSource); +void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) { + SurfaceD2D &surfOther = static_cast(surfaceSource); surfOther.FlushDrawing(); ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast( surfOther.pRenderTarget); @@ -920,46 +1631,7 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { } } -// 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 -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 { -public: - int tlen; - TextWide(const char *s, int len, bool unicodeMode, int codePage=0) : - VarBuffer(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 TextPositions; - -void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT) { +void SurfaceD2D::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT) { SetFont(font_); RECT rcw = RectFromPRectangle(rc); @@ -985,7 +1657,7 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, c } } -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, +void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -994,7 +1666,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, c } } -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, +void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -1003,7 +1675,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, } } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, +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;iPushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED); @@ -1189,21 +1861,24 @@ void SurfaceImpl::SetClip(PRectangle rc) { } } -void SurfaceImpl::FlushCachedState() { +void SurfaceD2D::FlushCachedState() { } -void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { +void SurfaceD2D::SetUnicodeMode(bool unicodeMode_) { unicodeMode=unicodeMode_; } -void SurfaceImpl::SetDBCSMode(int codePage_) { +void SurfaceD2D::SetDBCSMode(int codePage_) { // No action on window as automatically handled by system. codePage = codePage_; win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP()); } -Surface *Surface::Allocate(int /* technology */) { - return new SurfaceImpl; +Surface *Surface::Allocate(int technology) { + if (technology == SCWIN_TECH_GDI) + return new SurfaceGDI; + else + return new SurfaceD2D; } Window::~Window() { diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index b3b9d1bb0..525621b2c 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -383,8 +383,6 @@ void ScintillaWin::Initialise() { ::GetProcAddress(commctrl32, "_TrackMouseEvent"); } } - - LoadD2D(); } void ScintillaWin::Finalise() { @@ -546,25 +544,35 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) { pps = &ps; ::BeginPaint(MainHWND(), pps); } - //AutoSurface surfaceWindow(pps->hdc, this); - 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); + 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(); - HRESULT hr = pRenderTarget->EndDraw(); - if (hr == D2DERR_RECREATE_TARGET) { - DropRenderTarget(); - } } if (hRgnUpdate) { ::DeleteRgn(hRgnUpdate); @@ -1131,6 +1139,11 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case SCI_SETTECHNOLOGY: if ((wParam == SC_TECHNOLOGY_DEFAULT) || (wParam == SC_TECHNOLOGY_DIRECTWRITE)) { if (technology != static_cast(wParam)) { + if (static_cast(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. InvalidateStyleRedraw(); -- cgit v1.2.3 From 4e7c52c1935534fbd4ba3ebda77ae28155842f60 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 11 Aug 2011 12:09:27 +1000 Subject: Parallel stacks for GDI and DirectWrite works. --- src/FontQuality.h | 2 +- win32/PlatWin.cxx | 37 ++++++++++++++++++++++--------------- win32/ScintillaWin.cxx | 42 +++++++++++++++++++++++++++--------------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/FontQuality.h b/src/FontQuality.h index dc6f28b4c..45600c35e 100644 --- a/src/FontQuality.h +++ b/src/FontQuality.h @@ -12,4 +12,4 @@ #define SC_EFF_QUALITY_LCD_OPTIMIZED 3 #define SCWIN_TECH_GDI 0 -#define SCWIN_TECH_DIRECTWRITE 0 +#define SCWIN_TECH_DIRECTWRITE 1 diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 54b455111..2849144e1 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -236,16 +236,17 @@ bool LoadD2D() { } struct FormatAndMetrics { + int technology; HFONT hfont; IDWriteTextFormat *pTextFormat; int extraFontFlag; FLOAT yAscent; FLOAT yDescent; - FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_) : - hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) { - } FormatAndMetrics(HFONT hfont_, int extraFontFlag_) : - hfont(hfont_), pTextFormat(0), extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1) { + 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) @@ -261,15 +262,19 @@ struct FormatAndMetrics { }; HFONT FormatAndMetrics::HFont() { - LOGFONTW lf; - memset(&lf, 0, sizeof(lf)); + 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(pTextFormat->GetFontSize()); - return ::CreateFontIndirectW(&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(pTextFormat->GetFontSize()); + return ::CreateFontIndirectW(&lf); + } } return 0; } @@ -315,7 +320,7 @@ static D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) { 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(static_cast(size))); + lf.lfHeight = -(abs(static_cast(size + 0.5))); lf.lfWeight = weight; lf.lfItalic = static_cast(italic ? 1 : 0); lf.lfCharSet = static_cast(characterSet); @@ -717,6 +722,7 @@ void SurfaceGDI::BrushColor(ColourAllocated back) { void SurfaceGDI::SetFont(Font &font_) { if (font_.GetID() != font) { FormatAndMetrics *pfm = reinterpret_cast(font_.GetID()); + PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_GDI); if (fontOld) { ::SelectObject(hdc, pfm->hfont); } else { @@ -1395,6 +1401,7 @@ void SurfaceD2D::D2DPenColour(ColourAllocated fore, int alpha) { void SurfaceD2D::SetFont(Font &font_) { FormatAndMetrics *pfm = reinterpret_cast(font_.GetID()); + PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_DIRECTWRITE); pTextFormat = pfm->pTextFormat; yAscent = pfm->yAscent; yDescent = pfm->yDescent; @@ -2306,8 +2313,8 @@ void ListBoxX::SetFont(Font &font) { ::DeleteObject(fontCopy); fontCopy = 0; } - FormatAndMetrics *pfabl = reinterpret_cast(font.GetID()); - fontCopy = pfabl->HFont(); + FormatAndMetrics *pfm = reinterpret_cast(font.GetID()); + fontCopy = pfm->HFont(); ::SendMessage(lb, WM_SETFONT, reinterpret_cast(fontCopy), 0); } } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 525621b2c..bfc4c1b43 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -1146,6 +1146,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam } technology = wParam; // Invalidate all cached information including layout. + DropGraphics(true); InvalidateStyleRedraw(); } } @@ -2379,30 +2380,41 @@ void ScintillaWin::RealizeWindowPalette(bool) { * This paint will not be abandoned. */ void ScintillaWin::FullPaint() { - //HDC hdc = ::GetDC(MainHWND()); - //FullPaintDC(hdc); - //::ReleaseDC(MainHWND(), hdc); - FullPaintDC(0); + if (technology == SC_TECHNOLOGY_DEFAULT) { + HDC hdc = ::GetDC(MainHWND()); + FullPaintDC(hdc); + ::ReleaseDC(MainHWND(), hdc); + } else { + FullPaintDC(0); + } } /** * Redraw all of text area on the specified DC. * This paint will not be abandoned. */ -void ScintillaWin::FullPaintDC(HDC) { +void ScintillaWin::FullPaintDC(HDC hdc) { paintState = painting; rcPaint = GetClientRectangle(); paintingAllText = true; - EnsureRenderTarget(); - AutoSurface surfaceWindow(pRenderTarget, this); - if (surfaceWindow) { - pRenderTarget->BeginDraw(); - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - HRESULT hr = pRenderTarget->EndDraw(); - if (hr == D2DERR_RECREATE_TARGET) { - DropRenderTarget(); - } + 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; } -- cgit v1.2.3 From d3cb2fd86ffe51a93548d4f0b48efc6bec3f0868 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 11 Aug 2011 13:17:37 +1000 Subject: Fix bugs in calltip and autocompletion with technology choice. Simplified Direct2D code. --- win32/PlatWin.cxx | 71 +++++++++++++++++++++----------------------------- win32/ScintillaWin.cxx | 23 +++++++++------- 2 files changed, 43 insertions(+), 51 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 2849144e1..f3c063c1b 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -1192,15 +1192,9 @@ namespace Scintilla { class SurfaceD2D : public Surface { bool unicodeMode; - HDC hdc; - bool hdcOwned; - int maxWidthMeasure; - int maxLenText; int x, y; int codePage; - // If 9x OS and current code page is same as ANSI code page. - bool win9xACPSame; ID2D1RenderTarget *pRenderTarget; bool ownRenderTarget; @@ -1211,9 +1205,10 @@ class SurfaceD2D : public Surface { FLOAT yDescent; ID2D1SolidColorBrush *pBrush; + + int logPixelsY; float dpiScaleX; float dpiScaleY; - bool hasBegun; void SetFont(Font &font_); @@ -1224,7 +1219,7 @@ public: SurfaceD2D(); virtual ~SurfaceD2D(); - void SetDWrite(HDC hdc); + void SetScale(); void Init(WindowID wid); void Init(SurfaceID sid, WindowID wid); void InitPixMap(int width, int height, Surface *surface_, WindowID wid); @@ -1279,27 +1274,24 @@ public: SurfaceD2D::SurfaceD2D() : unicodeMode(false), - hdc(0), hdcOwned(false), x(0), y(0) { - // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels - maxWidthMeasure = IsNT() ? INT_MAX : 30000; - // There appears to be a 16 bit string length limit in GDI on NT and a limit of - // 8192 characters on Windows 95. - maxLenText = IsNT() ? 65535 : 8192; codePage = 0; - win9xACPSame = false; 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; - hasBegun = false; } SurfaceD2D::~SurfaceD2D() { @@ -1307,12 +1299,6 @@ SurfaceD2D::~SurfaceD2D() { } void SurfaceD2D::Release() { - if (hdcOwned) { - ::DeleteDC(reinterpret_cast(hdc)); - hdc = 0; - hdcOwned = false; - } - if (pBrush) { pBrush->Release(); pBrush = 0; @@ -1329,9 +1315,12 @@ void SurfaceD2D::Release() { } } -void SurfaceD2D::SetDWrite(HDC hdc) { - dpiScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; - dpiScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; +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() { @@ -1342,29 +1331,20 @@ HRESULT SurfaceD2D::FlushDrawing() { return pRenderTarget->Flush(); } -void SurfaceD2D::Init(WindowID wid) { +void SurfaceD2D::Init(WindowID /* wid */) { Release(); - hdc = ::CreateCompatibleDC(NULL); - hdcOwned = true; - ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); - RECT rc; - ::GetClientRect(reinterpret_cast(wid), &rc); - SetDWrite(hdc); + SetScale(); } void SurfaceD2D::Init(SurfaceID sid, WindowID) { Release(); - hdc = ::CreateCompatibleDC(NULL); - hdcOwned = true; + SetScale(); pRenderTarget = reinterpret_cast(sid); - ::SetTextAlign(reinterpret_cast(hdc), TA_BASELINE); - SetDWrite(hdc); } void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) { Release(); - hdc = ::CreateCompatibleDC(NULL); // Just for measurement - hdcOwned = true; + SetScale(); SurfaceD2D *psurfOther = static_cast(surface_); ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL; HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget( @@ -1411,7 +1391,7 @@ void SurfaceD2D::SetFont(Font &font_) { } int SurfaceD2D::LogPixelsY() { - return ::GetDeviceCaps(hdc, LOGPIXELSY); + return logPixelsY; } int SurfaceD2D::DeviceHeightFont(int points) { @@ -1878,7 +1858,6 @@ void SurfaceD2D::SetUnicodeMode(bool unicodeMode_) { void SurfaceD2D::SetDBCSMode(int codePage_) { // No action on window as automatically handled by system. codePage = codePage_; - win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP()); } Surface *Surface::Allocate(int technology) { @@ -2485,7 +2464,16 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { if (pimage) { Surface *surfaceItem = Surface::Allocate(technology); if (surfaceItem) { - if (pD2DFactory) { + 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( @@ -2510,7 +2498,6 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { surfaceItem->DrawRGBAImage(rcImage, pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels()); delete surfaceItem; - ::SetTextAlign(pDrawItem->hDC, TA_TOP); pDCRT->EndDraw(); pDCRT->Release(); } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index bfc4c1b43..c16da8fdb 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -2792,20 +2792,25 @@ sptr_t PASCAL ScintillaWin::CTWndProc( RECT rc; GetClientRect(hWnd, &rc); // Create a Direct2D render target. - pD2DFactory->CreateHwndRenderTarget( - D2D1::RenderTargetProperties(), - D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)), - &pCTRenderTarget); - //surfaceWindow->Init(ps.hdc, hWnd); - surfaceWindow->Init(pCTRenderTarget, hWnd); + 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); - pCTRenderTarget->BeginDraw(); sciThis->ct.PaintCT(surfaceWindow); - pCTRenderTarget->EndDraw(); + if (pCTRenderTarget) + pCTRenderTarget->EndDraw(); surfaceWindow->Release(); delete surfaceWindow; - pCTRenderTarget->Release(); + if (pCTRenderTarget) + pCTRenderTarget->Release(); } ::EndPaint(hWnd, &ps); return 0; -- cgit v1.2.3 From 9346fc9f67867d64ddb767080ab053abd9a07083 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 11 Aug 2011 14:22:16 +1000 Subject: Implement new APIs defined for technology choice on Windows. --- cocoa/PlatCocoa.mm | 15 +++++++-------- cocoa/ScintillaCocoa.mm | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm index 0965409c1..9b4455237 100644 --- a/cocoa/PlatCocoa.mm +++ b/cocoa/PlatCocoa.mm @@ -156,8 +156,7 @@ static int FontCharacterSet(Font &f) { /** * Creates a CTFontRef with the given properties. */ -void Font::Create(const char *faceName, int characterSet, float size, int weight, bool italic, - int /* extraFontFlag */) +void Font::Create(const FontParameters &fp) { Release(); @@ -165,9 +164,9 @@ void Font::Create(const char *faceName, int characterSet, float size, int weight fid = style; // Create the font with attributes - QuartzFont font(faceName, strlen(faceName), size, bold, italic); + QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic); CTFontRef fontRef = font.getFontID(); - style->setFontRef(fontRef, characterSet); + style->setFontRef(fontRef, fp.characterSet); } //-------------------------------------------------------------------------------------------------- @@ -1095,7 +1094,7 @@ void SurfaceImpl::SetDBCSMode(int codePage_) { codePage = codePage_; } -Surface *Surface::Allocate() +Surface *Surface::Allocate(int) { return new SurfaceImpl(); } @@ -1374,7 +1373,7 @@ static NSImage* ImageFromXPM(XPM* pxpm) const int width = pxpm->GetWidth(); const int height = pxpm->GetHeight(); PRectangle rcxpm(0, 0, width, height); - Surface* surfaceXPM = Surface::Allocate(); + Surface* surfaceXPM = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceXPM) { surfaceXPM->InitPixMap(width, height, NULL, NULL); @@ -1510,7 +1509,7 @@ public: // ListBox methods void SetFont(Font& font); - void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_); + void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_); void SetAverageCharWidth(int width); void SetVisibleRows(int rows); int GetVisibleRows() const; @@ -1595,7 +1594,7 @@ ListBox* ListBox::Allocate() } void ListBoxImpl::Create(Window& /*parent*/, int /*ctrlID*/, Scintilla::Point pt, - int lineHeight_, bool unicodeMode_) + int lineHeight_, bool unicodeMode_, int) { lineHeight = lineHeight_; unicodeMode = unicodeMode_; diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm index 089568d66..7927652a7 100644 --- a/cocoa/ScintillaCocoa.mm +++ b/cocoa/ScintillaCocoa.mm @@ -702,7 +702,7 @@ void ScintillaCocoa::Paste(bool forceRectangular) void ScintillaCocoa::CTPaint(void* gc, NSRect rc) { #pragma unused(rc) - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceWindow) { surfaceWindow->Init(gc, wMain.GetID()); surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ct.codePage); @@ -1251,7 +1251,7 @@ void ScintillaCocoa::SyncPaint(void* gc, PRectangle rc) rcPaint = rc; PRectangle rcText = GetTextRectangle(); paintingAllText = rcPaint.Contains(rcText); - Surface *sw = Surface::Allocate(); + Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (sw) { sw->Init(gc, wMain.GetID()); -- cgit v1.2.3 From b6c394825bf6dd8212bf1ff8820d6d2ffab2a7d3 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Thu, 11 Aug 2011 14:42:35 +1000 Subject: Implement new APIs defined for technology choice on Windows. --- gtk/PlatGTK.cxx | 77 +++++++++++++++++++++++++--------------------------- gtk/ScintillaGTK.cxx | 8 +++--- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 9f24e1b1d..a8bd051a8 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -459,13 +459,13 @@ static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, floa * 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, int weight, bool italic) { +static int HashFont(const FontParameters &fp) { return - size ^ - (characterSet << 10) ^ - ((weight / 100) << 12) ^ - (italic ? 0x20000000 : 0) ^ - faceName[0]; + static_cast(fp.size+0.5) ^ + (fp.characterSet << 10) ^ + ((fp.weight / 100) << 12) ^ + (fp.italic ? 0x20000000 : 0) ^ + fp.faceName[0]; } class FontCached : Font { @@ -473,35 +473,34 @@ class FontCached : Font { int usage; LOGFONT lf; int hash; - FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); + FontCached(const FontParameters &fp); ~FontCached() {} - bool SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); + bool SameAs(const FontParameters &fp); virtual void Release(); - static FontID CreateNewFont(const char *fontName, int characterSet, - float size, int weight, bool italic); + static FontID CreateNewFont(const FontParameters &fp); static FontCached *first; public: - static FontID FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_); + static FontID FindOrCreate(const FontParameters &fp); static void ReleaseId(FontID fid_); }; FontCached *FontCached::first = 0; -FontCached::FontCached(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) : +FontCached::FontCached(const FontParameters &fp) : next(0), usage(0), hash(0) { - ::SetLogFont(lf, faceName_, characterSet_, size_, weight_, italic_); - hash = HashFont(faceName_, characterSet_, size_, weight_, italic_); - fid = CreateNewFont(faceName_, characterSet_, size_, weight_, italic_); + ::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic); + hash = HashFont(fp); + fid = CreateNewFont(fp); usage = 1; } -bool FontCached::SameAs(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) { +bool FontCached::SameAs(const FontParameters &fp) { return - lf.size == size_ && - lf.weight == weight_ && - lf.italic == italic_ && - lf.characterSet == characterSet_ && - 0 == strcmp(lf.faceName, faceName_); + lf.size == fp.size && + lf.weight == fp.weight && + lf.italic == fp.italic && + lf.characterSet == fp.characterSet && + 0 == strcmp(lf.faceName, fp.faceName); } void FontCached::Release() { @@ -510,19 +509,19 @@ void FontCached::Release() { fid = 0; } -FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, float size_, int weight_, bool italic_) { +FontID FontCached::FindOrCreate(const FontParameters &fp) { FontID ret = 0; FontMutexLock(); - int hashFind = HashFont(faceName_, characterSet_, size_, weight_, italic_); + int hashFind = HashFont(fp); for (FontCached *cur = first; cur; cur = cur->next) { if ((cur->hash == hashFind) && - cur->SameAs(faceName_, characterSet_, size_, weight_, italic_)) { + cur->SameAs(fp)) { cur->usage++; ret = cur->fid; } } if (ret == 0) { - FontCached *fc = new FontCached(faceName_, characterSet_, size_, weight_, italic_); + FontCached *fc = new FontCached(fp); if (fc) { fc->next = first; first = fc; @@ -562,16 +561,15 @@ static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) { } #endif -FontID FontCached::CreateNewFont(const char *fontName, int characterSet, - float size, int weight, bool italic) { - if (fontName[0] == '!') { +FontID FontCached::CreateNewFont(const FontParameters &fp) { + if (fp.faceName[0] == '!') { PangoFontDescription *pfd = pango_font_description_new(); if (pfd) { - pango_font_description_set_family(pfd, fontName+1); - pango_font_description_set_size(pfd, pango_units_from_double(size)); - pango_font_description_set_weight(pfd, static_cast(weight)); - pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); - return new FontHandle(pfd, characterSet); + pango_font_description_set_family(pfd, fp.faceName+1); + pango_font_description_set_size(pfd, pango_units_from_double(fp.size)); + pango_font_description_set_weight(pfd, static_cast(fp.weight)); + pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); + return new FontHandle(pfd, fp.characterSet); } } @@ -729,10 +727,9 @@ Font::Font() : fid(0) {} Font::~Font() {} -void Font::Create(const char *faceName, int characterSet, float size, - int weight, bool italic, int) { +void Font::Create(const FontParameters &fp) { Release(); - fid = FontCached::FindOrCreate(faceName, characterSet, size, weight, italic); + fid = FontCached::FindOrCreate(fp); } void Font::Release() { @@ -2103,8 +2100,8 @@ void SurfaceImpl::SetDBCSMode(int codePage) { et = dbcs; } -Surface *Surface::Allocate() { - return new SurfaceImpl; +Surface *Surface::Allocate(int) { + return new SurfaceImpl(); } Window::~Window() {} @@ -2324,7 +2321,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; @@ -2413,7 +2410,7 @@ static void StyleSet(GtkWidget *w, GtkStyle*, void*) { #endif } -void ListBoxX::Create(Window &, int, Point, int, bool) { +void ListBoxX::Create(Window &, int, Point, int, bool, int) { wid = gtk_window_new(GTK_WINDOW_POPUP); GtkWidget *frame = gtk_frame_new(NULL); diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index b7cea5ed3..2b2a7c689 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -586,7 +586,7 @@ void ScintillaGTK::UnMapThis() { #else GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED); #endif - DropGraphics(); + DropGraphics(false); gdk_window_hide(PWindow(wMain)); gtk_widget_unmap(PWidget(wText)); gtk_widget_unmap(PWidget(scrollbarh)); @@ -1114,7 +1114,7 @@ void ScintillaGTK::SyncPaint(PRectangle rc) { PRectangle rcClient = GetClientRectangle(); paintingAllText = rcPaint.Contains(rcClient); if (PWindow(wText)) { - Surface *sw = Surface::Allocate(); + Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (sw) { #if GTK_CHECK_VERSION(3,0,0) cairo_t *cr = gdk_cairo_create(PWindow(wText)); @@ -2475,7 +2475,7 @@ gboolean ScintillaGTK::DrawTextThis(cairo_t *cr) { rcPaint.bottom = y2; PRectangle rcClient = GetClientRectangle(); paintingAllText = rcPaint.Contains(rcClient); - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceWindow) { surfaceWindow->Init(cr, PWidget(wText)); Paint(surfaceWindow, rcPaint); @@ -2833,7 +2833,7 @@ gboolean ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, Scintil gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) { try { - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceWindow) { surfaceWindow->Init(cr, widget); surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); -- cgit v1.2.3 From 9f1e13f587c8c3221a99cd2beee90242c32862fc Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Fri, 12 Aug 2011 23:12:47 +1000 Subject: Added SCI_STYLESETSIZEFRACTIONAL, SCI_STYLESETWEIGHT, and SCI_SETTECHNOLOGY. --- doc/ScintillaDoc.html | 34 ++++++++++++++++++++++++++++++++++ include/Scintilla.iface | 4 ++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index c733db471..c0b0c7a6f 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -2392,9 +2392,15 @@ struct Sci_TextToFind { SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)
SCI_STYLEGETSIZE(int styleNumber)
+ SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int + sizeInHundredthPoints)
+ SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
SCI_STYLESETBOLD(int styleNumber, bool bold)
SCI_STYLEGETBOLD(int styleNumber)
+ SCI_STYLESETWEIGHT(int styleNumber, int + weight)
+ SCI_STYLEGETWEIGHT(int styleNumber)
SCI_STYLESETITALIC(int styleNumber, bool italic)
SCI_STYLEGETITALIC(int styleNumber)
@@ -2443,8 +2449,12 @@ struct Sci_TextToFind { SCI_STYLEGETFONT(int styleNumber, char *fontName)
SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)
SCI_STYLEGETSIZE(int styleNumber)
+ SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int sizeInHundredthPoints)
+ SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)
SCI_STYLESETBOLD(int styleNumber, bool bold)
SCI_STYLEGETBOLD(int styleNumber)
+ SCI_STYLESETWEIGHT(int styleNumber, int weight)
+ SCI_STYLEGETWEIGHT(int styleNumber)
SCI_STYLESETITALIC(int styleNumber, bool italic)
SCI_STYLEGETITALIC(int styleNumber)
These messages (plus +

Sizes can be set to a whole number of points with SCI_STYLESETSIZE + or to a fractional point size in hundredths of a point with SCI_STYLESETSIZEFRACTIONAL + by multiplying the size by 100 (SC_FONT_SIZE_MULTIPLIER). + For example, a text size of 9.4 points is set with SCI_STYLESETSIZEFRACTIONAL(<style>, 940). +

+

The weight or boldness of a font can be set with SCI_STYLESETBOLD + or SCI_STYLESETWEIGHT. The weight is a number between 1 and 999 with 1 being very light + and 999 very heavy. While any value can be used, fonts often only support between 2 and 4 weights with three weights + being common enough to have symbolic names: + SC_WEIGHT_NORMAL (400), + SC_WEIGHT_SEMIBOLD (600), and + SC_WEIGHT_BOLD (700). + The SCI_STYLESETBOLD message takes a boolean argument with 0 choosing SC_WEIGHT_NORMAL + and 1 SC_WEIGHT_BOLD. +

SCI_STYLESETUNDERLINE(int styleNumber, bool underline)
@@ -2983,6 +3008,8 @@ struct Sci_TextToFind {
SCI_GETBUFFEREDDRAW
SCI_SETTWOPHASEDRAW(bool twoPhase)
SCI_GETTWOPHASEDRAW
+ SCI_SETTECHNOLOGY(int technology)
+ SCI_GETTECHNOLOGY
SCI_SETFONTQUALITY(int fontQuality)
SCI_GETFONTQUALITY
SCI_SETCODEPAGE(int codePage)
@@ -3046,6 +3073,13 @@ struct Sci_TextToFind { transparent mode. Two phase drawing may flicker more than single phase unless buffered drawing is on. The default is for drawing to be two phase.

+

SCI_SETTECHNOLOGY(int technology)
+ SCI_GETTECHNOLOGY
+ The technology property allows choosing between different drawing APIs and options. + On most platforms, the only choice is SC_TECHNOLOGY_DEFAULT (0). + On Windows Vista or later, SC_TECHNOLOGY_DIRECTWRITE (1) + can be chosen to use the Direct2D and DirectWrite APIs for higher quality antialiased drawing.

+

SCI_SETFONTQUALITY(int fontQuality)
SCI_GETFONTQUALITY
Manage font quality (antialiasing method). Currently, the following values are available on Windows: diff --git a/include/Scintilla.iface b/include/Scintilla.iface index c5b58caae..08a77b605 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -487,7 +487,7 @@ val SC_FONT_SIZE_MULTIPLIER=100 # Set the size of characters of a style. Size is in points multiplied by 100. set void StyleSetSizeFractional=2061(int style, int caseForce) -# Get the weight of characters of a style in points multiplied by 100 +# Get the size of characters of a style in points multiplied by 100 get int StyleGetSizeFractional=2062(int style,) enu FontWeight=SC_WEIGHT_ @@ -495,7 +495,7 @@ val SC_WEIGHT_NORMAL=400 val SC_WEIGHT_SEMIBOLD=600 val SC_WEIGHT_BOLD=700 -# Get the weight of characters of a style. +# Set the weight of characters of a style. set void StyleSetWeight=2063(int style, int weight) # Get the weight of characters of a style. -- cgit v1.2.3 From 2598b5e38c3e22e4264dc6d89fefc5dd10b45476 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Fri, 9 Sep 2011 23:39:47 +1000 Subject: Simplify some expressions which seem to cause failures. --- src/Editor.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Editor.cxx b/src/Editor.cxx index 1257ac4b0..9e84132f2 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -2588,7 +2588,7 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin // Draw the eol-is-selected rectangle rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; - rcSegment.right = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth; + rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); @@ -2608,7 +2608,7 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin } // Fill the remainder of the line - rcSegment.left = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth; + rcSegment.left = rcSegment.right; if (rcSegment.left < rcLine.left) rcSegment.left = rcLine.left; rcSegment.right = rcLine.right; -- cgit v1.2.3 From a848e8165894cc4124635ea44b721f8eadf54354 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Fri, 9 Sep 2011 23:43:31 +1000 Subject: Update calls to Surface::Allocate for GTK+ 2. --- gtk/ScintillaGTK.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index efb0e0cd5..1422a183a 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -2534,7 +2534,7 @@ gboolean ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *os rgnUpdate = gdk_region_copy(ose->region); PRectangle rcClient = GetClientRectangle(); paintingAllText = rcPaint.Contains(rcClient); - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceWindow) { surfaceWindow->Init(PWindow(wText), PWidget(wText)); Paint(surfaceWindow, rcPaint); @@ -2850,7 +2850,7 @@ gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) { gboolean ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) { try { - Surface *surfaceWindow = Surface::Allocate(); + Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT); if (surfaceWindow) { surfaceWindow->Init(WindowFromWidget(widget), widget); surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage); -- cgit v1.2.3 From 33e27dc25f933a92566d91a667ba4ee732ba6cfa Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Fri, 9 Sep 2011 23:44:33 +1000 Subject: Update deprecated calls to GTK+ 3 maintained functions. --- gtk/PlatGTK.cxx | 4 ++++ gtk/ScintillaGTK.cxx | 28 +++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index ffb04d005..064d5161a 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -2219,7 +2219,11 @@ void Window::SetCursor(Cursor curs) { if (WindowFromWidget(PWidget(wid))) gdk_window_set_cursor(WindowFromWidget(PWidget(wid)), gdkCurs); +#if GTK_CHECK_VERSION(3,0,0) + g_object_unref(gdkCurs); +#else gdk_cursor_unref(gdkCurs); +#endif } void Window::SetTitle(const char *s) { diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 1422a183a..fd59e0f97 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -405,6 +405,14 @@ ScintillaGTK::~ScintillaGTK() { g_idle_remove_by_data(this); } +static void UnRefCursor(GdkCursor *cursor) { +#if GTK_CHECK_VERSION(3,0,0) + g_object_unref(cursor); +#else + gdk_cursor_unref(cursor); +#endif +} + void ScintillaGTK::RealizeThis(GtkWidget *widget) { //Platform::DebugPrintf("ScintillaGTK::realize this\n"); #if GTK_CHECK_VERSION(2,20,0) @@ -436,12 +444,14 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) { gtk_widget_set_window(widget, gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_CURSOR)); gdk_window_set_user_data(gtk_widget_get_window(widget), widget); - // Deprecated: should chain up to parent class' "realize" implementation - gtk_widget_style_attach(widget); - gdk_window_set_background(gtk_widget_get_window(widget), - &(gtk_widget_get_style(widget)->bg[GTK_STATE_NORMAL])); + GtkStyleContext *styleContext = gtk_widget_get_style_context(widget); + if (styleContext) { + GdkRGBA colourBackWidget; + gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_NORMAL, &colourBackWidget); + gdk_window_set_background_rgba(gtk_widget_get_window(widget), &colourBackWidget); + } gdk_window_show(gtk_widget_get_window(widget)); - gdk_cursor_unref(cursor); + UnRefCursor(cursor); #else widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR); @@ -449,7 +459,7 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) { widget->style = gtk_style_attach(widget->style, widget->window); gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]); gdk_window_show(widget->window); - gdk_cursor_unref(cursor); + UnRefCursor(cursor); #endif wPreedit = gtk_window_new(GTK_WINDOW_POPUP); wPreeditDraw = gtk_drawing_area_new(); @@ -483,15 +493,15 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) { cursor = gdk_cursor_new(GDK_XTERM); gdk_window_set_cursor(PWindow(wText), cursor); - gdk_cursor_unref(cursor); + UnRefCursor(cursor); cursor = gdk_cursor_new(GDK_LEFT_PTR); gdk_window_set_cursor(PWindow(scrollbarv), cursor); - gdk_cursor_unref(cursor); + UnRefCursor(cursor); cursor = gdk_cursor_new(GDK_LEFT_PTR); gdk_window_set_cursor(PWindow(scrollbarh), cursor); - gdk_cursor_unref(cursor); + UnRefCursor(cursor); gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, clipboardCopyTargets, nClipboardCopyTargets); -- cgit v1.2.3