Skip to content

Commit

Permalink
Add shadowed rounded rectangles to tab bar and path bar (6)
Browse files Browse the repository at this point in the history
  • Loading branch information
sdottaka committed Jun 23, 2024
1 parent 264e179 commit 21872b5
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 68 deletions.
212 changes: 146 additions & 66 deletions Src/Common/Bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap)
* @brief Duplicate a bitmap and make it dark
* @param pDC [in] Device context
* @param pBitmap [in] the bitmap to darken
* @param radius [in]
* @param lighten [in] make bitmap lighten if ligthen is true
* @return The bitmap object
*/
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, int radius, bool lighten)
{
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
Expand All @@ -73,7 +74,7 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biHeight = -bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = 0;
Expand All @@ -86,77 +87,156 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
auto pbuf = std::make_unique<BYTE[]>(bi.bmiHeader.biSizeImage);
GetDIBits(dcMem.m_hDC, (HBITMAP)*pBitmapDarkened, 0, bm.bmHeight, pbuf.get(), &bi, DIB_RGB_COLORS);

radius = std::clamp(radius, 0, static_cast<int>((std::min)(bm.bmWidth / 3, bm.bmHeight / 3)));

if (!lighten)
{
for (int x = 0; x < bm.bmWidth; x++)
{
double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
for (int y = 1; y < bm.bmHeight - 1; y++)
auto darkenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
{
for (int x = left; x < right; x++)
{
double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
for (int y = top; y < bottom; y++)
{
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
}
}
}

};
auto darkenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
{
auto sqr = [](double x) { return x * x; };
for (int x = left; x < right; x++)
{
const double b = 0.85 + (0.10 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0)));
for (int y = top; y < bottom; y++)
{
int i = x * 4 + y * bm.bmWidth * 4;
const double dist = std::sqrt(sqr(x - cx) + sqr(y - cy)) - static_cast<double>(radius);
if (dist < 0)
{
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
}
else if (dist <= 1.0)
{
pbuf[i] = (BYTE)(pbuf[i] * (0.95 + 0.05 * dist));
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * (0.9 + 0.1 * dist));
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * (0.9 + 0.1 * dist));
}
}
}
};
auto darkenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * b);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * b);
}
}
for (int x = 0; x < bm.bmWidth; x++)
{
int i = x * 4 + 0 * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
i = x * 4 + (bm.bmHeight - 1) * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
}
for (int y = 0; y < bm.bmHeight; y++)
{
int i = 0 * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
i = (bm.bmWidth - 1) * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
}
for (int x = left; x < right; x++)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.9);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.9);
}
};
auto darkenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
{
for (int y = top; y < bottom; y++)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)(pbuf[i] * 0.95);
pbuf[i + 1] = (BYTE)(pbuf[i + 1] * 0.85);
pbuf[i + 2] = (BYTE)(pbuf[i + 2] * 0.85);
}
};
darkenInner(radius, 1, bm.bmWidth - radius, radius);
darkenInner(radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1);
darkenInner(1, radius, bm.bmWidth - 1, bm.bmHeight - radius);
darkenCorner(0, 0, radius, radius, radius, radius, radius);
darkenCorner(bm.bmWidth - radius, 0, bm.bmWidth, radius, bm.bmWidth - radius - 1, radius, radius);
darkenCorner(0, bm.bmHeight - radius, radius, bm.bmHeight, radius, bm.bmHeight - radius - 1, radius);
darkenCorner(bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth, bm.bmHeight, bm.bmWidth - radius - 1, bm.bmHeight - radius - 1, radius);
darkenTopBottomEdge(0, radius, bm.bmWidth - radius);
darkenTopBottomEdge(bm.bmHeight - 1, radius, bm.bmWidth - radius);
darkenLeftRightEdge(0, radius, bm.bmHeight - radius);
darkenLeftRightEdge(bm.bmWidth - 1, radius, bm.bmHeight - radius);
}
else
{
for (int x = 0; x < bm.bmWidth; x++)
{
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
for (int y = 1; y < bm.bmHeight - 1; y++)
auto lightenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
{
for (int x = left; x < right; x++)
{
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
for (int y = top; y < bottom; y++)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
}
}
};
auto lightenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
{
auto sqr = [](double x) { return x * x; };
for (int x = left; x < right; x++)
{
int b = static_cast<int>(12.0 + (20.0 * sin(acos((double)x / bm.bmWidth*2.0 - 1.0))));
for (int y = top; y < bottom; y++)
{
int i = x * 4 + y * bm.bmWidth * 4;
const double dist = std::sqrt(sqr(x - cx) + sqr(y - cy)) - static_cast<double>(radius);
if (dist < 0)
{
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
}
else if (dist <= 1.0)
{
pbuf[i] = (BYTE)((std::min)(pbuf[i] + (BYTE)(40 * (1.0 - dist)), 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + (BYTE)(32 * (1.0 - dist)), 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + (BYTE)(32 * (1.0 - dist)), 255));
}
}
}
};
auto lightenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
{
for (int x = left; x < right; x++)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
}
};
auto lightenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + b, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + b, 255));
}
}
for (int x = 0; x < bm.bmWidth; x++)
{
int i = x * 4 + 0 * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
i = x * 4 + (bm.bmHeight - 1) * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
}
for (int y = 0; y < bm.bmHeight; y++)
{
int i = 0 * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
i = (bm.bmWidth - 1) * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
}
for (int y = top; y < bottom; y++)
{
int i = x * 4 + y * bm.bmWidth * 4;
pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40, 255));
pbuf[i + 1] = (BYTE)((std::min)(pbuf[i + 1] + 32, 255));
pbuf[i + 2] = (BYTE)((std::min)(pbuf[i + 2] + 32, 255));
}
};
lightenInner(radius, 1, bm.bmWidth - radius, radius);
lightenInner(radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1);
lightenInner(1, radius, bm.bmWidth - 1, bm.bmHeight - radius);
lightenCorner(0, 0, radius, radius, radius, radius, radius);
lightenCorner(bm.bmWidth - radius, 0, bm.bmWidth, radius, bm.bmWidth - radius - 1, radius, radius);
lightenCorner(0, bm.bmHeight - radius, radius, bm.bmHeight, radius, bm.bmHeight - radius - 1, radius);
lightenCorner(bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth, bm.bmHeight, bm.bmWidth - radius - 1, bm.bmHeight - radius - 1, radius);
lightenTopBottomEdge(0, radius, bm.bmWidth - radius);
lightenTopBottomEdge(bm.bmHeight - 1, radius, bm.bmWidth - radius);
lightenLeftRightEdge(0, radius, bm.bmHeight - radius);
lightenLeftRightEdge(bm.bmWidth - 1, radius, bm.bmHeight - radius);
}

SetDIBits(dcMem.m_hDC, (HBITMAP)*pBitmapDarkened, 0, bm.bmHeight, pbuf.get(), &bi, DIB_RGB_COLORS);
Expand Down
2 changes: 1 addition & 1 deletion Src/Common/Bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ namespace ATL { class CImage; }

CBitmap *CopyRectToBitmap(CDC *pDC, const CRect & rect);
void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap);
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten = false);
CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, int radius, bool lighten = false);
bool LoadImageFromResource(ATL::CImage& image, const tchar_t *pName, const tchar_t *pType);
5 changes: 4 additions & 1 deletion Src/LocationView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,9 @@ void CLocationView::DrawVisibleAreaRect(CDC *pClientDC, int nTopLine, int nBotto
nBottomLine = nTopLine + nScreenLines;
}

const int lpx = pClientDC->GetDeviceCaps(LOGPIXELSX);
auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); };

CRect rc;
GetClientRect(rc);
int nbLines = INT_MAX;
Expand Down Expand Up @@ -918,7 +921,7 @@ void CLocationView::DrawVisibleAreaRect(CDC *pClientDC, int nTopLine, int nBotto

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

Expand Down

0 comments on commit 21872b5

Please sign in to comment.