dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 1 | // Copyright 2016 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 | |
dsinclair | 1727aee | 2016-09-29 13:12:56 -0700 | [diff] [blame] | 7 | #include "core/fpdfdoc/cpdf_iconfit.h" |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 8 | |
Lei Zhang | 59a1a91 | 2021-06-07 16:55:25 +0000 | [diff] [blame] | 9 | #include <algorithm> |
| 10 | |
dsinclair | 488b7ad | 2016-10-04 11:55:50 -0700 | [diff] [blame] | 11 | #include "core/fpdfapi/parser/cpdf_array.h" |
| 12 | #include "core/fpdfapi/parser/cpdf_dictionary.h" |
dsinclair | a52ab74 | 2016-09-29 13:59:29 -0700 | [diff] [blame] | 13 | #include "core/fxcrt/fx_string.h" |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 14 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 15 | namespace { |
| 16 | |
| 17 | constexpr float kDefaultPosition = 0.5f; |
| 18 | |
| 19 | } // namespace |
| 20 | |
Tom Sepez | 797ca5c | 2017-05-25 12:03:18 -0700 | [diff] [blame] | 21 | CPDF_IconFit::CPDF_IconFit(const CPDF_Dictionary* pDict) : m_pDict(pDict) {} |
| 22 | |
| 23 | CPDF_IconFit::CPDF_IconFit(const CPDF_IconFit& that) = default; |
| 24 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 25 | CPDF_IconFit::~CPDF_IconFit() = default; |
Tom Sepez | 797ca5c | 2017-05-25 12:03:18 -0700 | [diff] [blame] | 26 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 27 | CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod() const { |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 28 | if (!m_pDict) |
Lei Zhang | 55ae76d | 2020-06-23 01:12:41 +0000 | [diff] [blame] | 29 | return ScaleMethod::kAlways; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 30 | |
Ryan Harrison | 275e260 | 2017-09-18 14:23:18 -0400 | [diff] [blame] | 31 | ByteString csSW = m_pDict->GetStringFor("SW", "A"); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 32 | if (csSW == "B") |
Lei Zhang | 55ae76d | 2020-06-23 01:12:41 +0000 | [diff] [blame] | 33 | return ScaleMethod::kBigger; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 34 | if (csSW == "S") |
Lei Zhang | 55ae76d | 2020-06-23 01:12:41 +0000 | [diff] [blame] | 35 | return ScaleMethod::kSmaller; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 36 | if (csSW == "N") |
Lei Zhang | 55ae76d | 2020-06-23 01:12:41 +0000 | [diff] [blame] | 37 | return ScaleMethod::kNever; |
| 38 | return ScaleMethod::kAlways; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 41 | bool CPDF_IconFit::IsProportionalScale() const { |
| 42 | return !m_pDict || m_pDict->GetStringFor("S", "P") != "A"; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 43 | } |
| 44 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 45 | CFX_PointF CPDF_IconFit::GetIconBottomLeftPosition() const { |
| 46 | float fLeft = kDefaultPosition; |
| 47 | float fBottom = kDefaultPosition; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 48 | if (!m_pDict) |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 49 | return {fLeft, fBottom}; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 50 | |
Lei Zhang | dbf13f6 | 2018-05-24 01:36:40 +0000 | [diff] [blame] | 51 | const CPDF_Array* pA = m_pDict->GetArrayFor("A"); |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 52 | if (!pA) |
| 53 | return {fLeft, fBottom}; |
| 54 | |
Lei Zhang | f40380f | 2018-10-12 18:31:51 +0000 | [diff] [blame] | 55 | size_t dwCount = pA->size(); |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 56 | if (dwCount > 0) |
| 57 | fLeft = pA->GetNumberAt(0); |
| 58 | if (dwCount > 1) |
| 59 | fBottom = pA->GetNumberAt(1); |
| 60 | return {fLeft, fBottom}; |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 61 | } |
| 62 | |
Lei Zhang | 65b8db9 | 2018-10-10 17:50:31 +0000 | [diff] [blame] | 63 | bool CPDF_IconFit::GetFittingBounds() const { |
Lei Zhang | 76ec926 | 2018-10-09 23:32:10 +0000 | [diff] [blame] | 64 | return m_pDict && m_pDict->GetBooleanFor("FB", false); |
dsinclair | 27053d8 | 2016-08-02 15:43:46 -0700 | [diff] [blame] | 65 | } |
Tom Sepez | d49e057 | 2019-12-18 00:04:16 +0000 | [diff] [blame] | 66 | |
| 67 | CFX_PointF CPDF_IconFit::GetIconPosition() const { |
| 68 | if (!m_pDict) |
| 69 | return CFX_PointF(); |
| 70 | |
| 71 | const CPDF_Array* pA = m_pDict->GetArrayFor("A"); |
| 72 | if (!pA) |
| 73 | return CFX_PointF(); |
| 74 | |
| 75 | size_t dwCount = pA->size(); |
| 76 | return {dwCount > 0 ? pA->GetNumberAt(0) : 0.0f, |
| 77 | dwCount > 1 ? pA->GetNumberAt(1) : 0.0f}; |
| 78 | } |
Tom Sepez | a043b72 | 2021-04-21 18:27:45 +0000 | [diff] [blame] | 79 | |
Tom Sepez | aa5065c | 2021-04-21 21:48:39 +0000 | [diff] [blame] | 80 | CFX_VectorF CPDF_IconFit::GetScale(const CFX_SizeF& image_size, |
| 81 | const CFX_FloatRect& rcPlate) const { |
Tom Sepez | a043b72 | 2021-04-21 18:27:45 +0000 | [diff] [blame] | 82 | float fHScale = 1.0f; |
| 83 | float fVScale = 1.0f; |
Tom Sepez | 47a8cd0 | 2021-04-21 23:13:30 +0000 | [diff] [blame] | 84 | const float fPlateWidth = rcPlate.Width(); |
| 85 | const float fPlateHeight = rcPlate.Height(); |
| 86 | const float fImageWidth = image_size.width; |
| 87 | const float fImageHeight = image_size.height; |
| 88 | switch (GetScaleMethod()) { |
Tom Sepez | a043b72 | 2021-04-21 18:27:45 +0000 | [diff] [blame] | 89 | case CPDF_IconFit::ScaleMethod::kAlways: |
| 90 | fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); |
| 91 | fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); |
| 92 | break; |
| 93 | case CPDF_IconFit::ScaleMethod::kBigger: |
| 94 | if (fPlateWidth < fImageWidth) |
| 95 | fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); |
| 96 | if (fPlateHeight < fImageHeight) |
| 97 | fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); |
| 98 | break; |
| 99 | case CPDF_IconFit::ScaleMethod::kSmaller: |
| 100 | if (fPlateWidth > fImageWidth) |
| 101 | fHScale = fPlateWidth / std::max(fImageWidth, 1.0f); |
| 102 | if (fPlateHeight > fImageHeight) |
| 103 | fVScale = fPlateHeight / std::max(fImageHeight, 1.0f); |
| 104 | break; |
| 105 | case CPDF_IconFit::ScaleMethod::kNever: |
| 106 | break; |
| 107 | } |
| 108 | |
| 109 | if (IsProportionalScale()) { |
| 110 | float min_scale = std::min(fHScale, fVScale); |
| 111 | fHScale = min_scale; |
| 112 | fVScale = min_scale; |
| 113 | } |
| 114 | return {fHScale, fVScale}; |
| 115 | } |
| 116 | |
Tom Sepez | aa5065c | 2021-04-21 21:48:39 +0000 | [diff] [blame] | 117 | CFX_VectorF CPDF_IconFit::GetImageOffset(const CFX_SizeF& image_size, |
Tom Sepez | 47a8cd0 | 2021-04-21 23:13:30 +0000 | [diff] [blame] | 118 | const CFX_VectorF& scale, |
Tom Sepez | aa5065c | 2021-04-21 21:48:39 +0000 | [diff] [blame] | 119 | const CFX_FloatRect& rcPlate) const { |
Tom Sepez | 47a8cd0 | 2021-04-21 23:13:30 +0000 | [diff] [blame] | 120 | const CFX_PointF icon_position = GetIconPosition(); |
| 121 | const float fImageFactWidth = image_size.width * scale.x; |
| 122 | const float fImageFactHeight = image_size.height * scale.y; |
| 123 | return {(rcPlate.Width() - fImageFactWidth) * icon_position.x, |
| 124 | (rcPlate.Height() - fImageFactHeight) * icon_position.y}; |
Tom Sepez | a043b72 | 2021-04-21 18:27:45 +0000 | [diff] [blame] | 125 | } |