unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
blob 0101c0372298a548533a2b805a9550a50706f1f6 6194 bytes (raw)
name: src/gtkimage.c 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
 
/* gtkimage.c -- Load images with GDK.
   Copyright (C) 2020 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/>.  */

#include "gtkimage.h"
#include "coding.h"
#include "blockinput.h"
#include "pgtkterm.h"

#include <gtk/gtk.h>
#include <cairo/cairo.h>


#ifdef USE_CAIRO
#define PUT_PIXEL image_pix_container_put_pixel
#define NO_PIXMAP 0

#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#endif

static Lisp_Object
image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found)
{
  Lisp_Object tail;

  eassert (valid_image_p (spec));

  for (tail = XCDR (spec);
       CONSP (tail) && CONSP (XCDR (tail));
       tail = XCDR (XCDR (tail)))
    {
      if (EQ (XCAR (tail), key))
	{
	  if (found)
	    *found = 1;
	  return XCAR (XCDR (tail));
	}
    }

  if (found)
    *found = 0;
  return Qnil;
}


static Emacs_Pix_Container
image_create_pix_container (struct frame *f, unsigned int width,
			    unsigned int height, unsigned int depth)
{
  Emacs_Pix_Container pimg;

  pimg = xmalloc (sizeof (*pimg));
  pimg->width = width;
  pimg->height = height;
  pimg->bits_per_pixel = depth == 1 ? 8 : 32;
  pimg->bytes_per_line = cairo_format_stride_for_width ((depth == 1
							 ? CAIRO_FORMAT_A8
							 : CAIRO_FORMAT_RGB24),
							width);
  pimg->data = xmalloc (pimg->bytes_per_line * height);

  return pimg;
}

typedef void Picture;

static bool
image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int depth,
				   Emacs_Pix_Container *pimg,
				   Emacs_Pixmap *pixmap, Picture *picture)
{
  eassert (input_blocked_p ());

  /* Allocate a pixmap of the same size.  */
  *pixmap = image_create_pix_container (f, width, height, depth);
  *pimg = *pixmap;
  return 1;
}

static bool
image_create_x_image_and_pixmap (struct frame *f, struct image *img,
				 int width, int height, int depth,
				 Emacs_Pix_Container *ximg, bool mask_p)
{
  eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP);

  Picture *picture = NULL;
  return image_create_x_image_and_pixmap_1 (f, width, height, depth, ximg,
					    !mask_p ? &img->pixmap : &img->mask,
					    picture);
}

static void
gimg_set_cr_source_with_color (cairo_t *cr, struct frame *f, unsigned long color)
{
  block_input ();
  Emacs_Color col;
  col.pixel = color;
  pgtk_query_color (f, &col);
  cairo_set_source_rgba (cr, col.red / 65535.0,
			 col.green / 65535.0,
			 col.blue / 65535.0, 1.0);
  unblock_input ();
}

static void
image_pix_container_put_pixel (Emacs_Pix_Container image,
			       int x, int y, unsigned long pixel)
{
  if (image->bits_per_pixel == 32)
    ((uint32_t *)(image->data + y * image->bytes_per_line))[x] = pixel;
  else
    ((uint8_t *)(image->data + y * image->bytes_per_line))[x] = pixel;
}

static unsigned long
lookup_rgb_color (struct frame *f, int r, int g, int b)
{
  return RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
}

bool
gdk_load (struct frame *f, struct image *img)
{
  block_input ();
  Lisp_Object specified_file;
  Lisp_Object specified_data;
  specified_file = image_spec_value (img->spec, QCfile, NULL);
  specified_data = image_spec_value (img->spec, QCdata, NULL);
  if (!STRINGP (specified_file))
    return false;
  specified_file = image_find_image_file (specified_file);
  if (!STRINGP (specified_file))
    return false;
  GError *error = NULL;
  GdkTexture *text;
  if (STRINGP (specified_file))
    text = gdk_texture_new_from_file (g_file_new_for_path (SSDATA (ENCODE_FILE (specified_file))),
				      &error);
  else if (STRINGP (specified_data))
    return false; // TODO!
  else
    return false;
  if (error)
    {
      g_error_free (error);
      return false;
    }
  Emacs_Pix_Context xpx = NULL;
  ptrdiff_t h = gdk_texture_get_height (text), w = gdk_texture_get_width (text);
  if (!image_create_x_image_and_pixmap (f, img, w, h, 0, &xpx, 0))
    {
      g_object_unref (text);
      return false;
    }
  cairo_surface_t *surface
    = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                  gdk_texture_get_width (text),
                                  gdk_texture_get_height (text));
  cairo_t *cr = cairo_create (surface);
  gimg_set_cr_source_with_color (cr, f, FRAME_BACKGROUND_COLOR (f));
  cairo_rectangle (cr, 0, 0, gdk_texture_get_width (text),
		   gdk_texture_get_height (text));
  cairo_paint (cr);
  cairo_surface_flush (surface);
  cairo_surface_t *vsuf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
						      gdk_texture_get_width (text),
						      gdk_texture_get_height (text));
  gdk_texture_download (text, cairo_image_surface_get_data (vsuf),
                        cairo_image_surface_get_stride (vsuf));
  cairo_surface_mark_dirty (vsuf);
  cairo_set_source_surface (cr, vsuf, 0, 0);
  cairo_paint (cr);
  cairo_surface_destroy (vsuf);
  cairo_destroy (cr);
  uint8_t *data = cairo_image_surface_get_data (surface);
  for (ptrdiff_t y = 0; y < h; ++y)
    {
      ptrdiff_t idx = w * y;
      for (ptrdiff_t x = 0; x < w; ++x)
        {
          struct
          {
#ifdef WORDS_BIGENDIAN
            uint8_t a, r, g, b;
#else
            uint8_t b, g, r, a;
#endif
          } cvals = *((typeof (cvals) *) data + idx + x);
          PUT_PIXEL (xpx, x, y,
                     lookup_rgb_color (f, 256 * cvals.r, 256 * cvals.g,
                                       256 * cvals.b));
        }
    }
  img->height = h;
  img->width = w;
  img->mask = NULL;
  IMAGE_BACKGROUND (img, f, (Emacs_Pix_Context) xpx);
  g_object_unref (text);
  cairo_surface_destroy (surface);
  unblock_input ();
  return true;
}

debug log:

solving 0101c03722 ...
found 0101c03722 in https://yhetil.org/emacs-devel/87zhaxjpea.fsf@yahoo.com/

applying [1/1] https://yhetil.org/emacs-devel/87zhaxjpea.fsf@yahoo.com/
diff --git a/src/gtkimage.c b/src/gtkimage.c
new file mode 100644
index 0000000000..0101c03722

Checking patch src/gtkimage.c...
Applied patch src/gtkimage.c cleanly.

index at:
100644 0101c0372298a548533a2b805a9550a50706f1f6	src/gtkimage.c

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).