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