x11: load icon differently

Now it's sourced from the etc/ PNG files directly, instead of
preprocessing them with imagemagick.

Add some ad-hoc code to decode PNG files with libavcodec. At least we
can drop the zlib code in exchange.
This commit is contained in:
wm4 2017-07-01 15:56:12 +02:00
parent aee81828e2
commit 9127939071
6 changed files with 111 additions and 99 deletions

View File

@ -1,15 +0,0 @@
#!/bin/sh
# This script is expected to be called as TOOLS/gen-x11-icon.sh (it will access
# etc/mpv-icon...), and it will write video/out/x11_icon.bin.
conv() {
echo
echo `identify -format "icon: %w %h" "$1"`
convert "$1" -depth 8 rgba:-
}
(echo "# File generated by gen-x11-icon.sh" ;
conv etc/mpv-icon-8bit-16x16.png ;
conv etc/mpv-icon-8bit-32x32.png ;
conv etc/mpv-icon-8bit-64x64.png) | gzip -c > video/out/x11_icon.bin

48
video/image_loader.c Normal file
View File

@ -0,0 +1,48 @@
#include <libavcodec/avcodec.h>
#include "common/common.h"
#include "mp_image.h"
#include "image_writer.h"
#include "image_loader.h"
struct mp_image *load_image_png_buf(void *buffer, size_t buffer_size, int imgfmt)
{
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_PNG);
if (!codec)
return NULL;
AVCodecContext *avctx = avcodec_alloc_context3(codec);
if (!avctx)
return NULL;
if (avcodec_open2(avctx, codec, NULL) < 0) {
avcodec_free_context(&avctx);
return NULL;
}
AVPacket *pkt = av_packet_alloc();
if (pkt) {
if (av_new_packet(pkt, buffer_size) >= 0)
memcpy(pkt->data, buffer, buffer_size);
}
// (There is only 1 outcome: either it takes it and decodes it, or not.)
avcodec_send_packet(avctx, pkt);
avcodec_send_packet(avctx, NULL);
av_packet_free(&pkt);
struct mp_image *res = NULL;
AVFrame *frame = av_frame_alloc();
if (frame && avcodec_receive_frame(avctx, frame) >= 0) {
struct mp_image *r = mp_image_from_av_frame(frame);
if (r)
res = convert_image(r, imgfmt, mp_null_log);
talloc_free(r);
}
av_frame_free(&frame);
avcodec_free_context(&avctx);
return res;
}

9
video/image_loader.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef MP_IMAGE_LOADER_H_
#define MP_IMAGE_LOADER_H_
#include <stddef.h>
struct mp_image;
struct mp_image *load_image_png_buf(void *buffer, size_t buffer_size, int imgfmt);
#endif

View File

