示例#1
0
文件: FontPtr.cpp 项目: 2asoft/ConEmu
int CFontPtr::Release()
{
	CFont* p = NULL;
	klSwap(p, mp_Ref);
	int iRef = p ? p->Release() : 0;
	return iRef;
}
示例#2
0
文件: FontPtr.cpp 项目: 2asoft/ConEmu
bool CFontPtr::Attach(CFont* apRef)
{
	if (apRef != mp_Ref)
	{
		klSwap(mp_Ref, apRef);
		if (mp_Ref)
			mp_Ref->AddRef();
		SafeRelease(apRef);
	}

	return (mp_Ref != NULL);
}
示例#3
0
// Shrink lengths of [part1..part2] (including)
// They must not exceed `right` X coordinate
void CVConLine::DistributeParts(uint part1, uint part2, uint right)
{
	if ((part1 > part2) || (part2 >= PartsCount))
	{
		_ASSERTE((part1 <= part2) && (part2 < PartsCount));
		return;
	}

	// If possible - shrink only last part
	// TRF_SizeFree - Spaces or horizontal frames. It does not matter, how many *real* characters we may write
	if ((TextParts[part2].Flags & TRF_SizeFree)
		&& ((TextParts[part2].PositionX + MIN_SIZEFREE_WIDTH) < right)
		)
		part1 = part2;

	if (right <= TextParts[part1].PositionX)
	{
		_ASSERTE(right > TextParts[part1].PositionX);
		return;
	}

	const uint suggMul = 4, suggDiv = 5;
	uint FontWidth2 = (FontWidth * 2);
	uint FontWidth2m = (FontWidth2 * suggMul / suggDiv);
	uint ReqWidth = (right - TextParts[part1].PositionX);

	// unused?
	uint FullWidth = (TextParts[part2].PositionX + TextParts[part2].TotalWidth - TextParts[part1].PositionX);

	// 1) shrink only TCF_WidthFree chars
	// 2) also shrink TCF_WidthDouble (if exist) a little
	// 3) shrink all possibilities

	WARNING("Change the algorithm");
	// a) count all TCF_WidthFree, TCF_WidthNormal, TCF_WidthDouble separatedly
	// b) so we able to find most suitable way to shrink either part with its own factor (especially useful when both CJK and single-cell chars exists)

	VConTextPartWidth AllWidths[TCF_WidthLast] = {};

	// Count all widths for parts and check if we may do shrink with TCF_WidthFree chars only
	bool bHasFreeOverlaps = HasFreeOverlaps(part1, part2, right, AllWidths);

	uint nAllWidths = (AllWidths[TCF_WidthFree].Width + AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthDouble].Width);
	_ASSERTE(nAllWidths == FullWidth); // At the moment, they must match

	// What we may to shrink?
	if (nAllWidths <= ReqWidth)
	{
		if ((nAllWidths != ReqWidth) && !bHasFreeOverlaps)
		{
			DistributePartsFree(part1, part2, right);
		}
		else
		{
			_ASSERTE(FALSE && "Already fit, nothing to shrink");
		}
		return;
	}

	// Only spaces and horizontal frames
	if (!bHasFreeOverlaps
		&& ((AllWidths[TCF_WidthFree].MinWidth + AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthDouble].Width) <= ReqWidth)
		)
	{
		DistributePartsFree(part1, part2, right);
		return;
	}

	uint nAllMin = AllWidths[TCF_WidthFree].MinWidth + AllWidths[TCF_WidthNormal].MinWidth + AllWidths[TCF_WidthDouble].MinWidth;
	if (!nAllMin)
	{
		_ASSERTE(nAllMin!=NULL); // Must not be zero!
		return;
	}

	// method and options
	uint nShrinkParts = (1 << TCF_WidthFree);

	if ((AllWidths[TCF_WidthFree].MinWidth + AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthDouble].Width) <= ReqWidth)
	{
		AllWidths[TCF_WidthFree].ReqWidth = ReqWidth - (AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthDouble].Width);
	}
	else if ((AllWidths[TCF_WidthFree].MinWidth + AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthDouble].MinWidth) <= ReqWidth)
	{
		// Spaces and double-space glyphs
		// Actually, with monospaced fonts we would have fit problems,
		// when double-space glyphs takes only one cell in console.
		// That is non-DBCS systems or UTF-8(?) on DBCS system
		nShrinkParts |= (1 << TCF_WidthDouble);
		AllWidths[TCF_WidthFree].ReqWidth = AllWidths[TCF_WidthFree].MinWidth;
		AllWidths[TCF_WidthDouble].ReqWidth = ReqWidth - (AllWidths[TCF_WidthNormal].Width + AllWidths[TCF_WidthFree].ReqWidth);
	}
	else
	{
		// Shrink all types
		nShrinkParts |= (1 << TCF_WidthNormal) | (1 << TCF_WidthDouble);

		// And we may apply a larger coefficient to dominating type of chars

		// Count each double-space glyph as 2 cells (preferred)
		AllWidths[TCF_WidthDouble].Count *= 2;
		// Count "all" cells
		int nAllCells = AllWidths[TCF_WidthDouble].Count + AllWidths[TCF_WidthNormal].Count + AllWidths[TCF_WidthFree].Count;

		// Sort types by cells used
		uint nMost = TCF_WidthFree;
		if ((AllWidths[TCF_WidthDouble].Count >= AllWidths[TCF_WidthNormal].Count) && (AllWidths[TCF_WidthDouble].Count >= AllWidths[TCF_WidthFree].Count))
			nMost = TCF_WidthDouble;
		else if ((AllWidths[TCF_WidthNormal].Count >= AllWidths[TCF_WidthDouble].Count) && (AllWidths[TCF_WidthNormal].Count >= AllWidths[TCF_WidthFree].Count))
			nMost = TCF_WidthNormal;
		uint nOther1 = (nMost != TCF_WidthDouble) ? TCF_WidthDouble : TCF_WidthNormal;
		uint nFlags = (1 << nMost) | (1 << nOther1);
		uint nOther2 = (!(nFlags & (1 << TCF_WidthDouble))) ? TCF_WidthDouble
			: (!(nFlags & (1 << TCF_WidthNormal))) ? TCF_WidthNormal
			: TCF_WidthFree;
		if (AllWidths[nOther1].Count < AllWidths[nOther2].Count)
			klSwap(nOther1, nOther2);

		uint nMostMul = (nMost == TCF_WidthDouble) ? 9 : 10;
		uint nMostDiv = 10;

		// Apply denominators
		AllWidths[nMost].ReqWidth = ReqWidth * AllWidths[nMost].Count * nMostMul / (nAllCells * nMostDiv);
		_ASSERTE(AllWidths[nMost].ReqWidth <= ReqWidth);

		// And prepare lesser types
		if ((ReqWidth - AllWidths[nMost].ReqWidth) >= (AllWidths[nOther1].Width + AllWidths[nOther2].MinWidth))
		{
			AllWidths[nOther1].ReqWidth = AllWidths[nOther1].Width;
			AllWidths[nOther2].ReqWidth = ReqWidth - (AllWidths[nMost].ReqWidth + AllWidths[nOther1].ReqWidth);
		}
		else if (AllWidths[nOther1].Count > 0 && AllWidths[nOther2].Count > 0)
		{
			_ASSERTE(AllWidths[nMost].Count > 0);
			AllWidths[nOther1].ReqWidth = ReqWidth * AllWidths[nOther1].Count / nAllCells;
			AllWidths[nOther2].ReqWidth = ReqWidth - (AllWidths[nMost].ReqWidth + AllWidths[nOther1].ReqWidth);
		}
		else if (AllWidths[nOther1].Count > 0)
		{
			_ASSERTE(AllWidths[nMost].Count > 0 && AllWidths[nOther2].Count == 0);
			AllWidths[nOther1].ReqWidth = ReqWidth - (AllWidths[nMost].ReqWidth);
			_ASSERTE(AllWidths[nOther2].Width == 0);
			AllWidths[nOther2].ReqWidth = 0;
		}
		else
		{
			_ASSERTE(AllWidths[nMost].Count > 0 && AllWidths[nOther1].Count == 0 && AllWidths[nOther2].Count == 0);
			_ASSERTE(AllWidths[nOther1].Width == 0 && AllWidths[nOther2].Width == 0);
			AllWidths[nOther1].ReqWidth = AllWidths[nOther2].ReqWidth = 0;
		}
		// Return *char* count
		AllWidths[TCF_WidthDouble].Count /= 2;
	}

	// Debug validations
	_ASSERTE((int)AllWidths[TCF_WidthFree].ReqWidth >= 0);
	_ASSERTE((int)AllWidths[TCF_WidthNormal].ReqWidth >= 0);
	_ASSERTE((int)AllWidths[TCF_WidthDouble].ReqWidth >= 0);

	// *Process* the shrink

	// Leftmost char coord
	uint PosX = TextParts[part1].PositionX;

	for (uint k = part1; k <= part2; k++)
	{
		VConTextPart& part = TextParts[k];
		if (!part.Flags)
		{
			_ASSERTE(part.Flags); // Part must not be dropped yet!
			continue;
		}

		// Update new leftmost coord for this part
		part.PositionX = PosX;

		// Prepare loops
		TextCharType* pcf = part.CharFlags; // character flags (zero/free/normal/double)
		uint* pcw = part.CharWidth; // pointer to character width

		// Run part shrink
		part.TotalWidth = 0;
		if ((part.Flags & TRF_SizeFree) && (nShrinkParts & (1 << TCF_WidthFree)))
		{
			VConTextPartWidth& aw = AllWidths[TCF_WidthFree];
			int iShrinkLeft = part.Length;
			_ASSERTE(AllWidths[TCF_WidthFree].Count>0);
			uint partReqWidth = (AllWidths[TCF_WidthFree].Count > 0) ? (aw.ReqWidth / AllWidths[TCF_WidthFree].Count) : 0;
			for (uint c = 0; c < part.Length; c++, pcf++, pcw++)
			{
				_ASSERTE(*pcf == TCF_WidthFree);
				DoShrink(*pcw, iShrinkLeft, partReqWidth, part.TotalWidth);
			}
		}
		else
		{
			for (uint c = 0; c < part.Length; c++, pcf++, pcw++)
			{
				if (nShrinkParts & (1 << *pcf))
				{
					VConTextPartWidth& aw = AllWidths[*pcf];
					DoShrink(*pcw, aw.Count, aw.ReqWidth, part.TotalWidth);
				}
				else
				{
					part.TotalWidth += *pcw;
				}
			}
		}

		PosX += part.TotalWidth;
	}

	// End of shrink (no more parts, no more methods)
	_ASSERTE(PosX <= right);
}