#include "StdAfx.h"
#include "aplPdf.h"

#undef  UNUSED // т.к. переопределяется
extern "C" {
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
}

#if _MSC_VER < 1600
	#ifdef _DEBUG
		#pragma comment (lib,"mupdf\\Debug\\libmupdf.lib")
		//#pragma comment (lib,"mupdf\\Debug\\libmupdf-js-none.lib")
		#pragma comment (lib,"mupdf\\Debug\\libthirdparty.lib")
		#pragma comment (lib,"mupdf\\Release\\libfonts.lib")
	#else 
		#pragma comment (lib,"mupdf\\Release\\libmupdf.lib")
		//#pragma comment (lib,"mupdf\\Release\\libmupdf-js-none.lib")
		#pragma comment (lib,"mupdf\\Release\\libthirdparty.lib")
		#pragma comment (lib,"mupdf\\Release\\libfonts.lib")
	#endif
#else
	#ifdef _DEBUG
		#pragma comment (lib,"mupdf\\Debug\\libmupdf_2015.lib")
		//#pragma comment (lib,"mupdf\\Debug\\libmupdf-js-none_2015.lib")
		#pragma comment (lib,"mupdf\\Debug\\libthirdparty_2015.lib")
		#pragma comment (lib,"mupdf\\Release\\libfonts_2015.lib")
	#else 
		#pragma comment (lib,"mupdf\\Release\\libmupdf_2015.lib")
		//#pragma comment (lib,"mupdf\\Release\\libmupdf-js-none_2015.lib")
		#pragma comment (lib,"mupdf\\Release\\libthirdparty_2015.lib")
		#pragma comment (lib,"mupdf\\Release\\libfonts_2015.lib")
	#endif
#endif

#define mm_ctx (fz_context*)m_ctx
#define mm_fz_doc (fz_document*)m_fz_doc
#define mm_fz_page (fz_page*)m_fz_page
//#define mm_pix (fz_pixmap*)m_pix

CaplPdf::CaplPdf()
{
	m_ctx=0;
	m_fz_doc=0;
	m_page=0;
	m_PagesCount=0;
	m_CurPage=0;
	m_file_buf=0;

}

CaplPdf::~CaplPdf()
{
	CloseFile();
}



bool CaplPdf::OpenFile(LPCTSTR fname)
{
	CloseFile();

	CString sFname=fname;
	if(sFname==_T("")) return false;

	int i=sFname.ReverseFind(_T('.'));
	if(i<0) return false;
	CString sFileExt=sFname.Right(sFname.GetLength()-(i+1));

	CFile file;
	if(!file.Open(sFname,CFile::modeRead|CFile::shareDenyWrite|CFile::typeBinary)) return false;
	CFileStatus fstatus;
	file.GetStatus(fstatus);
	if(0==fstatus.m_size) {file.Close(); return false;}

	unsigned char *file_buf=new unsigned char[fstatus.m_size];
	if(!file.Read(file_buf,fstatus.m_size)){delete file_buf; file_buf=0; file.Close(); return false;}
	file.Close();
	m_file_buf=file_buf;
	return OpenFileFromMemory(file_buf,fstatus.m_size,LPCTSTR(sFileExt),false);
}
bool CaplPdf::OpenFileFromMemory(unsigned char *mem, ULONG memsize, LPCTSTR file_ext, bool bCreateCopyMemory)
{
	if(0==mem) return false;
	if(0==m_ctx) m_ctx = (p_fz_context) fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
	if(0==m_ctx) return false;

	pdf_install_load_system_font_funcs(mm_ctx);
	fz_register_document_handlers(mm_ctx);

	//m_fz_doc = (p_fz_document) fz_open_document(mm_ctx, fname);
	//if(0==m_fz_doc) return false;

	unsigned char *mem1=mem;
	if(bCreateCopyMemory) 
	{
		if(0!=m_file_buf) delete m_file_buf;
		m_file_buf=new unsigned char[memsize];
		memcpy(m_file_buf,mem,memsize);
		mem1=m_file_buf;
	}

	fz_stream *fz_stream0= fz_open_memory(mm_ctx, mem1, memsize);
	if(0==fz_stream0) {CloseFile(); return false;}

	CString sMagic=_T("0."); sMagic+=file_ext;

#ifndef UNICODE
	m_fz_doc=fz_open_document_with_stream(mm_ctx, LPCSTR(sMagic), fz_stream0);
	//m_fz_doc=fz_open_document_with_stream(mm_ctx, file_ext, fz_stream0);
#else
	CHAR szTmp[64];
	WideCharToMultiByte(0, 0, LPCWSTR(sMagic),-1, szTmp, 64, NULL, NULL);
	m_fz_doc=fz_open_document_with_stream(mm_ctx, szTmp, fz_stream0);
#endif

	//!!!fz_close(fz_stream0);
	fz_drop_stream(mm_ctx,fz_stream0);
	if(0==m_fz_doc) {CloseFile(); return false;}

	m_PagesCount = fz_count_pages(mm_ctx, mm_fz_doc);
	return true;
}

