⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scdcrendtexts_i.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	// Update current position
	if (bUpdatingPos)
	{
		m_PtCurPos.X = (INT)positions[uiCount-1].X;
		m_PtCurPos.Y = (INT)positions[uiCount-1].Y;
		switch (m_dwTextAlign & (TA_TOP|TA_BASELINE|TA_BOTTOM))
		{
		case TA_BASELINE:
			// do nothing
			break;

		case TA_TOP:
			// We must shift up from base line to top.
			m_PtCurPos.Y -= itmAscent;
			break;
			
		case TA_BOTTOM:
			// We must shift down from base line to bottom.
			m_PtCurPos.Y += m_pFont->SCGetDescent();
			break;
		}

		m_PtCurPos.X += (INT)LastChSize.Width;
	}

	delete [] positions;
	// restore transformation
	if (bRestoreMat)
		m_pGraphics->SetTransform(&svdMatrix);
	if (uiOptions & ETO_CLIPPED)
		m_pGraphics->SetClip(&ClipRgn);
}

///
///	Add a text to the current path.
///
void CSCEMFdcRenderer::SCAddTextInPath(INT x, INT y, UINT uiOptions, LPCRECT pRect, LPCWSTR pwString,
								UINT uiCount, LPCINT pDxWidths, FLOAT fScaleX, FLOAT fScaleY)
{
	ASSERT(m_pGraphics);
	ASSERT(m_pPath);
	ASSERT(m_pFont);

	// String's reference point
	POINT PtRef;
	BOOL bUpdatingPos = (TA_UPDATECP == (m_dwTextAlign & (TA_NOUPDATECP|TA_UPDATECP)));
	if (bUpdatingPos)
	{
		// We must update/use current position.
		PtRef.x = m_PtCurPos.X;
		PtRef.y = m_PtCurPos.Y;
	} else
	{
		// TA_NOUPDATECP: use the passed-on point
		PtRef.x = x;
		PtRef.y = y;
	}
	INT flags = DriverStringOptionsCmapLookup;
	if (uiOptions & ETO_GLYPH_INDEX)
	{
		flags = 0;
		// TODO: AddString is unaware of ETO_GLYPH_INDEX
	}

	// Save last char size and text's vertical extent
	RectF LastChSize;
	Matrix matrix;
	{
		PointF PtDummy(0, 0); // cause we don't know if the corresponding parameter can be NULL
		Status Res = m_pGraphics->MeasureDriverString((pwString + uiCount - 1), 1, m_pFont,
			&PtDummy, flags, &matrix, &LastChSize);
	}

	// Compute text horizontal extent
	RectF TextSize;
	TextSize.Height = LastChSize.Height;
	TextSize.Width = (REAL)SCComputeTextWidth(pwString, uiCount, pDxWidths, flags);

	SCRectPolygon BoundingPoly;
	INT itmAscent = m_pFont->SCGetAscent();
	SCComputeTextBBox(m_dwTextAlign, TextSize, BoundingPoly, PtRef, itmAscent);

	// Compute placements for (left,top) glyph positioning
	// Glyph's vertical alignment (we can't use StringFormat to do it)
	INT iYPos = PtRef.y;
	switch (m_dwTextAlign & SC_VTXTALIGN_MASK)
	{
	case TA_BASELINE:
		iYPos -= itmAscent; // AddString uses (left,top) alignment
		break;

	case TA_TOP:
		// Do nothing.
		break;
		
	case TA_BOTTOM:
		// We must shitf up.
		iYPos -= m_pFont->SCGetDescent() + itmAscent;
		break;
	}

	// Glyph's horizontal alignment
	REAL fXPos = (REAL)PtRef.x;
	switch (m_dwTextAlign & SC_HTXTALIGN_MASK)
	{
	case TA_LEFT:
		break;
		
	case TA_CENTER:
		fXPos -= TextSize.Width / 2; 
		break;
		
	case TA_RIGHT:
		fXPos -= TextSize.Width;
		break;
	}
#if 1
	// TODO: explain why the text is shifted by (tm.tmInternalLeading + tm.tmExternalLeading)
	fXPos -= m_pFont->SCGetInterExternal();
	// I know, this is really unacceptable code! Sorry for the inconvenience.
#endif

	// Compute characters' horizontal placements
	PointF* positions = new PointF[uiCount];
	for (UINT j = 0; (j < uiCount); j++)
	{
		positions[j].X = fXPos;
		positions[j].Y = (REAL)iYPos;
		fXPos += pDxWidths[j];
	}

	GraphicsPath* pPath = (GraphicsPath*)m_pPath;
	// if local transformations are required, we will use a sub path to hold them
	float fxRatio = (float)(fabs(fScaleY)/fabs(fScaleX));
	INT iFontAngle = m_pFont->SCGetAngle();
	BOOL bSubPath = ((iFontAngle!=0) || (fScaleX<0) || (fScaleY<0) || (fxRatio!=1));
	if (bSubPath)
	{
		pPath = new GraphicsPath;
	}

	// Can't use AddString if we don't have FontFamily, emSize, etc... Are you kidding?
	// Can't do: pPath->AddString((WCHAR*)pwString, (INT)uiCount, m_pFont, ...);
	FontFamily family;
	m_pFont->GetFamily(&family);
	REAL emSize = m_pFont->GetSize();
	INT style = m_pFont->GetStyle();
	DWORD dwFontSimul = m_pFont->SCGetSimulStatus();
	if (dwFontSimul & SC_FONT_SIMUL_UNDERLINE)
		style |= FontStyleUnderline;
	if (dwFontSimul & SC_FONT_SIMUL_OVERSTRIKE)
		style |= FontStyleStrikeout;

	// GDI+1.0 can't position characters in path. 
	// Good place to say: GDI+ does not work!
	// Try doing it one character at a time (but the ETO_GLYPH_INDEX problem still remains)
	for (UINT i=0; (i<uiCount); i++)
	{
		pPath->AddString(pwString+i, 1, &family,
			style, emSize, positions[i], NULL);
	}

#ifdef SC_SHOW_BBOX
	{// Debug stuff
		pPath->StartFigure();
		pPath->AddLines((const Point*)&BoundingPoly.m_Points, 4);
		pPath->CloseFigure();
	}
#endif

	// Transformations (Documentation in SCDrawText)
	if (bSubPath)
	{
		Matrix pathMat;
		// rotate
		if (iFontAngle)
		{
			pathMat.Translate((REAL)PtRef.x, (REAL)PtRef.y);
			pathMat.Rotate(-iFontAngle/10.0f);
			pathMat.Translate(-(REAL)PtRef.x, -(REAL)PtRef.y);
		}

		// reflect
		if (fScaleY<0)
		{// Vertical reflection
			XFORM xform;
			switch (m_dwTextAlign & SC_VTXTALIGN_MASK)
			{
			case TA_BASELINE:
				BoundingPoly.SCComputeReflectionBase(xform, itmAscent);
				break;
				
			case TA_TOP:
				BoundingPoly.SCComputeReflectionTop(xform);
				break;
				
			case TA_BOTTOM:
				BoundingPoly.SCComputeReflectionBottom(xform);
				break;
			}
			
			Matrix MatReflect(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
			pathMat.Multiply(&MatReflect);
		}
		if (fScaleX<0)
		{// Horizontal reflection
			XFORM xform;
			switch (m_dwTextAlign & SC_HTXTALIGN_MASK)
			{
			case TA_LEFT:
				BoundingPoly.SCComputeReflectionLeft(xform);
				break;
				
			case TA_CENTER:
				// TODO: Reflect about the center
				//
				break;
				
			case TA_RIGHT:
				BoundingPoly.SCComputeReflectionRight(xform);
				break;
			}
			
			Matrix MatReflect(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
			pathMat.Multiply(&MatReflect);
		}
		// scale
		if (fxRatio!=1)
		{
			pathMat.Translate(PtRef.x*(1 - fxRatio), 0);
			pathMat.Scale(fxRatio, 1);
		}
		// clip
		// TODO: if ETO_CLIPPED is set, we should clip the path.
		// pPath->Intersect(ClipRect);

		// transform and add
		pPath->Transform(&pathMat);
		m_pPath->AddPath(pPath, FALSE);
	}

	// Update current position? (Don't know what GDI would do)
	if (bUpdatingPos)
	{
		m_PtCurPos.X = (INT)positions[uiCount-1].X;
		m_PtCurPos.Y = (INT)positions[uiCount-1].Y;
		switch (m_dwTextAlign & (TA_TOP|TA_BASELINE|TA_BOTTOM))
		{
		case TA_BASELINE:
			// do nothing
			break;

		case TA_TOP:
			// We must shift up from base line to top.
			m_PtCurPos.Y -= itmAscent;
			break;
			
		case TA_BOTTOM:
			// We must shift down from base line to bottom.
			m_PtCurPos.Y += m_pFont->SCGetDescent();
			break;
		}

		m_PtCurPos.X += (INT)LastChSize.Width;
	}

	delete [] positions;
}

///
/// Build a non-rotated text box from a reference point text extents
/// This rectangle is ready to use for a (TA_TOP,TA_LEFT) aligned text.
/// 
void CSCEMFdcRenderer::SCBuildTextRect(ULONG ulTextAlign, POINT PtRef, RECT& ClipRect,
					RectF TextSize, INT itmAscent)
{
	// Text's horizontal alignment
	switch (ulTextAlign & SC_HTXTALIGN_MASK)
	{
	case TA_LEFT:
		ClipRect.left = PtRef.x;
		break;
		
	case TA_CENTER:
		ClipRect.left = (long)(PtRef.x - TextSize.Width / 2); 
		break;
		
	case TA_RIGHT:
		ClipRect.left = (long)(PtRef.x - TextSize.Width);
		break;
	}
	
	// Text's vertical alignment
	switch (ulTextAlign & SC_VTXTALIGN_MASK)
	{
	case TA_TOP:
		ClipRect.top = PtRef.y;
		break;
		
	case TA_BASELINE:
		ClipRect.top = PtRef.y - itmAscent;
		break;
		
	case TA_BOTTOM:
		ClipRect.top = (long)(PtRef.y - TextSize.Height);
		break;
	}		
	ClipRect.right = (long)(ClipRect.left + TextSize.Width);
	ClipRect.bottom = (long)(ClipRect.top + TextSize.Height);
}

///
/// Compute text witdh
///
INT CSCEMFdcRenderer::SCComputeTextWidth(LPCWSTR pwString, INT iCount, CONST INT* pDxWidths, INT flags)
{
	// Compute text's horizontal extent
	INT iWdth = 0;
	CONST INT* pWdt = pDxWidths;
	for (INT i = 0; (i < iCount); i++)
		iWdth += *pWdt++;

	ASSERT(iWdth>0);
	return iWdth;
}

///
/// Construct the parallelogram surrounding a text.
/// 
void CSCEMFdcRenderer::SCComputeTextBBox(ULONG ulTextAlign, RectF TextSize,
					   SCRectPolygon& RectPolygon, POINT& PtRef, INT itmAscent)
{
	ASSERT(TextSize.Width>0 && TextSize.Height>0);

	// make a rectangle for ta_left/ta_top aligned text
	RECT rcText;
	SCBuildTextRect(ulTextAlign, PtRef, rcText, TextSize, itmAscent);
	
	// transform into polygon
	RectPolygon.SCFromRect(&rcText);

#if 0
	// rotate if necessary
	ASSERT(m_pFont);
	INT iFontAngle = m_pFont->SCGetAngle();
	if (iFontAngle)
	{
		// Caution: use this only if reflection is done BEFORE rotation
		RectPolygon.SCRotate(iFontAngle, PtRef.x, PtRef.y);
		// But if the font angle is already taken into account in another transformation,
		// do not rotate the text box.
	}
#endif
}

	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -