Project

General

Profile

caching_images_20151011.txt

Sergey Ivanovskiy, 10/11/2015 05:11 PM

Download (20.4 KB)

 
1
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/BufferedImageDrawHelper.java'
2
--- src/com/goldencode/p2j/ui/client/gui/driver/BufferedImageDrawHelper.java	2015-08-13 14:51:06 +0000
3
+++ src/com/goldencode/p2j/ui/client/gui/driver/BufferedImageDrawHelper.java	2015-10-11 20:59:55 +0000
4
@@ -31,7 +31,7 @@
5
     * @param    ps
6
     *           The holder for images parameters.
7
     * 
8
-    * @return The wrapped image with its with and its height.
9
+    * @return The wrapped image with its width and its height.
10
     */
11
    @Override
12
    public ImageWrapper<BufferedImage> processImage(PaintStructure<?, BufferedImage> ps)
13
@@ -127,6 +127,78 @@
14
    }
15
 
16
    /**
17
+    * Calculate the transformed image bounds.
18
+    * 
19
+    * @param    ps
20
+    *           The holder for images parameters.
21
+    * 
22
+    * @return The 2-elements array filled with new transformed image width and its new height.
23
+    */
24
+   @Override
25
+   public Integer[] calculateImageBounds(PaintStructure<?, BufferedImage> ps)
26
+   {
27
+      int width  = 0;
28
+      int height = 0;
29
+      // scaling factors for vertical and horizontal
30
+      float kHor = 0;
31
+      float kVer = 0;
32
+      if (ps.xOffset == -1 && ps.yOffset == -1)
33
+      {
34
+         width    = ps.width;
35
+         height   = ps.height;
36
+         kHor = ((float)ps.width) / ((float) ps.img.getWidth());
37
+         kVer = ((float)ps.height) / ((float) ps.img.getHeight()); 
38
+      }
39
+      else
40
+      {
41
+         // need to recalc the width and height for subimage to cut
42
+         // to not go out of image borders
43
+         int widthToCut = ps.img.getWidth() - ps.xOffset;
44
+         if (widthToCut > ps.width)
45
+         {
46
+            widthToCut = ps.width;
47
+         }
48
+         int heightToCut = ps.img.getHeight() - ps.yOffset;
49
+         if (heightToCut > ps.height)
50
+         {
51
+            heightToCut = ps.height;
52
+         }
53
+
54
+         width    = widthToCut;
55
+         height   = heightToCut;
56
+         kHor = ((float)ps.width) / ((float)widthToCut);
57
+         kVer = ((float)ps.height) / ((float)heightToCut); 
58
+      }
59
+      // resizing
60
+      if (ps.stretchToFit)
61
+      {
62
+         if (ps.retainShape)
63
+         {
64
+            // need to calculate native aspect ratio for image
65
+            // if we have two different scaling factors for x and y we choose only one
66
+            // to keep scaling in both directions, this must be one that is smaller
67
+            if (kHor < kVer)
68
+            {
69
+               width  = ps.width;
70
+               height = Math.round(((float)height) * kHor);
71
+            }
72
+            else
73
+            {
74
+               width = Math.round(((float)width) * kVer);
75
+               height = ps.height;
76
+            }
77
+         }
78
+         else
79
+         {
80
+            width  = ps.width;
81
+            height = ps.height;
82
+         }
83
+      }
84
+
85
+      return new Integer[] {width, height};
86
+   }
87
+
88
+   /**
89
     * Converts the image replacing standard 3D colors with currently redefined.
90
     * 
91
     * @param   img
92

    
93
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/ClientImageDrawHelper.java'
94
--- src/com/goldencode/p2j/ui/client/gui/driver/ClientImageDrawHelper.java	2015-08-13 14:51:06 +0000
95
+++ src/com/goldencode/p2j/ui/client/gui/driver/ClientImageDrawHelper.java	2015-10-11 20:34:44 +0000
96
@@ -14,6 +14,8 @@
97
 
98
 package com.goldencode.p2j.ui.client.gui.driver;
99
 
100
+import java.awt.image.BufferedImage;
101
+
102
 /**
103
  * Defines additional processing for images.
104
  * 
105
@@ -28,7 +30,17 @@
106
     * @param    ps
107
     *           The holder for images parameters.
108
     * 
109
-    * @return The wrapped image with its with and its height.
110
+    * @return The wrapped image with its width and its height.
111
     */