bool CaplPdf::CloseFile()
{
	if(0!=m_page) {delete m_page; m_page=0;}
	if(0!=m_fz_doc) { fz_drop_document(mm_ctx, mm_fz_doc); m_fz_doc=0;}
	if(0!=m_ctx) { fz_drop_context(mm_ctx); m_ctx=0;}
	if(0!=m_file_buf){delete m_file_buf; m_file_buf=0;}

	m_PagesCount=0;
	return false;
}

CaplPdfPage  *CaplPdf::LoadPage(int num_page, bool bTemp)
{
	if(0==m_fz_doc)  return 0;
	if(num_page<0) return 0;
	if(num_page>m_PagesCount) return 0;

	apl_clear_tiff_info();

	fz_page	*page = fz_load_page(mm_ctx,mm_fz_doc, num_page);
	if(0==page) return 0;

	if(bTemp) return new CaplPdfPage(this,page,num_page);

	if(0!=m_page) delete m_page;
	m_page=new CaplPdfPage(this,page,num_page);

	m_CurPage=num_page;
	return m_page;
}

p_fz_context CaplPdf::GetCtx(){return m_ctx;};
p_fz_document CaplPdf::GetFzDoc(){return m_fz_doc;};

//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
/*
CaplPdfPage::CaplPdfPage()
{
	m_fz_page=0;
	//fz_rect m_bounds;
	m_pix=0;
	m_original_cx=0;
	m_original_cy=0;
}
*/


