/*
** Draws the meter on the double buffer
**
*/
bool MeterRoundLine::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

	// Calculate the center of for the line
	int x = GetX();
	int y = GetY();
	double cx = x + m_W / 2.0;
	double cy = y + m_H / 2.0;

	double lineStart = ((m_CntrlLineStart) ? m_LineStartShift * m_Value : 0) + m_LineStart;
	double lineLength = ((m_CntrlLineLength) ? m_LineLengthShift * m_Value : 0) + m_LineLength;

	// Calculate the end point of the line
	double angle = ((m_CntrlAngle) ? m_RotationAngle * m_Value : m_RotationAngle) + m_StartAngle;
	double e_cos = cos(angle);
	double e_sin = sin(angle);

	REAL sx = (REAL)(e_cos * lineStart + cx);
	REAL sy = (REAL)(e_sin * lineStart + cy);
	REAL ex = (REAL)(e_cos * lineLength + cx);
	REAL ey = (REAL)(e_sin * lineLength + cy);

	if (m_Solid)
	{
		REAL startAngle = (REAL)(fmod(CONVERT_TO_DEGREES(m_StartAngle), 360.0));
		REAL sweepAngle = (REAL)(CONVERT_TO_DEGREES(m_RotationAngle * m_Value));

		// Calculate the start point of the line
		double s_cos = cos(m_StartAngle);
		double s_sin = sin(m_StartAngle);

		//Create a path to surround the arc
		GraphicsPath path;
		path.AddArc((REAL)(cx - lineStart), (REAL)(cy - lineStart), (REAL)(lineStart * 2.0), (REAL)(lineStart * 2.0), startAngle, sweepAngle);
		path.AddLine((REAL)(lineStart * s_cos + cx), (REAL)(lineStart * s_sin + cy), (REAL)(lineLength * s_cos + cx), (REAL)(lineLength * s_sin + cy));
		path.AddArc((REAL)(cx - lineLength), (REAL)(cy - lineLength), (REAL)(lineLength * 2.0), (REAL)(lineLength * 2.0), startAngle, sweepAngle);
		path.AddLine(ex, ey, sx, sy);

		SolidBrush solidBrush(m_LineColor);
		graphics.FillPath(&solidBrush, &path);
	}
	else
	{
		Pen pen(m_LineColor, (REAL)m_LineWidth);
		graphics.DrawLine(&pen, sx, sy, ex, ey);
	}

	canvas.EndGdiplusContext();

	return true;
}
Exemple #2
0
/*
** Draws a bevel inside the given area
*/
void Meter::DrawBevel(Gfx::Canvas& canvas, const D2D1_RECT_F& rect, const D2D1_COLOR_F& light, const D2D1_COLOR_F& dark)
{
	const FLOAT l = rect.left;
	const FLOAT r = rect.right - 1.0f;
	const FLOAT t = rect.top;
	const FLOAT b = rect.bottom - 1.0f;

	canvas.DrawLine(light, l,        t,        l,        b,        2.0f);
	canvas.DrawLine(light, l,        t,        r,        t,        2.0f);
	canvas.DrawLine(light, l + 1.0f, t + 1.0f, l + 1.0f, b - 1.0f, 2.0f);
	canvas.DrawLine(light, l + 1.0f, t + 1.0f, r - 1.0f, t + 1.0f, 2.0f);
	canvas.DrawLine(dark,  l,        b,        r,        b,        2.0f);
	canvas.DrawLine(dark,  r,        t,        r,        b,        2.0f);
	canvas.DrawLine(dark,  l + 1.0f, b - 1.0f, r - 1.0f, b - 1.0f, 2.0f);
	canvas.DrawLine(dark,  r - 1.0f, t + 1.0f, r - 1.0f, b - 1.0f, 2.0f);
}
/*
** Draws the meter on the double buffer
**
*/
bool MeterButton::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	if (m_Bitmaps[m_State] == nullptr) return false;	// Unable to continue

	Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

	Gdiplus::Rect meterRect = GetMeterRectPadding();

	// Blit the image
	graphics.DrawCachedBitmap(m_Bitmaps[m_State], meterRect.X, meterRect.Y);

	canvas.EndGdiplusContext();

	return true;
}
Exemple #4
0
/*
** Draws the solid background & bevel if such are defined
*/
bool Meter::Draw(Gfx::Canvas& canvas)
{
	if (IsHidden()) return false;

	canvas.SetAntiAliasing(m_AntiAlias);

	if (m_SolidColor.a != 0.0f || m_SolidColor2.a != 0.0f)
	{
		const FLOAT x = (FLOAT)GetX();
		const FLOAT y = (FLOAT)GetY();

		const D2D1_RECT_F r = D2D1::RectF(x, y, x + (FLOAT)m_W, y + (FLOAT)m_H);

		if (m_SolidColor.r == m_SolidColor2.r && m_SolidColor.g == m_SolidColor2.g && 
			m_SolidColor.b == m_SolidColor2.b && m_SolidColor.a == m_SolidColor2.a)
		{
			canvas.FillRectangle(r, m_SolidColor);
		}
		else
		{
			canvas.FillGradientRectangle(r, m_SolidColor, m_SolidColor2, (FLOAT)m_SolidAngle);
		}
	}

	if (m_SolidBevel != BEVELTYPE_NONE)
	{
		D2D1_COLOR_F lightColor = D2D1::ColorF(D2D1::ColorF::White);
		D2D1_COLOR_F darkColor = D2D1::ColorF(D2D1::ColorF::Black);
		
		if (m_SolidBevel == BEVELTYPE_DOWN)
		{
			lightColor = D2D1::ColorF(D2D1::ColorF::Black);
			darkColor = D2D1::ColorF(D2D1::ColorF::White);
		}

		// The bevel is drawn outside the meter
		const FLOAT x = (FLOAT)GetX();
		const FLOAT y = (FLOAT)GetY();
		const D2D1_RECT_F rect = D2D1::RectF(x - 2.0f, y - 2.0f, x + (FLOAT)m_W + 2.0f, y + (FLOAT)m_H + 2.0f);
		DrawBevel(canvas, rect, lightColor, darkColor);
	}

	return true;
}
Exemple #5
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterButton::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	const auto image = m_Image.GetImage();
	D2D1_RECT_F meterRect = GetMeterRectPadding();

	if (image)
	{
		canvas.DrawBitmap(
			image,
			D2D1::RectF(
				meterRect.left,
				meterRect.top,
				meterRect.left + (FLOAT)m_W,
				meterRect.top + (FLOAT)m_H),
			m_BitmapsRects[m_State]);
	}

	return true;
}
/*
** Draws the string or calculates it's size
**
*/
bool MeterString::DrawString(Gfx::Canvas& canvas, RectF* rect)
{
	if (!m_TextFormat->IsInitialized()) return false;

	LPCWSTR string = m_String.c_str();
	UINT stringLen = (UINT)m_String.length();

	canvas.SetTextAntiAliasing(m_AntiAlias);

	m_TextFormat->SetTrimming(
		m_ClipType == CLIP_ON ||
		(m_ClipType == CLIP_AUTO && (m_NeedsClipping || (m_WDefined && m_HDefined))));

	Gdiplus::Rect meterRect = GetMeterRectPadding();

	if (rect)
	{
		rect->X = (REAL)meterRect.X;
		rect->Y = (REAL)meterRect.Y;
		if (canvas.MeasureTextW(string, stringLen, *m_TextFormat, *rect) &&
			m_ClipType == CLIP_AUTO)
		{
			// Set initial clipping
			m_NeedsClipping = false;

			REAL w, h;
			bool updateSize = true;

			if (m_WDefined)
			{
				w = (REAL)meterRect.Width;
				h = rect->Height;
				m_NeedsClipping = true;
			}
			else if (m_HDefined)
			{
				if (m_ClipStringW == -1)
				{
					// Text does not fit in defined height, clip it
					if (rect->Height > (REAL)meterRect.Height)
					{
						m_NeedsClipping = true;
					}

					rect->Height = (REAL)meterRect.Height;
					updateSize = false;

				}
				else
				{
					if (rect->Width > (REAL)m_ClipStringW)
					{
						w = (REAL)m_ClipStringW;
						m_NeedsClipping = true;
					}
					else
					{
						w = rect->Width;
					}

					h = (REAL)meterRect.Height;
				}
			}
			else
			{
				if (m_ClipStringW == -1)
				{
					// Clip text if already larger than ClipStringH
					if (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH)
					{
						m_NeedsClipping = true;
						rect->Height = (REAL)m_ClipStringH;
					}

					updateSize = false;
				}
				else
				{
					if (rect->Width > (REAL)m_ClipStringW)
					{
						w = (REAL)m_ClipStringW;
						m_NeedsClipping = true;
					}
					else
					{
						w = rect->Width;
					}

					h = rect->Height;
				}
			}

			if (updateSize)
			{
				UINT lines = 0;
				RectF layout((REAL)meterRect.X, (REAL)meterRect.Y, w, h);
				if (canvas.MeasureTextLinesW(string, stringLen, *m_TextFormat, layout, lines) &&
					lines != 0)
				{
					rect->Width = w;
					rect->Height = layout.Height;

					if (m_HDefined || (m_ClipStringH != -1 && rect->Height > (REAL)m_ClipStringH))
					{
						rect->Height = m_HDefined ? (REAL)meterRect.Height : (REAL)m_ClipStringH;
					}
				}
			}
		}
	}
	else
	{
		RectF rcDest((REAL)meterRect.X, (REAL)meterRect.Y, (REAL)meterRect.Width, (REAL)meterRect.Height);
		m_Rect = rcDest;

		if (m_Angle != 0.0f)
		{
			const float baseX = (float)Meter::GetX();
			canvas.RotateTransform(CONVERT_TO_DEGREES(m_Angle), baseX, (REAL)meterRect.Y, -baseX, -(REAL)meterRect.Y);
		}

		if (m_Effect != EFFECT_NONE)
		{
			SolidBrush solidBrush(m_EffectColor);
			RectF rcEffect(rcDest);

			if (m_Effect == EFFECT_SHADOW)
			{
				rcEffect.Offset(1, 1);
				canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush);
			}
			else  //if (m_Effect == EFFECT_BORDER)
			{
				rcEffect.Offset(0, 1);
				canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush);
				rcEffect.Offset(1, -1);
				canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush);
				rcEffect.Offset(-1, -1);
				canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush);
				rcEffect.Offset(-1, 1);
				canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcEffect, solidBrush);
			}
		}

		SolidBrush solidBrush(m_Color);
		canvas.DrawTextW(string, (UINT)stringLen, *m_TextFormat, rcDest, solidBrush);

		if (m_Angle != 0.0f)
		{
			canvas.ResetTransform();
		}
	}

	return true;
}
Exemple #7
0
/*
** Draws the solid background & bevel if such are defined
*/
bool Meter::Draw(Gfx::Canvas& canvas)
{
    if (IsHidden()) return false;

    canvas.SetAntiAliasing(m_AntiAlias);

    if (m_SolidColor.GetA() != 0 || m_SolidColor2.GetA() != 0)
    {
        int x = GetX();
        int y = GetY();

        Rect r(x, y, m_W, m_H);

        if (m_SolidColor.GetValue() == m_SolidColor2.GetValue())
        {
            SolidBrush solid(m_SolidColor);
            canvas.FillRectangle(r, solid);
        }
        else
        {
            Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

            if (!m_AntiAlias)
            {
                // Fix the tiling issue in some GradientAngle values
                graphics.SetPixelOffsetMode(PixelOffsetModeHalf);
            }

            LinearGradientBrush gradient(r, m_SolidColor, m_SolidColor2, m_SolidAngle, TRUE);
            graphics.FillRectangle(&gradient, r);

            if (!m_AntiAlias)
            {
                graphics.SetPixelOffsetMode(PixelOffsetModeDefault);
            }

            canvas.EndGdiplusContext();
        }
    }

    if (m_SolidBevel != BEVELTYPE_NONE)
    {
        Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

        int x = GetX();
        int y = GetY();

        Color lightColor(255, 255, 255, 255);
        Color darkColor(255, 0, 0, 0);

        if (m_SolidBevel == BEVELTYPE_DOWN)
        {
            lightColor.SetValue(Color::MakeARGB(255, 0, 0, 0));
            darkColor.SetValue(Color::MakeARGB(255, 255, 255, 255));
        }

        Pen light(lightColor);
        Pen dark(darkColor);

        // The bevel is drawn outside the meter
        Rect rect(x - 2, y - 2, m_W + 4, m_H + 4);
        DrawBevel(graphics, rect, light, dark);

        canvas.EndGdiplusContext();
    }

    return true;
}
Exemple #8
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterImage::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	if (m_Image.IsLoaded())
	{
		// Copy the image over the doublebuffer
		Bitmap* drawBitmap = m_Image.GetImage();

		int imageW = drawBitmap->GetWidth();
		int imageH = drawBitmap->GetHeight();

		if (imageW == 0 || imageH == 0 || m_W == 0 || m_H == 0) return true;

		int x = GetX();
		int y = GetY();

		int drawW = m_W;
		int drawH = m_H;

		if (drawW == imageW && drawH == imageH &&
			m_ScaleMargins.left == 0 && m_ScaleMargins.top == 0 && m_ScaleMargins.right == 0 && m_ScaleMargins.bottom == 0)
		{
			canvas.DrawBitmap(drawBitmap, Rect(x, y, drawW, drawH), Rect(0, 0, imageW, imageH));
		}
		else if (m_DrawMode == DRAWMODE_TILE)
		{
			Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

			ImageAttributes imgAttr;
			imgAttr.SetWrapMode(WrapModeTile);

			Rect r(x, y, drawW, drawH);
			graphics.DrawImage(drawBitmap, r, 0, 0, drawW, drawH, UnitPixel, &imgAttr);

			canvas.EndGdiplusContext();
		}
		else if (m_DrawMode == DRAWMODE_KEEPRATIO || m_DrawMode == DRAWMODE_KEEPRATIOANDCROP)
		{
			int cropX = 0;
			int cropY = 0;
			int cropW = imageW;
			int cropH = imageH;

			if (m_WDefined && m_HDefined)
			{
				REAL imageRatio = imageW / (REAL)imageH;
				REAL meterRatio = m_W / (REAL)m_H;

				if (imageRatio != meterRatio)
				{
					if (m_DrawMode == DRAWMODE_KEEPRATIO)
					{
						if (imageRatio > meterRatio)
						{
							drawH = m_W * imageH / imageW;
							y += (m_H - drawH) / 2;
						}
						else
						{
							drawW = m_H * imageW / imageH;
							x += (m_W - drawW) / 2;
						}
					}
					else
					{
						if (imageRatio > meterRatio)
						{
							cropW = (int)(imageH * meterRatio);
							cropX = (imageW - cropW) / 2;
						}
						else
						{
							cropH = (int)(imageW / meterRatio);
							cropY = (imageH - cropH) / 2;
						}
					}
				}
			}

			Rect r(x, y, drawW, drawH);
			canvas.DrawBitmap(drawBitmap, r, Rect(cropX, cropY, cropW, cropH));
		}
		else
		{
			const RECT& m = m_ScaleMargins;

			if (m.top > 0)
			{
				if (m.left > 0)
				{
					// Top-Left
					Rect r(x, y, m.left, m.top);
					canvas.DrawBitmap(drawBitmap, r, Rect(0, 0, m.left, m.top));
				}

				// Top
				Rect r(x + m.left, y, drawW - m.left - m.right, m.top);
				canvas.DrawBitmap(drawBitmap, r, Rect(m.left, 0, imageW - m.left - m.right, m.top));

				if (m.right > 0)
				{
					// Top-Right
					Rect r(x + drawW - m.right, y, m.right, m.top);
					canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, 0, m.right, m.top));
				}
			}

			if (m.left > 0)
			{
				// Left
				Rect r(x, y + m.top, m.left, drawH - m.top - m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(0, m.top, m.left, imageH - m.top - m.bottom));
			}

			// Center
			Rect r(x + m.left, y + m.top, drawW - m.left - m.right, drawH - m.top - m.bottom);
			canvas.DrawBitmap(drawBitmap, r, Rect(m.left, m.top, imageW - m.left - m.right, imageH - m.top - m.bottom));

			if (m.right > 0)
			{
				// Right
				Rect r(x + drawW - m.right, y + m.top, m.right, drawH - m.top - m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, m.top, m.right, imageH - m.top - m.bottom));
			}

			if (m.bottom > 0)
			{
				if (m.left > 0)
				{
					// Bottom-Left
					Rect r(x, y + drawH - m.bottom, m.left, m.bottom);
					canvas.DrawBitmap(drawBitmap, r, Rect(0, imageH - m.bottom, m.left, m.bottom));
				}

				// Bottom
				Rect r(x + m.left, y + drawH - m.bottom, drawW - m.left - m.right, m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(m.left, imageH - m.bottom, imageW - m.left - m.right, m.bottom));

				if (m.right > 0)
				{
					// Bottom-Right
					Rect r(x + drawW - m.right, y + drawH - m.bottom, m.right, m.bottom);
					canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, imageH - m.bottom, m.right, m.bottom));
				}
			}
		}
	}

	return true;
}
/*
** Draws the meter on the double buffer
**
*/
bool MeterHistogram::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas) ||
		(m_Measures.size() >= 1 && !m_PrimaryValues) ||
		(m_Measures.size() >= 2 && !m_SecondaryValues)) return false;

	Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

	Measure* secondaryMeasure = (m_Measures.size() >= 2) ? m_Measures[1] : nullptr;

	GraphicsPath primaryPath;
	GraphicsPath secondaryPath;
	GraphicsPath bothPath;

	Bitmap* primaryBitmap = m_PrimaryImage.GetImage();
	Bitmap* secondaryBitmap = m_SecondaryImage.GetImage();
	Bitmap* bothBitmap = m_OverlapImage.GetImage();

	Gdiplus::Rect meterRect = GetMeterRectPadding();

	// Default values (GraphStart=Right, GraphOrientation=Vertical)
	int i;
	int startValue = 0;
	int* endValueLHS = &i;
	int* endValueRHS = &meterRect.Width;
	int step = 1;
	int endValue = -1; //(should be 0, but need to simulate <=)

	// GraphStart=Left, GraphOrientation=Vertical
	if (!m_GraphHorizontalOrientation)
	{
		if (m_GraphStartLeft)
		{
			startValue = meterRect.Width - 1;
			endValueLHS = &endValue;
			endValueRHS = &i;
			step = -1;
		}
	}
	else
	{
		if (!m_Flip)
		{
			endValueRHS = &meterRect.Height;
		}
		else
		{
			startValue = meterRect.Height - 1;
			endValueLHS = &endValue;
			endValueRHS = &i;
			step = -1;
		}
	}

	// Horizontal or Vertical graph
	if (m_GraphHorizontalOrientation)
	{
		for (i = startValue; *endValueLHS < *endValueRHS; i += step)
		{
			double value = (m_MaxPrimaryValue == 0.0) ?
				  0.0
				: m_PrimaryValues[(i + (m_MeterPos % meterRect.Height)) % meterRect.Height] / m_MaxPrimaryValue;
			value -= m_MinPrimaryValue;
			int primaryBarHeight = (int)(meterRect.Width * value);
			primaryBarHeight = min(meterRect.Width, primaryBarHeight);
			primaryBarHeight = max(0, primaryBarHeight);

			if (secondaryMeasure)
			{
				value = (m_MaxSecondaryValue == 0.0) ?
					  0.0
					: m_SecondaryValues[(i + m_MeterPos) % meterRect.Height] / m_MaxSecondaryValue;
				value -= m_MinSecondaryValue;
				int secondaryBarHeight = (int)(meterRect.Width * value);
				secondaryBarHeight = min(meterRect.Width, secondaryBarHeight);
				secondaryBarHeight = max(0, secondaryBarHeight);

				// Check which measured value is higher
				int bothBarHeight = min(primaryBarHeight, secondaryBarHeight);

				// Cache image/color rectangle for the both lines
				{
					Rect& r = m_GraphStartLeft ?
						  Rect(meterRect.X, meterRect.Y + startValue + (step * i), bothBarHeight, 1)
						: Rect(meterRect.X + meterRect.Width - bothBarHeight, meterRect.Y + startValue + (step * i), bothBarHeight, 1);

					bothPath.AddRectangle(r);  // cache
				}

				// Cache the image/color rectangle for the rest
				if (secondaryBarHeight > primaryBarHeight)
				{
					Rect& r = m_GraphStartLeft ?
						  Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1)
						: Rect(meterRect.X + meterRect.Width - secondaryBarHeight, meterRect.Y + startValue + (step * i), secondaryBarHeight - bothBarHeight, 1);

					secondaryPath.AddRectangle(r);  // cache
				}
				else
				{
					Rect& r = m_GraphStartLeft ?
						  Rect(meterRect.X + bothBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1)
						: Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight - bothBarHeight, 1);

					primaryPath.AddRectangle(r);  // cache
				}
			}
			else
			{
				Rect& r = m_GraphStartLeft ?
					  Rect(meterRect.X, meterRect.Y + startValue + (step * i), primaryBarHeight, 1)
					: Rect(meterRect.X + meterRect.Width - primaryBarHeight, meterRect.Y + startValue + (step * i), primaryBarHeight, 1);

				primaryPath.AddRectangle(r);  // cache
			}
		}
	}
	else	// GraphOrientation=Vertical
	{
		for (i = startValue; *endValueLHS < *endValueRHS; i += step)
		{
			double value = (m_MaxPrimaryValue == 0.0) ?
				  0.0
				: m_PrimaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxPrimaryValue;
			value -= m_MinPrimaryValue;
			int primaryBarHeight = (int)(meterRect.Height * value);
			primaryBarHeight = min(meterRect.Height, primaryBarHeight);
			primaryBarHeight = max(0, primaryBarHeight);

			if (secondaryMeasure)
			{
				value = (m_MaxSecondaryValue == 0.0) ?
					  0.0
					: m_SecondaryValues[(i + m_MeterPos) % meterRect.Width] / m_MaxSecondaryValue;
				value -= m_MinSecondaryValue;
				int secondaryBarHeight = (int)(meterRect.Height * value);
				secondaryBarHeight = min(meterRect.Height, secondaryBarHeight);
				secondaryBarHeight = max(0, secondaryBarHeight);

				// Check which measured value is higher
				int bothBarHeight = min(primaryBarHeight, secondaryBarHeight);

				// Cache image/color rectangle for the both lines
				{
					Rect& r = m_Flip ?
						  Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, bothBarHeight)
						: Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - bothBarHeight, 1, bothBarHeight);

					bothPath.AddRectangle(r);  // cache
				}

				// Cache the image/color rectangle for the rest
				if (secondaryBarHeight > primaryBarHeight)
				{
					Rect& r = m_Flip ?
						  Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, secondaryBarHeight - bothBarHeight)
						: Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - secondaryBarHeight, 1, secondaryBarHeight - bothBarHeight);

					secondaryPath.AddRectangle(r);  // cache
				}
				else
				{
					Rect& r = m_Flip ?
						  Rect(meterRect.X + startValue + (step * i), meterRect.Y + bothBarHeight, 1, primaryBarHeight - bothBarHeight)
						: Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight - bothBarHeight);

					primaryPath.AddRectangle(r);  // cache
				}
			}
			else
			{
				Rect& r = m_Flip ?
					  Rect(meterRect.X + startValue + (step * i), meterRect.Y, 1, primaryBarHeight)
					: Rect(meterRect.X + startValue + (step * i), meterRect.Y + meterRect.Height - primaryBarHeight, 1, primaryBarHeight);

				primaryPath.AddRectangle(r);  // cache
			}
		}
	}

	// Draw cached rectangles
	if (primaryBitmap)
	{
		Rect r(meterRect.X, meterRect.Y, primaryBitmap->GetWidth(), primaryBitmap->GetHeight());

		graphics.SetClip(&primaryPath);
		graphics.DrawImage(primaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel);
		graphics.ResetClip();
	}
	else
	{
		SolidBrush brush(m_PrimaryColor);
		graphics.FillPath(&brush, &primaryPath);
	}
	if (secondaryMeasure)
	{
		if (secondaryBitmap)
		{
			Rect r(meterRect.X, meterRect.Y, secondaryBitmap->GetWidth(), secondaryBitmap->GetHeight());

			graphics.SetClip(&secondaryPath);
			graphics.DrawImage(secondaryBitmap, r, 0, 0, r.Width, r.Height, UnitPixel);
			graphics.ResetClip();
		}
		else
		{
			SolidBrush brush(m_SecondaryColor);
			graphics.FillPath(&brush, &secondaryPath);
		}
		if (bothBitmap)
		{
			Rect r(meterRect.X, meterRect.Y, bothBitmap->GetWidth(), bothBitmap->GetHeight());

			graphics.SetClip(&bothPath);
			graphics.DrawImage(bothBitmap, r, 0, 0, r.Width, r.Height, UnitPixel);
			graphics.ResetClip();
		}
		else
		{
			SolidBrush brush(m_OverlapColor);
			graphics.FillPath(&brush, &bothPath);
		}
	}

	canvas.EndGdiplusContext();

	return true;
}
Exemple #10
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterBitmap::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	int newY, newX;

	if (m_FrameCount == 0 || !m_Image.IsLoaded()) return false;	// Unable to continue

	Bitmap* bitmap = m_Image.GetImage();

	int x = GetX();
	int y = GetY();

	if (m_Extend)
	{
		int value = (int)m_Value;
		value = max(0, value);		// Only positive integers are supported

		int transitionValue = (int)m_TransitionStartValue;
		transitionValue = max(0, transitionValue);		// Only positive integers are supported

		// Calc the number of numbers
		int numOfNums = 0;

		if (m_Digits > 0)
		{
			numOfNums = m_Digits;
		}
		else
		{
			int tmpValue = value;

			do
			{
				++numOfNums;
				if (m_FrameCount == 1)
				{
					tmpValue /= 2;
				}
				else
				{
					tmpValue /= m_FrameCount;
				}
			}
			while (tmpValue > 0);
		}

		// Blit the images
		int offset;
		if (m_Align == ALIGN_RIGHT)
		{
			offset = 0;
		}
		else if (m_Align == ALIGN_CENTER)
		{
			offset = numOfNums * (m_W + m_Separation) / 2;
		}
		else
		{
			offset = numOfNums * (m_W + m_Separation);
		}

		do
		{
			offset = offset - (m_W + m_Separation);

			int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1));
			int frame = (value % realFrames) * (m_TransitionFrameCount + 1);

			// If transition is ongoing the pick the correct frame
			if (m_TransitionStartTicks > 0)
			{
				int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks);

				int range = ((value % realFrames) - (transitionValue % realFrames)) * (m_TransitionFrameCount + 1);
				if (range < 0)
				{
					range += m_FrameCount;
				}
				int frameAdjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate());
				if (frameAdjustment > range)
				{
					m_TransitionStartTicks = 0;		// The transition is over. Draw with the real value.
				}
				else
				{
					frame = (transitionValue % realFrames) * (m_TransitionFrameCount + 1);
					frame += frameAdjustment;
					frame %= m_FrameCount;
				}
			}

