//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1992, 1994 by Borland International, All Rights Reserved // // Implementation for GDI Brush object //---------------------------------------------------------------------------- #include #include DIAG_DECLARE_GROUP(OwlGDI); // General GDI diagnostic group // // internal brush cache to keep most common brushes around cached by color // class TBrushCache { public: struct TEntry { HBRUSH Handle; TColor Color; TEntry(HANDLE handle) {Handle = (HBRUSH)handle;} }; TBrushCache(TEntry* entries, int numEntries); HBRUSH Lookup(TColor color); private: TEntry* Entries; int NumEntries; }; TBrushCache::TBrushCache(TEntry* entries, int numEntries) { Entries = entries; NumEntries = numEntries; for (int i = 0; i < NumEntries; i++) { LOGBRUSH logBrush; if (GetObject(Entries[i].Handle, sizeof(LOGBRUSH), &logBrush)) Entries[i].Color = logBrush.lbColor; } } HBRUSH TBrushCache::Lookup(TColor color) { for (int i = 0; i < NumEntries; i++) if (color == Entries[i].Color) return Entries[i].Handle; return 0; } // // Static instance of a brush cache table & the cache itself // static TBrushCache::TEntry BrushCacheEntries[] = { {::GetStockObject(BLACK_BRUSH)}, {::GetStockObject(DKGRAY_BRUSH)}, {::GetStockObject(GRAY_BRUSH)}, {::GetStockObject(LTGRAY_BRUSH)}, {::GetStockObject(WHITE_BRUSH)} }; static TBrushCache BrushCache(BrushCacheEntries, COUNTOF(BrushCacheEntries)); // // Constructors // TBrush::TBrush(HBRUSH handle, TAutoDelete autoDelete) : TGdiObject(handle, autoDelete) { #if !defined(NO_GDI_ORPHAN_CONTROL) if (ShouldDelete) OBJ_REF_ADD(Handle, Brush); #endif } TBrush::TBrush(TColor color) { if ((Handle = BrushCache.Lookup(color)) != 0) { ShouldDelete = false; return; } Handle = ::CreateSolidBrush(color); WARNX(OwlGDI, !Handle, 0, "Cannot create solid TBrush " << hex << color); CheckValid(); OBJ_REF_ADD(Handle, Brush); } TBrush::TBrush(TColor color, int style) { Handle = ::CreateHatchBrush(style, color); WARNX(OwlGDI, !Handle, 0, "Cannot create hatch TBrush " << hex << color << " " << style); CheckValid(); OBJ_REF_ADD(Handle, Brush); } TBrush::TBrush(const TBitmap& pattern) { Handle = ::CreatePatternBrush(pattern); WARNX(OwlGDI, !Handle, 0, "Cannot create pattern TBrush from bitmap " << hex << (uint)(HBITMAP)pattern); CheckValid(); OBJ_REF_ADD(Handle, Brush); } TBrush::TBrush(const TDib& pattern) { // This calls is 16/32 independent (& avoids Win32s not-implemented problem) // #if (0) // Extra step using hbitmap required for some Win32 versions TBitmap bm(pattern); LOGBRUSH lb = { BS_PATTERN, 0, (int)HANDLE(bm) }; Handle = ::CreateBrushIndirect(&lb); #else Handle = ::CreateDIBPatternBrush(pattern, pattern.Usage()); #endif WARNX(OwlGDI, !Handle, 0, "Cannot create pattern TBrush from DIB " << hex << (uint)(HANDLE)pattern); CheckValid(); OBJ_REF_ADD(Handle, Brush); } TBrush::TBrush(const LOGBRUSH far* logBrush) { PRECONDITION(logBrush); Handle = ::CreateBrushIndirect((LPLOGBRUSH)logBrush); // API cast WARNX(OwlGDI, !Handle, 0, "Cannot create TBrush from logBrush @" << hex << uint32(LPVOID(logBrush))); CheckValid(); OBJ_REF_ADD(Handle, Brush); } TBrush::TBrush(const TBrush& src) { LOGBRUSH logBrush; src.GetObject(logBrush); Handle = ::CreateBrushIndirect(&logBrush); WARNX(OwlGDI, !Handle, 0, "Cannot create TBrush from TBrush @" << hex << uint32(LPVOID(&src))); CheckValid(); OBJ_REF_ADD(Handle, Brush); } //---------------------------------------------------------------------------- THatch8x8Brush::THatch8x8Brush(const uint8 hatch[], TColor fgColor, TColor bgColor) : TBrush(Create(hatch, fgColor, bgColor), AutoDelete) { } // // reconstructs the brush with a new pattern or colors // void THatch8x8Brush::Reconstruct(const uint8 hatch[], TColor fgColor, TColor bgColor) { if (Handle) { #if !defined(NO_GDI_ORPHAN_CONTROL) OBJ_REF_DEC(Handle, true); #else if (!::DeleteObject(Handle)) THROW( TXGdi(IDS_GDIDELETEFAIL, Handle) ); #endif } Handle = Create(hatch, fgColor, bgColor); OBJ_REF_ADD(Handle, Brush); } // // private static create member to create or re-create the handle // HBRUSH THatch8x8Brush::Create(const uint8 hatch[], TColor fgColor, TColor bgColor) { TDib dib(8, 8, 2, DIB_RGB_COLORS); unsigned char HUGE* bits = (unsigned char HUGE*)dib.GetBits(); memset(bits, 0, 8*sizeof(uint32)); for (int i = 0; i < 8; i++) bits[(7-i) * sizeof(uint32)] = hatch[i]; // Dib is upside down dib.SetColor(0, bgColor); dib.SetColor(1, fgColor); #if (0) // Extra step using hbitmap required for some Win32 versions TBitmap bm(dib); LOGBRUSH lb = { BS_PATTERN, DIB_RGB_COLORS, (int)HANDLE(bm) }; HBRUSH handle = ::CreateBrushIndirect(&lb); #else HBRUSH handle = ::CreateDIBPatternBrush(dib, DIB_RGB_COLORS); #endif CheckValid(handle); return handle; } // // Predefined 8x8 hatch patterns // const uint8 THatch8x8Brush::Hatch22F1[8] = { 0x99, 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC }; const uint8 THatch8x8Brush::Hatch13F1[8] = { 0x88, 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44 }; const uint8 THatch8x8Brush::Hatch11F1[8] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; const uint8 THatch8x8Brush::Hatch22B1[8] = { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 }; const uint8 THatch8x8Brush::Hatch13B1[8] = { 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11, 0x88 };