1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "../../include/pdfwindow/PDFWindow.h"
8#include "../../include/pdfwindow/PWL_Wnd.h"
9#include "../../include/pdfwindow/PWL_Icon.h"
10#include "../../include/pdfwindow/PWL_Utils.h"
11
12/* ------------------------------- CPWL_Image ---------------------------------- */
13
14CPWL_Image::CPWL_Image() : m_pPDFStream(NULL)
15{
16}
17
18CPWL_Image::~CPWL_Image()
19{
20}
21
22CFX_ByteString CPWL_Image::GetImageAppStream()
23{
24	CFX_ByteTextBuf sAppStream;
25
26	CFX_ByteString sAlias = this->GetImageAlias();
27	CPDF_Rect rcPlate = GetClientRect();
28	CPDF_Matrix mt;
29	mt.SetReverse(GetImageMatrix());
30
31	FX_FLOAT fHScale = 1.0f;
32	FX_FLOAT fVScale = 1.0f;
33	GetScale(fHScale,fVScale);
34
35	FX_FLOAT fx = 0.0f;
36	FX_FLOAT fy = 0.0f;
37	GetImageOffset(fx,fy);
38
39	if (m_pPDFStream && sAlias.GetLength()>0)
40	{
41		sAppStream << "q\n";
42		sAppStream << rcPlate.left << " " << rcPlate.bottom << " "
43			<< rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom << " re W n\n";
44
45		sAppStream << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " " << rcPlate.bottom + fy << " cm\n";
46		sAppStream << mt.GetA() << " " << mt.GetB() << " " << mt.GetC() << " " << mt.GetD() << " " << mt.GetE() << " " << mt.GetF() << " cm\n";
47
48		sAppStream << "0 g 0 G 1 w /" << sAlias << " Do\n" << "Q\n";
49	}
50
51	return sAppStream.GetByteString();
52}
53
54void CPWL_Image::SetPDFStream(CPDF_Stream * pStream)
55{
56	m_pPDFStream = pStream;
57}
58
59CPDF_Stream * CPWL_Image::GetPDFStream()
60{
61	return this->m_pPDFStream;
62}
63
64void CPWL_Image::GetImageSize(FX_FLOAT & fWidth,FX_FLOAT & fHeight)
65{
66	fWidth = 0.0f;
67	fHeight = 0.0f;
68
69	if (m_pPDFStream)
70	{
71		if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())
72		{
73			CPDF_Rect rect = pDict->GetRect("BBox");
74
75			fWidth = rect.right - rect.left;
76			fHeight = rect.top - rect.bottom;
77		}
78	}
79}
80
81CPDF_Matrix	CPWL_Image::GetImageMatrix()
82{
83	if (m_pPDFStream)
84	{
85		if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())
86		{
87			return pDict->GetMatrix("Matrix");
88		}
89	}
90
91	return CPDF_Matrix();
92}
93
94CFX_ByteString CPWL_Image::GetImageAlias()
95{
96	if (m_sImageAlias.IsEmpty())
97	{
98		if (m_pPDFStream)
99		{
100			if (CPDF_Dictionary * pDict = m_pPDFStream->GetDict())
101			{
102				return pDict->GetString("Name");
103			}
104		}
105	}
106	else
107		return m_sImageAlias;
108
109	return CFX_ByteString();
110}
111
112void CPWL_Image::SetImageAlias(FX_LPCSTR sImageAlias)
113{
114	m_sImageAlias = sImageAlias;
115}
116
117void CPWL_Image::GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)
118{
119	fHScale = 1.0f;
120	fVScale = 1.0f;
121}
122
123
124void CPWL_Image::GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)
125{
126	x = 0.0f;
127	y = 0.0f;
128}
129
130/* ------------------------------- CPWL_Icon ---------------------------------- */
131
132CPWL_Icon::CPWL_Icon() : m_pIconFit(NULL)
133{
134}
135
136CPWL_Icon::~CPWL_Icon()
137{
138}
139
140FX_INT32 CPWL_Icon::GetScaleMethod()
141{
142	if (m_pIconFit)
143		return m_pIconFit->GetScaleMethod();
144
145	return 0;
146}
147
148FX_BOOL	CPWL_Icon::IsProportionalScale()
149{
150	if (m_pIconFit)
151		return m_pIconFit->IsProportionalScale();
152
153	return FALSE;
154}
155
156void CPWL_Icon::GetIconPosition(FX_FLOAT & fLeft, FX_FLOAT & fBottom)
157{
158	if (m_pIconFit)
159	{
160		//m_pIconFit->GetIconPosition(fLeft,fBottom);
161		fLeft = 0.0f;
162		fBottom = 0.0f;
163		CPDF_Array* pA = m_pIconFit->m_pDict->GetArray("A");
164		if (pA != NULL)
165		{
166			FX_DWORD dwCount = pA->GetCount();
167			if (dwCount > 0) fLeft = pA->GetNumber(0);
168			if (dwCount > 1) fBottom = pA->GetNumber(1);
169		}
170	}
171	else
172	{
173		fLeft = 0.0f;
174		fBottom = 0.0f;
175	}
176}
177
178FX_BOOL CPWL_Icon::GetFittingBounds()
179{
180	if (m_pIconFit)
181		return m_pIconFit->GetFittingBounds();
182
183	return FALSE;
184}
185
186void CPWL_Icon::GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)
187{
188	fHScale = 1.0f;
189	fVScale = 1.0f;
190
191	if (m_pPDFStream)
192	{
193		FX_FLOAT fImageWidth,fImageHeight;
194		FX_FLOAT fPlateWidth,fPlateHeight;
195
196		CPDF_Rect rcPlate = this->GetClientRect();
197		fPlateWidth = rcPlate.right - rcPlate.left;
198		fPlateHeight = rcPlate.top - rcPlate.bottom;
199
200		GetImageSize(fImageWidth,fImageHeight);
201
202		FX_INT32 nScaleMethod = this->GetScaleMethod();
203
204		/*
205		enum ScaleMethod
206		{
207			Always = 0,	//A, Always scale
208			Bigger,		//B, Scale only when the icon is bigger than the annotation rectangle
209			Smaller,	//S, Scale only when the icon is smaller then the annotation rectangle
210			Never		//N, Never scale
211		};
212		*/
213
214		switch (nScaleMethod)
215		{
216		default:
217		case 0:
218			fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
219			fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
220			break;
221		case 1:
222			if (fPlateWidth < fImageWidth)
223				fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
224			if (fPlateHeight < fImageHeight)
225				fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
226			break;
227		case 2:
228			if (fPlateWidth > fImageWidth)
229				fHScale = fPlateWidth / PWL_MAX(fImageWidth,1.0f);
230			if (fPlateHeight > fImageHeight)
231				fVScale = fPlateHeight / PWL_MAX(fImageHeight,1.0f);
232			break;
233		case 3:
234			break;
235		}
236
237		FX_FLOAT fMinScale;
238		if (IsProportionalScale())
239		{
240			fMinScale = PWL_MIN(fHScale,fVScale);
241			fHScale = fMinScale;
242			fVScale = fMinScale;
243		}
244	}
245}
246
247void CPWL_Icon::GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)
248{
249	FX_FLOAT fLeft,fBottom;
250
251	this->GetIconPosition(fLeft,fBottom);
252	x = 0.0f;
253	y = 0.0f;
254
255	FX_FLOAT fImageWidth,fImageHeight;
256	GetImageSize(fImageWidth,fImageHeight);
257
258	FX_FLOAT fHScale,fVScale;
259	GetScale(fHScale,fVScale);
260
261	FX_FLOAT fImageFactWidth = fImageWidth * fHScale;
262	FX_FLOAT fImageFactHeight = fImageHeight * fVScale;
263
264	FX_FLOAT fPlateWidth,fPlateHeight;
265	CPDF_Rect rcPlate = this->GetClientRect();
266	fPlateWidth = rcPlate.right - rcPlate.left;
267	fPlateHeight = rcPlate.top - rcPlate.bottom;
268
269	x = (fPlateWidth - fImageFactWidth) * fLeft;
270	y = (fPlateHeight - fImageFactHeight)  * fBottom;
271}
272
273