CaplPdfPage::CaplPdfPage(CaplPdf *doc, p_fz_page page, int pagenum)
{
	//fz_rect m_bounds;
	//m_pix=0;
	m_PageNum=pagenum;

	m_strech_k=0;

	m_doc=doc;
	m_fz_doc=doc->GetFzDoc();
	m_ctx=doc->GetCtx();
	m_fz_page=page;

	m_cx=0;
	m_cy=0;
	m_cur_angle=0;

	m_img_compression=0;
	m_img_bitspersample=0;
	m_img_samplesperpixel=0;

	// Нормально сработает только для tiff
	apl_get_last_tiff_info(&m_img_compression, &m_img_bitspersample, &m_img_samplesperpixel);

	m_dibinf.bmiHeader.biSize = sizeof(m_dibinf.bmiHeader);
	m_dibinf.bmiHeader.biPlanes = 1;
	m_dibinf.bmiHeader.biBitCount = 32;
	m_dibinf.bmiHeader.biCompression = BI_RGB;
	m_dibinf.bmiHeader.biXPelsPerMeter = 2834;
	m_dibinf.bmiHeader.biYPelsPerMeter = 2834;
	m_dibinf.bmiHeader.biClrUsed = 0;
	m_dibinf.bmiHeader.biClrImportant = 0;
	m_dibinf.bmiHeader.biClrUsed = 0;

	//m_dibinf->bmiColors[0].rgbBlue=255;
	//m_dibinf->bmiColors[0].rgbGreen=255;
	//m_dibinf->bmiColors[0].rgbRed=255;
	//m_dibinf->bmiColors[0].rgbReserved=0;


	// Определяем размер
	fz_rect bounds;
	fz_bound_page(mm_ctx, mm_fz_page, &bounds);
	m_original_cx=bounds.x1-bounds.x0;
	m_original_cy=bounds.y1-bounds.y0;
}
//*****************************************************************************
CaplPdfPage::~CaplPdfPage(void)
{
	//if(0!=m_pix)   fz_drop_pixmap(mm_ctx, mm_pix);
	//if(0!=m_fz_page)  fz_free_page(mm_fz_doc, mm_fz_page);
	if(0!=m_fz_page)  fz_drop_page(mm_ctx, mm_fz_page);
}
//*****************************************************************************
bool CaplPdfPage::GetOriginalSizeIn_mm(float &cx, float &cy) // Возвращает размер страницы в мм
{
	cx=0; cy=0;
	if(0==m_fz_doc) return false;
	cx=(m_original_cx*25.4)/72;
	cy=(m_original_cy*25.4)/72;
	return true;
}
//*****************************************************************************
bool CaplPdfPage::GetOriginalSize(float &cx, float &cy) // Возвращает размер страницы
{
	cx=0; cy=0;
	if(0==m_fz_doc) return false;
	cx=m_original_cx;
	cy=m_original_cy;
	return true;
}
//*****************************************************************************
bool CaplPdfPage::GetCurImageSize(int &cx, int &cy)
{
	cx=m_cx; cy=m_cy;  	return true;
}

void CaplPdfPage:: FreeBitmap()
{
	m_cx=0;
	m_bitmap.DeleteObject();
}

