/*
** 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;
}
Пример #2
0
/*
** 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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
/*
** 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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
0
/*
** 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;
}