//			LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false");

			if (bitmap->GetHeight() > bitmap->GetWidth())
			{
				newX = 0;
				newY = m_H * frame;
			}
			else
			{
				newX = m_W * frame;
				newY = 0;
			}

			canvas.DrawBitmap(bitmap, Rect(x + offset, y, m_W, m_H), Rect(newX, newY, m_W, m_H));
			if (m_FrameCount == 1)
			{
				value /= 2;
				transitionValue /= 2;
			}
			else
			{
				value /= realFrames;
				transitionValue /= realFrames;
			}
			--numOfNums;
		}
		while (numOfNums > 0);
	}
	else
	{
		int frame = 0;
		int realFrames = (m_FrameCount / (m_TransitionFrameCount + 1));

		if (m_ZeroFrame)
		{
			// Use the first frame only if the value is zero
			if (m_Value > 0)
			{
				frame = (int)(m_Value * (realFrames - 1)) * (m_TransitionFrameCount + 1);
			}
		}
		else
		{
			// Select the correct frame linearly
			frame = (int)(m_Value * realFrames) * (m_TransitionFrameCount + 1);
		}

		// If transition is ongoing the pick the correct frame
		if (m_TransitionStartTicks > 0)
		{
			int diffTicks = (int)(System::GetTickCount64() - m_TransitionStartTicks);

			if (diffTicks > ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate()))
			{
				m_TransitionStartTicks = 0;		// The transition is over. Draw with the real value.
			}
			else
			{
				double range = (m_Value - m_TransitionStartValue);
				double adjustment = range * diffTicks / ((m_TransitionFrameCount + 1) * m_MeterWindow->GetTransitionUpdate());
				double frameAdjustment = adjustment * m_FrameCount;

				frame = (int)(m_TransitionStartValue * realFrames) * (m_TransitionFrameCount + 1);
				frame += (int)frameAdjustment;
				frame %= m_FrameCount;
				frame = max(0, frame);
			}
		}