//*****************************************************************************
bool CaplPdfPage::Make2Cx(CDC *dc, int cx, int rotation, LPCTSTR sSignsInField, LPCTSTR sInfoInField, LPCTSTR sBarCodeInFied, LPCTSTR sOrderNum)
{
	if(0==m_fz_doc) return false;
	if(0==m_original_cx) return false;

	static CString st_sSignsInField, st_sInfoInField, st_sBarCodeInFied, st_sOrderNum;

	if(m_cx==cx && m_cur_angle == rotation)
	{
		CString tmp_sSignsInField=sSignsInField;
		CString tmp_sInfoInField=sInfoInField;
		CString tmp_sBarCodeInFied=sBarCodeInFied;
		CString tmp_sOrderNum=sOrderNum;
		
		if( st_sSignsInField == tmp_sSignsInField
		&& st_sInfoInField == tmp_sInfoInField
		&& st_sBarCodeInFied == tmp_sBarCodeInFied 
		&& st_sOrderNum == tmp_sOrderNum) return true;  // Все уже готово
	}
		
	st_sSignsInField=sSignsInField;
	st_sInfoInField=sInfoInField;
	st_sBarCodeInFied=sBarCodeInFied;
	st_sOrderNum=sOrderNum;


	// Размер исходной картинки
	fz_rect src_bounds;
	fz_bound_page(mm_ctx, mm_fz_page, &src_bounds);	
	

	//Определяем масштаб
	float width=src_bounds.x1-src_bounds.x0;
	float high=src_bounds.y1-src_bounds.y0;
	if(width<0.0001) return false; // Очень маленькая исходная картинка

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

	float scale=cx/width;
	if(rotation==90 || rotation==270) scale=cx/high;

	fz_matrix transform;
	transform.a=transform.b=transform.c=transform.d=transform.e=transform.f=0;
	fz_irect bmp_box; // размер, но не из float, а из int

	// Подбираем размер bmp, чтобы он влез в память

	m_strech_k=1;
	while(true)
	{
		float scale1=scale/m_strech_k;
		fz_rotate(&transform, (float) rotation);
		fz_pre_scale(&transform, scale1, scale1);
		fz_transform_rect(&src_bounds, &transform);
		fz_round_rect(&bmp_box, &src_bounds);
		int img_cx=bmp_box.x1-bmp_box.x0;
		int img_cy=bmp_box.y1-bmp_box.y0;
		if(m_bitmap.CreateCompatibleBitmap(dc,img_cx,img_cy)) break; // получилось выделить память
		if(img_cx<512) // Если, уж, и такая картина не влезала в память, то дальше уменьшать смысла нет
		{
			m_comp_dc.DeleteDC();
			return false;
		}
		m_strech_k++;
		transform.a=transform.b=transform.c=transform.d=transform.e=transform.f=0;
		fz_bound_page(mm_ctx, mm_fz_page, &src_bounds);	

	}
	m_comp_dc.SelectObject(m_bitmap);

	fz_pixmap* pixmap=0;
	//pixmap= mm_pix;
	//if(0!=mm_pix) 	fz_drop_pixmap(mm_ctx, mm_pix);
	//m_pix = fz_new_pixmap_with_bbox(m_ctx, fz_device_rgb(m_ctx), &bmp_box); // для линукса ?
	pixmap = fz_new_pixmap_with_bbox(mm_ctx, fz_device_bgr(mm_ctx), &bmp_box, 1);
	if(0==pixmap) return false; // не хватило памяти ?
	fz_clear_pixmap_with_value(mm_ctx, pixmap, 0xff);
	
	int image_w0 = fz_pixmap_width(mm_ctx,pixmap);
	int image_h0 = fz_pixmap_height(mm_ctx, pixmap);

	fz_device *dev = fz_new_draw_device(mm_ctx, 0, pixmap);
	fz_run_page(mm_ctx, mm_fz_page, dev, &transform, NULL);
	fz_drop_device(mm_ctx,dev);

	int image_w = fz_pixmap_width(mm_ctx,pixmap);
	int image_h = fz_pixmap_height(mm_ctx, pixmap);
	int image_n = fz_pixmap_components(mm_ctx, pixmap);  // Байт на цвет, насколько я понял (Если !=4, то перед SetDIBitsToDevice было какое-то преобразование)

	m_dibinf.bmiHeader.biWidth = image_w;
	m_dibinf.bmiHeader.biHeight = -image_h;
	m_dibinf.bmiHeader.biSizeImage = image_h * 4;

	m_cx=image_w*m_strech_k; // по идее, это то же что и img_cx, но на всякий случай
	m_cy=image_h*m_strech_k;
	
	unsigned char *samples= fz_pixmap_samples(mm_ctx, pixmap); // Возврат указателя , память не выделяется

	//int k=SetDIBitsToDevice(dc->m_hDC,0, 0, image_w, image_h, 0, 0, 0, image_h, m_samples, 	m_dibinf, DIB_RGB_COLORS);
	int k=SetDIBitsToDevice(m_comp_dc.m_hDC, 
		0, 0, // <- коорд. верхнего левого угла приемника
		m_dibinf.bmiHeader.biWidth, -m_dibinf.bmiHeader.biHeight, //<- размеры источника
		0, 0, // <- коорд. нижнего левого угла источника
		0, -m_dibinf.bmiHeader.biHeight, // <- первая строка развертки в массиве и число строк развертки
		samples, 	&m_dibinf, DIB_RGB_COLORS);

	fz_drop_pixmap(mm_ctx, pixmap);
	m_cur_angle=rotation;

	DrawTextInRect(m_comp_dc, 25, 0.5, -5, 4, rotation, sInfoInField);		// Рисуем информационную  строку
	if(0!=sSignsInField)DrawTextInRect(m_comp_dc, -4.5, 5, -1, -140, rotation+270, sSignsInField);// Рисуем строку с подписями
	//if(0!=sOrderNum)DrawTextInRect(m_comp_dc, -4.5, 5, -0.5, 50, rotation+270, sOrderNum);// Рисуем номер заказа
	
	if(0!=sBarCodeInFied)
	{
		DrawTextInRect(m_comp_dc, -4.5, -15, -0.5,  -65, rotation + 270, sBarCodeInFied, true);
		DrawTextInRect(m_comp_dc, -5,   -66, -0.5, -150, rotation + 270, sBarCodeInFied);
	}	
	
	//DrawTextInRect(m_comp_dc, -4.5, 5, -1, -5, rotation+270, APL_T("У попа была собака"));

	// Тесты для низкого широкого штрихкода (без растяжения)
	//DrawTextInRect(m_comp_dc, 30, 25, 200, 35,  0, _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 30, 36, 200, 46, 180, _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 25, 60, 35, 230, 90, _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 36, 60, 46, 230, 270, _T("123456789"),true);

	// Тесты для высокого узкого штрихкода (с растяжением)
	//DrawTextInRect(m_comp_dc, 25, 60, 55, 230, 0,   _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 65, 60, 95, 230, 180, _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 30, 25, 200, 35,  90, _T("123456789"),true);
	//DrawTextInRect(m_comp_dc, 30, 36, 200, 46, 270, _T("123456789"),true);

	return true;
}