112
    public ImageWrapper<I> processImage(PaintStructure<?, I> ps);
113
+
114
+   /**
115
+    * Calculate the transformed image bounds.
116
+    * 
117
+    * @param    ps
118
+    *           The holder for images parameters.
119
+    * 
120
+    * @return The 2-elements array filled with new transformed image width and its new height.
121
+    */
122
+   public Integer[] calculateImageBounds(PaintStructure<?, BufferedImage> ps);
123
 }
124

    
125
=== added file 'src/com/goldencode/p2j/ui/client/gui/driver/EmbeddedImageStructure.java'
126
--- src/com/goldencode/p2j/ui/client/gui/driver/EmbeddedImageStructure.java	1970-01-01 00:00:00 +0000
127
+++ src/com/goldencode/p2j/ui/client/gui/driver/EmbeddedImageStructure.java	2015-10-11 21:00:55 +0000
128
@@ -0,0 +1,171 @@
129
+/*
130
+** Module   : EmbeddedImageStructure.java
131
+** Abstract : A structure used to store images drawing parameters.
132
+**
133
+** Copyright (c) 2014-2015, Golden Code Development Corporation.
134
+** ALL RIGHTS RESERVED. Use is subject to license terms.
135
+**
136
+**           Golden Code Development Corporation
137
+**                      CONFIDENTIAL
138
+**
139
+** -#- -I- --Date-- ---------------------------------Description---------------------------------
140
+** 001 SBI 20151011 First version.
141
+**/
142
+
143
+package com.goldencode.p2j.ui.client.gui.driver;
144
+
145
+import java.util.Arrays;
146
+import java.util.List;
147
+
148
+
149
+/**
150
+ * Encapsulates the image drawing parameters. 
151
+ */
152
+public class EmbeddedImageStructure
153
+{
154
+   /** convert 3d image bit mask */
155
+   static final int CONVERT_3D_MASK  = 1;
156
+
157
+   /** transparent image bit mask */
158
+   static final int TRANSPARENT_MASK = 2;
159
+
160
+   /** stretch to fit image bit mask */
161
+   static final int STRETCH_TO_FIT_MASK = 4;
162
+
163
+   /** retain shape image bit mask */
164
+   static final int RETAIN_SHAPE_MASK   = 8;
165
+
166
+
167
+   /** Width parameter */
168
+   private final int width;
169
+   
170
+   /** Height parameter */
171
+   private final int height;
172
+   
173
+   /** X offset to start drawing image. */
174
+   private final int xOffset;
175
+   
176
+   /** Y offset to start drawing image. */
177
+   private final int yOffset;
178
+
179
+   /** Image to draw */
180
+   private final ImageWrapper img;
181
+
182
+   /** The bits mask that encodes image conversions. */
183
+   private final int imageConversionMask;
184
+
185
+   /**
186
+    * @param paintStructure
187
+    */
188
+   EmbeddedImageStructure(PaintStructure paintStructure)
189
+   {
190
+      this.width   = paintStructure.width;
191
+      this.height  = paintStructure.height;
192
+      this.xOffset = paintStructure.xOffset;
193
+      this.yOffset = paintStructure.yOffset;
194
+      this.img     = paintStructure.img;
195
+      this.imageConversionMask = encodeImageConversionMask(paintStructure);
196
+   }
197
+
198
+   /**
199
+    * Encodes image conversions: 3d, transparent, stretch, retain.
200
+    * 
201
+    * @return   The bits mask that encodes image conversions.
202
+    */
203
+   private static byte encodeImageConversionMask(PaintStructure paintStructure)
204
+   {
205
+      byte mask = 0;
206
+      if (paintStructure.convert3D)
207
+      {
208
+         mask |= CONVERT_3D_MASK;
209
+      }
210
+      if (paintStructure.transparent)
211
+      {
212
+         mask |= TRANSPARENT_MASK;
213
+      }
214
+      if (paintStructure.stretchToFit)
215
+      {
216
+         mask |= STRETCH_TO_FIT_MASK;
217
+      }
218
+      if (paintStructure.retainShape)
219
+      {
220
+         mask |= RETAIN_SHAPE_MASK;
221
+      }
222
+
223
+      return mask;
224
+   }
225
+
226
+   /**
227
+    * Returns the image canvas width.
228
+    * 
229
+    * @return   The width.
230
+    */
231
+   public int getWidth()
232
+   {
233
+      return this.width;
234
+   }
235
+
236
+   /**
237
+    * Returns the image canvas height.
238
+    * 
239
+    * @return The canvas height.
240
+    */
241
+   public int getHeight()
242
+   {
243
+      return this.height;
244
+   }
245
+
246
+   /**
247
+    * The image drawing offset along x-axis.
248
+    * 
249
+    * @return   The xOffset
250
+    */
251
+   public int getxOffset()
252
+   {
253
+      return this.xOffset;
254
+   }
255
+
256
+   /**
257
+    * The image drawing offset along y-axis.
258
+    * 
259
+    * @return   The yOffset.
260
+    */
261
+   public int getyOffset()
262
+   {
263
+      return this.yOffset;
264
+   }
265
+
266
+   /**
267
+    * Returns the wrapped image to draw.
268
+    * 
269
+    * @return   The wrapped image.
270
+    */
271
+   public ImageWrapper getImage()
272
+   {
273
+      return this.img;
274
+   }
275
+
276
+   /**
277
+    * Encodes image conversions: 3d, transparent, stretch, retain.
278
+    * 
279
+    * @return   The bits mask that encodes image conversions.
280
+    */
281
+   public int getImageConversionMask()
282
+   {
283
+      return this.imageConversionMask;
284
+   }
285
+
286
+   /**
287
+    * Returns the embedded image identity 6-tuple.
288
+    * 
289
+    * @return   The array of 6 integer to represent the embedded image identity.
290
+    */
291
+   public List<Integer> getObjectSeal()
292
+   {
293
+      return Arrays.<Integer>asList(
294
+               new Integer [] {
295
+                           this.xOffset, this.yOffset, this.width, this.height,
296
+                           this.imageConversionMask, this.img.getUniqueId()
297
+                        });
298
+   }
299
+}
300

    
301
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/ImageWrapper.java'
302
--- src/com/goldencode/p2j/ui/client/gui/driver/ImageWrapper.java	2015-05-18 20:48:28 +0000
303
+++ src/com/goldencode/p2j/ui/client/gui/driver/ImageWrapper.java	2015-10-11 18:43:32 +0000
304
@@ -14,11 +14,30 @@
305
 
