Skip to content

Commit 21872b5

Browse files
committed
Add shadowed rounded rectangles to tab bar and path bar (6)
1 parent 264e179 commit 21872b5

File tree

3 files changed

+151
-68
lines changed

3 files changed

+151
-68
lines changed

Src/Common/Bitmap.cpp

Lines changed: 146 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap)
5656
* @brief Duplicate a bitmap and make it dark
5757
* @param pDC [in] Device context
5858
* @param pBitmap [in] the bitmap to darken
59+
* @param radius [in]
5960
* @param lighten [in] make bitmap lighten if ligthen is true
6061
* @return The bitmap object
6162
*/
62-
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
63+
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, int radius, bool lighten)
6364
{
6465
CDC dcMem;
6566
dcMem.CreateCompatibleDC(pDC);
@@ -73,7 +74,7 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
7374
BITMAPINFO bi;
7475
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
7576
bi.bmiHeader.biWidth = bm.bmWidth;
76-
bi.bmiHeader.biHeight = bm.bmHeight;
77+
bi.bmiHeader.biHeight = -bm.bmHeight;
7778
bi.bmiHeader.biPlanes = 1;
7879
bi.bmiHeader.biBitCount = 32;
7980
bi.bmiHeader.biCompression = 0;
@@ -86,77 +87,156 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
8687
auto pbuf = std::make_unique<BYTE[]>(bi.bmiHeader.biSizeImage);
8788
GetDIBits(dcMem.m_hDC, (HBITMAP)*pBitmapDarkened, 0, bm.bmHeight, pbuf.get(), &bi, DIB_RGB_COLORS);
8889

90+
radius = std::clamp(radius, 0, static_cast<int>((std::min)(bm.bmWidth / 3, bm.bmHeight / 3)));
91+
8992
if (!lighten)
9093
{
91-
for (int x = 0; x < bm.bmWidth; x++)
92-
{
93-
double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
94-
for (int y = 1; y < bm.bmHeight - 1; y++)
94+
auto darkenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
95+
{
96+
for (int x = left; x < right; x++)
97+
{
98+
double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
99+
for (int y = top; y < bottom; y++)
100+
{
101+
{
102+
int i = x * 4 + y * bm.bmWidth * 4;
103+
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
104+
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
105+
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
106+
}
107+
}
108+
}
109+
110+
};
111+
auto darkenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
112+
{
113+
auto sqr = [](double x) { return x * x; };
114+
for (int x = left; x < right; x++)
115+
{
116+
const double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
117+
for (int y = top; y < bottom; y++)
118+
{
119+
int i = x * 4 + y * bm.bmWidth * 4;
120+
const double dist = std::sqrt(sqr(x - cx) + sqr(y - cy)) - static_cast<double>(radius);
121+
if (dist < 0)
122+
{
123+
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
124+
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
125+
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
126+
}
127+
else if (dist <= 1.0)
128+
{
129+
pbuf[i] = (BYTE)(pbuf[i] * (0.95 + 0.05 * dist));
130+
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * (0.9 + 0.1 * dist));
131+
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * (0.9 + 0.1 * dist));
132+
}
133+
}
134+
}
135+
};
136+
auto darkenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
95137
{
96-
int i = x * 4 + y * bm.bmWidth * 4;
97-
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
98-
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
99-
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
100-
}
101-
}
102-
for (int x = 0; x < bm.bmWidth; x++)
103-
{
104-
int i = x * 4 + 0 * bm.bmWidth * 4;
105-
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
106-
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
107-
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
108-
i = x * 4 + (bm.bmHeight - 1) * bm.bmWidth * 4;
109-
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
110-
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
111-
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
112-
}
113-
for (int y = 0; y < bm.bmHeight; y++)
114-
{
115-
int i = 0 * 4 + y * bm.bmWidth * 4;
116-
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
117-
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
118-
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
119-
i = (bm.bmWidth - 1) * 4 + y * bm.bmWidth * 4;
120-
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
121-
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
122-
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
123-
}
138+
for (int x = left; x < right; x++)
139+
{
140+
int i = x * 4 + y * bm.bmWidth * 4;
141+
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
142+
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
143+
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
144+
}
145+
};
146+
auto darkenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
147+
{
148+
for (int y = top; y < bottom; y++)
149+
{
150+
int i = x * 4 + y * bm.bmWidth * 4;
151+
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
152+
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.85);
153+
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.85);
154+
}
155+
};
156+
darkenInner(radius, 1, bm.bmWidth - radius, radius);
157+
darkenInner(radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1);
158+
darkenInner(1, radius, bm.bmWidth - 1, bm.bmHeight - radius);
159+
darkenCorner(0, 0, radius, radius, radius, radius, radius);
160+
darkenCorner(bm.bmWidth - radius, 0, bm.bmWidth, radius, bm.bmWidth - radius - 1, radius, radius);
161+
darkenCorner(0, bm.bmHeight - radius, radius, bm.bmHeight, radius, bm.bmHeight - radius - 1, radius);
162+
darkenCorner(bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth, bm.bmHeight, bm.bmWidth - radius - 1, bm.bmHeight - radius - 1, radius);
163+
darkenTopBottomEdge(0, radius, bm.bmWidth - radius);
164+
darkenTopBottomEdge(bm.bmHeight - 1, radius, bm.bmWidth - radius);
165+
darkenLeftRightEdge(0, radius, bm.bmHeight - radius);
166+
darkenLeftRightEdge(bm.bmWidth - 1, radius, bm.bmHeight - radius);
124167
}
125168
else
126169
{
127-
for (int x = 0; x < bm.bmWidth; x++)
128-
{
129-
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
130-
for (int y = 1; y < bm.bmHeight - 1; y++)
170+
auto lightenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
171+
{
172+
for (int x = left; x < right; x++)
173+
{
174+
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
175+
for (int y = top; y < bottom; y++)
176+
{
177+
int i = x * 4 + y * bm.bmWidth * 4;
178+
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
179+
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
180+
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
181+
}
182+
}
183+
};
184+
auto lightenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
185+
{
186+
auto sqr = [](double x) { return x * x; };
187+
for (int x = left; x < right; x++)
188+
{
189+
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
190+
for (int y = top; y < bottom; y++)
191+
{
192+
int i = x * 4 + y * bm.bmWidth * 4;
193+
const double dist = std::sqrt(sqr(x - cx) + sqr(y - cy)) - static_cast<double>(radius);
194+
if (dist < 0)
195+
{
196+
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
197+
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
198+
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
199+
}
200+
else if (dist <= 1.0)
201+
{
202+
pbuf[i] = (BYTE)((std::min)(pbuf[i] + (BYTE)(40 * (1.0 - dist)), 255));
203+
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + (BYTE)(32 * (1.0 - dist)), 255));
204+
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + (BYTE)(32 * (1.0 - dist)), 255));
205+
}
206+
}
207+
}
208+
};
209+
auto lightenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
210+
{
211+
for (int x = left; x < right; x++)
212+
{
213+
int i = x * 4 + y * bm.bmWidth * 4;
214+
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
215+
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
216+
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
217+
}
218+
};
219+
auto lightenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
131220
{
132-
int i = x * 4 + y * bm.bmWidth * 4;
133-
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
134-
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
135-
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
136-
}
137-
}
138-
for (int x = 0; x < bm.bmWidth; x++)
139-
{
140-
int i = x * 4 + 0 * bm.bmWidth * 4;
141-
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
142-
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
143-
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
144-
i = x * 4 + (bm.bmHeight - 1) * bm.bmWidth * 4;
145-
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
146-
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
147-
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
148-
}
149-
for (int y = 0; y < bm.bmHeight; y++)
150-
{
151-
int i = 0 * 4 + y * bm.bmWidth * 4;
152-
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
153-
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
154-
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
155-
i = (bm.bmWidth - 1) * 4 + y * bm.bmWidth * 4;
156-
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
157-
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
158-
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
159-
}
221+
for (int y = top; y < bottom; y++)
222+
{
223+
int i = x * 4 + y * bm.bmWidth * 4;
224+
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
225+
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
226+
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
227+
}
228+
};
229+
lightenInner(radius, 1, bm.bmWidth - radius, radius);
230+
lightenInner(radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1);
231+
lightenInner(1, radius, bm.bmWidth - 1, bm.bmHeight - radius);
232+
lightenCorner(0, 0, radius, radius, radius, radius, radius);
233+
lightenCorner(bm.bmWidth - radius, 0, bm.bmWidth, radius, bm.bmWidth - radius - 1, radius, radius);
234+
lightenCorner(0, bm.bmHeight - radius, radius, bm.bmHeight, radius, bm.bmHeight - radius - 1, radius);
235+
lightenCorner(bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth, bm.bmHeight, bm.bmWidth - radius - 1, bm.bmHeight - radius - 1, radius);
236+
lightenTopBottomEdge(0, radius, bm.bmWidth - radius);
237+
lightenTopBottomEdge(bm.bmHeight - 1, radius, bm.bmWidth - radius);
238+
lightenLeftRightEdge(0, radius, bm.bmHeight - radius);
239+
lightenLeftRightEdge(bm.bmWidth - 1, radius, bm.bmHeight - radius);
160240
}
161241

