1 /* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
2
3 Copyright (C) 2023 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19
20 package org.gnu.emacs;
21
22 import android.graphics.Bitmap;
23 import android.graphics.Canvas;
24 import android.graphics.Paint;
25 import android.graphics.Rect;
26
27 import android.util.Log;
28
29 public final class EmacsFillRectangle
30 {
31 public static void
32 perform (EmacsDrawable drawable, EmacsGC gc,
33 int x, int y, int width, int height)
34 {
35 Paint maskPaint, paint;
36 Canvas maskCanvas;
37 Bitmap maskBitmap;
38 Rect rect;
39 Rect maskRect, dstRect;
40 Canvas canvas;
41 Bitmap clipBitmap;
42
43 /* TODO implement stippling. */
44 if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
45 return;
46
47 canvas = drawable.lockCanvas (gc);
48
49 if (canvas == null)
50 return;
51
52 paint = gc.gcPaint;
53 rect = new Rect (x, y, x + width, y + height);
54
55 paint.setStyle (Paint.Style.FILL);
56
57 if (gc.clip_mask == null)
58 canvas.drawRect (rect, paint);
59 else
60 {
61 /* Drawing with a clip mask involves calculating the
62 intersection of the clip mask with the dst rect, and
63 extrapolating the corresponding part of the src rect. */
64
65 clipBitmap = gc.clip_mask.bitmap;
66 dstRect = new Rect (x, y, x + width, y + height);
67 maskRect = new Rect (gc.clip_x_origin,
68 gc.clip_y_origin,
69 (gc.clip_x_origin
70 + clipBitmap.getWidth ()),
71 (gc.clip_y_origin
72 + clipBitmap.getHeight ()));
73
74 if (!maskRect.setIntersect (dstRect, maskRect))
75 /* There is no intersection between the clip mask and the
76 dest rect. */
77 return;
78
79 /* Finally, create a temporary bitmap that is the size of
80 maskRect. */
81
82 maskBitmap
83 = Bitmap.createBitmap (maskRect.width (), maskRect.height (),
84 Bitmap.Config.ARGB_8888);
85
86 /* Draw the mask onto the maskBitmap. */
87 maskCanvas = new Canvas (maskBitmap);
88 maskRect.offset (-gc.clip_x_origin,
89 -gc.clip_y_origin);
90 maskCanvas.drawBitmap (gc.clip_mask.bitmap,
91 maskRect, new Rect (0, 0,
92 maskRect.width (),
93 maskRect.height ()),
94 paint);
95 maskRect.offset (gc.clip_x_origin,
96 gc.clip_y_origin);
97
98 /* Set the transfer mode to SRC_IN to preserve only the parts
99 of the source that overlap with the mask. */
100 maskPaint = new Paint ();
101 maskPaint.setXfermode (EmacsGC.srcInAlu);
102
103 /* Draw the source. */
104 maskCanvas.drawRect (maskRect, maskPaint);
105
106 /* Finally, draw the mask bitmap to the destination. */
107 paint.setXfermode (null);
108 canvas.drawBitmap (maskBitmap, null, maskRect, paint);
109
110 /* Recycle this unused bitmap. */
111 maskBitmap.recycle ();
112 }
113
114 drawable.damageRect (rect);
115 }
116 }