bool CaplPdfPage::DrawTextInRect(CDC &dc, float x0, float y0, float x1, float y1, int rotation, LPCTSTR sText, bool bDrawAsBarCode)
{
	//if(0==dc) return false;
	if(0==sText) return false;
	if(_T('\0')==sText[0]) return false;

	float pcx,pcy;
	GetOriginalSizeIn_mm(pcx,pcy);

	static double m=72/25.4;
	x0*=m; y0*=m; x1*=m; y1*=m;

	// Если координаты заданы от другого края
	if(x0<0) x0+=m_original_cx;
	if(x1<0) x1+=m_original_cx;
	if(y0<0) y0+=m_original_cy;
	if(y1<0) y1+=m_original_cy;

	// Пересчитываем в текущие точки;
	int t, ix0, iy0, ix1, iy1;
	ConvertPointFromOrigUnit(x0,y0,ix0,iy0);
	ConvertPointFromOrigUnit(x1,y1,ix1,iy1);

	if(ix0>ix1){int t=ix1; ix1=ix0; ix0=t;}
	if(iy0>iy1){int t=iy1; iy1=iy0; iy0=t;}

	if(1!=m_strech_k) {ix0/=m_strech_k; iy0/=m_strech_k; ix1/=m_strech_k; iy1/=m_strech_k;	}


	//m_comp_dc.FillSolidRect(ix0,iy0,ix1-ix0,iy1-iy0,RGB(255,0,0));

	// Угол поворота текста подписей
	int iSignsRotation=rotation;
	if(iSignsRotation>=360) iSignsRotation = iSignsRotation % 360; 

	RECT txt_rect; 
	int font_h;
	txt_rect.left=ix0; txt_rect.right=ix1; txt_rect.top=iy0; txt_rect.bottom=iy1;

	if(bDrawAsBarCode)
	{
		//m_comp_dc.FillSolidRect(ix0,iy0,ix1-ix0,iy1-iy0,RGB(255,192,192));
		return DrawBarCode(m_comp_dc, txt_rect, rotation, sText);
	}

	if(iSignsRotation==90 || iSignsRotation==270) font_h=-(ix1-ix0);
	else font_h=-(iy1-iy0);

	//Вычисляем ширину текста
	RECT r1=txt_rect;
	CFont font,horfont;
	horfont.CreateFont(font_h,0,0,0,FW_NORMAL,0,0,0,RUSSIAN_CHARSET,0,0,0,0,_T("Arial"));
	m_comp_dc.SelectObject(&horfont);
	m_comp_dc.DrawText(sText, &r1, DT_SINGLELINE|DT_NOCLIP|DT_TOP|DT_LEFT|DT_CALCRECT);
	int txt_cx=2+r1.right-r1.left;

	font.CreateFont(font_h,0,-10*iSignsRotation,-10*iSignsRotation,FW_NORMAL,0,0,0,RUSSIAN_CHARSET,0,0,0,0,_T("Arial"));
	m_comp_dc.SelectObject(&font);

	if(iSignsRotation==0)
	{
		txt_rect.right=txt_rect.left+txt_cx;
	}
	else if(iSignsRotation==180)
	{
		txt_rect.left=txt_rect.right-txt_cx;
		t=txt_rect.left; txt_rect.left=txt_rect.right; txt_rect.right=t;
		t=txt_rect.top; txt_rect.top=txt_rect.bottom; txt_rect.bottom=t;
	}
	else if(iSignsRotation==90)
	{
		t=txt_rect.left; txt_rect.left=txt_rect.right; txt_rect.right=t;
		txt_rect.bottom=txt_rect.top+txt_cx;
	}
	else if(iSignsRotation==270)
	{
		txt_rect.top=txt_rect.bottom-txt_cx;
		t=txt_rect.top; txt_rect.top=txt_rect.bottom; txt_rect.bottom=t;
	}
	//m_comp_dc.FillSolidRect(&txt_rect,RGB(0,255,0));
	//m_comp_dc.Draw3dRect(&txt_rect,RGB(255,0,0),RGB(255,0,0));
	m_comp_dc.SetTextColor(RGB(0,0,0));
	m_comp_dc.SetBkMode(TRANSPARENT);
	m_comp_dc.SelectObject(&font);
	m_comp_dc.SelectStockObject(NULL_BRUSH);
	m_comp_dc.DrawText(sText, &txt_rect, DT_SINGLELINE|DT_NOCLIP|DT_TOP|DT_LEFT);

	return true;
}


