Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
GDI.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
5#include "Stroika/Foundation/Execution/Exceptions.h"
6
7namespace Stroika::Frameworks::Led {
8
9 /*
10 ********************************************************************************
11 ************************************ Point_Base ********************************
12 ********************************************************************************
13 */
14 template <typename COORD_TYPE>
15 constexpr Point_Base<COORD_TYPE>::Point_Base ()
16 : v (COORD_TYPE (0))
17 , h (COORD_TYPE (0))
18 {
19 }
20 template <typename COORD_TYPE>
21 constexpr Point_Base<COORD_TYPE>::Point_Base (COORD_TYPE newV, COORD_TYPE newH)
22 : v (newV)
23 , h (newH)
24 {
25 }
26 template <typename COORD_TYPE>
27 constexpr Point_Base<COORD_TYPE> operator+ (const Point_Base<COORD_TYPE>& lhs, const Point_Base<COORD_TYPE>& rhs)
28 {
29 Led_Point result = lhs;
30 result.v += rhs.v;
31 result.h += rhs.h;
32 return result;
33 }
34
35 /*
36 ********************************************************************************
37 ************************************ Led_Point *********************************
38 ********************************************************************************
39 */
40 inline Led_Point operator- (const Led_Point& lhs, const Led_Point& rhs)
41 {
42 return (Led_Point (lhs.v - rhs.v, lhs.h - rhs.h));
43 }
44
45 /*
46 ********************************************************************************
47 ************************************ Rect_Base *********************************
48 ********************************************************************************
49 */
50 template <typename POINT_TYPE, typename SIZE_TYPE>
51 /*
52 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::Rect_Base
53 @DESCRIPTION: <p>No-argument constructor leaves object uninitialized (garbage data).</p>
54 */
55 constexpr Rect_Base<POINT_TYPE, SIZE_TYPE>::Rect_Base ()
56 : top (CoordinateType (0))
57 , left (CoordinateType (0))
58 , bottom (CoordinateType (0))
59 , right (CoordinateType (0))
60 {
61 }
62 template <typename POINT_TYPE, typename SIZE_TYPE>
63 /*
64 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::Rect_Base
65 @DESCRIPTION: <p>Initialize with argument top, left, height, width.</p>
66 */
67 constexpr Rect_Base<POINT_TYPE, SIZE_TYPE>::Rect_Base (CoordinateType newTop, CoordinateType newLeft, DistanceType newHeight, DistanceType newWidth)
68 : top (newTop)
69 , left (newLeft)
70 , bottom (newTop + newHeight)
71 , right (newLeft + newWidth)
72 {
73 }
74 template <typename POINT_TYPE, typename SIZE_TYPE>
75 constexpr Rect_Base<POINT_TYPE, SIZE_TYPE>::Rect_Base (POINT_TYPE origin, SIZE_TYPE size)
76 : top (origin.v)
77 , left (origin.h)
78 , bottom (origin.v + size.v)
79 , right (origin.h + size.h)
80 {
81 }
82 template <typename POINT_TYPE, typename SIZE_TYPE>
83 /*
84 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetTop
85 @DESCRIPTION: <p>Retrieve top of rectangle.</p>
86 */
87 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::CoordinateType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetTop () const
88 {
89 return top;
90 }
91 template <typename POINT_TYPE, typename SIZE_TYPE>
92 /*
93 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetLeft
94 @DESCRIPTION: <p>Retrieve left of rectangle.</p>
95 */
96 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::CoordinateType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetLeft () const
97 {
98 return left;
99 }
100 template <typename POINT_TYPE, typename SIZE_TYPE>
101 /*
102 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetBottom
103 @DESCRIPTION: <p>Retrieve bottom of rectangle.</p>
104 */
105 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::CoordinateType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetBottom () const
106 {
107 return bottom;
108 }
109 template <typename POINT_TYPE, typename SIZE_TYPE>
110 /*
111 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetRight
112 @DESCRIPTION: <p>Retrieve right of rectangle.</p>
113 */
114 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::CoordinateType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetRight () const
115 {
116 return right;
117 }
118 template <typename POINT_TYPE, typename SIZE_TYPE>
119 /*
120 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::IsEmpty
121 @DESCRIPTION: <p>Returns true if either horizontal or vertical dimentions are less or equal to zero.</p>
122 */
123 inline bool Rect_Base<POINT_TYPE, SIZE_TYPE>::IsEmpty () const
124 {
125 return (right <= left or bottom <= top);
126 }
127 template <typename POINT_TYPE, typename SIZE_TYPE>
128 /*
129 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetHeight
130 @DESCRIPTION: <p>Asserts height is non-negative, and then returns height.</p>
131 */
132 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::DistanceType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetHeight () const
133 {
134 Ensure (bottom >= top);
135 return (bottom - top);
136 }
137 template <typename POINT_TYPE, typename SIZE_TYPE>
138 /*
139 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::GetWidth
140 @DESCRIPTION: <p>Asserts width is non-negative, and then returns width.</p>
141 */
142 inline typename Rect_Base<POINT_TYPE, SIZE_TYPE>::DistanceType Rect_Base<POINT_TYPE, SIZE_TYPE>::GetWidth () const
143 {
144 Ensure (right >= left);
145 return (right - left);
146 }
147 template <typename POINT_TYPE, typename SIZE_TYPE>
148 inline POINT_TYPE Rect_Base<POINT_TYPE, SIZE_TYPE>::GetTopLeft () const
149 {
150 return (POINT_TYPE (top, left));
151 }
152 template <typename POINT_TYPE, typename SIZE_TYPE>
153 inline POINT_TYPE Rect_Base<POINT_TYPE, SIZE_TYPE>::GetTopRight () const
154 {
155 return (POINT_TYPE (top, right));
156 }
157 template <typename POINT_TYPE, typename SIZE_TYPE>
158 inline POINT_TYPE Rect_Base<POINT_TYPE, SIZE_TYPE>::GetBotRight () const
159 {
160 return (POINT_TYPE (bottom, right));
161 }
162 template <typename POINT_TYPE, typename SIZE_TYPE>
163 inline POINT_TYPE Rect_Base<POINT_TYPE, SIZE_TYPE>::GetOrigin () const
164 {
165 return (POINT_TYPE (top, left));
166 }
167 template <typename POINT_TYPE, typename SIZE_TYPE>
168 inline SIZE_TYPE Rect_Base<POINT_TYPE, SIZE_TYPE>::GetSize () const
169 {
170 return (SIZE_TYPE (bottom - top, right - left));
171 }
172 template <typename POINT_TYPE, typename SIZE_TYPE>
173 inline bool Rect_Base<POINT_TYPE, SIZE_TYPE>::Contains (POINT_TYPE p) const
174 {
175 return ((p >= GetTopLeft ()) and (p <= GetBotRight ()));
176 }
177 template <typename POINT_TYPE, typename SIZE_TYPE>
178 inline bool Rect_Base<POINT_TYPE, SIZE_TYPE>::Contains (Rect_Base<POINT_TYPE, SIZE_TYPE> r) const
179 {
180 // could be more terse, but this does it...
181 return (Contains (r.GetTopLeft ()) and Contains (r.GetBotRight ()));
182 }
183 template <typename POINT_TYPE, typename SIZE_TYPE>
184 inline void Rect_Base<POINT_TYPE, SIZE_TYPE>::SetOrigin (POINT_TYPE p)
185 {
186 top = p.v;
187 left = p.h;
188 }
189 template <typename POINT_TYPE, typename SIZE_TYPE>
190 inline void Rect_Base<POINT_TYPE, SIZE_TYPE>::SetTop (CoordinateType t)
191 {
192 this->top = t;
193 }
194 template <typename POINT_TYPE, typename SIZE_TYPE>
195 inline void Rect_Base<POINT_TYPE, SIZE_TYPE>::SetLeft (CoordinateType l)
196 {
197 this->left = l;
198 }
199 template <typename POINT_TYPE, typename SIZE_TYPE>
200 inline void Rect_Base<POINT_TYPE, SIZE_TYPE>::SetBottom (CoordinateType b)
201 {
202 this->bottom = b;
203 }
204 template <typename POINT_TYPE, typename SIZE_TYPE>
205 inline void Rect_Base<POINT_TYPE, SIZE_TYPE>::SetRight (CoordinateType r)
206 {
207 this->right = r;
208 }
209 template <typename POINT_TYPE, typename SIZE_TYPE>
210 inline const Rect_Base<POINT_TYPE, SIZE_TYPE>& Rect_Base<POINT_TYPE, SIZE_TYPE>::operator+= (const POINT_TYPE& delta)
211 {
212 *this = THIS_TYPE (GetTopLeft () + delta, GetSize ()); // simple definition - but could tweek!
213 return *this;
214 }
215 template <typename POINT_TYPE, typename SIZE_TYPE>
216 inline const Rect_Base<POINT_TYPE, SIZE_TYPE>& Rect_Base<POINT_TYPE, SIZE_TYPE>::operator-= (const POINT_TYPE& delta)
217 {
218 *this = THIS_TYPE (GetTopLeft () - delta, GetSize ()); // simple definition - but could tweek!
219 return *this;
220 }
221 template <typename POINT_TYPE, typename SIZE_TYPE>
222 /*
223 @METHOD: Rect_Base<POINT_TYPE,SIZE_TYPE>::operator*=
224 @DESCRIPTION: <p>Intersects this rect with the argument rectangle.</p>
225 */
226 inline const Rect_Base<POINT_TYPE, SIZE_TYPE>& Rect_Base<POINT_TYPE, SIZE_TYPE>::operator*= (const Rect_Base<POINT_TYPE, SIZE_TYPE>& intersectWith)
227 {
228 POINT_TYPE topLeft = max (GetTopLeft (), intersectWith.GetTopLeft ());
229 POINT_TYPE botRight = min (GetBotRight (), intersectWith.GetBotRight ());
230 POINT_TYPE newSize = botRight - topLeft;
231 if (newSize >= Led_Point (0, 0)) {
232 *this = THIS_TYPE (topLeft, SIZE_TYPE (newSize));
233 }
234 else {
235 *this = THIS_TYPE (0, 0, 0, 0);
236 }
237 return *this;
238 }
239 template <typename POINT_TYPE, typename SIZE_TYPE>
240 inline bool Rect_Base<POINT_TYPE, SIZE_TYPE>::operator== (const Rect_Base<POINT_TYPE, SIZE_TYPE>& rhs) const
241 {
242 return ((GetLeft () == rhs.GetLeft ()) and (GetRight () == rhs.GetRight ()) and (GetTop () == rhs.GetTop ()) and
243 (GetBottom () == rhs.GetBottom ()));
244 }
245
246 /*
247 ********************************************************************************
248 ************************************ TWIPS *************************************
249 ********************************************************************************
250 */
251 constexpr inline TWIPS::TWIPS (long v)
252 : fValue (v)
253 {
254 }
255 constexpr TWIPS::operator long () const
256 {
257 return fValue;
258 }
259 inline TWIPS& TWIPS::operator+= (const TWIPS& rhs)
260 {
261 fValue += rhs.fValue;
262 return *this;
263 }
264 inline TWIPS& TWIPS::operator-= (const TWIPS& rhs)
265 {
266 fValue -= rhs.fValue;
267 return *this;
268 }
269 inline TWIPS& TWIPS::operator*= (double rhs)
270 {
271 fValue = static_cast<long> (fValue * rhs);
272 return *this;
273 }
274 inline TWIPS operator+ (const TWIPS& lhs, const TWIPS& rhs)
275 {
276 return TWIPS (static_cast<long> (lhs) + static_cast<long> (rhs));
277 }
278 inline TWIPS operator- (const TWIPS& lhs, const TWIPS& rhs)
279 {
280 return TWIPS (static_cast<long> (lhs) - static_cast<long> (rhs));
281 }
282 inline constexpr TWIPS TWIPS::kPoint = TWIPS{20}; // a printers 'point' (1/72 of an inch)
283 inline constexpr TWIPS TWIPS::kInch = TWIPS{1440};
284 inline constexpr TWIPS TWIPS::kOneInch = TWIPS{1440};
285
286#if qStroika_Platform_Windows
287 /*
288 ********************************************************************************
289 ******************************** FontObject ************************************
290 ********************************************************************************
291 */
292 inline FontObject::~FontObject ()
293 {
294 (void)DeleteObject ();
295 }
296 inline FontObject ::operator HFONT () const
297 {
298 return m_hObject;
299 }
300 inline int FontObject ::GetObject (int nCount, LPVOID lpObject) const
301 {
302 Assert (m_hObject != nullptr);
303 return ::GetObject (m_hObject, nCount, lpObject);
304 }
305 inline BOOL FontObject ::DeleteObject ()
306 {
307 if (m_hObject == nullptr)
308 return FALSE;
309 HFONT h = m_hObject;
310 m_hObject = nullptr;
311 return ::DeleteObject (h);
312 }
313 inline BOOL FontObject ::CreateFontIndirect (const LOGFONT* lpLogFont)
314 {
315 return Attach (::CreateFontIndirect (lpLogFont));
316 }
317 inline BOOL FontObject ::Attach (HFONT hObject)
318 {
319 Assert (m_hObject == nullptr); // only attach once, detach on destroy
320 if (hObject == nullptr)
321 return FALSE;
322 m_hObject = hObject;
323 return TRUE;
324 }
325#endif
326
327#if qStroika_Platform_Windows
328 /*
329 ********************************************************************************
330 *********************************** Brush **************************************
331 ********************************************************************************
332 */
333 inline Brush::Brush (COLORREF crColor)
334 : m_hObject{nullptr}
335 {
336 if (!Attach (::CreateSolidBrush (crColor)))
337 Foundation::Execution::Throw (bad_alloc{});
338 }
339 inline Brush::~Brush ()
340 {
341 (void)DeleteObject ();
342 }
343 inline Brush::operator HBRUSH () const
344 {
345 return m_hObject;
346 }
347 inline BOOL Brush::Attach (HBRUSH hObject)
348 {
349 Assert (m_hObject == nullptr); // only attach once, detach on destroy
350 if (hObject == nullptr)
351 return FALSE;
352 m_hObject = hObject;
353 return TRUE;
354 }
355 inline BOOL Brush::DeleteObject ()
356 {
357 if (m_hObject == nullptr)
358 return FALSE;
359 HBRUSH h = m_hObject;
360 m_hObject = nullptr;
361 return ::DeleteObject (h);
362 }
363#endif
364
365#if qStroika_Frameworks_Led_SupportGDI
366 /*
367 ********************************************************************************
368 ************************************ Region ************************************
369 ********************************************************************************
370 */
371 inline Region::Region ()
372#if qStroika_Platform_Windows
373 : fRgn{::CreateRectRgn (0, 0, 0, 0)}
374#endif
375 {
376#if qStroika_Platform_Windows
377 Foundation::Execution::ThrowIfNull (fRgn);
378#endif
379 }
380 inline Region::Region (const Led_Rect& r)
381#if qStroika_Platform_Windows
382 : fRgn (::CreateRectRgn (r.GetLeft (), r.GetTop (), r.GetRight (), r.GetBottom ()))
383#endif
384 {
385 Require (r.GetHeight () >= 0);
386 Require (r.GetWidth () >= 0);
387#if qStroika_Platform_Windows
388 Foundation::Execution::ThrowIfNull (fRgn);
389#endif
390 Assert (GetBoundingRect () == r or (GetBoundingRect ().IsEmpty () and r.IsEmpty ()));
391 }
392 inline Region::Region (const Region& from)
393#if qStroika_Platform_Windows
394 : fRgn (::CreateRectRgn (0, 0, 0, 0))
395#endif
396 {
397#if qStroika_Platform_Windows
398 Foundation::Execution::ThrowIfNull (fRgn);
399#endif
400#if qStroika_Platform_Windows
401 Verify (::CombineRgn (fRgn, from, from, RGN_COPY) != ERROR);
402#endif
403 }
404 inline const Region& Region::operator= (const Region& rhs)
405 {
406#if qStroika_Platform_Windows
407 Verify (::CombineRgn (fRgn, rhs, rhs, RGN_COPY) != ERROR);
408#endif
409#if qStroika_Platform_Windows
410 Foundation::Execution::ThrowIfNull (fRgn);
411#endif
412 return *this;
413 }
414 inline Region::~Region ()
415 {
416#if qStroika_Platform_Windows
417 if (fRgn != nullptr) {
418 ::DeleteObject (fRgn);
419 }
420#endif
421 }
422 inline bool Region::IsEmpty () const
423 {
424#if qStroika_Platform_Windows
425 AssertNotNull (fRgn);
426#endif
427 Assert (false); //NYI - not used yet - so don't worry about this right now... LGP 2002-12-03
428 return false;
429 }
430 inline Led_Rect Region::GetBoundingRect () const
431 {
432#if qStroika_Platform_Windows
433 AssertNotNull (fRgn);
434 RECT r;
435 int tmp = ::GetRgnBox (fRgn, &r);
436 Verify (tmp != 0);
438 if (tmp == 0) {
439 Assert (AsLedRect (r) == Led_Rect (0, 0, 0, 0));
440 }
441 }
442 return AsLedRect (r);
443#else
444 Assert (false);
445 return Led_Rect (0, 0, 0, 0);
446#endif
447 }
448 inline Region operator* (const Region& lhs, const Region& rhs)
449 {
450 Region result;
451#if qStroika_Platform_Windows
452 Verify (::CombineRgn (result, lhs, rhs, RGN_AND) != ERROR);
453#endif
454 return result;
455 }
456 inline Region operator+ (const Region& lhs, const Region& rhs)
457 {
458 Region result;
459#if qStroika_Platform_Windows
460 Verify (::CombineRgn (result, lhs, rhs, RGN_OR) != ERROR);
461#endif
462 return result;
463 }
464 inline Led_Rect operator* (const Led_Rect& lhs, const Led_Rect& rhs)
465 {
466 Led_Rect tmp = lhs;
467 return tmp *= rhs;
468 }
469#if qStroika_Platform_Windows
470 inline Region::operator HRGN () const
471 {
472 return fRgn;
473 }
474 inline int Region::CombineRgn (Region* pRgn1, Region* pRgn2, int nCombineMode)
475 {
476 Require (pRgn1 != nullptr);
477 Require (pRgn2 != nullptr);
478 Require (fRgn != nullptr);
479 return ::CombineRgn (fRgn, pRgn1->fRgn, pRgn2->fRgn, nCombineMode);
480 }
481 inline BOOL Region::PtInRegion (int x, int y) const
482 {
483 Require (fRgn != nullptr);
484 return ::PtInRegion (fRgn, x, y);
485 }
486 inline BOOL Region::PtInRegion (POINT point) const
487 {
488 Require (fRgn != nullptr);
489 return ::PtInRegion (fRgn, point.x, point.y);
490 }
491
492 inline BOOL Region::DeleteObject ()
493 {
494 if (fRgn == nullptr)
495 return FALSE;
496 HRGN r = fRgn;
497 fRgn = nullptr;
498 return ::DeleteObject (r);
499 }
500#endif
501#endif
502
503 /*
504 ********************************************************************************
505 ************************************ TabStopList *******************************
506 ********************************************************************************
507 */
508#if qStroika_Frameworks_Led_SupportGDI
509 inline DistanceType TabStopList::ComputeTabStopAfterPosition (Tablet* tablet, DistanceType afterPos) const
510 {
511 RequireNotNull (tablet);
512 return tablet->CvtFromTWIPSH (ComputeTabStopAfterPosition (tablet->CvtToTWIPSH (afterPos)));
513 }
514#endif
515
516#if qStroika_Platform_Windows
517 /*
518 ********************************************************************************
519 **************************************** Bitmap ********************************
520 ********************************************************************************
521 */
522 inline Bitmap::~Bitmap ()
523 {
524 if (m_hObject != nullptr) {
525 ::DeleteObject (m_hObject);
526 }
527 }
528 inline void Bitmap::DeleteObject ()
529 {
530 if (m_hObject != nullptr) {
531 ::DeleteObject (m_hObject);
532 m_hObject = nullptr;
533 }
534 }
535 inline Bitmap::operator HBITMAP () const
536 {
537 return m_hObject;
538 }
539 inline Led_Size Bitmap::GetImageSize () const
540 {
541 // only valid if m_hObject != nullptr
542 RequireNotNull (m_hObject);
543 return fImageSize;
544 }
545#endif
546
547#if qStroika_Frameworks_Led_SupportGDI
548 /*
549 ********************************************************************************
550 **************************************** Tablet ********************************
551 ********************************************************************************
552 */
553#if qStroika_Platform_Windows
554 inline Tablet::operator HDC () const
555 {
556 return m_hDC;
557 }
558#endif
559 /*
560 @METHOD: Tablet::CvtFromTWIPSV
561 @DESCRIPTION:
562 <p>See also @'Tablet::CvtFromTWIPSH', @'Tablet::CvtToTWIPSV', @'Tablet::CvtToTWIPSH'.</p>
563 */
564 inline CoordinateType Tablet::CvtFromTWIPSV (TWIPS from) const
565 {
566#if qStroika_Platform_Windows
567 if (fLogPixelsV == 0) {
568 fLogPixelsV = GetDeviceCaps (LOGPIXELSY);
569 }
570 POINT vpOrg;
571 Verify (::GetViewportOrgEx (m_hAttribDC, &vpOrg));
572 POINT wOrg;
573 Verify (::GetWindowOrgEx (m_hAttribDC, &wOrg));
574 POINT x = vpOrg;
575 x.y += ::MulDiv (from, fLogPixelsV, 1440);
576 Verify (::DPtoLP (m_hAttribDC, &x, 1));
577 x.y -= wOrg.y;
578 Assert (x.x == wOrg.x);
579 return x.y;
580#else
581 //TMPHACK - look at tablet resolution?
582 return from * Globals::Get ().GetMainScreenLogPixelsV () / 1440;
583// return from / 20; // assume 72dpi on mac
584#endif
585 }
586 /*
587 @METHOD: Tablet::CvtFromTWIPSH
588 @DESCRIPTION:
589 <p>See also @'Tablet::CvtFromTWIPSV', @'Tablet::CvtToTWIPSV', @'Tablet::CvtToTWIPSH'.</p>
590 */
591 inline CoordinateType Tablet::CvtFromTWIPSH (TWIPS from) const
592 {
593#if qStroika_Platform_Windows
594 if (fLogPixelsH == 0) {
595 fLogPixelsH = GetDeviceCaps (LOGPIXELSX);
596 }
597 POINT vpOrg;
598 Verify (::GetViewportOrgEx (m_hAttribDC, &vpOrg));
599 POINT wOrg;
600 Verify (::GetWindowOrgEx (m_hAttribDC, &wOrg));
601 POINT x = vpOrg;
602 x.x += ::MulDiv (from, fLogPixelsH, 1440);
603 Verify (::DPtoLP (m_hAttribDC, &x, 1));
604 x.x -= wOrg.x;
605 Assert (x.y == wOrg.y);
606 return x.x;
607#else
608 //TMPHACK - look at tablet resolution?
609 return from * Globals::Get ().GetMainScreenLogPixelsH () / 1440;
610// return from / 20; // assume 72dpi on mac
611#endif
612 }
613 /*
614 @METHOD: Tablet::CvtToTWIPSV
615 @DESCRIPTION: <p>Utility routine to convert from logical coordinates (usually pixels) to TWIPS.</p>
616 <p>See also @'Tablet::CvtFromTWIPSV', @'Tablet::CvtFromTWIPSH', @'Tablet::CvtToTWIPSH'.</p>
617 */
618 inline TWIPS Tablet::CvtToTWIPSV (CoordinateType from) const
619 {
620#if qStroika_Platform_Windows
621 if (fLogPixelsV == 0) {
622 fLogPixelsV = GetDeviceCaps (LOGPIXELSY);
623 }
624 POINT vpOrg;
625 Verify (::GetViewportOrgEx (m_hAttribDC, &vpOrg));
626 POINT wOrg;
627 Verify (::GetWindowOrgEx (m_hAttribDC, &wOrg));
628 POINT x = wOrg;
629 x.y += from;
630 Verify (::LPtoDP (m_hAttribDC, &x, 1));
631 x.y -= vpOrg.y;
632 Assert (x.x == wOrg.x);
633 return TWIPS (::MulDiv (x.y, 1440, fLogPixelsV));
634#else
635 return TWIPS (from * 1440 / Globals::Get ().GetMainScreenLogPixelsV ());
636// return TWIPS (from * 20); // assume 72dpi on mac
637#endif
638 }
639 /*
640 @METHOD: Tablet::CvtToTWIPSH
641 @DESCRIPTION: <p>Utility routine to convert from logical coordinates (usually pixels) to TWIPS.</p>
642 <p>See also @'Tablet::CvtFromTWIPSV', @'Tablet::CvtFromTWIPSH', @'Tablet::CvtToTWIPSV'.</p>
643 */
644 inline TWIPS Tablet::CvtToTWIPSH (CoordinateType from) const
645 {
646#if qStroika_Platform_Windows
647 if (fLogPixelsH == 0) {
648 fLogPixelsH = GetDeviceCaps (LOGPIXELSX);
649 }
650 POINT vpOrg;
651 Verify (::GetViewportOrgEx (m_hAttribDC, &vpOrg));
652 POINT wOrg;
653 Verify (::GetWindowOrgEx (m_hAttribDC, &wOrg));
654 POINT x = wOrg;
655 x.x += from;
656 Verify (::LPtoDP (m_hAttribDC, &x, 1));
657 x.x -= vpOrg.x;
658 Assert (x.y == vpOrg.y);
659 return TWIPS (::MulDiv (x.x, 1440, fLogPixelsH));
660#else
661 return TWIPS (from * 1440 / Globals::Get ().GetMainScreenLogPixelsH ());
662// return TWIPS (from * 20); // assume 72dpi on mac
663#endif
664 }
665#if qStroika_Platform_Windows
666 inline BOOL Tablet::BitBlt (int x, int y, int nWidth, int nHeight, Tablet* pSrcDC, int xSrc, int ySrc, DWORD dwRop)
667 {
668 AssertNotNull (m_hDC);
669 return ::BitBlt (m_hDC, x, y, nWidth, nHeight, pSrcDC->m_hDC, xSrc, ySrc, dwRop);
670 }
671 inline BOOL Tablet::CreateCompatibleDC (Tablet* pDC)
672 {
673 Assert (m_hDC == nullptr); // only attach once, detach on destroy
674 Assert (m_hAttribDC == nullptr); // only attach to an empty DC
675
676 m_hDC = ::CreateCompatibleDC (pDC == nullptr ? nullptr : pDC->m_hDC);
677 if (m_hDC == nullptr)
678 return FALSE;
679
680 m_hAttribDC = m_hDC;
681 fOwnsDC = eOwnsDC;
682 return TRUE;
683 }
684 inline COLORREF Tablet::SetTextColor (COLORREF crColor)
685 {
686 Assert (m_hDC != nullptr);
687 COLORREF crRetVal = CLR_INVALID;
688
689 if (m_hDC != m_hAttribDC)
690 crRetVal = ::SetTextColor (m_hDC, crColor);
691 if (m_hAttribDC != nullptr)
692 crRetVal = ::SetTextColor (m_hAttribDC, crColor);
693 return crRetVal;
694 }
695 inline COLORREF Tablet::SetBkColor (COLORREF crColor)
696 {
697 Assert (m_hDC != nullptr);
698 COLORREF crRetVal = CLR_INVALID;
699
700 if (m_hDC != m_hAttribDC)
701 crRetVal = ::SetBkColor (m_hDC, crColor);
702 if (m_hAttribDC != nullptr)
703 crRetVal = ::SetBkColor (m_hAttribDC, crColor);
704 return crRetVal;
705 }
706 inline HWND Tablet::GetWindow () const
707 {
708 Assert (m_hDC != nullptr);
709 return ::WindowFromDC (m_hDC);
710 }
711 inline BOOL Tablet::IsPrinting () const
712 {
713 return m_bPrinting;
714 }
715 inline BOOL Tablet::RoundRect (int x1, int y1, int x2, int y2, int x3, int y3)
716 {
717 Assert (m_hDC != nullptr);
718 return ::RoundRect (m_hDC, x1, y1, x2, y2, x3, y3);
719 }
720 inline BOOL Tablet::TextOut (int x, int y, LPCTSTR lpszString, int nCount)
721 {
722 Assert (m_hDC != nullptr);
723 return ::TextOut (m_hDC, x, y, lpszString, nCount);
724 }
725 inline int Tablet::SetBkMode (int nBkMode)
726 {
727 Assert (m_hDC != nullptr);
728 int nRetVal = 0;
729
730 if (m_hDC != m_hAttribDC)
731 nRetVal = ::SetBkMode (m_hDC, nBkMode);
732 if (m_hAttribDC != nullptr)
733 nRetVal = ::SetBkMode (m_hAttribDC, nBkMode);
734 return nRetVal;
735 }
736 inline unsigned int Tablet::SetTextAlign (unsigned int nTextAlign)
737 {
738 Assert (m_hDC != nullptr);
739 unsigned int nRetVal = 0;
740
741 if (m_hDC != m_hAttribDC)
742 nRetVal = ::SetTextAlign (m_hDC, nTextAlign);
743 if (m_hAttribDC != nullptr)
744 nRetVal = ::SetTextAlign (m_hAttribDC, nTextAlign);
745 return nRetVal;
746 }
747 inline SIZE Tablet::GetWindowExt () const
748 {
749 Assert (m_hAttribDC != nullptr);
750 SIZE size;
751 Verify (::GetWindowExtEx (m_hAttribDC, &size));
752 return size;
753 }
754 inline SIZE Tablet::GetViewportExt () const
755 {
756 Assert (m_hAttribDC != nullptr);
757 SIZE size;
758 Verify (::GetViewportExtEx (m_hAttribDC, &size));
759 return size;
760 }
761 inline BOOL Tablet::Rectangle (int x1, int y1, int x2, int y2)
762 {
763 Assert (m_hDC != nullptr);
764 return ::Rectangle (m_hDC, x1, y1, x2, y2);
765 }
766 inline BOOL Tablet::Rectangle (const RECT& r)
767 {
768 Assert (m_hDC != nullptr);
769 return ::Rectangle (m_hDC, r.left, r.top, r.right, r.bottom);
770 }
771 inline BOOL Tablet::Rectangle (LPCRECT lpRect)
772 {
773 Assert (m_hDC != nullptr);
774 return ::Rectangle (m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
775 }
776 inline BOOL Tablet::GetTextMetrics (LPTEXTMETRIC lpMetrics) const
777 {
778 Assert (m_hAttribDC != nullptr);
779 return ::GetTextMetrics (m_hAttribDC, lpMetrics);
780 }
781 inline HBITMAP Tablet::SelectObject (HBITMAP hBitmap)
782 {
783 Assert (m_hDC != nullptr);
784 return (HBITMAP)::SelectObject (m_hDC, hBitmap);
785 }
786#if defined(STRICT)
787 inline HFONT Tablet::SelectObject (HFONT hFont)
788 {
789 Assert (m_hDC != nullptr);
790 return (HFONT)::SelectObject (m_hDC, hFont);
791 }
792#endif
793 inline POINT Tablet::SetWindowOrg (int x, int y)
794 {
795 Assert (m_hDC != nullptr);
796 POINT point;
797 memset (&point, 0, sizeof (point));
798 if (m_hDC != m_hAttribDC)
799 Verify (::SetWindowOrgEx (m_hDC, x, y, &point));
800 if (m_hAttribDC != nullptr)
801 Verify (::SetWindowOrgEx (m_hAttribDC, x, y, &point));
802 return point;
803 }
804 inline int Tablet::GetDeviceCaps (int nIndex) const
805 {
806 Assert (m_hAttribDC != nullptr);
807 return ::GetDeviceCaps (m_hAttribDC, nIndex);
808 }
809 inline BOOL Tablet::Attach (HDC hDC, Tablet::OwnDCControl ownsDC)
810 {
811 Assert (m_hDC == nullptr); // only attach once, detach on destroy
812 Assert (m_hAttribDC == nullptr); // only attach to an empty DC
813
814 if (hDC == nullptr)
815 return FALSE;
816
817 m_hDC = hDC;
818 m_hAttribDC = m_hDC; // Default to same as output
819 fOwnsDC = ownsDC;
820 return TRUE;
821 }
822 inline HDC Tablet::Detach ()
823 {
824 HDC hDC = m_hDC;
825 m_hAttribDC = nullptr;
826 m_hDC = nullptr;
827 return hDC;
828 }
829#endif
830 inline void Tablet::MoveTo (const Led_Point& to)
831 {
832#if qStroika_Platform_Windows
833 Assert (m_hDC != nullptr);
834 Verify (::MoveToEx (m_hDC, to.h, to.v, nullptr));
835#endif
836 }
837 inline void Tablet::LineTo (const Led_Point& to)
838 {
839#if qStroika_Platform_Windows
840 Assert (m_hDC != nullptr);
841 Verify (::LineTo (m_hDC, to.h, to.v));
842#endif
843 }
844 inline Region Tablet::GetClip () const
845 {
846 Region result;
847#if qStroika_Platform_Windows
848 int r = ::GetClipRgn (*this, result);
849 Assert (r == 0 or r == 1 or r == -1);
850 if (r == 0) {
851 static Region kWideOpened = Region (Led_Rect (-10000, -10000, 20000, 20000));
852 result = kWideOpened;
853 }
854#else
855 Assert (false); // NYI
856#endif
857 return result;
858 }
859 inline bool Tablet::GetClip (Region* r) const
860 {
861 RequireNotNull (r);
862#if qStroika_Platform_Windows
863 int res = ::GetClipRgn (*this, *r);
864 Assert (res == 0 or res == 1 or res == -1);
865 if (res == 0) {
866 return false;
867 }
868 return true;
869#else
870 Assert (false); // NYI
871 return false;
872#endif
873 }
874 inline void Tablet::SetClip ()
875 {
876#if qStroika_Platform_Windows
877 Verify (::SelectClipRgn (*this, nullptr) != ERROR);
878#else
879 Assert (false); // NYI
880#endif
881 }
882 inline void Tablet::SetClip (const Led_Rect& clipTo)
883 {
884#if qStroika_Platform_Windows
885 Verify (::SelectClipRgn (*this, Region (clipTo)) != ERROR);
886 Ensure (GetClip ().GetBoundingRect () == clipTo);
887#else
888 Assert (false); // NYI
889#endif
890 }
891 inline void Tablet::SetClip (const Region& clipTo)
892 {
893#if qStroika_Platform_Windows
894 Verify (::SelectClipRgn (*this, clipTo) != ERROR);
895#else
896 Assert (false); // NYI
897#endif
898 }
899#endif
900
901#if qStroika_Frameworks_Led_SupportGDI
902 /*
903 ********************************************************************************
904 ****************************************** Globals *****************************
905 ********************************************************************************
906 */
907 inline Globals& Globals::Get ()
908 {
909 if (sThe == nullptr) {
910 sThe = new Globals ();
911 }
912 return *sThe;
913 }
914 inline DistanceType Globals::GetMainScreenLogPixelsH () const
915 {
916 return fLogPixelsH;
917 }
918 inline DistanceType Globals::GetMainScreenLogPixelsV () const
919 {
920 return fLogPixelsV;
921 }
922#endif
923
924 /*
925 ********************************************************************************
926 *********************************** Led_Rect ***********************************
927 ********************************************************************************
928 */
929 inline Led_Rect operator- (const Led_Rect& lhs, const Led_Point& rhs)
930 {
931 return Led_Rect (lhs.GetTop () - rhs.v, lhs.GetLeft () - rhs.h, lhs.GetHeight (), lhs.GetWidth ());
932 }
933 inline Led_Rect operator+ (Led_Point p, Led_Rect r)
934 {
935 return (Led_Rect (r.GetTop () + p.v, r.GetLeft () + p.h, r.GetHeight (), r.GetWidth ()));
936 }
937 inline Led_Rect operator+ (Led_Rect r, Led_Point p)
938 {
939 return (Led_Rect (r.GetTop () + p.v, r.GetLeft () + p.h, r.GetHeight (), r.GetWidth ()));
940 }
941
942 /*
943 ********************************************************************************
944 *********************************** Intersect **********************************
945 ********************************************************************************
946 */
947 inline bool Intersect (const Led_Rect& lhs, const Led_Rect& rhs)
948 {
949 if (rhs.GetTop () >= lhs.GetBottom ()) {
950 return false;
951 }
952 else if (rhs.GetBottom () <= lhs.GetTop ()) {
953 return false;
954 }
955 else if (rhs.GetLeft () >= lhs.GetRight ()) {
956 return false;
957 }
958 else if (rhs.GetRight () <= lhs.GetLeft ()) {
959 return false;
960 }
961
962 if (rhs.GetHeight () == 0 or rhs.GetWidth () == 0 or lhs.GetHeight () == 0 or lhs.GetWidth () == 0) {
963 return false;
964 }
965 return true;
966 }
967#if qStroika_Frameworks_Led_SupportGDI
968 inline bool Intersect (const Led_Rect& lhs, const Region& rhs)
969 {
970#if qStroika_Platform_Windows
971 Region lhsRgn = lhs;
972 Region result;
973 return result.CombineRgn (&lhsRgn, const_cast<Region*> (&rhs), RGN_AND) != NULLREGION;
974#endif
975 }
976 inline bool Intersect (const Region& lhs, const Led_Rect& rhs)
977 {
978#if qStroika_Platform_Windows
979 Region rhsRgn = rhs;
980 Region result;
981 return result.CombineRgn (const_cast<Region*> (&lhs), &rhsRgn, RGN_AND) != NULLREGION;
982#endif
983 }
984 inline bool Intersect (const Region& lhs, const Region& rhs)
985 {
986#if qStroika_Platform_Windows
987 Region result;
988 return result.CombineRgn (const_cast<Region*> (&lhs), const_cast<Region*> (&rhs), RGN_AND) != NULLREGION;
989#endif
990 }
991#endif
992
993 /*
994 ********************************************************************************
995 ******************************** Intersection **********************************
996 ********************************************************************************
997 */
998 inline Led_Rect Intersection (const Led_Rect& lhs, const Led_Rect& rhs)
999 {
1000 Led_Rect tmp = lhs;
1001 return tmp *= rhs;
1002 }
1003
1004 /*
1005 ********************************************************************************
1006 ************************************ Led_Size **********************************
1007 ********************************************************************************
1008 */
1009 inline Led_Size operator+ (Led_Size lhs, Led_Size rhs)
1010 {
1011 return Led_Size (lhs.v + rhs.v, lhs.h + rhs.h);
1012 }
1013 inline Led_Size operator* (int lhs, Led_Size rhs)
1014 {
1015 return Led_Size (lhs * rhs.v, lhs * rhs.h);
1016 }
1017
1018 /*
1019 ********************************************************************************
1020 *********************************** InsetRect **********************************
1021 ********************************************************************************
1022 */
1023 /*
1024 @METHOD: InsetRect
1025 @DESCRIPTION: <p>Utility routine to convert shrink (if vBy/hBy posative), or expand (if negative) the given @'Led_Rect'.
1026 NB: This routine pins the minimum output rect size (in each dimention) to be zero.</p>
1027 */
1028 inline Led_Rect InsetRect (const Led_Rect& r, int vBy, int hBy)
1029 {
1030 return Led_Rect (r.GetTop () + vBy, r.GetLeft () + hBy, max (0L, CoordinateType (r.GetHeight ()) - 2 * vBy),
1031 max (0L, CoordinateType (r.GetWidth ()) - 2 * hBy));
1032 }
1033
1034 /*
1035 ********************************************************************************
1036 *********************************** EnsureRectInRect ***************************
1037 ********************************************************************************
1038 */
1039 /*
1040 @METHOD: EnsureRectInRect
1041 @DESCRIPTION: <p>Utility routine to ensure the first rect is entirely enclosed in the second (enclosing) rectangle.
1042 Pin the edges so it fits.</p>
1043 */
1044 inline Led_Rect EnsureRectInRect (const Led_Rect& r, Led_Rect enlosingR)
1045 {
1046 DistanceType winWidth = min (r.GetWidth (), enlosingR.GetWidth ());
1047 DistanceType winHeight = min (r.GetHeight (), enlosingR.GetHeight ());
1048 CoordinateType winLeft = max (r.GetLeft (), enlosingR.GetLeft ());
1049 CoordinateType winTop = max (r.GetTop (), enlosingR.GetTop ());
1050
1051 DISABLE_COMPILER_MSC_WARNING_START (4018) //signed/unsigned mismatch
1052 if ((winLeft + winWidth) > enlosingR.GetRight ()) {
1053 winLeft = enlosingR.GetRight () - winWidth;
1054 }
1055 if ((winTop + winHeight) > enlosingR.GetBottom ()) {
1056 winTop = enlosingR.GetBottom () - winHeight;
1057 }
1058 DISABLE_COMPILER_MSC_WARNING_END (4018)
1059 return Led_Rect (winTop, winLeft, winHeight, winWidth);
1060 }
1061
1062#if qStroika_Frameworks_Led_SupportGDI
1063 /*
1064 ********************************************************************************
1065 ********************************* EnsureRectOnScreen ***************************
1066 ********************************************************************************
1067 */
1068 /*
1069 @METHOD: EnsureRectOnScreen
1070 @DESCRIPTION: <p>Utility routine to ensure the first rect (typically used for a window) fits on the sceen.
1071 Pin the edges so it fits. See also @'EnsureRectInRect'.</p>
1072 */
1073 inline Led_Rect EnsureRectOnScreen ([[maybe_unused]] Led_Rect& r)
1074 {
1075#if qStroika_Platform_Windows
1076 // Get the limits of the 'workarea'
1077 RECT rWorkArea;
1078 memset (&rWorkArea, 0, sizeof (rWorkArea));
1079 BOOL bResult = SystemParametersInfo (SPI_GETWORKAREA, sizeof (RECT), &rWorkArea, 0);
1080 if (!bResult) {
1081 rWorkArea.left = rWorkArea.top = 0;
1082 rWorkArea.right = GetSystemMetrics (SM_CXSCREEN);
1083 rWorkArea.bottom = GetSystemMetrics (SM_CYSCREEN);
1084 }
1085 return EnsureRectInRect (r, AsLedRect (rWorkArea));
1086#else
1087 Assert (false); // NYI -
1088 return Led_Rect (0, 0, 0, 0);
1089#endif
1090 }
1091#endif
1092
1093 /*
1094 ********************************************************************************
1095 ************************************* Led_Point ********************************
1096 ********************************************************************************
1097 */
1098#if qStroika_Platform_Windows
1099 inline Led_Point AsLedPoint (POINT p)
1100 {
1101 return Led_Point (p.y, p.x);
1102 }
1103 inline POINT AsPOINT (Led_Point p)
1104 {
1105 POINT newP;
1106 newP.x = p.h;
1107 newP.y = p.v;
1108 return newP;
1109 }
1110 inline Led_Rect AsLedRect (RECT r)
1111 {
1112 return Led_Rect (r.top, r.left, r.bottom - r.top, r.right - r.left);
1113 }
1114 inline RECT AsRECT (Led_Rect r)
1115 {
1116 RECT newR;
1117 newR.top = r.GetTop ();
1118 newR.left = r.GetLeft ();
1119 newR.bottom = r.GetBottom ();
1120 newR.right = r.GetRight ();
1121 return newR;
1122 }
1123 inline SIZE AsSIZE (Led_Size s)
1124 {
1125 SIZE result;
1126 result.cx = s.h;
1127 result.cy = s.v;
1128 return result;
1129 }
1130 inline Led_Size AsLedSize (SIZE s)
1131 {
1132 Led_Size result;
1133 result.h = s.cx;
1134 result.v = s.cy;
1135 return result;
1136 }
1137#endif
1138
1139#if qStroika_Frameworks_Led_SupportGDI
1140 /*
1141 @METHOD: Led_CvtScreenPixelsToTWIPSV
1142 @DESCRIPTION: <p>Utility routine to convert from logical coordinates (usually pixels) to TWIPS.
1143 <p>See also @'Led_CvtScreenPixelsToTWIPSH'.</p>
1144 */
1145 inline TWIPS Led_CvtScreenPixelsToTWIPSV (CoordinateType from)
1146 {
1147#if qStroika_Platform_Windows
1148 return TWIPS (::MulDiv (from, 1440, Globals::Get ().GetMainScreenLogPixelsV ()));
1149#else
1150 return TWIPS (from * 1440 / Globals::Get ().GetMainScreenLogPixelsV ());
1151#endif
1152 }
1153
1154 /*
1155 @METHOD: Led_CvtScreenPixelsToTWIPSH
1156 @DESCRIPTION: <p>Utility routine to convert from logical coordinates (usually pixels) to TWIPS.
1157 <p>See also @'Led_CvtScreenPixelsToTWIPSV'.</p>
1158 */
1159 inline TWIPS Led_CvtScreenPixelsToTWIPSH (CoordinateType from)
1160 {
1161#if qStroika_Platform_Windows
1162 return TWIPS (::MulDiv (from, 1440, Globals::Get ().GetMainScreenLogPixelsH ()));
1163#else
1164 return TWIPS (from * 1440 / Globals::Get ().GetMainScreenLogPixelsH ());
1165#endif
1166 }
1167 /*
1168 @METHOD: Led_CvtScreenPixelsFromTWIPSV
1169 @DESCRIPTION: <p>Utility routine to convert from TWIPS to logical coordinates (usually pixels).
1170 <p>See also @'Led_CvtScreenPixelsFromTWIPSH'.</p>
1171 */
1172 inline CoordinateType Led_CvtScreenPixelsFromTWIPSV (TWIPS from)
1173 {
1174#if qStroika_Platform_Windows
1175 return ::MulDiv (from, Globals::Get ().GetMainScreenLogPixelsV (), 1440);
1176#else
1177 return TWIPS{from * Globals::Get ().GetMainScreenLogPixelsV () / 1440};
1178#endif
1179 }
1180 /*
1181 @METHOD: Led_CvtScreenPixelsFromTWIPSH
1182 @DESCRIPTION: <p>Utility routine to convert from TWIPS to logical coordinates (usually pixels).
1183 <p>See also @'Led_CvtScreenPixelsFromTWIPSV'.</p>
1184 */
1185 inline CoordinateType Led_CvtScreenPixelsFromTWIPSH (TWIPS from)
1186 {
1187#if qStroika_Platform_Windows
1188 return ::MulDiv (from, Globals::Get ().GetMainScreenLogPixelsH (), 1440);
1189#else
1190 return TWIPS{from * Globals::Get ().GetMainScreenLogPixelsH () / 1440};
1191#endif
1192 }
1193#endif
1194
1195#if qStroika_Frameworks_Led_SupportGDI
1196 /*
1197 ********************************************************************************
1198 ******************************* FontMetrics ************************************
1199 ********************************************************************************
1200 */
1201#if qStroika_Platform_Windows
1202 inline FontMetrics::FontMetrics (const TEXTMETRIC& from)
1203 : fPlatformSpecific (from)
1204 {
1205 }
1206#endif
1207 inline DistanceType FontMetrics::GetAscent () const
1208 {
1209#if qStroika_Platform_Windows
1210 return (fPlatformSpecific.tmAscent);
1211#endif
1212 }
1213 inline DistanceType FontMetrics::GetDescent () const
1214 {
1215#if qStroika_Platform_Windows
1216 return (fPlatformSpecific.tmDescent);
1217#endif
1218 }
1219 inline DistanceType FontMetrics::GetLeading () const
1220 {
1221#if qStroika_Platform_Windows
1222 return (fPlatformSpecific.tmExternalLeading);
1223#endif
1224 }
1225 inline DistanceType FontMetrics::GetHeight () const
1226 {
1227#if qStroika_Platform_Windows
1228 Assert (fPlatformSpecific.tmHeight >= 0);
1229 Assert (GetAscent () + GetDescent () == DistanceType (fPlatformSpecific.tmHeight));
1230#endif
1231 return (GetAscent () + GetDescent ());
1232 }
1233 inline DistanceType FontMetrics::GetLineHeight () const
1234 {
1235 return (GetAscent () + GetDescent () + GetLeading ());
1236 }
1237 inline nonvirtual DistanceType FontMetrics::GetMaxCharacterWidth () const
1238 {
1239#if qStroika_Platform_Windows
1240 return fPlatformSpecific.tmMaxCharWidth;
1241#endif
1242 }
1243#if qStroika_Platform_Windows
1244 inline nonvirtual DistanceType FontMetrics::GetAveCharacterWidth () const
1245 {
1246 return fPlatformSpecific.tmAveCharWidth;
1247 }
1248#endif
1249#if qStroika_Platform_Windows
1250 inline FontMetrics::operator const TEXTMETRIC*() const
1251 {
1252 return &fPlatformSpecific;
1253 }
1254 inline FontMetrics::operator TEXTMETRIC*()
1255 {
1256 return &fPlatformSpecific;
1257 }
1258#endif
1259#endif
1260
1261 /*
1262 ********************************************************************************
1263 ************************************* Color ************************************
1264 ********************************************************************************
1265 */
1266 constexpr inline Color::Color (ColorValue redValue, ColorValue greenValue, ColorValue blueValue)
1267 : fRed{redValue}
1268 , fGreen{greenValue}
1269 , fBlue{blueValue}
1270 {
1271 }
1272#if qStroika_Platform_Windows
1273 inline Color::Color (COLORREF colorRef)
1274 : fRed (static_cast<ColorValue> (GetRValue (colorRef)) << 8)
1275 , fGreen (static_cast<ColorValue> (GetGValue (colorRef)) << 8)
1276 , fBlue (static_cast<ColorValue> (GetBValue (colorRef)) << 8)
1277 {
1278 }
1279#endif
1280 inline Color::ColorValue Color::GetRed () const
1281 {
1282 return fRed;
1283 }
1284 inline Color::ColorValue Color::GetGreen () const
1285 {
1286 return fGreen;
1287 }
1288 inline Color::ColorValue Color::GetBlue () const
1289 {
1290 return fBlue;
1291 }
1292#if qStroika_Platform_Windows
1293 inline COLORREF Color::GetOSRep () const
1294 {
1295 return RGB (fRed >> 8, fGreen >> 8, fBlue >> 8);
1296 }
1297#endif
1298 inline Color operator* (Color lhs, float factor)
1299 {
1300 using CV = Color::ColorValue;
1301 return Color (static_cast<CV> (lhs.GetRed () * factor), static_cast<CV> (lhs.GetGreen () * factor), static_cast<CV> (lhs.GetBlue () * factor));
1302 }
1303 inline Color operator/ (Color lhs, float divBy)
1304 {
1305 return Color (static_cast<Color::ColorValue> (lhs.GetRed () / divBy), static_cast<Color::ColorValue> (lhs.GetGreen () / divBy),
1306 static_cast<Color::ColorValue> (lhs.GetBlue () / divBy));
1307 }
1308 inline Color operator+ (Color lhs, Color rhs)
1309 {
1310 return Color (lhs.GetRed () + rhs.GetRed (), lhs.GetGreen () + rhs.GetGreen (), lhs.GetBlue () + rhs.GetBlue ());
1311 }
1312 inline Color operator- (Color lhs, Color rhs)
1313 {
1314 return Color (lhs.GetRed () - rhs.GetRed (), lhs.GetGreen () - rhs.GetGreen (), lhs.GetBlue () - rhs.GetBlue ());
1315 }
1316 inline unsigned int Distance_Squared (Color lhs, Color rhs)
1317 {
1318 int rDiff = static_cast<int> (lhs.GetRed ()) - static_cast<int> (rhs.GetRed ());
1319 int gDiff = static_cast<int> (lhs.GetGreen ()) - static_cast<int> (rhs.GetGreen ());
1320 int bDiff = static_cast<int> (lhs.GetBlue ()) - static_cast<int> (rhs.GetBlue ());
1321 unsigned int sum = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
1322 return sum;
1323 }
1324 inline unsigned int Distance (Color lhs, Color rhs)
1325 {
1326 return static_cast<unsigned int> (::sqrt (static_cast<float> (Distance_Squared (lhs, rhs))));
1327 }
1328#if qStroika_Platform_Windows
1329 inline unsigned int Distance_Squared (COLORREF lhs, COLORREF rhs)
1330 {
1331 int rDiff = static_cast<int> (GetRValue (lhs)) - static_cast<int> (GetRValue (rhs));
1332 int gDiff = static_cast<int> (GetGValue (lhs)) - static_cast<int> (GetGValue (rhs));
1333 int bDiff = static_cast<int> (GetBValue (lhs)) - static_cast<int> (GetBValue (rhs));
1334 unsigned int sum = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
1335 return sum;
1336 }
1337#endif
1338}
1339
1340namespace std {
1341 template <>
1342 struct less<Stroika::Frameworks::Led::Color> {
1343 bool operator() (const Stroika::Frameworks::Led::Color& _Left, const Stroika::Frameworks::Led::Color& _Right) const
1344 {
1345 if (_Left.GetRed () < _Right.GetRed ()) {
1346 return true;
1347 }
1348 else if (_Left.GetRed () == _Right.GetRed ()) {
1349 if (_Left.GetGreen () < _Right.GetGreen ()) {
1350 return true;
1351 }
1352 else if (_Left.GetGreen () == _Right.GetGreen ()) {
1353 return (_Left.GetBlue () < _Right.GetBlue ());
1354 }
1355 }
1356 return false;
1357 }
1358 };
1359}
1360
1361namespace Stroika::Frameworks::Led {
1362#if qStroika_Platform_Windows
1363 inline Pen::Pen (int nPenStyle, int nWidth, COLORREF crColor)
1364 : m_hObject{nullptr}
1365 {
1366 if (!Attach (::CreatePen (nPenStyle, nWidth, crColor)))
1367 Foundation::Execution::Throw (bad_alloc{});
1368 }
1369 inline Pen::~Pen ()
1370 {
1371 (void)DeleteObject ();
1372 }
1373 inline Pen::operator HPEN () const
1374 {
1375 return m_hObject;
1376 }
1377 inline BOOL Pen::Attach (HPEN hObject)
1378 {
1379 Assert (m_hObject == nullptr); // only attach once, detach on destroy
1380 if (hObject == nullptr)
1381 return FALSE;
1382 m_hObject = hObject;
1383 return TRUE;
1384 }
1385 inline BOOL Pen::DeleteObject ()
1386 {
1387 if (m_hObject == nullptr)
1388 return FALSE;
1389 HPEN h = m_hObject;
1390 m_hObject = nullptr;
1391 return ::DeleteObject (h);
1392 }
1393#endif
1394}
1395
1396namespace Stroika::Frameworks::Led {
1397 /*
1398 ********************************************************************************
1399 ************************************* LineSpacing ******************************
1400 ********************************************************************************
1401 */
1402 constexpr LineSpacing::LineSpacing (Rule rule)
1403 : fRule{rule}
1404 {
1405 Require (rule == eSingleSpace or rule == eOnePointFiveSpace or rule == eDoubleSpace);
1406 }
1407 constexpr LineSpacing::LineSpacing (Rule rule, TWIPS twips)
1408 : fRule{rule}
1409 , fArg{static_cast<unsigned> (twips)}
1410 {
1411 Require (rule == eAtLeastTWIPSSpacing or rule == eExactTWIPSSpacing);
1412 }
1413 constexpr LineSpacing::LineSpacing (Rule rule, unsigned lineCount)
1414 : fRule{rule}
1415 , fArg{lineCount}
1416 {
1417 Require (rule == eExactLinesSpacing);
1418 switch (lineCount) {
1419 case 20:
1420 fRule = eSingleSpace;
1421 break;
1422 case 30:
1423 fRule = eOnePointFiveSpace;
1424 break;
1425 case 40:
1426 fRule = eDoubleSpace;
1427 break;
1428 }
1429 }
1430 constexpr bool LineSpacing::operator== (const LineSpacing& rhs) const
1431 {
1432 if (fRule != rhs.fRule) {
1433 return false;
1434 }
1435 if (fRule == LineSpacing::eAtLeastTWIPSSpacing or fRule == LineSpacing::eExactTWIPSSpacing or fRule == LineSpacing::eExactLinesSpacing) {
1436 if (fArg != rhs.fArg) {
1437 return false;
1438 }
1439 }
1440 return true;
1441 }
1442
1443 /*
1444 ********************************************************************************
1445 ********************** FontSpecification::FontNameSpecifier ********************
1446 ********************************************************************************
1447 */
1448#if qStroika_Platform_Windows
1449 inline FontSpecification::FontNameSpecifier::FontNameSpecifier ()
1450 {
1451 fName[0] = '\0';
1452 }
1453#endif
1454
1455 /*
1456 ********************************************************************************
1457 ****************************** FontSpecification *******************************
1458 ********************************************************************************
1459 */
1460 inline FontSpecification::FontSpecification (const IncrementalFontSpecification& from)
1461#if qStroika_Platform_Windows
1462 : fFontInfo (((const FontSpecification&)from).fFontInfo)
1463#else
1464 : fFontFamily (from.fFontFamily)
1465 , fBold (from.fBold)
1466 , fItalics (from.fItalics)
1467 , fUnderline (from.fUnderline)
1468 , fFontSize (from.fFontSize)
1469#endif
1470 , fSubOrSuperScript (((const FontSpecification&)from).fSubOrSuperScript)
1471 , fTextColor (((const FontSpecification&)from).fTextColor)
1472 {
1473 }
1474 /*
1475 @METHOD: FontSpecification::GetFontName
1476 @DESCRIPTION: <p>Retrieve the 'FontName' attribute of the given font specification. This name is a string, and corresponds to the font family name.</p>
1477 <p>See also @'FontSpecification::SetFontName'.</p>
1478 */
1479 inline SDKString FontSpecification::GetFontName () const
1480 {
1481#if qStroika_Platform_Windows
1482 return fFontInfo.lfFaceName;
1483#else
1484 return fFontFamily.AsSDKString ();
1485#endif
1486 }
1487 // FontName info
1488 inline FontSpecification::FontNameSpecifier FontSpecification::GetFontNameSpecifier () const
1489 {
1490#if qStroika_Platform_Windows
1491 return fFontInfo.lfFaceName;
1492#else
1493 return fFontFamily;
1494#endif
1495 }
1496 // Style info
1497 /*
1498 @METHOD: FontSpecification::GetStyle_Plain
1499 @DESCRIPTION: <p>Checks all the various font 'style' attributes, such as 'bold', or 'italic'. Returns true iff all
1500 of these styles are not set.</p>
1501 <p>See also @'FontSpecification::SetStyle_Plain'.</p>
1502 */
1503 inline bool FontSpecification::GetStyle_Plain () const
1504 {
1505 if (fSubOrSuperScript != eNoSubOrSuperscript) {
1506 return false;
1507 }
1508#if qStroika_Platform_Windows
1509 return (fFontInfo.lfItalic == false and fFontInfo.lfWeight <= FW_NORMAL and fFontInfo.lfUnderline == false and fFontInfo.lfStrikeOut == false);
1510#else
1511 return not fBold and not fItalics and not fUnderline;
1512#endif
1513 }
1514 /*
1515 @METHOD: FontSpecification::SetStyle_Plain
1516 @DESCRIPTION: <p>Clears all 'style' attributes, such as 'bold', or 'italic'.</p>
1517 <p>See also @'FontSpecification::GetStyle_Plain'.</p>
1518 */
1519 inline void FontSpecification::SetStyle_Plain ()
1520 {
1521 fSubOrSuperScript = eNoSubOrSuperscript;
1522#if qStroika_Platform_Windows
1523 fFontInfo.lfItalic = false;
1524 fFontInfo.lfWeight = FW_NORMAL;
1525 fFontInfo.lfUnderline = false;
1526 fFontInfo.lfStrikeOut = false;
1527#endif
1528 }
1529 inline bool FontSpecification::GetStyle_Bold () const
1530 {
1531#if qStroika_Platform_Windows
1532 return fFontInfo.lfWeight > FW_NORMAL;
1533#else
1534 return fBold;
1535#endif
1536 }
1537 inline void FontSpecification::SetStyle_Bold (bool isBold)
1538 {
1539#if qStroika_Platform_Windows
1540 fFontInfo.lfWeight = isBold ? FW_BOLD : FW_NORMAL;
1541#endif
1542 }
1543 inline bool FontSpecification::GetStyle_Italic () const
1544 {
1545#if qStroika_Platform_Windows
1546 return !!fFontInfo.lfItalic;
1547#else
1548 return fItalics;
1549#endif
1550 }
1551 inline void FontSpecification::SetStyle_Italic (bool isItalic)
1552 {
1553#if qStroika_Platform_Windows
1554 fFontInfo.lfItalic = isItalic;
1555#else
1556 fItalics = isItalic;
1557#endif
1558 }
1559 inline bool FontSpecification::GetStyle_Underline () const
1560 {
1561#if qStroika_Platform_Windows
1562 return !!fFontInfo.lfUnderline;
1563#else
1564 return fUnderline;
1565#endif
1566 }
1567 inline void FontSpecification::SetStyle_Underline (bool isUnderline)
1568 {
1569#if qStroika_Platform_Windows
1570 fFontInfo.lfUnderline = isUnderline;
1571#endif
1572 }
1573 inline FontSpecification::SubOrSuperScript FontSpecification::GetStyle_SubOrSuperScript () const
1574 {
1575 return fSubOrSuperScript;
1576 }
1577 inline void FontSpecification::SetStyle_SubOrSuperScript (SubOrSuperScript subOrSuperScript)
1578 {
1579 fSubOrSuperScript = subOrSuperScript;
1580 }
1581#if qStroika_Platform_Windows
1582 inline bool FontSpecification::GetStyle_Strikeout () const
1583 {
1584 return !!fFontInfo.lfStrikeOut;
1585 }
1586 inline void FontSpecification::SetStyle_Strikeout (bool isStrikeout)
1587 {
1588 fFontInfo.lfStrikeOut = isStrikeout;
1589 }
1590#endif
1591 // FontSize info
1592 inline FontSpecification::FontSize FontSpecification::GetPointSize () const
1593 {
1594#if qStroika_Platform_Windows
1595 if (fFontInfo.lfHeight >= 0) {
1596 // I probably should be doing some magic here with subtracing internal leading, or something like that from this value -
1597 // See GetStaticDefaultFont () and Win32 SDK docs for LOGFONT
1598 // LGP 960222
1599 WindowDC screenDC (nullptr);
1600 FontObject font;
1601 Verify (font.CreateFontIndirect (&fFontInfo));
1602 HFONT oldFont = screenDC.SelectObject (font);
1603 TEXTMETRIC tms;
1604 screenDC.GetTextMetrics (&tms);
1605 screenDC.SelectObject (oldFont);
1606 return (unsigned short)::MulDiv (tms.tmHeight, 72, Globals::Get ().GetMainScreenLogPixelsV ());
1607 }
1608 else {
1609 return static_cast<unsigned short> (::MulDiv (-fFontInfo.lfHeight, 72, Globals::Get ().GetMainScreenLogPixelsV ()));
1610 }
1611#else
1612 return fFontSize;
1613#endif
1614 }
1615 inline void FontSpecification::SetPointSize (FontSize pointSize)
1616 {
1617#if qStroika_Platform_Windows
1618 fFontInfo.lfHeight = ::MulDiv (-long (pointSize), Globals::Get ().GetMainScreenLogPixelsV (), 72);
1619#else
1620 fFontSize = pointSize;
1621#endif
1622 }
1623#if qStroika_Platform_Windows
1624 inline long FontSpecification::PeekAtTMHeight () const
1625 {
1626 return fFontInfo.lfHeight;
1627 }
1628 inline void FontSpecification::PokeAtTMHeight (long tmHeight)
1629 {
1630 fFontInfo.lfHeight = tmHeight;
1631 }
1632#endif
1633 inline Color FontSpecification::GetTextColor () const
1634 {
1635 return fTextColor;
1636 }
1637 inline void FontSpecification::SetTextColor (const Color& textColor)
1638 {
1639 fTextColor = textColor;
1640 }
1641#if qStroika_Platform_Windows
1642 inline LOGFONT FontSpecification::GetOSRep () const
1643 {
1644 return fFontInfo;
1645 }
1646 inline void FontSpecification::GetOSRep (LOGFONT* logFont) const
1647 {
1648 RequireNotNull (logFont);
1649 *logFont = fFontInfo;
1650 }
1651 inline void FontSpecification::SetOSRep (LOGFONT logFont)
1652 {
1653 fFontInfo = logFont;
1654 }
1655 inline void FontSpecification::LightSetOSRep (LOGFONT logFont)
1656 {
1657 fFontInfo = logFont;
1658 fFontInfo.lfWidth = 0;
1659 fFontInfo.lfEscapement = 0;
1660 fFontInfo.lfOrientation = 0;
1661 fFontInfo.lfCharSet = DEFAULT_CHARSET;
1662 fFontInfo.lfOutPrecision = 0;
1663 fFontInfo.lfClipPrecision = 0;
1664 fFontInfo.lfQuality = 0;
1665 fFontInfo.lfPitchAndFamily = 0;
1666 }
1667#endif
1668#if qStroika_Platform_Windows
1669 inline FontSpecification::FontSpecification (const LOGFONT& logFont)
1670 : fFontInfo ()
1671 , fSubOrSuperScript (eNoSubOrSuperscript)
1672 , fTextColor (Color::kBlack)
1673 {
1674 LightSetOSRep (logFont);
1675 }
1676#endif
1677 inline bool FontSpecification::operator== (const FontSpecification& rhs) const
1678 {
1679 const FontSpecification& lhs = *this;
1680 // FontName Info
1681 if (lhs.GetFontNameSpecifier () != rhs.GetFontNameSpecifier ()) {
1682 return false;
1683 }
1684
1685// Style Info
1686#if qStroika_Platform_Windows
1687 if (lhs.GetStyle_Bold () != rhs.GetStyle_Bold ()) {
1688 return false;
1689 }
1690 if (lhs.GetStyle_Italic () != rhs.GetStyle_Italic ()) {
1691 return false;
1692 }
1693 if (lhs.GetStyle_Underline () != rhs.GetStyle_Underline ()) {
1694 return false;
1695 }
1696 if (lhs.GetStyle_Strikeout () != rhs.GetStyle_Strikeout ()) {
1697 return false;
1698 }
1699#endif
1700 if (lhs.GetStyle_SubOrSuperScript () != rhs.GetStyle_SubOrSuperScript ()) {
1701 return false;
1702 }
1703
1704 // Color Info
1705 if (lhs.GetTextColor () != rhs.GetTextColor ()) {
1706 return false;
1707 }
1708
1709// Size Info
1710#if qStroika_Platform_Windows
1711 // Speed tweek to avoid divide and getdevicecaps crap...
1712 if (lhs.PeekAtTMHeight () == rhs.PeekAtTMHeight ()) {
1713 return true;
1714 }
1715 else if ((lhs.PeekAtTMHeight () > 0) == (rhs.PeekAtTMHeight () > 0)) {
1716 return false; // if same sign, we can just compare for equality, and since they
1717 // ABOVE didn't compare equal, they must be different point sizes
1718 // (or at least very close depending a little on resoution...)
1719 // If their signs DIFFER, we must fall through into the scaling crap (GetPointSize).
1720 }
1721#endif
1722 if (lhs.GetPointSize () != rhs.GetPointSize ()) {
1723 return false;
1724 }
1725
1726 return true;
1727 }
1728 inline void FontSpecification::MergeIn (const IncrementalFontSpecification& addInTheseAttributes)
1729 {
1730 // Font Name
1731 if (addInTheseAttributes.GetFontNameSpecifier_Valid ()) {
1732 SetFontNameSpecifier (addInTheseAttributes.GetFontNameSpecifier ());
1733 }
1734
1735 // Font Styles
1736 if (addInTheseAttributes.GetStyle_Bold_Valid ()) {
1737 SetStyle_Bold (addInTheseAttributes.GetStyle_Bold ());
1738 }
1739 if (addInTheseAttributes.GetStyle_Italic_Valid ()) {
1740 SetStyle_Italic (addInTheseAttributes.GetStyle_Italic ());
1741 }
1742 if (addInTheseAttributes.GetStyle_Underline_Valid ()) {
1743 SetStyle_Underline (addInTheseAttributes.GetStyle_Underline ());
1744 }
1745 if (addInTheseAttributes.GetStyle_SubOrSuperScript_Valid ()) {
1746 SetStyle_SubOrSuperScript (addInTheseAttributes.GetStyle_SubOrSuperScript ());
1747 }
1748#if qStroika_Platform_Windows
1749 if (addInTheseAttributes.GetStyle_Strikeout_Valid ()) {
1750 SetStyle_Strikeout (addInTheseAttributes.GetStyle_Strikeout ());
1751 }
1752#endif
1753
1754 // Font Size
1755 if (addInTheseAttributes.GetPointSize_Valid ()) {
1756#if qStroika_Platform_Windows
1757 // speed tweek - avoid costly conversion to 'points'. All we want todo is copy the tmHeight field!
1758 PokeAtTMHeight (addInTheseAttributes.PeekAtTMHeight ());
1759#else
1760 SetPointSize (addInTheseAttributes.GetPointSize ());
1761#endif
1762 }
1763 if (addInTheseAttributes.GetPointSizeIncrement_Valid ()) {
1764 short pointSize = GetPointSize ();
1765 pointSize += addInTheseAttributes.GetPointSizeIncrement ();
1766 if (pointSize <= 0) { // never let point size get any smaller...
1767 pointSize = 1;
1768 }
1769 SetPointSize (pointSize);
1770 }
1771
1772 // Text Color
1773 if (addInTheseAttributes.GetTextColor_Valid ()) {
1774 SetTextColor (addInTheseAttributes.GetTextColor ());
1775 }
1776
1777#if qStroika_Platform_Windows
1778 // could have done somewhat earlier, but if so, must be more careful about what else gets changed... (like textcolor not part of this guy)
1779 if (addInTheseAttributes.GetDidSetOSRepCallFlag ()) {
1780 LOGFONT lf;
1781 addInTheseAttributes.GetOSRep (&lf);
1782 SetOSRep (lf);
1783 }
1784#endif
1785 }
1786
1787 /*
1788 ********************************************************************************
1789 ************************** IncrementalFontSpecification ************************
1790 ********************************************************************************
1791 */
1792 inline IncrementalFontSpecification::IncrementalFontSpecification (const FontSpecification& fontSpec)
1793 : FontSpecification{fontSpec}
1794 , fFontSpecifierValid (true)
1795 , fStyleValid_Bold (true)
1796 , fStyleValid_Italic (true)
1797 , fStyleValid_Underline (true)
1798 , fStyleValid_SubOrSuperScript (true)
1799 ,
1800#if qStroika_Platform_Windows
1801 fStyleValid_Strikeout (true)
1802 , fDidSetOSRepCallFlag (true)
1803 ,
1804#endif
1805 fFontSizeValid (true)
1806 , fFontSizeIncrementValid (false)
1807 , fTextColorValid (true)
1808 {
1809 }
1810 inline FontSpecification::FontNameSpecifier IncrementalFontSpecification::GetFontNameSpecifier () const
1811 {
1812 Require (fFontSpecifierValid);
1813 return inherited::GetFontNameSpecifier ();
1814 }
1815 inline bool IncrementalFontSpecification::GetFontNameSpecifier_Valid () const
1816 {
1817 return (fFontSpecifierValid);
1818 }
1819 inline void IncrementalFontSpecification::InvalidateFontNameSpecifier ()
1820 {
1821 fFontSpecifierValid = false;
1822#if qStroika_Platform_Windows
1823 fDidSetOSRepCallFlag = false;
1824#endif
1825 }
1826 inline void IncrementalFontSpecification::SetFontNameSpecifier (FontNameSpecifier fontNameSpecifier)
1827 {
1828 fFontSpecifierValid = true;
1829#if qStroika_Platform_Windows
1830 fDidSetOSRepCallFlag = false;
1831#endif
1832 inherited::SetFontNameSpecifier (fontNameSpecifier);
1833 }
1834 inline void IncrementalFontSpecification::SetFontName (const SDKString& fontName)
1835 {
1836 fFontSpecifierValid = true;
1837#if qStroika_Platform_Windows
1838 fDidSetOSRepCallFlag = false;
1839#endif
1840 inherited::SetFontName (fontName);
1841 }
1842 inline bool IncrementalFontSpecification::GetStyle_Plain () const
1843 {
1844 Require (fStyleValid_Bold);
1845 Require (fStyleValid_Italic);
1846 Require (fStyleValid_Underline);
1847 Require (fStyleValid_SubOrSuperScript);
1848#if qStroika_Platform_Windows
1849 Require (fStyleValid_Strikeout);
1850#endif
1851 return inherited::GetStyle_Plain ();
1852 }
1853 inline bool IncrementalFontSpecification::GetStyle_Plain_Valid () const
1854 {
1855 bool isValid = fStyleValid_Bold and fStyleValid_Italic and fStyleValid_Underline and fStyleValid_SubOrSuperScript;
1856#if qStroika_Platform_Windows
1857 isValid = isValid and fStyleValid_Strikeout;
1858#endif
1859 return isValid;
1860 }
1861 inline void IncrementalFontSpecification::InvalidateStyles ()
1862 {
1863 fStyleValid_Bold = false;
1864 fStyleValid_Italic = false;
1865 fStyleValid_Underline = false;
1866 fStyleValid_SubOrSuperScript = false;
1867#if qStroika_Platform_Windows
1868 fStyleValid_Strikeout = false;
1869 fDidSetOSRepCallFlag = false;
1870#endif
1871 }
1872 inline void IncrementalFontSpecification::SetStyle_Plain ()
1873 {
1874 fStyleValid_Bold = true;
1875 fStyleValid_Italic = true;
1876 fStyleValid_Underline = true;
1877 fStyleValid_SubOrSuperScript = true;
1878#if qStroika_Platform_Windows
1879 fStyleValid_Strikeout = true;
1880 fDidSetOSRepCallFlag = false;
1881#endif
1882 inherited::SetStyle_Plain ();
1883 }
1884 inline bool IncrementalFontSpecification::GetStyle_Bold () const
1885 {
1886 Require (fStyleValid_Bold);
1887 return inherited::GetStyle_Bold ();
1888 }
1889 inline bool IncrementalFontSpecification::GetStyle_Bold_Valid () const
1890 {
1891 return (fStyleValid_Bold);
1892 }
1893 inline void IncrementalFontSpecification::InvalidateStyle_Bold ()
1894 {
1895 fStyleValid_Bold = false;
1896#if qStroika_Platform_Windows
1897 fDidSetOSRepCallFlag = false;
1898#endif
1899 }
1900 inline void IncrementalFontSpecification::SetStyle_Bold (bool isBold)
1901 {
1902 fStyleValid_Bold = true;
1903#if qStroika_Platform_Windows
1904 fDidSetOSRepCallFlag = false;
1905#endif
1906 inherited::SetStyle_Bold (isBold);
1907 }
1908 inline bool IncrementalFontSpecification::GetStyle_Italic () const
1909 {
1910 Require (fStyleValid_Italic);
1911 return inherited::GetStyle_Italic ();
1912 }
1913 inline bool IncrementalFontSpecification::GetStyle_Italic_Valid () const
1914 {
1915 return (fStyleValid_Italic);
1916 }
1917 inline void IncrementalFontSpecification::InvalidateStyle_Italic ()
1918 {
1919 fStyleValid_Italic = false;
1920#if qStroika_Platform_Windows
1921 fDidSetOSRepCallFlag = false;
1922#endif
1923 }
1924 inline void IncrementalFontSpecification::SetStyle_Italic (bool isItalic)
1925 {
1926 fStyleValid_Italic = true;
1927#if qStroika_Platform_Windows
1928 fDidSetOSRepCallFlag = false;
1929#endif
1930 inherited::SetStyle_Italic (isItalic);
1931 }
1932 inline bool IncrementalFontSpecification::GetStyle_Underline () const
1933 {
1934 Require (fStyleValid_Underline);
1935 return inherited::GetStyle_Underline ();
1936 }
1937 inline bool IncrementalFontSpecification::GetStyle_Underline_Valid () const
1938 {
1939 return (fStyleValid_Underline);
1940 }
1941 inline void IncrementalFontSpecification::InvalidateStyle_Underline ()
1942 {
1943 fStyleValid_Underline = false;
1944#if qStroika_Platform_Windows
1945 fDidSetOSRepCallFlag = false;
1946#endif
1947 }
1948 inline void IncrementalFontSpecification::SetStyle_Underline (bool isUnderline)
1949 {
1950 fStyleValid_Underline = true;
1951#if qStroika_Platform_Windows
1952 fDidSetOSRepCallFlag = false;
1953#endif
1954 inherited::SetStyle_Underline (isUnderline);
1955 }
1956 inline FontSpecification::SubOrSuperScript IncrementalFontSpecification::GetStyle_SubOrSuperScript () const
1957 {
1958 Require (fStyleValid_SubOrSuperScript);
1959 return inherited::GetStyle_SubOrSuperScript ();
1960 }
1961 inline bool IncrementalFontSpecification::GetStyle_SubOrSuperScript_Valid () const
1962 {
1963 return (fStyleValid_SubOrSuperScript);
1964 }
1965 inline void IncrementalFontSpecification::InvalidateStyle_SubOrSuperScript ()
1966 {
1967 fStyleValid_SubOrSuperScript = false;
1968#if qStroika_Platform_Windows
1969 fDidSetOSRepCallFlag = false;
1970#endif
1971 }
1972 inline void IncrementalFontSpecification::SetStyle_SubOrSuperScript (SubOrSuperScript subOrSuperScript)
1973 {
1974 fStyleValid_SubOrSuperScript = true;
1975#if qStroika_Platform_Windows
1976 fDidSetOSRepCallFlag = false;
1977#endif
1978 inherited::SetStyle_SubOrSuperScript (subOrSuperScript);
1979 }
1980#if qStroika_Platform_Windows
1981 inline bool IncrementalFontSpecification::GetStyle_Strikeout () const
1982 {
1983 Require (fStyleValid_Strikeout);
1984 return (inherited::GetStyle_Strikeout ());
1985 }
1986 inline bool IncrementalFontSpecification::GetStyle_Strikeout_Valid () const
1987 {
1988 return (fStyleValid_Strikeout);
1989 }
1990 inline void IncrementalFontSpecification::InvalidateStyle_Strikeout ()
1991 {
1992 fStyleValid_Strikeout = false;
1993#if qStroika_Platform_Windows
1994 fDidSetOSRepCallFlag = false;
1995#endif
1996 }
1997 inline void IncrementalFontSpecification::SetStyle_Strikeout (bool isStrikeout)
1998 {
1999 fStyleValid_Strikeout = true;
2000#if qStroika_Platform_Windows
2001 fDidSetOSRepCallFlag = false;
2002#endif
2003 inherited::SetStyle_Strikeout (isStrikeout);
2004 }
2005#endif
2006 // FontSize info
2007 inline unsigned short IncrementalFontSpecification::GetPointSize () const
2008 {
2009 Require (fFontSizeValid);
2010 Require (not fFontSizeIncrementValid);
2011 return inherited::GetPointSize ();
2012 }
2013 inline bool IncrementalFontSpecification::GetPointSize_Valid () const
2014 {
2015 return (fFontSizeValid);
2016 }
2017 inline void IncrementalFontSpecification::InvalidatePointSize ()
2018 {
2019 fFontSizeValid = false;
2020 fFontSizeIncrementValid = false;
2021#if qStroika_Platform_Windows
2022 fDidSetOSRepCallFlag = false;
2023#endif
2024 }
2025 inline void IncrementalFontSpecification::SetPointSize (FontSize pointSize)
2026 {
2027 fFontSizeValid = true;
2028#if qStroika_Platform_Windows
2029 fDidSetOSRepCallFlag = false;
2030#endif
2031 inherited::SetPointSize (pointSize);
2032 fFontSizeIncrementValid = false;
2033 }
2034#if qStroika_Platform_Windows
2035 inline void IncrementalFontSpecification::PokeAtTMHeight (long tmHeight)
2036 {
2037 fFontSizeValid = true;
2038 fDidSetOSRepCallFlag = false;
2039 fFontSizeIncrementValid = false;
2040 inherited::PokeAtTMHeight (tmHeight);
2041 }
2042#endif
2043 inline short IncrementalFontSpecification::GetPointSizeIncrement () const
2044 {
2045 Require (not fFontSizeValid);
2046 Require (fFontSizeIncrementValid);
2047 return (short)inherited::GetPointSize ();
2048 }
2049 inline bool IncrementalFontSpecification::GetPointSizeIncrement_Valid () const
2050 {
2051 return (fFontSizeIncrementValid);
2052 }
2053 inline void IncrementalFontSpecification::InvalidatePointSizeIncrement ()
2054 {
2055 fFontSizeValid = false;
2056 fFontSizeIncrementValid = false;
2057#if qStroika_Platform_Windows
2058 fDidSetOSRepCallFlag = false;
2059#endif
2060 }
2061 inline void IncrementalFontSpecification::SetPointSizeIncrement (short pointSizeIncrement)
2062 {
2063 fFontSizeValid = false;
2064#if qStroika_Platform_Windows
2065 fDidSetOSRepCallFlag = false;
2066#endif
2067 inherited::SetPointSize ((unsigned short)pointSizeIncrement);
2068 fFontSizeIncrementValid = true;
2069 }
2070 inline Color IncrementalFontSpecification::GetTextColor () const
2071 {
2072 Require (fTextColorValid);
2073 return inherited::GetTextColor ();
2074 }
2075 inline bool IncrementalFontSpecification::GetTextColor_Valid () const
2076 {
2077 return (fTextColorValid);
2078 }
2079 inline void IncrementalFontSpecification::InvalidateTextColor ()
2080 {
2081 fTextColorValid = false;
2082 }
2083 inline void IncrementalFontSpecification::SetTextColor (const Color& textColor)
2084 {
2085 fTextColorValid = true;
2086 inherited::SetTextColor (textColor);
2087 }
2088#if qStroika_Platform_Windows
2089 inline LOGFONT IncrementalFontSpecification::GetOSRep () const
2090 {
2091 Require (fFontSpecifierValid and fStyleValid_Bold and fStyleValid_Italic and fStyleValid_Underline and fFontSizeValid);
2092 Require (fStyleValid_Strikeout);
2093 return inherited::GetOSRep ();
2094 }
2095 inline void IncrementalFontSpecification::GetOSRep (LOGFONT* logFont) const
2096 {
2097 RequireNotNull (logFont);
2098 Require (fFontSpecifierValid and fStyleValid_Bold and fStyleValid_Italic and fStyleValid_Underline and fFontSizeValid);
2099 Require (fStyleValid_Strikeout);
2100 inherited::GetOSRep (logFont);
2101 }
2102 inline void IncrementalFontSpecification::SetOSRep (LOGFONT logFont)
2103 {
2104 fFontSpecifierValid = true;
2105 fStyleValid_Bold = true;
2106 fStyleValid_Italic = true;
2107 fStyleValid_Underline = true;
2108 fStyleValid_Strikeout = true;
2109 fFontSizeValid = true;
2110 fFontSizeIncrementValid = false;
2111 fDidSetOSRepCallFlag = true;
2112 inherited::SetOSRep (logFont);
2113 }
2114 inline void IncrementalFontSpecification::LightSetOSRep (LOGFONT logFont)
2115 {
2116 fFontSpecifierValid = true;
2117 fStyleValid_Bold = true;
2118 fStyleValid_Italic = true;
2119 fStyleValid_Underline = true;
2120 fStyleValid_Strikeout = true;
2121 fFontSizeValid = true;
2122 fFontSizeIncrementValid = false;
2123 fDidSetOSRepCallFlag = true;
2124 inherited::LightSetOSRep (logFont);
2125 }
2126 inline bool IncrementalFontSpecification::GetDidSetOSRepCallFlag () const
2127 {
2128 return fDidSetOSRepCallFlag;
2129 }
2130#endif
2131 inline void IncrementalFontSpecification::MergeIn (const IncrementalFontSpecification& addInTheseAttributes)
2132 {
2133 // Font Name
2134 if (addInTheseAttributes.GetFontNameSpecifier_Valid ()) {
2135 SetFontNameSpecifier (addInTheseAttributes.GetFontNameSpecifier ());
2136 }
2137
2138 // Font Styles
2139 if (addInTheseAttributes.GetStyle_Bold_Valid ()) {
2140 SetStyle_Bold (addInTheseAttributes.GetStyle_Bold ());
2141 }
2142 if (addInTheseAttributes.GetStyle_Italic_Valid ()) {
2143 SetStyle_Italic (addInTheseAttributes.GetStyle_Italic ());
2144 }
2145 if (addInTheseAttributes.GetStyle_Underline_Valid ()) {
2146 SetStyle_Underline (addInTheseAttributes.GetStyle_Underline ());
2147 }
2148#if qStroika_Platform_Windows
2149 if (addInTheseAttributes.GetStyle_Strikeout_Valid ()) {
2150 SetStyle_Strikeout (addInTheseAttributes.GetStyle_Strikeout ());
2151 }
2152#endif
2153
2154 // Font Size
2155 if (addInTheseAttributes.GetPointSize_Valid ()) {
2156#if qStroika_Platform_Windows
2157 // speed tweek - avoid costly conversion to 'points'. All we want todo is copy the tmHeight field!
2158 PokeAtTMHeight (addInTheseAttributes.PeekAtTMHeight ());
2159#else
2160 SetPointSize (addInTheseAttributes.GetPointSize ());
2161#endif
2162 }
2163 if (addInTheseAttributes.GetPointSizeIncrement_Valid ()) {
2164 short pointSize = GetPointSize ();
2165 pointSize += addInTheseAttributes.GetPointSizeIncrement ();
2166 if (pointSize <= 0) { // never let point size get any smaller...
2167 pointSize = 1;
2168 }
2169 SetPointSize (pointSize);
2170 }
2171
2172 // Text Color
2173 if (addInTheseAttributes.GetTextColor_Valid ()) {
2174 SetTextColor (addInTheseAttributes.GetTextColor ());
2175 }
2176
2177#if qStroika_Platform_Windows
2178 fDidSetOSRepCallFlag = addInTheseAttributes.GetDidSetOSRepCallFlag ();
2179#endif
2180 }
2181 inline bool IncrementalFontSpecification::operator== (const IncrementalFontSpecification& rhs) const
2182 {
2183 // Either make this non-portable, or somehow do some hack to make this test FASTER than it looks like
2184 // it may be currently - profile??? - LGP 960517
2185 //
2186 // FontName Info
2187 {
2188 if (GetFontNameSpecifier_Valid () != rhs.GetFontNameSpecifier_Valid ()) {
2189 return false;
2190 }
2191 if (GetFontNameSpecifier_Valid () and (GetFontNameSpecifier () != rhs.GetFontNameSpecifier ())) {
2192 return false;
2193 }
2194 }
2195
2196 // Style Info
2197 {
2198 if (GetStyle_Bold_Valid () != rhs.GetStyle_Bold_Valid ()) {
2199 return false;
2200 }
2201 if (GetStyle_Bold_Valid () and (GetStyle_Bold () != rhs.GetStyle_Bold ())) {
2202 return false;
2203 }
2204 }
2205 {
2206 if (GetStyle_Italic_Valid () != rhs.GetStyle_Italic_Valid ()) {
2207 return false;
2208 }
2209 if (GetStyle_Italic_Valid () and (GetStyle_Italic () != rhs.GetStyle_Italic ())) {
2210 return false;
2211 }
2212 }
2213 {
2214 if (GetStyle_Underline_Valid () != rhs.GetStyle_Underline_Valid ()) {
2215 return false;
2216 }
2217 if (GetStyle_Underline_Valid () and (GetStyle_Underline () != rhs.GetStyle_Underline ())) {
2218 return false;
2219 }
2220 }
2221 {
2222 if (GetStyle_SubOrSuperScript_Valid () != rhs.GetStyle_SubOrSuperScript_Valid ()) {
2223 return false;
2224 }
2225 if (GetStyle_SubOrSuperScript_Valid () and (GetStyle_SubOrSuperScript () != rhs.GetStyle_SubOrSuperScript ())) {
2226 return false;
2227 }
2228 }
2229#if qStroika_Platform_Windows
2230 {
2231 if (GetStyle_Strikeout_Valid () != rhs.GetStyle_Strikeout_Valid ()) {
2232 return false;
2233 }
2234 if (GetStyle_Strikeout_Valid () and (GetStyle_Strikeout () != rhs.GetStyle_Strikeout ())) {
2235 return false;
2236 }
2237 }
2238#endif
2239
2240 // Font Color Info
2241 {
2242 if (GetTextColor_Valid () != rhs.GetTextColor_Valid ()) {
2243 return false;
2244 }
2245 if (GetTextColor_Valid () and (GetTextColor () != rhs.GetTextColor ())) {
2246 return false;
2247 }
2248 }
2249
2250 // Size Info
2251 {
2252 if (GetPointSizeIncrement_Valid () != rhs.GetPointSizeIncrement_Valid ()) {
2253 return false;
2254 }
2255 if (GetPointSizeIncrement_Valid () and (GetPointSizeIncrement () != rhs.GetPointSizeIncrement ())) {
2256 return false;
2257 }
2258 }
2259 {
2260 if (GetPointSize_Valid () != rhs.GetPointSize_Valid ()) {
2261 return false;
2262 }
2263 if (GetPointSize_Valid ()) {
2264#if qStroika_Platform_Windows
2265 // Speed tweek to avoid divide and getdevicecaps crap...
2266 if (PeekAtTMHeight () == rhs.PeekAtTMHeight ()) {
2267 return true;
2268 }
2269 else if ((PeekAtTMHeight () > 0) == (rhs.PeekAtTMHeight () > 0)) {
2270 return false; // if same sign, we can just compare for equality, and since they
2271 // ABOVE didn't compare equal, they must be different point sizes
2272 // (or at least very close depending a little on resoution...)
2273 // If their signs DIFFER, we must fall through into the scaling crap (GetPointSize).
2274 }
2275#endif
2276 if (GetPointSize () != rhs.GetPointSize ()) {
2277 return false;
2278 }
2279 }
2280 }
2281
2282 return true;
2283 }
2284
2285 /*
2286 ********************************************************************************
2287 ********************************** InstalledFonts ******************************
2288 ********************************************************************************
2289 */
2290 inline const vector<SDKString>& InstalledFonts::GetUsableFontNames () const
2291 {
2292 return fFontNames;
2293 }
2294
2295#if qStroika_Frameworks_Led_SupportGDI
2296 /*
2297 ********************************************************************************
2298 ******************************** Led_GetTextColor ******************************
2299 ********************************************************************************
2300 */
2301 inline Color Led_GetTextColor ()
2302 {
2303#if qStroika_Platform_Windows
2304 return Color (::GetSysColor (COLOR_WINDOWTEXT));
2305#endif
2306 }
2307
2308 /*
2309 ********************************************************************************
2310 ************************** Led_GetTextBackgroundColor **************************
2311 ********************************************************************************
2312 */
2313 inline Color Led_GetTextBackgroundColor ()
2314 {
2315#if qStroika_Platform_Windows
2316 return Color (::GetSysColor (COLOR_WINDOW));
2317#endif
2318 }
2319#endif
2320
2321#if qStroika_Frameworks_Led_SupportGDI
2322 /*
2323 ********************************************************************************
2324 **************************** Led_GetSelectedTextColor **************************
2325 ********************************************************************************
2326 */
2327 inline Color Led_GetSelectedTextColor ()
2328 {
2329#if qStroika_Platform_Windows
2330 // return Color (::GetSysColor (COLOR_CAPTIONTEXT));
2331 return Color (::GetSysColor (COLOR_HIGHLIGHTTEXT));
2332#endif
2333 }
2334 inline Color Led_GetSelectedTextBackgroundColor ()
2335 {
2336#if qStroika_Platform_Windows
2337 //return Color (::GetSysColor (COLOR_ACTIVECAPTION));
2338 return Color (::GetSysColor (COLOR_HIGHLIGHT));
2339#endif
2340 }
2341#endif
2342
2343#if qStroika_Frameworks_Led_SupportGDI
2344 /*
2345 ********************************************************************************
2346 ************************ Tablet::ClipNarrowAndRestore **************************
2347 ********************************************************************************
2348 */
2349 inline Tablet::ClipNarrowAndRestore::ClipNarrowAndRestore (Tablet* tablet)
2350 : fTablet (tablet)
2351 , fHasOldClip (false)
2352 , fOldClip ()
2353 {
2354 RequireNotNull (tablet);
2355#if qStroika_Platform_Windows
2356 if (::GetDeviceCaps (fTablet->m_hDC, TECHNOLOGY) == DT_METAFILE) {
2357 return;
2358 }
2359#endif
2360 fHasOldClip = tablet->GetClip (&fOldClip);
2361 }
2362 inline Tablet::ClipNarrowAndRestore::ClipNarrowAndRestore (Tablet* tablet, const Led_Rect& clipFurtherTo)
2363 : fTablet (tablet)
2364 , fHasOldClip (false)
2365 , fOldClip ()
2366 {
2367 RequireNotNull (tablet);
2368 fHasOldClip = tablet->GetClip (&fOldClip);
2369#if qStroika_Platform_Windows
2370 /*
2371 * NB: We must use IntersectClipRect instead of the above SetClip () call because the CLIP on Win32 is in
2372 * device rather than logical coordinates.
2373 */
2374 if (::GetDeviceCaps (tablet->m_hDC, TECHNOLOGY) == DT_METAFILE) {
2375 return;
2376 }
2377 Verify (::IntersectClipRect (*tablet, clipFurtherTo.GetLeft (), clipFurtherTo.GetTop (), clipFurtherTo.GetRight (),
2378 clipFurtherTo.GetBottom ()) != ERROR);
2379#endif
2380 }
2381 inline Tablet::ClipNarrowAndRestore::ClipNarrowAndRestore (Tablet* tablet, [[maybe_unused]] const Region& clipFurtherTo)
2382 : fTablet (tablet)
2383 , fHasOldClip (false)
2384 , fOldClip ()
2385 {
2386 RequireNotNull (tablet);
2387 fHasOldClip = tablet->GetClip (&fOldClip);
2388#if qStroika_Platform_Windows
2389 Assert (false); // NYI - see SPR#????
2390#else
2391 Assert (false); // NYI
2392#endif
2393 }
2394 inline Tablet::ClipNarrowAndRestore::~ClipNarrowAndRestore ()
2395 {
2396 AssertNotNull (fTablet);
2397#if qStroika_Platform_Windows
2398 if (::GetDeviceCaps (fTablet->m_hDC, TECHNOLOGY) == DT_METAFILE) {
2399 return;
2400 }
2401#endif
2402 if (fHasOldClip) {
2403 fTablet->SetClip (fOldClip);
2404 }
2405 else {
2406 fTablet->SetClip ();
2407 }
2408 }
2409#endif
2410
2411#if qStroika_Platform_Windows
2412 /*
2413 ********************************************************************************
2414 ********************************** WindowDC ************************************
2415 ********************************************************************************
2416 */
2417 inline WindowDC::WindowDC (HWND hWnd)
2418 : fHWnd_{hWnd}
2419 {
2420 Require (fHWnd_ == nullptr or ::IsWindow (fHWnd_));
2421 if (!Attach (::GetWindowDC (fHWnd_))) {
2422 Foundation::Execution::Throw (bad_alloc{});
2423 }
2424 }
2425 inline WindowDC::~WindowDC ()
2426 {
2427 AssertNotNull (m_hDC);
2428 ::ReleaseDC (fHWnd_, Detach ());
2429 }
2430
2431#endif
2432
2433#if qStroika_Frameworks_Led_SupportGDI
2434 /*
2435 ********************************************************************************
2436 *********************************** GDI_Obj_Selector ***************************
2437 ********************************************************************************
2438 */
2439#if qStroika_Platform_Windows
2440 inline GDI_Obj_Selector::GDI_Obj_Selector (Tablet* tablet, HGDIOBJ objToSelect)
2441 : fTablet (tablet)
2442 , fRestoreObject (nullptr)
2443 , fRestoreAttribObject (nullptr)
2444 {
2445 AssertNotNull (tablet);
2446 AssertNotNull (objToSelect);
2447 // See CDC::SelectObject for the logic..., but we do better than thiers and restore
2448 // right object to right DC!!!! - LGP 950525
2449 if (tablet->m_hDC != tablet->m_hAttribDC) {
2450 fRestoreObject = ::SelectObject (tablet->m_hDC, objToSelect);
2451 }
2452 if (tablet->m_hAttribDC != nullptr) {
2453 fRestoreAttribObject = ::SelectObject (tablet->m_hAttribDC, objToSelect);
2454 }
2455 }
2456#endif
2457 inline GDI_Obj_Selector::~GDI_Obj_Selector ()
2458 {
2459#if qStroika_Platform_Windows
2460 //NB: These restore objects CAN be nullptr, if no font (or whatever) selected into DC before we do... (aside from error cases)
2461 if (fRestoreObject != nullptr) {
2462 Verify (::SelectObject (fTablet->m_hDC, fRestoreObject));
2463 }
2464 if (fRestoreAttribObject != nullptr) {
2465 Verify (::SelectObject (fTablet->m_hAttribDC, fRestoreAttribObject));
2466 }
2467#endif
2468 }
2469#endif
2470
2471 /*
2472 ********************************************************************************
2473 *************************** Led_GetMacPict* ************************************
2474 ********************************************************************************
2475 */
2476 inline short Led_GetMacPictTop (const Led_Picture* picture)
2477 {
2478 RequireNotNull (picture);
2479 return Led_ByteSwapFromMac (picture->picFrameTop);
2480 }
2481 inline short Led_GetMacPictLeft (const Led_Picture* picture)
2482 {
2483 RequireNotNull (picture);
2484 return Led_ByteSwapFromMac (picture->picFrameLeft);
2485 }
2486 inline short Led_GetMacPictBottom (const Led_Picture* picture)
2487 {
2488 RequireNotNull (picture);
2489 return Led_ByteSwapFromMac (picture->picFrameBottom);
2490 }
2491 inline short Led_GetMacPictRight (const Led_Picture* picture)
2492 {
2493 RequireNotNull (picture);
2494 return Led_ByteSwapFromMac (picture->picFrameRight);
2495 }
2496 inline short Led_GetMacPictWidth (const Led_Picture* picture)
2497 {
2498 return Led_GetMacPictRight (picture) - Led_GetMacPictLeft (picture);
2499 }
2500 inline short Led_GetMacPictHeight (const Led_Picture* picture)
2501 {
2502 return Led_GetMacPictBottom (picture) - Led_GetMacPictTop (picture);
2503 }
2504 inline Led_Size Led_GetMacPictSize (const Led_Picture* picture)
2505 {
2506 return Led_Size (Led_GetMacPictHeight (picture), Led_GetMacPictWidth (picture));
2507 }
2508
2509#if qStroika_Frameworks_Led_ProvideIMESupport
2510 /*
2511 ********************************************************************************
2512 *************************************** IME ************************************
2513 ********************************************************************************
2514 */
2515 DISABLE_COMPILER_MSC_WARNING_START (6011)
2516 inline IME& IME::Get ()
2517 {
2518 if (sThe == nullptr) {
2519 new IME ();
2520 }
2521 AssertNotNull (sThe);
2522 return *sThe;
2523 }
2524 DISABLE_COMPILER_MSC_WARNING_END (6011)
2525 inline void IME::Enable ()
2526 {
2527 if (fIMEEnableProc != nullptr) {
2528 fIMEEnableProc (nullptr, true);
2529 }
2530 }
2531 inline void IME::Disable ()
2532 {
2533 if (fIMEEnableProc != nullptr) {
2534 fIMEEnableProc (nullptr, false);
2535 }
2536 }
2537 inline bool IME::Available () const
2538 {
2539 return fWinNlsAvailable;
2540 }
2541 inline void IME::ForgetPosition ()
2542 {
2543 fLastX = -1;
2544 fLastY = -1;
2545 }
2546#endif
2547
2548}
#define AssertNotNull(p)
Definition Assertions.h:336
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:49
#define RequireNotNull(p)
Definition Assertions.h:350
#define Verify(c)
Definition Assertions.h:422
set< T > Intersection(const set< T > &s1, const set< T > &s2)
basic_string< SDKChar > SDKString
Definition SDKString.h:38
STL namespace.