// 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 ? m_pIconFit->m_pDict->GetArray("A") : NULL;
		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;
}

