summaryrefslogtreecommitdiff
path: root/src/ftcrfont.c
diff options
context:
space:
mode:
authorJan D <jan.h.d@swipnet.se>2015-02-11 16:14:35 +0100
committerJan D <jan.h.d@swipnet.se>2015-02-11 16:14:35 +0100
commitdddcc0e78452f2186c132823a33a174d2596ba33 (patch)
tree8369d54925d9ea4b60ecf6a53c6a321dffd194f9 /src/ftcrfont.c
parent061c7e2b5a5a5854b2b85f2ace5b1d9222dd7f11 (diff)
downloademacs-dddcc0e78452f2186c132823a33a174d2596ba33.tar.gz
Add cairo drawing.
* configure.ac (with-cairo): New option. (USE_CAIRO): Default to yes for Gtk+ 3. Add code to test for cairo, set CAIRO_CFLAGS, CAIRO_LIBS. Add ftcrfonto to FONT_OBJ if cairo. Output "Does Emacs use cairo?". * lisp/version.el (emacs-version): Add cairo version. * src/Makefile.in (CAIRO_CFLAGS, CAIRO_LIBS): New variables. (FONT_OBJ): Add comment about ftcrfont. (ALL_CFLAGS): Add CAIRO_CFLAGS. (LIBES): Add CAIRO_LIBS. * src/dispextern.h (struct image): Add cr_data for cairo. (x_cr_init_fringe): Declare. * src/font.c (syms_of_font): Call syms_of_ftcrfont for cairo. * src/font.h (ftcrfont_driver, syms_of_ftcrfont): Declare * src/fringe.c (x_cr_init_fringe): New function name that shares code with w32_init_fringe. * src/ftcrfont.c: New font driver for cairo, based on the ftfont driver. * src/ftfont.c (ftfont_info_size); New global variable. (ftfont_open2): New extern function almost the same as old ftfont_open, but takes the font_object as argument. (ftfont_open): Build font object and call ftfont_open2. * src/ftfont.h (ftfont_open2, ftfont_info_size): Declare. * src/gtkutil.c (xg_clear_under_internal_border) (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Only queue_draw if not cairo. Change args to x_clear_area. (xg_get_font): Use Qftcr when using cairo, Qxft otherwise. (xg_page_setup_dialog, xg_get_page_setup, draw_page) (xg_print_frames_dialog): New functions for printing. * src/gtkutil.h (xg_page_setup_dialog, xg_get_page_setup) (xg_print_frames_dialog): Declare. * src/image.c: Add defined (USE_CAIRO) for PNG. Add !defined USE_CAIRO for W32 PNG code. (x_clear_image): If cairo, destroy the surface in cr_data. (png_load): Add new cairo compatible implementation. (lookup_image_type): Add defined (USE_CAIRO) for define png_type. * src/xfns.c: New section Printing. (x-export-frames, x-page-setup-dialog, x-get-page-setup) (x-print-frames-dialog): New printing functions. (Fx_create_frame, x_create_tip_frame): Register ftcrfont if cairo. (syms_of_xfns): Defsym Qorientation, Qtop_margin, Qbottom_margin, Qportrait, Qlandscape, Qreverse_portrait, Qreverse_landscape). (syms_of_xfns): Provide cairo and defvar cairo-version-string. defsubr Sx_page_setup_dialog, Sx_get_page_setup, Sx_print_frames_dialog. * src/xterm.c (x_clear_area1, x_prepare_for_xlibdraw) (x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle) (x_draw_rectangle, x_fill_trapezoid_for_relief, x_clear_window) (x_gc_get_ext_data, x_extension_initialize, x_cr_accumulate_data): Declare. (FRAME_CR_CONTEXT, FRAME_CR_SURFACE): New macros. (max_fringe_bmp, fringe_bmp): New variables. (x_gc_get_ext_data, x_extension_initialize) (x_cr_destroy_surface, x_begin_cr_clip, x_end_cr_clip) (x_set_cr_source_with_gc_foreground) (x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap) (x_cr_destroy_fringe_bitmap, x_cr_draw_image, x_cr_draw_frame) (x_cr_accumulate_data, x_cr_destroy, x_cr_export_frames) (x_prepare_for_xlibdraw, x_set_clip_rectangles) (x_reset_clip_rectangles, x_fill_rectangle, x_draw_rectangle) (x_clear_window, x_fill_trapezoid_for_relief): New functions. (x_update_begin): Create cairo surface if needed. (x_draw_vertical_window_border): Call x_fill_rectangle for cairo. (x_update_end): Paint cairo drawing surface to xlib surface. (x_clear_under_internal_border, x_after_update_window_line): Adjust arguments to x_clear_area. (x_draw_fringe_bitmap): Call x_fill_rectangle. Get GC values and call x_cr_draw_image for cairo. Call x_reset_clip_rectangles instead of XSetClipMask. (x_set_glyph_string_clipping) (x_set_glyph_string_clipping_exactly): Use x_set_clip_rectangles instead of XSetClipRectangles. (x_clear_glyph_string_rect, x_draw_glyph_string_background): Use x_fill_rectangle instead of XFillRectangle. (x_draw_glyph_string_foreground) (x_draw_composite_glyph_string_foreground) (x_draw_glyphless_glyph_string_foreground): Use x_draw_rectangle instead of XDrawRectangle. (x_draw_relief_rect): Add code for USE_CAIRO. Call x_reset_clip_rectangles instead of XSetClipMask. (x_draw_box_rect): x_set_clip_rectangles instead of XSetClipRectangles, x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_draw_image_foreground, x_draw_image_foreground_1): x_draw_rectangle instead of XDrawRectangle. (x_draw_glyph_string_bg_rect): x_fill_rectangle instead of XFillRectangle. (x_draw_image_glyph_string): If img has cr_data, use it as a cairo surface. (x_draw_stretch_glyph_string): x_set_clip_rectangles instead of XSetClipRectangles, x_fill_rectangle instead of XFillRectangle. (x_draw_glyph_string): x_fill_rectangle instead of XFillRectangle., x_reset_clip_rectangles instead of XSetClipMask. (x_shift_glyphs_for_insert): Call x_prepare_for_xlibdraw. (x_clear_area1): New function that calls XClearArea. (x_clear_area): Takes frame as parameter, calls x_clear_area1 for non-cairo. (x_clear_frame): x_clear_window instead of XClearWindow. (x_scroll_run): Set frame garbaged if cairo. (XTmouse_position): Initialize *part to 0. (x_scroll_bar_create): Adjust arguments to x_clear_area. (x_scroll_bar_set_handle): x_clear_area1 instead of x_clear_area, x_fill_rectangle instead of XFillRectangle. (XTset_vertical_scroll_bar, XTset_horizontal_scroll_bar): Adjust arguments to x_clear_area. (x_scroll_bar_expose): x_draw_rectangle instead of XDrawRectangle. (handle_one_xevent): Adjust arguments to x_clear_area. Destroy cairo surface for frame if ConfigureNotify. (x_clip_to_row): x_set_clip_rectangles instead of XSetClipRectangles. (x_draw_hollow_cursor): x_draw_rectangle instead of XDrawRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_draw_bar_cursor): x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_clear_frame_area): Adjust arguments to x_clear_area. (x_free_frame_resources): Call x_prepare_for_xlibdraw. (x_term_init): Call x_extension_initialize if cairo. (x_redisplay_interface): Add x_cr_define_fringe_bitmap, x_cr_destroy_fringe_bitmap for cairo. (x_initialize): Call x_cr_init_fringe for cairo. * src/xterm.h: Add include of cairo header files. (x_bitmap_record): Add img if cairo. (x_gc_ext_data): New struct for cairo. (x_display_info): Add ext_codes for cairo. (x_output): Add cr_context and cr_surface for cairo. (x_clear_area): Change arguments from Display*/Window to frame pointer. (x_query_color, x_begin_cr_clip, x_end_cr_clip) (x_set_cr_source_with_gc_foreground, x_set_cr_source_with_gc_background) (x_cr_draw_frame, x_cr_export_frames): Declare.
Diffstat (limited to 'src/ftcrfont.c')
-rw-r--r--src/ftcrfont.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
new file mode 100644
index 00000000000..d60c1202b9d
--- /dev/null
+++ b/src/ftcrfont.c
@@ -0,0 +1,314 @@
+/* ftcrfont.c -- FreeType font driver on cairo.
+ Copyright (C) 2015 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <cairo-ft.h>
+
+#include "lisp.h"
+#include "dispextern.h"
+#include "xterm.h"
+#include "frame.h"
+#include "blockinput.h"
+#include "character.h"
+#include "charset.h"
+#include "fontset.h"
+#include "font.h"
+#include "ftfont.h"
+
+/* FTCR font driver. */
+
+/* The actual structure for ftcr font that can be casted to struct
+ font. */
+
+struct ftcrfont_info
+{
+ struct font font;
+ /* The following six members must be here in this order to be
+ compatible with struct ftfont_info (in ftfont.c). */
+#ifdef HAVE_LIBOTF
+ bool maybe_otf; /* Flag to tell if this may be OTF or not. */
+ OTF *otf;
+#endif /* HAVE_LIBOTF */
+ FT_Size ft_size;
+ int index;
+ FT_Matrix matrix;
+
+ cairo_font_face_t *cr_font_face;
+ /* To prevent cairo from cluttering the activated FT_Size maintained
+ in ftfont.c, we activate this special FT_Size before drawing. */
+ FT_Size ft_size_draw;
+ /* Font metrics cache. */
+ struct font_metrics **metrics;
+ short metrics_nrows;
+};
+
+#define METRICS_NCOLS_PER_ROW (128)
+
+enum metrics_status
+ {
+ METRICS_INVALID = -1, /* metrics entry is invalid */
+ };
+
+#define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
+#define METRICS_SET_STATUS(metrics, status) \
+ ((metrics)->ascent = 0, (metrics)->descent = (status))
+
+/* Prototypes for helper function. */
+static int ftcrfont_glyph_extents (struct font *, unsigned,
+ struct font_metrics *);
+
+/* Prototypes for font-driver methods. */
+static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object);
+static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object);
+static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int);
+static void ftcrfont_close (struct font *);
+static void ftcrfont_text_extents (struct font *, unsigned *, int,
+ struct font_metrics *);
+static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool);
+
+struct font_driver ftcrfont_driver;
+
+static int
+ftcrfont_glyph_extents (struct font *font,
+ unsigned glyph,
+ struct font_metrics *metrics)
+{
+ struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
+ int row, col;
+ struct font_metrics *cache;
+
+ row = glyph / METRICS_NCOLS_PER_ROW;
+ col = glyph % METRICS_NCOLS_PER_ROW;
+ if (row >= ftcrfont_info->metrics_nrows)
+ {
+ ftcrfont_info->metrics =
+ xrealloc (ftcrfont_info->metrics,
+ sizeof (struct font_metrics *) * (row + 1));
+ bzero (ftcrfont_info->metrics + ftcrfont_info->metrics_nrows,
+ (sizeof (struct font_metrics *)
+ * (row + 1 - ftcrfont_info->metrics_nrows)));
+ ftcrfont_info->metrics_nrows = row + 1;
+ }
+ if (ftcrfont_info->metrics[row] == NULL)
+ {
+ struct font_metrics *new;
+ int i;
+
+ new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
+ for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
+ METRICS_SET_STATUS (new + i, METRICS_INVALID);
+ ftcrfont_info->metrics[row] = new;
+ }
+ cache = ftcrfont_info->metrics[row] + col;
+
+ if (METRICS_STATUS (cache) == METRICS_INVALID)
+ ftfont_driver.text_extents (font, &glyph, 1, cache);
+
+ if (metrics)
+ *metrics = *cache;
+
+ return cache->width;
+}
+
+static Lisp_Object
+ftcrfont_list (struct frame *f, Lisp_Object spec)
+{
+ Lisp_Object list = ftfont_driver.list (f, spec), tail;
+
+ for (tail = list; CONSP (tail); tail = XCDR (tail))
+ ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
+ return list;
+}
+
+static Lisp_Object
+ftcrfont_match (struct frame *f, Lisp_Object spec)
+{
+ Lisp_Object entity = ftfont_driver.match (f, spec);
+
+ if (VECTORP (entity))
+ ASET (entity, FONT_TYPE_INDEX, Qftcr);
+ return entity;
+}
+
+extern FT_Face ftfont_get_ft_face (Lisp_Object);
+
+static Lisp_Object
+ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
+{
+ Lisp_Object font_object;
+ struct font *font;
+ struct ftcrfont_info *ftcrfont_info;
+ FT_Face ft_face;
+ FT_UInt size;
+
+ block_input ();
+ size = XINT (AREF (entity, FONT_SIZE_INDEX));
+ if (size == 0)
+ size = pixel_size;
+ font_object = font_build_object (VECSIZE (struct ftcrfont_info),
+ Qftcr, entity, size);
+ font_object = ftfont_open2 (f, entity, pixel_size, font_object);
+ if (NILP (font_object)) return Qnil;
+
+ font = XFONT_OBJECT (font_object);
+ font->driver = &ftcrfont_driver;
+ ftcrfont_info = (struct ftcrfont_info *) font;
+ ft_face = ftcrfont_info->ft_size->face;
+ FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
+ FT_Activate_Size (ftcrfont_info->ft_size_draw);
+ FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
+ ftcrfont_info->cr_font_face =
+ cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+ ftcrfont_info->metrics = NULL;
+ ftcrfont_info->metrics_nrows = 0;
+ unblock_input ();
+
+ return font_object;
+}
+
+static void
+ftcrfont_close (struct font *font)
+{
+ struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
+ int i;
+
+ block_input ();
+ for (i = 0; i < ftcrfont_info->metrics_nrows; i++)
+ if (ftcrfont_info->metrics[i])
+ xfree (ftcrfont_info->metrics[i]);
+ if (ftcrfont_info->metrics)
+ xfree (ftcrfont_info->metrics);
+ FT_Done_Size (ftcrfont_info->ft_size_draw);
+ cairo_font_face_destroy (ftcrfont_info->cr_font_face);
+ unblock_input ();
+
+ ftfont_driver.close (font);
+}
+
+static void
+ftcrfont_text_extents (struct font *font,
+ unsigned *code,
+ int nglyphs,
+ struct font_metrics *metrics)
+{
+ int width, i;
+
+ block_input ();
+ width = ftcrfont_glyph_extents (font, code[0], metrics);
+ for (i = 1; i < nglyphs; i++)
+ {
+ struct font_metrics m;
+ int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL);
+
+ if (metrics)
+ {
+ if (width + m.lbearing < metrics->lbearing)
+ metrics->lbearing = width + m.lbearing;
+ if (width + m.rbearing > metrics->rbearing)
+ metrics->rbearing = width + m.rbearing;
+ if (m.ascent > metrics->ascent)
+ metrics->ascent = m.ascent;
+ if (m.descent > metrics->descent)
+ metrics->descent = m.descent;
+ }
+ width += w;
+ }
+ unblock_input ();
+
+ if (metrics)
+ metrics->width = width;
+}
+
+static int
+ftcrfont_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 ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) s->font;
+ cairo_t *cr;
+ cairo_glyph_t *glyphs;
+ cairo_surface_t *surface;
+ int len = to - from;
+ int i;
+
+ block_input ();
+
+ cr = x_begin_cr_clip (f, s->gc);
+
+ if (with_background)
+ {
+ x_set_cr_source_with_gc_background (f, s->gc);
+ cairo_rectangle (cr, x, y - FONT_BASE (face->font),
+ s->width, FONT_HEIGHT (face->font));
+ cairo_fill (cr);
+ }
+
+ glyphs = alloca (sizeof (cairo_glyph_t) * len);
+ for (i = 0; i < len; i++)
+ {
+ unsigned code = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
+ | XCHAR2B_BYTE2 (s->char2b + from + i));
+
+ glyphs[i].index = code;
+ glyphs[i].x = x;
+ glyphs[i].y = y;
+ x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, code, NULL));
+ }
+
+ x_set_cr_source_with_gc_foreground (f, s->gc);
+ cairo_set_font_face (cr, ftcrfont_info->cr_font_face);
+ cairo_set_font_size (cr, s->font->pixel_size);
+ /* cairo_set_font_matrix */
+ /* cairo_set_font_options */
+
+ FT_Activate_Size (ftcrfont_info->ft_size_draw);
+ cairo_show_glyphs (cr, glyphs, len);
+ surface = cairo_get_target (cr);
+ if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
+ cairo_surface_flush (surface);
+
+ x_end_cr_clip (f);
+
+ unblock_input ();
+
+ return len;
+}
+
+
+
+void
+syms_of_ftcrfont (void)
+{
+ if (ftfont_info_size != offsetof (struct ftcrfont_info, cr_font_face))
+ abort ();
+
+ DEFSYM (Qftcr, "ftcr");
+
+ ftcrfont_driver = ftfont_driver;
+ ftcrfont_driver.type = Qftcr;
+ ftcrfont_driver.list = ftcrfont_list;
+ ftcrfont_driver.match = ftcrfont_match;
+ ftcrfont_driver.open = ftcrfont_open;
+ ftcrfont_driver.close = ftcrfont_close;
+ ftcrfont_driver.text_extents = ftcrfont_text_extents;
+ ftcrfont_driver.draw = ftcrfont_draw;
+ register_font_driver (&ftcrfont_driver, NULL);
+}