#include "stdafx.h"

#define APL_REPORT_IMPL

#include "aplReport.h"
#include <aplXML.h>
#include <aplPdf.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//bool RotateBitmap(CBitmap &bmp, int angle);

CaplReportField::CaplReportField()
{
	Init();
}

void CaplReportField::Init()
{
	m_x=0; m_y=0; m_cx=0; m_cy=0; m_font_index=-1; m_pen_index=-1; m_top_pen_index=-1;
	m_h_allign=_T('l'); m_v_allign=_T('m'); m_image=0; m_angle=0; m_inst=0;
	m_ident_x=0; m_ident_y=0;
	m_sCondition=0;
}
CaplReportField::CaplReportField(LPCTSTR text, float cx, float cy, LPCTSTR pen_id, LPCTSTR font_id, TCHAR h_align, TCHAR v_align) 
{
	Init();
	m_text=text; m_cx=cx; m_cy=cy; m_pen_id = pen_id;  m_font_id=font_id; m_h_allign=h_align; m_v_allign=v_align;
}

CaplReportField::CaplReportField(CaplReportField *src_field)
{
	Init();
	if(0==src_field)  return;

	m_x=src_field->m_x;
	m_y=src_field->m_y;
	m_cx=src_field->m_cx;
	m_cy=src_field->m_cy;
	m_v_allign=src_field->m_v_allign;
	m_h_allign=src_field->m_h_allign;
	m_field=src_field->m_field;
	m_text=src_field->m_text;
	m_font_index=src_field->m_font_index;
	m_pen_index=src_field->m_pen_index;
	m_top_pen_index=src_field->m_top_pen_index;
	m_font_id=src_field->m_font_id;
	m_pen_id=src_field->m_pen_id;
	m_top_pen_id=src_field->m_top_pen_id;
	m_image=src_field->m_image;
	m_angle=src_field->m_angle;
	m_inst=src_field->m_inst;
	m_data=src_field->m_data;
	m_ident_x=src_field->m_ident_x;
	m_ident_y=src_field->m_ident_y;
}

CaplReportField::CaplReportField(LPCTSTR text, CaplReportTableColumn *src_column, bool bCopyPen)
{
	ASSERT(0!=src_column);

	Init();
	m_text=text;
	m_cx=src_column->m_cx;
	m_cy=src_column->m_table->m_row_cy;
	m_v_allign=src_column->m_v_allign;
	m_h_allign=src_column->m_h_allign;
	//m_field=;
	//m_text=;
	m_font_index=src_column->m_font_index;

	if(bCopyPen)
	{
		m_pen_index=src_column->m_table->m_pen_index;
		m_pen_id=src_column->m_table->m_pen_id;
	}

	m_font_id=src_column->m_font_id;
	//m_top_pen_id=;
	//m_data=;
	m_ident_x=src_column->m_ident_x;
	m_ident_y=src_column->m_ident_y;
}

CaplReportField::~CaplReportField()
{
	if(0!=m_sCondition) {delete m_sCondition; m_sCondition=0;}
}

//******************************************************************
//******************************************************************
//******************************************************************
CaplReportImage::~CaplReportImage()
{
	if(0!=m_pdf) delete m_pdf;
	if(0!=m_blob) delete m_blob;
};

//******************************************************************
//******************************************************************
//******************************************************************

CaplReportPage::CaplReportPage(CaplReportPage *src_page)
{
	if(0==src_page) return;
	m_table=0;
	m_report=src_page->m_report;
	m_cx_mm=src_page->m_cx_mm;
	m_cy_mm=src_page->m_cy_mm;
	m_name=src_page->m_name;
	m_cx=0;
	m_cy=0;
	int i;
	for(i=0; i<src_page->m_fields.GetSize();i++)
	{
		m_fields.Add(new CaplReportField(src_page->m_fields[i]));
	}
	if(src_page->m_table!=0) m_table=new CaplReportTable(src_page->m_table);
}

void CaplReportPage::Clear()
{
	m_fields.Clear();
	if(0!=m_table) {delete m_table; m_table=0;}
}

CaplPdfPage *CaplReportImage::LoadImage()
{
	if(0!=m_pdf)
	{
		CaplPdfPage *page=m_pdf->GetActualPage();
		if(0==page) page=m_pdf->LoadPage(0);
		return page;
	}
	if(0==m_blob_size || 0==m_blob) return 0;

#ifdef UNICODE
	// временная затычка (aplPDF для Unicode на данный момент не готов)
	return NULL;
#else
	CaplPdf *pdf=new CaplPdf;
	CString sFileExt;
	int i=m_name.ReverseFind(_T('.'));
	if(i>=0)sFileExt=m_name.Right(m_name.GetLength()-i);
	
	if(!pdf->OpenFileFromMemory(m_blob,m_blob_size,sFileExt,false)){ delete pdf; return 0;}
	CaplPdfPage *pdfPage=pdf->LoadPage(0);
	if(0==pdfPage) { delete pdf; return 0;}

	m_pdf=pdf;	
	return pdfPage;
#endif
}


void CaplReportImage::FreeImage()
{
	if(0==m_pdf) return;
	delete m_pdf;
	m_pdf=0;
}



//******************************************************************
//******************************************************************
//******************************************************************

bool CaplReportPage::GetCurImageSize(int &cx, int &cy)
{
	cx=m_cx;
	cy=m_cy;
	if(0==m_cx || 0==cy) return false;
	return false;
}
//******************************************************************
bool CaplReportPage::GetOriginalSizeIn_mm(float &cx, float &cy) // Возвращает размер страницы в мм
{
	cx=(float)m_cx_mm; cy=(float)m_cy_mm;
	return true;
}

//******************************************************************
bool CaplReportPage::ConvertPointFromOrigUnit(float  x0, float y0, int &x1, int &y1)
{
	x1=0; y1=0;
	if(0==m_cx || 0==m_cx_mm ) return false;

	//float k= ((float)25.4/72)*(m_cx/m_cx_mm);

	float k;
	if(90==m_cur_angle || 270== m_cur_angle)k=(float)m_cx/m_cy_mm;
	else k=(float)m_cx/m_cx_mm;
	
	k*=(float)25.4/72;

	x1=(int)(x0*k);
	y1=(int)(y0*k);

	if(0!=m_cur_angle)
	{
		if(180==m_cur_angle) {x1=m_cx-x1; y1=m_cy-y1;}
		else if( 90==m_cur_angle) {int tmp=x1; x1=m_cx-y1; y1=tmp;}
		else if(270==m_cur_angle) {int tmp=x1; x1=y1; y1=m_cy-tmp;}
	}	
	return true;
}
//******************************************************************
bool CaplReportPage::ConvertPointToOrigUnit(int  x0, int y0, float &x1, float &y1)
{
	x1=0; y1=0;
	if(0==m_cx || 0==m_cx_mm ) return false;

	float k= (float)(72/25.4)*(m_cx_mm/m_cx);
	x1=(float)(x0*k);
	y1=(float)(y0*k);

	return true;
}

//******************************************************************
//******************************************************************
//******************************************************************
void CaplReportPage::FreeBitmap()
{
	if(0!=m_bitmap.m_hObject) m_bitmap.DeleteObject();
	if(0!=m_comp_dc.m_hDC) m_comp_dc.DeleteDC();
	m_cx=0;
	m_cy=0;
}

