neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
units.hpp
Go to the documentation of this file.
1// units.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2019, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
26
27namespace neogfx
28{
45
47 {
48 public:
49 virtual ~i_units_context();
50 public:
51 virtual bool device_metrics_available() const = 0;
52 virtual const i_device_metrics& device_metrics() const = 0;
53 // helpers
54 public:
72 template <typename T>
73 std::enable_if_t<std::is_scalar_v<T>, T> dpi_scale(T aValue) const
74 {
75 return static_cast<T>(static_cast<dimension>(aValue) * dpi_scale_factor());
76 }
78 {
79 return aValue * dpi_scale_factor();
80 }
81 vector2 dpi_scale(const vector2& aVector) const
82 {
83 return aVector * dpi_scale_factor();
84 }
85 size dpi_scale(const size& aSize) const
86 {
87 auto result = aSize;
88 if (result.cx != size::max_dimension())
89 result.cx *= dpi_scale_factor();
90 if (result.cy != size::max_dimension())
91 result.cy *= dpi_scale_factor();
92 return result;
93 }
94 delta dpi_scale(const delta& aDelta) const
95 {
96 auto result = aDelta;
97 if (result.dx != size::max_dimension())
98 result.dx *= dpi_scale_factor();
99 if (result.dy != size::max_dimension())
100 result.dy *= dpi_scale_factor();
101 return result;
102 }
103 point dpi_scale(const point& aPoint) const
104 {
105 return aPoint * dpi_scale_factor();
106 }
107 padding dpi_scale(const padding& aPadding) const
108 {
109 return aPadding * dpi_scale_factor();
110 }
111 template <typename T>
112 T&& dpi_select(T&& aLowDpiValue, T&& aHighDpiValue) const
113 {
114 return std::forward<T>(dpi_scale_factor() >= 1.5 ? aHighDpiValue : aLowDpiValue);
115 }
116 };
117
119 {
120 // construction
121 public:
123 ~scoped_units_context() noexcept(false);
124 // operations
125 public:
127 static void context_destroyed(i_units_context const& aContext);
128 // implementation
129 private:
130 void set_context(const i_units_context& aNewContext);
131 void restore_saved_context();
132 // attributes
133 private:
134 const i_units_context* iSavedContext;
135 };
136
141
142 template<typename T>
143 inline T convert_units(i_units_context const& aUnitsContext, units aSourceUnits, units aDestinationUnits, const T& aValue);
144
145 template <typename Units>
147 {
148 // exceptions
149 public:
150 struct units_scope_ended : std::logic_error { units_scope_ended() : std::logic_error("neogfx::basic_scoped_units_scope_ended") {} };
151 // types
152 public:
153 typedef Units units;
154 // construction
155 public:
156 basic_scoped_units(units aNewUnits = current_units()) : iSavedUnits{ current_units() }
157 {
158 set_units(aNewUnits);
159 }
160 basic_scoped_units(i_units_context const& aNewContext, units aNewUnits = current_units()) : iScopedContext{ aNewContext }, iSavedUnits { current_units() }
161 {
162 set_units(aNewUnits);
163 }
165 {
166 end();
167 }
168 // operations
169 public:
171 {
172 return current_units_for_this_thread();
173 }
175 {
176 if (iSavedUnits != std::nullopt)
177 return *iSavedUnits;
178 throw units_scope_ended();
179 }
180 void end()
181 {
182 restore_saved_units();
183 }
184 // implementation
185 private:
186 void set_units(units aNewUnits)
187 {
188 current_units_for_this_thread() = aNewUnits;
189 }
190 void restore_saved_units()
191 {
192 if (iSavedUnits != std::nullopt)
193 {
194 set_units(*iSavedUnits);
195 iSavedUnits = std::nullopt;
196 }
197 }
198 static units& current_units_for_this_thread()
199 {
200 shared_thread_local_class(units, basic_scoped_units<Units>, current_units_for_this_thread, tCurrentUnits, units::Default);
201 return tCurrentUnits;
202 }
203 // attributes
204 private:
205 std::optional<scoped_units_context> iScopedContext;
206 std::optional<units> iSavedUnits;
207 };
208
209 template <typename T>
211 {
212 typedef basic_length<T> self_type;
213 public:
214 struct unknown_unit : std::runtime_error { unknown_unit(std::string const& aUnitName) : std::runtime_error{ "neoGFX: Error: Unknown unit '" + aUnitName + "'" } {} };
215 public:
216 typedef T value_type;
217 public:
219 iValue{ aValue }, iUnits{ aUnits }
220 {
221 }
222 public:
223 bool operator==(const self_type& aRhs) const
224 {
225 return iValue == aRhs.iValue && iUnits == aRhs.iUnits;
226 }
227 bool operator!=(const self_type& aRhs) const
228 {
229 return !(*this == aRhs);
230 }
231 bool operator<(const self_type& aRhs) const
232 {
233 return std::forward_as_tuple(iValue, iUnits) < std::forward_as_tuple(aRhs.iValue, aRhs.iUnits);
234 }
235 public:
236 operator value_type() const
237 {
238 return value();
239 }
241 {
242 if (units() == units::NoUnitsAsMaximumLength)
243 return std::numeric_limits<value_type>::infinity();
244 return convert_units(scoped_units_context::current_context(), units(), basic_scoped_units<neogfx::units>::current_units(), unconverted_value());
245 }
247 {
248 return iValue;
249 }
251 {
252 return iUnits;
253 }
254 std::string to_string(bool aToEmit = true) const
255 {
257 return (aToEmit ? "std::numeric_limits<dimension>::infinity()" : "max");
258 std::ostringstream oss;
259 oss << unconverted_value();
260 if (aToEmit)
261 oss << "_";
262 switch (units())
263 {
265 oss << "px";
266 break;
268 oss << "dip";
269 break;
271 oss << "pt";
272 break;
274 oss << "pc";
275 break;
277 oss << "em";
278 break;
280 oss << "mm";
281 break;
283 oss << "cm";
284 break;
286 oss << "in";
287 break;
289 oss << "pct";
290 break;
291 }
292 return oss.str();
293 }
294 static self_type from_string(std::string const& aValue)
295 {
296 static const std::unordered_map<std::string, neogfx::units> sUnitTypes
297 {
298 { "px", neogfx::units::Pixels },
301 { "pt", neogfx::units::Points },
302 { "pc", neogfx::units::Picas },
303 { "em", neogfx::units::Ems },
306 { "in", neogfx::units::Inches },
308 };
309 if (aValue == "max")
310 return self_type{ 0.0, neogfx::units::NoUnitsAsMaximumLength };
311 self_type result;
312 std::istringstream iss{ aValue };
313 iss >> result.iValue;
314 std::string unitName;
315 iss >> unitName;
316 auto u = sUnitTypes.find(unitName);
317 if (u == sUnitTypes.end())
318 throw unknown_unit(unitName);
319 result.iUnits = u->second;
320 return result;
321 }
322 private:
323 value_type iValue;
324 neogfx::units iUnits;
325 };
326
328 {
329 public:
330 struct bad_parameter : std::logic_error { bad_parameter() : std::logic_error("neogfx::units_converter::bad_parameter") {} };
331 // construction
332 public:
333 units_converter() = delete;
337 // operations
338 public:
341 public:
342 vector2 to_device_units(const vector2& aValue) const;
344 delta to_device_units(const delta& aValue) const;
345 size to_device_units(const size& aValue) const;
346 point to_device_units(const point& aValue) const;
347 rect to_device_units(const rect& aValue) const;
348 padding to_device_units(const padding& aValue) const;
349 vector2 to_device_units(const size& aExtents, const vector2& aValue) const;
350 dimension to_device_units(const size& aExtents, dimension aValue) const;
351 delta to_device_units(const size& aExtents, const delta& aValue) const;
352 size to_device_units(const size& aExtents, const size& aValue) const;
353 point to_device_units(const size& aExtents, const point& aValue) const;
354 rect to_device_units(const size& aExtents, const rect& aValue) const;
355 vector2 from_device_units(const vector2& aValue) const;
357 delta from_device_units(const delta& aValue) const;
358 size from_device_units(const size& aValue) const;
359 point from_device_units(const point& aValue) const;
360 rect from_device_units(const rect& aValue) const;
361 padding from_device_units(const padding& aValue) const;
362 vector2 from_device_units(const size& aExtents, const vector2& aValue) const;
363 dimension from_device_units(const size& aExtents, dimension aValue) const;
364 delta from_device_units(const size& aExtents, const delta& aValue) const;
365 size from_device_units(const size& aExtents, const size& aValue) const;
366 point from_device_units(const size& aExtents, const point& aValue) const;
367 rect from_device_units(const size& aExtents, const rect& aValue) const;
368 public:
369 template <typename T, uint32_t D>
371 {
372 basic_vector<T, D> result;
373 for (uint32_t i = 0; i < D; ++i)
374 result[i] = to_device_units(aValue[i]);
375 return result;
376 }
377 template <typename T, uint32_t D>
379 {
380 basic_vector<T, D> result;
381 for (uint32_t i = 0; i < D; ++i)
382 result[i] = to_device_units(aExtents, aValue[i]);
383 return result;
384 }
385 template <typename T, uint32_t D>
387 {
388 basic_vector<T, D> result;
389 for (uint32_t i = 0; i < D; ++i)
390 result[i] = from_device_units(aValue[i]);
391 return result;
392 }
393 template <typename T, uint32_t D>
395 {
396 basic_vector<T, D> result;
397 for (uint32_t i = 0; i < D; ++i)
398 result[i] = from_device_units(aExtents, aValue[i]);
399 return result;
400 }
401 // attributes
402 private:
403 i_units_context const& iContext;
404 neogfx::units iUnits;
405 };
406
407 template<typename T>
408 inline T from_units(i_units_context const& aSourceUnitsContext, units aUnits, const T& aValue)
409 {
411 return aValue;
412 units_converter uc(aSourceUnitsContext);
413 uc.set_units(aUnits);
414 auto const result = static_cast<T>(uc.to_device_units(aValue));
416 return static_cast<T>(uc.from_device_units(result));
417 }
418
419 template<typename T>
420 inline T from_units(units aUnits, const T& aValue)
421 {
422 return from_units(scoped_units_context::current_context(), aUnits, aValue);
423 }
424
425 template<typename T>
426 inline T to_units(i_units_context const& aSourceUnitsContext, units aNewUnits, const T& aValue)
427 {
429 return aValue;
430 T result = units_converter(aSourceUnitsContext).to_device_units(aValue);
431 basic_scoped_units<units> su(aSourceUnitsContext, aNewUnits);
432 return units_converter(aSourceUnitsContext).from_device_units(result);
433 }
434
435 template<typename T>
436 inline T to_units(units aNewUnits, const T& aValue)
437 {
438 return to_units(scoped_units_context::current_context(), aNewUnits, aValue);
439 }
440
441 template<typename T>
442 inline T convert_units(i_units_context const& aSourceUnitsContext, i_units_context const& aDestinationUnitsContext, units aSourceUnits, units aDestinationUnits, const T& aValue)
443 {
444 if (aSourceUnits == aDestinationUnits)
445 {
446 if (aSourceUnits != units::Pixels ||
447 (aSourceUnitsContext.device_metrics().horizontal_dpi() == aDestinationUnitsContext.device_metrics().horizontal_dpi() &&
448 aSourceUnitsContext.device_metrics().vertical_dpi() == aDestinationUnitsContext.device_metrics().vertical_dpi()))
449 {
450 return aValue;
451 }
452 }
453 T const sourceInDeviceUnits = units_converter(aSourceUnitsContext, aSourceUnits).to_device_units(aValue);
454 T const sourceInMillimetres = units_converter(aSourceUnitsContext, units::Millimetres).from_device_units(sourceInDeviceUnits);
455 T const destinationInDeviceUnits = units_converter(aDestinationUnitsContext, units::Millimetres).to_device_units(sourceInMillimetres);
456 auto const result = units_converter(aDestinationUnitsContext, aDestinationUnits).from_device_units(destinationInDeviceUnits);
457 if (aDestinationUnits == units::Pixels || aDestinationUnits == units::ScaledPixels)
458 {
459 if constexpr (std::is_scalar_v<T>)
460 return std::round(result);
461 else
462 return result.round();
463 }
464 return result;
465 }
466
467 template<typename T>
468 inline T convert_units(i_units_context const& aUnitsContext, units aSourceUnits, units aDestinationUnits, const T& aValue)
469 {
470 return convert_units(aUnitsContext, aUnitsContext, aSourceUnits, aDestinationUnits, aValue);
471 }
472
473 template <typename T>
474 inline T from_px(T aValue)
475 {
476 return from_units(units::Pixels, aValue);
477 }
478
479 template <typename T>
480 inline T from_dip(T aValue)
481 {
482 return from_units(units::ScaledPixels, aValue);
483 }
484
485 template <typename T>
486 inline T from_pt(T aValue)
487 {
488 return from_units(units::Points, aValue);
489 }
490
491 template <typename T>
492 inline T from_pc(T aValue)
493 {
494 return from_units(units::Picas, aValue);
495 }
496
497 template <typename T>
498 inline T from_em(T aValue)
499 {
500 return from_units(units::Ems, aValue);
501 }
502
503 template <typename T>
504 inline T from_mm(T aValue)
505 {
506 return from_units(units::Millimetres, aValue);
507 }
508
509 template <typename T>
510 inline T from_cm(T aValue)
511 {
512 return from_units(units::Centimetres, aValue);
513 }
514
515 template <typename T>
516 inline T from_in(T aValue)
517 {
518 return from_units(units::Inches, aValue);
519 }
520
521 template <typename T>
522 inline T from_pct(T aValue)
523 {
524 return from_units(units::Percentage, aValue);
525 }
526
527 template <typename ResultT, typename T>
528 inline ResultT from_px(T aValue)
529 {
530 return static_cast<ResultT>(from_units(units::Pixels, aValue));
531 }
532
533 template <typename ResultT, typename T>
534 inline ResultT from_dip(T aValue)
535 {
536 return static_cast<ResultT>(from_units(units::ScaledPixels, aValue));
537 }
538
539 template <typename ResultT, typename T>
540 inline ResultT from_pt(T aValue)
541 {
542 return static_cast<ResultT>(from_units(units::Points, aValue));
543 }
544
545 template <typename ResultT, typename T>
546 inline ResultT from_pc(T aValue)
547 {
548 return static_cast<ResultT>(from_units(units::Picas, aValue));
549 }
550
551 template <typename ResultT, typename T>
552 inline ResultT from_em(T aValue)
553 {
554 return static_cast<ResultT>(from_units(units::Ems, aValue));
555 }
556
557 template <typename ResultT, typename T>
558 inline ResultT from_mm(T aValue)
559 {
560 return static_cast<ResultT>(from_units(units::Millimetres, aValue));
561 }
562
563 template <typename ResultT, typename T>
564 inline ResultT from_cm(T aValue)
565 {
566 return static_cast<ResultT>(from_units(units::Centimetres, aValue));
567 }
568
569 template <typename ResultT, typename T>
570 inline ResultT from_in(T aValue)
571 {
572 return static_cast<ResultT>(from_units(units::Inches, aValue));
573 }
574
575 template <typename ResultT, typename T>
576 inline ResultT from_pct(T aValue)
577 {
578 return static_cast<ResultT>(from_units(units::Percentage, aValue));
579 }
580
581 template <typename T>
582 inline T to_px(T aValue)
583 {
584 return to_units(units::Pixels, aValue);
585 }
586
587 template <typename T>
588 inline T to_dip(T aValue)
589 {
590 return to_units(units::ScaledPixels, aValue);
591 }
592
593 template <typename T>
594 inline T to_pt(T aValue)
595 {
596 return to_units(units::Points, aValue);
597 }
598
599 template <typename T>
600 inline T to_pc(T aValue)
601 {
602 return to_units(units::Picas, aValue);
603 }
604
605 template <typename T>
606 inline T to_em(T aValue)
607 {
608 return to_units(units::Ems, aValue);
609 }
610
611 template <typename T>
612 inline T to_mm(T aValue)
613 {
614 return to_units(units::Millimetres, aValue);
615 }
616
617 template <typename T>
618 inline T to_cm(T aValue)
619 {
620 return to_units(units::Centimetres, aValue);
621 }
622
623 template <typename T>
624 inline T to_in(T aValue)
625 {
626 return to_units(units::Inches, aValue);
627 }
628
629 template <typename T>
630 inline T to_pct(T aValue)
631 {
632 return to_units(units::Percentage, aValue);
633 }
634
635 template <typename ResultT, typename T>
636 inline ResultT to_px(T aValue)
637 {
638 return static_cast<ResultT>(to_units(units::Pixels, aValue));
639 }
640
641 template <typename ResultT, typename T>
642 inline ResultT to_dip(T aValue)
643 {
644 return static_cast<ResultT>(to_units(units::ScaledPixels, aValue));
645 }
646
647 template <typename ResultT, typename T>
648 inline ResultT to_pt(T aValue)
649 {
650 return static_cast<ResultT>(to_units(units::Points, aValue));
651 }
652
653 template <typename ResultT, typename T>
654 inline ResultT to_pc(T aValue)
655 {
656 return static_cast<ResultT>(to_units(units::Picas, aValue));
657 }
658
659 template <typename ResultT, typename T>
660 inline ResultT to_em(T aValue)
661 {
662 return static_cast<ResultT>(to_units(units::Ems, aValue));
663 }
664
665 template <typename ResultT, typename T>
666 inline ResultT to_mm(T aValue)
667 {
668 return static_cast<ResultT>(to_units(units::Millimetres, aValue));
669 }
670
671 template <typename ResultT, typename T>
672 inline ResultT to_cm(T aValue)
673 {
674 return static_cast<ResultT>(to_units(units::Centimetres, aValue));
675 }
676
677 template <typename ResultT, typename T>
678 inline ResultT to_in(T aValue)
679 {
680 return static_cast<ResultT>(to_units(units::Inches, aValue));
681 }
682
683 template <typename ResultT, typename T>
684 inline ResultT to_pct(T aValue)
685 {
686 return static_cast<ResultT>(to_units(units::Percentage, aValue));
687 }
688
689 template <typename T>
690 inline basic_length<T> px(T aValue)
691 {
692 return basic_length<T>{ aValue, units::Pixels };
693 }
694
695 template <typename T>
696 inline basic_length<T> dip(T aValue)
697 {
698 return basic_length<T>{ aValue, units::ScaledPixels };
699 }
700
701 template <typename T>
702 inline basic_length<T> pt(T aValue)
703 {
704 return basic_length<T>{ aValue, units::Points };
705 }
706
707 template <typename T>
708 inline basic_length<T> pc(T aValue)
709 {
710 return basic_length<T>{ aValue, units::Picas };
711 }
712
713 template <typename T>
714 inline basic_length<T> em(T aValue)
715 {
716 return basic_length<T>{ aValue, units::Ems };
717 }
718
719 template <typename T>
720 inline basic_length<T> mm(T aValue)
721 {
722 return basic_length<T>{ aValue, units::Millimetres };
723 }
724
725 template <typename T>
726 inline basic_length<T> cm(T aValue)
727 {
728 return basic_length<T>{ aValue, units::Centimetres };
729 }
730
731 template <typename T>
732 inline basic_length<T> in(T aValue)
733 {
734 return basic_length<T>{ aValue, units::Inches };
735 }
736
737 template <typename T>
738 inline basic_length<T> pct(T aValue)
739 {
740 return basic_length<T>{ aValue, units::Percentage };
741 }
742
743 template <typename T>
744 inline T ceil_rasterized(T aValue)
745 {
746 return from_px(std::ceil(to_px(aValue)));
747 }
748
749 template <typename T>
751 {
752 return basic_delta<T>{ ceil_rasterized(aDelta.dx), ceil_rasterized(aDelta.dy) };
753 }
754
755 template <typename T>
757 {
758 return basic_size<T>{ ceil_rasterized(aSize.cx), ceil_rasterized(aSize.cy) };
759 }
760
761 template <typename T>
763 {
764 return basic_point<T>{ ceil_rasterized(aPoint.x), ceil_rasterized(aPoint.y) };
765 }
766
767 template <typename T>
772
773 template <typename T>
775 {
776 return basic_rect<T>{ ceil_rasterized(aRect.position()), ceil_rasterized(aRect.extents()) };
777 }
778
779 template <typename T>
780 inline T ceil_rasterized(const basic_length<T>& aLength)
781 {
782 return ceil_rasterized(static_cast<T>(aLength));
783 }
784
785 template <typename T>
786 inline T floor_rasterized(T aValue)
787 {
788 return from_px(std::floor(to_px(aValue)));
789 }
790
791 template <typename T>
793 {
794 return basic_delta<T>{ floor_rasterized(aDelta.dx), floor_rasterized(aDelta.dy) };
795 }
796
797 template <typename T>
799 {
800 return basic_size<T>{ floor_rasterized(aSize.cx), floor_rasterized(aSize.cy) };
801 }
802
803 template <typename T>
805 {
806 return basic_point<T>{ floor_rasterized(aPoint.x), floor_rasterized(aPoint.y) };
807 }
808
809 template <typename T>
811 {
813 }
814
815 template <typename T>
816 inline T floor_rasterized(const basic_length<T>& aLength)
817 {
818 return floor_rasterized(static_cast<T>(aLength));
819 }
820
821 namespace unit_literals
822 {
823 inline basic_length<default_geometry_value_type> operator ""_px(long double aValue)
824 {
825 return px(static_cast<default_geometry_value_type>(aValue));
826 }
827
828 inline basic_length<default_geometry_value_type> operator ""_dip(long double aValue)
829 {
830 return dip(static_cast<default_geometry_value_type>(aValue));
831 }
832
833 inline basic_length<default_geometry_value_type> operator ""_dp(long double aValue)
834 {
835 return dip(static_cast<default_geometry_value_type>(aValue));
836 }
837
838 inline basic_length<default_geometry_value_type> operator ""_pt(long double aValue)
839 {
840 return pt(static_cast<default_geometry_value_type>(aValue));
841 }
842
843 inline basic_length<default_geometry_value_type> operator ""_pc(long double aValue)
844 {
845 return pc(static_cast<default_geometry_value_type>(aValue));
846 }
847
848 inline basic_length<default_geometry_value_type> operator ""_em(long double aValue)
849 {
850 return em(static_cast<default_geometry_value_type>(aValue));
851 }
852
853 inline basic_length<default_geometry_value_type> operator ""_mm(long double aValue)
854 {
855 return mm(static_cast<default_geometry_value_type>(aValue));
856 }
857
858 inline basic_length<default_geometry_value_type> operator ""_cm(long double aValue)
859 {
860 return cm(static_cast<default_geometry_value_type>(aValue));
861 }
862
863 inline basic_length<default_geometry_value_type> operator ""_in(long double aValue)
864 {
865 return in(static_cast<default_geometry_value_type>(aValue));
866 }
867
868 inline basic_length<default_geometry_value_type> operator ""_pct(long double aValue)
869 {
870 return pct(static_cast<default_geometry_value_type>(aValue));
871 }
872
873 inline basic_length<default_geometry_value_type> operator ""_px(unsigned long long int aValue)
874 {
875 return px(static_cast<default_geometry_value_type>(aValue));
876 }
877
878 inline basic_length<default_geometry_value_type> operator ""_dip(unsigned long long int aValue)
879 {
880 return dip(static_cast<default_geometry_value_type>(aValue));
881 }
882
883 inline basic_length<default_geometry_value_type> operator ""_dp(unsigned long long int aValue)
884 {
885 return dip(static_cast<default_geometry_value_type>(aValue));
886 }
887
888 inline basic_length<default_geometry_value_type> operator ""_pt(unsigned long long int aValue)
889 {
890 return pt(static_cast<default_geometry_value_type>(aValue));
891 }
892
893 inline basic_length<default_geometry_value_type> operator ""_pc(unsigned long long int aValue)
894 {
895 return pc(static_cast<default_geometry_value_type>(aValue));
896 }
897
898 inline basic_length<default_geometry_value_type> operator ""_em(unsigned long long int aValue)
899 {
900 return em(static_cast<default_geometry_value_type>(aValue));
901 }
902
903 inline basic_length<default_geometry_value_type> operator ""_mm(unsigned long long int aValue)
904 {
905 return mm(static_cast<default_geometry_value_type>(aValue));
906 }
907
908 inline basic_length<default_geometry_value_type> operator ""_cm(unsigned long long int aValue)
909 {
910 return cm(static_cast<default_geometry_value_type>(aValue));
911 }
912
913 inline basic_length<default_geometry_value_type> operator ""_in(unsigned long long int aValue)
914 {
915 return in(static_cast<default_geometry_value_type>(aValue));
916 }
917
918 inline basic_length<default_geometry_value_type> operator ""_pct(unsigned long long int aValue)
919 {
920 return pct(static_cast<default_geometry_value_type>(aValue));
921 }
922 }
923
924 using namespace unit_literals;
925
928}
coordinate_type dy
coordinate_type dx
std::string to_string(bool aToEmit=true) const
Definition units.hpp:254
value_type value() const
Definition units.hpp:240
value_type unconverted_value() const
Definition units.hpp:246
bool operator==(const self_type &aRhs) const
Definition units.hpp:223
bool operator!=(const self_type &aRhs) const
Definition units.hpp:227
basic_length(value_type aValue=value_type{}, neogfx::units aUnits=neogfx::units::Pixels)
Definition units.hpp:218
static self_type from_string(std::string const &aValue)
Definition units.hpp:294
bool operator<(const self_type &aRhs) const
Definition units.hpp:231
neogfx::units units() const
Definition units.hpp:250
coordinate_type x
coordinate_type y
const point_type & position() const
const size_type & extents() const
basic_scoped_units(units aNewUnits=current_units())
Definition units.hpp:156
basic_scoped_units(i_units_context const &aNewContext, units aNewUnits=current_units())
Definition units.hpp:160
static units current_units()
Definition units.hpp:170
units saved_units() const
Definition units.hpp:174
static constexpr dimension_type max_dimension()
dimension_type cy
dimension_type cx
virtual dimension horizontal_dpi() const =0
virtual dimension vertical_dpi() const =0
virtual const i_device_metrics & device_metrics() const =0
point dpi_scale(const point &aPoint) const
Definition units.hpp:103
vector2 dpi_scale(const vector2 &aVector) const
Definition units.hpp:81
virtual ~i_units_context()
Definition units.hpp:137
dimension x2_dpi_scale_factor() const
Definition units.hpp:55
size dpi_scale(const size &aSize) const
Definition units.hpp:85
dimension xn_dpi_scale_factor() const
Definition units.hpp:60
dimension dpi_scale(dimension aValue) const
Definition units.hpp:77
std::enable_if_t< std::is_scalar_v< T >, T > dpi_scale(T aValue) const
Definition units.hpp:73
delta dpi_scale(const delta &aDelta) const
Definition units.hpp:94
T && dpi_select(T &&aLowDpiValue, T &&aHighDpiValue) const
Definition units.hpp:112
dimension dpi_scale_factor() const
Definition units.hpp:65
padding dpi_scale(const padding &aPadding) const
Definition units.hpp:107
virtual bool device_metrics_available() const =0
static void context_destroyed(i_units_context const &aContext)
~scoped_units_context() noexcept(false)
static i_units_context const & current_context()
scoped_units_context(i_units_context const &aNewContext)
size from_device_units(const size &aExtents, const size &aValue) const
point to_device_units(const size &aExtents, const point &aValue) const
units_converter(i_units_context const &aContext)
basic_vector< T, D > from_device_units(const size &aExtents, const basic_vector< T, D > &aValue)
Definition units.hpp:394
dimension to_device_units(dimension aValue) const
void set_units(neogfx::units aUnits)
vector2 from_device_units(const size &aExtents, const vector2 &aValue) const
neogfx::units units() const
point from_device_units(const size &aExtents, const point &aValue) const
basic_vector< T, D > to_device_units(const size &aExtents, const basic_vector< T, D > &aValue)
Definition units.hpp:378
dimension from_device_units(const size &aExtents, dimension aValue) const
dimension to_device_units(const size &aExtents, dimension aValue) const
dimension from_device_units(dimension aValue) const
padding from_device_units(const padding &aValue) const
size to_device_units(const size &aValue) const
basic_vector< T, D > from_device_units(const basic_vector< T, D > &aValue)
Definition units.hpp:386
delta to_device_units(const size &aExtents, const delta &aValue) const
delta from_device_units(const delta &aValue) const
rect from_device_units(const size &aExtents, const rect &aValue) const
rect to_device_units(const size &aExtents, const rect &aValue) const
rect from_device_units(const rect &aValue) const
padding to_device_units(const padding &aValue) const
point from_device_units(const point &aValue) const
basic_vector< T, D > to_device_units(const basic_vector< T, D > &aValue)
Definition units.hpp:370
vector2 to_device_units(const vector2 &aValue) const
vector2 from_device_units(const vector2 &aValue) const
delta to_device_units(const delta &aValue) const
units_converter(i_units_context const &aContext, neogfx::units aUnits)
point to_device_units(const point &aValue) const
delta from_device_units(const size &aExtents, const delta &aValue) const
size to_device_units(const size &aExtents, const size &aValue) const
vector2 to_device_units(const size &aExtents, const vector2 &aValue) const
size from_device_units(const size &aValue) const
rect to_device_units(const rect &aValue) const
self_type round() const
#define shared_thread_local_class(VariableType, ClassType, VariableScope, VariableName,...)
T to_pc(T aValue)
Definition units.hpp:600
basic_length< T > pt(T aValue)
Definition units.hpp:702
T to_pt(T aValue)
Definition units.hpp:594
T to_mm(T aValue)
Definition units.hpp:612
T to_dip(T aValue)
Definition units.hpp:588
T to_em(T aValue)
Definition units.hpp:606
T to_units(i_units_context const &aSourceUnitsContext, units aNewUnits, const T &aValue)
Definition units.hpp:426
T from_pct(T aValue)
Definition units.hpp:522
T to_cm(T aValue)
Definition units.hpp:618
T from_mm(T aValue)
Definition units.hpp:504
T from_pc(T aValue)
Definition units.hpp:492
basic_length< T > pct(T aValue)
Definition units.hpp:738
default_geometry_value_type dimension
basic_length< T > cm(T aValue)
Definition units.hpp:726
basic_length< T > in(T aValue)
Definition units.hpp:732
T to_pct(T aValue)
Definition units.hpp:630
T from_em(T aValue)
Definition units.hpp:498
T from_in(T aValue)
Definition units.hpp:516
T floor_rasterized(T aValue)
Definition units.hpp:786
basic_length< default_geometry_value_type > length
Definition units.hpp:926
basic_length< T > px(T aValue)
Definition units.hpp:690
T from_dip(T aValue)
Definition units.hpp:480
dimension x2_dpi_scale_factor(dimension aPpi)
T to_in(T aValue)
Definition units.hpp:624
basic_length< T > em(T aValue)
Definition units.hpp:714
dpi_scale_type & dpi_scale_type_for_thread()
basic_length< T > dip(T aValue)
Definition units.hpp:696
T from_pt(T aValue)
Definition units.hpp:486
scalar default_geometry_value_type
T to_px(T aValue)
Definition units.hpp:582
dimension xn_dpi_scale_factor(dimension aPpi)
T ceil_rasterized(T aValue)
Definition units.hpp:744
T from_units(i_units_context const &aSourceUnitsContext, units aUnits, const T &aValue)
Definition units.hpp:408
T convert_units(i_units_context const &aUnitsContext, units aSourceUnits, units aDestinationUnits, const T &aValue)
Definition units.hpp:468
basic_length< T > pc(T aValue)
Definition units.hpp:708
T from_px(T aValue)
Definition units.hpp:474
basic_scoped_units< units > scoped_units
Definition units.hpp:927
basic_length< T > mm(T aValue)
Definition units.hpp:720
T from_cm(T aValue)
Definition units.hpp:510
unknown_unit(std::string const &aUnitName)
Definition units.hpp:214