//*****************************************************************************
bool CaplPdfPage::Draw(CDC *dc, int x0, int y0, int cx, int cy, int x1, int y1, CDC *dc4draw)
{
	if(0==dc) return false;
	if(0==m_original_cx) return false;
	if(m_cx<=0) return false;
	//if(0==m_pix)  return false;

	CDC *src_dc=&m_comp_dc;
	if(0!=dc4draw) 
		src_dc=dc4draw;
	
	/* //ЯАИ: Эксперименты показали,что SetDIBitsToDevice в 1.6 раза медленние BitBlt
	    // А хранание в DC занимает в 4 раза меньше памяти, чем в fz_pixmap

	fz_pixmap* pixmap = mm_pix;
	if(0!=pixmap)
	{
		unsigned char *samples= fz_pixmap_samples(mm_ctx, fz_pixmap); // Возврат указателя , память не выделяется
		int k=SetDIBitsToDevice(dc->m_hDC, 
			x0, y0, // <- коорд. верхнего левого угла приемника
			m_dibinf.bmiHeader.biWidth, -m_dibinf.bmiHeader.biHeight, //<- размеры источника
			0, 0, // <- коорд. нижнего левого угла источника
			0, -m_dibinf.bmiHeader.biHeight, // <- первая строка развертки в массиве и число строк развертки
			samples, 	&m_dibinf, DIB_RGB_COLORS);
	}
	*/

	
	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); //все целиком
		}
		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);
		}
	}
	else
	{
		dc->FillSolidRect(x0,y0,cx,cy,RGB(255,0,0));
	}
