www.pudn.com > StyleToolkit_demo_src.zip > Style.cpp


// 
// Style.cpp: implementation file for the Style class and Stack class. 
// 
// Author:  Darren Sessions 
//           
// 
// Description: 
//    
//		The Stack class defines the User API of the Style Toolkit.  The Style 
//		class is used to paint the stacks. 
// 
// History 
//     Version 1.0 - 2008 June 24 
//     - Initial public release 
// 
// License: 
//     This software is released under the Code Project Open License (CPOL), 
//     which may be found here:  http://www.codeproject.com/info/eula.aspx 
//     You are free to use this software in any way you like, except that you  
//     may not sell this source code. 
// 
//     This software is provided "as is" with no expressed or implied warranty. 
//     I accept no liability for any damage or loss of business that this  
//     software may cause. 
// 
/////////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "Style.h" 
 
Style::Style() 
{ 
	// pre allocate some stack space 
	m_Stacks.reserve(5); 
} 
 
Style::~Style() 
{ 
	int tmp=1; 
} 
 
//============================================================================= 
// 
// AddStack() 
// 
// Purpose:     Adds a stack to the top of this style 
// 
// Parameters:  stack	- [in] the stack to add 
//				 
// Returns:     None 
// 
int Style::AddStack(Stack& stack) 
{ 
	m_Stacks.push_back(stack); 
 
	return (m_Stacks.size() - 1); 
} 
 
//============================================================================= 
// 
// PaintStyle() 
// 
// Purpose:     Paints all the stacks for this style 
// 
// Parameters:  pDevC	- [in] the device context 
//				rect	- [in] the bounding rect for this style 
//				 
// Returns:     None 
// 
void Style::PaintStyle(CDC* pDevC, CRect rect) 
{ 
	MemDC pDC(pDevC, rect, TRUE); 
 
	Graphics gdi(pDC->m_hDC); 
 
	gdi.SetSmoothingMode(SmoothingModeAntiAlias); 
	gdi.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); 
 
	// paint all stacks 
	for(stack = m_Stacks.begin(); stack != m_Stacks.end(); ++stack) 
	{ 
		if((*stack).Frame.bUseBitmap) 
		{ 
			// copy the bitmap to the DC 
			pDC->BitBlt((*stack).Frame.frect.X,  
						(*stack).Frame.frect.Y,  
						(*stack).Frame.frect.Width,  
						(*stack).Frame.frect.Height,  
						(*stack).GetDC(), 0, 0, SRCCOPY	); 
		} 
		else 
		{ 
			// the first call to PaintStyle will create all the bitmaps here 
			(*stack).PaintStack(pDC, &gdi); 
		} 
	} 
} 
 
//============================================================================= 
// 
// SetPosition() 
// 
// Purpose:     Sets the origin of all the stacks and layers 
// 
// Parameters:  x	- [in] the x offset 
//				y	- [in] the y offset 
//				 
// Returns:     None 
// 
void Style::SetPosition(int x, int y) 
{ 
	// iterate all stacks 
	for(stack = m_Stacks.begin(); stack != m_Stacks.end(); ++stack) 
	{ 
		ASSERT(!((*stack).Frame.frect.Width == 0 && (*stack).Frame.frect.Height == 0)); 
		 
		(*stack).SetPosition(x, y); 
	} 
} 
 
 
//============================================================================= 
// operator = 
Stack& Stack::operator=(const Stack& other) 
//============================================================================= 
{ 
	Layers::m_Layers.clear(); 
	Layers::Copy(other); 
	return *this; 
} 
 
//============================================================================= 
// operator += 
Stack& Stack::operator+=(const Stack& other) 
//============================================================================= 
{ 
	// the region indexes need to be adjusted to add 
	// the layers beneath it 
	int cnt = this->m_Layers.size(); 
	Layers::CopyLayers(other); 
 
	for(layer = m_Layers.begin() + cnt; layer != m_Layers.end(); ++layer) 
	{ 
		// just adjust all of them even if they don't apply 
		(*layer).rgnIndex[0] += cnt; 
		(*layer).rgnIndex[1] += cnt; 
	} 
 
	return *this; 
} 
 
//============================================================================= 
// operator + 
Stack operator+(const Stack& lhs, const Stack& rhs) 
//============================================================================= 
{ 
	return Stack(lhs)+=rhs; 
} 
 
