[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemacs-commit] qemacs display.c display.h fractal.c haiku.cpp ...
From: |
Charlie Gordon |
Subject: |
[Qemacs-commit] qemacs display.c display.h fractal.c haiku.cpp ... |
Date: |
Mon, 15 May 2017 05:44:22 -0400 (EDT) |
CVSROOT: /sources/qemacs
Module name: qemacs
Changes by: Charlie Gordon <chqrlie> 17/05/15 05:44:21
Modified files:
. : display.c display.h fractal.c haiku.cpp
html2png.c tty.c win32.c x11.c
Log message:
graphics: add device and generic picture display functions
- add bitmap formats for 4BPP and BGR combinations
- add color palette in QEPicture
- add xfactor and yfactor in QEDisplay for preferred pixel granularity
yfactor is typically 2 for text mode display
- add dpy_draw_picture() device function
- add bitmap drawing functions:
qe_create_picture(int width, int height, QEBitmapFormat format, int
flags);
int qe_picture_lock(QEPicture *ip);
void qe_picture_unlock(QEPicture *ip);
qe_free_picture(QEPicture **ipp);
QE_PAL_MODE(r, g, b, incr)
int qe_picture_set_palette(QEPicture *ip, int mode,
unsigned char *p, int count, int tcolor);
int qe_picture_copy(QEPicture *dst, int dst_x, int dst_y, int
dst_w, int dst_h,
const QEPicture *src, int src_x, int src_y, int
src_w, int src_h,
int flags);
int qe_draw_picture(QEditScreen *s, int dst_x, int dst_y, int
dst_w, int dst_h,
const QEPicture *ip,
int src_x, int src_y, int src_w, int src_h,
int flags, QEColor col);
- add 3 compile time selectable image interfaces in flactal.c benchmark
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/display.c?cvsroot=qemacs&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/qemacs/display.h?cvsroot=qemacs&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/qemacs/fractal.c?cvsroot=qemacs&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/qemacs/haiku.cpp?cvsroot=qemacs&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/qemacs/html2png.c?cvsroot=qemacs&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/qemacs/tty.c?cvsroot=qemacs&r1=1.86&r2=1.87
http://cvs.savannah.gnu.org/viewcvs/qemacs/win32.c?cvsroot=qemacs&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/qemacs/x11.c?cvsroot=qemacs&r1=1.54&r2=1.55
Patches:
Index: display.c
===================================================================
RCS file: /sources/qemacs/qemacs/display.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- display.c 3 May 2017 12:58:23 -0000 1.23
+++ display.c 15 May 2017 09:44:21 -0000 1.24
@@ -97,7 +97,7 @@
}
static QEDisplay const dummy_dpy = {
- "dummy",
+ "dummy", 1, 1,
NULL, /* dpy_probe */
dummy_dpy_init,
dummy_dpy_close,
@@ -120,6 +120,7 @@
NULL, /* dpy_bmp_draw */
NULL, /* dpy_bmp_lock */
NULL, /* dpy_bmp_unlock */
+ NULL, /* dpy_draw_picture */
NULL, /* dpy_full_screen */
NULL, /* dpy_describe */
NULL, /* next */
@@ -422,3 +423,447 @@
if (h2) fill_rectangle(s->screen, x0 + w1, y0 + h0 - h2, w0 - w1 - w2, h2,
color);
}
+/*---------------- QEPicture handling functions ----------------*/
+
+int qe_draw_picture(QEditScreen *s, int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *ip,
+ int src_x, int src_y, int src_w, int src_h,
+ int flags, QEColor col)
+{
+#ifndef CONFIG_TINY
+ int x1 = dst_x;
+ int y1 = dst_y;
+ int x2 = x1 + dst_w;
+ int y2 = y1 + dst_h;
+ int w1, h1;
+
+ /* quick clip rejection */
+ if (x2 <= s->clip_x1 || y2 <= s->clip_y1 ||
+ x1 >= s->clip_x2 || y1 >= s->clip_y2)
+ return 1;
+
+ /* region update */
+ if (x2 > s->clip_x2)
+ x2 = s->clip_x2;
+ if (y2 > s->clip_y2)
+ y2 = s->clip_y2;
+ if (x1 < s->clip_x1)
+ x1 = s->clip_x1;
+ if (y1 < s->clip_y1)
+ y1 = s->clip_y1;
+
+ /* rejection if zero size */
+ w1 = x2 - x1;
+ h1 = y2 - y1;
+ if (w1 < 0 || h1 < 0)
+ return 1;
+
+ if (w1 != dst_w) {
+ int dx = min((x1 - dst_x) * src_w / dst_w, src_w - 1);
+ src_x += dx;
+ src_w = clamp(src_w * w1 / dst_w, 1, src_w - dx);
+ }
+ if (h1 != dst_h) {
+ int dy = min((y1 - dst_y) * src_h / dst_h, src_h - 1);
+ src_y += dy;
+ src_h = clamp(src_h * h1 / dst_h, 1, src_h - dy);
+ }
+
+ if (s->dpy.dpy_draw_picture &&
+ !s->dpy.dpy_draw_picture(s, x1, y1, w1, h1,
+ ip, src_x, src_y, src_w, src_h, flags)) {
+ return 0;
+ } else {
+ if (col != COLOR_TRANSPARENT) {
+ /* if image cannot be displayed, just draw a rectangle */
+ fill_rectangle(s, x1, y1, w1, h1, col);
+ }
+ return 2;
+ }
+#else
+ return 1;
+#endif
+}
+
+#ifndef CONFIG_TINY
+static int qe_picture_format_bits(QEBitmapFormat format) {
+ switch (format) {
+ case QEBITMAP_FORMAT_1BIT:
+ return 1;
+ case QEBITMAP_FORMAT_4BIT:
+ return 4;
+ case QEBITMAP_FORMAT_8BIT:
+ return 8;
+ case QEBITMAP_FORMAT_RGB565:
+ case QEBITMAP_FORMAT_RGB555:
+ return 16;
+ case QEBITMAP_FORMAT_RGB24:
+ case QEBITMAP_FORMAT_BGR24:
+ return 24;
+ case QEBITMAP_FORMAT_RGBA32:
+ case QEBITMAP_FORMAT_BGRA32:
+ return 32;
+ case QEBITMAP_FORMAT_YUV420P:
+ /* unsupported for now */
+ default:
+ return 0;
+ }
+}
+
+QEPicture *qe_create_picture(int width, int height,
+ QEBitmapFormat format, int flags)
+{
+ QEPicture *ip;
+ unsigned int bits;
+
+ bits = qe_picture_format_bits(format);
+ if (bits <= 0)
+ return NULL;
+
+ ip = qe_mallocz(QEPicture);
+ if (ip) {
+ /* align pixmap lines on 64 bit boundaries */
+ unsigned int wb = width * bits + 63 / 64 * 8;
+ ip->width = width;
+ ip->height = height;
+ ip->format = format;
+ ip->data[0] = qe_malloc_array(unsigned char, wb * height);
+ ip->linesize[0] = wb;
+ }
+ return ip;
+}
+
+void qe_free_picture(QEPicture **ipp) {
+ if (*ipp) {
+ qe_free(&(*ipp)->data[0]);
+ qe_free(ipp);
+ }
+}
+
+int qe_picture_set_palette(QEPicture *ip, int mode,
+ unsigned char *p, int count, int tcolor)
+{
+ int i, r, g, b, incr;
+
+ if (!ip)
+ return 1;
+
+ if (mode == 0)
+ mode = QE_PAL_QECOLOR;
+
+ incr = mode & 15;
+ b = (mode >> 4) & 15;
+ g = (mode >> 8) & 15;
+ r = (mode >> 12) & 15;
+
+ ip->tcolor = tcolor;
+ if (ip->palette_size != 256) {
+ qe_free(&ip->palette);
+ ip->palette_size = 256;
+ ip->palette = qe_malloc_array(QEColor, 256);
+ if (ip->palette == NULL) {
+ ip->palette_size = 0;
+ return -1;
+ }
+ /* Default colors to standard palette */
+ memcpy(ip->palette, xterm_colors, 256 * sizeof(*ip->palette));
+ }
+ count = min(count, 256);
+ for (i = 0; i < count; i++) {
+ ip->palette[i] = QERGB(p[r], p[g], p[b]);
+ p += incr;
+ }
+ return 0;
+}
+
+static int qe_picture_scale(QEPicture *to, int dst_x, int dst_y, int dst_w,
int dst_h,
+ const QEPicture *from,
+ int src_x, int src_y, int src_w, int src_h, int
flags)
+{
+ if (from->format != to->format)
+ return 1;
+
+ if (from->format != QEBITMAP_FORMAT_RGBA32
+ && from->format != QEBITMAP_FORMAT_BGRA32)
+ return 1;
+
+#if 0
+ /* Bilinear interpolation */
+ uint32_t w = src_w, h = src_h, w2 = dst_w, h2 = dst_h;
+ uint32_t x_ratio = ((w - 1) << 16) / w2;
+ uint32_t y_ratio = ((h - 1) << 16) / h2;
+ uint32_t pitch = from->linesize[0];
+ uint32_t pitch2 = to->linesize[0];
+ uint32_t y = 0;
+ for (uint32_t i = 0; i < h2; i++, y += y_ratio) {
+ uint32_t yr = y >> 16;
+ uint32_t y_diff = y & 0xFFFF;
+ const uint8_t *src = from->data[0] + (src_y + yr) * pitch + src_x * 4;
+ uint8_t *dst = to->data[0] + (dst_y + i) * pitch2 + dst_x * 4;
+ uint32_t x = 0;
+ for (uint32_t j = 0; j < w2; j++, x += x_ratio) {
+ uint32_t xr = x >> 16;
+ uint32_t x_diff = x & 0xFFFF;
+ uint32_t m0 = (0x10000 - x_diff) * (0x10000 - y_diff);
+ uint32_t m1 = x_diff * (0x10000 - y_diff);
+ uint32_t m2 = (0x10000 - x_diff) * y_diff;
+ uint32_t m3 = x_diff * y_diff;
+
+ for (int k = 0; k < 3; k++) {
+ uint32_t v = (src[xr * 4 + k + 0] * (int64_t)m0 +
+ src[xr * 4 + k + 4] * (int64_t)m1 +
+ src[xr * 4 + k + pitch + 0] * (int64_t)m2 +
+ src[xr * 4 + k + pitch + 4] * (int64_t)m3) >> 32;
+ dst[j * 4 + k] = (uint8_t)v;
+ }
+ }
+ }
+#else
+ int x, y, sx, sy, sx0, sy0, dx, dy, width = dst_w, height = dst_h;
+
+ /* Nearest-neighbor interpolation */
+ dx = dy = sx0 = sy0 = 0;
+ if (dst_w > 1) {
+ if (dst_w > src_w) {
+ dx = src_w * 0x10000 / dst_w;
+ } else {
+ dx = (src_w - 1) * 0x10000 / (dst_w - 1);
+ sx0 = 0x8000;
+ }
+ }
+ if (dst_h > 1) {
+ if (dst_h > src_h) {
+ dy = src_h * 0x10000 / dst_h;
+ } else {
+ dy = (src_h - 1) * 0x10000 / (dst_h - 1);
+ sy0 = 0x8000;
+ }
+ }
+ for (y = 0, sy = sy0; y < height; y++, sy += dy) {
+ const uint32_t *src = (const uint32_t *)(void *)(from->data[0] +
+ (src_y + (sy >> 16))
* from->linesize[0]) + src_x;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+
+ for (x = 0, sx = sx0; x < width; x++, sx += dx) {
+ /* XXX: No filtering */
+ dst[x + 0] = src[sx >> 16];
+ }
+ }
+#endif
+ return 0;
+}
+
+int qe_picture_copy(QEPicture *to, int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *from,
+ int src_x, int src_y, int src_w, int src_h, int flags)
+{
+ const uint32_t *palette;
+ int x, y, width = src_w, height = src_h;
+ int res = 0;
+
+ if (src_w != dst_w || src_h != dst_h) {
+ /* Generic scaling */
+ QEPicture *ip1 = NULL;
+
+ if (from->format != QEBITMAP_FORMAT_RGBA32) {
+ ip1 = qe_create_picture(src_w, src_h, QEBITMAP_FORMAT_RGBA32, 0);
+ if (!ip1)
+ return -1;
+ res = qe_picture_copy(ip1, 0, 0, src_w, src_h,
+ from, src_x, src_y, src_w, src_h, 0);
+ from = ip1;
+ src_x = src_y = 0;
+ }
+ if (!res) {
+ res = qe_picture_scale(to, dst_x, dst_y, dst_w, dst_h,
+ from, src_x, src_y, src_w, src_h, flags);
+ }
+ qe_free_picture(&ip1);
+ return res;
+ }
+
+ if (from->format == QEBITMAP_FORMAT_8BIT && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ palette = from->palette;
+ if (palette == NULL) {
+ palette = xterm_colors;
+ }
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + src_x;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int w4 = width & ~3;
+
+ for (x = 0; x < w4; x += 4) {
+ dst[x + 0] = palette[src[x + 0]];
+ dst[x + 1] = palette[src[x + 1]];
+ dst[x + 2] = palette[src[x + 2]];
+ dst[x + 3] = palette[src[x + 3]];
+ }
+ for (; x < width; x++) {
+ dst[x] = palette[src[x]];
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_4BIT && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ palette = from->palette;
+ if (palette == NULL) {
+ palette = xterm_colors;
+ }
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + (src_x >> 1);
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int shift, w4;
+
+ x = 0;
+ if (src_x & 1) {
+ /* Convert incomplete left block */
+ dst[x] = palette[*src++ & 15];
+ x++;
+ }
+ /* Convert middle block */
+ w4 = x + ((width - x) & ~3);
+ for (x = 0; x < w4; x += 4, src += 2) {
+ dst[x + 0] = palette[src[0] >> 4];
+ dst[x + 1] = palette[src[0] & 15];
+ dst[x + 2] = palette[src[1] >> 4];
+ dst[x + 3] = palette[src[1] & 15];
+ }
+ /* Convert right block */
+ shift = 4;
+ for (; x < width; x++) {
+ dst[x] = palette[(src[0] >> shift) & 15];
+ src += (shift ^= 4) >> 2;
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_1BIT && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ QEColor bw[2] = { QERGB(0, 0, 0), QERGB(0xff, 0xff, 0xff) };
+
+ palette = from->palette;
+ if (palette == NULL) {
+ palette = bw;
+ }
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + (src_x >> 3);
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int bits, shift, w8;
+
+ x = 0;
+ if (src_x & 7) {
+ /* Convert incomplete left block */
+ bits = *src++;
+ shift = 8 - (src_x & 7);
+ for (; x < width && shift != 0; x++) {
+ dst[x] = palette[(bits >> --shift) & 1];
+ }
+ }
+ /* Convert middle block */
+ w8 = x + ((width - x) & ~7);
+ for (; x < w8; x += 8) {
+ bits = *src++;
+ dst[x + 0] = palette[(bits >> 7) & 1];
+ dst[x + 1] = palette[(bits >> 6) & 1];
+ dst[x + 2] = palette[(bits >> 5) & 1];
+ dst[x + 3] = palette[(bits >> 4) & 1];
+ dst[x + 4] = palette[(bits >> 3) & 1];
+ dst[x + 5] = palette[(bits >> 2) & 1];
+ dst[x + 6] = palette[(bits >> 1) & 1];
+ dst[x + 7] = palette[(bits >> 0) & 1];
+ }
+ if (x < width) {
+ /* Convert incomplete right block */
+ bits = *src;
+ shift = 8;
+ for (; x < width; x++) {
+ dst[x] = palette[(bits >> --shift) & 1];
+ }
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_RGB565 && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ /* XXX: deal with endianness */
+ for (y = 0; y < height; y++) {
+ const uint16_t *src = (const uint16_t *)(void *)(from->data[0] +
(src_y + y) * from->linesize[0]) + src_x;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ for (x = 0; x < width; x++, src++) {
+ unsigned int r = (src[0] >> 8) & 0xF8;
+ unsigned int g = (src[0] >> 3) & 0xFC;
+ unsigned int b = (src[0] << 3) & 0xF8;
+ dst[x] = QERGB(r | (r >> 5), g | (g >> 6), b | (b >> 5));
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_RGB555 && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ /* XXX: deal with endianness */
+ for (y = 0; y < height; y++) {
+ const uint16_t *src = (const uint16_t *)(void *)(from->data[0] +
(src_y + y) * from->linesize[0]) + src_x;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ for (x = 0; x < width; x++, src++) {
+ unsigned int r = (src[0] >> 7) & 0xF8;
+ unsigned int g = (src[0] >> 2) & 0xF8;
+ unsigned int b = (src[0] << 3) & 0xF8;
+ dst[x] = QERGB(r | (r >> 5), g | (g >> 5), b | (b >> 5));
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_RGB24 && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + src_x * 3;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int w4 = width & ~3;
+
+ for (x = 0; x < w4; x += 4, src += 12) {
+ dst[x + 0] = QERGB(src[0], src[1], src[2]);
+ dst[x + 1] = QERGB(src[3], src[4], src[5]);
+ dst[x + 2] = QERGB(src[6], src[7], src[8]);
+ dst[x + 3] = QERGB(src[9], src[10], src[11]);
+ }
+ for (; x < width; x++, src += 3) {
+ dst[x] = QERGB(src[0], src[1], src[2]);
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_BGR24 && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + src_x * 3;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int w4 = width & ~3;
+
+ for (x = 0; x < w4; x += 4, src += 12) {
+ dst[x + 0] = QERGB(src[2], src[1], src[0]);
+ dst[x + 1] = QERGB(src[5], src[4], src[3]);
+ dst[x + 2] = QERGB(src[8], src[7], src[6]);
+ dst[x + 3] = QERGB(src[11], src[10], src[9]);
+ }
+ for (; x < width; x++, src += 3) {
+ dst[x] = QERGB(src[2], src[1], src[0]);
+ }
+ }
+ return 0;
+ }
+ if (from->format == QEBITMAP_FORMAT_BGRA32 && to->format ==
QEBITMAP_FORMAT_RGBA32) {
+ for (y = 0; y < height; y++) {
+ const unsigned char *src = from->data[0] + (src_y + y) *
from->linesize[0] + src_x * 4;
+ uint32_t *dst = (uint32_t *)(void *)(to->data[0] + (dst_y + y) *
to->linesize[0]) + dst_x;
+ int w4 = width & ~3;
+
+ for (x = 0; x < w4; x += 4, src += 16) {
+ dst[x + 0] = QERGB(src[0], src[1], src[2]);
+ dst[x + 1] = QERGB(src[4], src[5], src[6]);
+ dst[x + 2] = QERGB(src[8], src[9], src[10]);
+ dst[x + 3] = QERGB(src[12], src[13], src[14]);
+ }
+ for (; x < width; x++, src += 4) {
+ dst[x] = QERGB(src[0], src[1], src[2]);
+ }
+ }
+ return 0;
+ }
+ return 1;
+}
+#endif /* !CONFIG_TINY */
Index: display.h
===================================================================
RCS file: /sources/qemacs/qemacs/display.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- display.h 5 May 2017 20:07:52 -0000 1.23
+++ display.h 15 May 2017 09:44:21 -0000 1.24
@@ -64,11 +64,14 @@
typedef enum QEBitmapFormat {
QEBITMAP_FORMAT_1BIT = 0,
+ QEBITMAP_FORMAT_4BIT,
QEBITMAP_FORMAT_8BIT,
QEBITMAP_FORMAT_RGB565,
QEBITMAP_FORMAT_RGB555,
QEBITMAP_FORMAT_RGB24,
+ QEBITMAP_FORMAT_BGR24,
QEBITMAP_FORMAT_RGBA32,
+ QEBITMAP_FORMAT_BGRA32,
QEBITMAP_FORMAT_YUV420P,
} QEBitmapFormat;
@@ -93,6 +96,9 @@
QEBitmapFormat format;
unsigned char *data[4];
int linesize[4];
+ QEColor *palette;
+ int palette_size;
+ int tcolor;
} QEPicture;
typedef struct QEditScreen QEditScreen;
@@ -100,6 +106,7 @@
struct QEDisplay {
const char *name;
+ int xfactor, yfactor;
int (*dpy_probe)(void);
int (*dpy_init)(QEditScreen *s, int w, int h);
void (*dpy_close)(QEditScreen *s);
@@ -135,6 +142,11 @@
void (*dpy_bmp_lock)(QEditScreen *s, QEBitmap *bitmap, QEPicture *pict,
int x1, int y1, int w1, int h1);
void (*dpy_bmp_unlock)(QEditScreen *s, QEBitmap *b);
+ int (*dpy_draw_picture)(QEditScreen *s,
+ int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *ip,
+ int src_x, int src_y, int src_w, int src_h,
+ int flags);
void (*dpy_full_screen)(QEditScreen *s, int full_screen);
void (*dpy_describe)(QEditScreen *s, EditBuffer *b);
QEDisplay *next;
@@ -285,4 +297,27 @@
font->refcount--;
}
+QEPicture *qe_create_picture(int width, int height,
+ QEBitmapFormat format, int flags);
+static inline int qe_picture_lock(QEPicture *ip) { return ip == NULL; }
+static inline void qe_picture_unlock(QEPicture *ip) {}
+void qe_free_picture(QEPicture **ipp);
+
+#define QE_PAL_MODE(r, g, b, incr) (((r) << 12) | ((g) << 8) | ((b) << 4) |
(incr))
+#define QE_PAL_RGB3 QE_PAL_MODE(0, 1, 2, 3)
+#define QE_PAL_RGB4 QE_PAL_MODE(0, 1, 2, 4)
+#define QE_PAL_BGR3 QE_PAL_MODE(2, 1, 0, 3)
+#define QE_PAL_BGR4 QE_PAL_MODE(2, 1, 0, 4)
+#define QE_PAL_QECOLOR QE_PAL_MODE(2, 1, 0, 4) /* XXX: depends on
endianness */
+int qe_picture_set_palette(QEPicture *ip, int mode,
+ unsigned char *p, int count, int tcolor);
+
+int qe_picture_copy(QEPicture *dst, int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *src, int src_x, int src_y, int src_w, int
src_h,
+ int flags);
+
+int qe_draw_picture(QEditScreen *s, int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *ip,
+ int src_x, int src_y, int src_w, int src_h,
+ int flags, QEColor col);
#endif
Index: fractal.c
===================================================================
RCS file: /sources/qemacs/qemacs/fractal.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- fractal.c 8 May 2017 10:47:23 -0000 1.5
+++ fractal.c 15 May 2017 09:44:21 -0000 1.6
@@ -309,7 +309,8 @@
/*---------------- Interactive fractal explorer ----------------*/
-#define USE_BITMAP_API 1 /* Using device bitmap API */
+#define USE_BITMAP_API 0 /* Using device bitmap API */
+#define USE_DRAW_PICTURE 1 /* Using qe_draw_picture() */
static ModeDef fractal_mode;
@@ -328,7 +329,7 @@
struct FractalState {
QEModeData base;
- int cols, rows; /* fractal size in pixels */
+ int width, height; /* fractal size in pixels */
int type; /* fractal type 0..8 */
int maxiter; /* maximum iteration number */
int cb, nc; /* color palette base and length */
@@ -338,11 +339,13 @@
fnum_t bailout; /* maximum squared module (default 4.0) */
fnum_t x, y; /* center position */
fnum_t m0, m1, m2, m3; /* rotation matrix */
- int hfactor; /* vertical pixel granularity */
int shift; /* color animation base */
QEColor colors[256]; /* color palette */
QEditScreen *screen; /* for bmp_free() */
QEBitmap *disp_bmp; /* device image */
+#if USE_DRAW_PICTURE
+ QEPicture *ip;
+#endif
};
const char fractal_default_parameters[] = {
@@ -508,7 +511,7 @@
/* This will force fractal image recomputation */
/* XXX: color changes should not cause recomputation
if the fractal is computed as a paletted image */
- ms->cols = ms->rows = 0;
+ ms->width = ms->height = 0;
}
static void fractal_set_rotation(FractalState *ms, int rot) {
@@ -566,11 +569,11 @@
if (p) {
if (strmatchword(p, "gray256", pp)) {
int c;
- for (c = 0; c < 256; c++) {
- ms->colors[c] = QERGB(c, c, c);
+ for (c = 1; c < 256; c++) {
+ ms->colors[256 - c] = QERGB(c, c, c);
}
- ms->cb = 0;
- ms->nc = 256;
+ ms->cb = 1;
+ ms->nc = 255;
} else
if (strmatchword(p, "gray", pp)) {
ms->cb = 232;
@@ -619,7 +622,7 @@
{
const char *p;
- ms->cols = ms->rows = 0; /* force refresh */
+ ms->width = ms->height = 0; /* force redraw */
for (p = parms;;) {
p += strspn(p, ";, \t\r\n");
@@ -670,7 +673,7 @@
static void do_fractal_draw(EditState *s, FractalState *ms)
{
#if USE_BITMAP_API
- int cols = ms->cols, rows = ms->rows;
+ int width = ms->width, height = ms->height;
int maxiter = ms->maxiter + ms->zoom, nc = ms->nc;
int i, nx, ny, shift;
fnum_t x, y, dx, dy;
@@ -680,33 +683,29 @@
uint32_t *palette32 = NULL;
QEPicture pict;
- if (s->height == 0 || s->width == 0 || rows == 0 || cols == 0 || nc == 0)
+ if (s->width == 0 || s->height == 0 || width == 0 || height == 0 || nc ==
0)
return;
if (s->width == s->cols) {
- /* character based, assume 80x25 4/3 aspect ratio */
- /* XXX: get subsampling and aspect ratio from window or screen */
- ms->hfactor = 2;
- rows *= ms->hfactor;
- dx = 3.2 * ms->scale / cols;
+ /* character based, assume 80x25 4/3 aspect ratio, 2 pixels per char */
+ dx = 3.2 * ms->scale / width;
dy = dx * 1.2;
} else {
/* pixel based, assume 100% pixel aspect ratio */
- ms->hfactor = 1;
- cols = s->width;
- rows = s->height;
- dy = dx = 3.2 * ms->scale / cols;
+ dy = dx = 3.2 * ms->scale / width;
}
- if (ms->disp_bmp == NULL || ms->disp_bmp->width != cols ||
ms->disp_bmp->height != rows) {
+ if (ms->disp_bmp == NULL
+ || ms->disp_bmp->width != width
+ || ms->disp_bmp->height != height) {
bmp_free(ms->screen, &ms->disp_bmp);
/* create the displayed bitmap and put the image in it */
ms->screen = s->screen;
- ms->disp_bmp = bmp_alloc(ms->screen, cols, rows, 0);
+ ms->disp_bmp = bmp_alloc(ms->screen, width, height, 0);
}
if (!ms->disp_bmp)
return;
- bmp_lock(ms->screen, ms->disp_bmp, &pict, 0, 0, cols, rows);
+ bmp_lock(ms->screen, ms->disp_bmp, &pict, 0, 0, width, height);
/* Compute shifted palette */
shift = nc + ms->shift % nc; /* 0 < shift < 2 * nc */
@@ -724,10 +723,10 @@
}
/* Compute fractal bitmap */
- for (ny = 0, y = -dy * rows / 2; ny < rows; ny++, y += dy) {
+ for (ny = 0, y = -dy * height / 2; ny < height; ny++, y += dy) {
if (pict.format == QEBITMAP_FORMAT_8BIT) {
unsigned char *pb = pict.data[0] + ny * pict.linesize[0];
- for (nx = 0, x = -dx * cols / 2; nx < cols; nx++, x += dx) {
+ for (nx = 0, x = -dx * width / 2; nx < width; nx++, x += dx) {
fnum_t xr = ms->x + x * ms->m0 + y * ms->m1;
fnum_t yr = ms->y + x * ms->m2 + y * ms->m3;
pb[nx] = palette8[(*func)(xr, yr, ms->bailout, maxiter)];
@@ -735,7 +734,7 @@
} else
if (pict.format == QEBITMAP_FORMAT_RGBA32) {
uint32_t *pb = (uint32_t *)(void*)(pict.data[0] + ny *
pict.linesize[0]);
- for (nx = 0, x = -dx * cols / 2; nx < cols; nx++, x += dx) {
+ for (nx = 0, x = -dx * width / 2; nx < width; nx++, x += dx) {
fnum_t xr = ms->x + x * ms->m0 + y * ms->m1;
fnum_t yr = ms->y + x * ms->m2 + y * ms->m3;
pb[nx] = palette32[(*func)(xr, yr, ms->bailout, maxiter)];
@@ -746,8 +745,46 @@
qe_free(&palette8);
qe_free(&palette32);
edit_invalidate(s, 1);
+#elif USE_DRAW_PICTURE
+ int width = ms->width, height = ms->height, zoom = ms->zoom;
+ int maxiter = ms->maxiter + zoom, cb = ms->cb, nc = ms->nc;
+ int i, nx, ny;
+ fnum_t xc = ms->x, yc = ms->y, scale = ms->scale;
+ fnum_t bailout = ms->bailout;
+ fnum_t x, y, dx, dy, xr, yr;
+ int (*func)(fnum_t x, fnum_t y, fnum_t bailout, int maxiter) =
+ fractal_type[ms->type].func;
+
+ if (s->width == 0 || s->height == 0 || width == 0 || height == 0 || nc ==
0)
+ return;
+
+ if (s->width == s->cols) {
+ /* character based, assume 80x25 4/3 aspect ratio, 2 pixels per char */
+ dx = 3.2 * scale / width;
+ dy = dx * 1.2;
+ } else {
+ /* pixel based, assume 100% pixel aspect ratio */
+ dy = dx = 3.2 * scale / width;
+ }
+ if (ms->ip == NULL || ms->ip->width != width || ms->ip->height != height) {
+ qe_free_picture(&ms->ip);
+ ms->ip = qe_create_picture(width, height, QEBITMAP_FORMAT_8BIT, 0);
+ }
+ if (!ms->ip)
+ return;
+
+ for (ny = 0, y = -dy * height / 2; ny < height; ny++, y += dy) {
+ unsigned char *pb = ms->ip->data[0] + ny * ms->ip->linesize[0];
+ for (nx = 0, x = -dx * width / 2; nx < width; nx++, x += dx) {
+ xr = xc + x * ms->m0 + y * ms->m1;
+ yr = yc + x * ms->m2 + y * ms->m3;
+ i = (*func)(xr, yr, bailout, maxiter);
+ pb[nx] = (i >= maxiter) ? 0 : cb + i % nc;
+ }
+ }
+ edit_invalidate(s, 1);
#else
- int cols = ms->cols, rows = ms->rows;
+ int width = ms->width, height = ms->height / 2;
int maxiter = ms->maxiter + ms->zoom, nc = ms->nc;
int i, nx, ny, fg, bg, shift;
fnum_t x, y, dx, dy;
@@ -755,17 +792,16 @@
fractal_type[ms->type].func;
unsigned char *palette8 = NULL;
- if (s->height == 0 || s->width == 0 || rows == 0 || cols == 0 || nc == 0)
+ if (s->width == 0 || s->height == 0 || width == 0 || height == 0 || nc ==
0)
return;
- ms->hfactor = 2;
- dx = 3.2 * ms->scale / cols;
+ dx = 3.2 * ms->scale / width;
if (s->width == s->cols) {
- /* character based, assume 80x25 4/3 aspect ratio */
+ /* character based, assume 80x25 4/3 aspect ratio, 2 pixels per char */
dy = dx * 2.4;
} else {
/* pixel based, assume 100% pixel aspect ratio */
- dy = dx * cols / s->width * s->height / rows;
+ dy = dx * width / s->width * s->height / height;
}
/* Compute shifted palette */
@@ -779,8 +815,8 @@
eb_delete_range(s->b, 0, s->b->total_size);
- for (ny = 0, y = -dy * rows / 2; ny < rows; ny++, y += dy) {
- for (nx = 0, x = -dx * cols / 2; nx < cols; nx++, x += dx) {
+ for (ny = 0, y = -dy * height / 2; ny < height; ny++, y += dy) {
+ for (nx = 0, x = -dx * width / 2; nx < width; nx++, x += dx) {
fnum_t xr = ms->x + x * ms->m0 + y * ms->m1;
fnum_t yr = ms->y + x * ms->m2 + y * ms->m3;
bg = palette8[(*func)(xr, yr, ms->bailout, maxiter)];
@@ -801,12 +837,12 @@
#if USE_BITMAP_API
static void fractal_display(EditState *s) {
FractalState *ms = fractal_get_state(s, 0);
- int col = QERGB(0, 0, 0);
+ QEColor col = qe_styles[QE_STYLE_GUTTER].bg_color;
if (s->display_invalid) {
- if (ms && ms->disp_bmp && ms->hfactor) {
+ if (ms && ms->disp_bmp) {
int w = min(s->width, ms->disp_bmp->width);
- int h = min(s->height, ms->disp_bmp->height / ms->hfactor);
+ int h = min(s->height, ms->disp_bmp->height /
s->screen->dpy.yfactor);
int x = (s->width - w) / 2;
int y = (s->height - h) / 2;
@@ -834,6 +870,52 @@
}
#endif
+#if USE_DRAW_PICTURE
+static void fractal_display(EditState *s) {
+ FractalState *ms = fractal_get_state(s, 0);
+ QEColor col = qe_styles[QE_STYLE_GUTTER].bg_color;
+
+ if (s->display_invalid) {
+ if (ms && ms->ip) {
+ int w = min(s->width, ms->ip->width);
+ int h = min(s->height, ms->ip->height / s->screen->dpy.yfactor);
+ int x0 = (s->width - w) / 2;
+ int y0 = (s->height - h) / 2;
+ uint32_t palette[256];
+ int c;
+
+ palette[0] = ms->colors[0];
+ for (c = 1; c < 256; c++) {
+ palette[c] = ms->colors[(c + ms->shift) & 255];
+ }
+ ms->ip->palette = palette;
+ ms->ip->palette_size = 256;
+ qe_draw_picture(s->screen, s->xleft + x0, s->ytop + y0, w, h,
+ ms->ip, 0, 0, w, h * s->screen->dpy.yfactor,
+ 0, QERGB(128, 128, 128));
+ ms->ip->palette = NULL;
+ fill_border(s, x0, y0, w, h, col);
+ } else {
+ fill_rectangle(s->screen, s->xleft, s->ytop, s->width, s->height,
col);
+ }
+ s->display_invalid = 0;
+ }
+ if (s->qe_state->active_window == s) {
+ /* Update cursor */
+ int xc = s->xleft;
+ int yc = s->ytop;
+ int w = s->char_width;
+ int h = s->line_height;
+ if (s->screen->dpy.dpy_cursor_at) {
+ /* hardware cursor */
+ s->screen->dpy.dpy_cursor_at(s->screen, xc, yc, w, h);
+ } else {
+ xor_rectangle(s->screen, xc, yc, w, h, QERGB(0xFF, 0xFF, 0xFF));
+ }
+ }
+}
+#endif
+
static void do_fractal_move(EditState *s, int deltax, int deltay) {
FractalState *ms = fractal_get_state(s, 1);
if (ms) {
@@ -871,7 +953,11 @@
FractalState *ms = fractal_get_state(s, 1);
if (ms) {
ms->shift += delta;
+#if USE_BITMAP_API
fractal_invalidate(ms);
+#else
+ edit_invalidate(s, 1);
+#endif
}
}
@@ -885,7 +971,11 @@
if (type == 1) {
fractal_set_colors(ms, "gray", NULL);
}
+#if USE_BITMAP_API
fractal_invalidate(ms);
+#else
+ edit_invalidate(s, 1);
+#endif
}
}
@@ -942,7 +1032,7 @@
eb_printf(b, "%*s: %s\n", w, "formula", fractal_type[ms->type].formula);
eb_printf(b, "%*s: "MFT"\n", w, "x", ms->x);
eb_printf(b, "%*s: "MFT"\n", w, "y", ms->y);
- eb_printf(b, "%*s: %dx%d\n", w, "size", ms->cols, ms->rows * ms->hfactor);
+ eb_printf(b, "%*s: %dx%d\n", w, "size", ms->width, ms->height);
eb_printf(b, "%*s: %d\n", w, "zoom", ms->zoom);
eb_printf(b, "%*s: %.6g\n", w, "scale", (double)ms->scale);
eb_printf(b, "%*s: %d\n", w, "rot", ms->rot);
@@ -975,12 +1065,19 @@
static void fractal_display_hook(EditState *s) {
FractalState *ms = fractal_get_state(s, 0);
if (ms) {
+#if USE_BITMAP_API || USE_DRAW_PICTURE
+ int width = s->width;
+ int height = s->height * s->screen->dpy.yfactor;
+#else
+ int width = s->cols;
+ int height = s->rows * 2;
+#endif
if (s->xleft == 0 && s->ytop == 0
- && (s->rows != ms->rows || s->cols != ms->cols)) {
+ && (ms->height != height || ms->width != width)) {
/* XXX: should use a separate thread for this */
/* XXX: should use a different bitmap for each window */
- ms->cols = s->cols;
- ms->rows = s->rows;
+ ms->width = width;
+ ms->height = height;
do_fractal_draw(s, ms);
}
}
@@ -1059,6 +1156,12 @@
bmp_free(ms->screen, &ms->disp_bmp);
#endif
+#if USE_DRAW_PICTURE
+ FractalState *ms = state;
+
+ /* free bitmap and palette */
+ qe_free_picture(&ms->ip);
+#endif
}
static void do_mandelbrot_test(EditState *s) {
@@ -1075,7 +1178,7 @@
fractal_mode.mode_free = fractal_mode_free;
fractal_mode.display_hook = fractal_display_hook;
fractal_mode.default_wrap = WRAP_TRUNCATE;
-#if USE_BITMAP_API
+#if USE_BITMAP_API || USE_DRAW_PICTURE
fractal_mode.display = fractal_display;
#endif
qe_register_mode(&fractal_mode, MODEF_NOCMD | MODEF_VIEW);
Index: haiku.cpp
===================================================================
RCS file: /sources/qemacs/qemacs/haiku.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- haiku.cpp 18 Apr 2017 09:14:55 -0000 1.18
+++ haiku.cpp 15 May 2017 09:44:21 -0000 1.19
@@ -864,7 +864,7 @@
}
static QEDisplay haiku_dpy = {
- "haiku",
+ "haiku", 1, 1,
haiku_probe,
haiku_init,
haiku_close,
@@ -886,6 +886,7 @@
NULL, /* dpy_bmp_draw */
NULL, /* dpy_bmp_lock */
NULL, /* dpy_bmp_unlock */
+ NULL, /* dpy_draw_picture */
haiku_full_screen,
NULL, /* dpy_describe */
NULL, /* next */
Index: html2png.c
===================================================================
RCS file: /sources/qemacs/qemacs/html2png.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- html2png.c 18 Apr 2017 09:14:55 -0000 1.20
+++ html2png.c 15 May 2017 09:44:21 -0000 1.21
@@ -108,7 +108,7 @@
static void ppm_close(QEditScreen *s);
static QEDisplay ppm_dpy = {
- "ppm",
+ "ppm", 1, 1,
NULL,
ppm_init,
ppm_close,
@@ -130,6 +130,7 @@
NULL, /* dpy_bmp_draw */
NULL, /* dpy_bmp_lock */
NULL, /* dpy_bmp_unlock */
+ NULL, /* dpy_draw_picture */
NULL, /* dpy_full_screen */
NULL, /* dpy_describe */
NULL, /* next */
Index: tty.c
===================================================================
RCS file: /sources/qemacs/qemacs/tty.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -b -r1.86 -r1.87
--- tty.c 7 May 2017 06:18:40 -0000 1.86
+++ tty.c 15 May 2017 09:44:21 -0000 1.87
@@ -39,6 +39,8 @@
#define TTY_STYLE_BITS 32
#define TTY_FG_COLORS 7936
#define TTY_BG_COLORS 7936
+#define TTY_RGB_FG(r,g,b) (0x1000 | (((r) & 0xF0) << 4) | ((g) & 0xF0) |
((b) >> 4))
+#define TTY_RGB_BG(r,g,b) (0x1000 | (((r) & 0xF0) << 4) | ((g) & 0xF0) |
((b) >> 4))
#define TTY_CHAR(ch,fg,bg) ((uint32_t)(ch) | ((uint64_t)((fg) | ((bg) <<
17)) << 32))
#define TTY_CHAR2(ch,col) ((uint32_t)(ch) | ((uint64_t)(col) << 32))
#define TTY_CHAR_GET_CH(cc) ((uint32_t)(cc))
@@ -61,6 +63,8 @@
#define TTY_STYLE_BITS 16
#define TTY_FG_COLORS 256
#define TTY_BG_COLORS 16
+#define TTY_RGB_FG(r,g,b) (16 + ((r) / 51 * 36) + ((g) / 51 * 6) | ((b) /
51))
+#define TTY_RGB_BG(r,g,b) qe_map_color(QERGB(r, g, b), xterm_colors, 16,
NULL)
#define TTY_CHAR(ch,fg,bg) ((uint32_t)(ch) | ((uint32_t)((fg) | ((bg) <<
12)) << 16))
#define TTY_CHAR2(ch,col) ((uint32_t)(ch) | ((uint32_t)(col) << 16))
#define TTY_CHAR_GET_CH(cc) ((cc) & 0xFFFF)
@@ -1430,13 +1434,91 @@
}
}
+#ifdef CONFIG_TINY
+#define tty_dpy_draw_picture NULL
+#else
+static int tty_dpy_draw_picture(QEditScreen *s,
+ int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *ip0,
+ int src_x, int src_y, int src_w, int src_h,
+ int flags)
+{
+ TTYState *ts = s->priv_data;
+ TTYChar *ptr;
+ int x, y;
+ const QEPicture *ip = ip0;
+ QEPicture *ip1 = NULL;
+
+ if ((src_w == dst_w && src_h == 2 * dst_h)
+ && ip->format == QEBITMAP_FORMAT_8BIT
+ && ip->palette
+ && ip->palette_size == 256
+ && !memcmp(ip->palette, xterm_colors, 256 * sizeof(*ip->palette))) {
+ /* Handle 8-bit picture with direct terminal colors */
+ ptr = ts->screen + dst_y * s->width + dst_x;
+ for (y = 0; y < dst_h; y++) {
+ unsigned char *p1 = ip->data[0] + (src_y + y * 2) *
ip->linesize[0] + src_x;
+ unsigned char *p2 = p1 + ip->linesize[0];
+ ts->line_updated[dst_y + y] = 1;
+ for (x = 0; x < dst_w; x++) {
+ int bg = p1[x];
+ int fg = p2[x];
+ if (fg == bg)
+ ptr[x] = TTY_CHAR(' ', fg, bg);
+ else
+ ptr[x] = TTY_CHAR(0x2584, fg, bg);
+ }
+ ptr += s->width;
+ }
+ } else {
+ /* Convert picture to true color bitmap */
+ if (ip->format != QEBITMAP_FORMAT_RGBA32
+ || !(src_w == dst_w && src_h == 2 * dst_h)) {
+ ip1 = qe_create_picture(dst_w, 2 * dst_h, QEBITMAP_FORMAT_RGBA32,
0);
+ if (!ip1)
+ return -1;
+ if (qe_picture_copy(ip1, 0, 0, ip1->width, ip1->height,
+ ip0, src_x, src_y, src_w, src_h, flags)) {
+ /* unsupported conversion or scaling */
+ qe_free_picture(&ip1);
+ return -1;
+ }
+ ip = ip1;
+ src_x = src_y = 0;
+ src_w = ip1->width;
+ src_h = ip1->height;
+ }
+ /* Use terminal true color emulation */
+ ptr = ts->screen + dst_y * s->width + dst_x;
+ for (y = 0; y < dst_h; y++) {
+ uint32_t *p1 = (uint32_t*)(void*)(ip->data[0] + (src_y + y * 2) *
ip->linesize[0]) + src_x;
+ uint32_t *p2 = p1 + (ip->linesize[0] >> 2);
+ ts->line_updated[dst_y + y] = 1;
+ for (x = 0; x < dst_w; x++) {
+ int bg = p1[x];
+ int fg = p2[x];
+ bg = TTY_RGB_BG(QERGB_RED(bg), QERGB_GREEN(bg),
QERGB_BLUE(bg));
+ fg = TTY_RGB_FG(QERGB_RED(fg), QERGB_GREEN(fg),
QERGB_BLUE(fg));
+ if (fg == bg)
+ ptr[x] = TTY_CHAR(' ', fg, bg);
+ else
+ ptr[x] = TTY_CHAR(0x2584, fg, bg);
+ }
+ ptr += s->width;
+ }
+ qe_free_picture(&ip1);
+ }
+ return 0;
+}
+#endif
+
static void tty_dpy_describe(QEditScreen *s, EditBuffer *b)
{
comb_cache_describe(s, b);
}
static QEDisplay tty_dpy = {
- "vt100",
+ "vt100", 1, 2,
tty_dpy_probe,
tty_dpy_init,
tty_dpy_close,
@@ -1458,6 +1540,7 @@
tty_dpy_bmp_draw,
tty_dpy_bmp_lock,
tty_dpy_bmp_unlock,
+ tty_dpy_draw_picture,
NULL, /* dpy_full_screen */
tty_dpy_describe,
NULL, /* next */
Index: win32.c
===================================================================
RCS file: /sources/qemacs/qemacs/win32.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- win32.c 18 Apr 2017 09:14:55 -0000 1.19
+++ win32.c 15 May 2017 09:44:21 -0000 1.20
@@ -511,7 +511,7 @@
}
static QEDisplay win32_dpy = {
- "win32",
+ "win32", 1, 1,
win_probe,
win_init,
win_close,
@@ -533,6 +533,7 @@
NULL, /* dpy_bmp_draw */
NULL, /* dpy_bmp_lock */
NULL, /* dpy_bmp_unlock */
+ NULL, /* dpy_draw_picture */
NULL, /* dpy_full_screen */
NULL, /* dpy_describe */
NULL, /* next */
Index: x11.c
===================================================================
RCS file: /sources/qemacs/qemacs/x11.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -b -r1.54 -r1.55
--- x11.c 5 May 2017 20:05:35 -0000 1.54
+++ x11.c 15 May 2017 09:44:21 -0000 1.55
@@ -1059,6 +1059,7 @@
r++;
}
#endif
+ /* XXX: update cursor? */
XFlush(xs->display);
#ifdef CONFIG_DOUBLE_BUFFER
update_reset(xs);
@@ -1895,8 +1896,72 @@
}
}
+static int x11_dpy_draw_picture(QEditScreen *s,
+ int dst_x, int dst_y, int dst_w, int dst_h,
+ const QEPicture *ip0,
+ int src_x, int src_y, int src_w, int src_h,
+ int flags)
+{
+ X11State *xs = s->priv_data;
+ XImage *im;
+ int status = 0, depth;
+ const QEPicture *ip = ip0;
+ QEPicture *ip1 = NULL;
+
+ /* Only support 32-bit true color X11 displays */
+ /* XXX: should enumerate visuals? */
+ depth = DefaultDepth(xs->display, xs->xscreen);
+ if (depth != 24)
+ return 1;
+
+ if (ip->format != QEBITMAP_FORMAT_RGBA32
+ || !(src_w == dst_w && src_h == dst_h)) {
+ ip1 = qe_create_picture(dst_w, dst_h, QEBITMAP_FORMAT_RGBA32, 0);
+ if (!ip1)
+ return 2;
+ /* Convert and/or resize picture */
+ if (qe_picture_copy(ip1, 0, 0, dst_w, dst_h,
+ ip0, src_x, src_y, src_w, src_h, flags)) {
+ qe_free_picture(&ip1);
+ return 3;
+ }
+ ip = ip1;
+ src_x = src_y = 0;
+ src_w = dst_w;
+ src_h = dst_h;
+ }
+
+ im = XCreateImage(xs->display, xs->attr.visual, depth, ZPixmap, 0,
+ NULL, dst_w, dst_h, 32, ip->linesize[0] / 4);
+ if (im == NULL) {
+ qe_free_picture(&ip1);
+ return 4;
+ }
+ if (im->bits_per_pixel != 32) {
+ XDestroyImage(im);
+ qe_free_picture(&ip1);
+ return 5;
+ }
+
+ if (ip->format == QEBITMAP_FORMAT_RGBA32) {
+ im->data = (char *)(ip->data[0] + src_y * ip->linesize[0] + src_x * 4);
+ im->bytes_per_line = ip->linesize[0];
+ update_rect(xs, dst_x, dst_y, dst_x + dst_w, dst_y + dst_h);
+ status = XPutImage(xs->display, xs->dbuffer, xs->gc, im,
+ 0, 0, dst_x, dst_y, dst_w, dst_h);
+ XFlush(xs->display);
+ } else {
+ status = 6;
+ }
+
+ im->data = NULL;
+ XDestroyImage(im);
+ qe_free_picture(&ip1);
+ return status;
+}
+
static QEDisplay x11_dpy = {
- "x11",
+ "x11", 1, 1,
x11_dpy_probe,
x11_dpy_init,
x11_dpy_close,
@@ -1918,6 +1983,7 @@
x11_dpy_bmp_draw,
x11_dpy_bmp_lock,
x11_dpy_bmp_unlock,
+ x11_dpy_draw_picture,
x11_dpy_full_screen,
NULL, /* dpy_describe */
NULL, /* next */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemacs-commit] qemacs display.c display.h fractal.c haiku.cpp ...,
Charlie Gordon <=