]> git.eshelyaron.com Git - emacs.git/commitdiff
Check in new files
authorPo Lu <luangruo@yahoo.com>
Sun, 8 Jan 2023 07:43:09 +0000 (15:43 +0800)
committerPo Lu <luangruo@yahoo.com>
Sun, 8 Jan 2023 07:43:09 +0000 (15:43 +0800)
* src/sfnt.h:
* src/sfntfont-android.c:
* src/sfntfont.c:
* src/sfntfont.h: New files.

src/sfnt.h [new file with mode: 0644]
src/sfntfont-android.c [new file with mode: 0644]
src/sfntfont.c [new file with mode: 0644]
src/sfntfont.h [new file with mode: 0644]

diff --git a/src/sfnt.h b/src/sfnt.h
new file mode 100644 (file)
index 0000000..868d0f9
--- /dev/null
@@ -0,0 +1,957 @@
+/* sfnt format font support for GNU Emacs.
+
+Copyright (C) 2023 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, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _SFNT_H_
+#define _SFNT_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+\f
+
+/* Container structure and enumerator definitions.  */
+
+/* The sfnt container format is organized into different tables, such
+   as ``cmap'' or ``glyf''.  Each of these tables has a specific
+   format and use.  These are all the tables known to Emacs.  */
+
+enum sfnt_table
+  {
+    SFNT_TABLE_CMAP,
+    SFNT_TABLE_GLYF,
+    SFNT_TABLE_HEAD,
+    SFNT_TABLE_HHEA,
+    SFNT_TABLE_HMTX,
+    SFNT_TABLE_LOCA,
+    SFNT_TABLE_MAXP,
+    SFNT_TABLE_NAME,
+    SFNT_TABLE_META,
+  };
+
+#define SFNT_ENDOF(type, field, type1)                 \
+  ((size_t) offsetof (type, field) + sizeof (type1))
+
+/* Each of these structures must be aligned so that no compiler will
+   ever generate padding bytes on platforms where the alignment
+   requirements for uint32_t and uint16_t are no larger than 4 and 2
+   bytes respectively.  */
+
+struct sfnt_offset_subtable
+{
+  /* The scaler type.  */
+  uint32_t scaler_type;
+
+  /* The number of tables.  */
+  uint16_t num_tables;
+
+  /* (Maximum power of 2 <= numTables) * 16.  */
+  uint16_t search_range;
+
+  /* log2 (maximum power of 2 <= numTables) */
+  uint16_t entry_selector;
+
+  /* numTables * 16 - searchRange.  */
+  uint16_t range_shift;
+
+  /* Variable length data.  */
+  struct sfnt_table_directory *subtables;
+};
+
+/* The table directory.  Follows the offset subtable, with one for
+   each table.  */
+
+struct sfnt_table_directory
+{
+  /* 4-byte identifier for each table.  See sfnt_table_names.  */
+  uint32_t tag;
+
+  /* Table checksum.  */
+  uint32_t checksum;
+
+  /* Offset from the start of the file.  */
+  uint32_t offset;
+
+  /* Length of the table in bytes, not subject to padding.  */
+  uint32_t length;
+};
+
+enum sfnt_scaler_type
+  {
+    SFNT_SCALER_TRUE = 0x74727565,
+    SFNT_SCALER_VER1 = 0x00010000,
+    SFNT_SCALER_TYP1 = 0x74797031,
+    SFNT_SCALER_OTTO = 0x4F54544F,
+  };
+
+typedef int32_t sfnt_fixed;
+typedef int16_t sfnt_fword;
+typedef uint16_t sfnt_ufword;
+
+#define sfnt_coerce_fixed(fixed) ((sfnt_fixed) (fixed) / 65535.0)
+
+typedef unsigned int sfnt_glyph;
+typedef unsigned int sfnt_char;
+
+struct sfnt_head_table
+{
+  /* The version.  This is a 16.16 fixed point number.  */
+  sfnt_fixed version;
+
+  /* The revision.  */
+  sfnt_fixed revision;
+
+  /* Checksum adjustment.  */
+  uint32_t checksum_adjustment;
+
+  /* Magic number, should be 0x5F0F3CF5.  */
+  uint32_t magic;
+
+  /* Flags for the font.  */
+  uint16_t flags;
+
+  /* Units per em.  */
+  uint16_t units_per_em;
+
+  /* Time of creation.  */
+  uint32_t created_high, created_low;
+
+  /* Time of modification.  */
+  uint32_t modified_high, modified_low;
+
+  /* Minimum bounds.  */
+  sfnt_fword xmin, ymin, xmax, ymax;
+
+  /* Mac specific stuff.  */
+  uint16_t mac_style;
+
+  /* Smallest readable size in pixels.  */
+  uint16_t lowest_rec_ppem;
+
+  /* Font direction hint.  */
+  int16_t font_direction_hint;
+
+  /* Index to loc format.  0 for short offsets, 1 for long.  */
+  int16_t index_to_loc_format;
+
+  /* Unused.  */
+  int16_t glyph_data_format;
+};
+
+struct sfnt_hhea_table
+{
+  /* The version.  This is a 16.16 fixed point number.  */
+  sfnt_fixed version;
+
+  /* The maximum ascent and descent values for this font.  */
+  sfnt_fword ascent, descent;
+
+  /* The typographic line gap.  */
+  sfnt_fword line_gap;
+
+  /* The maximum advance width.  */
+  sfnt_ufword advance_width_max;
+
+  /* The minimum bearings on either side.  */
+  sfnt_fword min_left_side_bearing, min_right_side_bearing;
+
+  /* The maximum extent.  */
+  sfnt_fword x_max_extent;
+
+  /* Caret slope.  */
+  int16_t caret_slope_rise, caret_slope_run;
+
+  /* Caret offset for non slanted fonts.  */
+  sfnt_fword caret_offset;
+
+  /* Reserved values.  */
+  int16_t reserved1, reserved2, reserved3, reserved4;
+
+  /* Should always be zero.  */
+  int16_t metric_data_format;
+
+  /* Number of advanced widths in metrics table.  */
+  uint16_t num_of_long_hor_metrics;
+};
+
+struct sfnt_cmap_table
+{
+  /* Should be zero.  */
+  uint16_t version;
+
+  /* Number of subtables.  */
+  uint16_t num_subtables;
+};
+
+enum sfnt_platform_id
+  {
+    SFNT_PLATFORM_UNICODE   = 0,
+    SFNT_PLATFORM_MACINTOSH = 1,
+    SFNT_PLATFORM_RESERVED  = 2,
+    SFNT_PLATFORM_MICROSOFT = 3,
+  };
+
+enum sfnt_unicode_platform_specific_id
+  {
+    SFNT_UNICODE_1_0                = 0,
+    SFNT_UNICODE_1_1                = 1,
+    SFNT_UNICODE_ISO_10646_1993             = 2,
+    SFNT_UNICODE_2_0_BMP            = 3,
+    SFNT_UNICODE_2_0                = 4,
+    SFNT_UNICODE_VARIATION_SEQUENCES = 5,
+    SFNT_UNICODE_LAST_RESORT        = 6,
+  };
+
+enum sfnt_macintosh_platform_specific_id
+  {
+    SFNT_MACINTOSH_ROMAN              = 0,
+    SFNT_MACINTOSH_JAPANESE           = 1,
+    SFNT_MACINTOSH_TRADITIONAL_CHINESE = 2,
+    SFNT_MACINTOSH_KOREAN             = 3,
+    SFNT_MACINTOSH_ARABIC             = 4,
+    SFNT_MACINTOSH_HEBREW             = 5,
+    SFNT_MACINTOSH_GREEK              = 6,
+    SFNT_MACINTOSH_RUSSIAN            = 7,
+    SFNT_MACINTOSH_RSYMBOL            = 8,
+    SFNT_MACINTOSH_DEVANGARI          = 9,
+    SFNT_MACINTOSH_GURMUKHI           = 10,
+    SFNT_MACINTOSH_GUJARATI           = 11,
+    SFNT_MACINTOSH_ORIYA              = 12,
+    SFNT_MACINTOSH_BENGALI            = 13,
+    SFNT_MACINTOSH_TAMIL              = 14,
+    SFNT_MACINTOSH_TELUGU             = 15,
+    SFNT_MACINTOSH_KANNADA            = 16,
+    SFNT_MACINTOSH_MALAYALAM          = 17,
+    SFNT_MACINTOSH_SINHALESE          = 18,
+    SFNT_MACINTOSH_BURMESE            = 19,
+    SFNT_MACINTOSH_KHMER              = 20,
+    SFNT_MACINTOSH_THAI                       = 21,
+    SFNT_MACINTOSH_LAOTIAN            = 22,
+    SFNT_MACINTOSH_GEORGIAN           = 23,
+    SFNT_MACINTOSH_ARMENIAN           = 24,
+    SFNT_MACINTOSH_SIMPLIFIED_CHINESE  = 25,
+    SFNT_MACINTOSH_TIBETIAN           = 26,
+    SFNT_MACINTOSH_MONGOLIAN          = 27,
+    SFNT_MACINTOSH_GEEZ                       = 28,
+    SFNT_MACINTOSH_SLAVIC             = 29,
+    SFNT_MACINTOSH_VIETNAMESE         = 30,
+    SFNT_MACINTOSH_SINDHI             = 31,
+    SFNT_MACINTOSH_UNINTERPRETED       = 32,
+  };
+
+enum sfnt_microsoft_platform_specific_id
+  {
+    SFNT_MICROSOFT_SYMBOL       = 0,
+    SFNT_MICROSOFT_UNICODE_BMP  = 1,
+    SFNT_MICROSOFT_SHIFT_JIS    = 2,
+    SFNT_MICROSOFT_PRC          = 3,
+    SFNT_MICROSOFT_BIG_FIVE     = 4,
+    SFNT_MICROSOFT_WANSUNG      = 5,
+    SFNT_MICROSOFT_JOHAB        = 6,
+    SFNT_MICROSOFT_UNICODE_UCS_4 = 10,
+  };
+
+struct sfnt_cmap_encoding_subtable
+{
+  /* The platform ID.  */
+  uint16_t platform_id;
+
+  /* Platform specific ID.  */
+  uint16_t platform_specific_id;
+
+  /* Mapping table offset.  */
+  uint32_t offset;
+};
+
+struct sfnt_cmap_encoding_subtable_data
+{
+  /* Format and possibly the length in bytes.  */
+  uint16_t format, length;
+};
+
+struct sfnt_cmap_format_0
+{
+  /* Format, set to 0.  */
+  uint16_t format;
+
+  /* Length in bytes.  Should be 262.  */
+  uint16_t length;
+
+  /* Language code.  */
+  uint16_t language;
+
+  /* Character code to glyph index map.  */
+  uint8_t glyph_index_array[256];
+};
+
+struct sfnt_cmap_format_2_subheader
+{
+  uint16_t first_code;
+  uint16_t entry_count;
+  int16_t id_delta;
+  uint16_t id_range_offset;
+};
+
+struct sfnt_cmap_format_2
+{
+  /* Format, set to 2.  */
+  uint16_t format;
+
+  /* Length in bytes.  */
+  uint16_t length;
+
+  /* Language code.  */
+  uint16_t language;
+
+  /* Array mapping high bytes to subheaders.  */
+  uint16_t sub_header_keys[256];
+
+  /* Variable length data.  */
+  struct sfnt_cmap_format_2_subheader *subheaders;
+  uint16_t *glyph_index_array;
+  uint16_t num_glyphs;
+};
+
+struct sfnt_cmap_format_4
+{
+  /* Format, set to 4.  */
+  uint16_t format;
+
+  /* Length in bytes.  */
+  uint16_t length;
+
+  /* Language code.  */
+  uint16_t language;
+
+  /* 2 * seg_count.  */
+  uint16_t seg_count_x2;
+
+  /* 2 * (2**FLOOR(log2(segCount))) */
+  uint16_t search_range;
+
+  /* log2(searchRange/2) */
+  uint16_t entry_selector;
+
+  /* Variable-length data.  */
+  uint16_t *end_code;
+  uint16_t *reserved_pad;
+  uint16_t *start_code;
+  int16_t *id_delta;
+  int16_t *id_range_offset;
+  uint16_t *glyph_index_array;
+
+  /* The number of elements in glyph_index_array.  */
+  size_t glyph_index_size;
+};
+
+struct sfnt_cmap_format_6
+{
+  /* Format, set to 6.  */
+  uint16_t format;
+
+  /* Length in bytes.  */
+  uint16_t length;
+
+  /* Language code.  */
+  uint16_t language;
+
+  /* First character code in subrange.  */
+  uint16_t first_code;
+
+  /* Number of character codes.  */
+  uint16_t entry_count;
+
+  /* Variable-length data.  */
+  uint16_t *glyph_index_array;
+};
+
+struct sfnt_cmap_format_8_or_12_group
+{
+  uint32_t start_char_code;
+  uint32_t end_char_code;
+  uint32_t start_glyph_code;
+};
+
+struct sfnt_cmap_format_8
+{
+  /* Format, set to 8.  */
+  uint16_t format;
+
+  /* Reserved.  */
+  uint16_t reserved;
+
+  /* Length in bytes.  */
+  uint32_t length;
+
+  /* Language code.  */
+  uint32_t language;
+
+  /* Tightly packed array of bits (8K bytes total) indicating whether
+     the particular 16-bit (index) value is the start of a 32-bit
+     character code.  */
+  uint8_t is32[65536];
+
+  /* Number of groups.  */
+  uint32_t num_groups;
+
+  /* Variable length data.  */
+  struct sfnt_cmap_format_8_or_12_group *groups;
+};
+
+/* cmap formats 10, 13 and 14 unsupported.  */
+
+struct sfnt_cmap_format_12
+{
+  /* Format, set to 12.  */
+  uint16_t format;
+
+  /* Reserved.  */
+  uint16_t reserved;
+
+  /* Length in bytes.  */
+  uint32_t length;
+
+  /* Language code.  */
+  uint32_t language;
+
+  /* Number of groups.  */
+  uint32_t num_groups;
+
+  /* Variable length data.  */
+  struct sfnt_cmap_format_8_or_12_group *groups;
+};
+
+struct sfnt_maxp_table
+{
+  /* Table version.  */
+  sfnt_fixed version;
+
+  /* The number of glyphs in this font - 1.  Set at version 0.5 or
+     later.  */
+  uint16_t num_glyphs;
+
+  /* These fields are only set in version 1.0 or later.  Maximum
+     points in a non-composite glyph.  */
+  uint16_t max_points;
+
+  /* Maximum contours in a non-composite glyph.  */
+  uint16_t max_contours;
+
+  /* Maximum points in a composite glyph.  */
+  uint16_t max_composite_points;
+
+  /* Maximum contours in a composite glyph.  */
+  uint16_t max_composite_contours;
+
+  /* 1 if instructions do not use the twilight zone (Z0), or 2 if
+     instructions do use Z0; should be set to 2 in most cases.  */
+  uint16_t max_zones;
+
+  /* Maximum points used in Z0.  */
+  uint16_t max_twilight_points;
+
+  /* Number of Storage Area locations.  */
+  uint16_t max_storage;
+
+  /* Number of FDEFs, equal to the highest function number + 1.  */
+  uint16_t max_function_defs;
+
+  /* Number of IDEFs.  */
+  uint16_t max_instruction_defs;
+
+  /* Maximum stack depth across Font Program ('fpgm' table), CVT
+     Program ('prep' table) and all glyph instructions (in the 'glyf'
+     table).  */
+  uint16_t max_stack_elements;
+
+  /* Maximum byte count for glyph instructions.  */
+  uint16_t max_size_of_instructions;
+
+  /* Maximum number of components referenced at ``top level'' for any
+     composite glyph.  */
+  uint16_t max_component_elements;
+
+  /* Maximum levels of recursion; 1 for simple components.  */
+  uint16_t max_component_depth;
+};
+
+struct sfnt_loca_table_short
+{
+  /* Offsets to glyph data divided by two.  */
+  uint16_t *offsets;
+
+  /* Size of the offsets list.  */
+  size_t num_offsets;
+};
+
+struct sfnt_loca_table_long
+{
+  /* Offsets to glyph data.  */
+  uint32_t *offsets;
+
+  /* Size of the offsets list.  */
+  size_t num_offsets;
+};
+
+struct sfnt_glyf_table
+{
+  /* Size of the glyph data.  */
+  size_t size;
+
+  /* Pointer to possibly unaligned glyph data.  */
+  unsigned char *glyphs;
+};
+
+struct sfnt_simple_glyph
+{
+  /* The total number of points in this glyph.  */
+  size_t number_of_points;
+
+  /* Array containing the last points of each contour.  */
+  uint16_t *end_pts_of_contours;
+
+  /* Total number of bytes needed for instructions.  */
+  uint16_t instruction_length;
+
+  /* Instruction data.  */
+  uint8_t *instructions;
+
+  /* Array of flags.  */
+  uint8_t *flags;
+
+  /* Array of X coordinates.  */
+  int16_t *x_coordinates;
+
+  /* Array of Y coordinates.  */
+  int16_t *y_coordinates;
+
+  /* Pointer to the end of that array.  */
+  int16_t *y_coordinates_end;
+};
+
+struct sfnt_compound_glyph_component
+{
+  /* Compound glyph flags.  */
+  uint16_t flags;
+
+  /* Component glyph index.  */
+  uint16_t glyph_index;
+
+  /* X-offset for component or point number; type depends on bits 0
+     and 1 in component flags.  */
+  union {
+    uint8_t a;
+    int8_t b;
+    uint16_t c;
+    int16_t d;
+  } argument1;
+
+  /* Y-offset for component or point number; type depends on bits 0
+     and 1 in component flags.  */
+  union {
+    uint8_t a;
+    int8_t b;
+    uint16_t c;
+    int16_t d;
+  } argument2;
+
+  /* Various scale formats.  */
+  union {
+    uint16_t scale;
+    struct {
+      uint16_t xscale;
+      uint16_t yscale;
+    } a;
+    struct {
+      uint16_t xscale;
+      uint16_t scale01;
+      uint16_t scale10;
+      uint16_t yscale;
+    } b;
+  } u;
+};
+
+struct sfnt_compound_glyph
+{
+  /* Pointer to array of components.  */
+  struct sfnt_compound_glyph_component *components;
+
+  /* Number of elements in that array.  */
+  size_t num_components;
+
+  /* Instruction data.  */
+  uint8_t *instructions;
+
+  /* Length of instructions.  */
+  uint16_t instruction_length;
+};
+
+struct sfnt_glyph
+{
+  /* Number of contours in this glyph.  */
+  int16_t number_of_contours;
+
+  /* Coordinate bounds.  */
+  sfnt_fword xmin, ymin, xmax, ymax;
+
+  /* Either a simple glyph or a compound glyph, depending on which is
+     set.  */
+  struct sfnt_simple_glyph *simple;
+  struct sfnt_compound_glyph *compound;
+};
+
+\f
+
+/* Glyph outline decomposition.  */
+
+struct sfnt_point
+{
+  /* X and Y in em space.  */
+  sfnt_fixed x, y;
+};
+
+typedef void (*sfnt_move_to_proc) (struct sfnt_point, void *);
+typedef void (*sfnt_line_to_proc) (struct sfnt_point, void *);
+typedef void (*sfnt_curve_to_proc) (struct sfnt_point,
+                                   struct sfnt_point,
+                                   void *);
+
+typedef struct sfnt_glyph *(*sfnt_get_glyph_proc) (sfnt_glyph, void *,
+                                                  bool *);
+typedef void (*sfnt_free_glyph_proc) (struct sfnt_glyph *, void *);
+
+\f
+
+/* Decomposed glyph outline.  */
+
+struct sfnt_glyph_outline_command
+{
+  /* Flags for this outline command.  */
+  int flags;
+
+  /* X and Y position of this command.  */
+  sfnt_fixed x, y;
+};
+
+/* Structure describing a single recorded outline in fixed pixel
+   space.  */
+
+struct sfnt_glyph_outline
+{
+  /* Array of outlines elements.  */
+  struct sfnt_glyph_outline_command *outline;
+
+  /* Size of the outline data, and how much is full.  */
+  size_t outline_size, outline_used;
+
+  /* Rectangle defining bounds of the outline.  Namely, the minimum
+     and maximum X and Y positions.  */
+  sfnt_fixed xmin, ymin, xmax, ymax;
+};
+
+enum sfnt_glyph_outline_flags
+  {
+    SFNT_GLYPH_OUTLINE_LINETO    = (1 << 1),
+  };
+
+struct sfnt_build_glyph_outline_context
+{
+  /* The outline being built.  */
+  struct sfnt_glyph_outline *outline;
+
+  /* The head table.  */
+  struct sfnt_head_table *head;
+
+  /* The pixel size being used, and any extra flags to apply to the
+     outline at this point.  */
+  int pixel_size;
+
+  /* Factor to multiply positions by to get the pixel width.  */
+  double factor;
+
+  /* The position of the pen in 16.16 fixed point format.  */
+  sfnt_fixed x, y;
+};
+
+\f
+
+/* Glyph rasterization.  */
+
+struct sfnt_raster
+{
+  /* Basic dimensions of the raster.  */
+  unsigned short width, height;
+
+  /* Integer offset to apply to positions in the raster.  */
+  unsigned short offx, offy;
+
+  /* Pointer to coverage data.  */
+  unsigned char *cells;
+};
+
+struct sfnt_edge
+{
+  /* Next edge in this chain.  */
+  struct sfnt_edge *next;
+
+  /* Winding direction.  1 if clockwise, -1 if counterclockwise.  */
+  int winding;
+
+  /* X position, top and bottom of edges.  */
+  sfnt_fixed x, top, bottom;
+
+  /* step_x is how many pixels to move for each increase in Y.  */
+  sfnt_fixed step_x;
+};
+
+\f
+
+/* Polygon rasterization constants.  */
+
+enum
+  {
+    SFNT_POLY_SHIFT  = 2,
+    SFNT_POLY_SAMPLE = (1 << SFNT_POLY_SHIFT),
+    SFNT_POLY_MASK   = (SFNT_POLY_SAMPLE - 1),
+    SFNT_POLY_STEP   = (0x10000 >> SFNT_POLY_SHIFT),
+    SFNT_POLY_START  = (SFNT_POLY_STEP >> 1),
+  };
+
+\f
+
+/* Glyph metrics computation.  */
+
+struct sfnt_long_hor_metric
+{
+  uint16_t advance_width;
+  int16_t left_side_bearing;
+};
+
+struct sfnt_hmtx_table
+{
+  /* Array of horizontal metrics for each glyph.  */
+  struct sfnt_long_hor_metric *h_metrics;
+
+  /* Lbearing for remaining glyphs.  */
+  int16_t *left_side_bearing;
+};
+
+/* Structure describing the metrics of a single glyph.  The fields
+   mean the same as in XCharStruct, except they are 16.16 fixed point
+   values, and are missing significant information.  */
+
+struct sfnt_glyph_metrics
+{
+  /* Distance between origin and left edge of raster.  Positive
+     changes move rightwards.  */
+  sfnt_fixed lbearing;
+
+  /* Advance to next glyph's origin.  */
+  sfnt_fixed advance;
+};
+
+\f
+
+/* Font style parsing.  */
+
+struct sfnt_name_record
+{
+  /* Platform identifier code.  */
+  uint16_t platform_id;
+
+  /* Platform specific ID.  */
+  uint16_t platform_specific_id;
+
+  /* Language identifier.  */
+  uint16_t language_id;
+
+  /* Name identifier.  */
+  uint16_t name_id;
+
+  /* String length in bytes.  */
+  uint16_t length;
+
+  /* Offset from start of storage area.  */
+  uint16_t offset;
+};
+
+struct sfnt_name_table
+{
+  /* Format selector of name table.  */
+  uint16_t format;
+
+  /* Number of name records.  */
+  uint16_t count;
+
+  /* Offset to start of string data.  */
+  uint16_t string_offset;
+
+  /* Variable length data.  */
+  struct sfnt_name_record *name_records;
+
+  /* Start of string data.  */
+  unsigned char *data;
+};
+
+/* Name identifier codes.  These are Apple's codes, not
+   Microsoft's.  */
+
+enum sfnt_name_identifier_code
+  {
+    SFNT_NAME_COPYRIGHT_NOTICE                 = 0,
+    SFNT_NAME_FONT_FAMILY                      = 1,
+    SFNT_NAME_FONT_SUBFAMILY                   = 2,
+    SFNT_NAME_UNIQUE_SUBFAMILY_IDENTIFICATION  = 3,
+    SFNT_NAME_FULL_NAME                                = 4,
+    SFNT_NAME_NAME_TABLE_VERSION               = 5,
+    SFNT_NAME_POSTSCRIPT_NAME                  = 6,
+    SFNT_NAME_TRADEMARK_NOTICE                 = 7,
+    SFNT_NAME_MANUFACTURER_NAME                        = 8,
+    SFNT_NAME_DESIGNER                         = 9,
+    SFNT_NAME_DESCRIPTION                      = 10,
+    SFNT_NAME_FONT_VENDOR_URL                  = 11,
+    SFNT_NAME_FONT_DESIGNER_URL                        = 12,
+    SFNT_NAME_LICENSE_DESCRIPTION              = 13,
+    SFNT_NAME_LICENSE_INFORMATION_URL          = 14,
+    SFNT_NAME_PREFERRED_FAMILY                 = 16,
+    SFNT_NAME_PREFERRED_SUBFAMILY              = 17,
+    SFNT_NAME_COMPATIBLE_FULL                  = 18,
+    SFNT_NAME_SAMPLE_TEXT                      = 19,
+    SFNT_NAME_VARIATIONS_POSTSCRIPT_NAME_PREFIX = 25,
+  };
+
+struct sfnt_meta_data_map
+{
+  /* Identifier for the tag.  */
+  uint32_t tag;
+
+  /* Offset from start of table to data.  */
+  uint32_t data_offset;
+
+  /* Length of the data.  */
+  uint32_t data_length;
+};
+
+struct sfnt_meta_table
+{
+  /* Version of the table.  Currently set to 1.  */
+  uint32_t version;
+
+  /* Flags.  Currently 0.  */
+  uint32_t flags;
+
+  /* Offset from start of table to beginning of variable length
+     data.  */
+  uint32_t data_offset;
+
+  /* Number of data maps in the table.  */
+  uint32_t num_data_maps;
+
+  /* Beginning of variable length data.  */
+  struct sfnt_meta_data_map *data_maps;
+
+  /* The whole table contents.  */
+  unsigned char *data;
+};
+
+enum sfnt_meta_data_tag
+  {
+    SFNT_META_DATA_TAG_DLNG = 0x646c6e67,
+    SFNT_META_DATA_TAG_SLNG = 0x736c6e67,
+  };
+
+\f
+
+/* Function declarations.  Keep these sorted by the order in which
+   they appear in sfnt.c.  Keep each line no longer than 80
+   columns.  */
+
+#ifndef TEST
+
+extern struct sfnt_offset_subtable *sfnt_read_table_directory (int);
+
+#define PROTOTYPE                              \
+  int, struct sfnt_offset_subtable *,          \
+  struct sfnt_cmap_encoding_subtable **,       \
+  struct sfnt_cmap_encoding_subtable_data ***
+static struct sfnt_cmap_table *sfnt_read_cmap_table (PROTOTYPE);
+#undef PROTOTYPE
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+extern struct sfnt_head_table *sfnt_read_head_table (PROTOTYPE);
+extern struct sfnt_hhea_table *sfnt_read_hhea_table (PROTOTYPE);
+extern struct sfnt_loca_table_short *sfnt_read_loca_table_short (PROTOTYPE);
+extern struct sfnt_loca_table_long *sfnt_read_loca_table_long (PROTOTYPE);
+extern struct sfnt_maxp_table *sfnt_read_maxp_table (PROTOTYPE);
+extern struct sfnt_glyf_table *sfnt_read_glyf_table (PROTOTYPE);
+#undef PROTOTYPE
+
+extern struct sfnt_glyph *sfnt_read_glyph (sfnt_glyph, struct sfnt_glyf_table *,
+                                          struct sfnt_loca_table_short *,
+                                          struct sfnt_loca_table_long *);
+
+#define PROTOTYPE              \
+  struct sfnt_glyph *,         \
+  struct sfnt_head_table *,    \
+  int, sfnt_get_glyph_proc,    \
+  sfnt_free_glyph_proc,                \
+  void *
+extern struct sfnt_glyph_outline *sfnt_build_glyph_outline (PROTOTYPE);
+#undef PROTOTYPE
+
+extern void sfnt_prepare_raster (struct sfnt_raster *,
+                                struct sfnt_glyph_outline *);
+
+#define PROTOTYPE struct sfnt_glyph_outline *
+extern struct sfnt_raster *sfnt_raster_glyph_outline (PROTOTYPE);
+#undef PROTOTYPE
+
+#define PROTOTYPE                      \
+  int,                                 \
+  struct sfnt_offset_subtable *,       \
+  struct sfnt_hhea_table *,            \
+  struct sfnt_maxp_table *
+extern struct sfnt_hmtx_table *sfnt_read_hmtx_table (PROTOTYPE);
+#undef PROTOTYPE
+
+extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int,
+                                     struct sfnt_glyph_metrics *,
+                                     struct sfnt_hmtx_table *,
+                                     struct sfnt_hhea_table *,
+                                     struct sfnt_head_table *,
+                                     struct sfnt_maxp_table *);
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE);
+#undef PROTOTYPE
+
+extern unsigned char *sfnt_find_name (struct sfnt_name_table *,
+                                     enum sfnt_name_identifier_code,
+                                     struct sfnt_name_record *);
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+extern struct sfnt_meta_table *sfnt_read_meta_table (PROTOTYPE);
+#undef PROTOTYPE
+
+extern char *sfnt_find_metadata (struct sfnt_meta_table *,
+                                enum sfnt_meta_data_tag,
+                                struct sfnt_meta_data_map *);
+
+#endif /* TEST */
+#endif /* _SFNT_H_ */
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c
new file mode 100644 (file)
index 0000000..d3c05fa
--- /dev/null
@@ -0,0 +1,36 @@
+/* sfnt format font driver for Android.
+
+Copyright (C) 2023 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, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <config.h>
+
+#include "androidterm.h"
+#include "sfntfont.h"
+
+void
+init_sfntfont_android (void)
+{
+
+}
+
+void
+syms_of_sfntfont_android (void)
+{
+
+}
diff --git a/src/sfntfont.c b/src/sfntfont.c
new file mode 100644 (file)
index 0000000..a9cc6d1
--- /dev/null
@@ -0,0 +1,493 @@
+/* sfnt format font driver for GNU Emacs.
+
+Copyright (C) 2023 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, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <config.h>
+
+#include "lisp.h"
+#include "sfnt.h"
+#include "coding.h"
+
+/* Generic font driver for sfnt-based fonts (currently TrueType, but
+   it would be easy to add CFF support in the future.)
+
+   This is not a complete font driver.  Hooks must be supplied by the
+   platform implementer to draw glyphs.  */
+
+\f
+
+/* Description of a font that hasn't been opened.  */
+
+struct sfnt_font_desc
+{
+  /* Next font in this list.  */
+  struct sfnt_font_desc *next;
+
+  /* Family name of the font.  */
+  Lisp_Object family;
+
+  /* Style name of the font.  */
+  Lisp_Object style;
+
+  /* Numeric width, weight, slant and spacing.  */
+  int width, weight, slant, spacing;
+
+  /* Path to the font file.  */
+  char *path;
+};
+
+/* List of fonts.  */
+
+static struct sfnt_font_desc *system_fonts;
+
+/* Font enumeration and matching.  The sfnt driver assumes it can read
+   data from each font at startup.  It then reads the head, meta and
+   name tables to determine font data, and records the font in a list
+   of system fonts that is then matched against.  */
+
+/* Set up the coding system CODING to decode string data from the
+   given platform id ID and platform specific id PLATFORM_SPECIFIC_ID.
+   Value is 0 upon success, 1 upon failure.  */
+
+static int
+sfnt_setup_coding_system (enum sfnt_platform_id id, int platform_specific_id,
+                         struct coding_system *coding)
+{
+  Lisp_Object system;
+
+  system = Qnil;
+
+  /* Figure out what coding system to use.  */
+
+  switch (id)
+    {
+    case SFNT_PLATFORM_UNICODE:
+      system = Qutf_16be;
+      break;
+
+    case SFNT_PLATFORM_MACINTOSH:
+
+      if (platform_specific_id == SFNT_MACINTOSH_ROMAN)
+       system = Qmac_roman;
+      else
+       /* MULE doesn't support the rest... */
+       system = Qnil;
+
+      break;
+
+    case SFNT_PLATFORM_MICROSOFT:
+      system = Qutf_16be;
+
+      /* FIXME will someone look at the MS spec and see if this
+        right.  */
+      if (platform_specific_id
+         == SFNT_MICROSOFT_BIG_FIVE)
+       system = Qchinese_big5;
+
+      break;
+    }
+
+  if (NILP (system))
+    return 1;
+
+  setup_coding_system (system, coding);
+}
+
+/* Globals used to communicate inside the condition-case wrapper.  */
+static struct coding_system *sfnt_font_coding;
+
+/* The src_object being encoded from.  This should be on the stack as
+   well, or it will get garbage collected.  */
+static Lisp_Object sfnt_font_src_object;
+
+/* From-position.  */
+static ptrdiff_t sfnt_font_from, sfnt_font_from_byte;
+
+/* To-position.  */
+static ptrdiff_t sfnt_font_to, sfnt_font_to_byte;
+
+/* Destination object.  Once again, this should also be on the
+   stack.  */
+static Lisp_Object sfnt_font_dst_object;
+
+/* Error flag.  Set to true if a signal was caught.  */
+static bool sfnt_font_signal;
+
+static Lisp_Object
+sfnt_safe_encode_coding_object_1 (void)
+{
+  encode_coding_object (sfnt_font_coding,
+                       sfnt_font_src_object,
+                       sfnt_font_from,
+                       sfnt_font_from_byte,
+                       sfnt_font_to,
+                       sfnt_font_to_byte,
+                       sfnt_font_dst_object);
+  return Qnil;
+}
+
+static Lisp_Object
+sfnt_safe_encode_coding_object_2 (void)
+{
+  sfnt_font_signal = true;
+
+  return Qnil;
+}
+
+/* Like encode_coding_object, but return 1 if a signal happens.  Value
+   is otherwise 0.  */
+
+static int
+sfnt_safe_encode_coding_object (struct coding_system *coding,
+                               Lisp_Object src_object,
+                               ptrdiff_t from, ptrdiff_t from_byte,
+                               ptrdiff_t to, ptrdiff_t to_byte,
+                               Lisp_Object dst_object)
+{
+  sfnt_font_coding = coding;
+  sfnt_font_src_object = src_object;
+  sfnt_font_from = from;
+  sfnt_font_from_byte = from_byte;
+  sfnt_font_to = to;
+  sfnt_font_to_byte = to_byte;
+  sfnt_font_dst_object = dst_object;
+  sfnt_font_signal = false;
+
+  internal_condition_case (sfnt_safe_encode_coding_object_1,
+                          Qt,
+                          sfnt_safe_encode_coding_object_2);
+
+  return (int) sfnt_font_signal;
+}
+
+/* Decode the specified string DATA.  The encoding is determined based
+   on PLATFORM_ID, PLATFORM_SPECIFIC_ID and LANGUAGE_ID.  Consult
+   sfnt.h and the TrueType Reference Manual for more details.  LENGTH
+   is the length of DATA in bytes.
+
+   Value is nil upon failure, else the decoded string.  */
+
+static Lisp_Object
+sfnt_decode_font_string (unsigned char *data, enum sfnt_platform_id id,
+                        int platform_specific_id, int language_id,
+                        size_t length)
+{
+  struct coding_system coding;
+
+  memset (&coding, 0, sizeof coding);
+  sfnt_setup_coding_system (id, platform_specific_id, &coding);
+  coding.mode |= CODING_MODE_SAFE_ENCODING;
+  coding.mode |= CODING_MODE_LAST_BLOCK;
+  /* Suppress producing escape sequences for composition.  */
+  coding.common_flags &= ~CODING_ANNOTATION_MASK;
+  coding.source = data;
+
+  if (sfnt_safe_encode_coding_object (&coding, Qnil, 0, 0,
+                                     0, 0, length, length,
+                                     Qnil))
+    return Qnil;
+
+  return coding.dst_object;
+}
+
+/* Decode the family and style names from the name table NAME.  Return
+   0 and the family and style names upon success, else 1.  */
+
+static int
+sfnt_decode_family_style (struct sfnt_name_table *name,
+                         Lisp_Object *family, Lisp_Object *style)
+{
+  struct sfnt_name_record family_rec, style_rec;
+  unsigned char *family_data, *style_data;
+
+  family_data = sfnt_find_name (name, SFNT_NAME_FONT_FAMILY,
+                               &family_rec);
+  style_data = sfnt_find_name (name, SFNT_NAME_FONT_SUBFAMILY,
+                              &style_rec);
+
+  if (!family_data || !style_data)
+    return 1;
+
+  /* Now decode the data.  */
+  *family = sfnt_decode_font_string (family_data,
+                                    family_rec.platform_id,
+                                    family_rec.platform_specific_id,
+                                    family_rec.language_id,
+                                    family_rec.length);
+  *style = sfnt_decode_font_string (style_data,
+                                   style_rec.platform_id,
+                                   style_rec.platform_specific_id,
+                                   style_rec.language_id,
+                                   style_rec.length);
+
+  /* Return whether or not it was successful.  */
+  return (!NILP (*family) && !NILP (*style)) ? 0 : 1;
+}
+
+struct sfnt_style_desc
+{
+  /* The C string to match against.  */
+  const char *c_string;
+
+  /* The value of the style field.  */
+  int value;
+};
+
+/* Array of style descriptions describing weight.  */
+static struct sfnt_style_desc sfnt_weight_descriptions =
+  {
+    { "thin", 0,               },
+    { "extralight", 40,                },
+    { "ultralight", 40,                },
+    { "demilight", 55,         },
+    { "semilight", 55,         },
+    { "book", 75,              },
+    { "medium", 100,           },
+    { "demibold", 180,         },
+    { "semibold", 180,         },
+    { "bold", 200,             },
+    { "extrabold", 205,                },
+    { "ultrabold", 205,                },
+    { "black", 210,            },
+    { "heavy", 210,            },
+    { "extrablack", 215,       },
+    { "ultrablack", 215,       },
+  };
+
+/* Array of style descriptions describing slant.  */
+static struct sfnt_style_desc sfnt_slant_descriptions =
+  {
+    { "italic", 100,   },
+    { "oblique", 110,  },
+  };
+
+/* Array of style descriptions describing width.  */
+static struct sfnt_width_desc sfnt_width_descriptions =
+  {
+    { "ultracondensed", 50,    },
+    { "extracondensed", 63,    },
+    { "condensed", 75,         },
+    { "semicondensed", 87,     },
+    { "semiexpanded", 113,     },
+    { "expanded", 125,         },
+    { "extraexpanded", 150,    },
+    { "ultraexpanded", 200,    },
+  };
+
+/* Figure out DESC->width, DESC->weight, DESC->slant and DESC->spacing
+   based on the style name passed as STYLE.  */
+
+static void
+sfnt_parse_style (Lisp_Object style, struct sfnt_font_desc *desc)
+{
+  char *style, single, *saveptr;
+  int i;
+
+  /* Fill in default values.  */
+  desc->weight = 80;
+  desc->slant = 0;
+  desc->width = 100;
+
+  /* Split the style into spaces.  As long as no weight, slant, or
+     width is encountered, look in the corresponding descriptions
+     array.  GC must not happen inside this block.  */
+  style = SSDATA (Fdowncase (style));
+  saveptr = NULL;
+
+  while ((single = strtok_r (style, " ", &saveptr)))
+    {
+      style = NULL;
+
+      if (desc->weight == 80)
+       {
+         /* Weight hasn't been found yet.  Scan through the weight
+            table.  */
+         for (i = 0; i < ARRAYELTS (sfnt_weight_descriptions); ++i)
+           {
+             if (!strcmp (sfnt_weight_descriptions[i].c_string,
+                          single))
+               {
+                 /* Weight found.  Continue on reading the slant and
+                    width.  */
+                 desc->weight = sfnt_weight_descriptions[i].value;
+                 goto next;
+               }
+           }
+       }
+
+      if (!desc->slant)
+       {
+         /* Slant hasn't been found yet.  Scan through the slant
+            table.  */
+         for (i = 0; i < ARRAYELTS (sfnt_slant_descriptions); ++i)
+           {
+             if (!strcmp (sfnt_weight_descriptions[i].c_string,
+                          single))
+               {
+                 /* Slant found.  Continue on reading the weight and
+                    width.  */
+                 desc->slant = sfnt_weight_descriptions[i].value;
+                 goto next;
+               }
+           }
+       }
+
+      if (desc->width == 100)
+       {
+         /* Width hasn't been found yet.  Scan through the width
+            table.  */
+         for (i = 0; i < ARRAYELTS (sfnt_width_descriptions); ++i)
+           {
+             if (!strcmp (sfnt_width_descriptions[i].c_string,
+                          single))
+               {
+                 /* Width found.  Continue on reading the slant and
+                    weight.  */
+                 desc->slant = sfnt_width_descriptions[i].value;
+                 goto next;
+               }
+           }
+       }
+
+    next:
+
+      /* Break early if everything has been found.  */
+      if (desc->slant && desc->width != 100 && desc->weight != 80)
+       break;
+
+      continue;
+    }
+}
+
+/* Enumerate the font FILE into the list of system fonts.  Return 1 if
+   it could not be enumerated, 0 otherwise.  */
+
+int
+sfnt_enum_font (const char *file)
+{
+  struct sfnt_font_desc *desc;
+  int fd;
+  struct sfnt_offset_subtable *subtables;
+  struct sfnt_head_table *head;
+  struct sfnt_name_table *name;
+  struct sfnt_meta_table *meta;
+  Lisp_Object family, style;
+
+  /* Create the font desc and copy in the file name.  */
+  desc = xzalloc (sizeof *desc + strlen (file) + 1);
+  desc->path = (char *) (desc + 1);
+  memcpy (desc->path, file, strlen (file) + 1);
+
+  /* Now open the font for reading.  */
+  fd = emacs_open (file, O_RDWR);
+
+  /* Read the table directory.  */
+  subtables = sfnt_read_table_directory (fd);
+
+  if (!subtables)
+    goto bail0;
+
+  /* Check that this is a TrueType font.  */
+  if (subtables->scaler_type != SFNT_SCALER_TRUE
+      && subtables->scaler_type != SFNT_SCALER_VER1)
+    goto bail1;
+
+  /* Read required tables.  */
+  head = sfnt_read_head_table (fd, subtables);
+  if (!head)
+    goto bail1;
+
+  name = sfnt_read_name_table (fd, subtables);
+  if (!name)
+    goto bail2;
+
+  /* meta is not required, nor present on many non-Apple fonts.  */
+  meta = sfnt_read_meta_table (fd, subtables);
+
+  /* Decode the family and style from the name table.  */
+  if (sfnt_decode_family_style (name, &family, &style))
+    goto bail3;
+
+  /* Set the family.  */
+  desc->family = family;
+
+  /* Parse the style.  */
+  sfnt_parse_style (style, desc);
+
+  /* Figure out the spacing.  Some fancy test like what Fontconfig
+     does is probably in order but not really necessary.  */
+  if (!NILP (Fstring_search (Fdowncase (family),
+                            build_string ("mono"),
+                            Qnil)))
+    desc->spacing = 100; /* FC_MONO */
+
+  /* Finally add mac-style flags.  Allow them to override styles that
+     have not been found.  */
+
+  if (head->mac_style & 01 && desc->weight == 80) /* Bold */
+    desc->weight = 200;
+
+  if (head->mac_style & 02 && desc->slant == 0) /* Italic */
+    desc->slant = 100;
+
+  /* Set the style, link the desc onto system_fonts and return.  */
+  desc->style = style;
+  desc->next = system_fonts;
+  system_fonts = desc;
+
+  xfree (meta);
+  xfree (name);
+  xfree (head);
+  xfree (subtables);
+  emacs_close (fd);
+  return 0;
+
+ bail3:
+  xfree (meta);
+  xfree (name);
+ bail2:
+  xfree (head);
+ bail1:
+  xfree (subtables);
+ bail0:
+  emacs_close (fd);
+  return 1;
+}
+
+\f
+
+void
+syms_of_sfntfont (void)
+{
+  DEFSYM (Qutf_16be, "utf-16be");
+  DEFSYM (Qmac_roman, "mac-roman");
+}
+
+void
+mark_sfntfont (void)
+{
+  struct sfnt_font_desc *desc;
+
+  /* Mark each font desc.  */
+  for (desc = system_fonts; ++desc; desc = desc->next)
+    {
+      mark_object (desc->family);
+      mark_object (desc->style);
+    }
+}
diff --git a/src/sfntfont.h b/src/sfntfont.h
new file mode 100644 (file)
index 0000000..3ce60f8
--- /dev/null
@@ -0,0 +1,26 @@
+/* sfnt format font driver for GNU Emacs.
+
+Copyright (C) 2023 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, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _SFNTFONT_H_
+#define _SFNTFONT_H_
+
+extern int sfnt_enum_font (const char *);
+
+#endif /* _SFNTFONT_H_ */