//============================================================================= 
// GDI constructor with boundaries 
Stack::Stack(SRect sr) 
//============================================================================= 
{ 
	Init(); 
	MakeFrame(sr.rect); 
} 
 
//============================================================================= 
// GDI constructor with Initial layer 
Stack::Stack(SRect sr, Clr clr) 
//============================================================================= 
{ 
	Init(); 
	MakeFrame(sr.rect); 
	AddLayer(sr.rect, clr); 
} 
 
//============================================================================= 
// 
// AddLayer() 
// 
// Purpose:     Adds a layer to the stack.  A transparent layer will be created 
//				and set to the Frames rect just prior to painting  
// 
// Parameters:  None 
//				 
// Returns:     None 
// 
int Stack::AddLayer() 
{ 
	OPERATION Layer; 
	::ZeroMemory(&Layer, sizeof(OPERATION)); 
 
	m_Layers.push_back(Layer); 
	return (m_Layers.size() - 1); 
} 
 
//============================================================================= 
// 
// AddLayer() 
// 
// Purpose:     Adds a layer to the stack.  If only the rect is passed 
//				a transparent layer will be created 
// 
// Parameters:  sr		- [in] Rect boundary of this layer 
//				clr		- [in] optional - color of this layer 
//				 
// Returns:     None 
// 
int Stack::AddLayer(SRect sr, Clr clr) 
{ 
	OPERATION Layer; 
	::ZeroMemory(&Layer, sizeof(OPERATION)); 
 
	Layer.lrect = sr.rect; 
	Layer.clr1 = clr.value; 
 
	m_Layers.push_back(Layer); 
 
	return (m_Layers.size() - 1); 
} 
 
//============================================================================= 
Bitmap* Style::GetBitmap(CDC* pDevC, CRect rect) 
//============================================================================= 
{ 
	MemDC pDC(pDevC, rect, TRUE); 
	PaintStyle(pDC, rect); 
	return pDC->GetBitmap(); 
} 
 
//============================================================================= 
// 
// SetRect() 
// 
// Purpose:     Sets the size and position of the stack relative to the  
//				parent's origin (the parent is the Style that will paint  
//				this object) 
// 
// Parameters:  rect	- [in] CRect object 
//				 
// Returns:     None 
// 
void Stack::SetRect(SRect rect) 
{ 
	MakeFrame(rect); 
} 
 
//============================================================================= 
// 
// SetShape() 
// 
// Purpose:     Sets the shape of the stacks borders to the passed argurmen 
// 
// Parameters:  shape	- [in] one of LayerShapes 
//				radius	- [in] radius of corner for ROUNDRECT type shape 
//				 
// Returns:     None 
// 
void Stack::SetShape(int shape, int radius) 
{ 
	Layers::SetShape(shape, radius); 
} 
 
//============================================================================= 
// 
// Regenerate() 
// 
// Purpose:		Marks the stack to be regenerated on the next paint operation. 
//				If a layer index is passed, it will reset all of the layer rects 
//				above and including the index to zero, causing them to be  
//				recalcculated from the frame rect 
// 
// Parameters:  x	- [in] the x offset 
//				y	- [in] the y offset 
//				 
// Returns:     None 
// 
void Stack::Regenerate(int layerIdx) 
{ 
	Layers::Regenerate(layerIdx); 
} 
 
//============================================================================= 
// 
// SetPosition() 
// 
// Purpose:     Moves the frame and all the layers in the stack to the x y position 
// 
// Parameters:  x, y - [in] the new position 
//				 
// Returns:     None 
// 
void Stack::SetPosition(int x, int y) 
{ 
	int xoff = x - Frame.frect.X; 
	int yoff = y - Frame.frect.Y; 
 
	// set the frame origin 
	Frame.frect.X = x; Frame.frect.Y = y; 
 
	// iterate all the layers 
	for(layer = m_Layers.begin(); layer != m_Layers.end(); ++layer) 
	{ 
		(*layer).lrect.X += xoff;  
		(*layer).lrect.Y += yoff; 
	} 
} 
 
//============================================================================= 
// 
// FillSolid() 
// 
// Purpose:     Defines the layer as a solid fill 
// 
// Parameters:  cr			- [in] the rect for this layer 
//				clr1		- [in] color for this layer 
//				 
// Returns:     index to layer added 
// 
int Stack::FillSolid(SRect cr, Clr color) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = cr.rect; 
	m_Layers[layer].clr1 = color.value; 
	m_Layers[layer].LayerType = SOLID; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillSolid() 
