// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_Icon.h"
#include "../../include/pdfwindow/PWL_Utils.h"

/* ------------------------------- CPWL_Image ---------------------------------- */

CPWL_Image::CPWL_Image() : m_pPDFStream(NULL)
{
}

CPWL_Image::~CPWL_Image()
{
}

CFX_ByteString CPWL_Image::GetImageAppStream()
{
	CFX_ByteTextBuf sAppStream;

	CFX_ByteString sAlias = this->GetImageAlias();
	CPDF_Rect rcPlate = GetClientRect();
	CPDF_Matrix mt;
	mt.SetReverse(GetImageMatrix());

	FX_FLOAT fHScale = 1.0f;
	FX_FLOAT fVScale = 1.0f;
	GetScale(fHScale,fVScale);

	FX_FLOAT fx = 0.0f;
	FX_FLOAT fy = 0.0f;
	GetImageOffset(fx,fy);

	if (m_pPDFStream && sAlias.GetLength()>0)
	{
		sAppStream << "q\n";
		sAppStream << rcPlate.left << " " << rcPlate.bottom << " "
			<< rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom << " re W n\n";

		sAppStream << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " " << rcPlate.bottom + fy << " cm\n";
		sAppStream << mt.GetA() << " " << mt.GetB() << " " << mt.GetC() << " " << mt.GetD() << " " << mt.GetE() << " " << mt.GetF() << " cm\n";

		sAppStream << "0 g 0 G 1 w /" << sAlias << " Do\n" << "Q\n";
	}

	return sAppStream.GetByteString();
}

void CPWL_Image::SetPDFStream(CPDF_Stream * pStream)
{
	m_pPDFStream = pStream;
}

CPDF_Stream * CPWL_Image::GetPDFStream()
{
	return this->m_pPDFStream;
}

void CPWL_Image::GetImageSize(FX_FLOAT & fWidth,FX_FLOAT & fHeight)
{
	fWidth = 0.0f;
	fHeight = 0.0f;

	if (m_pPDFStream)
	{
		if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())
		{
			CPDF_Rect rect = pDict->GetRect("BBox");

			fWidth = rect.right - rect.left;
			fHeight = rect.top - rect.bottom;
		}
	}
}

CPDF_Matrix	CPWL_Image::GetImageMatrix()
{
	if (m_pPDFStream)
	{
		if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())
		{
			return pDict->GetMatrix("Matrix");
		}
	}

	return CPDF_Matrix();
}

CFX_ByteString CPWL_Image::GetImageAlias()
{
	if (m_sImageAlias.IsEmpty())
	{
		if (m_pPDFStream)
		{
			if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())		
			{
				return pDict->GetString("Name");
			}
		}
	}
	else
		return m_sImageAlias;

	return CFX_ByteString();
}

void CPWL_Image::SetImageAlias(FX_LPCSTR sImageAlias)
{
	m_sImageAlias = sImageAlias;
}

void CPWL_Image::GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)
{
	fHScale = 1.0f;
	fVScale = 1.0f;
}


void CPWL_Image::GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)
{
	x = 0.0f;
	y = 0.0f;
}

/* ------------------------------- CPWL_Icon ---------------------------------- */

CPWL_Icon::CPWL_Icon() : m_pIconFit(NULL)
{
}

CPWL_Icon::~CPWL_Icon()
{
}

FX_INT32 CPWL_Icon::GetScaleMethod()
{
	if (m_pIconFit)
		return m_pIconFit->GetScaleMethod();

	return 0;
}

FX_BOOL	CPWL_Icon::IsProportionalScale()
{
	if (m_pIconFit)
		return m_pIconFit->IsProportionalScale();

	return FALSE;
}

void CPWL_Icon::GetIconPosition(FX_FLOAT & fLeft, FX_FLOAT & fBottom)
{
	if (m_pIconFit)
	{
		//m_pIconFit->GetIconPosition(fLeft,fBottom);
		fLeft = 0.0f;
		fBottom = 0.0f;
		CPDF_Array* pA = m_pIconFit->m_pDict->GetArray("A");
		if (pA != NULL)
		{
			FX_DWORD dwCount = pA->GetCount();
			if (dwCount > 0) fLeft = pA->GetNumber(0);
			if (dwCount > 1) fBottom = pA->GetNumber(1);
		}
	}
	else
	{
		fLeft = 0.0f;
		fBottom = 0.0f;
	}
}

FX_BOOL CPWL_Icon::GetFittingBounds()
{
	if (m_pIconFit)
		return m_pIconFit->GetFittingBounds();

	return FALSE;
}

void CPWL_Icon::GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)
{
	fHScale = 1.0f;
	fVScale = 1.0f;
	
	if (m_pPDFStream)
	{
		FX_FLOAT fImageWidth,fImageHeight;
		FX_FLOAT fPlateWidth,fPlateHeight;

		CPDF_Rect rcPlate = this->GetClientRect();	
		fPlateWidth = rcPlate.right - rcPlate.left;
		fPlateHeight = rcPlate.top - rcPlate.bottom;

		GetImageSize(fImageWidth,fImageHeight);

		FX_INT32 nScaleMethod = this->GetScaleMethod();

		/*
		enum ScaleMethod
		{
			Always = 0,	//A, Always scale
			Bigger,		//B, Scale only when the icon is bigger than the annotation rectangle
			Smaller,	//S, Scale only when the icon is smaller then the annotation rectangle
			Never		//N, Never scale
		};
		*/

		switch (nScaleMethod)
		{
		default:
		case 0:
			fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
			fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
			break;
		case 1:
			if (fPlateWidth < fImageWidth)
				fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
			if (fPlateHeight < fImageHeight)
				fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
			break;
		case 2:
			if (fPlateWidth > fImageWidth)
				fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
			if (fPlateHeight > fImageHeight)
				fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
			break;
		case 3:
			break;
		}

		FX_FLOAT fMinScale;
		if (IsProportionalScale())
		{
			fMinScale = PWL_MIN(fHScale,fVScale);
			fHScale = fMinScale;
			fVScale = fMinScale;
		}
	}
}

void CPWL_Icon::GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)
{
	FX_FLOAT fLeft,fBottom;

	this->GetIconPosition(fLeft,fBottom);
	x = 0.0f;
	y = 0.0f;

	FX_FLOAT fImageWidth,fImageHeight;
	GetImageSize(fImageWidth,fImageHeight);

	FX_FLOAT fHScale,fVScale;
	GetScale(fHScale,fVScale);

	FX_FLOAT fImageFactWidth = fImageWidth * fHScale;
	FX_FLOAT fImageFactHeight = fImageHeight * fVScale;

	FX_FLOAT fPlateWidth,fPlateHeight;
	CPDF_Rect rcPlate = this->GetClientRect();	
	fPlateWidth = rcPlate.right - rcPlate.left;
	fPlateHeight = rcPlate.top - rcPlate.bottom;

	x = (fPlateWidth - fImageFactWidth) * fLeft;
	y = (fPlateHeight - fImageFactHeight)  * fBottom;
}

