/* 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);
}