aboutsummaryrefslogtreecommitdiffstats
path: root/java/org/gnu/emacs/EmacsCopyArea.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/org/gnu/emacs/EmacsCopyArea.java')
-rw-r--r--java/org/gnu/emacs/EmacsCopyArea.java135
1 files changed, 112 insertions, 23 deletions
diff --git a/java/org/gnu/emacs/EmacsCopyArea.java b/java/org/gnu/emacs/EmacsCopyArea.java
index f34d1ecde01..0dd5b2c1fb6 100644
--- a/java/org/gnu/emacs/EmacsCopyArea.java
+++ b/java/org/gnu/emacs/EmacsCopyArea.java
@@ -32,19 +32,22 @@ public class EmacsCopyArea implements EmacsPaintReq
32 private int src_x, src_y, dest_x, dest_y, width, height; 32 private int src_x, src_y, dest_x, dest_y, width, height;
33 private EmacsDrawable destination, source; 33 private EmacsDrawable destination, source;
34 private EmacsGC immutableGC; 34 private EmacsGC immutableGC;
35 private static Xfermode xorAlu, srcInAlu; 35 private static Xfermode xorAlu, srcInAlu, overAlu;
36 36
37 static 37 static
38 { 38 {
39 overAlu = new PorterDuffXfermode (Mode.SRC_OVER);
39 xorAlu = new PorterDuffXfermode (Mode.XOR); 40 xorAlu = new PorterDuffXfermode (Mode.XOR);
40 srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); 41 srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
41 }; 42 };
42 43
43 public 44 public
44 EmacsCopyArea (EmacsDrawable destination, EmacsDrawable source, 45 EmacsCopyArea (EmacsDrawable source, EmacsDrawable destination,
45 int src_x, int src_y, int width, int height, 46 int src_x, int src_y, int width, int height,
46 int dest_x, int dest_y, EmacsGC immutableGC) 47 int dest_x, int dest_y, EmacsGC immutableGC)
47 { 48 {
49 Bitmap bitmap;
50
48 this.destination = destination; 51 this.destination = destination;
49 this.source = source; 52 this.source = source;
50 this.src_x = src_x; 53 this.src_x = src_x;
@@ -71,6 +74,16 @@ public class EmacsCopyArea implements EmacsPaintReq
71 return destination; 74 return destination;
72 } 75 }
73 76
77 private void
78 insetRectBy (Rect rect, int left, int top, int right,
79 int bottom)
80 {
81 rect.left += left;
82 rect.top += top;
83 rect.right -= right;
84 rect.bottom -= bottom;
85 }
86
74 @Override 87 @Override
75 public EmacsGC 88 public EmacsGC
76 getGC () 89 getGC ()
@@ -86,16 +99,45 @@ public class EmacsCopyArea implements EmacsPaintReq
86 Bitmap bitmap; 99 Bitmap bitmap;
87 Paint maskPaint; 100 Paint maskPaint;
88 Canvas maskCanvas; 101 Canvas maskCanvas;
89 Bitmap maskBitmap; 102 Bitmap srcBitmap, maskBitmap, clipBitmap;
90 Rect rect, srcRect; 103 Rect rect, maskRect, srcRect, dstRect, maskDestRect;
104 boolean needFill;
91 105
92 /* TODO implement stippling. */ 106 /* TODO implement stippling. */
93 if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) 107 if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
94 return; 108 return;
95 109
96 alu = immutableGC.function; 110 alu = immutableGC.function;
111
112 /* A copy must be created or drawBitmap could end up overwriting
113 itself. */
114 srcBitmap = source.getBitmap ();
115
116 /* If srcBitmap is out of bounds, then adjust the source rectangle
117 to be within bounds. Note that tiling on windows with
118 backgrounds is unimplemented. */
119
120 if (src_x < 0)
121 {
122 width += src_x;
123 dest_x -= src_x;
124 src_x = 0;
125 }
126
127 if (src_y < 0)
128 {
129 height += src_y;
130 dest_y -= src_y;
131 src_y = 0;
132 }
133
134 if (src_x + width > srcBitmap.getWidth ())
135 width = srcBitmap.getWidth () - src_x;
136
137 if (src_y + height > srcBitmap.getHeight ())
138 height = srcBitmap.getHeight () - src_y;
139
97 rect = getRect (); 140 rect = getRect ();
98 bitmap = source.getBitmap ();
99 141
100 if (alu == EmacsGC.GC_COPY) 142 if (alu == EmacsGC.GC_COPY)
101 paint.setXfermode (null); 143 paint.setXfermode (null);
@@ -103,29 +145,76 @@ public class EmacsCopyArea implements EmacsPaintReq
103 paint.setXfermode (xorAlu); 145 paint.setXfermode (xorAlu);
104 146
105 if (immutableGC.clip_mask == null) 147 if (immutableGC.clip_mask == null)
106 canvas.drawBitmap (bitmap, new Rect (src_x, src_y, 148 {
107 src_x + width, 149 bitmap = Bitmap.createBitmap (srcBitmap,
108 src_y + height), 150 src_x, src_y, width,
109 rect, paint); 151 height);
152 canvas.drawBitmap (bitmap, null, rect, paint);
153 }
110 else 154 else
111 { 155 {
112 maskPaint = new Paint (); 156 /* Drawing with a clip mask involves calculating the
113 srcRect = new Rect (0, 0, rect.width (), 157 intersection of the clip mask with the dst rect, and
114 rect.height ()); 158 extrapolating the corresponding part of the src rect. */
115 maskBitmap 159 clipBitmap = immutableGC.clip_mask.bitmap;
116 = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888, 160 dstRect = new Rect (dest_x, dest_y,
117 true); 161 dest_x + width,
118 162 dest_y + height);
119 if (maskBitmap == null) 163 maskRect = new Rect (immutableGC.clip_x_origin,
164 immutableGC.clip_y_origin,
165 (immutableGC.clip_x_origin
166 + clipBitmap.getWidth ()),
167 (immutableGC.clip_y_origin
168 + clipBitmap.getHeight ()));
169 clipBitmap = immutableGC.clip_mask.bitmap;
170
171 if (!maskRect.setIntersect (dstRect, maskRect))
172 /* There is no intersection between the clip mask and the
173 dest rect. */
120 return; 174 return;
121 175
122 maskPaint.setXfermode (srcInAlu); 176 /* Now figure out which part of the source corresponds to
177 maskRect and return it relative to srcBitmap. */
178 srcRect = new Rect (src_x, src_y, src_x + width,
179 src_y + height);
180 insetRectBy (srcRect, maskRect.left - dstRect.left,
181 maskRect.top - dstRect.top,
182 maskRect.right - dstRect.right,
183 maskRect.bottom - dstRect.bottom);
184
185 /* Finally, create a temporary bitmap that is the size of
186 maskRect. */
187
188 maskBitmap
189 = Bitmap.createBitmap (maskRect.width (), maskRect.height (),
190 Bitmap.Config.ARGB_8888);
191
192 /* Draw the mask onto the maskBitmap. */
123 maskCanvas = new Canvas (maskBitmap); 193 maskCanvas = new Canvas (maskBitmap);
124 maskCanvas.drawBitmap (bitmap, new Rect (src_x, src_y, 194 maskRect.offset (-immutableGC.clip_x_origin,
125 src_x + width, 195 -immutableGC.clip_y_origin);
126 src_y + height), 196 maskCanvas.drawBitmap (immutableGC.clip_mask.bitmap,
127 srcRect, maskPaint); 197 maskRect, new Rect (0, 0,
128 canvas.drawBitmap (maskBitmap, srcRect, rect, paint); 198 maskRect.width (),
199 maskRect.height ()),
200 paint);
201 maskRect.offset (immutableGC.clip_x_origin,
202 immutableGC.clip_y_origin);
203
204 /* Set the transfer mode to SRC_IN to preserve only the parts
205 of the source that overlap with the mask. */
206 maskPaint = new Paint ();
207 maskPaint.setXfermode (srcInAlu);
208
209 /* Draw the source. */
210 maskDestRect = new Rect (0, 0, srcRect.width (),
211 srcRect.height ());
212 maskCanvas.drawBitmap (srcBitmap, srcRect, maskDestRect,
213 maskPaint);
214
215 /* Finally, draw the mask bitmap to the destination. */
216 paint.setXfermode (overAlu);
217 canvas.drawBitmap (maskBitmap, null, maskRect, paint);
129 } 218 }
130 } 219 }
131} 220}