306
 package com.goldencode.p2j.ui.client.gui.driver;
307
 
308
+import java.util.concurrent.atomic.AtomicInteger;
309
+
310
 /**
311
  * Contains the state for a native image which can be accessed in a general purpose manner.
312
  */
313
 public class ImageWrapper<I>
314
 {
315
+   /** Represents a images sequence that holds the next free sequence id. */
316
+   private final static AtomicInteger IMAGES_SEQUENCE = new AtomicInteger(1);
317
+   
318
+   
319
+   /**
320
+    * Returns the next unique image id within this class loader.
321
+    * 
322
+    * @return   The next unigue image id.
323
+    */
324
+   private static final int getImageUniqueId()
325
+   {
326
+      return IMAGES_SEQUENCE.getAndIncrement();
327
+   }
328
+   
329
+   /** The image unique id.*/
330
+   private final int uniqueId;
331
+   
332
    /** Contained native image. */
333
    private I image = null;
334
    
335
@@ -40,11 +59,22 @@
336
     */
337
    public ImageWrapper(I image, int height, int width)
338
    {
339
+      this.uniqueId = getImageUniqueId();
340
       this.image  = image;
341
       this.height = height;
342
       this.width  = width;
343
    }
344
-   
345
+
346
+   /**
347
+    * Returns the image unique id.
348
+    * 
349
+    * @return The image unique id.
350
+    */
351
+   public int getUniqueId()
352
+   {
353
+      return uniqueId;
354
+   }
355
+
356
    /**
357
     * Obtain the contained native image instance.
358
     *
359

    
360
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/PaintStructure.java'
361
--- src/com/goldencode/p2j/ui/client/gui/driver/PaintStructure.java	2015-09-16 16:53:54 +0000
362
+++ src/com/goldencode/p2j/ui/client/gui/driver/PaintStructure.java	2015-10-11 20:46:32 +0000
363
@@ -26,7 +26,6 @@
364
 
365
 import com.goldencode.p2j.ui.*;
366
 import com.goldencode.p2j.ui.client.*;
367
-import com.goldencode.util.*;
368
 
369
 /**
370
  * A structure used to store paint parameters. Depending on paint operation different fields are
371
@@ -119,4 +118,14 @@
372
    {
373
       this.id = id;
374
    }
375
+   
376
+   /**
377
+    * Return the embedded image structure filled with the required parameters to draw the target.
378
+    * 
379
+    * @return   The embedded image structure.
380
+    */
381
+   public EmbeddedImageStructure getEmbeddedImageStructure()
382
+   {
383
+      return new EmbeddedImageStructure(this);
384
+   }
385
 }
