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

📄 scgdiplusutils.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		pPen->SetDashStyle(DashStyleDashDot);
		break;

	case PS_DASHDOTDOT:
		pPen->SetDashStyle(DashStyleDashDotDot);
		break;

	case PS_USERSTYLE:
		pPen->SetDashStyle(DashStyleCustom);
		// user-supplied style array pointed to by elpStyleEntry (limited to
		// elpNumEntries elements) must be used to describe the custom pen
		{
			REAL* pReals = SCREALFromDWORD(pExtLogPen->elpStyleEntry, pExtLogPen->elpNumEntries);
			// "The length of each dash and space in the dash pattern is the product of
			// the element value in the array and the width of the Pen object."
			
			// So now we must devide somehow.
			// But I'm not sure the method coded here is bullet proof, since I should
			// use what GDI calls "style units" to make the division. But listen:
			// "If you absolutely have to know the style unit, the application must draw a styled
			// line in a bitmap and read it back to determine the size of the style units
			// in the x and y directions".
			if (0==iWidth)
				iWidth = 1;
			for (UINT i=0; (i<pExtLogPen->elpNumEntries); i++)
			{
				pReals[i] = pReals[i]/(REAL)iWidth;
			}

			pPen->SetDashPattern(pReals, pExtLogPen->elpNumEntries);
			delete [] pReals;
		}
		break;

	case PS_INSIDEFRAME:
		// comments in SCPenFromLogPen
		pPen->SetDashStyle(DashStyleSolid);
		pPen->SetAlignment(PenAlignmentInset);
		break;

	case PS_ALTERNATE:
		// Windows NT/2000/XP: we don't have the corresponding style in GDI+, so just pray.

		// fall through
	default:
		pPen->SetDashStyle(DashStyleSolid);
		ASSERT(0);
	}

	if (PS_GEOMETRIC==iPenType)
	{
		// Lines joint (applies only to PS_GEOMETRIC pens in GDI)
		switch (pExtLogPen->elpPenStyle & PS_JOIN_MASK)
		{
		case PS_JOIN_ROUND:
			pPen->SetLineJoin(LineJoinRound);
			break;
			
		case PS_JOIN_MITER:
			pPen->SetLineJoin(LineJoinMiter);
			break;
			
		case PS_JOIN_BEVEL:
			pPen->SetLineJoin(LineJoinBevel);
			break;
			
		default:
			// (cf. MSDN "Pens in Win32")
			pPen->SetLineJoin(LineJoinRound);
			ASSERT(0);
		}

		// End cap (applies only to PS_GEOMETRIC pens in GDI)
		switch (pExtLogPen->elpPenStyle & PS_ENDCAP_MASK)
		{
		case PS_ENDCAP_ROUND:
			pPen->SetLineCap(LineCapRound, LineCapRound, DashCapRound);
			break;
			
		case PS_ENDCAP_FLAT:
			pPen->SetLineCap(LineCapFlat, LineCapFlat, DashCapFlat);
			break;
			
		case PS_ENDCAP_SQUARE:
			pPen->SetLineCap(LineCapSquare, LineCapSquare, DashCapFlat);
			break;
			
		default:
			// (cf. MSDN "Pens in Win32")
			pPen->SetLineCap(LineCapRound, LineCapRound, DashCapRound);
			ASSERT(0);
		}

		// "all [brush related] members must be used to specify the brush
		// attributes of the pen".
		if  ((BS_HOLLOW!=pExtLogPen->elpBrushStyle) &&
			(BS_SOLID!=pExtLogPen->elpBrushStyle || PS_SOLID!=iPenStyle))
		{
			LOGBRUSH LogBrush;
			LogBrush.lbStyle = pExtLogPen->elpBrushStyle;
			LogBrush.lbColor = pExtLogPen->elpColor;
			LogBrush.lbHatch = pExtLogPen->elpHatch;
			
			BOOL bSvd = rDCState.bMonoBrush;
			
			Brush* pBrush = SCBrushFromLogBrush(LogBrush, rDCState);
			if (pBrush)
				pPen->SetBrush(pBrush);
			
			rDCState.bMonoBrush = bSvd;
		}
	} 
	// else PS_COSMETIC:
	// "the [pExtLogPen->elpColor] member specifies the color of the pen and the
	// [pExtLogPen->elpPenStyle] member must be set to BS_SOLID"

	return pPen;
}

