/ src / modules / MeasureTool / MeasureToolCore / Measurement.cpp
Measurement.cpp
  1  #include "pch.h"
  2  
  3  #include "Measurement.h"
  4  
  5  #include <iostream>
  6  
  7  Measurement::Measurement(RECT winRect, float px2mmRatio) :
  8      px2mmRatio{ px2mmRatio }
  9  {
 10      rect.left = static_cast<float>(winRect.left);
 11      rect.right = static_cast<float>(winRect.right);
 12      rect.top = static_cast<float>(winRect.top);
 13      rect.bottom = static_cast<float>(winRect.bottom);
 14  }
 15  
 16  Measurement::Measurement(D2D1_RECT_F d2dRect, float px2mmRatio) :
 17      rect{ d2dRect }, px2mmRatio{ px2mmRatio }
 18  {
 19  }
 20  
 21  namespace
 22  {
 23      inline float Convert(const float pixels, const Measurement::Unit units, float px2mmRatio)
 24      {
 25          if (px2mmRatio > 0)
 26          {
 27              switch (units)
 28              {
 29              case Measurement::Unit::Pixel:
 30                  return pixels;
 31              case Measurement::Unit::Inch:
 32                  return pixels * px2mmRatio / 10.0f / 2.54f;
 33              case Measurement::Unit::Centimetre:
 34                  return pixels * px2mmRatio / 10.0f;
 35              case Measurement::Unit::Millimetre:
 36                  return pixels * px2mmRatio;
 37              default:
 38                  return pixels;
 39              }
 40          }
 41          else
 42          {
 43              switch (units)
 44              {
 45              case Measurement::Unit::Pixel:
 46                  return pixels;
 47              case Measurement::Unit::Inch:
 48                  return pixels / 96.0f;
 49              case Measurement::Unit::Centimetre:
 50                  return pixels / 96.0f * 2.54f;
 51              case Measurement::Unit::Millimetre:
 52                  return pixels / 96.0f / 10.0f * 2.54f;
 53              default:
 54                  return pixels;
 55              }
 56          }
 57      }
 58  }
 59  
 60  winrt::hstring Measurement::abbreviations[4]{};
 61  
 62  inline float Measurement::Width(const Unit units) const
 63  {
 64      return Convert(rect.right - rect.left + 1.f, units, px2mmRatio);
 65  }
 66  
 67  inline float Measurement::Height(const Unit units) const
 68  {
 69      return Convert(rect.bottom - rect.top + 1.f, units, px2mmRatio);
 70  }
 71  
 72  Measurement::Unit Measurement::GetUnitFromIndex(int index)
 73  {
 74      switch (index)
 75      {
 76      case 0:
 77          return Measurement::Unit::Pixel;
 78      case 1:
 79          return Measurement::Unit::Inch;
 80      case 2:
 81          return Measurement::Unit::Centimetre;
 82      case 3:
 83          return Measurement::Unit::Millimetre;
 84      default:
 85          return Measurement::Unit::Pixel;
 86      }
 87  }
 88  
 89  void Measurement::InitResources()
 90  {
 91      auto rm = winrt::ResourceManager{};
 92      auto mm = rm.MainResourceMap();
 93      abbreviations[0] = mm.GetValue(L"Resources/MeasurementUnitAbbrPixel").ValueAsString();
 94      abbreviations[1] = mm.GetValue(L"Resources/MeasurementUnitAbbrInch").ValueAsString();
 95      abbreviations[2] = mm.GetValue(L"Resources/MeasurementUnitAbbrCentimetre").ValueAsString();
 96      abbreviations[3] = mm.GetValue(L"Resources/MeasurementUnitAbbrMillimetre").ValueAsString();
 97  }
 98  
 99  const wchar_t* Measurement::GetUnitAbbreviation(Measurement::Unit units)