// 
// Purpose:     Defines the layer as a solid fill 
// 
// Parameters:  clr1		- [in] color for this layer 
//				 
// Returns:     index to layer added 
// 
int Stack::FillSolid(Clr color) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].clr1 = color.value; 
	m_Layers[layer].LayerType = SOLID; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillGrad2() 
// 
// Purpose:     Defines the layer as a 2 color gradient 
// 
// Parameters:  rect		- [in] Rectangle for this layer 
//				style		- [in] Gradient style - HORIZ, VERT, DIAGF, DIAGR 
//				clr1		- [in] Begin color for gradient 
//				clr2		- [in] End color for gradient 
//				diffpt		- [in] Diffusion point (-1.0, 1.0)  
//								   negative values mean diffuse relative to clr2 position 
//				 
// Returns:     index to layer added 
// 
int Stack::FillGrad2(SRect sr, int style, Clr clr1, Clr clr2, float diffpt) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].gradMode = style; 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
	m_Layers[layer].rParams[0] = diffpt; 
	m_Layers[layer].LayerType = BIGRAD; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillGrad2() 
// 
// Purpose:     Defines the layer as a 2 color gradient 
// 
// Parameters:  style		- [in] Gradient style - HORIZ, VERT, DIAGF, DIAGR 
//				clr1		- [in] Begin color for gradient 
//				clr2		- [in] End color for gradient 
//				diffpt		- [in] Diffusion point (-1.0, 1.0)  
//								   negative values mean diffuse relative to clr2 position 
//				 
// Returns:     index to layer added 
// 
int Stack::FillGrad2(int style, Clr clr1, Clr clr2, float diffpt) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].gradMode = style; 
	m_Layers[layer].rParams[0] = diffpt; 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
 
	m_Layers[layer].LayerType = BIGRAD; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillRadial() 
// 
// Purpose:     Defines the layer as a 2 radial gradient 
// 
// Parameters:  rect		- [in] Rectangle for this layer 
//				clr1		- [in] Begin color for gradient 
//				clr2		- [in] End color for gradient 
//				 
// Returns:     index to layer added 
// 
int Stack::FillRadial(SRect sr, Clr clr1, Clr clr2) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
 
	m_Layers[layer].LayerType = RADIAL; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillRadial() 
// 
// Purpose:     Defines the layer as a 2 radial gradient 
// 
// Parameters:  clr1		- [in] Begin color for gradient 
//				clr2		- [in] End color for gradient 
//				 
// Returns:     index to layer added 
// 
int Stack::FillRadial(Clr clr1, Clr clr2) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
 
	m_Layers[layer].LayerType = RADIAL; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillGrad3() 
// 
// Purpose:     Defines the layer as a 3 color gradient 
// 
// Parameters:  cr			- [in] rect for this layer 
//				style		- [in] Gradient style - HORIZ, VERT, DIAGF, DIAGR 
//				clr1		- [in] Begin color for gradient 
//				clr2		- [in] Middle color for gradient 
//				clr3		- [in] End color for gradient 
//				diffpt		- [in] Diffusion point (-1.0, 1.0) (future) 
//				 
// Returns:     index to layer added 
//=============================================================================/// 
int Stack::FillGrad3(SRect sr, int style, Clr clr1, Clr clr2, Clr clr3, float diffpt) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].gradMode = style; 
	m_Layers[layer].rParams[0] = diffpt; 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
	m_Layers[layer].clr3 = clr3.value; 
 
	m_Layers[layer].LayerType = TRIGRAD; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillGrad3() 
// 
// Purpose:     Defines the layer as a 3 color gradient 
// 
// Parameters:  style		- [in] Gradient style - HORIZ, VERT, DIAGF, DIAGR 
//				clr1		- [in] Begin color for gradient 
//				clr2		- [in] Middle color for gradient 
//				clr3		- [in] End color for gradient 
//				diffpt		- [in] Diffusion point (0.0, 1.0) 
//				 
// Returns:     index to layer added 
//=============================================================================/// 
int Stack::FillGrad3(int style, Clr clr1, Clr clr2, Clr clr3, float diffpt) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].gradMode = style; 
	m_Layers[layer].rParams[0] = diffpt; 
	m_Layers[layer].clr1 = clr1.value; 
	m_Layers[layer].clr2 = clr2.value; 
	m_Layers[layer].clr3 = clr3.value; 
 
	m_Layers[layer].LayerType = TRIGRAD; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// SetOuterBorder()  
