1 /*
2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #ifndef AWT_GDIOBJECT_H
27 #define AWT_GDIOBJECT_H
28 
29 #include "awt.h"
30 #include "Hashtable.h"
31 #include "GDIHashtable.h"
32 
33 #define MEMORY_OVER_SPEED 1
34 
35 typedef struct {
36     HDC hDC;
37     BOOL gdiLimitReached;
38 } GetDCReturnStruct;
39 
40 /*
41  * An AwtGDIObject is a cached, color-based GDI object, such as a pen or
42  * brush.  This class also includes static methods for tracking the
43  * total number of active GDI Objects (Pen, Brush, and HDC).
44  */
45 class AwtGDIObject {
46 public:
GetColor()47     INLINE COLORREF GetColor() { return m_color; }
SetColor(COLORREF color)48     INLINE void SetColor(COLORREF color) { m_color = color; }
49 
GetHandle()50     INLINE HGDIOBJ GetHandle() { return m_handle; }
SetHandle(HGDIOBJ handle)51     INLINE void SetHandle(HGDIOBJ handle) { m_handle = handle; }
52 
53     /*
54      * NOTE: we don't syncronize access to the reference counter.
55      * Currently it is changed only when we are already synchronized
56      * on the global BatchDestructionManager lock.
57      */
GetRefCount()58     INLINE int GetRefCount() { return m_refCount; }
IncrRefCount()59     INLINE int IncrRefCount() { return ++m_refCount; }
DecrRefCount()60     INLINE int DecrRefCount() { return --m_refCount; }
61 
62     /*
63      * Decrement the reference count of a cached GDI object.  When it hits
64      * zero, notify the cache that the object can be safely removed.
65      * The cache will eventually delete the GDI object and this wrapper.
66      */
Release()67     INLINE void Release() {
68 #if MEMORY_OVER_SPEED
69         ReleaseInCache();
70 #endif
71     }
72 
73     // Workaround for Windows bug: do not let process have more than
74     // a set number of active (unreleased) GDI objects at any given time.
75     static BOOL IncrementIfAvailable();
76     static void Decrement();
77     static BOOL EnsureGDIObjectAvailability();
78 
79 protected:
80     /*
81      * Get a GDI object from its respective cache.  If it doesn't exist
82      * it gets created, otherwise its reference count gets bumped.
83      */
84     static AwtGDIObject* Get(COLORREF color);
85 
86     virtual void ReleaseInCache() = 0;
87 
AwtGDIObject()88     INLINE AwtGDIObject() {
89         m_handle = NULL;
90         m_refCount = 0;
91     }
92 
~AwtGDIObject()93     virtual ~AwtGDIObject() {
94         if (m_handle != NULL) {
95             ::DeleteObject(m_handle);
96             Decrement();
97         }
98     }
99 
100 private:
101     static int GetMaxGDILimit();
102 
103     COLORREF m_color;
104     HGDIOBJ  m_handle;
105     int      m_refCount;
106     static CriticalSection* objectCounterLock;
107     static int numCurrentObjects;
108     static int maxGDIObjects;
109 };
110 
111 #endif // AWT_GDIOBJECT_H
112