int CNotification::CalculateWidth(int defaultSize)
{
	CString s;
	GetWindowText(s);
	
	CDIB dib;
	dib.Resize(1, 1);
	if(!dib.Ready())
	{
		return defaultSize;
	}
	Graphics g(dib.dc);
	g.SetCompositingMode(CompositingModeSourceOver);
	g.SetSmoothingMode(SmoothingModeAntiAlias);

	RectF rf(0, 0, 0, 0);

	Font font(L"Arial", defaultSize * 0.6f, FontStyleRegular, UnitPixel);
	StringFormat *stringFormat = new StringFormat();
	stringFormat->SetAlignment(StringAlignmentCenter);
	stringFormat->SetLineAlignment(StringAlignmentCenter);
	stringFormat->SetFormatFlags(StringFormatFlagsLineLimit);
	stringFormat->SetTrimming(StringTrimmingEllipsisCharacter);

	g.MeasureString(s.GetBuffer(), s.GetLength(), &font, rf, stringFormat, &rf);

	delete stringFormat;

	defaultSize += (int)rf.Width - defaultSize / 2;
	return defaultSize;
}
void CSkinList::OnPaint()
{	
	CPaintDC dc(this);
	CDIB tmp;
	Draw(tmp);
	if(!tmp.Ready())
	{
		return;
	}
	BitBlt(dc.m_hDC, 0, 0, tmp.Width(), tmp.Height(), tmp.dc, 0, 0, SRCCOPY);
}
void CSkinList::Draw(CDIB &tmp)
{
	CRect r;
	GetClientRect(&r);

	tmp.Resize(r.Width(), r.Height());
	if(!tmp.Ready())
	{
		return;
	}

	RectF rf(0, 0, (REAL)tmp.Width(), (REAL)tmp.Height());
	RectF rx;

	Graphics g(tmp.dc);
	g.SetCompositingMode(CompositingModeSourceOver);

	if(bckg->Ready())
	{
		tmp.Draw(tmp.Rect(), 0, 0, bckg, DrawFlagsReflectDest);
	}

	if(dib->Ready())
	{
		g.DrawImage(dib->bmp, 0.0f, r.Height() * 0.36f);

		Font font(L"Arial", 9.0f);
		StringFormat *stringFormat = new StringFormat();
		stringFormat->SetAlignment(StringAlignmentCenter);
		stringFormat->SetLineAlignment(StringAlignmentCenter);
		stringFormat->SetTrimming(StringTrimmingEllipsisCharacter);

		CString s;
		s.Format(L"%s\n%s", skin->name.GetBuffer(), skin->description.GetBuffer());
		
		RectF rx(0, 0, (REAL)dib->Width(), r.Height() * 0.36f);

		rx.Y++;
		SolidBrush brush(0xfff0f0f0);
		g.DrawString(s.GetBuffer(), s.GetLength(), &font, rx, stringFormat, &brush);

		rx.Y--;
		brush.SetColor(0xff000000);
		g.DrawString(s.GetBuffer(), s.GetLength(), &font, rx, stringFormat, &brush);

		delete stringFormat;
	}
}
void CTabsControl::DrawItem(CTabControl *item, Gdiplus::Graphics &g)
{
	CRect rect = ItemRect(item);

	g.ResetTransform();
	g.TranslateTransform((REAL)rect.left, (REAL)rect.top);

	RectF rf(0.0f, 0.0f, (REAL)rect.Width(), (REAL)rect.Height());
	RectF rx;

	if(item->selected)
	{
		#define shadowb 10

		CDIB tmp;
		tmp.Resize(rect.Width() + shadowb * 2, rect.Height() + shadowb * 2);
		if(tmp.Ready())
		{
			Graphics gt(tmp.bmp);
			RectF rx(0, 0, (REAL)tmp.Width(), (REAL)tmp.Height());
			
			GraphicsPath *path = new GraphicsPath();
			path->AddLine(rx.X + shadowb, rx.Y + rx.Height - shadowb, rx.X + rx.Width - 2 - shadowb, rx.Y + rx.Height - shadowb);
			path->AddLine(rx.X + rx.Width - 2 - shadowb, rx.Y + rx.Height - shadowb, rx.X + rx.Width - 2, rx.Y);
			path->AddLine(rx.X + rx.Width - 2, rx.Y, rx.X + rx.Width, rx.Y + rx.Height);
			path->AddLine(rx.X + rx.Width, rx.Y + rx.Height, rx.X, rx.Y + rx.Height);
			path->AddLine(rx.X, rx.Y, rx.X + shadowb, rx.Y + rx.Height - shadowb);
			path->CloseFigure();

			SolidBrush brush(0xff000000);
			gt.FillPath(&brush, path);

			tmp.Blur(tmp.Rect(), CRect(0, 0, 0, 0), shadowb);

			g.DrawImage(tmp.bmp, rf, shadowb, shadowb, rf.Width, rf.Height, UnitPixel);

			delete path;
		}
	}

	Font font(L"Arial", item->selected ? 8.0f : 8.0f);
	StringFormat *stringFormat = new StringFormat();
	stringFormat->SetAlignment(StringAlignmentCenter);
	stringFormat->SetLineAlignment(StringAlignmentCenter);
	stringFormat->SetTrimming(StringTrimmingEllipsisCharacter);
	stringFormat->SetFormatFlags(StringFormatFlagsLineLimit);

	if(item->icon->Ready())
	{
		g.SetInterpolationMode(InterpolationModeBicubic);
		rx = rf;
		rx.Y += 6;
		rx.Height -= (20 + rx.Y);
		rx.Width = rx.Height;
		rx.X += (rf.Width - rx.Width) / 2;

		if(item->selected)
		{
			rx.Y++;

			#define shadow 5
			CDIB tmp;
			tmp.Resize(item->icon->Width(), item->icon->Height());
			if(tmp.Ready())
			{
				tmp.Draw(CRect(shadow, shadow, 
					item->icon->Width() - shadow, 
					item->icon->Height() - shadow), 
					item->icon->Rect(), item->icon);
				DIB_ARGB *p = tmp.scan0;
				int size = tmp.Width() * tmp.Height();
				for(int i = 0; i < size; i++, p++)
				{
					p->r = 0;
					p->g = 0;
					p->b = 0;
				}
				tmp.Blur(tmp.Rect(), CRect(0, 0, 0, 0), shadow);
				g.DrawImage(tmp.bmp, RectF(rx.X, rx.Y + shadow, rx.Width, rx.Height));
			}
			tmp.Assign(item->icon);
			/*if(tmp.Ready())
			{
				DIB_ARGB *p = tmp.scan0;
				int size = tmp.Width() * tmp.Height();
				for(int i = 0; i < size; i++, p++)
				{
					p->r = 0x6f;
					p->g = 0xa6;
					p->b = 0xde;
				} 
			}*/
			g.DrawImage(tmp.bmp, rx);
		}
		else
		{
			g.DrawImage(item->icon->bmp, rx);
		}
	}

	SolidBrush brush(0xff000000);
	rx = rf;
	rx.Height = 20;
	rx.Y = rf.Height - rx.Height;

	rx.Y++;
	g.DrawString(item->text.GetBuffer(), item->text.GetLength(), &font, rx, stringFormat, &brush);

	brush.SetColor(item->selected && false ? 0xff6fa6de : 0xfff0f0f0);
	rx.Y--;
	g.DrawString(item->text.GetBuffer(), item->text.GetLength(), &font, rx, stringFormat, &brush);

	delete stringFormat;

	//POSITION p = items.Find(item);
	//items.GetNext(p);
	//if(p)
	{
		RectF rx = rf;
		rx.X += rx.Width - 1;
		rx.Width = 1;
		LinearGradientBrush brush(rx, Color(140, 0x69, 0x69, 0x69), Color(0x69, 0x69, 0x69), LinearGradientModeVertical);
		g.FillRectangle(&brush, rx);
	}
}
bool Dock3D::DrawImage(CDIB *dst, CRect rect, int offsetX, CDIB *src)
{
	const int scale = 2;

	CDIB tmp;
	tmp.Resize(rect.Width() * scale, rect.Height() * scale);
	if (!tmp.Ready())
	{
		return false;
	}

	DrawDockD3Image(&tmp, tmp.Rect(), offsetX * scale, src);

	rect.left++;
	//rect.right--;

	dst->Draw(rect, tmp.Rect(), &tmp);

	/*int x, y, index, x1, x2;
	float y_ratio = (float)(src->Height() - 1) / rect.Height();
	float x_ratio, x_diff, y_diff;
	DIB_ARGB *pd, *psa, *psb, *psc, *psd;

	for(int i = 0; i < rect.Height(); i++)
	{
		x1 = (int)(rect.left + 1 + offsetX * (1 - (1.0f + i) / rect.Height()));
		x2 = (int)(rect.right - 1 - offsetX * (1 - (1.0f + i) / rect.Height()));

		x_ratio = (float)src->Width() / (x2 - x1);
		pd = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - i) * dst->Width() + x1) * 4);

		for(int j = 0; j < x2 - x1; j++, pd++)
		{
			x = (int)(x_ratio * j);
			y = (int)(y_ratio * i);
			x_diff = (x_ratio * j) - x;
			y_diff = (y_ratio * i) - y;
			index = y * src->Width() + x;
			psa = (DIB_ARGB*)((int)src->scan0 + (index) * 4);
			psb = (DIB_ARGB*)((int)src->scan0 + (index + 1) * 4);
			psc = (DIB_ARGB*)((int)src->scan0 + (index + src->Width()) * 4);
			psd = (DIB_ARGB*)((int)src->scan0 + (index + src->Width() + 1) * 4);

			pd->a = (unsigned char)(
				psa->a * (1 - x_diff) * (1 - y_diff) +
				psb->a * x_diff * (1 - y_diff) +
				psc->a * y_diff * (1 - x_diff) +
				psd->a * x_diff * y_diff);

			pd->b = (unsigned char)(
				psa->b * (1 - x_diff) * (1 - y_diff) +
				psb->b * x_diff * (1 - y_diff) +
				psc->b * y_diff * (1 - x_diff) +
				psd->b * x_diff * y_diff) * pd->a / 255;

			pd->g = (unsigned char)(
				psa->g * (1 - x_diff) * (1 - y_diff) +
				psb->g * x_diff * (1 - y_diff) +
				psc->g * y_diff * (1 - x_diff) +
				psd->g * x_diff * y_diff) * pd->a / 255;

			pd->r = (unsigned char)(
				psa->r * (1 - x_diff) * (1 - y_diff) +
				psb->r * x_diff * (1 - y_diff) +
				psc->r * y_diff * (1 - x_diff) +
				psd->r * x_diff * y_diff) * pd->a / 255;
		}
	}

	// Border's antialiasing
	DIB_ARGB *pd1, *pd2;
	int px2 = 0, py2 = 0, px1 = 0, py1 = 0;

	for(int i = 0; i <= rect.Height(); i++)
	{
		if(i == 0)
		{
			px1 = (int)(rect.left + 1 + offsetX * (1 - (1.0f + i) / rect.Height()));
			py1 = i;
			px2 = (int)(rect.right - 1 - offsetX * (1 - (1.0f + i) / rect.Height()));
			py2 = i;
		}
		else
		{
			x1 = (int)(rect.left + 1 + offsetX * (1 - (1.0f + i) / rect.Height()));
			if(x1 < px1)
			{
				pd1 = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py1) * dst->Width() + px1 + 1) * 4);
				pd2 = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py1 + 1) * dst->Width() + px1) * 4);
				pd = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py1) * dst->Width() + px1) * 4);

				for(int y = py1; y < i; y++, pd1 -= dst->Width(), pd2 -= dst->Width(), pd -= dst->Width())
				{
					pd->a = (unsigned char)((pd1->a + pd2->a) / 2 * (1 + y - py1) / (i - py1));
					pd->r = (pd1->r * 255 / max(pd1->a, 1) + pd2->r * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
					pd->g = (pd1->g * 255 / max(pd1->a, 1) + pd2->g * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
					pd->b = (pd1->b * 255 / max(pd1->a, 1) + pd2->b * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
				}
				px1 = x1;
				py1 = i;
			}

			x2 = (int)(rect.right - 1 - offsetX * (1 - (1.0f + i) / rect.Height()));
			if(x2 > px2)
			{
				pd1 = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py2) * dst->Width() + px2 - 1) * 4);
				pd2 = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py2 + 1) * dst->Width() + px2) * 4);
				pd = (DIB_ARGB*)((int)dst->scan0 + ((rect.bottom - 1 - py2) * dst->Width() + px2) * 4);

				for(int y = py2; y < i; y++, pd1 -= dst->Width(), pd2 -= dst->Width(), pd -= dst->Width())
				{
					pd->a = (unsigned char)((pd1->a + pd2->a) / 2 * (1 + y - py2) / (i - py2));
					pd->r = (pd1->r * 255 / max(pd1->a, 1) + pd2->r * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
					pd->g = (pd1->g * 255 / max(pd1->a, 1) + pd2->g * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
					pd->b = (pd1->b * 255 / max(pd1->a, 1) + pd2->b * 255 / max(pd2->a, 1)) / 2 * pd->a / 255;
				}
				px2 = x2;
				py2 = i;
			}
		}
	}*/

	return true;
}