OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
brush.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1992, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation for TBrush GDI Brush object. Includes cache for solid brushes
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/gdiobjec.h>
10
11#if defined(BI_MULTI_THREAD_RTL)
12#include <owl/thread.h>
13#endif
14
15#if defined(__BORLANDC__)
16# pragma option -w-ccc // Disable "Condition is always true/false"
17#endif
18
19using namespace std;
20
21namespace owl {
22
24DIAG_DECLARE_GROUP(OwlGDI); // General GDI diagnostic group
25
26#define CACHE_SIZE 16
27
28/// \addtogroup internal
29/// @{
30
31
32
33//////////////////////////////////////////////////////////////////////////////////////////////////
34// multithread support
35//
36/// Internal MRU brush cache to keep most recent solid brushes around cached by
37/// color
38//
39class TBrushCache
41 : public TLocalObject
42#endif
43{
44public:
45 struct TEntry {
46 HANDLE Handle;
47 COLORREF Color;
48 int RefCnt;
49 };
50
51 TBrushCache();
52 ~TBrushCache();
53
54 HANDLE Lookup(COLORREF color);
55 bool CheckHandle(HANDLE handle);
56 void Float(int i);
57 bool AddRef(HANDLE handle, COLORREF color);
58 void DecRef(HANDLE handle);
59
60#if defined(BI_MULTI_THREAD_RTL)
61 TMRSWSection Lock;
62#endif
63
64private:
65 TEntry Entries[CACHE_SIZE];
66 int Size;
67};
68
69static
70TBrushCache& GetBrushCache();
71
72/// @}
73
74
75//
76// Static instance of the brush cache used by TBrush
77//
78static
79TBrushCache& GetBrushCache()
80{
81 //#if defined(BI_MULTI_THREAD_RTL)
82 // static TProcessContainer<TBrushCache> __BrushCache;
83 //#else
84 static TBrushCache __BrushCache;
85 //#endif
86 return __BrushCache;
87};
88
89#if defined(BI_MULTI_THREAD_RTL)
90#define LOCKCACHE(l,s) TMRSWSection::TLock __lock(l,s)
91#else
92#define LOCKCACHE(l,s)
93#endif
94
95//
96//
97//
98TBrushCache::TBrushCache()
99:
100Size(CACHE_SIZE)
101{
102 memset(Entries,0,sizeof(Entries));
103}
104
105
106//
107//
108//
109TBrushCache::~TBrushCache()
110{
111 for (int i = 0; i < Size; i++){
112 if (Entries[i].Handle) {
113 TGdiObject::RefDec(Entries[i].Handle, false);
114
115 LOCKCACHE(Lock,false);
116 Entries[i].Handle = nullptr;
117 Entries[i].Color = 0;
118 Entries[i].RefCnt = 0;
119 }
120 }
121}
122
123//
124// Move an entry to the front, shifting in between ones down
125//
126void
127TBrushCache::Float(int i)
128{
129 if(i > 0){
130 HANDLE handle = Entries[i].Handle;
131 COLORREF color = Entries[i].Color;
132 int refCnt = Entries[i].RefCnt;
133
134 TRACEX(OwlGDI, 2, _T("TBrushCache::Float(") << i << _T(") (") <<
135 static_cast<void*>(handle) << _T(", ") << hex << color << _T(")"));
136 {
137 LOCKCACHE(Lock,false);
138 memmove(Entries+1, Entries, sizeof(TEntry)*i);
139 Entries[0].Handle = handle;
140 Entries[0].Color = color;
141 Entries[0].RefCnt = refCnt;
142 }
143 }
144}
145
146//
147// Add a new entry to the front, pushing the last old one off the end.
148//
149bool
150TBrushCache::AddRef(HANDLE handle, COLORREF color)
151{
152
153 TRACEX(OwlGDI, 2, _T("TBrushCache::Add(") << static_cast<void*>(handle) <<
154 _T(", ") << hex << color << _T(")"));
155 CHECK(Size > 1);
156
157 bool retval = true;
158 if (Entries[Size-1].Handle){
159 int i = Size-1;
160 for(; i >= 0; i--){
161 // if RefCnt == 0 no one use this
162 if(!Entries[i].RefCnt){
163 TGdiObject::RefDec(Entries[i].Handle, true);
164 LOCKCACHE(Lock,false);
165 Entries[i].Handle = handle;
166 Entries[i].Color = color;
167 Entries[i].RefCnt = 1;
168 Float(i);// move up
169 break;
170 }
171 }
172 if(i < 0) // free node not found
173 retval = false;
174 }
175 else{
176 LOCKCACHE(Lock,false);
177 memmove(Entries+1, Entries, sizeof(TEntry)*(Size-1));
178 Entries[0].Handle = handle;
179 Entries[0].Color = color;
180 Entries[0].RefCnt = 1;
181 }
182
183 TGdiObject::RefAdd(handle, TGdiObject::Brush);
184
185 return retval;
186}
187
188//
189//
190//
191void
192TBrushCache::DecRef(HANDLE handle)
193{
194 for (int i = 0; i < Size && Entries[i].Handle; i++){
195 if (handle == Entries[i].Handle) {
196 TRACEX(OwlGDI, 2, _T("TBrushCache::DecRef(") << hex << handle <<
197 _T("): found ") << _T(" @") << i);
198 Entries[i].RefCnt--;
199 CHECK(Entries[i].RefCnt >= 0);
200 break;
201 }
202 }
203}
204
205//
206//
207//
208bool
209TBrushCache::CheckHandle(HANDLE handle)
210{
211 for (int i = 0; i < Size && Entries[i].Handle; i++){
212 if (handle == Entries[i].Handle) {
213 TRACEX(OwlGDI, 2, _T("TBrushCache::CheckHandle(") <<
214 static_cast<void*>(Entries[i].Handle) << _T(" @") << i);
215 Entries[i].RefCnt++;
216 return true;
217 }
218 }
219 TRACEX(OwlGDI, 2, _T("TBrushCache::CheckHandle(") << static_cast<void*>(handle) << _T("): not found"));
220 return 0;
221}
222
223//
224// Lookup a color in the cache, returning the handle if found
225//
226HANDLE
227TBrushCache::Lookup(COLORREF color)
228{
229 for (int i = 0; i < Size && Entries[i].Handle; i++){
230 if (color == Entries[i].Color) {
231 TRACEX(OwlGDI, 2, _T("TBrushCache::Lookup(") << hex << color <<
232 _T("): found ") << static_cast<void*>(Entries[i].Handle) << _T(" @") << i);
233 Entries[i].RefCnt++;
234 Float(i);
235 return Entries[0].Handle; // After Float() our entry is at 0!
236 }
237 }
238 TRACEX(OwlGDI, 2, _T("TBrushCache::Lookup(") << hex << color << _T("): not found"));
239 return nullptr;
240}
241
242//
243// Constructors
244//
245
246//
247/// Alias an existing brush handle. Assume ownership if autoDelete says so
248//
249/// Creates a TBrush object and sets the Handle data member to the given borrowed
250/// handle. The ShouldDelete data member defaults to false, ensuring that the
251/// borrowed handle will not be deleted when the C++ object is destroyed.
252//
254:
256{
257 if (ShouldDelete)
259 else
260 GetBrushCache().CheckHandle(Handle);
261 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
262 _T(" with handle ") << static_cast<void*>(handle));
263}
264
265//--------------------------------------------------------------------------
266
267//
268/// Creates a solid TBrush object with the given color. To save a brush creation
269/// this constructor uses a cache that can detect any color that matches a stock
270/// color when useCache is true.
271//
273{
275
276 COLORREF cr = color;
277 if(useCache && (Handle = GetBrushCache().Lookup(cr)) != nullptr)
278 return;
279
280 //Use new win4.0 function if available? Probably very fast.
281 if (color.IsSysColor())
282 {
284 }
285 else
286 {
288 }
289 WARNX(OwlGDI, !Handle, 0, _T("Cannot create solid TBrush ") << hex << color);
290 CheckValid();
291
292 if (!color.IsSysColor())
293 {
294 if (useCache)
295 {
296 if(!GetBrushCache().AddRef(Handle, color))
297 {
298 TRACEX(OwlGDI, OWL_CDLEVEL, _T("Cannot add new TBrush to cache ") << hex << color);
299 ShouldDelete = true;
300 }
301 }
302 else
303 {
305 }
306 }
307 else
308 {
309 ShouldDelete = false;
310 }
311
312
313 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
314 _T(" with color ") << static_cast<COLORREF>(color));
315}
316
317
318//
319/// Creates a hatched TBrush object with the given style and color.
320//
321TBrush::TBrush(const TColor& color, int style)
322{
324 WARNX(OwlGDI, !Handle, 0, _T("Cannot create hatch TBrush ") << hex << color <<
325 _T(" ") << style);
326 CheckValid();
328 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
329 _T(" with color ") << static_cast<COLORREF>(color) <<
330 _T(", style 0x") << style);
331}
332
333
334//
335/// Creates a patterned TBrush object with the given pattern.
336//
338{
340 WARNX(OwlGDI, !Handle, 0, _T("Cannot create pattern TBrush from bitmap ") <<
341 static_cast<void*>(pattern.GetHandle()));
342 CheckValid();
344 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
345 _T(" from bitmap ") << static_cast<const void*>(pattern.GetHandle()));
346}
347
348
349//
350/// Creates a TBrush object with values from the given LOGBRUSH.
351//
353{
355 WARNX(OwlGDI, !Handle, 0, _T("Cannot create TBrush from logBrush @") << static_cast<const void*>(&logBrush));
356 CheckValid();
358 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << static_cast<void*>(this)
359 << _T(" from logBrush @") << static_cast<const void*>(&logBrush));
360}
361
362#if defined(OWL5_COMPAT)
363
364//
365/// Creates a TBrush object with values from the given LOGBRUSH.
366/// This overload is deprecated. Use the overload that takes a reference instead.
367//
369{
372 WARNX(OwlGDI, !Handle, 0, _T("Cannot create TBrush from logBrush @") << static_cast<const void*>(logBrush));
373 CheckValid();
375 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
376 _T(" from logBrush @") << static_cast<const void*>(logBrush));
377}
378
379#endif
380
381
382//
383/// Constructs a copy of an existing brush. Contructed brush will share the handle
384/// unless NO_GDI_SHARE_HANDLES is defined, in which case a new handle is created.
385//
387{
388#if !defined(NO_GDI_SHARE_HANDLES)
389 Handle = src.Handle;
391#else
393 src.GetObject(logBrush);
395 WARNX(OwlGDI, !Handle, 0, _T("Cannot create TBrush from TBrush @") <<
396 hex << uint32(LPVOID(&src)));
397 CheckValid();
399#endif
400 TRACEX(OwlGDI, OWL_CDLEVEL, _T("Copy constructed TBrush @") << (void*)this <<
401 _T(" from TBrush @") << (void*)&src);
402}
403
404
405//
406// Destroy the C++ object.
407//
409{
410 if(!ShouldDelete)
411 GetBrushCache().DecRef(Handle);
412 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush destructed @") << (void*)this);
413}
414
415//
416/// Creates a patterned TBrush object with the given DIB pattern.
417//
419{
421 WARNX(OwlGDI, !Handle, 0, _T("Cannot create pattern TBrush from DIB ") <<
422 static_cast<void*>(pattern.GetHandle()));
423 CheckValid();
425 TRACEX(OwlGDI, OWL_CDLEVEL, _T("TBrush constructed @") << (void*)this <<
426 _T(" from DIB ") << static_cast<void*>(pattern.GetHandle()));
427}
428
429//
430/// Retrieves information about this brush object and places it in the given
431/// LOGBRUSH structure. Returns true if the call is successful; otherwise returns false.
432//
434{
436 bool r = TGdiObject::GetObject(sizeof(logBrush), &logBrush) != 0;
437 if (!r) throw TXGdi(IDS_GDIFAILURE, GetHandle());
438 return logBrush;
439}
440
441
442//
443/// Constructs a THatchBrush object with the specified hatched pattern and colors.
444/// Although the hatched brush is, by default, white on a black background, you can
445/// control the displayed colors by passing different colors in the constructor,
446/// where fgColor represents the foreground color and bgColor represents the
447/// background color of a TColor object type.
448///
449/// Note that colors can be specified in either palette mode (a reference to a
450/// corresponding color palette entry in the currently realized palette) or RGB mode
451/// (an actual red, green, or blue color value).
452//
458
459//
460/// Reconstructs the hatched brush with a new pattern or new set of colors.
461//
462void
464{
465 if (Handle)
466 RefDec(Handle, true);
467
468 Handle = Create(hatch, fgColor, bgColor);
470}
471
472//
473/// Private static create member to create or re-create the handle
474//
475HBRUSH
476THatch8x8Brush::Create(const uint8 hatch[], const TColor& fgColor, const TColor& bgColor)
477{
478 TDib dib(8, 8, 2, DIB_RGB_COLORS);
479 uint8 * bits = (uint8 *)dib.GetBits();
480 memset(bits, 0, 8*sizeof(uint32));
481 for (int i = 0; i < 8; i++)
482 bits[(7-i) * sizeof(uint32)] = hatch[i]; // Dib is upside down
483 dib.SetColor(0, bgColor);
484 dib.SetColor(1, fgColor);
485
486#if 0 // Extra step using hbitmap required for some old Win32 versions
487 TBitmap bm(dib);
490#else
492#endif
493
495 return handle;
496}
497
498
499//
500// Predefined 8x8 hatch patterns
501//
503 0x99, 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC
504};
505//--------------------------------------------------------------------------
507 0x88, 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44
508};
509//--------------------------------------------------------------------------
511 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55
512};
513//--------------------------------------------------------------------------
515 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99
516};
517//--------------------------------------------------------------------------
519 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11, 0x88
520};
521
522
523} // OWL namespace
524
#define CACHE_SIZE
Definition brush.cpp:26
#define LOCKCACHE(l, s)
Definition brush.cpp:92
#define CHECK(condition)
Definition checks.h:239
#define WARNX(group, condition, level, message)
Definition checks.h:277
#define PRECONDITION(condition)
Definition checks.h:227
#define DIAG_DECLARE_GROUP(group)
Definition checks.h:404
#define TRACEX(group, level, message)
Definition checks.h:263
TBitmap is the GDI bitmap class derived from TGdiObject.
Definition gdiobjec.h:510
The GDI Brush class is derived from TGdiObject.
Definition gdiobjec.h:180
LOGBRUSH GetObject() const
Retrieves information about this brush object and places it in the given LOGBRUSH structure.
Definition brush.cpp:433
HBRUSH GetHandle() const
Returns the handle of the brush with type HBRUSH.
Definition gdiobjec.h:1110
TBrush(HBRUSH handle, TAutoDelete autoDelete=NoAutoDelete)
TBrush encapsulates an HBRUSH.
Definition brush.cpp:253
Class wrapper for management of color values.
Definition color.h:245
Pseudo-GDI object Device Independent Bitmap (DIB) class.
Definition gdiobjec.h:795
GdiObject is the root, pseudo-abstract base class for ObjectWindows' GDI (Graphics Device Interface) ...
Definition gdiobjec.h:68
static void RefDec(HANDLE handle, bool wantDelete)
Decrements this object's reference count by 1 and deletes the object when the reference count reaches...
Definition gdiobjec.cpp:200
void CheckValid(uint resId=IDS_GDIFAILURE)
Definition gdibase.cpp:49
static void _CheckValid(HANDLE handle, uint resId=IDS_GDIFAILURE)
Definition gdibase.cpp:58
int GetObject(int count, void *object) const
Retrieve the object's attributes into a buffer.
Definition gdiobjec.h:1051
bool ShouldDelete
Should object delete GDI handle in dtor?
Definition gdibase.h:82
static void RefAdd(HANDLE handle, TType type)
RefAdd adds a reference entry for the object with the given handle and type.
Definition gdiobjec.cpp:137
HANDLE Handle
GDI handle of this object.
Definition gdibase.h:81
static const uint8 Hatch11F1[8]
The static array Hatch11F1[8] holds the logical hatched brush pattern of one pixel on and one pixel o...
Definition gdiobjec.h:272
static const uint8 Hatch13F1[8]
The static array Hatch13F1[8] holds a hatched brush pattern of one pixel on and three pixels off in f...
Definition gdiobjec.h:266
void Reconstruct(const uint8 hatch[], const TColor &fgColor, const TColor &bgColor)
Reconstructs the hatched brush with a new pattern or new set of colors.
Definition brush.cpp:463
static const uint8 Hatch22F1[8]
The static array Hatch22F1[8] holds a monochrome hatched brush pattern of two pixels on and two off i...
Definition gdiobjec.h:260
static const uint8 Hatch13B1[8]
The static array Hatch13B1[8] holds a hatched brush pattern of one pixel on and three pixels off in b...
Definition gdiobjec.h:284
THatch8x8Brush(const uint8 hatch[], const TColor &fgColor=TColor::White, const TColor &bgColor=TColor::Black)
Constructs a THatchBrush object with the specified hatched pattern and colors.
Definition brush.cpp:453
static const uint8 Hatch22B1[8]
The static array Hatch22B1[8] holds a hatched brush pattern of two pixels on and two off in backward ...
Definition gdiobjec.h:278
Describes an exception resulting from GDI failures such as creating too many TWindow device contexts ...
Definition gdibase.h:52
#define _T(x)
Definition cygwin.h:51
Definition of abstract GDI object class and derived classes.
TAutoDelete
Flag for Handle ctors to control Handle deletion in dtor.
Definition gdibase.h:70
@ AutoDelete
Definition gdibase.h:70
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
unsigned char uint8
Definition number.h:32
unsigned long uint32
Definition number.h:34
OWL_DIAGINFO
Definition animctrl.cpp:14
#define OWL_CDLEVEL
Definition defs.h:171