<commit_before>#include "stdafx.h"
#include "GdiPlusLabelDrawer.h"
#include "UtilityFunctions.h"

using namespace Gdiplus;

// *********************************************************************
// 			InitGraphics()										
// *********************************************************************
void GdiPlusLabelDrawer::InitGraphics(Gdiplus::Graphics* g, ILabels* labels)
{
	_graphics = g;
	
	_compositingQuality = _graphics->GetCompositingQuality();
	_smoothingMode = _graphics->GetSmoothingMode();
	_textRenderingHint = _graphics->GetTextRenderingHint();

	tkTextRenderingHint textRenderingHint;
	labels->get_TextRenderingHint(&textRenderingHint);

	tkSmoothingMode smoothingMode = m_globalSettings.labelsSmoothingMode;
	tkCompositingQuality compositingQuality = m_globalSettings.labelsCompositingQuality;

	_graphics->SetCompositingQuality((CompositingQuality)compositingQuality);
	_graphics->SetSmoothingMode((SmoothingMode)smoothingMode);
	_graphics->SetTextRenderingHint((TextRenderingHint)textRenderingHint);
	_graphics->SetTextContrast(0u);
}

// *********************************************************************
// 			RestoreGraphics()										
// *********************************************************************
void GdiPlusLabelDrawer::RestoreGraphics()
{
	_graphics->SetCompositingQuality(_compositingQuality);
	_graphics->SetSmoothingMode(_smoothingMode);
	_graphics->SetTextRenderingHint(_textRenderingHint);
}

// *********************************************************************
// 					InitFromCategory()										
// *********************************************************************
void GdiPlusLabelDrawer::InitFromCategory(CLabelOptions* options, bool hasRotation)
{
	InitPensAndBrushes(options, hasRotation);

	TryAutoSetRenderingHint(options, hasRotation);
}

// *********************************************************************
// 					InitPensAndBrushes()										
// *********************************************************************
void GdiPlusLabelDrawer::InitPensAndBrushes(CLabelOptions* options, bool hasRotation)
{
	long alphaFont = (options->fontTransparency << 24);
	long alphaFrame = (options->frameTransparency << 24);

	_clFont1 = Utility::OleColor2GdiPlus(options->fontColor, options->fontTransparency);
	_clFont2 = Utility::OleColor2GdiPlus(options->fontColor2, options->fontTransparency);

	_clFrameBack1.SetValue(alphaFrame | BGR_TO_RGB(options->frameBackColor));
	_clFrameBack2.SetValue(alphaFrame | BGR_TO_RGB(options->frameBackColor2));

	_penFontOutline = new Pen(Color(alphaFont | BGR_TO_RGB(options->fontOutlineColor)), (Gdiplus::REAL)options->fontOutlineWidth);
	_penFontOutline->SetLineJoin(LineJoinRound);

	double haloWidth = fabs(options->fontSize / 16.0 * options->haloSize);
	_penHalo = new Pen(Color(alphaFont | BGR_TO_RGB(options->haloColor)), (Gdiplus::REAL)haloWidth);
	_penHalo->SetLineJoin(LineJoinRound);

	_penFrameOutline = new Pen(Color(alphaFrame | BGR_TO_RGB(options->frameOutlineColor)), (Gdiplus::REAL)options->frameOutlineWidth);
	_penFrameOutline->SetDashStyle(DashStyle(options->frameOutlineStyle));

	_brushFont = new SolidBrush(_clFont1);
	_brushFrame = new SolidBrush(_clFrameBack1);
	_brushShadow = new SolidBrush(Color(alphaFont | BGR_TO_RGB(options->shadowColor)));

	ConvertAlignment(options->inboxAlignment, stringFormat);

	stringFormat.SetFormatFlags(StringFormatFlagsNoClip);	// doesn't work?
}

