From 3443ea8530e6e6f2a1195b4ae472e9c50b9434f4 Mon Sep 17 00:00:00 2001 From: nyamatongwe Date: Sun, 26 Feb 2006 00:58:22 +0000 Subject: Translucency implementation for INDIC_ROUNDBOX and caret line. --- doc/ScintillaDoc.html | 31 +++++++++++++++++- gtk/PlatGTK.cxx | 84 +++++++++++++++++++++++++++++++++++++++++++++++ include/Platform.h | 2 ++ include/Scintilla.h | 6 ++++ include/Scintilla.iface | 11 +++++++ src/Editor.cxx | 15 ++++++++- src/Indicator.cxx | 6 ++++ src/ViewStyle.cxx | 2 ++ src/ViewStyle.h | 1 + win32/PlatWin.cxx | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ win32/ScintillaWin.cxx | 12 +++---- 11 files changed, 248 insertions(+), 8 deletions(-) diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 42314186a..e6aae3b73 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -130,6 +130,17 @@ system and the current screen mode. + + alpha + + Translucency is set using an alpha value. + Alpha ranges from 0 (SC_ALPHA_TRANSPARENT) which is completely transparent to + 255 (SC_ALPHA_OPAQUE) which is opaque. The value 256 (SC_ALPHA_NOALPHA) + is opaque and uses code that is not alpha-aware and may be faster. Not all platforms support + translucency and only some Scintilla features implement translucency. + The default alpha value for most features is SC_ALPHA_NOALPHA. + + <unused> @@ -2110,6 +2121,8 @@ struct TextToFind { SCI_GETCARETLINEVISIBLE
SCI_SETCARETLINEBACK(int colour)
SCI_GETCARETLINEBACK
+ SCI_SETCARETLINEBACKALPHA(int alpha)
+ SCI_GETCARETLINEBACKALPHA
SCI_SETCARETPERIOD(int milliseconds)
SCI_GETCARETPERIOD
SCI_SETCARETWIDTH(int pixels)
@@ -2146,13 +2159,20 @@ struct TextToFind { SCI_SETCARETLINEBACK(int colour)
SCI_GETCARETLINEBACK
+ SCI_SETCARETLINEBACKALPHA(int alpha)
+ SCI_GETCARETLINEBACKALPHA
You can choose to make the background colour of the line containing the caret different with these messages. To do this, set the desired background colour with SCI_SETCARETLINEBACK, then use SCI_SETCARETLINEVISIBLE(true) to enable the effect. You can cancel the effect with SCI_SETCARETLINEVISIBLE(false). The two SCI_GETCARET* functions return the state and the colour. This form of background colouring has highest priority when a line has markers that would otherwise change - the background colour.

+ the background colour. + The caret line may also be drawn translucently which allows other background colours to show + through. This is done by setting the alpha (translucency) value by calling + SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA, + the caret line is drawn after all other features so will affect the colour of all other features. +

SCI_SETCARETPERIOD(int milliseconds)
SCI_GETCARETPERIOD
@@ -2940,6 +2960,15 @@ struct TextToFind { A rectangle around the text. + + + INDIC_ROUNDBOX + + 6 + + A rectangle with rounded corners around the text using translucent drawing with the + interior more transparent than the border. + diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index f776a2c19..20c518fdb 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -713,6 +713,8 @@ public: 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 Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); @@ -1014,6 +1016,88 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl } } +// Plot a point into a guint32 buffer symetrically to all 4 qudrants +static void AllFour(guint32 *pixels, int stride, int width, int height, int x, int y, guint32 val) { + pixels[y*stride+x] = val; + pixels[y*stride+width-1-x] = val; + pixels[(height-1-y)*stride+x] = val; + pixels[(height-1-y)*stride+width-1-x] = val; +} + +static unsigned int GetRValue(unsigned int co) { + return (co >> 16) & 0xff; +} + +static unsigned int GetGValue(unsigned int co) { + return (co >> 8) & 0xff; +} + +static unsigned int GetBValue(unsigned int co) { + return co & 0xff; +} + +#if GTK_MAJOR_VERSION < 2 +void SurfaceImpl::AlphaRectangle(PRectangle rc, int , ColourAllocated , int , ColourAllocated outline, int , int ) { + if (gc && drawable) { + // Can't use GdkPixbuf on GTK+ 1.x, so draw an outline rather than use alpha. + PenColour(outline); + gdk_draw_rectangle(drawable, gc, 0, + rc.left, rc.top, + rc.right - rc.left - 1, rc.bottom - rc.top - 1); + } +} +#else +void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, + ColourAllocated outline, int alphaOutline, int flags) { + if (gc && drawable) { + 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); + // Make a 32 bit deep pixbuf with alpha + GdkPixbuf *pixalpha = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); + + guint8 pixVal[4] = {0}; + guint32 valEmpty = *(reinterpret_cast(pixVal)); + pixVal[0] = GetRValue(fill.AsLong()); + pixVal[1] = GetGValue(fill.AsLong()); + pixVal[2] = GetBValue(fill.AsLong()); + pixVal[3] = alphaFill; + guint32 valFill = *(reinterpret_cast(pixVal)); + pixVal[0] = GetRValue(outline.AsLong()); + pixVal[1] = GetGValue(outline.AsLong()); + pixVal[2] = GetBValue(outline.AsLong()); + pixVal[3] = alphaOutline; + guint32 valOutline = *(reinterpret_cast(pixVal)); + guint32 *pixels = reinterpret_cast(gdk_pixbuf_get_pixels(pixalpha)); + int stride = gdk_pixbuf_get_rowstride(pixalpha) / 4; + for (int y=0; ycontainsCaret) { + if (caret.active && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) { overrideBackground = true; background = vsDraw.caretLineBackground.allocated; } @@ -2653,6 +2653,13 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis rcSegment.right = rcSegment.left + 1; surface->FillRectangle(rcSegment, vsDraw.edgecolour.allocated); } + + if (caret.active && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha != SC_ALPHA_NOALPHA) && ll->containsCaret) { + rcSegment.left = xStart; + rcSegment.right = rcLine.right - 1; + surface->AlphaRectangle(rcSegment, 0, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha, + vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha, 0); + } } void Editor::RefreshPixMaps(Surface *surfaceWindow) { @@ -6723,6 +6730,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { vs.caretLineBackground.desired = wParam; InvalidateStyleRedraw(); break; + case SCI_GETCARETLINEBACKALPHA: + return vs.caretLineAlpha; + case SCI_SETCARETLINEBACKALPHA: + vs.caretLineAlpha = wParam; + InvalidateStyleRedraw(); + break; // Folding messages diff --git a/src/Indicator.cxx b/src/Indicator.cxx index a42abb203..7624a4a52 100644 --- a/src/Indicator.cxx +++ b/src/Indicator.cxx @@ -63,6 +63,12 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r surface->LineTo(rc.right, rcLine.top+1); surface->LineTo(rc.left, rcLine.top+1); surface->LineTo(rc.left, ymid+1); + } else if (style == INDIC_ROUNDBOX) { + PRectangle rcBox = rcLine; + rcBox.top = rcLine.top + 1; + rcBox.left = rc.left; + rcBox.right = rc.right; + surface->AlphaRectangle(rcBox, 1, fore.allocated, 30, fore.allocated, 50, 0); } else { // Either INDIC_PLAIN or unknown surface->MoveTo(rc.left, ymid); surface->LineTo(rc.right, ymid); diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index fe519905b..f221af193 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -95,6 +95,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) { caretcolour.desired = source.caretcolour.desired; showCaretLineBackground = source.showCaretLineBackground; caretLineBackground.desired = source.caretLineBackground.desired; + caretLineAlpha = source.caretLineAlpha; edgecolour.desired = source.edgecolour.desired; edgeState = source.edgeState; caretWidth = source.caretWidth; @@ -157,6 +158,7 @@ void ViewStyle::Init() { caretcolour.desired = ColourDesired(0, 0, 0); showCaretLineBackground = false; caretLineBackground.desired = ColourDesired(0xff, 0xff, 0); + caretLineAlpha = SC_ALPHA_NOALPHA; edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0); edgeState = EDGE_NONE; caretWidth = 1; diff --git a/src/ViewStyle.h b/src/ViewStyle.h index d06c02002..90d50b1fb 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -85,6 +85,7 @@ public: ColourPair caretcolour; bool showCaretLineBackground; ColourPair caretLineBackground; + int caretLineAlpha; ColourPair edgecolour; int edgeState; int caretWidth; diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index f9b05fce6..110f26421 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -64,9 +64,14 @@ static LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) { } #endif +typedef BOOL (WINAPI *AlphaBlendSig)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); + static CRITICAL_SECTION crPlatformLock; static HINSTANCE hinstPlatformRes = 0; static bool onNT = false; +static HMODULE hDLLImage = 0; +static AlphaBlendSig AlphaBlendFn = 0; + bool IsNT() { return onNT; @@ -355,6 +360,8 @@ public: 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 Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); @@ -557,6 +564,79 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl 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 + +void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, + ColourAllocated outline, int alphaOutline, int /* flags*/ ) { + if (AlphaBlendFn) { + 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); + + byte pixVal[4] = {0}; + DWORD valEmpty = *(reinterpret_cast(pixVal)); + pixVal[0] = static_cast(GetBValue(fill.AsLong()) * alphaFill / 255); + pixVal[1] = static_cast(GetGValue(fill.AsLong()) * alphaFill / 255); + pixVal[2] = static_cast(GetRValue(fill.AsLong()) * alphaFill / 255); + pixVal[3] = static_cast(alphaFill); + DWORD valFill = *(reinterpret_cast(pixVal)); + pixVal[0] = static_cast(GetBValue(outline.AsLong()) * alphaOutline / 255); + pixVal[1] = static_cast(GetGValue(outline.AsLong()) * alphaOutline / 255); + pixVal[2] = static_cast(GetRValue(outline.AsLong()) * alphaOutline / 255); + pixVal[3] = static_cast(alphaOutline); + DWORD valOutline = *(reinterpret_cast(pixVal)); + 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); + ::DeleteObject(hMemDC); + } else { + RectangleDraw(rc, outline, fill); + } +} + void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); BrushColor(back); @@ -2081,6 +2161,12 @@ void Platform_Initialise(void *hInstance) { onNT = osv.dwPlatformId == VER_PLATFORM_WIN32_NT; ::InitializeCriticalSection(&crPlatformLock); hinstPlatformRes = reinterpret_cast(hInstance); + if (!hDLLImage) { + hDLLImage = ::LoadLibrary(TEXT("Msimg32")); + } + if (hDLLImage) { + AlphaBlendFn = (AlphaBlendSig)::GetProcAddress(hDLLImage, "AlphaBlend"); + } ListBoxX_Register(); } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 34e8b1a96..62641213e 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -12,7 +12,7 @@ #include #include -#define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 #include #include #include @@ -494,7 +494,7 @@ sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) { ::ImmReleaseContext(MainHWND(), hIMC); } return 0; - } + } return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam); #endif } @@ -1792,7 +1792,7 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) { selectedText.characterSet, selectedText.codePage); uniText.Allocate(2 * selectedText.len); if (uniText) { - ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len, + ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len, static_cast(uniText.ptr), selectedText.len); } } @@ -1806,7 +1806,7 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) { GlobalMemory ansiText; ansiText.Allocate(selectedText.len); if (ansiText) { - ::WideCharToMultiByte(CP_ACP, 0, static_cast(uniText.ptr), -1, + ::WideCharToMultiByte(CP_ACP, 0, static_cast(uniText.ptr), -1, static_cast(ansiText.ptr), selectedText.len, NULL, NULL); ansiText.SetClip(CF_TEXT); } @@ -1945,7 +1945,7 @@ static bool CompareDevCap(HDC hdc, HDC hOtherDC, int nIndex) { bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) { HDC hdc = ::GetDC(MainHWND()); - bool isCompatible = + bool isCompatible = CompareDevCap(hdc, hOtherDC, TECHNOLOGY) && CompareDevCap(hdc, hOtherDC, LOGPIXELSY) && CompareDevCap(hdc, hOtherDC, LOGPIXELSX) && @@ -2256,7 +2256,7 @@ BOOL ScintillaWin::DestroySystemCaret() { } return retval; } - + // Take care of 32/64 bit pointers #ifdef GetWindowLongPtr static void *PointerFromWindow(HWND hWnd) { -- cgit v1.2.3