/* FreeType font driver for Haiku Copyright (C) 2021 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 . */ #include #include "blockinput.h" #include "haiku_support.h" #include "lisp.h" #include "dispextern.h" #include "font.h" #include "pdumper.h" #include "frame.h" #include "haikuterm.h" #include "termchar.h" #include "math.h" #include "ftfont.h" #ifdef HAVE_HARFBUZZ #include #include #endif static Lisp_Object ftbefont_list (struct frame *f, Lisp_Object spec) { return ftfont_list2 (f, spec, Qftbe); } static Lisp_Object ftbefont_match (struct frame *f, Lisp_Object spec) { return ftfont_match2 (f, spec, Qftbe); } #ifdef HAVE_HARFBUZZ static Lisp_Object ftbehbfont_list (struct frame *f, Lisp_Object spec) { return ftfont_list2 (f, spec, Qftbehb); } static Lisp_Object ftbehbfont_match (struct frame *f, Lisp_Object spec) { return ftfont_match2 (f, spec, Qftbehb); } #endif static int ftbefont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background) { struct frame *f = s->f; struct face *face = s->face; struct font_info *info = (struct font_info *) s->font; void *view = FRAME_HAIKU_VIEW (f); if (s->hl == DRAW_MOUSE_FACE) face = FACE_FROM_ID_OR_NULL (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); if (!face) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); block_input (); prepare_face_for_display (s->f, face); if (info->ft_size != info->face->size) FT_Activate_Size (info->ft_size); BView_draw_lock (view); BView_StartClip (view); if (with_background && !s->background_filled_p) { int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); int vx, vy, width, height; vx = s->x; vy = s->y; width = s->width; height = FONT_HEIGHT (face->font); if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) vx += max (s->face->box_vertical_line_width, 0); int mbox_line_width = max (s->face->box_vertical_line_width, 0); if (s->row->full_width_p) { if (vx <= fibw + 1 + mbox_line_width) { width += vx - mbox_line_width; vx = mbox_line_width; } if (FRAME_PIXEL_WIDTH (s->f) - (vx + width) <= fibw + 1) width += fibw; } if (s->face->box == FACE_NO_BOX) { /* Expand unboxed top row over internal border. */ if (vy <= fibw + 1 + mbox_line_width) { height += vy; vy = 0; } } else { int correction = abs (s->face->box_horizontal_line_width) + 1; vy += correction; height -= 2 * correction; correction = abs (s->face->box_vertical_line_width) + 1; vx += correction; width -= 2 * correction; } BView_SetHighColor (view, s->hl == DRAW_CURSOR ? FRAME_CURSOR_COLOR (s->f).pixel : face->background); BView_FillRectangle (view, vx, vy, width, height); s->background_filled_p = 1; } if (s->left_overhang && s->clip_head && !s->for_overlaps) { /* XXX: Why is this neccessary? */ BView_ClipToRect (view, s->clip_head->x, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); } if (s->hl == DRAW_CURSOR) BView_FT_render_glyphs (info->face, &s->char2b[from], to - from, FRAME_OUTPUT_DATA (s->f)->cursor_fg, x, y, view, info->sc); else BView_FT_render_glyphs (info->face, &s->char2b[from], to - from, face->foreground, x, y, view, info->sc); BView_EndClip (view); BView_draw_unlock (view); unblock_input (); return 0; } static Lisp_Object ftbefont_open (struct frame *f, Lisp_Object entity, int pixel_size) { Lisp_Object ft = ftfont_open (f, entity, pixel_size); if (FONT_OBJECT_P (ft)) { struct font_info *info = (struct font_info *) XFONT_OBJECT (ft); ASET (ft, FONT_TYPE_INDEX, Qftbe); info->font.driver = &ftbefont_driver; info->sc = be_make_ft_shape_cache (); } return ft; } #ifdef HAVE_HARFBUZZ static hb_font_t * ftbehbfont_begin_hb_font (struct font *font, double *position_unit) { struct font_info *ftfont_info = (struct font_info *) font; FT_Face ft_face = ftfont_info->face; ftfont_info->ft_size = ft_face->size; return fthbfont_begin_hb_font (font, position_unit); } static void ftbehbfont_end_hb_font (struct font *font, hb_font_t *hb_font) { struct font_info *ftfont_info = (struct font_info *) font; ftfont_info->ft_size = NULL; } static Lisp_Object ftbehbfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { Lisp_Object ft = ftfont_open (f, entity, pixel_size); if (FONT_OBJECT_P (ft)) { struct font_info *info = (struct font_info *) XFONT_OBJECT (ft); ASET (ft, FONT_TYPE_INDEX, Qftbehb); info->font.driver = &ftbehbfont_driver; info->sc = be_make_ft_shape_cache (); } return ft; } #endif static void ftbefont_close (struct font *font) { if (font_data_structures_may_be_ill_formed ()) return; be_free_ft_shape_cache (((struct font_info *) font)->sc); ftfont_close (font); } struct font_driver const ftbefont_driver = { .type = LISPSYM_INITIALLY (Qftbe), .get_cache = ftfont_get_cache, .list = ftbefont_list, .match = ftbefont_match, .draw = ftbefont_draw, .list_family = ftfont_list_family, .open_font = ftbefont_open, .close_font = ftbefont_close, .has_char = ftfont_has_char, .encode_char = ftfont_encode_char, .text_extents = ftfont_text_extents, .get_bitmap = ftfont_get_bitmap, .anchor_point = ftfont_anchor_point, #ifdef HAVE_LIBOTF .otf_capability = ftfont_otf_capability, #endif #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF .shape = ftfont_shape, #endif #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX .get_variation_glyphs = ftfont_variation_glyphs, #endif .filter_properties = ftfont_filter_properties, .combining_capability = ftfont_combining_capability }; #ifdef HAVE_HARFBUZZ struct font_driver ftbehbfont_driver; #endif static void syms_of_ftbefont_for_pdumper (void) { register_font_driver (&ftbefont_driver, NULL); #ifdef HAVE_HARFBUZZ ftbehbfont_driver = ftbefont_driver; ftbehbfont_driver.type = Qftbehb; ftbehbfont_driver.list = ftbehbfont_list; ftbehbfont_driver.match = ftbehbfont_match; ftbehbfont_driver.otf_capability = hbfont_otf_capability; ftbehbfont_driver.shape = hbfont_shape; ftbehbfont_driver.open_font = ftbehbfont_open; ftbehbfont_driver.combining_capability = hbfont_combining_capability; ftbehbfont_driver.begin_hb_font = ftbehbfont_begin_hb_font; ftbehbfont_driver.end_hb_font = ftbehbfont_end_hb_font; register_font_driver (&ftbehbfont_driver, NULL); #endif } void syms_of_ftbefont (void) { DEFSYM (Qftbe, "ftbe"); #ifdef HAVE_HARFBUZZ DEFSYM (Qftbehb, "ftbehb"); Fput (Qftbe, Qfont_driver_superseded_by, Qftbehb); #endif pdumper_do_now_and_after_load (syms_of_ftbefont_for_pdumper); }