root/java/org/gnu/emacs/EmacsPixmap.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lockCanvas
  2. damageRect
  3. getBitmap
  4. destroyHandle

     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 java.lang.IllegalArgumentException;
    23 
    24 import android.graphics.Bitmap;
    25 import android.graphics.Canvas;
    26 import android.graphics.Rect;
    27 
    28 import android.os.Build;
    29 
    30 /* Drawable backed by bitmap.  */
    31 
    32 public final class EmacsPixmap extends EmacsHandleObject
    33   implements EmacsDrawable
    34 {
    35   /* The depth of the bitmap.  This is not actually used, just defined
    36      in order to be consistent with X.  */
    37   public int depth, width, height;
    38 
    39   /* The bitmap itself.  */
    40   public Bitmap bitmap;
    41 
    42   /* The canvas used to draw to BITMAP.  */
    43   public Canvas canvas;
    44 
    45   /* Whether or not GC should be explicitly triggered upon
    46      release.  */
    47   private boolean needCollect;
    48 
    49   /* ID used to determine whether or not the GC clip rects
    50      changed.  */
    51   private long gcClipRectID;
    52 
    53   public
    54   EmacsPixmap (short handle, int colors[], int width,
    55                int height, int depth)
    56   {
    57     super (handle);
    58 
    59     if (depth != 1 && depth != 24)
    60       throw new IllegalArgumentException ("Invalid depth specified"
    61                                           + " for pixmap: " + depth);
    62 
    63     switch (depth)
    64       {
    65       case 1:
    66         bitmap = Bitmap.createBitmap (colors, width, height,
    67                                       Bitmap.Config.ALPHA_8);
    68         break;
    69 
    70       case 24:
    71         bitmap = Bitmap.createBitmap (colors, width, height,
    72                                       Bitmap.Config.ARGB_8888);
    73         bitmap.setHasAlpha (false);
    74         break;
    75       }
    76 
    77     this.width = width;
    78     this.height = height;
    79     this.depth = depth;
    80   }
    81 
    82   public
    83   EmacsPixmap (short handle, int width, int height, int depth)
    84   {
    85     super (handle);
    86 
    87     if (depth != 1 && depth != 24)
    88       throw new IllegalArgumentException ("Invalid depth specified"
    89                                           + " for pixmap: " + depth);
    90 
    91     switch (depth)
    92       {
    93       case 1:
    94         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    95           bitmap = Bitmap.createBitmap (width, height,
    96                                         Bitmap.Config.ALPHA_8,
    97                                         false);
    98         else
    99           bitmap = Bitmap.createBitmap (width, height,
   100                                         Bitmap.Config.ALPHA_8);
   101         break;
   102 
   103       case 24:
   104 
   105         /* Emacs doesn't just use the first kind of `createBitmap'
   106            because the latter allows specifying that the pixmap is
   107            always opaque, which really increases efficiency.  */
   108         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
   109           bitmap = Bitmap.createBitmap (width, height,
   110                                         Bitmap.Config.ARGB_8888);
   111         else
   112           bitmap = Bitmap.createBitmap (width, height,
   113                                         Bitmap.Config.ARGB_8888,
   114                                         false);
   115         break;
   116       }
   117 
   118     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1)
   119       /* On these old versions of Android, Bitmap.recycle frees bitmap
   120          contents immediately.  */
   121       needCollect = false;
   122     else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
   123       needCollect = (bitmap.getByteCount ()
   124                      >= 1024 * 512);
   125     else
   126       needCollect = (bitmap.getAllocationByteCount ()
   127                      >= 1024 * 512);
   128 
   129     bitmap.eraseColor (0xff000000);
   130 
   131     this.width = width;
   132     this.height = height;
   133     this.depth = depth;
   134   }
   135 
   136   @Override
   137   public Canvas
   138   lockCanvas (EmacsGC gc)
   139   {
   140     int i;
   141 
   142     if (canvas == null)
   143       {
   144         canvas = new Canvas (bitmap);
   145         canvas.save ();
   146       }
   147 
   148     /* Now see if clipping has to be redone.  */
   149     if (gc.clipRectID == gcClipRectID)
   150       return canvas;
   151 
   152     /* It does have to be redone.  Reapply gc.real_clip_rects.  */
   153     canvas.restore ();
   154     canvas.save ();
   155 
   156     if (gc.real_clip_rects != null)
   157       {
   158         for (i = 0; i < gc.real_clip_rects.length; ++i)
   159           canvas.clipRect (gc.real_clip_rects[i]);
   160       }
   161 
   162     /* Save the clip rect ID again.  */
   163     gcClipRectID = gc.clipRectID;
   164     return canvas;
   165   }
   166 
   167   @Override
   168   public void
   169   damageRect (Rect damageRect)
   170   {
   171 
   172   }
   173 
   174   @Override
   175   public Bitmap
   176   getBitmap ()
   177   {
   178     return bitmap;
   179   }
   180 
   181   @Override
   182   public void
   183   destroyHandle ()
   184   {
   185     bitmap.recycle ();
   186     bitmap = null;
   187 
   188     /* Collect the bitmap storage if the bitmap is big.  */
   189     if (needCollect)
   190       Runtime.getRuntime ().gc ();
   191   }
   192 };

/* [<][>][^][v][top][bottom][index][help] */