// 
// Purpose:     Sets the Stacks border parameters 
// 
// Parameters:  width		- [in] the border width 
//				clr			- [in] color of border or upper left color if both are defined 
//				brclr		- [in] optional - bottom right color  
//				 
// Returns:     None 
// 
void Stack::SetOuterBorder(int width, Clr clr, Clr brclr) 
{ 
	Frame.OuterBorder.width = width; 
	Frame.OuterBorder.ulclr = clr.value; 
	Frame.OuterBorder.brclr = brclr.value; 
} 
void Stack::SetOuterBorder(int width, Clr clr) 
{ 
	Frame.OuterBorder.width = width; 
	Frame.OuterBorder.ulclr = clr.value; 
	Frame.OuterBorder.brclr = clr.value; 
} 
 
//============================================================================= 
// 
// SetMiddleBorder() 
// 
// Purpose:     Sets the Stacks border parameters 
// 
// Parameters:  width		- [in] the border width 
//				clr			- [in] color of border or upper left color if both are defined 
//				brclr		- [in] optional - bottom right color  
//				 
// Returns:     None 
// 
void Stack::SetMiddleBorder(int width, Clr clr, Clr brclr) 
{ 
	Frame.MiddleBorder.width = width; 
	Frame.MiddleBorder.ulclr = clr.value; 
	Frame.MiddleBorder.brclr = brclr.value; 
} 
void Stack::SetMiddleBorder(int width, Clr clr) 
{ 
	Frame.MiddleBorder.width = width; 
	Frame.MiddleBorder.ulclr = clr.value; 
	Frame.MiddleBorder.brclr = clr.value; 
} 
 
//============================================================================= 
// 
// SetInnerBorder() 
// 
// Purpose:     Sets the Stacks border parameters 
// 
// Parameters:  width		- [in] the border width 
//				clr			- [in] color of border or upper left color if both are defined 
//				brclr		- [in] optional - bottom right color  
//				 
// Returns:     None 
// 
void Stack::SetInnerBorder(int width, Clr clr, Clr brclr) 
{ 
	Frame.InnerBorder.width = width; 
	Frame.InnerBorder.ulclr = clr.value; 
	Frame.InnerBorder.brclr = brclr.value; 
} 
void Stack::SetInnerBorder(int width, Clr clr) 
{ 
	Frame.InnerBorder.width = width; 
	Frame.InnerBorder.ulclr = clr.value; 
	Frame.InnerBorder.brclr = clr.value; 
} 
 
 
//============================================================================= 
// 
// FillBar()  
//  
// Purpose:     Adds a gradient bar effect to one of edges 
// 
// Parameters:  cr			- [in] the rectangle containing this edge 
//				type		- [in] bar type - TOP_EDGE, LEFT_EDGE, RIGHT_EDGE, BOTTOM_EDGE 
//				width		- [in] the bar width 
//				tlclr		- [in] top or left color 
//				brclr		- [in] bottom or right color 
//				 
// Returns:     index to layer added 
// 
int Stack::FillBar(SRect sr,  int type, int width, Clr tlclr, Clr brclr) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
 
	m_Layers[layer].LayerType = type; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = brclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillBar()  
//  
// Purpose:     Adds a gradient bar effect to one of edges 
// 
// Parameters:  type		- [in] bar type - TOP_EDGE, LEFT_EDGE, RIGHT_EDGE, BOTTOM_EDGE 
//				width		- [in] the bar width 
//				tlclr		- [in] top or left color 
//				brclr		- [in] bottom or right color 
//				 
// Returns:     index to layer added 
// 
int Stack::FillBar(int type, int width, Clr tlclr, Clr brclr) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = type; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = brclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillBar()  
//  
// Purpose:     Adds a gradient bar effect to one of edges 
// 
// Parameters:  cr			- [in] the rectangle containing this edge 
//				type		- [in] bar type - TOP_EDGE, LEFT_EDGE, RIGHT_EDGE, BOTTOM_EDGE 
//				width		- [in] the bar width 
//				tlclr		- [in] top or left color 
//				mclr		- [in] middle color 
//				brclr		- [in] bottom or right color 
//				profile		- [in] array of 3 floats defining trinagle gradient 
//				 
// Returns:     index to layer added 
// 
int Stack::FillBar(SRect sr,  int type, int width, Clr tlclr, Clr mclr, Clr brclr, float* profile) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
 
	m_Layers[layer].LayerType = type; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = mclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
	memcpy(m_Layers[layer].rParams, profile, 3*sizeof(float)); 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillBar()  