///
///	Fill a two-color palette with current text/background colors of DC.
/// (For monochrome brush color realization)
///
void SCFillMonochromePalette(SCShortDCState& rDCState, PPALETTEENTRY palPalEntry)
{
	ASSERT(palPalEntry);

	COLORREF crBkColor = rDCState.crBkColor;
	COLORREF crTextColor = rDCState.crTextColor;
	palPalEntry[0].peRed = GetRValue(crTextColor);
	palPalEntry[0].peGreen = GetGValue(crTextColor);
	palPalEntry[0].peBlue = GetBValue(crTextColor);
	palPalEntry[0].peFlags = 0;
	palPalEntry[1].peRed = GetRValue(crBkColor);
	palPalEntry[1].peGreen = GetGValue(crBkColor);
	palPalEntry[1].peBlue = GetBValue(crBkColor);
	palPalEntry[1].peFlags = 0;
}

///
/// Attach a two-color palette to a GDI+ image, using the given colors.
///
inline BOOL SCSetMonochromeImagePalette(Image* pImage, COLORREF crTextColor, COLORREF crBkColor)
{
	ASSERT(pImage);

	BOOL bOk = FALSE;
	// Update color palette for 1-bpp.
	ColorPalette* pPal = (ColorPalette*)new BYTE[sizeof(ColorPalette) + 2*sizeof(ARGB)];
	pPal->Flags = PaletteFlagsHasAlpha;
	pPal->Count = 2;
	pPal->Entries[0] = Color::MakeARGB(255, GetRValue(crTextColor),
											GetGValue(crTextColor),
											GetBValue(crTextColor));
	pPal->Entries[1] = Color::MakeARGB(255, GetRValue(crBkColor),
											GetGValue(crBkColor),
											GetBValue(crBkColor));	

	bOk = (pImage->SetPalette(pPal)==Ok);
	delete [] (BYTE*)pPal;

	return bOk;
}

///
/// Attach a two-color palette to a GDI+ image, using current text and background color.
///
inline BOOL SCSetMonochromeBrushPalette(Image* pImage, SCShortDCState& rDCState)
{
	ASSERT(pImage);

	return SCSetMonochromeImagePalette(pImage, rDCState.crTextColor, rDCState.crBkColor);
}

///
/// Attach a two-color palette to a GDI+ image, using the DC state colors.
///
Brush* SCRealizeMonochromeBrushPalette(Brush* pBrush, SCShortDCState& rDCState)
{
	ASSERT(pBrush && pBrush->GetType()==BrushTypeTextureFill);
	if (!pBrush || pBrush->GetType()!=BrushTypeTextureFill)
		return NULL;

	// Well, the bitmap stored in the brush isn't 1bpp anymore
	// And setting palette on 32bpp bitmap will silently fail
	Bitmap* pBitmap = (Bitmap*)((TextureBrush*)pBrush)->GetImage(); // a 32bpp (a plain copy, not a "just to see" pointer)
	ASSERT(pBitmap && pBitmap->GetLastStatus()==Ok);

#if 0
	// This too fails. "Jeez!... it's full of 'stars!'"
	Bitmap* pClone = pBitmap->Clone(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight(), PixelFormat1bppIndexed);
#else
	// Manual cloning => bad/funny results
	// LockBits doesn't understand that WE WANT PixelFormat1bppIndexed!
//	"LockBits [...]
//	format 
//	[in] Integer that specifies the format of the pixel data in the temporary buffer.
//	The pixel format of the temporary buffer does not have to be the same as the pixel
//	format of this Bitmap object. The PixelFormat data type and constants that represent
//	various pixel formats are defined in Gdipluspixelformats.h. For more information about
//	pixel format constants, see Image Pixel Format Constants.
//	Microsoft Windows GDI+ version 1.0 does not support processing of 16-bits-per-channel
//	images, so you should not set this parameter equal to PixelFormat48bppRGB,
//	PixelFormat64bppARGB, or PixelFormat64bppPARGB."
// You can add PixelFormat1bppIndexed to the list.
	BitmapData BmData;
	Rect rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
	Status iRes = pBitmap->LockBits(&rect, ImageLockModeRead,
		PixelFormat32bppARGB/*oops!*/, &BmData);
	ASSERT(iRes==Ok);

	Bitmap* pClone = new Bitmap(pBitmap->GetWidth(), pBitmap->GetHeight(),
		BmData.Stride, PixelFormat1bppIndexed, (BYTE*)BmData.Scan0);

	pBitmap->UnlockBits(&BmData); 
#endif

	ASSERT(pBitmap->GetLastStatus()==Ok);
	ASSERT(pClone && pClone->GetLastStatus()==Ok);

	BOOL bOk = SCSetMonochromeImagePalette(pClone, rDCState.crTextColor, rDCState.crBkColor);

	TextureBrush* pNewBrush = NULL;
	if (bOk)
	{
		// We can't just set
		//((TextureBrush*)pBrush)->SetBitmap(pClone);
		Matrix matrix;
		((TextureBrush*)pBrush)->GetTransform(&matrix);

		pNewBrush = new TextureBrush(pClone);
		if (pNewBrush)
		{
			Status iRes = pNewBrush->SetTransform(&matrix);
			ASSERT(iRes==Ok);
		}
	}
	delete pClone;
	delete pBitmap; // warning!?

	return pNewBrush;
}

