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 "fpdfsdk/pdfwindow/PWL_Icon.h"
8
9 #include <algorithm>
10
11 #include "core/fpdfapi/parser/cpdf_array.h"
12 #include "core/fpdfapi/parser/cpdf_stream.h"
13 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
14 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
15
CPWL_Image()16 CPWL_Image::CPWL_Image() : m_pPDFStream(nullptr) {}
17
~CPWL_Image()18 CPWL_Image::~CPWL_Image() {}
19
GetImageAppStream()20 CFX_ByteString CPWL_Image::GetImageAppStream() {
21 CFX_ByteTextBuf sAppStream;
22
23 CFX_ByteString sAlias = GetImageAlias();
24 CFX_FloatRect rcPlate = GetClientRect();
25 CFX_Matrix mt;
26 mt.SetReverse(GetImageMatrix());
27
28 FX_FLOAT fHScale = 1.0f;
29 FX_FLOAT fVScale = 1.0f;
30 GetScale(fHScale, fVScale);
31
32 FX_FLOAT fx = 0.0f;
33 FX_FLOAT fy = 0.0f;
34 GetImageOffset(fx, fy);
35
36 if (m_pPDFStream && sAlias.GetLength() > 0) {
37 sAppStream << "q\n";
38 sAppStream << rcPlate.left << " " << rcPlate.bottom << " "
39 << rcPlate.right - rcPlate.left << " "
40 << rcPlate.top - rcPlate.bottom << " re W n\n";
41
42 sAppStream << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx
43 << " " << rcPlate.bottom + fy << " cm\n";
44 sAppStream << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " "
45 << mt.e << " " << mt.f << " cm\n";
46
47 sAppStream << "0 g 0 G 1 w /" << sAlias.AsStringC() << " Do\n"
48 << "Q\n";
49 }
50
51 return sAppStream.MakeString();
52 }
53
SetPDFStream(CPDF_Stream * pStream)54 void CPWL_Image::SetPDFStream(CPDF_Stream* pStream) {
55 m_pPDFStream = pStream;
56 }
57
GetPDFStream()58 CPDF_Stream* CPWL_Image::GetPDFStream() {
59 return m_pPDFStream;
60 }
61
GetImageSize(FX_FLOAT & fWidth,FX_FLOAT & fHeight)62 void CPWL_Image::GetImageSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight) {
63 fWidth = 0.0f;
64 fHeight = 0.0f;
65
66 if (m_pPDFStream) {
67 if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
68 CFX_FloatRect rect = pDict->GetRectFor("BBox");
69
70 fWidth = rect.right - rect.left;
71 fHeight = rect.top - rect.bottom;
72 }
73 }
74 }
75
GetImageMatrix()76 CFX_Matrix CPWL_Image::GetImageMatrix() {
77 if (m_pPDFStream) {
78 if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
79 return pDict->GetMatrixFor("Matrix");
80 }
81 }
82
83 return CFX_Matrix();
84 }
85
GetImageAlias()86 CFX_ByteString CPWL_Image::GetImageAlias() {
87 if (!m_sImageAlias.IsEmpty())
88 return m_sImageAlias;
89
90 if (m_pPDFStream) {
91 if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
92 return pDict->GetStringFor("Name");
93 }
94 }
95
96 return CFX_ByteString();
97 }
98
SetImageAlias(const FX_CHAR * sImageAlias)99 void CPWL_Image::SetImageAlias(const FX_CHAR* sImageAlias) {
100 m_sImageAlias = sImageAlias;
101 }
102
GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)103 void CPWL_Image::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) {
104 fHScale = 1.0f;
105 fVScale = 1.0f;
106 }
107
GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)108 void CPWL_Image::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) {
109 x = 0.0f;
110 y = 0.0f;
111 }
112
CPWL_Icon()113 CPWL_Icon::CPWL_Icon() : m_pIconFit(nullptr) {}
114
~CPWL_Icon()115 CPWL_Icon::~CPWL_Icon() {}
116
GetIconFit()117 CPDF_IconFit* CPWL_Icon::GetIconFit() {
118 return m_pIconFit;
119 }
120
GetScaleMethod()121 int32_t CPWL_Icon::GetScaleMethod() {
122 if (m_pIconFit)
123 return m_pIconFit->GetScaleMethod();
124
125 return 0;
126 }
127
IsProportionalScale()128 bool CPWL_Icon::IsProportionalScale() {
129 if (m_pIconFit)
130 return m_pIconFit->IsProportionalScale();
131
132 return false;
133 }
134
GetIconPosition(FX_FLOAT & fLeft,FX_FLOAT & fBottom)135 void CPWL_Icon::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) {
136 if (m_pIconFit) {
137 fLeft = 0.0f;
138 fBottom = 0.0f;
139 CPDF_Array* pA = m_pIconFit->GetDict()
140 ? m_pIconFit->GetDict()->GetArrayFor("A")
141 : nullptr;
142 if (pA) {
143 size_t dwCount = pA->GetCount();
144 if (dwCount > 0)
145 fLeft = pA->GetNumberAt(0);
146 if (dwCount > 1)
147 fBottom = pA->GetNumberAt(1);
148 }
149 } else {
150 fLeft = 0.0f;
151 fBottom = 0.0f;
152 }
153 }
154
GetScale(FX_FLOAT & fHScale,FX_FLOAT & fVScale)155 void CPWL_Icon::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) {
156 fHScale = 1.0f;
157 fVScale = 1.0f;
158
159 if (m_pPDFStream) {
160 FX_FLOAT fImageWidth, fImageHeight;
161 FX_FLOAT fPlateWidth, fPlateHeight;
162
163 CFX_FloatRect rcPlate = GetClientRect();
164 fPlateWidth = rcPlate.right - rcPlate.left;
165 fPlateHeight = rcPlate.top - rcPlate.bottom;
166
167 GetImageSize(fImageWidth, fImageHeight);
168
169 int32_t nScaleMethod = GetScaleMethod();
170
171 switch (nScaleMethod) {
172 default:
173 case 0:
174 fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
175 fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
176 break;
177 case 1:
178 if (fPlateWidth < fImageWidth)
179 fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
180 if (fPlateHeight < fImageHeight)
181 fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
182 break;
183 case 2:
184 if (fPlateWidth > fImageWidth)
185 fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
186 if (fPlateHeight > fImageHeight)
187 fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
188 break;
189 case 3:
190 break;
191 }
192
193 FX_FLOAT fMinScale;
194 if (IsProportionalScale()) {
195 fMinScale = std::min(fHScale, fVScale);
196 fHScale = fMinScale;
197 fVScale = fMinScale;
198 }
199 }
200 }
201
GetImageOffset(FX_FLOAT & x,FX_FLOAT & y)202 void CPWL_Icon::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) {
203 FX_FLOAT fLeft, fBottom;
204
205 GetIconPosition(fLeft, fBottom);
206 x = 0.0f;
207 y = 0.0f;
208
209 FX_FLOAT fImageWidth, fImageHeight;
210 GetImageSize(fImageWidth, fImageHeight);
211
212 FX_FLOAT fHScale, fVScale;
213 GetScale(fHScale, fVScale);
214
215 FX_FLOAT fImageFactWidth = fImageWidth * fHScale;
216 FX_FLOAT fImageFactHeight = fImageHeight * fVScale;
217
218 FX_FLOAT fPlateWidth, fPlateHeight;
219 CFX_FloatRect rcPlate = GetClientRect();
220 fPlateWidth = rcPlate.right - rcPlate.left;
221 fPlateHeight = rcPlate.top - rcPlate.bottom;
222
223 x = (fPlateWidth - fImageFactWidth) * fLeft;
224 y = (fPlateHeight - fImageFactHeight) * fBottom;
225 }
226