//  
// Purpose:     Adds a gradient bar effect to one of edges 
// 
// Parameters:  type		- [in] bar type - TOP_EDGE, LEFT_EDGE, RIGHT_EDGE, BOTTOM_EDGE 
//				width		- [in] the bar width 
//				tlclr		- [in] top or left color 
//				mclr		- [in] middle color 
//				brclr		- [in] bottom or right color 
//				profile		- [in] array of 3 floats defining trinagle gradient 
//				 
// Returns:     index to layer added 
// 
int Stack::FillBar(int type, int width, Clr tlclr, Clr mclr, Clr brclr, float* profile) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = type; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = mclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
	memcpy(m_Layers[layer].rParams, profile, 3*sizeof(float)); 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillWrap()  
//  
// Purpose:     Adds a gradient of size width to the rect and then tiles 
//				with the tile mode 
// 
// Parameters:  type		- [in] tile type  
//				width		- [in] the width of the tiled piece 
//				tlclr		- [in] top or left color 
//				mclr		- [in] middle color 
//				brclr		- [in] bottom or right color 
//				 
// Returns:     index to layer added 
// 
int Stack::FillWrap(int type, int width, Clr tlclr, Clr mclr, Clr brclr) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = WRAP; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = mclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// FillWrap()  
//  
// Purpose:     Adds a gradient of size width to the rect and then tiles 
//				with the tile mode 
// 
// Parameters:  type		- [in] tile type  
//				width		- [in] the width of the tiled piece 
//				tlclr		- [in] top or left color 
//				mclr		- [in] middle color 
//				brclr		- [in] bottom or right color 
//				 
// Returns:     index to layer added 
// 
int Stack::FillWrap(SRect sr, int type, int width, Clr tlclr, Clr mclr, Clr brclr) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].LayerType = WRAP; 
	m_Layers[layer].width = width; 
	m_Layers[layer].clr1 = tlclr.value; 
	m_Layers[layer].clr2 = mclr.value; 
	m_Layers[layer].clr3 = brclr.value; 
 
	return layer; 
} 
 
//============================================================================= 
// 
// CreateRgn()  
//  
// Purpose:     Create a region 
// 
// Parameters:  cr			- [in] the rectangle bounding the region 
//				shape		- [in] the clipping shape 
//				 
// Returns:     index to layer referencing this clip region 
// 
int Stack::CreateRgn(SRect sr, int shape) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].LayerType = CREATERGN; 
	m_Layers[layer].LayerShape = shape; 
 
	return layer;	 
} 
 
//============================================================================= 
// 
// CombineRgnModify()  
//  
// Purpose:     Combines two clipping regions using the passed clipping mode 
//				The resultRgn will be modified 
// 
// Parameters:  resultRgn	- [in] this region will contain the combined result 
//				combineRgn	- [in] this region will be combined with the resultRgn 
//				mode		- [in] the clipping mode 
//				 
// Returns:     index to layer added 
// 
int Stack::CombineRgnModify(int resultRgn, int combineRgn, int mode) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = COMBINEMOD; 
	m_Layers[layer].clipMode = mode; 
	m_Layers[layer].rgnIndex[0] = resultRgn; 
	m_Layers[layer].rgnIndex[1] = combineRgn; 
 
	return layer;	 
} 
 
//============================================================================= 
// 
// CombineRgnCreate()  
//  
// Purpose:     Combines two clipping regions using the passed clipping mode 
//				The combined result will be placed in a new region 
// 
// Parameters:  rgn1	- [in] this region will copied first 
//				rgn2	- [in] this region will be combined with the copy 
//				mode	- [in] the clipping mode 
//				 
// Returns:     index to layer added 
// 
int Stack::CombineRgnCreate(int rgn1, int rgn2, int mode) 
{ 
	ASSERT(rgn1 != NULL && rgn2 != NULL); 
 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = COMBINENEW; 
	m_Layers[layer].clipMode = mode; 
	m_Layers[layer].rgnIndex[0] = rgn1; 
	m_Layers[layer].rgnIndex[1] = rgn2; 
 
	return layer;	 
} 
 