#if 0
///
/// Create a GDI+ font from a GDI LOGFONT.
///
Font* SCFontFromLogFont(LOGFONT& rLogFont)
{
	ASSERT(0); // not implemented
	return NULL;
}
#endif


///
/// Build an TrueType approximation of the font describes in LogFont.
///	Note, this is a late font substitution (more complicated).
///
HFONT SCTTFontFromLOGFONT(LOGFONT& rLogFont, HDC hDC)
{
	rLogFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
	rLogFont.lfPitchAndFamily |= SCFontFamilyApproximant((TCHAR*)rLogFont.lfFaceName);

	HFONT hFont = CreateFontIndirect(&rLogFont);
	ASSERT(hFont);
	if (!hFont)
	{// silent failure
		switch (rLogFont.lfPitchAndFamily & 0xF0)
		{
		case FF_ROMAN:
			_tcscpy((TCHAR*)rLogFont.lfFaceName, _T("Times New Roman"));
			break;
			
		case FF_DONTCARE:
		case FF_SWISS:
		case FF_MODERN:
		case FF_SCRIPT:
		case FF_DECORATIVE:
		default:
			_tcscpy((TCHAR*)rLogFont.lfFaceName, _T("Arial"));
		}

		return NULL;
	}

	BOOL bTmpDC = (NULL==hDC);
	if (bTmpDC)
		hDC = ::GetDC(NULL);
	ASSERT(hDC);
	HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
	GetTextFace(hDC, LF_FACESIZE, rLogFont.lfFaceName);

	if (bTmpDC)
	{// no DC was given for selecting font
		SelectObject(hDC, hOldFont);
		ReleaseDC(NULL,hDC);
	} // else the returned font is selected in the DC
	  // the danger is we are losing hOldFont
	return hFont;
}


///
/// Create an array of GDI+ Points from an array of Win32 POINTs.
///
//	Point* SCPointFromPOINT(LPCPOINT pPoints, DWORD dwCount)
template <class T> 
Point* SCPointFromPOINT(T pPoints, DWORD dwCount)
{
	ASSERT(pPoints && dwCount);

	Point *pPts = new Point[dwCount];
	
	Point *pDest = pPts;
	Point *pLimit = pDest + dwCount;
	for(; (pDest<pLimit); pDest++, pPoints++) 
	{
		pDest->X = pPoints->x;
		pDest->Y = pPoints->y; 
	}

	return pPts;
}
// some explicit instantiations, cause it's a library
template Point* SCPointFromPOINT<LPPOINT>(LPPOINT, DWORD);
template Point* SCPointFromPOINT<LPPOINTS>(LPPOINTS, DWORD);
//

///
/// Create an array of GDI+ Points from an array of Win32 POINTSs completed by the
/// current position in play DC (hold in rPtStart).
///
template <class T>
Point* SCPointFromPOINTTo(Point& rPtStart, T pPoints, DWORD dwCount)
{
	ASSERT(pPoints && dwCount);
	// add +1 to count to include the current position in DC
	Point *pPts = new Point[++dwCount];
	
	// copy first point
	pPts->X = rPtStart.X;
	pPts->Y = rPtStart.Y; 

	// copy other points
	Point *pDest = pPts + 1;
	Point *pLimit = pPts + dwCount;

	for(; (pDest<pLimit); pDest++, pPoints++) 
	{
		pDest->X = pPoints->x;
		pDest->Y = pPoints->y; 
	}
	return pPts;
}
// some explicit instantiations, cause it's a library
template Point* SCPointFromPOINTTo<LPPOINT>(Point&, LPPOINT, DWORD);
template Point* SCPointFromPOINTTo<LPPOINTS>(Point&, LPPOINTS, DWORD);
//

///
/// Create an array of REALs from an array of DWORDs.
///
REAL* SCREALFromDWORD(LPDWORD pDWords, DWORD dwCount)
{
	ASSERT(pDWords && dwCount);

	REAL *pReals = new REAL[dwCount];
	
	REAL *pDest = pReals;
	REAL *pLimit = pDest + dwCount;
	while (pDest<pLimit)
	{
		*pDest++ = (REAL)*pDWords++;
	}

	return pReals;
}

///
/// Translate GDI clipping modes into GDI+ equivalent.
///
CombineMode SCClipModeFormRGNMode(INT iMode)
{
	switch (iMode)
	{
	case RGN_COPY:
		return CombineModeReplace;

	case RGN_AND:
		return CombineModeIntersect;

	case RGN_DIFF:
		return CombineModeExclude;

	case RGN_OR:
		return CombineModeUnion;

	case RGN_XOR:
		return CombineModeXor;

	default:
		ASSERT(0);
	}
	return CombineModeReplace;
}