//		LogDebugF(L"[%u] Value: %f Frame: %i (Transition = %s)", GetTickCount(), m_Value, frame, m_TransitionStartTicks > 0 ? L"true" : L"false");

		if (bitmap->GetHeight() > bitmap->GetWidth())
		{
			newX = 0;
			newY = frame * m_H;
		}
		else
		{
			newX = frame * m_W;
			newY = 0;
		}

		canvas.DrawBitmap(bitmap, Rect(x, y, m_W, m_H), Rect(newX, newY, m_W, m_H));
	}

	return true;
}
Exemple #11
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterBar::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	const D2D1_RECT_F rect = GetMeterRectPadding();
	const FLOAT width = rect.right - rect.left;
	const FLOAT height = rect.bottom - rect.top;
	const FLOAT border = (FLOAT)m_Border;

	Gfx::D2DBitmap* drawBitmap = m_Image.GetImage();

	if (m_Orientation == VERTICAL)
	{
		const FLOAT barSize = height - 2.0f * border;
		FLOAT size = barSize * (FLOAT)m_Value;
		size = min(barSize, size);
		size = max(0.0f, size);

		if (drawBitmap)
		{
			if (m_Flip)
			{
				if (border > 0.0f)
				{
					const auto d = Gfx::Util::ToRectF(rect.left, rect.top, width, border);
					const auto s = Gfx::Util::ToRectF(0.0f, 0.0f, width, border);
					canvas.DrawBitmap(drawBitmap, d, s);

					const auto d2 = Gfx::Util::ToRectF(rect.left, rect.top + size + border, width, border);
					const auto s2 = Gfx::Util::ToRectF(0.0f, height - border, width, border);
					canvas.DrawBitmap(drawBitmap, d2, s2);
				}

				const auto d = Gfx::Util::ToRectF(rect.left, rect.top + border, width, size);
				const auto s = Gfx::Util::ToRectF(0.0f, border, width, size);
				canvas.DrawBitmap(drawBitmap, d, s);
			}
			else
			{
				if (border > 0.0f)
				{
					const auto d = Gfx::Util::ToRectF(rect.left, rect.bottom - size - 2.0f * border, width, border);
					const auto s = Gfx::Util::ToRectF(0.0f, 0.0f, width, border);
					canvas.DrawBitmap(drawBitmap, d, s);

					const auto d2 = Gfx::Util::ToRectF(rect.left, rect.bottom - border, width, border);
					const auto s2 = Gfx::Util::ToRectF(0.0f, height - border, width, border);
					canvas.DrawBitmap(drawBitmap, d2, s2);
				}

				const auto d = Gfx::Util::ToRectF(rect.left, rect.bottom - size - border, width, size);
				const auto s = Gfx::Util::ToRectF(0.0f, height - size - border, width, size);
				canvas.DrawBitmap(drawBitmap, d, s);
			}
		}
		else
		{
			if (m_Flip)
			{
				const auto r = Gfx::Util::ToRectF(rect.left, rect.top, width, size);
				canvas.FillRectangle(r, m_Color);
			}
			else
			{
				const auto r = Gfx::Util::ToRectF(rect.left, rect.bottom - size, width, size);
				canvas.FillRectangle(r, m_Color);
			}
		}
	}
	else
	{
		const FLOAT barSize = width - 2.0f * border;
		FLOAT size = barSize * (FLOAT)m_Value;
		size = min(barSize, size);
		size = max(0.0f, size);

		if (drawBitmap)
		{
			if (m_Flip)
			{
				if (border > 0.0f)
				{
					const auto d = Gfx::Util::ToRectF(rect.right - size - 2.0f * border, rect.top, border, height);
					const auto s = Gfx::Util::ToRectF(0.0f, 0.0f, border, height);
					canvas.DrawBitmap(drawBitmap, d, s);

					const auto d2 = Gfx::Util::ToRectF(rect.right - border, rect.top, border, height);
					const auto s2 = Gfx::Util::ToRectF(width - border, 0.0f, border, height);
					canvas.DrawBitmap(drawBitmap, d2, s2);
				}

				const auto d = Gfx::Util::ToRectF(rect.right - size - border, rect.top, size, height);
				const auto s = Gfx::Util::ToRectF(width - size - border, 0.0f, size, height);
				canvas.DrawBitmap(drawBitmap, d, s);
			}
			else
			{
				if (border > 0.0f)
				{
					const auto d = Gfx::Util::ToRectF(rect.left, rect.top, border, height);
					const auto s = Gfx::Util::ToRectF(0.0f, 0.0f, border, height);
					canvas.DrawBitmap(drawBitmap, d, s);

					const auto d2 = Gfx::Util::ToRectF(rect.left + size + border, rect.top, border, height);
					const auto s2 = Gfx::Util::ToRectF(width - border, 0.0f, border, height);
					canvas.DrawBitmap(drawBitmap, d2, s2);
				}

				const auto d = Gfx::Util::ToRectF(rect.left + border, rect.top, size, height);
				const auto s = Gfx::Util::ToRectF(border, 0.0f, size, height);
				canvas.DrawBitmap(drawBitmap, d, s);
			}
		}
		else
		{
			if (m_Flip)
			{
				const auto r = Gfx::Util::ToRectF(rect.right - size, rect.top, size, height);
				canvas.FillRectangle(r, m_Color);
			}
			else
			{
				const auto r = Gfx::Util::ToRectF(rect.left, rect.top, size, height);
				canvas.FillRectangle(r, m_Color);
			}
		}
	}

	return true;
}
Exemple #12
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterLine::Draw(Gfx::Canvas& canvas)
{
	int maxSize = m_GraphHorizontalOrientation ? m_H : m_W;
	if (!Meter::Draw(canvas) || maxSize <= 0) return false;
	
	Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

	double maxValue = 0.0;
	int counter = 0;

	// Find the maximum value
	if (m_Autoscale)
	{
		double newValue = 0;
		counter = 0;
		for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i)
		{
			double scale = m_ScaleValues[counter];
			for (auto j = (*i).cbegin(); j != (*i).cend(); ++j)
			{
				double val = (*j) * scale;
				newValue = max(newValue, val);
			}
			++counter;
		}

		// Scale the value up to nearest power of 2
		if (newValue > DBL_MAX / 2.0)
		{
			maxValue = DBL_MAX;
		}
		else
		{
			maxValue = 2.0;
			while (maxValue < newValue)
			{
				maxValue *= 2.0;
			}
		}
	}
	else
	{
		for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i)
		{
			double val = (*i)->GetMaxValue();
			maxValue = max(maxValue, val);
		}

		if (maxValue == 0.0)
		{
			maxValue = 1.0;
		}
	}

	int x = GetX();
	int y = GetY();

	// Draw the horizontal lines
	if (m_HorizontalLines)
	{
		// Calc the max number of lines we should draw
		int maxLines = m_H / 4;	// one line per 4 pixels is max
		int numOfLines;

		// Check the highest power of 2 that fits in maxLines
		int power = 2;
		while (power < maxLines)
		{
			power *= 2;
		}

		numOfLines = ((int)maxValue % power) + 1;

		Pen pen(m_HorizontalColor);

		REAL Y;
		for (int j = 0; j < numOfLines; ++j)
		{
			Y = (REAL)((j + 1) * m_H / (numOfLines + 1));
			Y = y + m_H - Y - 1;
			graphics.DrawLine(&pen, (REAL)x, Y, (REAL)(x + m_W - 1), Y);	// GDI+
		}
	}

	// Draw all the lines

	if (m_GraphHorizontalOrientation)
	{
		const REAL W = m_W - 1.0f;
		counter = 0;
		for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i)
		{
			// Draw a line
			REAL X, oldX;

			const double scale = m_ScaleValues[counter] * W / maxValue;

			int pos = m_CurrentPos;

			auto calcX = [&](REAL& _x)
			{
				_x = (REAL)((*i)[pos] * scale);
				_x = min(_x, W);
				_x = max(_x, 0.0f);
				_x = x + (m_GraphStartLeft ? _x : W - _x);
			};

			calcX(oldX);

			// Cache all lines
			GraphicsPath path;
		
			if (!m_Flip)
			{
				for (int j = y + 1, R = y + m_H; j < R; ++j)
				{
					++pos;
					pos %= m_H;

					calcX(X);

					path.AddLine(oldX, (REAL)(j - 1), X, (REAL)j);

					oldX = X;
				}
			}
			else
			{
				for (int j = y + m_H, R = y + 1; j > R; --j)
				{
					++pos;
					pos %= m_H;

					calcX(X);

					path.AddLine(oldX, (REAL)(j - 1), X, (REAL)(j - 2));

					oldX = X;
				}
			}

			// Draw cached lines
			Pen pen(m_Colors[counter], (REAL)m_LineWidth);
			pen.SetLineJoin(LineJoinBevel);
			graphics.DrawPath(&pen, &path);

			++counter;
		}
	}
	else
	{
		const REAL H = m_H - 1.0f;
		counter = 0;
		for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i)
		{
			// Draw a line
			REAL Y, oldY;

			const double scale = m_ScaleValues[counter] * H / maxValue;

			int pos = m_CurrentPos;

			auto calcY = [&](REAL& _y)
			{
				_y = (REAL)((*i)[pos] * scale);
				_y = min(_y, H);
				_y = max(_y, 0.0f);
				_y = y + (m_Flip ? _y : H - _y);
			};

			calcY(oldY);

			// Cache all lines
			GraphicsPath path;
		
			if (!m_GraphStartLeft)
			{
				for (int j = x + 1, R = x + m_W; j < R; ++j)
				{
					++pos;
					pos %= m_W;

					calcY(Y);

					path.AddLine((REAL)(j - 1), oldY, (REAL)j, Y);

					oldY = Y;
				}
			}
			else
			{
				for (int j = x + m_W, R = x + 1; j > R; --j)
				{
					++pos;
					pos %= m_W;

					calcY(Y);

					path.AddLine((REAL)(j - 1), oldY, (REAL)(j - 2), Y);

					oldY = Y;
				}
			}

			// Draw cached lines
			Pen pen(m_Colors[counter], (REAL)m_LineWidth);
			pen.SetLineJoin(LineJoinBevel);
			graphics.DrawPath(&pen, &path);

			++counter;
		}
	}

	canvas.EndGdiplusContext();

	return true;
}
Exemple #13
0
/*
** Draws the meter on the double buffer
**
*/
bool MeterImage::Draw(Gfx::Canvas& canvas)
{
	if (!Meter::Draw(canvas)) return false;

	if (m_Image.IsLoaded())
	{
		// Copy the image over the doublebuffer
		Bitmap* drawBitmap = m_Image.GetImage();

		int imageW = drawBitmap->GetWidth();
		int imageH = drawBitmap->GetHeight();
		
		if (imageW == 0 || imageH == 0 || m_W == 0 || m_H == 0) return true;

		Gdiplus::Rect meterRect = GetMeterRectPadding();

		int drawW = meterRect.Width;
		int drawH = meterRect.Height;

		bool hasMask = (m_Skin->GetUseD2D() && m_MaskImage.IsLoaded());
		if (hasMask)
		{
			Bitmap* maskBitmap = m_MaskImage.GetImage();

			imageW = maskBitmap->GetWidth();
			imageH = maskBitmap->GetHeight();
			int imageMW = drawBitmap->GetWidth();
			int imageMH = drawBitmap->GetHeight();

			int cropX = 0;
			int cropY = 0;
			int cropW = imageMW;
			int cropH = imageMH;

			REAL imageratio = imageMW / (REAL)imageMH;
			REAL meterRatio = meterRect.Width / (REAL)meterRect.Height;

			if (imageratio != meterRatio)
			{
				if (imageratio > meterRatio)
				{
					cropW = (int)(imageMH * meterRatio);
					cropX = (imageMW - cropW) / 2;
				}
				else
				{
					cropH = (int)(imageMW / meterRatio);
					cropY = (imageMH - cropH) / 2;
				}
			}

			canvas.DrawMaskedBitmap(drawBitmap, maskBitmap, meterRect, Rect(0, 0, imageW, imageH), Gdiplus::Rect(cropX, cropY, cropW, cropH));
		}

		else if (drawW == imageW && drawH == imageH &&
			m_ScaleMargins.left == 0 && m_ScaleMargins.top == 0 && m_ScaleMargins.right == 0 && m_ScaleMargins.bottom == 0)
		{
			canvas.DrawBitmap(drawBitmap, Rect(meterRect.X, meterRect.Y, drawW, drawH), Rect(0, 0, imageW, imageH));
		}
		else if (m_DrawMode == DRAWMODE_TILE)
		{
			Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

			ImageAttributes imgAttr;
			imgAttr.SetWrapMode(WrapModeTile);

			Rect r(meterRect.X, meterRect.Y, drawW, drawH);
			graphics.DrawImage(drawBitmap, r, 0, 0, drawW, drawH, UnitPixel, &imgAttr);

			canvas.EndGdiplusContext();
		}
		else if (m_DrawMode == DRAWMODE_KEEPRATIO || m_DrawMode == DRAWMODE_KEEPRATIOANDCROP)
		{
			int cropX = 0;
			int cropY = 0;
			int cropW = imageW;
			int cropH = imageH;

			if (m_WDefined && m_HDefined)
			{
				REAL imageRatio = imageW / (REAL)imageH;
				REAL meterRatio = meterRect.Width / (REAL)meterRect.Height;

				if (imageRatio != meterRatio)
				{
					if (m_DrawMode == DRAWMODE_KEEPRATIO)
					{
						if (imageRatio > meterRatio)
						{
							drawH = meterRect.Width * imageH / imageW;
							meterRect.Y += (meterRect.Height - drawH) / 2;
						}
						else
						{
							drawW = meterRect.Height * imageW / imageH;
							meterRect.X += (meterRect.Width - drawW) / 2;
						}
					}
					else
					{
						if (imageRatio > meterRatio)
						{
							cropW = (int)(imageH * meterRatio);
							cropX = (imageW - cropW) / 2;
						}
						else
						{
							cropH = (int)(imageW / meterRatio);
							cropY = (imageH - cropH) / 2;
						}
					}
				}
			}

			Rect r(meterRect.X, meterRect.Y, drawW, drawH);
			canvas.DrawBitmap(drawBitmap, r, Rect(cropX, cropY, cropW, cropH));
		}
		else
		{
			const RECT& m = m_ScaleMargins;

			if (m.top > 0)
			{
				if (m.left > 0)
				{
					// Top-Left
					Rect r(meterRect.X, meterRect.Y, m.left, m.top);
					canvas.DrawBitmap(drawBitmap, r, Rect(0, 0, m.left, m.top));
				}

				// Top
				Rect r(meterRect.X + m.left, meterRect.Y, drawW - m.left - m.right, m.top);
				canvas.DrawBitmap(drawBitmap, r, Rect(m.left, 0, imageW - m.left - m.right, m.top));

				if (m.right > 0)
				{
					// Top-Right
					Rect r(meterRect.X + drawW - m.right, meterRect.Y, m.right, m.top);
					canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, 0, m.right, m.top));
				}
			}

			if (m.left > 0)
			{
				// Left
				Rect r(meterRect.X, meterRect.Y + m.top, m.left, drawH - m.top - m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(0, m.top, m.left, imageH - m.top - m.bottom));
			}

			// Center
			Rect r(meterRect.X + m.left, meterRect.Y + m.top, drawW - m.left - m.right, drawH - m.top - m.bottom);
			canvas.DrawBitmap(drawBitmap, r, Rect(m.left, m.top, imageW - m.left - m.right, imageH - m.top - m.bottom));

			if (m.right > 0)
			{
				// Right
				Rect r(meterRect.X + drawW - m.right, meterRect.Y + m.top, m.right, drawH - m.top - m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, m.top, m.right, imageH - m.top - m.bottom));
			}

			if (m.bottom > 0)
			{
				if (m.left > 0)
				{
					// Bottom-Left
					Rect r(meterRect.X, meterRect.Y + drawH - m.bottom, m.left, m.bottom);
					canvas.DrawBitmap(drawBitmap, r, Rect(0, imageH - m.bottom, m.left, m.bottom));
				}

				// Bottom
				Rect r(meterRect.X + m.left, meterRect.Y + drawH - m.bottom, drawW - m.left - m.right, m.bottom);
				canvas.DrawBitmap(drawBitmap, r, Rect(m.left, imageH - m.bottom, imageW - m.left - m.right, m.bottom));

				if (m.right > 0)
				{
					// Bottom-Right
					Rect r(meterRect.X + drawW - m.right, meterRect.Y + drawH - m.bottom, m.right, m.bottom);
					canvas.DrawBitmap(drawBitmap, r, Rect(imageW - m.right, imageH - m.bottom, m.right, m.bottom));
				}
			}
		}
	}

	return true;
}
/*
** Draws the meter on the double buffer
**
*/
bool MeterSegmentedLine::Draw(Gfx::Canvas& canvas)
{
	int maxSize = m_DataWidth;
	if (!Meter::Draw(canvas) || maxSize <= 0) return false;
	
	Gdiplus::Graphics& graphics = canvas.BeginGdiplusContext();

	double maxValue = 0.0;
	int counter = 0;

	// Find the maximum value
	if (m_Autoscale)
	{
		double newValue = 0;
		counter = 0;
		for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i)
		{
			double scale = m_ScaleValues[counter];
			for (auto j = (*i).cbegin(); j != (*i).cend(); ++j)
			{
				double val = (*j) * scale;
				newValue = max(newValue, val);
			}
			++counter;
		}

		// Scale the value up to nearest power of 2
		if (newValue > DBL_MAX / 2.0)
		{
			maxValue = DBL_MAX;
		}
		else
		{
			maxValue = 2.0;
			while (maxValue < newValue)
			{
				maxValue *= 2.0;
			}
		}
	}
	else
	{
		for (auto i = m_Measures.cbegin(); i != m_Measures.cend(); ++i)
		{
			double val = (*i)->GetMaxValue();
			maxValue = max(maxValue, val);
		}

		if (maxValue == 0.0)
		{
			maxValue = 1.0;
		}
	}

	Gdiplus::Rect meterRect = GetMeterRectPadding();

	// Draw all the lines
	const REAL H = meterRect.Height - 1.0f;
	counter = 0;
	auto pointsBuffer = m_Points.cbegin();
	for (auto i = m_AllValues.cbegin(); i != m_AllValues.cend(); ++i)
	{
		// Draw a line
		REAL Y, oldY;

		const double scale = m_ScaleValues[counter] * H / maxValue;

		int pos = m_CurrentPos;

		auto calcY = [&](REAL& _y, REAL stepSize, int currPos)		//TODO: move this lambda elsewhere
		{
			_y = 0;
			switch (m_CurveFitMethod)
			{
				//first value
				case 0:	_y = (REAL)((*i)[currPos]);
						break;

				//maximum value
				case 1: for (int ind = 0; ind < stepSize; ind++)
							_y = max(_y, (REAL)((*i)[(currPos + ind) % m_DataWidth]));
						break;

				//arithmetic mean
				case 2: for (int ind = 0; ind < stepSize; ind++)
							_y += (REAL)((*i)[(currPos + ind) % m_DataWidth]);
						_y /= stepSize;
						break;

				default: _y = (REAL)((*i)[currPos]);
			}
			
			_y *= scale;
			_y = min(_y, H);
			_y = max(_y, 0.0f);
			_y = meterRect.Y + (H - _y);
		};

		// Cache all lines
		GraphicsPath path;
		int segmentInd = 0,
			step,
			divider;

		//compute y values
		step = m_SegmentDividers[m_SegmentDividers.size() - 1];
		divider = m_Segments.size() > 0 ? m_W - m_Segments[m_Segments.size() - 1] : m_W;
		for (int j = 0; j < m_W; ++j)
		{
			calcY(Y, step, pos - pos % step);
			(*pointsBuffer)[j] = Y;

			if (segmentInd < m_Segments.size() && j >= divider)
			{
				segmentInd++;

				step = m_SegmentDividers[m_SegmentDividers.size() - segmentInd - 1];
				divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W;
			}

			pos += step;
			pos %= m_DataWidth;
		}
		
		//draw y values
		segmentInd = 0;
		divider = m_Segments.size() > 0 ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W;
		if (!m_GraphStartLeft)
		{
			for (int j = 1; j < m_W; ++j)
			{
				if (segmentInd < m_Segments.size() && j >= divider)
				{
					segmentInd++;
					path.SetMarker();
					path.StartFigure();

					divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W;
				}

				path.AddLine((REAL)(meterRect.X + j - 1), (*pointsBuffer)[j - 1], (REAL)(meterRect.X + j), (*pointsBuffer)[j]);
			}
		}
		else
		{
			for (int j = 1; j < m_W; ++j)
			{
				if (segmentInd < m_Segments.size() && j >= divider)
				{
					segmentInd++;
					path.SetMarker();
					path.StartFigure();
					divider = segmentInd != m_Segments.size() ? m_W - m_Segments[m_Segments.size() - segmentInd - 1] : m_W;
				}

				path.AddLine((REAL)(meterRect.X + meterRect.Width - j), (*pointsBuffer)[j - 1], (REAL)(meterRect.X + meterRect.Width - j - 1), (*pointsBuffer)[j]);
			}
		}

		// Draw cached lines
		GraphicsPathIterator pathIter(&path);
		GraphicsPath subPath;
		for (auto color = m_Colors[counter].rbegin(); color != m_Colors[counter].rend(); ++color)
		{
			pathIter.NextMarker(&subPath);

			Pen pen(*color, (REAL)m_LineWidth);
			pen.SetLineJoin(LineJoinRound);
			graphics.DrawPath(&pen, &subPath);
		}

		++counter;
		++pointsBuffer;
	}

	canvas.EndGdiplusContext();

	return true;
}
Exemple #15
0
/*
** Draws the meter on the double buffer
**
*/
bool CMeterBar::Draw(Gfx::Canvas& canvas)
{
    if (!CMeter::Draw(canvas)) return false;

    int x = GetX();
    int y = GetY();

    Bitmap* drawBitmap = m_Image.GetImage();

    if (m_Orientation == VERTICAL)
    {
        int barSize = m_H - 2 * m_Border;
        int size = (int)(barSize * m_Value);
        size = min(barSize, size);
        size = max(0, size);

        if (drawBitmap)
        {
            if (m_Flip)
            {
                if (m_Border > 0)
                {
                    Rect r2(x, y, m_W, m_Border);
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_W, m_Border));
                    r2.Y = y + size + m_Border;
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, m_H - m_Border, m_W, m_Border));
                }

                Rect r(x, y + m_Border, m_W, size);
                canvas.DrawBitmap(drawBitmap, r, Rect(0, m_Border, m_W, size));
            }
            else
            {
                if (m_Border > 0)
                {
                    Rect r2(x, y + m_H - size - 2 * m_Border, m_W, m_Border);
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_W, m_Border));
                    r2.Y = y + m_H - m_Border;
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, m_H - m_Border, m_W, m_Border));
                }

                Rect r(x, y + m_H - size - m_Border, m_W, size);
                canvas.DrawBitmap(drawBitmap, r, Rect(0, m_H - size - m_Border, m_W, size));
            }
        }
        else
        {
            SolidBrush brush(m_Color);
            if (m_Flip)
            {
                Rect r(x, y, m_W, size);
                canvas.FillRectangle(r, brush);
            }
            else
            {
                Rect r(x, y + m_H - size, m_W, size);
                canvas.FillRectangle(r, brush);
            }
        }
    }
    else
    {
        int barSize = m_W - 2 * m_Border;
        int size = (int)(barSize * m_Value);
        size = min(barSize, size);
        size = max(0, size);

        if (drawBitmap)
        {
            if (m_Flip)
            {
                if (m_Border > 0)
                {
                    Rect r2(x + m_W - size - 2 * m_Border, y, m_Border, m_H);
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, m_H));
                    r2.X = x + m_W - m_Border;
                    canvas.DrawBitmap(drawBitmap, r2, Rect(m_W - m_Border, 0, m_Border, m_H));
                }

                Rect r(x + m_W - size - m_Border, y, size, m_H);
                canvas.DrawBitmap(drawBitmap, r, Rect(m_W - size - m_Border, 0, size, m_H));
            }
            else
            {
                if (m_Border > 0)
                {
                    Rect r2(x, y, m_Border, m_H);
                    canvas.DrawBitmap(drawBitmap, r2, Rect(0, 0, m_Border, m_H));
                    r2.X = x + size + m_Border;
                    canvas.DrawBitmap(drawBitmap, r2, Rect(m_W - m_Border, 0, m_Border, m_H));
                }

                Rect r(x + m_Border, y, size, m_H);
                canvas.DrawBitmap(drawBitmap, r, Rect(m_Border, 0, size, m_H));
            }
        }
        else
        {
            SolidBrush brush(m_Color);
            if (m_Flip)
            {
                Rect r(x + m_W - size, y, size, m_H);
                canvas.FillRectangle(r, brush);
            }
            else
            {
                Rect r(x, y, size, m_H);
                canvas.FillRectangle(r, brush);
            }
        }
    }

    return true;
}