//============================================================================= 
// 
// ApplyClipRgn()  
//  
// Purpose:     Replace the current clipping region 
// 
// Parameters:  region		- [in] the new region 
//				 
// Returns:     index to layer added 
// 
int Stack::ApplyClipRgn(int region) 
{ 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = APPLYCLIP; 
	m_Layers[layer].rgnIndex[0] = region; 
 
	return layer;	 
} 
 
//============================================================================= 
// 
// ResetClip()  
//  
// Purpose:     Restores the clipping region to the Fram region 
// 
// Parameters:  None 
//				 
// Returns:     index to layer added 
// 
int Stack::ResetClipRgn() 
{ 
	int layer = AddLayer(); 
	m_Layers[layer].LayerType = RESTORECLIP; 
	return layer;	 
} 
 
//============================================================================= 
// 
// ApplyBlur()  
//  
// Purpose:     Applies a blur effect to the current frame 
// 
// Parameters:  width		- [in] the amount of blur 
//				 
// Returns:     index to layer added 
// 
int Stack::FillBlur(int region, Clr clr, int width) 
{ 
	int layer = AddLayer(); 
	m_Layers[layer].clr1 = clr.value; 
	m_Layers[layer].LayerType = REGIONBLUR; 
	m_Layers[layer].width = width; 
	m_Layers[layer].rgnIndex[0] = region; 
	return layer;	 
} 
 
//============================================================================= 
// 
// AddImage()  
//  
// Purpose:     Adds an image to the stack 
// 
// Parameters:  pt			- [in] offset into the layer rect 
//				id			- [in] resource id 
//				type		- [in] resource type 
//				clip		- [in] TRUE if clipped, else streched 
//				Alpha		- [in] opacity to apply to image (future) 
//				 
// Returns:     index to layer added 
// 
int Stack::AddImage(SPoint sp, UINT id, LPCTSTR type, int clip, int Alpha) 
{ 
	IMAGEINFO ii; 
	::ZeroMemory(&ii, sizeof(IMAGEINFO)); 
 
	ii.destpt = sp.point; 
	ii.resID = id; 
	ii.resType = type; 
	ii.ialpha = Alpha; 
	ii.clip = clip; 
 
	Layers::m_Images.push_back(ii); 
 
	int layer = AddLayer(); 
	m_Layers[layer].LayerType = IMAGE; 
	m_Layers[layer].imgIndex = (m_Images.size() - 1); 
 
	return layer; 
} 
 
//============================================================================= 
// 
// AddImage()  
//  
// Purpose:     Adds an image to the stack 
// 
// Parameters:  dest		- [in] images destination within the layer rect 
//				src			- [in] src rect within the image 
//				id			- [in] resource id 
//				type		- [in] resource type 
//				clip		- [in] TRUE if clipped, else streched 
//				Alpha		- [in] opacity to apply to image (future) 
//				 
// Returns:     index to layer added 
// 
int Stack::AddImage(SPoint dest, SPoint src, UINT id, LPCTSTR type, int clip, int Alpha) 
{ 
	IMAGEINFO ii; 
	::ZeroMemory(&ii, sizeof(IMAGEINFO)); 
	 
	ii.destpt = dest.point; 
	ii.srcpt = src.point; 
	ii.resID = id; 
	ii.resType = type; 
	ii.ialpha = Alpha; 
	ii.clip = clip; 
 
	m_Images.push_back(ii); 
 
	int layer = AddLayer(); 
	m_Layers[layer].LayerType = IMAGE; 
	m_Layers[layer].imgIndex = (m_Images.size() - 1); 
 
	return layer; 
} 
 