386

    
387
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebDriver.java'
388
--- src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebDriver.java	2015-10-09 19:15:11 +0000
389
+++ src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebDriver.java	2015-10-11 21:05:48 +0000
390
@@ -101,12 +101,18 @@
391
    
392
    /** Virtual screen for drawing in a memory */
393
    private VirtualScreen virtualScreen;
394
-   
395
-   /** Image usages is a mapping of an image loaded by a client to its owner windows. */
396
-   private final Map<Integer, Set<Integer> > imageUsages;
397
-   
398
-   /** Owned images is a mapping of a window to its owned images. */
399
-   private final Map<Integer, Set<Integer> > ownedImages;
400
+
401
+   /** Maps the image seal to the unique image identity. */
402
+   private final Map<List<Integer>, Integer > imageSeals;
403
+
404
+   /**
405
+    * Image usages is a mapping of an image loaded by a client to its owner windows.
406
+    * The loaded image is represented by its image seal 6-tuple integer array.
407
+    **/
408
+   private final Map<List<Integer>, Set<Integer> > imageUsages;
409
+   
410
+   /** Owned images is a mapping of a window to its owned images seals. */
411
+   private final Map<Integer, Set<List<Integer>> > ownedImages;
412
    
413
    /** A cache of font metrics objects, by their remote font ID. */
414
    private Map<Integer, FontMetricsHelper> fontMetricsCache = new HashMap<>();
415
@@ -150,8 +156,9 @@
416
       });
417
       
418
       this.config = config;
419
-      this.imageUsages = new HashMap<Integer, Set<Integer>>();
420
-      this.ownedImages = new HashMap<Integer, Set<Integer>>();
421
+      this.imageUsages = new HashMap<List<Integer>, Set<Integer>>();
422
+      this.ownedImages = new HashMap<Integer, Set<List<Integer>>>();
423
+      this.imageSeals  = new HashMap<List<Integer>, Integer>();
424
       
425
       new RepaintThread().start();
426
    }
427
@@ -271,7 +278,7 @@
428
     * 
429
     * @return   True iff it is the first usage of the given image.
430
     */
431
-   public boolean addImageUsage(int imageHash, int windowId)
432
+   public boolean addImageUsage(List<Integer> imageHash, int windowId)
433
    {
434
       boolean newLoadedImage = false;
435
       
436
@@ -284,10 +291,10 @@
437
       }
438
       usages.add(windowId);
439
       
440
-      Set<Integer> images = ownedImages.get(windowId);
441
+      Set<List<Integer>> images = ownedImages.get(windowId);
442
       if (images == null)
443
       {
444
-         images = new HashSet<Integer>();
445
+         images = new HashSet<List<Integer>>();
446
          ownedImages.put(windowId, images);
447
       }
