コード例 #1
0
ファイル: VConText.cpp プロジェクト: Maximus5/ConEmu
// For proportional fonts, caller MUST already change widths of all chars
// (this->TempCharWidth) from ‘default’ to exact values returned by GDI
void CVConLine::PolishParts(DWORD* pnXCoords)
{
	if (!TextParts || !PartsCount)
	{
		_ASSERTE(TextParts && PartsCount);
		return;
	}

	#ifdef _DEBUG
	// Validate structure
	for (unsigned k = 0; k < PartsCount; k++)
	{
		_ASSERTE(TextParts[k].Flags != TRF_None);
		_ASSERTE(TextParts[k].Length > 0);
		_ASSERTE(TextParts[k].Chars && TextParts[k].Attrs && TextParts[k].CharFlags);
	}
	#endif

	// VirtualConsole has set proper character widths, adopt them
	TotalLineWidth = 0;
	for (unsigned k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];
		part.Done();
		TotalLineWidth += part.TotalWidth;
	}

	unsigned PosX, CharIdx;
	int prevFixedPart; // !SIGNED!

	// First, we need to check if part do not overlap
	// with *next* part, which may have *fixed* PosX
	PosX = 0; prevFixedPart = -1;
	for (unsigned k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];

		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
		{
			if (part.Flags & TRF_SizeFixed)
			{
				for (unsigned i = 0; i < part.Length; i++)
				{
					#define CellWidth FontWidth
					if (part.CharWidth[i] != CellWidth)
					{
						part.TotalWidth += (int)((int)CellWidth - (int)part.CharWidth[i]);
						part.CharWidth[i] = CellWidth;
					}
				}
			}
			// Overlaps? Or may be lesser?
			if (k && (part.PositionX != PosX))
			{
				_ASSERTE(k>0); // We can't get here for k==0
				if (k)
				{
					DistributeParts(prevFixedPart + 1, k - 1, part.PositionX);
				}
			}
			// Store updated coord
			prevFixedPart = k;
			PosX = part.PositionX + part.TotalWidth;
		}
		else
		{
			//if (part.Flags & TRF_SizeFree)
			//	TextParts[k-1].MinWidth = 1;
			part.PositionX = PosX;
			PosX += part.TotalWidth;
		}
	}
	// If last part does not end on screen edge - redistribute
	if (PosX != (TextWidth * FontWidth))
	{
		DistributeParts(prevFixedPart + 1, PartsCount - 1, (TextWidth * FontWidth));
	}


	/* Fill all X coordinates */
	PosX = CharIdx = 0;
	TotalLineWidth = 0;
	for (unsigned k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];
		_ASSERTE(part.Flags != TRF_None);
		_ASSERTE(((int)part.TotalWidth > 0) || (part.Flags & TRF_Cropped) || ((part.Length==1) && (part.CharFlags[0]==TCF_WidthZero)));

		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
		{
			_ASSERTE(PosX <= part.PositionX);
			if (k && PosX && PosX < part.PositionX)
				ExpandPart(TextParts[k-1], part.PositionX);
			PosX = part.PositionX;
		}
		else
		{
			part.PositionX = PosX;
		}
		TotalLineWidth += part.TotalWidth;

		unsigned charPosX = PosX;
		unsigned* ptrWidth = part.CharWidth;
		for (unsigned l = part.Length; l--; CharIdx++, ptrWidth++)
		{
			charPosX += *ptrWidth;
			pnXCoords[CharIdx] = charPosX;
		}

		PosX += part.TotalWidth;
		_ASSERTE(PosX >= charPosX);
	}

	//TODO: Optimization. Use linked-list for TextParts
	//TODO: we'll get memory gain and easy part deletion

	// Now we may combine all parts, which are displayed same style
	for (unsigned k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];
		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
			continue;

		const CharAttr attr = ConAttrLine[part.Index];

		if (!(part.Flags & TRF_TextSpacing))
		{
			_ASSERTE(TRF_CompareMask & TRF_TextAlternative);
			for (unsigned k2 = k+1; k2 < PartsCount; k2++)
			{
				VConTextPart& part2 = TextParts[k2];
				if (part2.Flags & (TRF_PosFixed|TRF_PosRecommended))
					break;
				WARNING("At the moment we do not care about CJK and RTL differences, unless TRF_TextAlternative is specified");
				// Let GDI deal with them, seems like it successfully
				// process strings, containing all types of characters
				if ((part.Flags & TRF_CompareMask) != (part2.Flags & TRF_CompareMask))
					break;
				if (!(attr == ConAttrLine[part2.Index]))
					break;
				part.Length += part2.Length;
				part.TotalWidth += part2.TotalWidth;
				// "Hide" this part from list
				part2.Flags = TRF_None;
				k = k2;
			}
		}
	}

	return;
}
コード例 #2
0
ファイル: VConText.cpp プロジェクト: MoroGasper/ConEmu
// For proportional fonts, caller MUST already change widths of all chars
// (this->TempCharWidth) from ‘default’ to exact values returned by GDI
void CVConLine::PolishParts(DWORD* pnXCoords)
{
	if (!TextParts || !PartsCount)
	{
		_ASSERTE(TextParts && PartsCount);
		return;
	}

	#ifdef _DEBUG
	// Validate structure
	for (uint k = 0; k < PartsCount; k++)
	{
		_ASSERTE(TextParts[k].Flags != TRF_None);
		_ASSERTE(TextParts[k].Length > 0);
		_ASSERTE(TextParts[k].Chars && TextParts[k].Attrs && TextParts[k].CharFlags);
	}
	#endif

	uint PosX, CharIdx;
	int prevFixedPart; // !SIGNED!

	// First, we need to check if part do not overlap
	// with *next* part, which may have *fixed* PosX
	PosX = 0; prevFixedPart = -1;
	for (uint k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];

		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
		{
			if (part.Flags & TRF_SizeFixed)
			{
				for (uint i = 0; i < part.Length; i++)
				{
					#define CellWidth FontWidth
					if (part.CharWidth[i] != CellWidth)
					{
						part.TotalWidth += (int)((int)CellWidth - (int)part.CharWidth[i]);
						part.CharWidth[i] = CellWidth;
					}
				}
			}
			// Overlaps?
			if (k && (part.PositionX != PosX))
			{
				_ASSERTE(k>0); // We can't get here for k==0
				if (k)
				{
					DistributeParts(prevFixedPart + 1, k - 1, part.PositionX);
				}
			}
			// Store updated coord
			prevFixedPart = k;
			PosX = part.PositionX + part.TotalWidth;
		}
		else
		{
			//if (part.Flags & TRF_SizeFree)
			//	TextParts[k-1].MinWidth = 1;
			part.PositionX = PosX;
			PosX += part.TotalWidth;
		}
	}
	// If last part goes out of screen - redistribute
	if (PosX != (TextWidth * FontWidth))
	{
		DistributeParts(prevFixedPart + 1, PartsCount - 1, (TextWidth * FontWidth));
	}


	/* Fill all X coordinates */
	PosX = CharIdx = 0;
	TotalLineWidth = MinLineWidth = 0;
	for (uint k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];
		_ASSERTE(part.Flags != TRF_None);
		_ASSERTE(((int)part.TotalWidth > 0) || ((part.Length==1) && (part.CharFlags[0]==TCF_WidthZero)));

		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
		{
			_ASSERTE(PosX <= part.PositionX);
			if (k && PosX && PosX < part.PositionX)
				ExpandPart(TextParts[k-1], part.PositionX);
			PosX = part.PositionX;
		}
		else
		{
			part.PositionX = PosX;
		}
		TotalLineWidth += part.TotalWidth;
		MinLineWidth += part.MinWidth;

		uint charPosX = PosX;
		uint* ptrWidth = part.CharWidth;
		for (uint l = part.Length; l--; CharIdx++, ptrWidth++)
		{
			charPosX += *ptrWidth;
			pnXCoords[CharIdx] = charPosX;
		}

		PosX += part.TotalWidth;
		_ASSERTE(PosX >= charPosX);
	}

	//TODO: Optimization. Use linked-list for TextParts
	//TODO: we'll get memory gain and easy part deletion

	// Now we may combine all parts, which are displayed same style
	for (uint k = 0; k < PartsCount; k++)
	{
		VConTextPart& part = TextParts[k];
		if (part.Flags & (TRF_PosFixed|TRF_PosRecommended))
			continue;

		const CharAttr attr = ConAttrLine[part.Index];

		if (part.Flags & TRF_TextAlternative)
		{
			for (uint k2 = k+1; k2 < PartsCount; k2++)
			{
				VConTextPart& part2 = TextParts[k2];
				if ((part2.Flags & (TRF_PosFixed|TRF_PosRecommended))
					|| !(part2.Flags & TRF_TextAlternative))
					break;
				if (!(attr == ConAttrLine[part2.Index]))
					break;
				part.Length += part2.Length;
				part.TotalWidth += part2.TotalWidth;
				part.MinWidth += part2.MinWidth;
				// "Hide" this part from list
				part2.Flags = TRF_None;
				k = k2;
			}
		}
		else if (!(part.Flags & TRF_TextSpacing))
		{
			for (uint k2 = k+1; k2 < PartsCount; k2++)
			{
				VConTextPart& part2 = TextParts[k2];
				if ((part2.Flags & (TRF_PosFixed|TRF_PosRecommended|TRF_TextAlternative)))
					break;
				if (!(attr == ConAttrLine[part2.Index]))
					break;
				part.Length += part2.Length;
				part.TotalWidth += part2.TotalWidth;
				part.MinWidth += part2.MinWidth;
				// "Hide" this part from list
				part2.Flags = TRF_None;
				k = k2;
			}
		}
	}

	return;
}