// *********************************************************************
// 					TryAutoSetRenderingHint()										
// *********************************************************************
void GdiPlusLabelDrawer::TryAutoSetRenderingHint(CLabelOptions* options, bool hasRotation)
{
	if (m_globalSettings.autoChooseRenderingHintForLabels)
	{
		Gdiplus::TextRenderingHint hint = TextRenderingHintSingleBitPerPixelGridFit;
		if (hasRotation)
		{
			if (options->frameVisible && options->frameTransparency == 255) {
				hint = TextRenderingHintClearTypeGridFit;
			}
			else {
				hint = TextRenderingHintAntiAlias;
			}

		}
		_graphics->SetTextRenderingHint(hint);
	}
}

// *********************************************************************
// 					DrawLabel()										
// *********************************************************************
void GdiPlusLabelDrawer::DrawLabel(CLabelOptions* options, CRect& r, double piX, double piY, double angle)
{
	rect.X = (Gdiplus::REAL)r.left;
	rect.Y = (Gdiplus::REAL)r.top;
	rect.Width = (Gdiplus::REAL)r.Width();
	rect.Height = (Gdiplus::REAL)r.Height();

	Gdiplus::Matrix mtxInit;
	_graphics->GetTransform(&mtxInit);

	//Gdiplus::Matrix mtx;
	//mtx.Translate((Gdiplus::REAL)piX, (Gdiplus::REAL)piY);
	//mtx.Rotate((Gdiplus::REAL)angle);
	//_graphics->SetTransform(&mtx);

	_graphics->TranslateTransform((Gdiplus::REAL)piX, (Gdiplus::REAL)piY);
	_graphics->RotateTransform((Gdiplus::REAL)angle);

	// drawing frame
	if (options->frameTransparency != 0 && options->frameVisible)
	{
		if (options->frameGradientMode != gmNone)
		{
			_brushFrameGrad = new LinearGradientBrush(rect, _clFrameBack1, _clFrameBack2, (LinearGradientMode)options->frameGradientMode);
			DrawLabelFrame(_brushFrameGrad, *_penFrameOutline, options);
			delete _brushFrameGrad;
		}
		else
		{
			DrawLabelFrame(_brushFrame, *_penFrameOutline, options);
		}
	}

	if (options->fontTransparency != 0)
	{
		bool pathNeeded = options && (options->shadowVisible || options->haloVisible || options->fontOutlineVisible);
		GraphicsPath* gp = NULL;
		if (pathNeeded)
		{
			gp = new GraphicsPath();
			gp->StartFigure();
			FontFamily fam;
			font->GetFamily(&fam);
			gp->AddString(text, text.GetLength(), &fam, font->GetStyle(), font->GetSize(), rect, &stringFormat);
			gp->CloseFigure();
		}

		// drawing outlines
		if (options->shadowVisible)
		{
			//Gdiplus::Matrix mtx1;
			//mtx1.Translate((Gdiplus::REAL)options->shadowOffsetX, (Gdiplus::REAL)options->shadowOffsetY);
			//gp->Transform(&mtx1);
			//_graphics->FillPath(_brushShadow, gp);
			//mtx1.Translate(Gdiplus::REAL(-2 * options->shadowOffsetX), Gdiplus::REAL(-2 * options->shadowOffsetY));
			//gp->Transform(&mtx1);

			// jfaust: The FillPath calls used for Halo, Outline, and Shadow are not properly filling the full area.
			// for shadowing, we don't need the fill, so I am using the concept borrowed from DrawStringWithShade()
			// (which is used to draw the coordinates in the upper corner of the map).  I will revisit the FillPath
			// option for Halo and Outline affects, but for now, I wanted to at least get the Shadow working.
			_graphics->DrawString(text, text.GetLength(), font, rect, &stringFormat, _brushShadow);
			rect.X -= 1.0f;
			rect.Y -= 1.0f;
			// foreground text will be drawn below, as it is for all affects (so as not to alter previous behavior)
		}

		if (options && options->haloVisible)
			_graphics->DrawPath(_penHalo, gp);

		if (options->fontOutlineVisible)<commit_msg>MWGIS-74: Proper alignment of font Halo, Shadow, and Outline when using GDI+ labeling<commit_after>#include "stdafx.h"
#include "GdiPlusLabelDrawer.h"
#include "UtilityFunctions.h"

using namespace Gdiplus;

// *********************************************************************
// 			InitGraphics()										
// *********************************************************************
void GdiPlusLabelDrawer::InitGraphics(Gdiplus::Graphics* g, ILabels* labels)
{
	_graphics = g;
	
	_compositingQuality = _graphics->GetCompositingQuality();
	_smoothingMode = _graphics->GetSmoothingMode();
	_textRenderingHint = _graphics->GetTextRenderingHint();

	tkTextRenderingHint textRenderingHint;
	labels->get_TextRenderingHint(&textRenderingHint);

	tkSmoothingMode smoothingMode = m_globalSettings.labelsSmoothingMode;
	tkCompositingQuality compositingQuality = m_globalSettings.labelsCompositingQuality;

	_graphics->SetCompositingQuality((CompositingQuality)compositingQuality);
	_graphics->SetSmoothingMode((SmoothingMode)smoothingMode);
	_graphics->SetTextRenderingHint((TextRenderingHint)textRenderingHint);
	_graphics->SetTextContrast(0u);
}

// *********************************************************************
// 			RestoreGraphics()										
// *********************************************************************
void GdiPlusLabelDrawer::RestoreGraphics()
{
	_graphics->SetCompositingQuality(_compositingQuality);
	_graphics->SetSmoothingMode(_smoothingMode);
	_graphics->SetTextRenderingHint(_textRenderingHint);
}

// *********************************************************************
// 					InitFromCategory()										
// *********************************************************************
void GdiPlusLabelDrawer::InitFromCategory(CLabelOptions* options, bool hasRotation)
{
	InitPensAndBrushes(options, hasRotation);

	TryAutoSetRenderingHint(options, hasRotation);
}

// *********************************************************************
// 					InitPensAndBrushes()										
// *********************************************************************
void GdiPlusLabelDrawer::InitPensAndBrushes(CLabelOptions* options, bool hasRotation)
{
	long alphaFont = (options->fontTransparency << 24);
	long alphaFrame = (options->frameTransparency << 24);

	_clFont1 = Utility::OleColor2GdiPlus(options->fontColor, options->fontTransparency);
	_clFont2 = Utility::OleColor2GdiPlus(options->fontColor2, options->fontTransparency);

	_clFrameBack1.SetValue(alphaFrame | BGR_TO_RGB(options->frameBackColor));
	_clFrameBack2.SetValue(alphaFrame | BGR_TO_RGB(options->frameBackColor2));

	_penFontOutline = new Pen(Color(alphaFont | BGR_TO_RGB(options->fontOutlineColor)), (Gdiplus::REAL)options->fontOutlineWidth);
	_penFontOutline->SetLineJoin(LineJoinRound);

	double haloWidth = fabs(options->fontSize / 16.0 * options->haloSize);
	_penHalo = new Pen(Color(alphaFont | BGR_TO_RGB(options->haloColor)), (Gdiplus::REAL)haloWidth);
	_penHalo->SetLineJoin(LineJoinRound);

	_penFrameOutline = new Pen(Color(alphaFrame | BGR_TO_RGB(options->frameOutlineColor)), (Gdiplus::REAL)options->frameOutlineWidth);
	_penFrameOutline->SetDashStyle(DashStyle(options->frameOutlineStyle));

	_brushFont = new SolidBrush(_clFont1);
	_brushFrame = new SolidBrush(_clFrameBack1);
	_brushShadow = new SolidBrush(Color(alphaFont | BGR_TO_RGB(options->shadowColor)));

	ConvertAlignment(options->inboxAlignment, stringFormat);

	stringFormat.SetFormatFlags(StringFormatFlagsNoClip);	// doesn't work?
}

// *********************************************************************
// 					TryAutoSetRenderingHint()										
// *********************************************************************
void GdiPlusLabelDrawer::TryAutoSetRenderingHint(CLabelOptions* options, bool hasRotation)
{
	if (m_globalSettings.autoChooseRenderingHintForLabels)
	{
		Gdiplus::TextRenderingHint hint = TextRenderingHintSingleBitPerPixelGridFit;
		// JIRA MWGIS-74: not only rotation, but GraphicsPath-related functions also require AntiAliasing
		if (hasRotation || options->shadowVisible || options->haloVisible || options->fontOutlineVisible)
		{
			if (options->frameVisible && options->frameTransparency == 255) {
				hint = TextRenderingHintClearTypeGridFit;
			}
			else {
				hint = TextRenderingHintAntiAlias;
			}

		}
		_graphics->SetTextRenderingHint(hint);
	}
}

// *********************************************************************
// 					DrawLabel()										
// *********************************************************************
void GdiPlusLabelDrawer::DrawLabel(CLabelOptions* options, CRect& r, double piX, double piY, double angle)
{
	rect.X = (Gdiplus::REAL)r.left;
	rect.Y = (Gdiplus::REAL)r.top;
	rect.Width = (Gdiplus::REAL)r.Width();
	rect.Height = (Gdiplus::REAL)r.Height();

	Gdiplus::Matrix mtxInit;
	_graphics->GetTransform(&mtxInit);

	//Gdiplus::Matrix mtx;
	//mtx.Translate((Gdiplus::REAL)piX, (Gdiplus::REAL)piY);
	//mtx.Rotate((Gdiplus::REAL)angle);
	//_graphics->SetTransform(&mtx);

	_graphics->TranslateTransform((Gdiplus::REAL)piX, (Gdiplus::REAL)piY);
	_graphics->RotateTransform((Gdiplus::REAL)angle);

	// drawing frame
	if (options->frameTransparency != 0 && options->frameVisible)
	{
		if (options->frameGradientMode != gmNone)
		{
			_brushFrameGrad = new LinearGradientBrush(rect, _clFrameBack1, _clFrameBack2, (LinearGradientMode)options->frameGradientMode);
			DrawLabelFrame(_brushFrameGrad, *_penFrameOutline, options);
			delete _brushFrameGrad;
		}
		else
		{
			DrawLabelFrame(_brushFrame, *_penFrameOutline, options);
		}
	}

	if (options->fontTransparency != 0)
	{
		bool pathNeeded = options && (options->shadowVisible || options->haloVisible || options->fontOutlineVisible);
		GraphicsPath* gp = NULL;
		if (pathNeeded)
		{
			gp = new GraphicsPath();
			gp->StartFigure();
			FontFamily fam;
			font->GetFamily(&fam);
			// JIRA MWGIS-74: GraphicsPath font units are 'em's rather than Points
			Gdiplus::REAL factor = _graphics->GetDpiX() / 72; // 4.0 / 3.0;
			gp->AddString(text, text.GetLength(), &fam, font->GetStyle(), (font->GetSize() * factor), rect, &stringFormat);
			gp->CloseFigure();
		}

		// drawing outlines
		if (options->shadowVisible)
		{
			Gdiplus::Matrix mtx1;
			mtx1.Translate((Gdiplus::REAL)options->shadowOffsetX, (Gdiplus::REAL)options->shadowOffsetY);
			gp->Transform(&mtx1);
			_graphics->FillPath(_brushShadow, gp);
			mtx1.Translate(Gdiplus::REAL(-1 * options->shadowOffsetX), Gdiplus::REAL(-1 * options->shadowOffsetY));
			gp->Transform(&mtx1);
		}

		if (options && options->haloVisible)
			_graphics->DrawPath(_penHalo, gp);

		if (options->fontOutlineVisible)
{'fraction_non_alphanumeric': 0.236707831102566, 'fraction_numerical': 0.005915847075353102, 'mean_word_length': 6.45945945945946, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 136, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2536644', 'n_tokens_mistral': 4571, 'n_tokens_neox': 4034, 'n_words': 631}