@ -38,8 +38,6 @@
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xrandr.h>
#include <zlib.h>
#include "config.h"
#include "misc/bstr.h"
#include "options/options.h"
@ -48,6 +46,8 @@
#include "common/msg.h"
#include "input/input.h"
#include "input/event.h"
#include "video/image_loader.h"
#include "video/mp_image.h"
#include "x11_common.h"
#include "mpv_talloc.h"
@ -57,9 +57,6 @@
#include "osdep/timer.h"
#include "osdep/subprocess.h"
// Specifically for mp_cancel
#include "stream/stream.h"
#include "input/input.h"
#include "input/keycodes.h"
@ -109,10 +106,26 @@ typedef struct
long state;
} MotifWmHints;
static const char x11_icon[] =
#include "video/out/x11_icon.inc"
static const char x11_icon_16[] =
#include "video/out/x11_icon_16.inc"
;
static const char x11_icon_32[] =
#include "video/out/x11_icon_32.inc"
;
static const char x11_icon_64[] =
#include "video/out/x11_icon_64.inc"
;
#define ICON_ENTRY(var) { (char *)var, sizeof(var) }
static const struct bstr x11_icons[] = {
ICON_ENTRY(x11_icon_16),
ICON_ENTRY(x11_icon_32),
ICON_ENTRY(x11_icon_64),
{0}
};
static struct mp_log *x11_error_output;
static atomic_int x11_error_silence;
@ -1318,92 +1331,36 @@ static void vo_x11_xembed_send_message(struct vo_x11_state *x11, long m[4])
XSendEvent(x11->display, x11->parent, False, NoEventMask, &ev);
}
static bstr decompress_gz(bstr in)
{
bstr res = {0};
z_stream zstream;
uint8_t *dest;
size_t size = in.len;
int result;
zstream.zalloc = (alloc_func) 0;
zstream.zfree = (free_func) 0;
zstream.opaque = (voidpf) 0;
// 32 for gzip header, 15 for max. window bits
if (inflateInit2(&zstream, 32 + 15) != Z_OK)
goto error;
zstream.next_in = (Bytef *) in.start;
zstream.avail_in = size;
dest = NULL;
zstream.avail_out = size;
do {
size += 4000;
dest = talloc_realloc_size(NULL, dest, size);
zstream.next_out = (Bytef *) (dest + zstream.total_out);
result = inflate(&zstream, Z_NO_FLUSH);
if (result != Z_OK && result != Z_STREAM_END) {
talloc_free(dest);
dest = NULL;
inflateEnd(&zstream);
goto error;
}
zstream.avail_out += 4000;
} while (zstream.avail_out == 4000 && zstream.avail_in != 0
&& result != Z_STREAM_END);
size = zstream.total_out;
inflateEnd(&zstream);
res.start = dest;
res.len = size;
error:
return res;
}
#define MAX_ICONS 10
static void vo_x11_set_wm_icon(struct vo_x11_state *x11)
{
int num_icons = 0;
void *icon_data[MAX_ICONS];
int icon_w[MAX_ICONS], icon_h[MAX_ICONS];
int icon_size = 0;
long *icon = talloc_array(NULL, long, 0);
bstr uncompressed = decompress_gz((bstr){(char *)x11_icon, sizeof(x11_icon)});
bstr data = uncompressed;
while (data.len && num_icons < MAX_ICONS) {
bstr line = bstr_getline(data, &data);
if (bstr_eatstart0(&line, "icon: ")) {
int w, h;
if (bstr_sscanf(line, "%d %d", &w, &h) == 2) {
int size = w * h * 4;
icon_w[num_icons] = w;
icon_h[num_icons] = h;
icon_data[num_icons] = data.start;
num_icons++;
data = bstr_cut(data, size);
for (int n = 0; x11_icons[n].start; n++) {
struct mp_image *img =
load_image_png_buf(x11_icons[n].start, x11_icons[n].len, IMGFMT_RGBA);
if (!img)
continue;
int new_size = 2 + img->w * img->h;
MP_RESIZE_ARRAY(NULL, icon, icon_size + new_size);
long *cur = icon + icon_size;
icon_size += new_size;
*cur++ = img->w;
*cur++ = img->h;
for (int y = 0; y < img->h; y++) {
uint8_t *s = (uint8_t *)img->planes[0] + img->stride[0] * y;
for (int x = 0; x < img->w; x++) {
*cur++ = s[x * 4 + 0] | (s[x * 4 + 1] << 8) |
(s[x * 4 + 2] << 16) | ((unsigned)s[x * 4 + 3] << 24);
}
}
}
int icon_size = 0;
for (int n = 0; n < num_icons; n++)
icon_size += 2 + icon_w[n] * icon_h[n];
long *icon = talloc_array(NULL, long, icon_size);
long *cur = icon;
for (int n = 0; n < num_icons; n++) {
*cur++ = icon_w[n];
*cur++ = icon_h[n];
uint8_t *s = icon_data[n];
for (int i = 0; i < icon_h[n] * icon_w[n]; i++, s += 4)
*cur++ = s[0] | (s[1] << 8) | (s[2] << 16) | ((unsigned)s[3] << 24);
talloc_free(img);
}
XChangeProperty(x11->display, x11->window, XA(x11, _NET_WM_ICON),
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)icon, icon_size);
talloc_free(icon);
talloc_free(uncompressed.start);
}
static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis,

Binary file not shown.

View File

@ -59,8 +59,20 @@ def build(ctx):
ctx(
features = "file2string",
source = "video/out/x11_icon.bin",
target = "video/out/x11_icon.inc",
source = "etc/mpv-icon-8bit-16x16.png",
target = "video/out/x11_icon_16.inc",
)
ctx(
features = "file2string",
source = "etc/mpv-icon-8bit-32x32.png",
target = "video/out/x11_icon_32.inc",
)
ctx(
features = "file2string",
source = "etc/mpv-icon-8bit-64x64.png",
target = "video/out/x11_icon_64.inc",
)
ctx(
@ -315,6 +327,7 @@ def build(ctx):
( "video/csputils.c" ),
( "video/fmt-conversion.c" ),
( "video/gpu_memcpy.c", "sse4-intrinsics" ),
( "video/image_loader.c" ),
( "video/image_writer.c" ),
( "video/img_format.c" ),
( "video/hwdec.c" ),