/* 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) { int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font); /* Font's global height and ascent values might be preposterously large for some fonts. We fix here the case when those fonts are used for display of glyphless characters, because drawing background with font dimensions in those cases makes the display illegible. There's only one more call to the draw method with with_background set to true, and that's in x_draw_glyph_string_foreground, when drawing the cursor, where we have no such heuristics available. FIXME. */ if (s->first_glyph->type == GLYPHLESS_GLYPH && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)) height = ascent = s->first_glyph->slice.glyphless.lower_yoff - s->first_glyph->slice.glyphless.upper_yoff; BView_SetHighColor (view, s->hl == DRAW_CURSOR ? FRAME_CURSOR_COLOR (s->f).pixel : face->background); BView_FillRectangle (view, x, y - ascent, s->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, FT_LOAD_DEFAULT); else BView_FT_render_glyphs (info->face, &s->char2b[from], to - from, face->foreground, x, y, view, info->sc, FT_LOAD_DEFAULT); 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); }