162242
SetDIBits(dcMem.m_hDC, (HBITMAP)*pBitmapDarkened, 0, bm.bmHeight, pbuf.get(), &bi, DIB_RGB_COLORS);

Src/Common/Bitmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ namespace ATL { class CImage; }
1515

1616
CBitmap *CopyRectToBitmap(CDC *pDC, const CRect & rect);
1717
void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap);
18-
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten = false);
18+
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, int radius, bool lighten = false);
1919
bool LoadImageFromResource(ATL::CImage& image, const tchar_t *pName, const tchar_t *pType);

Src/LocationView.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,9 @@ void CLocationView::DrawVisibleAreaRect(CDC *pClientDC, int nTopLine, int nBotto
879879
nBottomLine = nTopLine + nScreenLines;
880880
}
881881

882+
const int lpx = pClientDC->GetDeviceCaps(LOGPIXELSX);
883+
auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); };
884+
882885
CRect rc;
883886
GetClientRect(rc);
884887
int nbLines = INT_MAX;
@@ -918,7 +921,7 @@ void CLocationView::DrawVisibleAreaRect(CDC *pClientDC, int nTopLine, int nBotto
918921

919922
CRect rcVisibleArea(2, m_visibleTop, rc.right - 2, m_visibleBottom);
920923
std::unique_ptr<CBitmap> pBitmap(CopyRectToBitmap(pClientDC, rcVisibleArea));
921-
std::unique_ptr<CBitmap> pDarkenedBitmap(GetDarkenedBitmap(pClientDC, pBitmap.get(), IsColorDark(GetBackgroundColor())));
924+
std::unique_ptr<CBitmap> pDarkenedBitmap(GetDarkenedBitmap(pClientDC, pBitmap.get(), pointToPixel(3), IsColorDark(GetBackgroundColor())));
922925
DrawBitmap(pClientDC, rcVisibleArea.left, rcVisibleArea.top, pDarkenedBitmap.get());
923926
}
924927

0 commit comments

Comments
 (0)