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 
7 #include "xfa/fxfa/parser/cxfa_measurement.h"
8 
9 #include "core/fxcrt/fx_extension.h"
10 
11 namespace {
12 
13 constexpr float kPtToInch = 72;
14 constexpr float kPtToCm = kPtToInch / 2.54f;
15 constexpr float kPtToMm = kPtToCm / 10;
16 constexpr float kPtToMp = 0.001f;
17 constexpr float kPtToPc = 12;
18 
19 }  // namespace
20 
CXFA_Measurement(const WideStringView & wsMeasure)21 CXFA_Measurement::CXFA_Measurement(const WideStringView& wsMeasure) {
22   SetString(wsMeasure);
23 }
24 
CXFA_Measurement()25 CXFA_Measurement::CXFA_Measurement() {
26   Set(-1, XFA_Unit::Unknown);
27 }
28 
CXFA_Measurement(float fValue,XFA_Unit eUnit)29 CXFA_Measurement::CXFA_Measurement(float fValue, XFA_Unit eUnit) {
30   Set(fValue, eUnit);
31 }
32 
SetString(const WideStringView & wsMeasure)33 void CXFA_Measurement::SetString(const WideStringView& wsMeasure) {
34   if (wsMeasure.IsEmpty()) {
35     m_fValue = 0;
36     m_eUnit = XFA_Unit::Unknown;
37     return;
38   }
39 
40   int32_t iUsedLen = 0;
41   int32_t iOffset = (wsMeasure[0] == L'=') ? 1 : 0;
42   float fValue = FXSYS_wcstof(wsMeasure.unterminated_c_str() + iOffset,
43                               wsMeasure.GetLength() - iOffset, &iUsedLen);
44   XFA_Unit eUnit = GetUnitFromString(
45       wsMeasure.Right(wsMeasure.GetLength() - (iOffset + iUsedLen)));
46   Set(fValue, eUnit);
47 }
48 
ToString() const49 WideString CXFA_Measurement::ToString() const {
50   switch (GetUnit()) {
51     case XFA_Unit::Mm:
52       return WideString::Format(L"%.8gmm", GetValue());
53     case XFA_Unit::Pt:
54       return WideString::Format(L"%.8gpt", GetValue());
55     case XFA_Unit::In:
56       return WideString::Format(L"%.8gin", GetValue());
57     case XFA_Unit::Cm:
58       return WideString::Format(L"%.8gcm", GetValue());
59     case XFA_Unit::Mp:
60       return WideString::Format(L"%.8gmp", GetValue());
61     case XFA_Unit::Pc:
62       return WideString::Format(L"%.8gpc", GetValue());
63     case XFA_Unit::Em:
64       return WideString::Format(L"%.8gem", GetValue());
65     case XFA_Unit::Percent:
66       return WideString::Format(L"%.8g%%", GetValue());
67     default:
68       break;
69   }
70   return WideString::Format(L"%.8g", GetValue());
71 }
72 
ToUnit(XFA_Unit eUnit) const73 float CXFA_Measurement::ToUnit(XFA_Unit eUnit) const {
74   float f;
75   return ToUnitInternal(eUnit, &f) ? f : 0;
76 }
77 
ToUnitInternal(XFA_Unit eUnit,float * fValue) const78 bool CXFA_Measurement::ToUnitInternal(XFA_Unit eUnit, float* fValue) const {
79   *fValue = GetValue();
80   XFA_Unit eFrom = GetUnit();
81   if (eFrom == eUnit)
82     return true;
83 
84   switch (eFrom) {
85     case XFA_Unit::Pt:
86       break;
87     case XFA_Unit::Mm:
88       *fValue *= kPtToMm;
89       break;
90     case XFA_Unit::In:
91       *fValue *= kPtToInch;
92       break;
93     case XFA_Unit::Cm:
94       *fValue *= kPtToCm;
95       break;
96     case XFA_Unit::Mp:
97       *fValue *= kPtToMp;
98       break;
99     case XFA_Unit::Pc:
100       *fValue *= kPtToPc;
101       break;
102     default:
103       *fValue = 0;
104       return false;
105   }
106   switch (eUnit) {
107     case XFA_Unit::Pt:
108       return true;
109     case XFA_Unit::Mm:
110       *fValue /= kPtToMm;
111       return true;
112     case XFA_Unit::In:
113       *fValue /= kPtToInch;
114       return true;
115     case XFA_Unit::Cm:
116       *fValue /= kPtToCm;
117       return true;
118     case XFA_Unit::Mp:
119       *fValue /= kPtToMp;
120       return true;
121     case XFA_Unit::Pc:
122       *fValue /= kPtToPc;
123       return true;
124     default:
125       NOTREACHED();
126       return false;
127   }
128 }
129 
130 // static
GetUnitFromString(const WideStringView & wsUnit)131 XFA_Unit CXFA_Measurement::GetUnitFromString(const WideStringView& wsUnit) {
132   if (wsUnit == L"mm")
133     return XFA_Unit::Mm;
134   if (wsUnit == L"pt")
135     return XFA_Unit::Pt;
136   if (wsUnit == L"in")
137     return XFA_Unit::In;
138   if (wsUnit == L"cm")
139     return XFA_Unit::Cm;
140   if (wsUnit == L"pc")
141     return XFA_Unit::Pc;
142   if (wsUnit == L"mp")
143     return XFA_Unit::Mp;
144   if (wsUnit == L"em")
145     return XFA_Unit::Em;
146   if (wsUnit == L"%")
147     return XFA_Unit::Percent;
148   return XFA_Unit::Unknown;
149 }
150