Skip to content

Commit de99b2d

Browse files
akoch-yattafedejeanne
authored andcommitted
[win32] Create Pattern handles on demand
This commit refactors Pattern in the win32 implementation to better support multiple handles for different zoom settings by creating all handles only on demand.
1 parent 0768d7e commit de99b2d

File tree

1 file changed

+131
-107
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+131
-107
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Pattern.java

Lines changed: 131 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,15 @@
4040
* @since 3.1
4141
*/
4242
public class Pattern extends Resource {
43-
44-
private int initialZoom;
45-
46-
private Runnable bitmapDestructor;
47-
4843
// These are the possible fields with which a pattern can be initialized from the appropriate constructors.
4944
private final Image image;
5045
private float baseX1, baseY1, baseX2, baseY2;
5146
private Color color1, color2;
5247
private int alpha1, alpha2;
5348

54-
private final Map<Integer, Long> zoomLevelToHandle = new HashMap<>();
49+
private final Map<Integer, PatternHandle> zoomToHandle = new HashMap<>();
50+
51+
private boolean isDestroyed;
5552

5653
/**
5754
* Constructs a new Pattern given an image. Drawing with the resulting
@@ -87,8 +84,6 @@ public Pattern(Device device, Image image) {
8784
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
8885
this.device.checkGDIP();
8986
this.image = image;
90-
initialZoom = DPIUtil.getDeviceZoom();
91-
setImageHandle(image, initialZoom);
9287
init();
9388
this.device.registerResourceWithZoomSupport(this);
9489
}
@@ -182,126 +177,48 @@ public Pattern(Device device, float x1, float y1, float x2, float y2, Color colo
182177
this.alpha1 = alpha1;
183178
this.alpha2 = alpha2;
184179
this.image = null;
185-
initialZoom = DPIUtil.getDeviceZoom();
186-
initializeSize(initialZoom);
180+
init();
187181
this.device.registerResourceWithZoomSupport(this);
188182
}
189183

190-
long getHandle(int zoom) {
191-
if (!this.zoomLevelToHandle.containsKey(zoom)) {
192-
if (isImagePattern()) {
193-
setImageHandle(image, zoom);
194-
} else {
195-
initializeSize(zoom);
196-
}
184+
private PatternHandle newPatternHandle(int zoom) {
185+
if (image != null) {
186+
return new ImagePatternHandle(zoom);
197187
}
198-
return this.zoomLevelToHandle.get(zoom);
188+
return new BasePatternHandle(zoom);
199189
}
200190

201-
private void initializeSize(int zoom) {
202-
long handle;
203-
float x1 = DPIUtil.scaleUp(this.baseX1, zoom);
204-
float y1 = DPIUtil.scaleUp(this.baseY1, zoom);
205-
float x2 = DPIUtil.scaleUp(this.baseX2, zoom);
206-
float y2 = DPIUtil.scaleUp(this.baseY2, zoom);
207-
if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
208-
if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
209-
if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
210-
if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
211-
this.device.checkGDIP();
212-
int colorRef1 = color1.handle;
213-
int foreColor = ((alpha1 & 0xFF) << 24) | ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16);
214-
if (x1 == x2 && y1 == y2) {
215-
handle = Gdip.SolidBrush_new(foreColor);
216-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
217-
} else {
218-
int colorRef2 = color2.handle;
219-
int backColor = ((alpha2 & 0xFF) << 24) | ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16);
220-
PointF p1 = new PointF();
221-
p1.X = x1;
222-
p1.Y = y1;
223-
PointF p2 = new PointF();
224-
p2.X = x2;
225-
p2.Y = y2;
226-
handle = Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor);
227-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
228-
if (alpha1 != 0xFF || alpha2 != 0xFF) {
229-
int a = (int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f);
230-
int r = (int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f);
231-
int g = (int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f);
232-
int b = (int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f);
233-
int midColor = a << 24 | r << 16 | g << 8 | b;
234-
Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int [] {foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3);
235-
}
191+
private PatternHandle getPatternHandle(int zoom) {
192+
if (!zoomToHandle.containsKey(zoom)) {
193+
zoomToHandle.put(zoom, newPatternHandle(zoom));
236194
}
237-
this.zoomLevelToHandle.put(zoom, handle);
238-
init();
195+
return zoomToHandle.get(zoom);
239196
}
240197

241-
void setImageHandle(Image image, int zoom) {
242-
long[] gdipImage = image.createGdipImage(zoom);
243-
long img = gdipImage[0];
244-
int width = Gdip.Image_GetWidth(img);
245-
int height = Gdip.Image_GetHeight(img);
246-
long handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
247-
bitmapDestructor = () -> {
248-
Gdip.Bitmap_delete(img);
249-
if (gdipImage[1] != 0) {
250-
long hHeap = OS.GetProcessHeap ();
251-
OS.HeapFree(hHeap, 0, gdipImage[1]);
252-
}
253-
};
254-
if (handle == 0) {
255-
bitmapDestructor.run();
256-
SWT.error(SWT.ERROR_NO_HANDLES);
257-
} else {
258-
zoomLevelToHandle.put(zoom, handle);
259-
}
198+
long getHandle(int zoom) {
199+
return this.getPatternHandle(zoom).handle;
260200
}
261201

262202
@Override
263203
void destroy() {
264204
device.deregisterResourceWithZoomSupport(this);
265-
for (long handle: zoomLevelToHandle.values()) {
266-
destroyHandle(handle);
267-
}
268-
zoomLevelToHandle.clear();
269-
if (bitmapDestructor != null) {
270-
bitmapDestructor.run();
271-
bitmapDestructor = null;
272-
}
205+
zoomToHandle.values().forEach(PatternHandle::destroy);
206+
zoomToHandle.clear();
207+
this.isDestroyed = true;
273208
}
274209

275210
@Override
276211
void destroyHandlesExcept(Set<Integer> zoomLevels) {
277-
zoomLevelToHandle.entrySet().removeIf(entry -> {
212+
zoomToHandle.entrySet().removeIf(entry -> {
278213
final Integer zoom = entry.getKey();
279-
if (!zoomLevels.contains(zoom) && zoom != initialZoom) {
280-
destroyHandle(entry.getValue());
214+
if (!zoomLevels.contains(zoom) ) {
215+
entry.getValue().destroy();
281216
return true;
282217
}
283218
return false;
284219
});
285220
}
286221

287-
private void destroyHandle(long handle) {
288-
int type = Gdip.Brush_GetType(handle);
289-
switch (type) {
290-
case Gdip.BrushTypeSolidColor:
291-
Gdip.SolidBrush_delete(handle);
292-
break;
293-
case Gdip.BrushTypeHatchFill:
294-
Gdip.HatchBrush_delete(handle);
295-
break;
296-
case Gdip.BrushTypeLinearGradient:
297-
Gdip.LinearGradientBrush_delete(handle);
298-
break;
299-
case Gdip.BrushTypeTextureFill:
300-
Gdip.TextureBrush_delete(handle);
301-
break;
302-
}
303-
}
304-
305222
/**
306223
* Returns <code>true</code> if the Pattern has been disposed,
307224
* and <code>false</code> otherwise.
@@ -314,7 +231,7 @@ private void destroyHandle(long handle) {
314231
*/
315232
@Override
316233
public boolean isDisposed() {
317-
return zoomLevelToHandle.isEmpty();
234+
return isDestroyed;
318235
}
319236

320237
/**
@@ -326,11 +243,118 @@ public boolean isDisposed() {
326243
@Override
327244
public String toString() {
328245
if (isDisposed()) return "Pattern {*DISPOSED*}";
329-
return "Pattern {" + zoomLevelToHandle + "}";
246+
return "Pattern {" + zoomToHandle + "}";
330247
}
331248

332-
private boolean isImagePattern() {
333-
return image != null;
249+
private class BasePatternHandle extends PatternHandle {
250+
public BasePatternHandle(int zoom) {
251+
super(zoom);
252+
}
253+
254+
@Override
255+
long createHandle(int zoom) {
256+
long handle;
257+
float x1 = DPIUtil.scaleUp(baseX1, zoom);
258+
float y1 = DPIUtil.scaleUp(baseY1, zoom);
259+
float x2 = DPIUtil.scaleUp(baseX2, zoom);
260+
float y2 = DPIUtil.scaleUp(baseY2, zoom);
261+
if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
262+
if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
263+
if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
264+
if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
265+
device.checkGDIP();
266+
int colorRef1 = color1.handle;
267+
int foreColor = ((alpha1 & 0xFF) << 24) | ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16);
268+
if (x1 == x2 && y1 == y2) {
269+
handle = Gdip.SolidBrush_new(foreColor);
270+
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
271+
} else {
272+
int colorRef2 = color2.handle;
273+
int backColor = ((alpha2 & 0xFF) << 24) | ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16);
274+
PointF p1 = new PointF();
275+
p1.X = x1;
276+
p1.Y = y1;
277+
PointF p2 = new PointF();
278+
p2.X = x2;
279+
p2.Y = y2;
280+
handle = Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor);
281+
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
282+
if (alpha1 != 0xFF || alpha2 != 0xFF) {
283+
int a = (int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f);
284+
int r = (int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f);
285+
int g = (int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f);
286+
int b = (int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f);
287+
int midColor = a << 24 | r << 16 | g << 8 | b;
288+
Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int [] {foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3);
289+
}
290+
}
291+
return handle;
292+
}
334293
}
335294

295+
private class ImagePatternHandle extends PatternHandle {
296+
private long[] gdipImage;
297+
298+
public ImagePatternHandle(int zoom) {
299+
super(zoom);
300+
}
301+
302+
@Override
303+
long createHandle(int zoom) {
304+
gdipImage = image.createGdipImage(zoom);
305+
long img = gdipImage[0];
306+
int width = Gdip.Image_GetWidth(img);
307+
int height = Gdip.Image_GetHeight(img);
308+
long handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
309+
if (handle == 0) {
310+
cleanupBitmap();
311+
SWT.error(SWT.ERROR_NO_HANDLES);
312+
}
313+
return handle;
314+
}
315+
316+
@Override
317+
protected void destroy() {
318+
super.destroy();
319+
cleanupBitmap();
320+
}
321+
322+
private void cleanupBitmap() {
323+
if (gdipImage.length < 2) return;
324+
long img = gdipImage[0];
325+
Gdip.Bitmap_delete(img);
326+
if (gdipImage[1] != 0) {
327+
long hHeap = OS.GetProcessHeap ();
328+
OS.HeapFree(hHeap, 0, gdipImage[1]);
329+
}
330+
}
331+
}
332+
333+
private abstract class PatternHandle {
334+
private final long handle;
335+
336+
public PatternHandle(int zoom) {
337+
this.handle = createHandle(zoom);
338+
}
339+
340+
abstract long createHandle(int zoom);
341+
342+
protected void destroy() {
343+
int type = Gdip.Brush_GetType(handle);
344+
switch (type) {
345+
case Gdip.BrushTypeSolidColor:
346+
Gdip.SolidBrush_delete(handle);
347+
break;
348+
case Gdip.BrushTypeHatchFill:
349+
Gdip.HatchBrush_delete(handle);
350+
break;
351+
case Gdip.BrushTypeLinearGradient:
352+
Gdip.LinearGradientBrush_delete(handle);
353+
break;
354+
case Gdip.BrushTypeTextureFill:
355+
Gdip.TextureBrush_delete(handle);
356+
break;
357+
}
358+
}
359+
}
336360
}

0 commit comments

Comments
 (0)