From: Po Lu Date: Sun, 8 May 2022 03:08:42 +0000 (+0000) Subject: Implement bitmap loading for faces on Haiku X-Git-Tag: emacs-29.0.90~1910^2~919 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=faa342c794dec66d6b77ccf550361d58455a4454;p=emacs.git Implement bitmap loading for faces on Haiku Stipples don't completely work yet. * lisp/faces.el (face-valid-attribute-values): Enable `:stipple' on Haiku. * src/haiku_draw_support.cc (BView_DrawBitmap) (BView_DrawBitmapWithEraseOp, BView_DrawMask): Don't push and pop states. (BView_DrawBitmapTiled): New function. * src/haiku_support.cc (BBitmap_import_mono_bits): Delete function. * src/haiku_support.h: Update prototypes. * src/haikuterm.c (get_string_resource): Fix coding style. (haiku_get_bitmap, haiku_draw_stipple_background): Implement partially. (haiku_set_scroll_bar_default_width) (haiku_set_scroll_bar_default_height, haiku_scroll_bar_create) (haiku_set_horizontal_scroll_bar, haiku_set_vertical_scroll_bar) (haiku_create_terminal, haiku_scroll_bar_remove): Fix coding style. * src/image.c (image_create_bitmap_from_data) (image_create_bitmap_from_file): Implement on Haiku. --- diff --git a/lisp/faces.el b/lisp/faces.el index 12a386c8f63..395ea315bae 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1202,7 +1202,7 @@ an integer value." (:height 'integerp) (:stipple - (and (memq (window-system frame) '(x ns pgtk)) ; No stipple on w32 or haiku + (and (memq (window-system frame) '(x ns pgtk haiku)) ; No stipple on w32 (mapcar #'list (apply #'nconc (mapcar (lambda (dir) diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index a8d46d000a3..551af51d7c1 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -285,11 +285,32 @@ BView_DrawBitmap (void *view, void *bitmap, int x, int y, BView *vw = get_view (view); BBitmap *bm = (BBitmap *) bitmap; - vw->PushState (); vw->SetDrawingMode (B_OP_OVER); vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); - vw->PopState (); + vw->SetDrawingMode (B_OP_COPY); +} + +void +BView_DrawBitmapTiled (void *view, void *bitmap, int x, int y, + int width, int height, int vx, int vy, + int vwidth, int vheight) +{ + BView *vw = get_view (view); + BBitmap *bm = (BBitmap *) bitmap; + BRect bounds = bm->Bounds (); + + if (width == -1) + width = BE_RECT_WIDTH (bounds); + + if (height == -1) + height = BE_RECT_HEIGHT (bounds); + + vw->SetDrawingMode (B_OP_OVER); + vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), + BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1), + B_TILE_BITMAP); + vw->SetDrawingMode (B_OP_COPY); } void @@ -300,17 +321,22 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, BBitmap *bm = (BBitmap *) bitmap; BBitmap bc (bm->Bounds (), B_RGBA32); BRect rect (x, y, x + width - 1, y + height - 1); + uint32_t *bits; + size_t stride; + rgb_color low_color; + BRect bounds; if (bc.InitCheck () != B_OK || bc.ImportBits (bm) != B_OK) return; - uint32_t *bits = (uint32_t *) bc.Bits (); - size_t stride = bc.BytesPerRow (); + bits = (uint32_t *) bc.Bits (); + stride = bc.BytesPerRow (); if (bm->ColorSpace () == B_GRAY1) { - rgb_color low_color = vw->LowColor (); - BRect bounds = bc.Bounds (); + low_color = vw->LowColor (); + bounds = bc.Bounds (); + for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) { for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) @@ -323,10 +349,11 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, } } - vw->PushState (); - vw->SetDrawingMode (bm->ColorSpace () == B_GRAY1 ? B_OP_OVER : B_OP_ERASE); + vw->SetDrawingMode ((bm->ColorSpace () + == B_GRAY1) + ? B_OP_OVER : B_OP_ERASE); vw->DrawBitmap (&bc, rect); - vw->PopState (); + vw->SetDrawingMode (B_OP_COPY); } void @@ -357,6 +384,7 @@ BView_DrawMask (void *src, void *view, vw->SetDrawingMode (B_OP_OVER); vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1), BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); + vw->SetDrawingMode (B_OP_COPY); } static BBitmap * diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 5dfb25d6dd7..27a676dd31c 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -3599,17 +3599,6 @@ BBitmap_import_fringe_bitmap (void *bitmap, unsigned short *bits, int wd, int h) } } -void -BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h) -{ - BBitmap *bmp = (BBitmap *) bitmap; - - if (wd % 8) - wd += 8 - (wd % 8); - - bmp->ImportBits (bits, wd / 8 * h, wd / 8, 0, B_GRAY1); -} - /* Make a scrollbar at X, Y known to the view VIEW. */ void BView_publish_scroll_bar (void *view, int x, int y, int width, int height) diff --git a/src/haiku_support.h b/src/haiku_support.h index 5ded9300d8a..eaca7a9bad7 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -541,6 +541,8 @@ extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int, extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); extern void BView_DrawMask (void *, void *, int, int, int, int, int, int, int, int, uint32_t); +extern void BView_DrawBitmapTiled (void *, void *, int, int, + int, int, int, int, int, int); extern void BView_resize_to (void *, int, int); extern void BView_set_view_cursor (void *, void *); @@ -570,9 +572,7 @@ extern void BView_invalidate (void *); extern void BView_draw_lock (void *, bool, int, int, int, int); extern void BView_invalidate_region (void *, int, int, int, int); extern void BView_draw_unlock (void *); - extern void BBitmap_import_fringe_bitmap (void *, unsigned short *, int, int); -extern void BBitmap_import_mono_bits (void *, void *, int, int); extern void haiku_font_pattern_free (struct haiku_font_pattern *); diff --git a/src/haikuterm.c b/src/haikuterm.c index f08fe681871..46ea5f90277 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -122,7 +122,8 @@ haiku_delete_terminal (struct terminal *terminal) } static const char * -get_string_resource (void *ignored, const char *name, const char *class) +haiku_get_string_resource (void *ignored, const char *name, + const char *class) { const char *native; @@ -990,10 +991,28 @@ haiku_draw_plain_background (struct glyph_string *s, struct face *face, s->height - 2 * box_line_hwidth); } +static void * +haiku_get_bitmap (struct frame *f, ptrdiff_t id) +{ + return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].img; +} + static void haiku_draw_stipple_background (struct glyph_string *s, struct face *face, int box_line_hwidth, int box_line_vwidth) { + void *view; + + view = FRAME_HAIKU_VIEW (s->f); + BView_StartClip (view); + haiku_clip_to_string (s); + BView_ClipToRect (view, s->x, s->y + box_line_hwidth, + s->background_width, + s->height - 2 * box_line_hwidth); + BView_DrawBitmapTiled (view, haiku_get_bitmap (s->f, face->stipple), + 0, 0, -1, -1, 0, 0, FRAME_PIXEL_WIDTH (s->f), + FRAME_PIXEL_HEIGHT (s->f)); + BView_EndClip (view); } static void @@ -2079,19 +2098,25 @@ haiku_draw_vertical_window_border (struct window *w, static void haiku_set_scroll_bar_default_width (struct frame *f) { - int unit = FRAME_COLUMN_WIDTH (f); - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = BScrollBar_default_size (0) + 1; - FRAME_CONFIG_SCROLL_BAR_COLS (f) = - (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit; + int unit, size; + + unit = FRAME_COLUMN_WIDTH (f); + size = BScrollBar_default_size (0) + 1; + + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = size; + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (size + unit - 1) / unit; } static void haiku_set_scroll_bar_default_height (struct frame *f) { - int height = FRAME_LINE_HEIGHT (f); - FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = BScrollBar_default_size (1) + 1; - FRAME_CONFIG_SCROLL_BAR_LINES (f) = - (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height; + int height, size; + + height = FRAME_LINE_HEIGHT (f); + size = BScrollBar_default_size (true) + 1; + + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = size; + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (size + height - 1) / height; } static void @@ -2273,15 +2298,17 @@ static struct scroll_bar * haiku_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal_p) { - struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct frame *f; Lisp_Object barobj; + struct scroll_bar *bar; + void *scroll_bar; + void *view; - void *sb = NULL; - void *vw = FRAME_HAIKU_VIEW (f); + f = XFRAME (WINDOW_FRAME (w)); + view = FRAME_HAIKU_VIEW (f); block_input (); - struct scroll_bar *bar - = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); + bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); XSETWINDOW (bar->window, w); bar->top = top; @@ -2294,15 +2321,14 @@ haiku_scroll_bar_create (struct window *w, int left, int top, bar->update = -1; bar->horizontal = horizontal_p; - sb = BScrollBar_make_for_view (vw, horizontal_p, - left, top, left + width - 1, - top + height - 1, bar); - - BView_publish_scroll_bar (vw, left, top, width, height); + scroll_bar = BScrollBar_make_for_view (view, horizontal_p, + left, top, left + width - 1, + top + height - 1, bar); + BView_publish_scroll_bar (view, left, top, width, height); bar->next = FRAME_SCROLL_BARS (f); bar->prev = Qnil; - bar->scroll_bar = sb; + bar->scroll_bar = scroll_bar; XSETVECTOR (barobj, bar); fset_scroll_bars (f, barobj); @@ -2316,18 +2342,20 @@ haiku_scroll_bar_create (struct window *w, int left, int top, static void haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) { - eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)); Lisp_Object barobj; struct scroll_bar *bar; int top, height, left, width; int window_x, window_width; + void *view; + eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)); /* Get window dimensions. */ window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); left = window_x; width = window_width; top = WINDOW_SCROLL_BAR_AREA_Y (w); height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w); + view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); block_input (); @@ -2342,15 +2370,15 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p { bar = XSCROLL_BAR (w->horizontal_scroll_bar); - if (bar->left != left || bar->top != top || - bar->width != width || bar->height != height) + if (bar->left != left || bar->top != top + || bar->width != width || bar->height != height) { - void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height); BView_move_frame (bar->scroll_bar, left, top, left + width - 1, top + height - 1); BView_publish_scroll_bar (view, left, top, width, height); + bar->left = left; bar->top = top; bar->width = width; @@ -2367,14 +2395,15 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p } static void -haiku_set_vertical_scroll_bar (struct window *w, - int portion, int whole, int position) +haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position) { - eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); Lisp_Object barobj; struct scroll_bar *bar; int top, height, left, width; int window_y, window_height; + void *view; + + eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); /* Get window dimensions. */ window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); @@ -2384,8 +2413,10 @@ haiku_set_vertical_scroll_bar (struct window *w, /* Compute the left edge and the width of the scroll bar area. */ left = WINDOW_SCROLL_BAR_AREA_X (w); width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); - block_input (); + view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); + + block_input (); if (NILP (w->vertical_scroll_bar)) { bar = haiku_scroll_bar_create (w, left, top, width, height, false); @@ -2396,15 +2427,15 @@ haiku_set_vertical_scroll_bar (struct window *w, { bar = XSCROLL_BAR (w->vertical_scroll_bar); - if (bar->left != left || bar->top != top || - bar->width != width || bar->height != height) + if (bar->left != left || bar->top != top + || bar->width != width || bar->height != height) { - void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w)); BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height); BView_move_frame (bar->scroll_bar, left, top, left + width - 1, top + height - 1); BView_publish_scroll_bar (view, left, top, width, height); + bar->left = left; bar->top = top; bar->width = width; @@ -3880,7 +3911,7 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo) terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible; terminal->set_frame_offset_hook = haiku_set_offset; terminal->delete_terminal_hook = haiku_delete_terminal; - terminal->get_string_resource_hook = get_string_resource; + terminal->get_string_resource_hook = haiku_get_string_resource; terminal->set_new_font_hook = haiku_new_font; terminal->defined_color_hook = haiku_defined_color; terminal->set_window_size_hook = haiku_set_window_size; @@ -4089,9 +4120,15 @@ mark_haiku_display (void) void haiku_scroll_bar_remove (struct scroll_bar *bar) { + void *view; + struct frame *f; + + f = WINDOW_XFRAME (XWINDOW (bar->window)); + view = FRAME_HAIKU_VIEW (f); + block_input (); - void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (XWINDOW (bar->window))); - BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height); + BView_forget_scroll_bar (view, bar->left, bar->top, + bar->width, bar->height); BScrollBar_delete (bar->scroll_bar); expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)), bar->left, bar->top, bar->width, bar->height); @@ -4100,7 +4137,6 @@ haiku_scroll_bar_remove (struct scroll_bar *bar) wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); else wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); - unblock_input (); }; diff --git a/src/image.c b/src/image.c index e4b56e29cff..757e1250066 100644 --- a/src/image.c +++ b/src/image.c @@ -542,12 +542,22 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #endif /* HAVE_PGTK */ #ifdef HAVE_HAIKU - void *bitmap = BBitmap_new (width, height, 1); + void *bitmap; + int bytes_per_line, x, y; + + bitmap = BBitmap_new (width, height, 1); if (!bitmap) return -1; - BBitmap_import_mono_bits (bitmap, bits, width, height); + bytes_per_line = (width + 7) / 8; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + PUT_PIXEL (bitmap, x, y, (bits[8] >> (x % 8)) & 1); + bits += bytes_per_line; + } #endif id = image_allocate_bitmap_record (f); @@ -592,12 +602,19 @@ image_create_bitmap_from_data (struct frame *f, char *bits, return id; } +#ifdef HAVE_HAIKU +static char *slurp_file (int, ptrdiff_t *); +static Lisp_Object image_find_image_fd (Lisp_Object, int *); +static bool xbm_read_bitmap_data (struct frame *, char *, char *, + int *, int *, char **, bool); +#endif + /* Create bitmap from file FILE for frame F. */ ptrdiff_t image_create_bitmap_from_file (struct frame *f, Lisp_Object file) { -#if defined (HAVE_NTGUI) || defined (HAVE_HAIKU) +#if defined (HAVE_NTGUI) return -1; /* W32_TODO : bitmap support */ #else Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); @@ -610,7 +627,6 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) if (!bitmap) return -1; - id = image_allocate_bitmap_record (f); dpyinfo->bitmaps[id - 1].img = bitmap; dpyinfo->bitmaps[id - 1].refcount = 1; @@ -637,7 +653,6 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) dpyinfo->bitmaps[id - 1].img = bitmap; dpyinfo->bitmaps[id - 1].refcount = 1; dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); - //dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); dpyinfo->bitmaps[id - 1].pattern @@ -692,6 +707,63 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) return id; #endif /* HAVE_X_WINDOWS */ + +#ifdef HAVE_HAIKU + ptrdiff_t id, size; + int fd, width, height, rc, bytes_per_line, x, y; + char *contents, *data, *tmp; + void *bitmap; + + if (!STRINGP (image_find_image_fd (file, &fd))) + return -1; + + contents = slurp_file (fd, &size); + + if (!contents) + return -1; + + rc = xbm_read_bitmap_data (f, contents, contents + size, + &width, &height, &data, 0); + + if (!rc) + { + xfree (contents); + return -1; + } + + bitmap = BBitmap_new (width, height, 1); + + if (!bitmap) + { + xfree (contents); + xfree (data); + return -1; + } + + id = image_allocate_bitmap_record (f); + + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].depth = 1; + dpyinfo->bitmaps[id - 1].file = NULL; + dpyinfo->bitmaps[id - 1].height = height; + dpyinfo->bitmaps[id - 1].width = width; + dpyinfo->bitmaps[id - 1].refcount = 1; + + bytes_per_line = (width + 7) / 8; + tmp = data; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + PUT_PIXEL (bitmap, x, y, (tmp[x / 8] >> (x % 8)) & 1); + + tmp += bytes_per_line; + } + + xfree (contents); + xfree (data); + return id; +#endif } /* Free bitmap B. */