bool CaplReportPage::Make2Cx(CDC *dc, int cx, int rotation, int start_strech_k, CString *sCondition)
{
	if(m_cx==cx && m_cur_angle == rotation) return true;  // Все уже готово

	if(0==m_cx_mm || 0==m_cy_mm ) return false;
	//m_cx=cx;
	//m_cy=(int)((float)cx*m_cy_mm/m_cx_mm);
	//CDC m_comp_dc;
	//CBitmap m_bitmap;

	m_bitmap.DeleteObject();
	m_comp_dc.DeleteDC();
	m_comp_dc.CreateCompatibleDC(dc);
	m_comp_dc.SelectObject(&m_bitmap);

	int cx0=cx; // ширина картинки с учетом что будем поворачивать
	if(rotation==90 || rotation==270) 
		cx0=(int) ((float)cx*m_cx_mm/m_cy_mm);
	
	m_strech_k=1;

	if(start_strech_k!=0) m_strech_k=start_strech_k;

	int img_cx,img_cy;
	while(true)
	{
		img_cx=(int)(cx0/m_strech_k);
		img_cy=(int) (((float)img_cx*m_cy_mm)/(m_cx_mm));
		
		if(m_bitmap.CreateCompatibleBitmap(dc,img_cx,img_cy)) break; // получилось выделить память
		if(img_cx<512) // Если, уж, и такая картина не влезала в память, то дальше уменьшать смысла нет
		{
			m_comp_dc.DeleteDC();
			return false;
		}
		m_strech_k++;

	}
	m_comp_dc.SelectObject(m_bitmap);

	m_cx=img_cx*m_strech_k; // по идее, это то же что и img_cx, но на всякий случай
	m_cy=img_cy*m_strech_k;
	m_cur_angle=rotation;

	/*m_comp_dc.FillSolidRect(0,0,img_cx,img_cy,RGB(255,0,0));
	CPen pen(PS_SOLID,3,RGB(0,255,0));
	m_comp_dc.SelectObject(&pen);
	m_comp_dc.MoveTo(0,0);
	m_comp_dc.LineTo(img_cx,img_cy);
	m_comp_dc.MoveTo(0,img_cy);
	m_comp_dc.LineTo(img_cx,0);*/

	CBrush fon_brush(RGB(255,255,255));
	RECT rect; rect.left=0; rect.top=0; rect.right=img_cx; rect.bottom=img_cy;
	m_comp_dc.FillRect(&rect,&fon_brush);

	float k_pix=(float)(img_cx/m_cx_mm);

	DrawConrent(m_comp_dc,k_pix, sCondition);

	if(rotation!=0) 
	{
		TRACE(_T("\n\nrotate image %i \n"),rotation);
		//BITMAP BitMap,BitMap1;
		//m_bitmap.GetBitmap(&BitMap);
		if(!CaplReport::RotateBitmap(m_bitmap,rotation)) return false;
		//m_bitmap.GetBitmap(&BitMap1);
		m_comp_dc.SelectObject(m_bitmap);
		if(rotation==90 || rotation==270) {int t=m_cx; m_cx=m_cy; m_cy=t;}

	}
	return true;
} 
//******************************************************************
//******************************************************************
//******************************************************************
bool CaplReportPage::Draw(CDC *dc, int x0, int y0, int cx, int cy, int x1, int y1, CDC *dc4draw)
{
	/*RECT rect;
	rect.left=x1;
	rect.right=rect.left+cx;
	rect.top=y1;
	rect.bottom=rect.top+cy;
	dc->FillSolidRect(&rect,RGB(0,255,0));*/

	if(0==dc) return false;
	if(0==m_cx_mm) return false;
	if(m_cx<=0) return false;

	CDC *src_dc=&m_comp_dc;
	if(0!=dc4draw) 
		src_dc=dc4draw;

	if(0!=m_bitmap.m_hObject && 0!=src_dc->m_hDC)
	{
		//if(m_cx<cx) cx=m_cx;
		//if(m_cy<cy) cy=m_cy;

		if(1==m_strech_k)
		{
			// ЯАИ: Выигрыш от отрисовки только части составил 1%. Похоже BitBlt сама копирует только нужное	
			dc->BitBlt(x1,y1,cx,cy,src_dc,x0,y0,SRCCOPY); //только видимое
			//dc->BitBlt(x1,y1,m_cx,m_cy,&m_comp_dc,0,0,SRCCOPY); //все целиком
			m_sLog =APL_T("CaplReportPage::Draw  используется BitBlt");
		}
		else
		{
			//dc->FillSolidRect(x1,y1,cx,cy,RGB(0,0,255));
			dc->StretchBlt(x1,y1,cx,cy,src_dc,x0/m_strech_k,y0/m_strech_k,cx/m_strech_k,cy/m_strech_k,SRCCOPY);
			m_sLog =APL_T("CaplReportPage::Draw  используется StretchBlt");
		}
	}
	else
	{
		dc->FillSolidRect(x0,y0,cx,cy,RGB(255,255,255));
		m_sLog =APL_T("CaplReportPage::Draw  Заливка белым т.к. нет картинки");
	}

	return true;
}
//***********************************************************
//***********************************************************
//***********************************************************
void CaplReportPage::DrawConrent(CDC &dc, float k, CString *sCondition)
{
	dc.SetTextColor(RGB(0,0,0));
	int i,n;
	CPen *pens=0;
	CFont *fonts=0;

	float fMinKfont=(float)CaplReport::m_font_reduce_percent/100;
	if(fMinKfont>1) fMinKfont=1; 
	else if(fMinKfont<0.1) fMinKfont=(float)0.1;

	n=m_report->m_pens.GetSize();
	if(n>0)
	{
		pens=new CPen[n];
		for(i=0;i<n;i++)
		{
			CaplReportPen *rpen=m_report->m_pens[i];
			int pen_stype=PS_SOLID|PS_GEOMETRIC;
			if(0==rpen->m_width) pen_stype=PS_NULL;
			pens[i].CreatePen(pen_stype,(int)(rpen->m_width*k), rpen->m_color);
		}
	}
	n=m_report->m_fonts.GetSize();
	if(n>0)
	{
		fonts=new CFont[n];
		for(i=0;i<n;i++)
		{
			CaplReportFont *rfont=m_report->m_fonts[i];
			int nWeight= FW_NORMAL; if(rfont->m_bBold)  nWeight=FW_BOLD;
			BYTE Underline=0; if(rfont->m_bUnderline)Underline=1;
			BYTE Italic=0; if(rfont->m_bItalic) Italic=1;
			int high=(int)(-rfont->m_size*k);
			fonts[i].CreateFont(high,0,0,0,nWeight,Italic,Underline,0,RUSSIAN_CHARSET,0,0,0,0,rfont->m_name);
		}
	}

	/*{
		CFont f1;  f1.CreateFont(40,0,900,900,0,0,0,0,RUSSIAN_CHARSET,0,0,0,0,_T("Arial"));
		dc.SelectObject(&f1);
		RECT rect; rect.left=100; rect.top=500; rect.right=400; rect.bottom=540;
		dc.Draw3dRect(&rect,RGB(255,0,0),RGB(255,0,0));
		rect.left=100; rect.top=500; rect.right=640; rect.bottom=200;
		dc.DrawText(_T("AAAAAAA"),&rect,DT_RIGHT);
		dc.Draw3dRect(&rect,RGB(0,0,255),RGB(255,0,255));
	}*/

	if(0!=sCondition) { if(sCondition->IsEmpty()) sCondition=0;} // Чтобы быстрее работало

	for(i=0;i<m_fields.GetSize();i++)
	{
		CaplReportField *field=m_fields[i];

		if(0!=field->m_sCondition) // Проверяем условие отрисовки
		{
			if(0==sCondition) continue;
			if(sCondition->Find(*field->m_sCondition) < 0) continue;
		}

		int x=(int)(field->m_x*k);
		int y=(int)(field->m_y*k);
		int cx=(int)(field->m_cx*k);
		int cy=(int)(field->m_cy*k);

		int lt_h=(int)(1.5*k); // горизонтальный отступ для текста  1.5 мм
		int lt_v=(int)(0.5*k); // вертикальный отступ для текста  0.5 мм

		if(0!=field->m_ident_x) lt_h=(int)(field->m_ident_x*k);
		if(0!=field->m_ident_y) lt_v=(int)(field->m_ident_y*k);

		if(field->m_pen_index>=0)
		{
			// рисуем прямоугольник
			dc.SelectObject(pens[field->m_pen_index]);
			dc.MoveTo(x,y);
			dc.LineTo(x+cx,y);
			dc.LineTo(x+cx,y+cy);
			dc.LineTo(x,y+cy);
			dc.LineTo(x,y);

			//lt+=(int)(k*((m_report->m_pens[field->m_pen_index])->m_width));
		}

		if(field->m_top_pen_index>=0)
		{
			// рисуем линию сверху
			dc.SelectObject(pens[field->m_top_pen_index]);
			dc.MoveTo(x,y);
			dc.LineTo(x+cx,y);
		}

		if(field->m_font_index>=0)	dc.SelectObject(fonts[field->m_font_index]);

		CString *text=0;
		if(field->m_text!=_T("")) text=&(field->m_text);
		else if(field->m_field!=_T("") && m_report->IsTemplate()) text= &(field->m_field);

		RECT rect;

		if(field->m_angle==90)
		{
			rect.left=x+lt_v; rect.right=rect.left+cx-(2*lt_v);
			rect.top=y+lt_h;  rect.bottom=rect.top+cy-(2*lt_h);	
		}
		else
		{
			rect.left=x+lt_h; rect.right=rect.left+cx-(2*lt_h);
			rect.top=y+lt_v;  rect.bottom=rect.top+cy-(2*lt_v);	
		}
		
		CFont tmp_font;
		if(0!=text)
		{
			/*if(field->m_field==_T("id"))
			{
				int a=0;
			}*/

			if(*text!="")
			{
				CFont *font=0;
				if(field->m_font_index>=0)	font=&(fonts[field->m_font_index]);
				if(0==font) font=dc.GetCurrentFont();
				dc.SelectObject(font);

				if(0==field->m_angle)
				{
					RECT rect1=rect;
					int iCalcFormat=DT_WORDBREAK|DT_LEFT|DT_TOP|DT_CALCRECT;

					dc.DrawText(*text,&rect1,iCalcFormat);

					if(rect1.bottom > rect.bottom || rect1.right>rect.right)
					{
						// Подбираем шрифт чтобы влезло
						LOGFONT lf;
						font->GetLogFont(&lf);
						double kfont=1;
						int lfHeight=lf.lfHeight;
						while(kfont>=fMinKfont) // Уменьшаем не более чем до 30 %
						{
							kfont*=0.95;
							lf.lfHeight=(int)(kfont*lfHeight);
							tmp_font.DeleteObject();
							tmp_font.CreateFontIndirect(&lf);
							dc.SelectObject(&tmp_font);
							rect1=rect;
							dc.DrawText(*text,&rect1,iCalcFormat);
							if(rect1.bottom < rect.bottom && rect1.right< rect.right) break;
						}
					}

					int iOutFormat=DT_WORDBREAK;

					if (_T('l')==field->m_h_allign) iOutFormat|=DT_LEFT;
					else if (_T('r')==field->m_h_allign) iOutFormat|=DT_RIGHT;
					else iOutFormat|=DT_CENTER;

					RECT rect_text_out=rect;

					if(rect1.bottom<rect.bottom) // А если не влазит, то сверху
					{
						// Для многострочного текста выравнивание не работает, поэтому так
						int dy=rect1.bottom-rect1.top; // высота текста
						if(field->m_v_allign==_T('m')) rect_text_out.top+=(int)(((rect.bottom-rect.top)-dy)/2);
						else if (field->m_v_allign==_T('b'))rect_text_out.top=rect.bottom-dy;
					}

					//dc.Draw3dRect(&rect_text_out,RGB(0,255,0),RGB(0,255,0)); // Для отладки
					dc.DrawText(*text,&rect_text_out,iOutFormat);
				}
				else if(90==field->m_angle) 
				{
					// При повернутом тексте вырввнивание, по сути никак не работает

					LOGFONT lf;
					CFont *curfont=dc.GetCurrentFont();
					if(0!=curfont)
					{
						curfont->GetLogFont(&lf);
						lf.lfEscapement=field->m_angle*10;
						lf.lfOrientation=field->m_angle*10;
						tmp_font.DeleteObject();
						tmp_font.CreateFontIndirect(&lf);
						dc.SelectObject(&tmp_font);
					}

					int t=rect.top; rect.top=rect.bottom; rect.bottom=t;  // Ибо так рисуется повернутый текст

					RECT rect1=rect;
					int iFormat=/*DT_WORDBREAK|*/DT_SINGLELINE|DT_TOP|DT_LEFT;

					dc.DrawText(*text,&rect1,iFormat|DT_CALCRECT);

					//dc.Draw3dRect(&rect1,RGB(0,255,255),RGB(0,255,255)); // Для отладки

					int txt_h=rect1.right-rect1.left;
					int txt_w=rect1.bottom-rect1.top; // Ибо прямоугольник возвращается повернутым

					int rect_cy=rect.top-rect.bottom;
					int rect_cx=rect.right-rect.left;

					if( (txt_w>rect_cx) || (txt_h>rect_cy) )
					{
						// Подбираем шрифт чтобы влезло
						LOGFONT lf;
						CFont *curfont1=dc.GetCurrentFont();
						curfont1->GetLogFont(&lf);
						double kfont=1;
						int lfHeight=lf.lfHeight;
						while(kfont>=fMinKfont)
						{
							kfont*=0.95;
							lf.lfHeight=(int)(kfont*lfHeight);
							tmp_font.DeleteObject();
							tmp_font.CreateFontIndirect(&lf);
							dc.SelectObject(&tmp_font);
							rect1=rect;
							dc.DrawText(*text,&rect1,iFormat|DT_CALCRECT);

							txt_h=rect1.right-rect1.left; // Ибо прямоугольник возвращается повернутым
							txt_w=rect1.bottom-rect1.top;

							if(  (txt_w<=rect_cx) && (txt_h<=rect_cy)) break;
						}
						int a=0;
					}

					RECT rect_text_out=rect;

					if((rect.right-rect.left)>txt_w)
					{
						if (_T('c')==field->m_h_allign) rect_text_out.left+=(int)(((rect.right-rect.left)-txt_w)/2);
						else if (_T('r')==field->m_h_allign) rect_text_out.left=rect_text_out.right-txt_w;
					}

					if((rect.top-rect.bottom)>txt_h) // Не забываем что прямоугольник перевернут
					{
						if (_T('m')==field->m_v_allign) rect_text_out.top-=(int)(((rect.top-rect.bottom)-txt_h)/2);
						else if (_T('t')==field->m_v_allign) 
							rect_text_out.top=rect_text_out.bottom+txt_h;
					}

					//dc.Draw3dRect(&rect_text_out,RGB(0,255,0),RGB(0,255,0)); // Для отладки
					dc.DrawText(*text,&rect_text_out,iFormat);
				}
			} // Конец вывода текста
		}

		// рисуем таблицу
		if(0!=m_table)
		{
			int x=(int)(m_table->m_x*k);
			int y=(int)(m_table->m_y*k);
			int cx=(int)(m_table->m_cx*k);
			int cy=(int)(m_table->m_cy*k);

			if(m_table->m_pen_index>=0)
			{
				// рисуем прямоугольник
				dc.SelectObject(pens[m_table->m_pen_index]);
				dc.MoveTo(x,y);
				dc.LineTo(x+cx,y);
				dc.LineTo(x+cx,y+cy);
				dc.LineTo(x,y+cy);
				dc.LineTo(x,y);

				if(m_table->m_row_cy>0.1)
				{
					float frh=m_table->m_y;
					while(true)
					{
						frh+=m_table->m_row_cy;
						if(frh>=(m_table->m_y+m_table->m_cy)) break;
						int rh=(int)(frh*k);
						dc.MoveTo(x,rh);
						dc.LineTo(x+cx,rh);
					}
				}
				int jc;
				float fx_column=m_table->m_x;
				for(jc=0;jc<m_table->m_columns.GetSize();jc++)
				{
					float fcx=m_table->m_columns[jc]->m_cx;
					if(fcx<=0) continue;
					fx_column+=fcx;
					int x_column=(int)(fx_column*k);

					dc.MoveTo(x_column,y);
					dc.LineTo(x_column,y+cy);
				}
			}
		}


		if(0!=field->m_image)
		{
			DrawImageInField(field,&dc,rect);
		}
	}
	if(0!=pens) delete [] pens;
	if(0!=fonts) delete [] fonts;
}