448
       images.add(imageHash);
449
@@ -306,18 +313,19 @@
450
    public Set<Integer> removeUnusedImages(int windowId)
451
    {
452
       Set<Integer> imagesToRemove = new HashSet<Integer>();
453
-      Set<Integer> images = ownedImages.remove(windowId);
454
+      Set<List<Integer>> images = ownedImages.remove(windowId);
455
       if (images != null && !images.isEmpty())
456
       {
457
-         for (Integer imageHash : images)
458
+         for (List<Integer> imageSeal : images)
459
          {
460
-            Set<Integer> usages = imageUsages.get(imageHash);
461
+            Set<Integer> usages = imageUsages.get(imageSeal);
462
             if (usages.remove(windowId))
463
             {
464
                if (usages.isEmpty())
465
                {
466
-                  imagesToRemove.add(imageHash);
467
-                  imageUsages.remove(imageHash);
468
+                  Integer imageUniqueId = imageSeals.remove(imageSeal);
469
+                  imagesToRemove.add(imageUniqueId);
470
+                  imageUsages.remove(imageSeal);
471
                }
472
             }
473
          }
474
@@ -327,6 +335,32 @@
475
    }
476
    
477
    /**
478
+    * Maps the image identity array to the unique image id.
479
+    * 
480
+    * @param    imageSeal
481
+    *           The image identity array.
482
+    * @param    uniqueId
483
+    *           The image unique id.
484
+    */
485
+   public void mapSealToUniqueId(List<Integer> imageSeal, Integer uniqueId)
486
+   {
487
+      imageSeals.put(imageSeal, uniqueId);
488
+   }
489
+   
490
+   /**
491
+    * Gets the unique image id by its identity array.
492
+    * 
493
+    * @param    imageSeal
494
+    *           The image identity array.
495
+    * 
496
+    * @return   The image unique id.
497
+    */
498
+   public Integer getUniqueIdForSeal(List<Integer> imageSeal)
499
+   {
500
+      return imageSeals.get(imageSeal);
501
+   }
502
+   
503
+   /**
504
     * Returns an application-usable display area. For example, a task bar is
505
     * not counted as the usable area and it is always at the bottom of the
506
     * virtual screen (when present).
507

    
508
=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebEmulatedWindow.java'
509
--- src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebEmulatedWindow.java	2015-09-29 14:43:06 +0000
510
+++ src/com/goldencode/p2j/ui/client/gui/driver/web/GuiWebEmulatedWindow.java	2015-10-11 20:45:05 +0000
511
@@ -320,13 +320,14 @@
512
             break;
513
          case DRAW_IMAGE:
514
             {
515
-               ImageWrapper wrappedImage = drawHelper.processImage(ps);
516
-               Object[] imageEncodedPacket = encodeImage(ps.x, ps.y, wrappedImage);
517
-               int imageHash = (Integer) imageEncodedPacket[0];
518
+               Object[] imageEncodedPacket = encodeImage(ps);
519
+               int imageId = (Integer) imageEncodedPacket[0];
520
                ImageEncoding encoding = (ImageEncoding) imageEncodedPacket[1];
521
                byte[] encodedImage = (byte[]) imageEncodedPacket[2];
522
-               websock.drawImage(ps.x, ps.y, wrappedImage.getWidth(), wrappedImage.getHeight(),
523
-                        encoding, imageHash, encodedImage);
524
+               Integer imageWidth  = (Integer) imageEncodedPacket[3];
525
+               Integer imageHeight = (Integer) imageEncodedPacket[4];
526
+               websock.drawImage(ps.x, ps.y, imageWidth, imageHeight,
527
+                        encoding, imageId, encodedImage);
528
             }
529
             break;
530
          case FILL_RECT:
531
@@ -417,13 +418,14 @@
532
             break;
533
          case SET_ICON:
534
             {
535
-               ImageWrapper wrappedImage = drawHelper.processImage(ps);
536
-               Object[] imageEncodedPacket = encodeImage(ps.x, ps.y, wrappedImage);
537
-               int imageHash = (Integer) imageEncodedPacket[0];
538
+               Object[] imageEncodedPacket = encodeImage(ps);
539
+               int imageId = (Integer) imageEncodedPacket[0];
540
                ImageEncoding encoding = (ImageEncoding) imageEncodedPacket[1];
541
                byte[] encodedImage = (byte[]) imageEncodedPacket[2];
542
-               websock.setIconImage(wrappedImage.getWidth(), wrappedImage.getHeight(), encoding,
543
-                        imageHash, encodedImage);
544
+               Integer imageWidth  = (Integer) imageEncodedPacket[3];
545
+               Integer imageHeight = (Integer) imageEncodedPacket[4];
546
+               websock.setIconImage(imageWidth, imageHeight, encoding,
547
+                        imageId, encodedImage);
548
             }
549
             break;
550
          default:
551
@@ -436,37 +438,49 @@
552
     * the image hash in its first element, the image encoding in its second element
553
     * and the encoded image or null in its third element depending on its loaded state.
554
     * 
555
-    * @param    x
556
-    *           The x-coordinate of the target image position. 
557
-    * @param    y
558
-    *           The y-coordinate of the target image position.
559
-    * @param    wrappedImage
560
-    *           The wrapped image.
561
+    * @param    ps
562
+    *           The paint structure filled with the target image parameters. 
563
     * 
564
-    * @return   The 3-elements array that holds the image hash in its first element,
565
-    *           the image encoding in its second element and the bytes array of the encoded image
566
-    *           or null in its third element. 
567
+    * @return   The 5-elements array that holds the image unique id in its first element, the image
568
+    *           encoding in its second element, the bytes array of the encoded image or null
569
+    *           in its third element, the width and the height of the embedded image in its forth
570
+    *           element and its fifth element respectively.
571
     */
572
-   private final Object[] encodeImage(int x, int y, ImageWrapper wrappedImage)
573
+   private final Object[] encodeImage(PaintStructure<Integer, BufferedImage> ps)
574
    {
575
+      EmbeddedImageStructure embeddedImageStructure = ps.getEmbeddedImageStructure();
576
+      List<Integer> imageSeal = embeddedImageStructure.getObjectSeal();
577
       VirtualScreen virtualScreen = webdriver.getVirtualScreen();
578
-      int imageHash = wrappedImage.getImage().hashCode();
579
       ImageEncoding encoding;
580
       byte[] encodedImage;
581
-      if (webdriver.addImageUsage(imageHash, windowId))
582
+      Integer imageWidth;
583
+      Integer imageHeight;
584
+      Integer imageId;
585
+      if (webdriver.addImageUsage(imageSeal, windowId))
586
       {
587
+         int x = ps.x;
588
+         int y = ps.y;
589
+         ImageWrapper embeddedImage = drawHelper.processImage(ps);
590
+         imageId = embeddedImage.getUniqueId();
591
+         webdriver.mapSealToUniqueId(imageSeal, imageId);
592
+         imageWidth  = embeddedImage.getWidth();
593
+         imageHeight = embeddedImage.getHeight();
594
          encoding = ImageEncoding.RAW;
595
-         virtualScreen.drawImage(wrappedImage, x, y);
596
+         virtualScreen.drawImage(embeddedImage, x, y);
597
          encodedImage = new RawEncoder().packToBinaries(virtualScreen, x, y,
598
-                  wrappedImage.getWidth(), wrappedImage.getHeight());
599
+                  imageWidth, imageHeight);
600
       }
601
       else
602
       {
603
+         imageId = webdriver.getUniqueIdForSeal(imageSeal);
604
          encoding = ImageEncoding.HASH;
605
          encodedImage = null;
606
+         Integer[] imageBounds = drawHelper.calculateImageBounds(ps);
607
+         imageWidth  = imageBounds[0];
608
+         imageHeight = imageBounds[1];
609
       }
610
       
611
-      return new Object[] {imageHash, encoding, encodedImage};
612
+      return new Object[] {imageId, encoding, encodedImage, imageWidth, imageHeight};
613
    }
614
    
615
    /**
616