40
40
* @since 3.1
41
41
*/
42
42
public class Pattern extends Resource {
43
-
44
- private int initialZoom ;
45
-
46
- private Runnable bitmapDestructor ;
47
-
48
43
// These are the possible fields with which a pattern can be initialized from the appropriate constructors.
49
44
private final Image image ;
50
45
private float baseX1 , baseY1 , baseX2 , baseY2 ;
51
46
private Color color1 , color2 ;
52
47
private int alpha1 , alpha2 ;
53
48
54
- private final Map <Integer , Long > zoomLevelToHandle = new HashMap <>();
49
+ private final Map <Integer , PatternHandle > zoomToHandle = new HashMap <>();
50
+
51
+ private boolean isDestroyed ;
55
52
56
53
/**
57
54
* Constructs a new Pattern given an image. Drawing with the resulting
@@ -87,8 +84,6 @@ public Pattern(Device device, Image image) {
87
84
if (image .isDisposed ()) SWT .error (SWT .ERROR_INVALID_ARGUMENT );
88
85
this .device .checkGDIP ();
89
86
this .image = image ;
90
- initialZoom = DPIUtil .getDeviceZoom ();
91
- setImageHandle (image , initialZoom );
92
87
init ();
93
88
this .device .registerResourceWithZoomSupport (this );
94
89
}
@@ -182,126 +177,48 @@ public Pattern(Device device, float x1, float y1, float x2, float y2, Color colo
182
177
this .alpha1 = alpha1 ;
183
178
this .alpha2 = alpha2 ;
184
179
this .image = null ;
185
- initialZoom = DPIUtil .getDeviceZoom ();
186
- initializeSize (initialZoom );
180
+ init ();
187
181
this .device .registerResourceWithZoomSupport (this );
188
182
}
189
183
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 );
197
187
}
198
- return this . zoomLevelToHandle . get (zoom );
188
+ return new BasePatternHandle (zoom );
199
189
}
200
190
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 ));
236
194
}
237
- this .zoomLevelToHandle .put (zoom , handle );
238
- init ();
195
+ return zoomToHandle .get (zoom );
239
196
}
240
197
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 ;
260
200
}
261
201
262
202
@ Override
263
203
void destroy () {
264
204
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 ;
273
208
}
274
209
275
210
@ Override
276
211
void destroyHandlesExcept (Set <Integer > zoomLevels ) {
277
- zoomLevelToHandle .entrySet ().removeIf (entry -> {
212
+ zoomToHandle .entrySet ().removeIf (entry -> {
278
213
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 ( );
281
216
return true ;
282
217
}
283
218
return false ;
284
219
});
285
220
}
286
221
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
-
305
222
/**
306
223
* Returns <code>true</code> if the Pattern has been disposed,
307
224
* and <code>false</code> otherwise.
@@ -314,7 +231,7 @@ private void destroyHandle(long handle) {
314
231
*/
315
232
@ Override
316
233
public boolean isDisposed () {
317
- return zoomLevelToHandle . isEmpty () ;
234
+ return isDestroyed ;
318
235
}
319
236
320
237
/**
@@ -326,11 +243,118 @@ public boolean isDisposed() {
326
243
@ Override
327
244
public String toString () {
328
245
if (isDisposed ()) return "Pattern {*DISPOSED*}" ;
329
- return "Pattern {" + zoomLevelToHandle + "}" ;
246
+ return "Pattern {" + zoomToHandle + "}" ;
330
247
}
331
248
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
+ }
334
293
}
335
294
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
+ }
336
360
}
0 commit comments