diff options
Diffstat (limited to 'java/org/gnu/emacs/EmacsPaintQueue.java')
| -rw-r--r-- | java/org/gnu/emacs/EmacsPaintQueue.java | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/java/org/gnu/emacs/EmacsPaintQueue.java b/java/org/gnu/emacs/EmacsPaintQueue.java new file mode 100644 index 00000000000..5af5868d3b9 --- /dev/null +++ b/java/org/gnu/emacs/EmacsPaintQueue.java @@ -0,0 +1,138 @@ +/* Communication module for Android terminals. -*- c-file-style: "GNU" -*- + +Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ + +package org.gnu.emacs; + +import java.util.LinkedList; +import java.util.List; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; + +public class EmacsPaintQueue +{ + /* Queue of paint operations. This is modified from the Emacs + thread, and entire paint queues are periodically flushed to the + application thread where it is executed. */ + private List<EmacsPaintReq> paintOperations; + + /* Number of operations in this queue. */ + public int numRequests; + + public + EmacsPaintQueue () + { + paintOperations = new LinkedList<EmacsPaintReq> (); + } + + public void + run () + { + EmacsDrawable drawable, last; + Canvas canvas; + EmacsGC gc, lastGC; + int i; + Paint paint; + Rect rect, offsetRect, copyRect; + + canvas = null; + last = null; + gc = null; + paint = new Paint (); + + for (EmacsPaintReq req : paintOperations) + { + drawable = req.getDrawable (); + + synchronized (req) + { + /* Ignore graphics requests for drawables that have been + destroyed. */ + if (drawable.isDestroyed ()) + continue; + } + + canvas = drawable.lockCanvas (); + + if (canvas == null) + /* No canvas is currently available. */ + continue; + + lastGC = gc; + gc = req.getGC (); + rect = req.getRect (); + + if (gc.clip_rects == null) + { + /* No clipping is applied. Just draw and continue. */ + canvas.save (); + req.paintTo (canvas, paint, gc); + canvas.restore (); + drawable.damageRect (rect); + continue; + } + + if (gc.clip_rects != null && gc.clip_rects.length > 0) + { + canvas.save (); + + if (gc.clip_rects.length == 1) + { + /* There is only a single clip rect, which is simple + enough. */ + canvas.clipRect (gc.clip_rects[0]); + req.paintTo (canvas, paint, gc); + } + else + { + /* There are multiple clip rects. Android doesn't let + programs use RegionOp.UNION on the clip rectangle, + so Emacs must iterate over each intersection and + paint it manually. This seems inefficient but + thankfully Emacs never seems to use more than one + clip rect. */ + + for (i = 0; i < gc.clip_rects.length; ++i) + { + copyRect = new Rect (gc.clip_rects[i]); + + if (copyRect.intersect (rect)) + { + canvas.save (); + canvas.clipRect (copyRect); + req.paintTo (canvas, paint, gc); + canvas.restore (); + } + } + } + + drawable.damageRect (rect); + canvas.restore (); + } + } + } + + public void + appendPaintOperation (EmacsPaintReq req) + { + paintOperations.add (req); + numRequests++; + } +}; |