//============================================================================= 
// 
// AddString()  
//  
// Purpose:     Adds a string to the stack 
// 
// Parameters:  str			- [in] the CString to add 
//				offset		- [in] CPoint offset into the Frame rect 
//				clr			- [in] sting color 
//				size		- [in] vertical size of the string 
//				style		- [in] the font style (one of enum FontStyles) 
//				name		- [in] Font Family name string 
//				 
// Returns:     index to layer added 
// 
int Stack::AddString(CString str, SPoint offset, Clr clr, int size, int style, WCHAR* name) 
{ 
	TEXTINFO ti; 
 
	::ZeroMemory(&ti, sizeof(TEXTINFO)); 
 
	memcpy(ti.fname, name, 2*wcslen(name)); 
	ti.fsize = size; 
	ti.fstyle = style; 
	ti.fclr = clr.value; 
	ti.foffset.X = (float)offset.point.X; 
	ti.foffset.Y = (float)offset.point.Y; 
	ti.align = -1;						// flag paint function to use offset 
 
	// convert the CString to wstring 
	size_t cssize = strlen(str) + 1; 
	size_t wcsize = cssize*sizeof(wchar_t); 
	ti.string.reserve(wcsize);  
 
	wchar_t *pwstr = (wchar_t*)malloc(wcsize); 
	 
	MultiByteToWideChar(CP_ACP, 0, str, cssize, pwstr, wcsize); 
 
	ti.string = pwstr; 
 
	m_Strings.push_back(ti); 
 
	free(pwstr); 
 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = STRING; 
	m_Layers[layer].strIndex = (m_Strings.size() - 1); 
 
	return layer; 
} 
 
//============================================================================= 
// 
// AddAString()  
//  
// Purpose:     Adds a string to the stack with alignment 
// 
// Parameters:  str			- [in] the CString to add 
//				alignment	- [in] the string alignment (one of enum StringAlign) 
//				xoffset		- [in] additional offset in case of image  
//				clr			- [in] sting color 
//				size		- [in] vertical size of the string 
//				style		- [in] the font style (one of enum FontStyles) 
//				name		- [in] Font Family name string 
//				 
// Returns:     index into the array of where the string was added 
// 
int	Stack::AddAString(	CString str, int alignment, int xoffset, Clr clr, 
					    int size, int style, WCHAR* name) 
{ 
	TEXTINFO ti; 
 
	::ZeroMemory(&ti, sizeof(TEXTINFO)); 
 
	memcpy(ti.fname, name, 2*wcslen(name)); 
	ti.fsize = size; 
	ti.fstyle = style; 
	ti.fclr = clr.value; 
	ti.align = alignment; 
	ti.foffset.X = (float)xoffset; 
 
	// convert the CString to wstring 
	size_t cssize = strlen(str) + 1; 
	size_t wcsize = cssize*sizeof(wchar_t); 
	ti.string.reserve(wcsize);  
 
	wchar_t *pwstr = (wchar_t*)malloc(wcsize); 
	 
	MultiByteToWideChar(CP_ACP, 0, str, cssize, pwstr, wcsize); 
 
	ti.string = pwstr; 
 
	m_Strings.push_back(ti); 
 
	free(pwstr); 
 
	int layer = AddLayer(); 
 
	m_Layers[layer].LayerType = STRING; 
	m_Layers[layer].strIndex = (m_Strings.size() - 1); 
 
	return layer; 
} 
 
 
//============================================================================= 
// 
// AddAString()  
//  
// Purpose:     Adds a string to the stack with alignment 
// 
// Parameters:  str			- [in] the CString to add 
//				alignment	- [in] the string alignment (one of enum StringAlign) 
//				xoffset		- [in] additional offset in case of image  
//				clr			- [in] sting color 
//				size		- [in] vertical size of the string 
//				style		- [in] the font style (one of enum FontStyles) 
//				name		- [in] Font Family name string 
//				 
// Returns:     index into the array of where the string was added 
// 
int	Stack::AddAString(	SRect sr, CString str, int alignment, Clr clr, 
					    int size, int style, WCHAR* name) 
{ 
	TEXTINFO ti; 
 
	::ZeroMemory(&ti, sizeof(TEXTINFO)); 
 
	memcpy(ti.fname, name, 2*wcslen(name)); 
	ti.fsize = size; 
	ti.fstyle = style; 
	ti.fclr = clr.value; 
	ti.align = alignment; 
 
	// convert the CString to wstring 
	size_t cssize = strlen(str) + 1; 
	size_t wcsize = cssize*sizeof(wchar_t); 
	ti.string.reserve(wcsize);  
 
	wchar_t *pwstr = (wchar_t*)malloc(wcsize); 
	 
	MultiByteToWideChar(CP_ACP, 0, str, cssize, pwstr, wcsize); 
 
	ti.string = pwstr; 
 
	m_Strings.push_back(ti); 
 
	free(pwstr); 
 
	int layer = AddLayer(); 
 
	m_Layers[layer].lrect = sr.rect; 
	m_Layers[layer].LayerType = STRING; 
	m_Layers[layer].strIndex = (m_Strings.size() - 1); 
 
	return layer; 
}