///
/// Perfom a rop opeartion by filling a rectangle with the color located at
/// the given index in the default system palette. (WHITENESS/BLACKNESS)
///
void SCSysPaletteFillRect(I_SCDCGraphics* pIGraphics, Rect& destRect, UINT uiPalIndex)
{
	ASSERT(pIGraphics);
	ASSERT(uiPalIndex<256);

	PALETTEENTRY PaletteEntry;

	// Bogus GDI documentation?: index 1 doesn't correspond to WHITENESS as expected
	// (And we know that the 20 static colors (reserved) use the following indices:
	// 0-9, 246-255; but that's true for Windows 3.0 and 3.1; for other systems, !!??)
	//
	// So, consider using manual colors.
	HDC hdc = GetDC(NULL);
	GetSystemPaletteEntries (hdc, uiPalIndex, 1, &PaletteEntry);
	ReleaseDC(NULL, hdc);
	
	Color BrushColor;
	BrushColor.SetFromCOLORREF(pIGraphics->SCGetFinalColor(RGB(PaletteEntry.peRed,
															   PaletteEntry.peGreen,
															   PaletteEntry.peBlue)));
	SolidBrush brush(BrushColor);

	Graphics* pGraphics = pIGraphics->SCGetGraphics();

	ASSERT(pGraphics);
	pGraphics->FillRectangle(&brush, destRect);
}

///
/// Perfom a DIB blt opeartion using ROP.
///
INT SCStretchDIBits(
  I_SCDCGraphics* pIGraphics, // pointer to destination graphics context
  INT XDest,              // x-coordinate of upper-left corner of dest. rectangle
  INT YDest,              // y-coordinate of upper-left corner of dest. rectangle
  INT nDestWidth,         // width of destination rectangle
  INT nDestHeight,        // height of destination rectangle
  INT XSrc,               // x-coordinate of upper-left corner of source rectangle
  INT YSrc,               // y-coordinate of upper-left corner of source rectangle
  INT nSrcWidth,          // width of source rectangle
  INT nSrcHeight,         // height of source rectangle
  CONST VOID *lpBits,            // address of bitmap bits
  CONST BITMAPINFO *lpBitsInfo,  // address of bitmap data
  UINT iUsage,                   // usage flags
  DWORD dwRop                    // raster operation code
)
{
	ASSERT(pIGraphics);

	// Prepare the temporary destination bitmap
	HDC hOutputDC = pIGraphics->SCGetDC();
	ASSERT(hOutputDC);
	if (!hOutputDC)
		return FALSE;

	HDC hDestDC = CreateCompatibleDC(hOutputDC);
#if 0
	// best quality (but memory hog, and time consuming for GDI+, not for GDI)
	INT iTmpWidth = nSrcWidth;
	INT iTmpHeight = nSrcHeight;
#else
	// faster (but less smooth image)
	INT iTmpWidth = abs(nSrcWidth);
	INT iTmpHeight = abs(nSrcHeight);
	if (iTmpWidth>=1000 || iTmpHeight>=1000) // TODO: fix these arbitrary values
	{// large high resolution bitmaps will bog down GDI+
	 // (it won't crash, but it can take 5 minutes, and generate 250Mo memory peaks)
		iTmpWidth = abs(nDestWidth);	
		iTmpHeight = abs(nDestHeight);
		// inflate dest to enhance quality
		if (iTmpWidth<500 && iTmpHeight<500)
		{
			iTmpWidth *= 2;
			iTmpHeight *= 2;
		}
	}
#endif
	HBITMAP hDestBmp = CreateCompatibleBitmap(hOutputDC, iTmpWidth, iTmpHeight);
	if (!hDestBmp)
	{
		DWORD dwError = GetLastError();
		ASSERT(0);
	}
	HBITMAP hOldBmp = (HBITMAP)SelectObject(hDestDC, hDestBmp);

	// Copy the destination rectangle
	BOOL bOK = StretchBlt(hDestDC, 0, 0, iTmpWidth, iTmpHeight,
		   hOutputDC, XDest, YDest, nDestWidth, nDestHeight, SRCCOPY);
	if (!bOK)
	{// Maybe failure due to rotation/shear found in hOutputDC
	 // (do a manual resampling of the destination rectangle)
		float pitchx = float(nDestWidth)/float(iTmpWidth);
		float pitchy = float(nDestHeight)/float(iTmpHeight);
		int ys;
		for (int y=0; (y<iTmpHeight); y++)
		{
			ys = (int)(YDest + y*pitchy);
			int xs;
			for (int x=0; (x<iTmpWidth); x++)
			{
				xs = (int)(XDest + x*pitchx);
				COLORREF crColor = GetPixel(hOutputDC, xs, ys);
				SetPixel(hDestDC, x, y, crColor);

⌨️ 快捷键说明

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