100  {
101      switch (units)
102      {
103      case Unit::Pixel:
104          return abbreviations[0].c_str();
105      case Unit::Inch:
106          return abbreviations[1].c_str();
107      case Unit::Centimetre:
108          return abbreviations[2].c_str();
109      case Unit::Millimetre:
110          return abbreviations[3].c_str();
111      default:
112          return L"??";
113      }
114  }
115  
116  Measurement::PrintResult Measurement::Print(wchar_t* buf,
117                                              const size_t bufSize,
118                                              const bool printWidth,
119                                              const bool printHeight,
120                                              const int units) const
121  {
122      PrintResult result;
123  
124      auto print = [=, &result](Measurement::Unit unit, const bool paren) {
125          if (paren)
126          {
127              result.strLen += swprintf_s(buf + result.strLen, bufSize - result.strLen, printWidth && printHeight ? L"\n(" : L" (");
128          }
129          if (printWidth)
130          {
131              result.strLen += swprintf_s(buf + result.strLen,
132                                          bufSize - result.strLen,
133                                          L"%.4g",
134                                          Width(unit));
135              if (printHeight)
136              {
137                  result.crossSymbolPos[paren] = result.strLen + 1;
138                  result.strLen += swprintf_s(buf + result.strLen,
139                                              bufSize - result.strLen,
140                                              L" \x00D7 ");
141              }
142          }
143          if (printHeight)
144          {
145              result.strLen += swprintf_s(buf + result.strLen,
146                                          bufSize - result.strLen,
147                                          L"%.4g",
148                                          Height(unit));
149          }
150          switch (unit)
151          {
152          case Measurement::Unit::Pixel:
153              result.strLen += swprintf_s(buf + result.strLen,
154                                          bufSize - result.strLen,
155                                          L" %s",
156                                          Measurement::GetUnitAbbreviation(unit));
157              break;
158          case Measurement::Unit::Inch:
159              result.strLen += swprintf_s(buf + result.strLen,
160                                          bufSize - result.strLen,
161                                          L" %s",
162                                          Measurement::GetUnitAbbreviation(unit));
163              break;
164          case Measurement::Unit::Centimetre:
165              result.strLen += swprintf_s(buf + result.strLen,
166                                          bufSize - result.strLen,
167                                          L" %s",
168                                          Measurement::GetUnitAbbreviation(unit));
169  
170              break;
171          case Measurement::Unit::Millimetre:
172              result.strLen += swprintf_s(buf + result.strLen,
173                                          bufSize - result.strLen,
174                                          L" %s",
175                                          Measurement::GetUnitAbbreviation(unit));
176  
177              break;
178          }
179          if (paren)
180          {
181              result.strLen += swprintf_s(buf + result.strLen, bufSize - result.strLen, L")");
182          }
183      };
184  
185      int count = 0;
186      const Measurement::Unit allUnits[] = {
187          Measurement::Unit::Pixel,
188          Measurement::Unit::Millimetre,
189          Measurement::Unit::Inch,
190          Measurement::Unit::Centimetre,
191      };
192      // We only use two units at most, it would be to long otherwise.
193      for each (Measurement::Unit unit in allUnits)
194      {
195          if ((unit & units) == unit)
196          {
197              count += 1;
198              if (count > 2)
199                  break;
200              print(unit, count != 1);
201          }
202      }
203  
204      return result;
205  }
206  
207  void Measurement::PrintToStream(std::wostream& stream,
208                                  const bool prependNewLine,
209                                  const bool printWidth,
210                                  const bool printHeight,
211                                  const Unit units) const
212  {
213      if (prependNewLine)
214      {
215          stream << std::endl;
216      }
217  
218      if (printWidth)
219      {
220          stream << Width(units);
221          if (printHeight)
222          {
223              stream << L" \x00D7 ";
224          }
225      }
226  
227      if (printHeight)
228      {
229          stream << Height(units);
230      }
231  
232      // If the unit is pixels, then the abbreviation will not be saved as it used to be.
233      if (units != Measurement::Unit::Pixel)
234      {
235          stream << L" " << Measurement::GetUnitAbbreviation(units);
236      }
237  }