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 16 CPWL_Image::CPWL_Image() : m_pPDFStream(nullptr) {} 17 18 CPWL_Image::~CPWL_Image() {} 19 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 54 void CPWL_Image::SetPDFStream(CPDF_Stream* pStream) { 55 m_pPDFStream = pStream; 56 } 57 58 CPDF_Stream* CPWL_Image::GetPDFStream() { 59 return m_pPDFStream; 60 } 61 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 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 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 99 void CPWL_Image::SetImageAlias(const FX_CHAR* sImageAlias) { 100 m_sImageAlias = sImageAlias; 101 } 102 103 void CPWL_Image::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) { 104 fHScale = 1.0f; 105 fVScale = 1.0f; 106 } 107 108 void CPWL_Image::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) { 109 x = 0.0f; 110 y = 0.0f; 111 } 112 113 CPWL_Icon::CPWL_Icon() : m_pIconFit(nullptr) {} 114 115 CPWL_Icon::~CPWL_Icon() {} 116 117 CPDF_IconFit* CPWL_Icon::GetIconFit() { 118 return m_pIconFit; 119 } 120 121 int32_t CPWL_Icon::GetScaleMethod() { 122 if (m_pIconFit) 123 return m_pIconFit->GetScaleMethod(); 124 125 return 0; 126 } 127 128 bool CPWL_Icon::IsProportionalScale() { 129 if (m_pIconFit) 130 return m_pIconFit->IsProportionalScale(); 131 132 return false; 133 } 134 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 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 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