Exemplo n.º 1
0
//*******************************************************************************
void CBCGPKnob::OnDrawTickMarkTextLabel(CBCGPGraphicsManager* pGM, const CBCGPTextFormat& tf, const CBCGPRect& rectText, const CString& strLabel, double dblVal, int nScale, const CBCGPBrush& br)
{
    if (m_sizeIcon.cx == 0)
    {
        CBCGPCircularGaugeImpl::OnDrawTickMarkTextLabel(pGM, tf, rectText, strLabel, dblVal, nScale, br);
        return;
    }

    if (m_sizeIcon.cy == 0)
    {
        m_sizeIcon.cy = pGM->GetImageSize(m_Icons).cy;
    }

    CBCGPSize sizeIcon(m_sizeIcon.cx * m_sizeScaleRatio.cx, m_sizeIcon.cy * m_sizeScaleRatio.cy);

    double cx = 0.;
    double cy = 0.;

    double angle = 0.;

    if (ValueToAngle(dblVal, angle, nScale))
    {
        cx = sizeIcon.cx * cos(bcg_deg2rad(angle)) / 2;
    }

    CBCGPPoint ptImage(
        rectText.left + max(0., .5 * (rectText.Width() - sizeIcon.cx)) + cx,
        rectText.top + max(0., .5 * (rectText.Height() - sizeIcon.cy)) + cy);

    pGM->DrawImage(m_Icons, ptImage, sizeIcon, 1., CBCGPImage::BCGP_IMAGE_INTERPOLATION_MODE_LINEAR,
                   CBCGPRect(CBCGPPoint(m_sizeIcon.cx * m_nCurrLabelIndex, 0), m_sizeIcon));
}
//***************************************************************************************
void CBCGPRadialMenuObject::OnDraw(CBCGPGraphicsManager* pGM, const CBCGPRect& /*rectClip*/, DWORD dwFlags)
{
	if (dwFlags == BCGP_DRAW_STATIC)
	{
		return;
	}

	m_nShadowDepth = pGM->IsSupported(BCGP_GRAPHICS_MANAGER_COLOR_OPACITY) ? GetShadowDepth() : 0;

	CBCGPRect rect = m_rect;
	if (rect.Width() < rect.Height())
	{
		rect.top += (rect.Height() - rect.Width()) / 2;
		rect.bottom = rect.top + rect.Width();
	}
	else if (rect.Height() < rect.Width())
	{
		rect.left += (rect.Width() - rect.Height()) / 2;
		rect.right = rect.left + rect.Height();
	}

	rect.DeflateRect(2., 2.);

	rect.right -= m_nShadowDepth;
	rect.bottom -= m_nShadowDepth;

	const double radius = rect.Width() / 2;
	const double radiusSmall = INTERNAL_PART * rect.Width() + 1.0;
	const CBCGPPoint center = rect.CenterPoint();

	CBCGPSize sizeIcon((double)m_cxIcon, 16);

	if (!m_Icons.IsNull())
	{
		sizeIcon.cy = pGM->GetImageSize(m_Icons).cy;
	}

	const int nItems = (int)m_arItems.GetSize();

	if (IsDirty())
	{
		int nCircleItems = m_bHasCenterButton ? nItems - 1 : nItems;

		double dblDeltaAngle = nCircleItems == 0 ? 0. : 360. / nCircleItems;
		double dblStartAngle = 90. - dblDeltaAngle / 2;

		for (int i = 0; i < nItems; i++)
		{
			CBCGPRadialMenuItem* pItem = m_arItems[i];
			ASSERT_VALID(pItem);

			pItem->m_bIsCenter = i == nItems -1 && m_bHasCenterButton;

			pItem->m_Shape.Destroy();
			pItem->m_Shape.Clear();

			if (!pItem->m_bIsCenter)
			{
				double dblFinishAngle = dblStartAngle + dblDeltaAngle;

				const double dblStartAngleRad = bcg_deg2rad(dblStartAngle);
				const double dblFinishAngleRad = bcg_deg2rad(dblFinishAngle);
				const double dblMiddleAngleRad = bcg_deg2rad(dblStartAngle + dblDeltaAngle / 2);

				double angleStartCos = cos(dblStartAngleRad);
				double angleStartSin = sin(dblStartAngleRad);
				double angleFinishCos = cos(dblFinishAngleRad);
				double angleFinishSin = sin(dblFinishAngleRad);

				pItem->m_Shape.SetStart(
					CBCGPPoint(center.x + angleStartCos * radius, center.y - angleStartSin * radius));
				pItem->m_Shape.AddArc(
					CBCGPPoint(center.x + angleFinishCos * radius, center.y - angleFinishSin * radius),
					CBCGPSize(radius, radius), dblStartAngle > dblFinishAngle, FALSE);
				pItem->m_Shape.AddLine(
					CBCGPPoint(center.x + angleFinishCos * radiusSmall, center.y - angleFinishSin * radiusSmall));
				pItem->m_Shape.AddArc(
					CBCGPPoint(center.x + angleStartCos * radiusSmall, center.y - angleStartSin * radiusSmall),
					CBCGPSize(radiusSmall, radiusSmall), dblStartAngle < dblFinishAngle, FALSE);

				pItem->m_ptCenter = CBCGPPoint(
					center.x + cos(dblMiddleAngleRad) * 2 * radius / 3,
					center.y - sin(dblMiddleAngleRad) * 2 * radius / 3);

				dblStartAngle = dblFinishAngle;
			}
			else
			{
				pItem->m_Shape.SetStart(center);
				pItem->m_Shape.AddLine(center);
				pGM->CombineGeometry(pItem->m_Shape, pItem->m_Shape, CBCGPEllipseGeometry(CBCGPEllipse(center, radiusSmall, radiusSmall)), RGN_OR);

				pItem->m_ptCenter = center;
			}
		}
	}

	CBCGPEllipse ellipseInt(center, radiusSmall, radiusSmall);

	CBCGPRect rectShadow = rect;
	rectShadow.OffsetRect(m_nShadowDepth, m_nShadowDepth);

	if (!m_bHasCenterButton && m_pCtrl->GetSafeHwnd() != NULL && (m_pCtrl->GetExStyle() & WS_EX_LAYERED))
	{
		if (m_nShadowDepth > 0)
		{
			CBCGPEllipseGeometry egShadow(rectShadow);

			CBCGPPoint centerShadow = center;
			centerShadow.x += m_nShadowDepth;
			centerShadow.y += m_nShadowDepth;

			CBCGPEllipse ellipseIntShadow(centerShadow, radiusSmall, radiusSmall);
			CBCGPEllipseGeometry egInternalShadow(ellipseIntShadow);

			CBCGPComplexGeometry shapeShadow;
			pGM->CombineGeometry(shapeShadow, egShadow, egInternalShadow, RGN_DIFF);

			pGM->FillGeometry(shapeShadow, m_brShadow);
		}

		CBCGPEllipseGeometry eg(rect);
		CBCGPEllipseGeometry egInternal(ellipseInt);

		CBCGPComplexGeometry shape;
		pGM->CombineGeometry(shape, eg, egInternal, RGN_DIFF);

		pGM->FillGeometry(shape, m_brFill);

	}
	else
	{
		if (m_nShadowDepth > 0)
		{
			pGM->FillEllipse(rectShadow, m_brShadow);
		}

		pGM->FillEllipse(rect, m_brFill);
	}

	pGM->DrawEllipse(rect, m_brBorder);

	if (!pGM->IsSupported(BCGP_GRAPHICS_MANAGER_COLOR_OPACITY))
	{
		CBCGPRect rect1 = rect;
		rect1.DeflateRect(1, 1);

		pGM->DrawEllipse(rect1, m_brFill);
	}

	BOOL bIsCtrlDisabled = m_pCtrl->GetSafeHwnd() != NULL && !m_pCtrl->IsWindowEnabled();

	for (int i = 0; i < nItems; i++)
	{
		CBCGPRadialMenuItem* pItem = m_arItems[i];
		ASSERT_VALID(pItem);

		if (i == m_nHighlighted)
		{
			pGM->FillGeometry(pItem->m_Shape, m_nHighlighted == m_nPressed ? m_brPressed : 
				m_brHighlighted.IsEmpty() ? m_brFill : m_brHighlighted);
		}

		pItem->OnDrawIcon(pGM, bIsCtrlDisabled, m_Icons, sizeIcon);

		pGM->DrawGeometry(pItem->m_Shape, m_brBorder);
	}

	pGM->DrawEllipse(ellipseInt, m_brBorder);

	if (!pGM->IsSupported(BCGP_GRAPHICS_MANAGER_ANTIALIAS))
	{
		rect.InflateRect(1, 1);
		pGM->DrawEllipse(rect, m_brBorder);
	}

	if (m_pCtrl->GetSafeHwnd() != NULL && m_pCtrl->IsFocused() && !m_pCtrl->IsPopup())
	{
		rect.InflateRect(1, 1);
		pGM->DrawEllipse(rect, m_brFocusedBorder);
	}
}
//*******************************************************************************
void CBCGPChartObject::OnCalcScreenPoints(CBCGPGraphicsManager* pGM)
{
	ASSERT_VALID(this);

	m_rectScreen.SetRectEmpty();
	m_rectScreenBounds.SetRectEmpty();
	m_ptAnchor.x = m_ptAnchor.y = 0.;

	if (m_pParentChart == NULL)
	{
		return;
	}

	CBCGPSize szScaleRatio = m_pParentChart->GetScaleRatio();

	CBCGPChartAxis* pXAxis = m_pXAxis;
	CBCGPChartAxis* pYAxis = m_pYAxis;

	if (m_coordinateMode == CBCGPChartObject::CM_CHART_VALUES || 
		m_coordinateMode == CBCGPChartObject::CM_CHART_VALUE_DIST_ANGLE ||
		m_coordinateMode == CBCGPChartObject::CM_AXIS_INSIDE_MARK ||
		m_coordinateMode == CBCGPChartObject::CM_AXIS_OUTSIDE_MARK)
	{
		if (pXAxis == NULL)
		{
			m_pXAxis = pXAxis = m_pParentChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
		}

		if (pYAxis == NULL)
		{
			m_pYAxis = pYAxis = m_pParentChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS);
		}
	}

	CBCGPSize szObjectSize = m_szObjectSize.IsNull() ?  OnCalcObjectSize(pGM) : m_szObjectSize;

	m_rectScreenBounds = OnCalcBoundingRect();

	CBCGPRect rectBounds = m_rectScreenBounds;

	CBCGPPoint ptLeftTop(CBCGPChartObject::_EmptyPoint);
	CBCGPPoint ptRightBottom(CBCGPChartObject::_EmptyPoint);

	if (m_coordinateMode == CBCGPChartObject::CM_PERCENTS)
	{
		if (m_rectCoordinates.left != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.x = rectBounds.left + rectBounds.Width() * m_rectCoordinates.left / 100.;
		}

		if (m_rectCoordinates.top != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.y = rectBounds.top + rectBounds.Height() * m_rectCoordinates.top / 100;
		}

		if (m_rectCoordinates.right != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.x = rectBounds.right - rectBounds.Width() * m_rectCoordinates.right / 100.;
		}

		if (m_rectCoordinates.bottom != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.y = rectBounds.bottom - rectBounds.Height() * m_rectCoordinates.bottom / 100.;
		}
	}
	else if (m_coordinateMode == CBCGPChartObject::CM_PIXELS)
	{
		if (m_rectCoordinates.left != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.x = rectBounds.left + m_rectCoordinates.left * szScaleRatio.cx;
		}

		if (m_rectCoordinates.top != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.y = rectBounds.top + m_rectCoordinates.top * szScaleRatio.cy;
		}

		if (m_rectCoordinates.right != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.x = rectBounds.right - m_rectCoordinates.right * szScaleRatio.cx;
		}

		if (m_rectCoordinates.bottom != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.y = rectBounds.bottom - m_rectCoordinates.bottom * szScaleRatio.cy;
		}
	}
	else if (m_coordinateMode == CBCGPChartObject::CM_PIXELS_FIXED_SIZE)
	{
		if (m_rectCoordinates.left != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.x = rectBounds.left + m_rectCoordinates.left * szScaleRatio.cx;
		}
		else
		{
			ptLeftTop.x = rectBounds.left;
		}

		if (m_rectCoordinates.top != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.y = rectBounds.top + m_rectCoordinates.top * szScaleRatio.cy;
		}
		else
		{
			ptLeftTop.y = rectBounds.top;
		}

		if (m_rectCoordinates.right != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.x = ptLeftTop.x + m_rectCoordinates.right * szScaleRatio.cx;
		}
		else
		{
			ptRightBottom.x = ptLeftTop.x + rectBounds.Width();
		}

		if (m_rectCoordinates.bottom != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.y = ptLeftTop.y + m_rectCoordinates.bottom * szScaleRatio.cy;
		}
		else
		{
			ptRightBottom.y = ptLeftTop.y + rectBounds.Height();
		}
	}
	else if (m_coordinateMode == CBCGPChartObject::CM_CHART_VALUES)
	{
		ASSERT_VALID(pXAxis);
		ASSERT_VALID(pYAxis);

		CBCGPRect rectCoordinates = m_rectCoordinates;

		if (pXAxis != NULL && pXAxis->IsVertical())
		{
			rectCoordinates = CBCGPRect(m_rectCoordinates.bottom, m_rectCoordinates.right,
										m_rectCoordinates.top, m_rectCoordinates.left);
			pXAxis = m_pYAxis;
			pYAxis = m_pXAxis;
		}

 		if (pXAxis->m_bReverseOrder && !pXAxis->IsVertical())
 		{
			if ((rectCoordinates.left != CBCGPChartObject::_EmptyCoordinate && 
				 rectCoordinates.right == CBCGPChartObject::_EmptyCoordinate) || 
				 (rectCoordinates.left == CBCGPChartObject::_EmptyCoordinate && 
				 rectCoordinates.right != CBCGPChartObject::_EmptyCoordinate))
			{
				rectCoordinates.SwapLeftRight();
			}
 		}
 
 		if (pYAxis->m_bReverseOrder && pYAxis->IsVertical())
 		{
			if ((rectCoordinates.top != CBCGPChartObject::_EmptyCoordinate && 
				 rectCoordinates.bottom == CBCGPChartObject::_EmptyCoordinate) || 
				 (rectCoordinates.top == CBCGPChartObject::_EmptyCoordinate && 
				 rectCoordinates.bottom != CBCGPChartObject::_EmptyCoordinate))
			{
				rectCoordinates.SwapTopBottom();
			}
 		}

		if (rectCoordinates.left != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.x = pXAxis->PointFromValue(rectCoordinates.left, FALSE);
		}
		else if (szObjectSize.cx == 0)
		{
			ptLeftTop.x = pXAxis->PointFromValue(pXAxis->GetMinDisplayedValue(TRUE), TRUE);
		}

		if (rectCoordinates.top != CBCGPChartObject::_EmptyCoordinate)
		{
			ptLeftTop.y = pYAxis->PointFromValue(rectCoordinates.top, FALSE);
		}
		else if (szObjectSize.cy == 0)
		{
			ptLeftTop.y = pYAxis->PointFromValue(pYAxis->GetMaxDisplayedValue(TRUE), TRUE);
		}

		if (rectCoordinates.right != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.x = pXAxis->PointFromValue(rectCoordinates.right, FALSE);
		}
		else if (szObjectSize.cx == 0)
		{
			ptRightBottom.x = pXAxis->PointFromValue(pXAxis->GetMaxDisplayedValue(TRUE), TRUE);
		}

		if (rectCoordinates.bottom != CBCGPChartObject::_EmptyCoordinate)
		{
			ptRightBottom.y = pYAxis->PointFromValue(rectCoordinates.bottom, FALSE);
		}
		else if (szObjectSize.cy == 0)
		{
			ptRightBottom.y = pYAxis->PointFromValue(pYAxis->GetMinDisplayedValue(TRUE), TRUE);
		}
	}
	else if (m_coordinateMode == CM_CHART_VALUE_DIST_ANGLE)
	{
		ASSERT_VALID(pXAxis);
		ASSERT_VALID(pYAxis);

		if (!IsRectOffsetsValid())
		{
			return;
		}

		CBCGPRect rectCoordinates = m_rectCoordinates;

		if (pXAxis != NULL && pXAxis->IsVertical())
		{
			rectCoordinates = CBCGPRect(m_rectCoordinates.top, m_rectCoordinates.left,
										m_rectCoordinates.right, m_rectCoordinates.bottom);
			pXAxis = m_pYAxis;
			pYAxis = m_pXAxis;
		}

		m_ptAnchor.x = pXAxis->PointFromValue(rectCoordinates.left, FALSE);
		m_ptAnchor.y = pYAxis->PointFromValue(rectCoordinates.top, FALSE); 

		double dblDistanceX = rectCoordinates.right * szScaleRatio.cx;
		double dblDistanceY = rectCoordinates.right * szScaleRatio.cy;

		CBCGPPoint ptCenter(m_ptAnchor.x + dblDistanceX * sin(bcg_deg2rad(rectCoordinates.bottom)),
							m_ptAnchor.y - dblDistanceY * cos(bcg_deg2rad(rectCoordinates.bottom)));

		ptLeftTop.SetPoint(ptCenter.x - szObjectSize.cx / 2, ptCenter.y - szObjectSize.cy / 2);
		ptRightBottom.SetPoint(ptCenter.x + szObjectSize.cx / 2, ptCenter.y + szObjectSize.cy / 2);
	}
	else if (m_coordinateMode == CM_AXIS_INSIDE_MARK || m_coordinateMode == CM_AXIS_OUTSIDE_MARK)
	{
		ASSERT_VALID(pXAxis);
		ASSERT_VALID(pYAxis);

		if (m_rectCoordinates.top == _EmptyCoordinate && m_rectCoordinates.left == _EmptyCoordinate)
		{
			return;
		}

		double dblHorzOffset = m_rectCoordinates.right == _EmptyCoordinate ? 0 : m_rectCoordinates.right * szScaleRatio.cx;
		double dblVertOffset = m_rectCoordinates.bottom == _EmptyCoordinate ? 0 : m_rectCoordinates.bottom * szScaleRatio.cy;

		CBCGPChartAxis* pUsedAxis = m_rectCoordinates.left != _EmptyCoordinate ? pXAxis : pYAxis;
		double dblUsedValue = m_rectCoordinates.left != _EmptyCoordinate ? m_rectCoordinates.left : m_rectCoordinates.top;

		double dblScrVal = pUsedAxis->PointFromValue(dblUsedValue, FALSE);
		CBCGPRect rectAxis = pUsedAxis->GetAxisRect(FALSE, FALSE, TRUE);

		CBCGPPoint ptCenter;

		if (m_coordinateMode == CM_AXIS_INSIDE_MARK && 
			(pUsedAxis->m_axisDefaultPosition == CBCGPChartAxis::ADP_BOTTOM || pUsedAxis->m_axisDefaultPosition == CBCGPChartAxis::ADP_LEFT) ||
			m_coordinateMode == CM_AXIS_OUTSIDE_MARK && 
			(pUsedAxis->m_axisDefaultPosition == CBCGPChartAxis::ADP_TOP || pUsedAxis->m_axisDefaultPosition == CBCGPChartAxis::ADP_RIGHT))
		{
			if (pUsedAxis->IsVertical())
			{
				ptCenter.x = rectAxis.right + dblVertOffset + szObjectSize.cx / 2;
				ptCenter.y = dblScrVal - dblHorzOffset;
			}
			else
			{
				ptCenter.x = dblScrVal + dblHorzOffset;
				ptCenter.y = rectAxis.top - dblVertOffset - szObjectSize.cy /2;
			}
		}
		else
		{
			if (pUsedAxis->IsVertical())
			{
				ptCenter.x = rectAxis.left - dblVertOffset - szObjectSize.cx / 2;
				ptCenter.y = dblScrVal - dblHorzOffset;
			}
			else
			{
				ptCenter.x = dblScrVal + dblHorzOffset;
				ptCenter.y = rectAxis.bottom + dblVertOffset + szObjectSize.cy /2;
			}
		}

		if (pUsedAxis->IsVertical() && (ptCenter.y < rectAxis.top || ptCenter.y > rectAxis.bottom) || 
			!pUsedAxis->IsVertical() && (ptCenter.x < rectAxis.left || ptCenter.x > rectAxis.right))
		{
			return;
		}

		ptLeftTop.SetPoint(ptCenter.x - szObjectSize.cx / 2, ptCenter.y - szObjectSize.cy / 2);
		ptRightBottom.SetPoint(ptCenter.x + szObjectSize.cx / 2, ptCenter.y + szObjectSize.cy / 2);
	}
	else
	{
		return;
	}

	if (m_format.m_textFormat.IsWordWrap())
	{
		if (ptLeftTop.x == CBCGPChartObject::_EmptyCoordinate && 
			ptRightBottom.x == CBCGPChartObject::_EmptyCoordinate && 
			szObjectSize.cx == 0)
		{
			ASSERT(FALSE);
			TRACE0(" CBCGPChartObject::OnCalcScreenPoints: Left and right offsets must be specified in order to properly use wrapped text.\n");
			return;
		}

		szObjectSize = pGM->GetTextSize(m_strText, m_format.m_textFormat, ptRightBottom.x - ptLeftTop.x);
	}
	

	if (ptLeftTop.x == CBCGPChartObject::_EmptyCoordinate)
	{
		ptLeftTop.x = ptRightBottom.x - szObjectSize.cx;
	}

	if (ptLeftTop.y == CBCGPChartObject::_EmptyCoordinate)
	{
		ptLeftTop.y = ptRightBottom.y - szObjectSize.cy;
	}

	if (ptRightBottom.x == CBCGPChartObject::_EmptyCoordinate)
	{
		ptRightBottom.x = ptLeftTop.x + szObjectSize.cx;
	}

	if (ptRightBottom.y == CBCGPChartObject::_EmptyCoordinate)
	{
		ptRightBottom.y = ptLeftTop.y + szObjectSize.cy;
	}

	m_rectScreen.SetRect(ptLeftTop, ptRightBottom);
}
Exemplo n.º 4
0
//*******************************************************************************
void CBCGPKnob::CreatePointerPoints(double dblRadius,
                                    CBCGPPointsArray& arPoints,
                                    int nPointerIndex, BOOL bShadow)
{
    if (m_rect.IsRectEmpty())
    {
        return;
    }

    CBCGPRect rect = m_rect;

    CBCGPKnobPointer* pData = DYNAMIC_DOWNCAST(CBCGPKnobPointer, m_arData[nPointerIndex]);
    if (pData == NULL)
    {
        ASSERT(FALSE);
        return;
    }

    CBCGPCircularGaugeScale* pScale = GetScale(pData->GetScale());
    if (pScale == NULL)
    {
        ASSERT(FALSE);
        return;
    }

    const double scaleRatio = GetScaleRatioMid();

    double dblValue = pData->IsAnimated() ? pData->GetAnimatedValue() : pData->GetValue();

    double dblOffset = bcg_clamp(pData->GetOffsetFromCenter(), 0.0, 1.0);
    if (dblOffset == 0.0)
    {
        dblOffset = dblRadius * .5;
    }
    else
    {
        dblOffset = dblRadius * bcg_clamp(dblOffset, 0.5, 1.0);
    }

    double dblAngle = bcg_deg2rad(pScale->GetStartAngle()) - bcg_deg2rad(pScale->GetStartAngle() - pScale->GetFinishAngle()) * (dblValue - pScale->GetStart()) / (pScale->GetFinish() - pScale->GetStart());
    dblAngle = bcg_normalize_rad (dblAngle);

    if (bShadow)
    {
        rect.OffsetRect(2 * m_sizeScaleRatio.cx, 2 * m_sizeScaleRatio.cy);
    }

    CBCGPPoint center((rect.left + rect.right) / 2.0, (rect.top + rect.bottom) / 2.0);

    const double angleCos  = cos(dblAngle);
    const double angleSin  = sin(dblAngle);

    double dblWidth = bcg_clamp(pData->GetWidth(), 0.0, dblRadius / 10.0);
    const double dblPointerAngle = dblAngle - M_PI_2;

    switch (pData->GetStyle())
    {
    case CBCGPKnobPointer::BCGP_KNOB_POINTER_HANDLE:
    {
        dblRadius -= .2 * scaleRatio;
        double dblExtend = (dblRadius * .9);
        double dblSize = dblRadius + dblExtend;
        center.x -= angleCos * dblExtend;
        center.y += angleSin * dblExtend;

        if (dblWidth == 0.0)
        {
            dblWidth = dblRadius / 3.0;
        }

        dblWidth *= 0.5;

        if (dblWidth < 1.0)
        {
            arPoints.Add(center);

            arPoints.Add(CBCGPPoint(
                             center.x + angleCos * dblSize,
                             center.y - angleSin * dblSize));
        }
        else
        {
            double dblArrowLen = max(2.0 * dblWidth, 10.0 * scaleRatio);
            dblSize -= dblArrowLen;

            const double dx = cos(dblPointerAngle) * dblWidth;
            const double dy = -sin(dblPointerAngle) * dblWidth;

            arPoints.Add(CBCGPPoint(center.x + dx, center.y + dy));

            arPoints.Add(CBCGPPoint(center.x - dx, center.y - dy));

            const CBCGPPoint pt1(
                center.x + angleCos * dblSize - dx,
                center.y - angleSin * dblSize - dy);

            const CBCGPPoint pt2(
                center.x + angleCos * dblSize + dx,
                center.y - angleSin * dblSize + dy);

            arPoints.Add(pt1);

            arPoints.Add(CBCGPPoint(
                             center.x + angleCos * (dblSize + dblArrowLen),
                             center.y - angleSin * (dblSize + dblArrowLen)));

            arPoints.Add(pt2);
        }
    }
    break;

    case CBCGPKnobPointer::BCGP_KNOB_POINTER_LINE:
    {
        if (bShadow)
        {
            return;
        }

        if (dblWidth == 0.0)
        {
            dblWidth = 2. * scaleRatio;
        }

        const double dx = cos(dblPointerAngle) * dblWidth;
        const double dy = -sin(dblPointerAngle) * dblWidth;

        arPoints.Add(CBCGPPoint(center.x + angleCos * dblOffset - dx, center.y - angleSin * dblOffset - dy));
        arPoints.Add(CBCGPPoint(center.x + angleCos * dblOffset + dx, center.y - angleSin * dblOffset + dy));

        dblOffset = dblRadius - 4. * scaleRatio;

        arPoints.Add(CBCGPPoint(center.x + angleCos * dblOffset + dx, center.y - angleSin * dblOffset + dy));
        arPoints.Add(CBCGPPoint(center.x + angleCos * dblOffset - dx, center.y - angleSin * dblOffset - dy));
    }
    break;

    case CBCGPKnobPointer::BCGP_KNOB_POINTER_CIRCLE:
    {
        if (bShadow)
        {
            return;
        }

        if (dblWidth == 0.0)
        {
            dblWidth = max(2. * scaleRatio, dblRadius / 8);
        }

        dblOffset = dblRadius - 6. * scaleRatio - dblWidth;

        arPoints.Add(CBCGPPoint(center.x + angleCos * dblOffset, center.y - angleSin * dblOffset));
        arPoints.Add(CBCGPPoint(dblWidth, dblWidth));
    }
    break;
    }
}