History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/awt/RepaintArea.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/awt/RepaintArea.java+312−0
@@ -0,0 +1,312 @@
1+/*
2+ * Copyright (c) 1999, 2007, 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+package sun.awt;
27+
28+import java.awt.Component;
29+import java.awt.Graphics;
30+import java.awt.Rectangle;
31+import java.awt.event.PaintEvent;
32+
33+/**
34+ * The <code>RepaintArea</code> is a geometric construct created for the
35+ * purpose of holding the geometry of several coalesced paint events.
36+ * This geometry is accessed synchronously, although it is written such
37+ * that painting may still be executed asynchronously.
38+ *
39+ * @author Eric Hawkes
40+ * @since 1.3
41+ */
42+public class RepaintArea {
43+
44+ /**
45+ * Maximum ratio of bounding rectangle to benefit for which
46+ * both the vertical and horizontal unions are repainted.
47+ * For smaller ratios the whole bounding rectangle is repainted.
48+ * @see #paint
49+ */
50+ private static final int MAX_BENEFIT_RATIO = 4;
51+
52+ private static final int HORIZONTAL = 0;
53+ private static final int VERTICAL = 1;
54+ private static final int UPDATE = 2;
55+
56+ private static final int RECT_COUNT = UPDATE + 1;
57+
58+ private Rectangle paintRects[] = new Rectangle[RECT_COUNT];
59+
60+
61+ /**
62+ * Constructs a new <code>RepaintArea</code>
63+ * @since 1.3
64+ */
65+ public RepaintArea() {
66+ }
67+
68+ /**
69+ * Constructs a new <code>RepaintArea</code> initialized to match
70+ * the values of the specified RepaintArea.
71+ *
72+ * @param ra the <code>RepaintArea</code> from which to copy initial
73+ * values to a newly constructed RepaintArea
74+ * @since 1.3
75+ */
76+ private RepaintArea(RepaintArea ra) {
77+ // This constructor is private because it should only be called
78+ // from the cloneAndReset method
79+ for (int i = 0; i < RECT_COUNT; i++) {
80+ paintRects[i] = ra.paintRects[i];
81+ }
82+ }
83+
84+ /**
85+ * Adds a <code>Rectangle</code> to this <code>RepaintArea</code>.
86+ * PAINT Rectangles are divided into mostly vertical and mostly horizontal.
87+ * Each group is unioned together.
88+ * UPDATE Rectangles are unioned.
89+ *
90+ * @param r the specified <code>Rectangle</code>
91+ * @param id possible values PaintEvent.UPDATE or PaintEvent.PAINT
92+ * @since 1.3
93+ */
94+ public synchronized void add(Rectangle r, int id) {
95+ // Make sure this new rectangle has positive dimensions
96+ if (r.isEmpty()) {
97+ return;
98+ }
99+ int addTo = UPDATE;
100+ if (id == PaintEvent.PAINT) {
101+ addTo = (r.width > r.height) ? HORIZONTAL : VERTICAL;
102+ }
103+ if (paintRects[addTo] != null) {
104+ paintRects[addTo].add(r);
105+ } else {
106+ paintRects[addTo] = new Rectangle(r);
107+ }
108+ }
109+
110+
111+ /**
112+ * Creates a new <code>RepaintArea</code> with the same geometry as this
113+ * RepaintArea, then removes all of the geometry from this
114+ * RepaintArea and restores it to an empty RepaintArea.
115+ *
116+ * @return ra a new <code>RepaintArea</code> having the same geometry as
117+ * this RepaintArea.
118+ * @since 1.3
119+ */
120+ private synchronized RepaintArea cloneAndReset() {
121+ RepaintArea ra = new RepaintArea(this);
122+ for (int i = 0; i < RECT_COUNT; i++) {
123+ paintRects[i] = null;
124+ }
125+ return ra;
126+ }
127+
128+ public boolean isEmpty() {
129+ for (int i = 0; i < RECT_COUNT; i++) {
130+ if (paintRects[i] != null) {
131+ return false;
132+ }
133+ }
134+ return true;
135+ }
136+
137+ /**
138+ * Constrains the size of the repaint area to the passed in bounds.
139+ */
140+ public synchronized void constrain(int x, int y, int w, int h) {
141+ for (int i = 0; i < RECT_COUNT; i++) {
142+ Rectangle rect = paintRects[i];
143+ if (rect != null) {
144+ if (rect.x < x) {
145+ rect.width -= (x - rect.x);
146+ rect.x = x;
147+ }
148+ if (rect.y < y) {
149+ rect.height -= (y - rect.y);
150+ rect.y = y;
151+ }
152+ int xDelta = rect.x + rect.width - x - w;
153+ if (xDelta > 0) {
154+ rect.width -= xDelta;
155+ }
156+ int yDelta = rect.y + rect.height - y - h;
157+ if (yDelta > 0) {
158+ rect.height -= yDelta;
159+ }
160+ if (rect.width <= 0 || rect.height <= 0) {
161+ paintRects[i] = null;
162+ }
163+ }
164+ }
165+ }
166+
167+ /**
168+ * Marks the passed in region as not needing to be painted. It's possible
169+ * this will do nothing.
170+ */
171+ public synchronized void subtract(int x, int y, int w, int h) {
172+ Rectangle subtract = new Rectangle(x, y, w, h);
173+ for (int i = 0; i < RECT_COUNT; i++) {
174+ if (subtract(paintRects[i], subtract)) {
175+ if (paintRects[i] != null && paintRects[i].isEmpty()) {
176+ paintRects[i] = null;
177+ }
178+ }
179+ }
180+ }
181+
182+ /**
183+ * Invokes paint and update on target Component with optimal
184+ * rectangular clip region.
185+ * If PAINT bounding rectangle is less than
186+ * MAX_BENEFIT_RATIO times the benefit, then the vertical and horizontal unions are
187+ * painted separately. Otherwise the entire bounding rectangle is painted.
188+ *
189+ * @param target Component to <code>paint</code> or <code>update</code>
190+ * @since 1.4
191+ */
192+ public void paint(Object target, boolean shouldClearRectBeforePaint) {
193+ Component comp = (Component)target;
194+
195+ if (isEmpty()) {
196+ return;
197+ }
198+
199+ if (!comp.isVisible()) {
200+ return;
201+ }
202+
203+ RepaintArea ra = this.cloneAndReset();
204+
205+ if (!subtract(ra.paintRects[VERTICAL], ra.paintRects[HORIZONTAL])) {
206+ subtract(ra.paintRects[HORIZONTAL], ra.paintRects[VERTICAL]);
207+ }
208+
209+ if (ra.paintRects[HORIZONTAL] != null && ra.paintRects[VERTICAL] != null) {
210+ Rectangle paintRect = ra.paintRects[HORIZONTAL].union(ra.paintRects[VERTICAL]);
211+ int square = paintRect.width * paintRect.height;
212+ int benefit = square - ra.paintRects[HORIZONTAL].width
213+ * ra.paintRects[HORIZONTAL].height - ra.paintRects[VERTICAL].width
214+ * ra.paintRects[VERTICAL].height;
215+ // if benefit is comparable with bounding box
216+ if (MAX_BENEFIT_RATIO * benefit < square) {
217+ ra.paintRects[HORIZONTAL] = paintRect;
218+ ra.paintRects[VERTICAL] = null;
219+ }
220+ }
221+ for (int i = 0; i < paintRects.length; i++) {
222+ if (ra.paintRects[i] != null
223+ && !ra.paintRects[i].isEmpty())
224+ {
225+ // Should use separate Graphics for each paint() call,
226+ // since paint() can change Graphics state for next call.
227+ Graphics g = comp.getGraphics();
228+ if (g != null) {
229+ try {
230+ g.setClip(ra.paintRects[i]);
231+ if (i == UPDATE) {
232+ updateComponent(comp, g);
233+ } else {
234+ if (shouldClearRectBeforePaint) {
235+ g.clearRect( ra.paintRects[i].x,
236+ ra.paintRects[i].y,
237+ ra.paintRects[i].width,
238+ ra.paintRects[i].height);
239+ }
240+ paintComponent(comp, g);
241+ }
242+ } finally {
243+ g.dispose();
244+ }
245+ }
246+ }
247+ }
248+ }
249+
250+ /**
251+ * Calls <code>Component.update(Graphics)</code> with given Graphics.
252+ */
253+ protected void updateComponent(Component comp, Graphics g) {
254+ if (comp != null) {
255+ comp.update(g);
256+ }
257+ }
258+
259+ /**
260+ * Calls <code>Component.paint(Graphics)</code> with given Graphics.
261+ */
262+ protected void paintComponent(Component comp, Graphics g) {
263+ if (comp != null) {
264+ comp.paint(g);
265+ }
266+ }
267+
268+ /**
269+ * Subtracts subtr from rect. If the result is rectangle
270+ * changes rect and returns true. Otherwise false.
271+ */
272+ static boolean subtract(Rectangle rect, Rectangle subtr) {
273+ if (rect == null || subtr == null) {
274+ return true;
275+ }
276+ Rectangle common = rect.intersection(subtr);
277+ if (common.isEmpty()) {
278+ return true;
279+ }
280+ if (rect.x == common.x && rect.y == common.y) {
281+ if (rect.width == common.width) {
282+ rect.y += common.height;
283+ rect.height -= common.height;
284+ return true;
285+ } else
286+ if (rect.height == common.height) {
287+ rect.x += common.width;
288+ rect.width -= common.width;
289+ return true;
290+ }
291+ } else
292+ if (rect.x + rect.width == common.x + common.width
293+ && rect.y + rect.height == common.y + common.height)
294+ {
295+ if (rect.width == common.width) {
296+ rect.height -= common.height;
297+ return true;
298+ } else
299+ if (rect.height == common.height) {
300+ rect.width -= common.width;
301+ return true;
302+ }
303+ }
304+ return false;
305+ }
306+
307+ public String toString() {
308+ return super.toString() + "[ horizontal=" + paintRects[0] +
309+ " vertical=" + paintRects[1] +
310+ " update=" + paintRects[2] + "]";
311+ }
312+}