/*
#ifdef _DEBUG
	{static int i=0; CString buf; buf.Format(_T("\n Draw %i cx= %i  cy= %i  m_cx= %i  m_cy=%i  "),i,cx,cy,m_cx,m_cy); TRACE(buf); i++;	}
#endif
*/
	return true;
}
//*****************************************************************************
bool CaplPdfPage::ConvertPointFromOrigUnit(float  x0, float y0, int &x1, int &y1)
{
	if(0==m_original_cx || 0==m_original_cy) {x1=0; y1=0; return false;}
	float k;
	if(90==m_cur_angle || 270== m_cur_angle)k=m_cx/m_original_cy;
	else k=m_cx/m_original_cx;

	float ky=m_cy/m_original_cy;
	x1=(int)(k*x0);
	y1=(int)(k*y0);

	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 CaplPdfPage::ConvertPointToOrigUnit(int  x0, int y0, float &x1, float &y1)
{
	if(0==m_original_cx || 0==m_original_cy) {x1=0; y1=0; return false;}

	if(0!=m_cur_angle)
	{
		if(180==m_cur_angle) {x0=m_cx-x0; y0=m_cy-y0;}
		else if( 90==m_cur_angle) {int tmp=x0; x0=y0; y0=m_cx-tmp;}
		else if(270==m_cur_angle) {int tmp=y0; y0=x0; x0=m_cy-tmp;}
	}

	float k;
	if(90==m_cur_angle || 270== m_cur_angle)k=m_cx/m_original_cy;
	else k=m_cx/m_original_cx;

	float ky=m_cy/m_original_cy;
	x1=(float)(((float)x0)/k);
	y1=(float)(((float)y0)/k);

	return true;
}

bool CaplPdfPage::GetFormat(CString &format)
{
	char buf[256];
	if (fz_lookup_metadata(mm_ctx, mm_fz_doc, "format", buf, sizeof buf) >= 0)
	{
		format=buf;
	}
	else return false;

	return true;
}

//*************************************************************************
//*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Определение скопированное из заголовочника, чтобы не тащить его в проектю
struct tiff_page_s
{
	fz_page super;
	fz_image *image;
};
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
//*************************************************************************
bool CaplPdfPage::GetImageInfo(int &cx, int &cy, int &xres, int &yres, CString &color_scheme, CString &img_coding)
{
	cx=0; cy=0; xres=0; yres=0; 
	color_scheme=_T(""); img_coding=_T("");
	CString buf,format;
	GetFormat(format);
	if(format.Find(_T("PDF"))>=0)  return false;

	tiff_page_s *tiff_page=(tiff_page_s*)mm_fz_page;
	fz_image *image=tiff_page->image;
	if(0==image) return false;

	cx=image->w;
	cy=image->h;
	xres=image->xres;
	yres=image->yres;


	if(0!=m_img_bitspersample*m_img_samplesperpixel)
	{
		//img_coding.Format(_T("Цветность: %i bit/pixel"),m_img_bitspersample*m_img_samplesperpixel);
		color_scheme.Format(_T("Цветность: %i bit/pixel"),m_img_bitspersample*m_img_samplesperpixel);
	}

	if(m_img_compression>0)
	{
		switch(m_img_compression)
		{
		case 1: buf=_T("NONE"); break;
		case 2: buf=_T("CCITTRLE"); break;
		case 3: buf=_T("CCITTFAX3 (CCITT_T4)"); break;
		case 4: buf=_T("CCITTFAX4 (CCITT_T6)"); break;
		case 5: buf=_T("LZW"); break;
		case 6: buf=_T("Old JPEG"); break;
		case 7: buf=_T("JPEG"); break;
		case 8: buf=_T("ADOBE_DEFLATE"); break;
		case 32766: buf=_T("NEXT"); break;
		case 32771: buf=_T("CCITTRLEW"); break;
		case 32773: buf=_T("PACKBITS"); break;
		case 32809: buf=_T("THUNDERSCAN"); break;
		case 32895: buf=_T("IT8CTPAD"); break;
		case 32896: buf=_T("IT8LW"); break;
		case 32897: buf=_T("IT8MP"); break;
		case 32898: buf=_T("IT8BL"); break;
		case 32908: buf=_T("PIXARFILM"); break;
		case 32909: buf=_T("PIXARLOG"); break;
		case 32946: buf=_T("DEFLATE"); break;
		case 32947: buf=_T("DCS"); break;
		case 34661: buf=_T("JBIG"); break;
		case 34676: buf=_T("SGILOG"); break;
		case 34677: buf=_T("SGILOG24"); break;
		case 34712: buf=_T("JP2000"); break;
		default:  buf=_T("?"); break;
		}
		if(img_coding!=_T("")) img_coding+=_T("\n\n");
		img_coding+=_T("Сжатие: "); img_coding+=buf;

	}

	if(0!=image->colorspace)
	{
		//color_scheme=image->colorspace->name;  В новой версии все поменялось. разбираться не стал.
		//n1=image->colorspace->n;
	}
	return true;
}