bool CaplReportPage::DrawImageInField(CaplReportField *field, CDC *dc, RECT &rect)
{
	if(0==field || 0==dc) return false;
	CaplReportImage *image=field->m_image;
	if(0==image) return false;

	CaplPdfPage *pdfPage=image->LoadImage();
	if(0==pdfPage) return false;

	// Вычисляем cx
	int rcx=rect.right-rect.left;
	int rcy=rect.bottom-rect.top;
	if(rcx<1) return false;
	
	float fcx,fcy;
	pdfPage->GetOriginalSize(fcx,fcy);

	int dx=0,dy=0; // Отсупы для выравнивания
	
	// размеры картинки
	int cx=rcx;
	int cy=(int)((fcy/fcx)*cx);

	if(cy>rcy) // картинка не влазит по высоте -> уменьшаем cx
	{
		cy=rcy;
		cx=(int)((fcx/fcy)*cy);

		if(field->m_h_allign==_T('r')) dx=rcx-cx;
		else  if(field->m_h_allign==_T('c')) dx=(int)((rcx-cx)/2);
	}

	pdfPage->Make2Cx(dc,cx,0);
	pdfPage->Draw(dc,0,0,cx,cy,rect.left+dx,rect.top+dy);
	return true;
}
//********************************************************
//********************************************************
//********************************************************
CaplReportTableColumn::CaplReportTableColumn(CaplReportTable *table, CaplReportTableColumn *src_column)
{
	m_table=table;

	m_id=src_column->m_id;
	m_cx=src_column->m_cx;
	m_ident_x=src_column->m_ident_x;
	m_ident_y=src_column->m_ident_y;

	m_v_allign=src_column->m_v_allign;  
	m_h_allign=src_column->m_h_allign;

	m_font_index=src_column->m_font_index;
	m_font_id=src_column->m_font_id; 
}
//********************************************************
CaplReportTable::CaplReportTable(CaplReportTable *src_table)
{
	VERIFY(0!=src_table);
	m_id=src_table->m_id;;
	m_x=src_table->m_x;
	m_y=src_table->m_y;
	m_cx=src_table->m_cx;
	m_cy=src_table->m_cy;
	m_row_cy=src_table->m_row_cy;
	m_pen_index=src_table->m_pen_index;
	m_pen_id=src_table->m_pen_id;

	int i;
	for(i=0;i<src_table->m_columns.GetSize();i++)
	{
		m_columns.Add(new CaplReportTableColumn(this,src_table->m_columns[i]));
	}
}