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

📄 wg_painter.cpp

📁 一个小巧的嵌入式图形系统wGUI, 可以用VC编译
💻 CPP
字号:
// wg_painter.cpp//// CPainter class////// Copyright (c) 2002 Rob Wiskow// rob-dev@boxedchaos.com//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//#include "wgui_include_config.h"#include "wg_painter.h"#include "wg_error.h"#include <algorithm>#ifdef WIN32#include <limits>#endif // WIN32namespace wGui{CPainter::CPainter(SDL_Surface* pSurface, EPaintMode ePaintMode) :	m_pSurface(pSurface),	m_pWindow(0),	m_PaintMode(ePaintMode){	if (!m_pSurface)	{		throw Wg_Ex_App("CPainter::CPainter : Invalid pointer to surface.");	}}CPainter::CPainter(CWindow* pWindow, EPaintMode ePaintMode) :	m_pSurface(0),	m_pWindow(pWindow),	m_PaintMode(ePaintMode){	if (!m_pWindow)	{		throw Wg_Ex_App("CPainter::CPainter : Invalid pointer to window.");	}	m_pSurface = pWindow->GetSDLSurface();	if (!m_pSurface)	{		throw Wg_Ex_App("CPainter::CPainter : Invalid pointer to surface.");	}}void CPainter::DrawHLine(int xStart, int xEnd, int y, const CRGBColor& LineColor){	if (m_pWindow)	{		CPoint Offset = m_pWindow->GetClientRect().TopLeft();		xStart += Offset.XPos();		xEnd += Offset.XPos();		y += Offset.YPos();	}#ifdef WIN32#ifndef MSVC6  // There are problems with VC6 and these std lib template classes	if (xStart < std::numeric_limits<short int>::min() ||xStart > std::numeric_limits<short int>::max()		|| xEnd < std::numeric_limits<short int>::min() ||xEnd > std::numeric_limits<short int>::max()		|| y < std::numeric_limits<short int>::min() ||y > std::numeric_limits<short int>::max())	{		throw(Wg_Ex_Range("CPainter::DrawHLine : Out of range - converting int to short int!"));	}#endif // MSVC6#endif // WIN32	SDL_Rect Rect;	Rect.x = static_cast<short int>(std::min(xStart, xEnd));	Rect.y = static_cast<short int>(y);	Rect.w = static_cast<short int>(std::max(xEnd - xStart + 1, xStart - xEnd + 1));	Rect.h = 1;	SDL_FillRect(m_pSurface, &Rect, LineColor.SDLColor(m_pSurface->format));}void CPainter::DrawVLine(int yStart, int yEnd, int x, const CRGBColor& LineColor){	if (m_pWindow)	{		CPoint Offset = m_pWindow->GetClientRect().TopLeft();		yStart += Offset.YPos();		yEnd += Offset.YPos();		x += Offset.XPos();	}#ifdef WIN32#ifndef MSVC6  // There are problems with VC6 and these std lib template classes	if (yStart < std::numeric_limits<short int>::min() ||yStart > std::numeric_limits<short int>::max()		|| yEnd < std::numeric_limits<short int>::min() ||yEnd > std::numeric_limits<short int>::max()		|| x < std::numeric_limits<short int>::min() ||x > std::numeric_limits<short int>::max())	{		throw(Wg_Ex_Range("CPainter::DrawVLine : Out of range - converting int to short int!"));	}#endif // MSVC6#endif // WIN32	SDL_Rect Rect;	Rect.x = static_cast<short int>(x);	Rect.y = static_cast<short int>(std::min(yStart, yEnd));	Rect.w = 1;	Rect.h = static_cast<short int>(std::max(yEnd - yStart + 1, yStart - yEnd + 1));	SDL_FillRect(m_pSurface, &Rect, LineColor.SDLColor(m_pSurface->format));}void CPainter::DrawRect(const CRect& Rect, bool bFilled, const CRGBColor& BorderColor, const CRGBColor& FillColor){	CRect RealRect((m_pWindow != 0) ? Rect + m_pWindow->GetClientRect().TopLeft() : Rect);	if (m_pWindow)	{		RealRect.ClipTo(m_pWindow->GetClientRect());	}	if (!bFilled || (BorderColor != FillColor))	{		DrawHLine(RealRect.Left(), RealRect.Right(), RealRect.Top(), BorderColor);		DrawHLine(RealRect.Left(), RealRect.Right(), RealRect.Bottom(), BorderColor);		DrawVLine(RealRect.Top(), RealRect.Bottom(), RealRect.Left(), BorderColor);		DrawVLine(RealRect.Top(), RealRect.Bottom(), RealRect.Right(), BorderColor);		RealRect.Grow(-1); //In case we have to fill the rect, then it's ready to go.	}	if (bFilled)	{		SDL_Rect FillRect = RealRect.SDLRect();		SDL_FillRect(m_pSurface, &FillRect, FillColor.SDLColor(m_pSurface->format));	}}void CPainter::DrawLine(const CPoint& Point1, const CPoint& Point2, const CRGBColor& LineColor){	if (Point1.XPos() == Point2.XPos())	{		DrawVLine(Point1.YPos(), Point2.YPos(), Point1.XPos(), LineColor);	}	else	{		double iSlope = double(Point2.YPos() - Point1.YPos()) / (Point2.XPos() - Point1.XPos());		if (iSlope <= 1 && iSlope >= -1)		{			CPoint StartPoint = (Point1.XPos() < Point2.XPos()) ? Point1 : Point2;			CPoint EndPoint = (Point1.XPos() < Point2.XPos()) ? Point2 : Point1;			for (int x = StartPoint.XPos(); x <= EndPoint.XPos(); ++x)			{				DrawPoint(CPoint(x, static_cast<int>(StartPoint.YPos() + (x - StartPoint.XPos()) * iSlope)), LineColor);			}		}		else		{			CPoint StartPoint = (Point1.YPos() < Point2.YPos()) ? Point1 : Point2;			CPoint EndPoint = (Point1.YPos() < Point2.YPos()) ? Point2 : Point1;			for (int y = StartPoint.YPos(); y <= EndPoint.YPos(); ++y)			{				DrawPoint(CPoint(static_cast<int>(StartPoint.XPos() + (y - StartPoint.YPos()) / iSlope), y), LineColor);			}		}	}}void CPainter::DrawPoint(const CPoint& Point, const CRGBColor& PointColor){	CPoint RealPoint = (m_pWindow != 0) ? Point + m_pWindow->GetClientRect().TopLeft() : Point;	if (CRect(0, 0, m_pSurface->w, m_pSurface->h).HitTest(RealPoint) == CRect::RELPOS_INSIDE)	{		LockSurface();		Uint8* PixelOffset = static_cast<Uint8*>(m_pSurface->pixels) +			m_pSurface->format->BytesPerPixel * RealPoint.XPos() + m_pSurface->pitch * RealPoint.YPos();		switch (m_pSurface->format->BytesPerPixel)		{		case 1: // 8 bpp			*reinterpret_cast<Uint8*>(PixelOffset) = static_cast<Uint8>(MixColor(ReadPoint(Point), PointColor).SDLColor(m_pSurface->format));			break;		case 2: // 16 bpp			*reinterpret_cast<Uint16*>(PixelOffset) = static_cast<Uint16>(MixColor(ReadPoint(Point), PointColor).SDLColor(m_pSurface->format));			break;		case 3:  // 24 bpp		{			Uint32 PixelColor = MixColor(ReadPoint(Point), PointColor).SDLColor(m_pSurface->format);			Uint8* pPixelSource = reinterpret_cast<Uint8*>(&PixelColor);			Uint8* pPixelDest = reinterpret_cast<Uint8*>(PixelOffset);			*pPixelDest = *pPixelSource;			*(++pPixelDest) = *(++pPixelSource);			*(++pPixelDest) = *(++pPixelSource);			break;		}		case 4: // 32 bpp			*reinterpret_cast<Uint32*>(PixelOffset) = static_cast<Uint32>(MixColor(ReadPoint(Point), PointColor).SDLColor(m_pSurface->format));			break;		default:			throw(Wg_Ex_SDL("CPainter::DrawPoint : Unrecognized BytesPerPixel."));			break;		}		UnlockSurface();	}}CRGBColor CPainter::ReadPoint(const CPoint& Point){	CPoint RealPoint = (m_pWindow != 0) ? Point + m_pWindow->GetClientRect().TopLeft() : Point;	Uint32 PixelColor = 0;	if (CRect(0, 0, m_pSurface->w, m_pSurface->h).HitTest(RealPoint) == CRect::RELPOS_INSIDE)	{		Uint8* PixelOffset = static_cast<Uint8*>(m_pSurface->pixels) +			m_pSurface->format->BytesPerPixel * RealPoint.XPos() + m_pSurface->pitch * RealPoint.YPos();		switch (m_pSurface->format->BytesPerPixel)		{		case 1: // 8 bpp			PixelColor = *reinterpret_cast<Uint8*>(PixelOffset);			break;		case 2: // 16 bpp			PixelColor = *reinterpret_cast<Uint16*>(PixelOffset);			break;		case 3: // 24 bpp		{			Uint8* pPixelDest = reinterpret_cast<Uint8*>(&PixelColor);			Uint8* pPixelSource = reinterpret_cast<Uint8*>(PixelOffset);			*pPixelDest = *pPixelSource;			*(++pPixelDest) = *(++pPixelSource);			*(++pPixelDest) = *(++pPixelSource);			break;		}		case 4: // 32 bpp			PixelColor = *reinterpret_cast<Uint32*>(PixelOffset);			break;		default:			throw(Wg_Ex_SDL("CPainter::DrawPoint : Unrecognized BytesPerPixel."));			break;		}	}	return CRGBColor(&PixelColor, m_pSurface->format);}void CPainter::LockSurface(void){	if (SDL_MUSTLOCK(m_pSurface))	{		if (SDL_LockSurface(m_pSurface) < 0)		{			SDL_Delay(10);			if (SDL_LockSurface(m_pSurface) < 0)			{				throw(Wg_Ex_SDL("Unable to lock surface."));			}		}	}}void CPainter::UnlockSurface(void){	if (SDL_MUSTLOCK(m_pSurface))	{		SDL_UnlockSurface(m_pSurface);	}}CRGBColor CPainter::MixColor(const CRGBColor& ColorBase, const CRGBColor& ColorAdd){	CRGBColor MixedColor(COLOR_TRANSPARENT);	switch (m_PaintMode)	{	case PAINT_IGNORE:		MixedColor = ColorBase;		break;	case PAINT_REPLACE:		MixedColor = ColorAdd;		break;	case PAINT_NORMAL:		MixedColor = ColorBase + ColorAdd;		break;	case PAINT_AND:		MixedColor = ColorBase & ColorAdd;		break;	case PAINT_OR:		MixedColor = ColorBase | ColorAdd;		break;	case PAINT_XOR:		MixedColor = ColorBase ^ ColorAdd;		break;	}	return MixedColor;}void CPainter::ReplaceColor(const CRGBColor& NewColor, const CRGBColor& OldColor){	for (int y = 0; y < m_pSurface->h; ++y)	{		for (int x = 0; x < m_pSurface->w; ++x)		{			CPoint point(x, y);			if(ReadPoint(point) == OldColor)			{				DrawPoint(point, NewColor);			}		}	}}void CPainter::TransparentColor(const CRGBColor& TransparentColor){	SDL_SetColorKey(m_pSurface, SDL_SRCCOLORKEY, TransparentColor.SDLColor(m_pSurface->format));}}

⌨️ 快捷键说明

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