add a lib for rendering text in sdl2 and rules to make in makefile
This commit is contained in:
93
SDL2_ttf/external/harfbuzz/util/Makefile.am
vendored
Normal file
93
SDL2_ttf/external/harfbuzz/util/Makefile.am
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
# Process this file with automake to produce Makefile.in
|
||||
|
||||
NULL =
|
||||
EXTRA_DIST =
|
||||
CLEANFILES =
|
||||
DISTCLEANFILES =
|
||||
MAINTAINERCLEANFILES =
|
||||
|
||||
EXTRA_DIST += meson.build
|
||||
|
||||
include Makefile.sources
|
||||
|
||||
# Convenience targets:
|
||||
lib:
|
||||
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib
|
||||
libs:
|
||||
@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs
|
||||
|
||||
bin_PROGRAMS =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DHB_DISABLE_DEPRECATED \
|
||||
-I$(top_srcdir)/src/ \
|
||||
-I$(top_builddir)/src/ \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(FREETYPE_CFLAGS) \
|
||||
$(CAIRO_FT_CFLAGS) \
|
||||
$(CHAFA_CFLAGS) \
|
||||
$(NULL)
|
||||
LDADD = \
|
||||
$(top_builddir)/src/libharfbuzz.la \
|
||||
-lm \
|
||||
$(GLIB_LIBS) \
|
||||
$(FREETYPE_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
if HAVE_GLIB
|
||||
|
||||
if HAVE_CAIRO
|
||||
hb_view_SOURCES = $(HB_VIEW_sources)
|
||||
hb_view_LDADD = \
|
||||
$(top_builddir)/src/libharfbuzz-cairo.la \
|
||||
$(LDADD) \
|
||||
$(CAIRO_LIBS) \
|
||||
$(CAIRO_FT_LIBS) \
|
||||
$(CHAFA_LIBS) \
|
||||
$(NULL)
|
||||
bin_PROGRAMS += hb-view
|
||||
endif # HAVE_CAIRO
|
||||
|
||||
hb_shape_SOURCES = $(HB_SHAPE_sources)
|
||||
bin_PROGRAMS += hb-shape
|
||||
|
||||
hb_info_SOURCES = $(HB_INFO_sources)
|
||||
hb_info_LDADD = \
|
||||
$(LDADD) \
|
||||
$(NULL)
|
||||
if HAVE_GOBJECT
|
||||
hb_info_LDADD += \
|
||||
$(top_builddir)/src/libharfbuzz-gobject.la \
|
||||
$(GOBJECT_LIBS) \
|
||||
$(NULL)
|
||||
endif # HAVE_GOBJECT
|
||||
if HAVE_CHAFA
|
||||
hb_info_LDADD += $(CHAFA_LIBS)
|
||||
endif # HAVE_CHAFA
|
||||
bin_PROGRAMS += hb-info
|
||||
|
||||
hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
|
||||
hb_subset_LDADD = \
|
||||
$(top_builddir)/src/libharfbuzz-subset.la \
|
||||
$(LDADD)
|
||||
bin_PROGRAMS += hb-subset
|
||||
|
||||
hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
|
||||
bin_PROGRAMS += hb-ot-shape-closure
|
||||
|
||||
endif # HAVE_GLIB
|
||||
|
||||
#if HAVE_FONTCONFIG
|
||||
#hb_fc_list_SOURCES = \
|
||||
# hb-fc.cc \
|
||||
# hb-fc.h \
|
||||
# hb-fc-list.c \
|
||||
# $(NULL)
|
||||
#hb_fc_list_LDADD = \
|
||||
# $(LDADD) \
|
||||
# $(FONTCONFIG_LIBS) \
|
||||
# $(NULL)
|
||||
#bin_PROGRAMS += hb-fc-list
|
||||
#endif # HAVE_FONTCONFIG
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
||||
59
SDL2_ttf/external/harfbuzz/util/Makefile.sources
vendored
Normal file
59
SDL2_ttf/external/harfbuzz/util/Makefile.sources
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
HB_VIEW_sources = \
|
||||
ansi-print.hh \
|
||||
face-options.hh \
|
||||
font-options.hh \
|
||||
hb-view.cc \
|
||||
helper-cairo-ansi.hh \
|
||||
helper-cairo-ft.hh \
|
||||
helper-cairo.hh \
|
||||
main-font-text.hh \
|
||||
options.hh \
|
||||
output-options.hh \
|
||||
shape-consumer.hh \
|
||||
shape-options.hh \
|
||||
text-options.hh \
|
||||
view-cairo.hh \
|
||||
view-options.hh \
|
||||
$(NULL)
|
||||
|
||||
HB_SHAPE_sources = \
|
||||
batch.hh \
|
||||
face-options.hh \
|
||||
font-options.hh \
|
||||
hb-shape.cc \
|
||||
main-font-text.hh \
|
||||
options.hh \
|
||||
output-options.hh \
|
||||
shape-consumer.hh \
|
||||
shape-format.hh \
|
||||
shape-options.hh \
|
||||
shape-output.hh \
|
||||
text-options.hh \
|
||||
$(NULL)
|
||||
|
||||
HB_INFO_sources = \
|
||||
batch.hh \
|
||||
face-options.hh \
|
||||
font-options.hh \
|
||||
hb-info.cc \
|
||||
options.hh \
|
||||
$(NULL)
|
||||
|
||||
HB_SUBSET_CLI_sources = \
|
||||
batch.hh \
|
||||
face-options.hh \
|
||||
hb-subset.cc \
|
||||
main-font-text.hh \
|
||||
options.hh \
|
||||
output-options.hh \
|
||||
text-options.hh \
|
||||
$(NULL)
|
||||
|
||||
HB_OT_SHAPE_CLOSURE_sources = \
|
||||
face-options.hh \
|
||||
font-options.hh \
|
||||
hb-ot-shape-closure.cc \
|
||||
main-font-text.hh \
|
||||
options.hh \
|
||||
text-options.hh \
|
||||
$(NULL)
|
||||
442
SDL2_ttf/external/harfbuzz/util/ansi-print.hh
vendored
Normal file
442
SDL2_ttf/external/harfbuzz/util/ansi-print.hh
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright © 2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef ANSI_PRINT_HH
|
||||
#define ANSI_PRINT_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER < 1800)
|
||||
static inline long int
|
||||
lround (double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
return floor (x + 0.5);
|
||||
else
|
||||
return ceil (x - 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CELL_W 8
|
||||
#define CELL_H (2 * CELL_W)
|
||||
|
||||
struct color_diff_t
|
||||
{
|
||||
int dot (const color_diff_t &o)
|
||||
{ return v[0]*o.v[0] + v[1]*o.v[1] + v[2]*o.v[2] + v[3]*o.v[3]; }
|
||||
|
||||
int v[4];
|
||||
};
|
||||
|
||||
struct color_t
|
||||
{
|
||||
static color_t from_ansi (unsigned int x)
|
||||
{
|
||||
color_t c = {(0xFFu<<24) | ((0xFFu*(x&1))<<16) | ((0xFFu*((x >> 1)&1))<<8) | (0xFFu*((x >> 2)&1))};
|
||||
return c;
|
||||
}
|
||||
unsigned int to_ansi ()
|
||||
{
|
||||
return ((v >> 23) & 1) | ((v >> 14)&2) | ((v >> 5)&4);
|
||||
}
|
||||
|
||||
color_diff_t diff (const color_t &o)
|
||||
{
|
||||
color_diff_t d;
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
d.v[i] = (int) ((v >> (i*8))&0xFF) - (int) ((o.v >> (i*8))&0xFF);
|
||||
return d;
|
||||
}
|
||||
|
||||
uint32_t v;
|
||||
};
|
||||
|
||||
struct image_t
|
||||
{
|
||||
public:
|
||||
|
||||
image_t (unsigned int width_,
|
||||
unsigned int height_,
|
||||
const uint32_t *data_,
|
||||
unsigned int stride_) :
|
||||
width (width_),
|
||||
height (height_),
|
||||
own_data (false),
|
||||
data ((color_t *) data_),
|
||||
stride (stride_) {}
|
||||
image_t (unsigned int width_,
|
||||
unsigned int height_) :
|
||||
width (width_),
|
||||
height (height_),
|
||||
own_data (true),
|
||||
data ((color_t *) malloc (sizeof (data[0]) * width * height)),
|
||||
stride (width) {}
|
||||
~image_t ()
|
||||
{ if (own_data) free (data); }
|
||||
|
||||
color_t &operator () (unsigned int x, unsigned int y)
|
||||
{ return data[x + y * stride]; }
|
||||
|
||||
color_t operator () (unsigned int x, unsigned int y) const
|
||||
{ return data[x + y * stride]; }
|
||||
|
||||
void
|
||||
copy_sub_image (const image_t &s,
|
||||
unsigned int x, unsigned int y,
|
||||
unsigned int w, unsigned int h)
|
||||
{
|
||||
assert (x < width);
|
||||
assert (y < height);
|
||||
for (unsigned int row = 0; row < h; row++) {
|
||||
color_t *p = data + x + hb_min (y + row, height - 1) * stride;
|
||||
color_t *q = s.data + row * s.stride;
|
||||
if (x + w <= width)
|
||||
for (unsigned int col = 0; col < w; col++)
|
||||
*q++ = *p++;
|
||||
else {
|
||||
unsigned int limit = width - x;
|
||||
for (unsigned int col = 0; col < limit; col++)
|
||||
*q++ = *p++;
|
||||
p--;
|
||||
for (unsigned int col = limit; col < w; col++)
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int width;
|
||||
const unsigned int height;
|
||||
|
||||
private:
|
||||
bool own_data;
|
||||
color_t * const data;
|
||||
const unsigned int stride;
|
||||
};
|
||||
|
||||
struct biimage_t
|
||||
{
|
||||
public:
|
||||
|
||||
biimage_t (unsigned int width, unsigned int height) :
|
||||
width (width),
|
||||
height (height),
|
||||
bg (0), fg (0), unicolor (true),
|
||||
data ((uint8_t *) malloc (sizeof (data[0]) * width * height)) {}
|
||||
~biimage_t ()
|
||||
{ free (data); }
|
||||
|
||||
void set (const image_t &image)
|
||||
{
|
||||
assert (image.width == width);
|
||||
assert (image.height == height);
|
||||
int freq[8] = {0};
|
||||
for (unsigned int y = 0; y < height; y++)
|
||||
for (unsigned int x = 0; x < width; x++) {
|
||||
color_t c = image (x, y);
|
||||
freq[c.to_ansi ()]++;
|
||||
}
|
||||
bg = 0;
|
||||
for (unsigned int i = 1; i < 8; i++)
|
||||
if (freq[bg] < freq[i])
|
||||
bg = i;
|
||||
fg = 8;
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
if (i != bg && (fg == 8 || freq[fg] < freq[i]))
|
||||
fg = i;
|
||||
if (freq[fg] == 0) {
|
||||
fg = bg;
|
||||
unicolor = true;
|
||||
}
|
||||
else
|
||||
unicolor = false;
|
||||
|
||||
/* Set the data... */
|
||||
|
||||
if (unicolor) {
|
||||
memset (data, 0, sizeof (data[0]) * width * height);
|
||||
return;
|
||||
}
|
||||
|
||||
color_t bgc = color_t::from_ansi (bg);
|
||||
color_t fgc = color_t::from_ansi (fg);
|
||||
color_diff_t diff = fgc.diff (bgc);
|
||||
double dd = sqrt (diff.dot (diff));
|
||||
for (unsigned int y = 0; y < height; y++)
|
||||
for (unsigned int x = 0; x < width; x++) {
|
||||
double d = sqrt (diff.dot (image (x, y).diff (bgc)));
|
||||
(*this)(x, y) = d <= 0 ? 0 : d >= dd ? 255 : lround (d / dd * 255.);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t &operator () (unsigned int x, unsigned int y)
|
||||
{ return data[x + y * width]; }
|
||||
|
||||
uint8_t operator () (unsigned int x, unsigned int y) const
|
||||
{ return data[x + y * width]; }
|
||||
|
||||
const unsigned int width;
|
||||
const unsigned int height;
|
||||
unsigned int bg;
|
||||
unsigned int fg;
|
||||
bool unicolor;
|
||||
|
||||
private:
|
||||
uint8_t * const data;
|
||||
};
|
||||
|
||||
static const char *
|
||||
block_best (const biimage_t &bi, bool *inverse)
|
||||
{
|
||||
assert (bi.width <= CELL_W);
|
||||
assert (bi.height <= CELL_H);
|
||||
|
||||
unsigned int score = UINT_MAX;
|
||||
unsigned int row_sum[CELL_H] = {0};
|
||||
unsigned int col_sum[CELL_W] = {0};
|
||||
unsigned int row_sum_i[CELL_H] = {0};
|
||||
unsigned int col_sum_i[CELL_W] = {0};
|
||||
unsigned int quad[2][2] = {{0}};
|
||||
unsigned int quad_i[2][2] = {{0}};
|
||||
unsigned int total = 0;
|
||||
unsigned int total_i = 0;
|
||||
for (unsigned int y = 0; y < bi.height; y++)
|
||||
for (unsigned int x = 0; x < bi.width; x++) {
|
||||
unsigned int c = bi (x, y);
|
||||
unsigned int c_i = 255 - c;
|
||||
row_sum[y] += c;
|
||||
row_sum_i[y] += c_i;
|
||||
col_sum[x] += c;
|
||||
col_sum_i[x] += c_i;
|
||||
quad[2 * y / bi.height][2 * x / bi.width] += c;
|
||||
quad_i[2 * y / bi.height][2 * x / bi.width] += c_i;
|
||||
total += c;
|
||||
total_i += c_i;
|
||||
}
|
||||
|
||||
/* Make the sums cumulative */
|
||||
for (unsigned int i = 1; i < bi.height; i++) {
|
||||
row_sum[i] += row_sum[i - 1];
|
||||
row_sum_i[i] += row_sum_i[i - 1];
|
||||
}
|
||||
for (unsigned int i = 1; i < bi.width; i++) {
|
||||
col_sum[i] += col_sum[i - 1];
|
||||
col_sum_i[i] += col_sum_i[i - 1];
|
||||
}
|
||||
|
||||
const char *best_c = " ";
|
||||
|
||||
/* Maybe empty is better! */
|
||||
if (total < score) {
|
||||
score = total;
|
||||
*inverse = false;
|
||||
best_c = " ";
|
||||
}
|
||||
/* Maybe full is better! */
|
||||
if (total_i < score) {
|
||||
score = total_i;
|
||||
*inverse = true;
|
||||
best_c = " ";
|
||||
}
|
||||
|
||||
/* Find best lower line */
|
||||
if (1) {
|
||||
unsigned int best_s = UINT_MAX;
|
||||
bool best_inv = false;
|
||||
int best_i = 0;
|
||||
for (unsigned int i = 0; i < bi.height - 1; i++)
|
||||
{
|
||||
unsigned int s;
|
||||
s = row_sum[i] + total_i - row_sum_i[i];
|
||||
if (s < best_s) {
|
||||
best_s = s;
|
||||
best_i = i;
|
||||
best_inv = false;
|
||||
}
|
||||
s = row_sum_i[i] + total - row_sum[i];
|
||||
if (s < best_s) {
|
||||
best_s = s;
|
||||
best_i = i;
|
||||
best_inv = true;
|
||||
}
|
||||
}
|
||||
if (best_s < score) {
|
||||
static const char *lower[7] = {"▁", "▂", "▃", "▄", "▅", "▆", "▇"};
|
||||
unsigned int which = lround ((double) ((best_i + 1) * 8) / bi.height);
|
||||
if (1 <= which && which <= 7) {
|
||||
score = best_s;
|
||||
*inverse = best_inv;
|
||||
best_c = lower[7 - which];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find best left line */
|
||||
if (1) {
|
||||
unsigned int best_s = UINT_MAX;
|
||||
bool best_inv = false;
|
||||
int best_i = 0;
|
||||
for (unsigned int i = 0; i < bi.width - 1; i++)
|
||||
{
|
||||
unsigned int s;
|
||||
s = col_sum[i] + total_i - col_sum_i[i];
|
||||
if (s < best_s) {
|
||||
best_s = s;
|
||||
best_i = i;
|
||||
best_inv = true;
|
||||
}
|
||||
s = col_sum_i[i] + total - col_sum[i];
|
||||
if (s < best_s) {
|
||||
best_s = s;
|
||||
best_i = i;
|
||||
best_inv = false;
|
||||
}
|
||||
}
|
||||
if (best_s < score) {
|
||||
static const char *left [7] = {"▏", "▎", "▍", "▌", "▋", "▊", "▉"};
|
||||
unsigned int which = lround ((double) ((best_i + 1) * 8) / bi.width);
|
||||
if (1 <= which && which <= 7) {
|
||||
score = best_s;
|
||||
*inverse = best_inv;
|
||||
best_c = left[which - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find best quadrant */
|
||||
if (1) {
|
||||
unsigned int q = 0;
|
||||
unsigned int qs = 0;
|
||||
for (unsigned int i = 0; i < 2; i++)
|
||||
for (unsigned int j = 0; j < 2; j++)
|
||||
if (quad[i][j] > quad_i[i][j]) {
|
||||
q += 1 << (2 * i + j);
|
||||
qs += quad_i[i][j];
|
||||
} else
|
||||
qs += quad[i][j];
|
||||
if (qs < score) {
|
||||
const char *c = nullptr;
|
||||
bool inv = false;
|
||||
switch (q) {
|
||||
case 1: c = "▟"; inv = true; break;
|
||||
case 2: c = "▙"; inv = true; break;
|
||||
case 4: c = "▖"; inv = false; break;
|
||||
case 6: c = "▞"; inv = false; break;
|
||||
case 7: c = "▛"; inv = false; break;
|
||||
case 8: c = "▗"; inv = false; break;
|
||||
case 9: c = "▚"; inv = false; break;
|
||||
case 11: c = "▜"; inv = false; break;
|
||||
case 13: c = "▙"; inv = false; break;
|
||||
case 14: c = "▟"; inv = false; break;
|
||||
}
|
||||
if (c) {
|
||||
score = qs;
|
||||
*inverse = inv;
|
||||
best_c = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_c;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ansi_print_image_rgb24 (const uint32_t *data,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int stride,
|
||||
cairo_write_func_t write_func,
|
||||
void *closure)
|
||||
{
|
||||
image_t image (width, height, data, stride);
|
||||
|
||||
unsigned int rows = (height + CELL_H - 1) / CELL_H;
|
||||
unsigned int cols = (width + CELL_W - 1) / CELL_W;
|
||||
image_t cell (CELL_W, CELL_H);
|
||||
biimage_t bi (CELL_W, CELL_H);
|
||||
unsigned int last_bg = -1, last_fg = -1;
|
||||
for (unsigned int row = 0; row < rows; row++)
|
||||
{
|
||||
for (unsigned int col = 0; col < cols; col++)
|
||||
{
|
||||
image.copy_sub_image (cell, col * CELL_W, row * CELL_H, CELL_W, CELL_H);
|
||||
bi.set (cell);
|
||||
if (bi.unicolor)
|
||||
{
|
||||
if (last_bg != bi.bg)
|
||||
{
|
||||
char buf[] = "\033[40m";
|
||||
buf[3] += bi.bg;
|
||||
write_func (closure, (unsigned char *) buf, 5);
|
||||
last_bg = bi.bg;
|
||||
}
|
||||
write_func (closure, (unsigned char *) " ", 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Figure out the closest character to the biimage */
|
||||
bool inverse = false;
|
||||
const char *c = block_best (bi, &inverse);
|
||||
if (inverse)
|
||||
{
|
||||
if (last_bg != bi.fg || last_fg != bi.bg)
|
||||
{
|
||||
char buf[] = "\033[30;40m";
|
||||
buf[3] += bi.bg;
|
||||
buf[6] += bi.fg;
|
||||
write_func (closure, (unsigned char *) buf, 8);
|
||||
last_bg = bi.fg;
|
||||
last_fg = bi.bg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last_bg != bi.bg || last_fg != bi.fg)
|
||||
{
|
||||
char buf[] = "\033[40;30m";
|
||||
buf[3] += bi.bg;
|
||||
buf[6] += bi.fg;
|
||||
write_func (closure, (unsigned char *) buf, 8);
|
||||
last_bg = bi.bg;
|
||||
last_fg = bi.fg;
|
||||
}
|
||||
}
|
||||
write_func (closure, (unsigned char *) c, strlen (c));
|
||||
}
|
||||
}
|
||||
write_func (closure, (unsigned char *) "\033[0m\n", 5); /* Reset */
|
||||
last_bg = last_fg = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
75
SDL2_ttf/external/harfbuzz/util/batch.hh
vendored
Normal file
75
SDL2_ttf/external/harfbuzz/util/batch.hh
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright © 2021 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef BATCH_HH
|
||||
#define BATCH_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
typedef int (*main_func_t) (int argc, char **argv);
|
||||
|
||||
template <typename main_t, bool report_status=false>
|
||||
int
|
||||
batch_main (int argc, char **argv)
|
||||
{
|
||||
if (argc == 2 && !strcmp (argv[1], "--batch"))
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[4092];
|
||||
while (fgets (buf, sizeof (buf), stdin))
|
||||
{
|
||||
size_t l = strlen (buf);
|
||||
if (l && buf[l - 1] == '\n') buf[l - 1] = '\0';
|
||||
|
||||
char *args[64];
|
||||
argc = 0;
|
||||
args[argc++] = argv[0];
|
||||
char *p = buf, *e;
|
||||
args[argc++] = p;
|
||||
while ((e = strchr (p, ';')) && argc < (int) ARRAY_LENGTH (args))
|
||||
{
|
||||
*e++ = '\0';
|
||||
while (*e == ';')
|
||||
e++;
|
||||
args[argc++] = p = e;
|
||||
}
|
||||
|
||||
int result = main_t () (argc, args);
|
||||
|
||||
if (report_status)
|
||||
fprintf (stdout, result == 0 ? "success\n" : "failure\n");
|
||||
fflush (stdout);
|
||||
|
||||
ret = MAX (ret, result);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ret = main_t () (argc, argv);
|
||||
if (report_status && ret != 0)
|
||||
fprintf (stdout, "error: Operation failed. Probably a bug. File github issue.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
142
SDL2_ttf/external/harfbuzz/util/face-options.hh
vendored
Normal file
142
SDL2_ttf/external/harfbuzz/util/face-options.hh
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef FACE_OPTIONS_HH
|
||||
#define FACE_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
struct face_options_t
|
||||
{
|
||||
~face_options_t ()
|
||||
{
|
||||
g_free (font_file);
|
||||
}
|
||||
|
||||
void set_face (hb_face_t *face_)
|
||||
{ face = face_; }
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
void post_parse (GError **error);
|
||||
|
||||
static struct cache_t
|
||||
{
|
||||
~cache_t ()
|
||||
{
|
||||
g_free (font_path);
|
||||
hb_blob_destroy (blob);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
char *font_path = nullptr;
|
||||
hb_blob_t *blob = nullptr;
|
||||
unsigned face_index = (unsigned) -1;
|
||||
hb_face_t *face = nullptr;
|
||||
} cache;
|
||||
|
||||
char *font_file = nullptr;
|
||||
unsigned face_index = 0;
|
||||
|
||||
hb_blob_t *blob = nullptr;
|
||||
hb_face_t *face = nullptr;
|
||||
};
|
||||
|
||||
|
||||
face_options_t::cache_t face_options_t::cache {};
|
||||
|
||||
void
|
||||
face_options_t::post_parse (GError **error)
|
||||
{
|
||||
if (!font_file)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"No font file set");
|
||||
return;
|
||||
}
|
||||
|
||||
assert (font_file);
|
||||
|
||||
const char *font_path = font_file;
|
||||
|
||||
if (0 == strcmp (font_path, "-"))
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
setmode (fileno (stdin), O_BINARY);
|
||||
font_path = "STDIN";
|
||||
#else
|
||||
font_path = "/dev/stdin";
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!cache.font_path || 0 != strcmp (cache.font_path, font_path))
|
||||
{
|
||||
hb_blob_destroy (cache.blob);
|
||||
cache.blob = hb_blob_create_from_file_or_fail (font_path);
|
||||
|
||||
free ((char *) cache.font_path);
|
||||
cache.font_path = g_strdup (font_path);
|
||||
|
||||
if (!cache.blob)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"%s: Failed reading file", font_path);
|
||||
return;
|
||||
}
|
||||
|
||||
hb_face_destroy (cache.face);
|
||||
cache.face = nullptr;
|
||||
cache.face_index = (unsigned) -1;
|
||||
}
|
||||
|
||||
if (cache.face_index != face_index)
|
||||
{
|
||||
hb_face_destroy (cache.face);
|
||||
cache.face = hb_face_create (cache.blob, face_index);
|
||||
cache.face_index = face_index;
|
||||
}
|
||||
|
||||
blob = cache.blob;
|
||||
face = cache.face;
|
||||
}
|
||||
|
||||
void
|
||||
face_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
|
||||
{"face-index", 'y', 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"face",
|
||||
"Font-face options:",
|
||||
"Options for the font face",
|
||||
this);
|
||||
}
|
||||
|
||||
#endif
|
||||
381
SDL2_ttf/external/harfbuzz/util/font-options.hh
vendored
Normal file
381
SDL2_ttf/external/harfbuzz/util/font-options.hh
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef FONT_OPTIONS_HH
|
||||
#define FONT_OPTIONS_HH
|
||||
|
||||
#include "face-options.hh"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include <hb-ft.h>
|
||||
#endif
|
||||
#include <hb-ot.h>
|
||||
|
||||
#define FONT_SIZE_UPEM 0x7FFFFFFF
|
||||
#define FONT_SIZE_NONE 0
|
||||
|
||||
extern const unsigned DEFAULT_FONT_SIZE;
|
||||
extern const unsigned SUBPIXEL_BITS;
|
||||
|
||||
struct font_options_t : face_options_t
|
||||
{
|
||||
~font_options_t ()
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
free (variations);
|
||||
#endif
|
||||
g_free (font_funcs);
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
void post_parse (GError **error);
|
||||
|
||||
hb_bool_t sub_font = false;
|
||||
#ifndef HB_NO_VAR
|
||||
hb_variation_t *variations = nullptr;
|
||||
unsigned int num_variations = 0;
|
||||
#endif
|
||||
int x_ppem = 0;
|
||||
int y_ppem = 0;
|
||||
double ptem = 0.;
|
||||
double x_embolden = 0.;
|
||||
double y_embolden = 0.;
|
||||
hb_bool_t embolden_in_place = false;
|
||||
double slant = 0.;
|
||||
unsigned int subpixel_bits = SUBPIXEL_BITS;
|
||||
mutable double font_size_x = DEFAULT_FONT_SIZE;
|
||||
mutable double font_size_y = DEFAULT_FONT_SIZE;
|
||||
char *font_funcs = nullptr;
|
||||
int ft_load_flags = 2;
|
||||
unsigned int named_instance = HB_FONT_NO_VAR_NAMED_INSTANCE;
|
||||
|
||||
hb_font_t *font = nullptr;
|
||||
};
|
||||
|
||||
|
||||
static struct supported_font_funcs_t {
|
||||
char name[4];
|
||||
void (*func) (hb_font_t *);
|
||||
} supported_font_funcs[] =
|
||||
{
|
||||
{"ot", hb_ot_font_set_funcs},
|
||||
#ifdef HAVE_FREETYPE
|
||||
{"ft", hb_ft_font_set_funcs},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
font_options_t::post_parse (GError **error)
|
||||
{
|
||||
assert (!font);
|
||||
font = hb_font_create (face);
|
||||
|
||||
if (font_size_x == FONT_SIZE_UPEM)
|
||||
font_size_x = hb_face_get_upem (face);
|
||||
if (font_size_y == FONT_SIZE_UPEM)
|
||||
font_size_y = hb_face_get_upem (face);
|
||||
|
||||
hb_font_set_ppem (font, x_ppem, y_ppem);
|
||||
hb_font_set_ptem (font, ptem);
|
||||
|
||||
hb_font_set_synthetic_bold (font,
|
||||
(float) x_embolden, (float) y_embolden,
|
||||
embolden_in_place);
|
||||
hb_font_set_synthetic_slant (font, slant);
|
||||
|
||||
int scale_x = (int) scalbnf (font_size_x, subpixel_bits);
|
||||
int scale_y = (int) scalbnf (font_size_y, subpixel_bits);
|
||||
hb_font_set_scale (font, scale_x, scale_y);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
hb_font_set_var_named_instance (font, named_instance);
|
||||
hb_font_set_variations (font, variations, num_variations);
|
||||
#endif
|
||||
|
||||
void (*set_font_funcs) (hb_font_t *) = nullptr;
|
||||
if (!font_funcs)
|
||||
{
|
||||
set_font_funcs = supported_font_funcs[0].func;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
if (0 == g_ascii_strcasecmp (font_funcs, supported_font_funcs[i].name))
|
||||
{
|
||||
set_font_funcs = supported_font_funcs[i].func;
|
||||
break;
|
||||
}
|
||||
if (!set_font_funcs)
|
||||
{
|
||||
GString *s = g_string_new (nullptr);
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
{
|
||||
if (i)
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_font_funcs[i].name);
|
||||
}
|
||||
g_string_append_c (s, '\n');
|
||||
char *p = g_string_free (s, FALSE);
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown font function implementation `%s'; supported values are: %s; default is %s",
|
||||
font_funcs,
|
||||
p,
|
||||
supported_font_funcs[0].name);
|
||||
free (p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_font_funcs (font);
|
||||
#ifdef HAVE_FREETYPE
|
||||
hb_ft_font_set_load_flags (font, ft_load_flags);
|
||||
#endif
|
||||
|
||||
if (sub_font)
|
||||
{
|
||||
hb_font_t *old_font = font;
|
||||
font = hb_font_create_sub_font (old_font);
|
||||
hb_font_set_scale (old_font, scale_x * 2, scale_y * 2);
|
||||
hb_font_destroy (old_font);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
static gboolean
|
||||
parse_variations (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
char *s = (char *) arg;
|
||||
char *p;
|
||||
|
||||
font_opts->num_variations = 0;
|
||||
g_free (font_opts->variations);
|
||||
font_opts->variations = nullptr;
|
||||
|
||||
if (!*s)
|
||||
return true;
|
||||
|
||||
/* count the variations first, so we can allocate memory */
|
||||
p = s;
|
||||
do {
|
||||
font_opts->num_variations++;
|
||||
p = strpbrk (p, ", ");
|
||||
if (p)
|
||||
p++;
|
||||
} while (p);
|
||||
|
||||
font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations));
|
||||
if (!font_opts->variations)
|
||||
return false;
|
||||
|
||||
/* now do the actual parsing */
|
||||
p = s;
|
||||
font_opts->num_variations = 0;
|
||||
while (p && *p) {
|
||||
char *end = strpbrk (p, ", ");
|
||||
if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations]))
|
||||
font_opts->num_variations++;
|
||||
p = end ? end + 1 : nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
parse_font_size (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
if (0 == strcmp (arg, "upem"))
|
||||
{
|
||||
font_opts->font_size_y = font_opts->font_size_x = FONT_SIZE_UPEM;
|
||||
return true;
|
||||
}
|
||||
switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->font_size_x, &font_opts->font_size_y)) {
|
||||
case 1: font_opts->font_size_y = font_opts->font_size_x; HB_FALLTHROUGH;
|
||||
case 2: return true;
|
||||
default:
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"%s argument should be one or two space-separated numbers",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_font_ppem (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) {
|
||||
case 1: font_opts->y_ppem = font_opts->x_ppem; HB_FALLTHROUGH;
|
||||
case 2: return true;
|
||||
default:
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"%s argument should be one or two space-separated numbers",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_font_embolden (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->x_embolden, &font_opts->y_embolden)) {
|
||||
case 1: font_opts->y_embolden = font_opts->x_embolden; HB_FALLTHROUGH;
|
||||
case 2: return true;
|
||||
default:
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"%s argument should be one or two space-separated numbers",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_font_bold (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
font_opts->embolden_in_place = false;
|
||||
return parse_font_embolden ( name, arg, data, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_font_grade (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
font_options_t *font_opts = (font_options_t *) data;
|
||||
font_opts->embolden_in_place = true;
|
||||
return parse_font_embolden ( name, arg, data, error);
|
||||
}
|
||||
|
||||
void
|
||||
font_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
face_options_t::add_options (parser);
|
||||
|
||||
char *text = nullptr;
|
||||
|
||||
{
|
||||
static_assert ((ARRAY_LENGTH_CONST (supported_font_funcs) > 0),
|
||||
"No supported font-funcs found.");
|
||||
GString *s = g_string_new (nullptr);
|
||||
g_string_printf (s, "Set font functions implementation to use (default: %s)\n\n Supported font function implementations are: %s",
|
||||
supported_font_funcs[0].name,
|
||||
supported_font_funcs[0].name);
|
||||
for (unsigned int i = 1; i < ARRAY_LENGTH (supported_font_funcs); i++)
|
||||
{
|
||||
g_string_append_c (s, '/');
|
||||
g_string_append (s, supported_font_funcs[i].name);
|
||||
}
|
||||
text = g_string_free (s, FALSE);
|
||||
parser->free_later (text);
|
||||
}
|
||||
|
||||
char *font_size_text;
|
||||
if (DEFAULT_FONT_SIZE == FONT_SIZE_UPEM)
|
||||
font_size_text = (char *) "Font size (default: upem)";
|
||||
else
|
||||
{
|
||||
font_size_text = g_strdup_printf ("Font size (default: %u)", DEFAULT_FONT_SIZE);
|
||||
parser->free_later (font_size_text);
|
||||
}
|
||||
|
||||
int font_size_flags = DEFAULT_FONT_SIZE == FONT_SIZE_NONE ? G_OPTION_FLAG_HIDDEN : 0;
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"font-size", 0, font_size_flags,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 integers or 'upem'"},
|
||||
{"font-ppem", 0, font_size_flags,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"},
|
||||
{"font-ptem", 0, font_size_flags,
|
||||
G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"},
|
||||
{"font-bold", 0, font_size_flags,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_bold, "Set synthetic bold (default: 0)", "1/2 numbers; eg. 0.05"},
|
||||
{"font-grade", 0, font_size_flags,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_grade, "Set synthetic grade (default: 0)", "1/2 numbers; eg. 0.05"},
|
||||
{"font-slant", 0, font_size_flags,
|
||||
G_OPTION_ARG_DOUBLE, &this->slant, "Set synthetic slant (default: 0)", "slant ratio; eg. 0.2"},
|
||||
{"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
|
||||
{"sub-font", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_NONE, &this->sub_font, "Create a sub-font (default: false)", "boolean"},
|
||||
{"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"font",
|
||||
"Font-instance options:",
|
||||
"Options for the font instance",
|
||||
this,
|
||||
false /* We add below. */);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
const gchar *variations_help = "Comma-separated list of font variations\n"
|
||||
"\n"
|
||||
" Variations are set globally. The format for specifying variation settings\n"
|
||||
" follows. All valid CSS font-variation-settings values other than 'normal'\n"
|
||||
" and 'inherited' are also accepted, though, not documented below.\n"
|
||||
"\n"
|
||||
" The format is a tag, optionally followed by an equals sign, followed by a\n"
|
||||
" number. For example:\n"
|
||||
"\n"
|
||||
" \"wght=500\"\n"
|
||||
" \"slnt=-7.5\"";
|
||||
|
||||
GOptionEntry entries2[] =
|
||||
{
|
||||
{"named-instance", 0, 0, G_OPTION_ARG_INT, &this->named_instance, "Set named-instance index (default: none)", "index"},
|
||||
{"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries2,
|
||||
"variations",
|
||||
"Variations options:",
|
||||
"Options for font variations used",
|
||||
this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
222
SDL2_ttf/external/harfbuzz/util/hb-fc-list.c
vendored
Normal file
222
SDL2_ttf/external/harfbuzz/util/hb-fc-list.c
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright © 2002 Keith Packard
|
||||
* Copyright © 2014 Google, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the author(s) not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. The authors make no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#define HAVE_GETOPT_LONG 1 /* XXX */
|
||||
|
||||
#include "hb-fc.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#else
|
||||
#ifdef linux
|
||||
#define HAVE_GETOPT_LONG 1
|
||||
#endif
|
||||
#define HAVE_GETOPT 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
#define HAVE_GETOPT 0
|
||||
#endif
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
#define HAVE_GETOPT_LONG 0
|
||||
#endif
|
||||
|
||||
#if HAVE_GETOPT_LONG
|
||||
#undef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#include <getopt.h>
|
||||
const struct option longopts[] = {
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"format", 1, 0, 'f'},
|
||||
{"quiet", 0, 0, 'q'},
|
||||
{"version", 0, 0, 'V'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{NULL,0,0,0},
|
||||
};
|
||||
#else
|
||||
#if HAVE_GETOPT
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage (char *program, int error)
|
||||
{
|
||||
FILE *file = error ? stderr : stdout;
|
||||
#if HAVE_GETOPT_LONG
|
||||
fprintf (file, "usage: %s [-vqVh] [-f FORMAT] [--verbose] [--format=FORMAT] [--quiet] [--version] [--help] text [pattern] {element ...} \n",
|
||||
program);
|
||||
#else
|
||||
fprintf (file, "usage: %s [-vqVh] [-f FORMAT] text [pattern] {element ...} \n",
|
||||
program);
|
||||
#endif
|
||||
fprintf (file, "List fonts matching [pattern] that can render [text]\n");
|
||||
fprintf (file, "\n");
|
||||
#if HAVE_GETOPT_LONG
|
||||
fprintf (file, " -v, --verbose display entire font pattern verbosely\n");
|
||||
fprintf (file, " -f, --format=FORMAT use the given output format\n");
|
||||
fprintf (file, " -q, --quiet suppress all normal output, exit 1 if no fonts matched\n");
|
||||
fprintf (file, " -V, --version display font config version and exit\n");
|
||||
fprintf (file, " -h, --help display this help and exit\n");
|
||||
#else
|
||||
fprintf (file, " -v (verbose) display entire font pattern verbosely\n");
|
||||
fprintf (file, " -f FORMAT (format) use the given output format\n");
|
||||
fprintf (file, " -q, (quiet) suppress all normal output, exit 1 if no fonts matched\n");
|
||||
fprintf (file, " -V (version) display HarfBuzz version and exit\n");
|
||||
fprintf (file, " -h (help) display this help and exit\n");
|
||||
#endif
|
||||
exit (error);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int verbose = 0;
|
||||
int quiet = 0;
|
||||
const FcChar8 *format = NULL;
|
||||
int nfont = 0;
|
||||
int i;
|
||||
FcObjectSet *os = 0;
|
||||
FcFontSet *fs;
|
||||
FcPattern *pat;
|
||||
const char *text;
|
||||
#if HAVE_GETOPT_LONG || HAVE_GETOPT
|
||||
int c;
|
||||
|
||||
#if HAVE_GETOPT_LONG
|
||||
while ((c = getopt_long (argc, argv, "vf:qVh", longopts, NULL)) != -1)
|
||||
#else
|
||||
while ((c = getopt (argc, argv, "vf:qVh")) != -1)
|
||||
#endif
|
||||
{
|
||||
switch (c) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'f':
|
||||
format = (FcChar8 *) strdup (optarg);
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'V':
|
||||
fprintf (stderr, "fontconfig version %d.%d.%d\n",
|
||||
FC_MAJOR, FC_MINOR, FC_REVISION);
|
||||
exit (0);
|
||||
case 'h':
|
||||
usage (argv[0], 0);
|
||||
default:
|
||||
usage (argv[0], 1);
|
||||
}
|
||||
}
|
||||
i = optind;
|
||||
#else
|
||||
i = 1;
|
||||
#endif
|
||||
|
||||
if (!argv[i])
|
||||
usage (argv[0], 1);
|
||||
|
||||
text = argv[i];
|
||||
i++;
|
||||
|
||||
if (argv[i])
|
||||
{
|
||||
pat = FcNameParse ((FcChar8 *) argv[i]);
|
||||
if (!pat)
|
||||
{
|
||||
fputs ("Unable to parse the pattern\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
while (argv[++i])
|
||||
{
|
||||
if (!os)
|
||||
os = FcObjectSetCreate ();
|
||||
FcObjectSetAdd (os, argv[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
pat = FcPatternCreate ();
|
||||
if (quiet && !os)
|
||||
os = FcObjectSetCreate ();
|
||||
if (!verbose && !format && !os)
|
||||
os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_FILE, (char *) 0);
|
||||
FcObjectSetAdd (os, FC_CHARSET);
|
||||
if (!format)
|
||||
format = (const FcChar8 *) "%{=fclist}\n";
|
||||
fs = FcFontList (0, pat, os);
|
||||
if (os)
|
||||
FcObjectSetDestroy (os);
|
||||
if (pat)
|
||||
FcPatternDestroy (pat);
|
||||
|
||||
if (!quiet && fs)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < fs->nfont; j++)
|
||||
{
|
||||
hb_font_t *font = hb_fc_font_create (fs->fonts[j]);
|
||||
hb_bool_t can_render = hb_fc_can_render (font, text);
|
||||
hb_font_destroy (font);
|
||||
|
||||
if (!can_render)
|
||||
continue;
|
||||
|
||||
FcPatternDel (fs->fonts[j], FC_CHARSET);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
FcPatternPrint (fs->fonts[j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
FcChar8 *s;
|
||||
|
||||
s = FcPatternFormat (fs->fonts[j], format);
|
||||
if (s)
|
||||
{
|
||||
printf ("%s", s);
|
||||
FcStrFree (s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fs) {
|
||||
nfont = fs->nfont;
|
||||
FcFontSetDestroy (fs);
|
||||
}
|
||||
|
||||
FcFini ();
|
||||
|
||||
return quiet ? (nfont == 0 ? 1 : 0) : 0;
|
||||
}
|
||||
147
SDL2_ttf/external/harfbuzz/util/hb-fc.cc
vendored
Normal file
147
SDL2_ttf/external/harfbuzz/util/hb-fc.cc
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright © 2014 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hb-fc.h"
|
||||
|
||||
static hb_bool_t
|
||||
hb_fc_get_glyph (hb_font_t *font /*HB_UNUSED*/,
|
||||
void *font_data,
|
||||
hb_codepoint_t unicode,
|
||||
hb_codepoint_t variation_selector,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data /*HB_UNUSED*/)
|
||||
|
||||
{
|
||||
FcCharSet *cs = (FcCharSet *) font_data;
|
||||
|
||||
if (variation_selector)
|
||||
{
|
||||
/* Fontconfig doesn't cache cmap-14 info. However:
|
||||
* 1. If the font maps the variation_selector, assume it's
|
||||
* supported,
|
||||
* 2. If the font doesn't map it, still say it's supported,
|
||||
* but return 0. This way, the caller will see the zero
|
||||
* and reject. If we return unsupported here, then the
|
||||
* variation selector will be hidden and ignored.
|
||||
*/
|
||||
if (FcCharSetHasChar (cs, unicode) &&
|
||||
FcCharSetHasChar (cs, variation_selector))
|
||||
{
|
||||
unsigned int var_num = 0;
|
||||
if (variation_selector - 0xFE00u < 16)
|
||||
var_num = variation_selector - 0xFE00 + 1;
|
||||
else if (variation_selector - 0xE0100u < (256 - 16))
|
||||
var_num = variation_selector - 0xE0100 + 17;
|
||||
*glyph = (var_num << 21) | unicode;
|
||||
}
|
||||
else
|
||||
{
|
||||
*glyph = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
*glyph = FcCharSetHasChar (cs, unicode) ? unicode : 0;
|
||||
return *glyph != 0;
|
||||
}
|
||||
|
||||
static hb_font_funcs_t *
|
||||
_hb_fc_get_font_funcs ()
|
||||
{
|
||||
static const hb_font_funcs_t *fc_ffuncs;
|
||||
|
||||
if (!fc_ffuncs)
|
||||
{
|
||||
hb_font_funcs_t *newfuncs = hb_font_funcs_create ();
|
||||
|
||||
hb_font_funcs_set_glyph_func (newfuncs, hb_fc_get_glyph, nullptr, nullptr);
|
||||
|
||||
/* XXX MT-unsafe */
|
||||
if (fc_ffuncs)
|
||||
hb_font_funcs_destroy (newfuncs);
|
||||
else
|
||||
fc_ffuncs = newfuncs;
|
||||
}
|
||||
|
||||
return const_cast<hb_font_funcs_t *> (fc_ffuncs);
|
||||
}
|
||||
|
||||
|
||||
hb_font_t *
|
||||
hb_fc_font_create (FcPattern *fcfont)
|
||||
{
|
||||
static hb_face_t *face;
|
||||
hb_font_t *font;
|
||||
|
||||
FcCharSet *cs;
|
||||
if (FcResultMatch != FcPatternGetCharSet (fcfont, FC_CHARSET, 0, &cs))
|
||||
return hb_font_get_empty ();
|
||||
|
||||
if (!face) /* XXX MT-unsafe */
|
||||
face = hb_face_create (hb_blob_get_empty (), 0);
|
||||
|
||||
font = hb_font_create (face);
|
||||
|
||||
hb_font_set_funcs (font,
|
||||
_hb_fc_get_font_funcs (),
|
||||
FcCharSetCopy (cs),
|
||||
(hb_destroy_func_t) FcCharSetDestroy);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_fc_can_render (hb_font_t *font, const char *text)
|
||||
{
|
||||
static const char *ot[] = {"ot", nullptr};
|
||||
|
||||
hb_buffer_t *buffer = hb_buffer_create ();
|
||||
hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
|
||||
|
||||
/* XXX Do we need this? I think Arabic and Hangul shapers are the
|
||||
* only one that make any use of this. The Hangul case is not really
|
||||
* needed, and for Arabic we'll miss a very narrow set of fonts.
|
||||
* Might be better to force generic shaper perhaps. */
|
||||
hb_buffer_guess_segment_properties (buffer);
|
||||
|
||||
if (!hb_shape_full (font, buffer, nullptr, 0, ot))
|
||||
abort (); /* hb-ot shaper not enabled? */
|
||||
|
||||
unsigned int len;
|
||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &len);
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
if (!info[i].codepoint)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
46
SDL2_ttf/external/harfbuzz/util/hb-fc.h
vendored
Normal file
46
SDL2_ttf/external/harfbuzz/util/hb-fc.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright © 2014 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_FC_H
|
||||
#define HB_FC_H
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
HB_BEGIN_DECLS
|
||||
|
||||
|
||||
hb_font_t *
|
||||
hb_fc_font_create (FcPattern *font);
|
||||
|
||||
hb_bool_t
|
||||
hb_fc_can_render (hb_font_t *font, const char *text);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
#endif /* HB_FC_H */
|
||||
1450
SDL2_ttf/external/harfbuzz/util/hb-info.cc
vendored
Normal file
1450
SDL2_ttf/external/harfbuzz/util/hb-info.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
122
SDL2_ttf/external/harfbuzz/util/hb-ot-shape-closure.cc
vendored
Normal file
122
SDL2_ttf/external/harfbuzz/util/hb-ot-shape-closure.cc
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright © 2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "batch.hh"
|
||||
#include "font-options.hh"
|
||||
#include "main-font-text.hh"
|
||||
#include "shape-options.hh"
|
||||
#include "text-options.hh"
|
||||
|
||||
const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_NONE;
|
||||
const unsigned SUBPIXEL_BITS = 0;
|
||||
|
||||
struct shape_closure_consumer_t
|
||||
{
|
||||
void add_options (struct option_parser_t *parser)
|
||||
{
|
||||
parser->set_summary ("Find glyph set from input text under shaping closure.");
|
||||
shaper.add_options (parser);
|
||||
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"no-glyph-names", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_glyph_names, "Use glyph indices instead of names", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"format",
|
||||
"Format options:",
|
||||
"Options controlling output formatting",
|
||||
this);
|
||||
}
|
||||
|
||||
void init (const font_options_t *font_opts)
|
||||
{
|
||||
glyphs = hb_set_create ();
|
||||
font = hb_font_reference (font_opts->font);
|
||||
failed = false;
|
||||
buffer = hb_buffer_create ();
|
||||
}
|
||||
template <typename text_options_type>
|
||||
bool consume_line (text_options_type &text_opts)
|
||||
{
|
||||
unsigned int text_len;
|
||||
const char *text;
|
||||
if (!(text = text_opts.get_line (&text_len)))
|
||||
return false;
|
||||
|
||||
hb_set_clear (glyphs);
|
||||
shaper.shape_closure (text, text_len, font, buffer, glyphs);
|
||||
|
||||
if (hb_set_is_empty (glyphs))
|
||||
return true;
|
||||
|
||||
/* Print it out! */
|
||||
bool first = true;
|
||||
for (hb_codepoint_t i = -1; hb_set_next (glyphs, &i);)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
printf (" ");
|
||||
if (show_glyph_names)
|
||||
{
|
||||
char glyph_name[64];
|
||||
hb_font_glyph_to_string (font, i, glyph_name, sizeof (glyph_name));
|
||||
printf ("%s", glyph_name);
|
||||
} else
|
||||
printf ("%u", i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void finish (const font_options_t *font_opts)
|
||||
{
|
||||
printf ("\n");
|
||||
hb_font_destroy (font);
|
||||
font = nullptr;
|
||||
hb_set_destroy (glyphs);
|
||||
glyphs = nullptr;
|
||||
hb_buffer_destroy (buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
|
||||
bool failed;
|
||||
|
||||
protected:
|
||||
shape_options_t shaper;
|
||||
hb_bool_t show_glyph_names = true;
|
||||
|
||||
hb_set_t *glyphs = nullptr;
|
||||
hb_font_t *font = nullptr;
|
||||
hb_buffer_t *buffer = nullptr;
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
using main_t = main_font_text_t<shape_closure_consumer_t, font_options_t, text_options_t>;
|
||||
return batch_main<main_t> (argc, argv);
|
||||
}
|
||||
43
SDL2_ttf/external/harfbuzz/util/hb-shape.cc
vendored
Normal file
43
SDL2_ttf/external/harfbuzz/util/hb-shape.cc
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2010 Behdad Esfahbod
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "batch.hh"
|
||||
#include "font-options.hh"
|
||||
#include "main-font-text.hh"
|
||||
#include "shape-consumer.hh"
|
||||
#include "shape-output.hh"
|
||||
#include "text-options.hh"
|
||||
|
||||
const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_UPEM;
|
||||
const unsigned SUBPIXEL_BITS = 0;
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
using main_t = main_font_text_t<shape_consumer_t<shape_output_t>, font_options_t, shape_text_options_t>;
|
||||
return batch_main<main_t> (argc, argv);
|
||||
}
|
||||
1046
SDL2_ttf/external/harfbuzz/util/hb-subset.cc
vendored
Normal file
1046
SDL2_ttf/external/harfbuzz/util/hb-subset.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
43
SDL2_ttf/external/harfbuzz/util/hb-view.cc
vendored
Normal file
43
SDL2_ttf/external/harfbuzz/util/hb-view.cc
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2010 Behdad Esfahbod
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#include "batch.hh"
|
||||
#include "font-options.hh"
|
||||
#include "main-font-text.hh"
|
||||
#include "shape-consumer.hh"
|
||||
#include "text-options.hh"
|
||||
#include "view-cairo.hh"
|
||||
|
||||
const unsigned DEFAULT_FONT_SIZE = 256;
|
||||
const unsigned SUBPIXEL_BITS = 6;
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
using main_t = main_font_text_t<shape_consumer_t<view_cairo_t>, font_options_t, shape_text_options_t>;
|
||||
return batch_main<main_t> (argc, argv);
|
||||
}
|
||||
229
SDL2_ttf/external/harfbuzz/util/helper-cairo-ansi.hh
vendored
Normal file
229
SDL2_ttf/external/harfbuzz/util/helper-cairo-ansi.hh
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright © 2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HELPER_CAIRO_ANSI_HH
|
||||
#define HELPER_CAIRO_ANSI_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#include "ansi-print.hh"
|
||||
|
||||
#ifdef HAVE_CHAFA
|
||||
# include <chafa.h>
|
||||
|
||||
/* Similar to ansi-print.cc */
|
||||
# define CELL_W 8
|
||||
# define CELL_H (2 * CELL_W)
|
||||
|
||||
static void
|
||||
chafa_print_image_rgb24 (const void *data, int width, int height, int stride, int level,
|
||||
cairo_write_func_t write_func,
|
||||
void *closure)
|
||||
{
|
||||
ChafaTermInfo *term_info;
|
||||
ChafaSymbolMap *symbol_map;
|
||||
ChafaCanvasConfig *config;
|
||||
ChafaCanvas *canvas;
|
||||
GString *gs;
|
||||
unsigned int cols = (width + CELL_W - 1) / CELL_W;
|
||||
unsigned int rows = (height + CELL_H - 1) / CELL_H;
|
||||
gchar **environ;
|
||||
ChafaCanvasMode mode;
|
||||
ChafaPixelMode pixel_mode;
|
||||
|
||||
/* Adapt to terminal; use sixels if available, and fall back to symbols
|
||||
* with as many colors as are supported */
|
||||
|
||||
chafa_set_n_threads (1); // https://github.com/hpjansson/chafa/issues/125#issuecomment-1397475217
|
||||
|
||||
environ = g_get_environ ();
|
||||
term_info = chafa_term_db_detect (chafa_term_db_get_default (),
|
||||
environ);
|
||||
|
||||
pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS;
|
||||
|
||||
if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_BEGIN_SIXELS))
|
||||
{
|
||||
pixel_mode = CHAFA_PIXEL_MODE_SIXELS;
|
||||
mode = CHAFA_CANVAS_MODE_TRUECOLOR;
|
||||
}
|
||||
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_DIRECT))
|
||||
mode = CHAFA_CANVAS_MODE_TRUECOLOR;
|
||||
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_256))
|
||||
mode = CHAFA_CANVAS_MODE_INDEXED_240;
|
||||
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_16))
|
||||
mode = CHAFA_CANVAS_MODE_INDEXED_16;
|
||||
else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_INVERT_COLORS))
|
||||
mode = CHAFA_CANVAS_MODE_FGBG_BGFG;
|
||||
else
|
||||
mode = CHAFA_CANVAS_MODE_FGBG;
|
||||
|
||||
/* Create the configuration */
|
||||
|
||||
symbol_map = chafa_symbol_map_new ();
|
||||
chafa_symbol_map_add_by_tags (symbol_map,
|
||||
(ChafaSymbolTags) (CHAFA_SYMBOL_TAG_BLOCK
|
||||
| CHAFA_SYMBOL_TAG_SPACE
|
||||
| (level >= 2 ? CHAFA_SYMBOL_TAG_WEDGE : 0)
|
||||
| (level >= 3 ? CHAFA_SYMBOL_TAG_ALL : 0)
|
||||
));
|
||||
|
||||
config = chafa_canvas_config_new ();
|
||||
chafa_canvas_config_set_canvas_mode (config, mode);
|
||||
chafa_canvas_config_set_pixel_mode (config, pixel_mode);
|
||||
chafa_canvas_config_set_cell_geometry (config, CELL_W, CELL_H);
|
||||
chafa_canvas_config_set_geometry (config, cols, rows);
|
||||
chafa_canvas_config_set_symbol_map (config, symbol_map);
|
||||
chafa_canvas_config_set_color_extractor (config, CHAFA_COLOR_EXTRACTOR_MEDIAN);
|
||||
chafa_canvas_config_set_work_factor (config, 1.0f);
|
||||
|
||||
/* Create canvas, draw to it and render output string */
|
||||
|
||||
canvas = chafa_canvas_new (config);
|
||||
chafa_canvas_draw_all_pixels (canvas,
|
||||
/* Cairo byte order is host native */
|
||||
G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
? CHAFA_PIXEL_BGRA8_PREMULTIPLIED
|
||||
: CHAFA_PIXEL_ARGB8_PREMULTIPLIED,
|
||||
(const guint8 *) data,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
gs = chafa_canvas_print (canvas, term_info);
|
||||
|
||||
/* Print the string */
|
||||
|
||||
write_func (closure, (const unsigned char *) gs->str, gs->len);
|
||||
|
||||
if (pixel_mode != CHAFA_PIXEL_MODE_SIXELS)
|
||||
write_func (closure, (const unsigned char *) "\n", 1);
|
||||
|
||||
/* Free resources */
|
||||
|
||||
g_string_free (gs, TRUE);
|
||||
chafa_canvas_unref (canvas);
|
||||
chafa_canvas_config_unref (config);
|
||||
chafa_symbol_map_unref (symbol_map);
|
||||
chafa_term_info_unref (term_info);
|
||||
g_strfreev (environ);
|
||||
}
|
||||
|
||||
#endif /* HAVE_CHAFA */
|
||||
|
||||
static inline cairo_status_t
|
||||
helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface,
|
||||
cairo_write_func_t write_func,
|
||||
void *closure)
|
||||
{
|
||||
unsigned int width = cairo_image_surface_get_width (surface);
|
||||
unsigned int height = cairo_image_surface_get_height (surface);
|
||||
if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
|
||||
cairo_surface_t *new_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
|
||||
cairo_t *cr = cairo_create (new_surface);
|
||||
if (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_A8) {
|
||||
cairo_set_source_rgb (cr, 0., 0., 0.);
|
||||
cairo_paint (cr);
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
cairo_mask_surface (cr, surface, 0, 0);
|
||||
} else {
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
cairo_paint (cr);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
surface = new_surface;
|
||||
} else
|
||||
cairo_surface_reference (surface);
|
||||
|
||||
unsigned int stride = cairo_image_surface_get_stride (surface);
|
||||
const uint32_t *data = (uint32_t *) (void *) cairo_image_surface_get_data (surface);
|
||||
|
||||
/* We don't have rows to spare on the terminal window...
|
||||
* Find the tight image top/bottom and only print in between. */
|
||||
|
||||
/* Use corner color as background color. */
|
||||
uint32_t bg_color = data ? * (uint32_t *) data : 0;
|
||||
|
||||
/* Drop first row while empty */
|
||||
auto orig_data = data;
|
||||
while (height)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < width; i++)
|
||||
if (data[i] != bg_color)
|
||||
break;
|
||||
if (i < width)
|
||||
break;
|
||||
data += stride / 4;
|
||||
height--;
|
||||
}
|
||||
if (orig_data < data)
|
||||
{
|
||||
data -= stride / 4;
|
||||
height++; /* Add one first blank row for padding. */
|
||||
}
|
||||
|
||||
/* Drop last row while empty */
|
||||
auto orig_height = height;
|
||||
while (height)
|
||||
{
|
||||
const uint32_t *row = data + (height - 1) * stride / 4;
|
||||
unsigned int i;
|
||||
for (i = 0; i < width; i++)
|
||||
if (row[i] != bg_color)
|
||||
break;
|
||||
if (i < width)
|
||||
break;
|
||||
height--;
|
||||
}
|
||||
if (height < orig_height)
|
||||
height++; /* Add one last blank row for padding. */
|
||||
|
||||
if (width && height)
|
||||
{
|
||||
#ifdef HAVE_CHAFA
|
||||
const char *env = getenv ("HB_CHAFA");
|
||||
int chafa_level = 1;
|
||||
if (env)
|
||||
chafa_level = atoi (env);
|
||||
if (chafa_level)
|
||||
chafa_print_image_rgb24 (data, width, height, stride, chafa_level,
|
||||
write_func, closure);
|
||||
else
|
||||
#endif
|
||||
ansi_print_image_rgb24 (data, width, height, stride / 4,
|
||||
write_func, closure);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
130
SDL2_ttf/external/harfbuzz/util/helper-cairo-ft.hh
vendored
Normal file
130
SDL2_ttf/external/harfbuzz/util/helper-cairo-ft.hh
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HELPER_CAIRO_FT_HH
|
||||
#define HELPER_CAIRO_FT_HH
|
||||
|
||||
#include "font-options.hh"
|
||||
|
||||
#include <cairo-ft.h>
|
||||
#include <hb-ft.h>
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
static FT_Library ft_library;
|
||||
|
||||
#ifdef HAVE_ATEXIT
|
||||
static inline
|
||||
void free_ft_library ()
|
||||
{
|
||||
FT_Done_FreeType (ft_library);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_release_blob (void *arg)
|
||||
{
|
||||
FT_Face ft_face = (FT_Face) arg;
|
||||
hb_blob_destroy ((hb_blob_t *) ft_face->generic.data);
|
||||
}
|
||||
|
||||
static inline cairo_font_face_t *
|
||||
helper_cairo_create_ft_font_face (const font_options_t *font_opts)
|
||||
{
|
||||
cairo_font_face_t *cairo_face;
|
||||
/* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because
|
||||
* cairo will reset the face size. As such, create new face...
|
||||
* TODO Perhaps add API to hb-ft to encapsulate this code. */
|
||||
FT_Face ft_face = nullptr;//hb_ft_font_get_face (font);
|
||||
if (!ft_face)
|
||||
{
|
||||
if (!ft_library)
|
||||
{
|
||||
FT_Init_FreeType (&ft_library);
|
||||
#ifdef HAVE_ATEXIT
|
||||
atexit (free_ft_library);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (font_opts->blob, &blob_length);
|
||||
|
||||
if (FT_New_Memory_Face (ft_library,
|
||||
(const FT_Byte *) blob_data,
|
||||
blob_length,
|
||||
font_opts->face_index,
|
||||
&ft_face))
|
||||
fail (false, "FT_New_Memory_Face fail");
|
||||
}
|
||||
if (!ft_face)
|
||||
{
|
||||
/* This allows us to get some boxes at least... */
|
||||
cairo_face = cairo_toy_font_face_create ("@cairo:sans",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft_face->generic.data = hb_blob_reference (font_opts->blob);
|
||||
ft_face->generic.finalizer = _release_blob;
|
||||
|
||||
#if !defined(HB_NO_VAR) && defined(HAVE_FT_SET_VAR_BLEND_COORDINATES)
|
||||
unsigned int num_coords;
|
||||
const float *coords = hb_font_get_var_coords_design (font_opts->font, &num_coords);
|
||||
if (num_coords)
|
||||
{
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed));
|
||||
if (ft_coords)
|
||||
{
|
||||
for (unsigned int i = 0; i < num_coords; i++)
|
||||
ft_coords[i] = coords[i] * 65536.f;
|
||||
FT_Set_Var_Design_Coordinates (ft_face, num_coords, ft_coords);
|
||||
free (ft_coords);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags);
|
||||
}
|
||||
return cairo_face;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
helper_cairo_ft_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
bool ret = false;
|
||||
#ifdef FT_HAS_COLOR
|
||||
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
||||
if (ft_face)
|
||||
{
|
||||
if (FT_HAS_COLOR (ft_face))
|
||||
ret = true;
|
||||
cairo_ft_scaled_font_unlock_face (scaled_font);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
634
SDL2_ttf/external/harfbuzz/util/helper-cairo.hh
vendored
Normal file
634
SDL2_ttf/external/harfbuzz/util/helper-cairo.hh
vendored
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HELPER_CAIRO_HH
|
||||
#define HELPER_CAIRO_HH
|
||||
|
||||
#include "view-options.hh"
|
||||
#include "output-options.hh"
|
||||
#ifdef HAVE_CAIRO_FT
|
||||
# include "helper-cairo-ft.hh"
|
||||
#endif
|
||||
|
||||
#include <cairo.h>
|
||||
#include <hb.h>
|
||||
#include <hb-cairo.h>
|
||||
|
||||
#include "helper-cairo-ansi.hh"
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
# include <cairo-svg.h>
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PDF_SURFACE
|
||||
# include <cairo-pdf.h>
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PS_SURFACE
|
||||
# include <cairo-ps.h>
|
||||
# if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0)
|
||||
# define HAS_EPS 1
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_eps_surface_create_for_stream (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = cairo_ps_surface_create_for_stream (write_func, closure, width, height);
|
||||
cairo_ps_surface_set_eps (surface, true);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
# else
|
||||
# undef HAS_EPS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
helper_cairo_use_hb_draw (const font_options_t *font_opts)
|
||||
{
|
||||
const char *env = getenv ("HB_DRAW");
|
||||
if (!env)
|
||||
/* Older cairo had a bug in rendering COLRv0 fonts in
|
||||
* right-to-left direction as well as clipping issue
|
||||
* with user-fonts.
|
||||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/4051 */
|
||||
return cairo_version () >= CAIRO_VERSION_ENCODE (1, 17, 5);
|
||||
|
||||
return atoi (env);
|
||||
}
|
||||
|
||||
static inline cairo_scaled_font_t *
|
||||
helper_cairo_create_scaled_font (const font_options_t *font_opts,
|
||||
const view_options_t *view_opts)
|
||||
{
|
||||
hb_font_t *font = font_opts->font;
|
||||
bool use_hb_draw = true;
|
||||
|
||||
#ifdef HAVE_CAIRO_FT
|
||||
use_hb_draw = helper_cairo_use_hb_draw (font_opts);
|
||||
#endif
|
||||
|
||||
|
||||
cairo_font_face_t *cairo_face = nullptr;
|
||||
if (use_hb_draw)
|
||||
{
|
||||
cairo_face = hb_cairo_font_face_create_for_font (font);
|
||||
hb_cairo_font_face_set_scale_factor (cairo_face, 1 << font_opts->subpixel_bits);
|
||||
}
|
||||
#ifdef HAVE_CAIRO_FT
|
||||
else
|
||||
cairo_face = helper_cairo_create_ft_font_face (font_opts);
|
||||
#endif
|
||||
|
||||
cairo_matrix_t ctm, font_matrix;
|
||||
cairo_font_options_t *font_options;
|
||||
|
||||
cairo_matrix_init_identity (&ctm);
|
||||
cairo_matrix_init_scale (&font_matrix,
|
||||
font_opts->font_size_x,
|
||||
font_opts->font_size_y);
|
||||
if (!use_hb_draw)
|
||||
font_matrix.xy = -font_opts->slant * font_opts->font_size_x;
|
||||
|
||||
font_options = cairo_font_options_create ();
|
||||
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
|
||||
cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
|
||||
#ifdef CAIRO_COLOR_PALETTE_DEFAULT
|
||||
cairo_font_options_set_color_palette (font_options, view_opts->palette);
|
||||
#endif
|
||||
#ifdef HAVE_CAIRO_FONT_OPTIONS_GET_CUSTOM_PALETTE_COLOR
|
||||
if (view_opts->custom_palette)
|
||||
{
|
||||
char **entries = g_strsplit (view_opts->custom_palette, ",", -1);
|
||||
unsigned idx = 0;
|
||||
for (unsigned i = 0; entries[i]; i++)
|
||||
{
|
||||
const char *p = strchr (entries[i], '=');
|
||||
if (!p)
|
||||
p = entries[i];
|
||||
else
|
||||
{
|
||||
sscanf (entries[i], "%u", &idx);
|
||||
p++;
|
||||
}
|
||||
|
||||
unsigned fr, fg, fb, fa;
|
||||
fr = fg = fb = fa = 0;
|
||||
if (parse_color (p, fr, fg,fb, fa))
|
||||
cairo_font_options_set_custom_palette_color (font_options, idx, fr / 255., fg / 255., fb / 255., fa / 255.);
|
||||
|
||||
idx++;
|
||||
}
|
||||
g_strfreev (entries);
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_scaled_font_t *scaled_font = cairo_scaled_font_create (cairo_face,
|
||||
&font_matrix,
|
||||
&ctm,
|
||||
font_options);
|
||||
|
||||
cairo_font_options_destroy (font_options);
|
||||
cairo_font_face_destroy (cairo_face);
|
||||
|
||||
return scaled_font;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
helper_cairo_scaled_font_has_color (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
hb_font_t *font = hb_cairo_font_face_get_font (cairo_scaled_font_get_font_face (scaled_font));
|
||||
|
||||
#ifdef HAVE_CAIRO_FT
|
||||
if (!font)
|
||||
return helper_cairo_ft_scaled_font_has_color (scaled_font);
|
||||
#endif
|
||||
|
||||
hb_face_t *face = hb_font_get_face (font);
|
||||
|
||||
return hb_ot_color_has_png (face) ||
|
||||
hb_ot_color_has_layers (face) ||
|
||||
hb_ot_color_has_paint (face);
|
||||
}
|
||||
|
||||
|
||||
enum class image_protocol_t {
|
||||
NONE = 0,
|
||||
ITERM2,
|
||||
KITTY,
|
||||
};
|
||||
|
||||
struct finalize_closure_t {
|
||||
void (*callback)(finalize_closure_t *);
|
||||
cairo_surface_t *surface;
|
||||
cairo_write_func_t write_func;
|
||||
void *closure;
|
||||
image_protocol_t protocol;
|
||||
};
|
||||
static cairo_user_data_key_t finalize_closure_key;
|
||||
|
||||
|
||||
static void
|
||||
finalize_ansi (finalize_closure_t *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
status = helper_cairo_surface_write_to_ansi_stream (closure->surface,
|
||||
closure->write_func,
|
||||
closure->closure);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
fail (false, "Failed to write output: %s",
|
||||
cairo_status_to_string (status));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_ansi_surface_create_for_stream (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width,
|
||||
double height,
|
||||
cairo_content_t content,
|
||||
image_protocol_t protocol HB_UNUSED)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
int w = ceil (width);
|
||||
int h = ceil (height);
|
||||
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_A8, w, h);
|
||||
break;
|
||||
default:
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
|
||||
break;
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
|
||||
break;
|
||||
}
|
||||
cairo_status_t status = cairo_surface_status (surface);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
fail (false, "Failed to create cairo surface: %s",
|
||||
cairo_status_to_string (status));
|
||||
|
||||
finalize_closure_t *ansi_closure = g_new0 (finalize_closure_t, 1);
|
||||
ansi_closure->callback = finalize_ansi;
|
||||
ansi_closure->surface = surface;
|
||||
ansi_closure->write_func = write_func;
|
||||
ansi_closure->closure = closure;
|
||||
|
||||
if (cairo_surface_set_user_data (surface,
|
||||
&finalize_closure_key,
|
||||
(void *) ansi_closure,
|
||||
(cairo_destroy_func_t) g_free))
|
||||
g_free ((void *) closure);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
||||
static cairo_status_t
|
||||
byte_array_write_func (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int size)
|
||||
{
|
||||
g_byte_array_append ((GByteArray *) closure, data, size);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
finalize_png (finalize_closure_t *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
GByteArray *bytes = nullptr;
|
||||
GString *string;
|
||||
gchar *base64;
|
||||
size_t base64_len;
|
||||
|
||||
if (closure->protocol == image_protocol_t::NONE)
|
||||
{
|
||||
status = cairo_surface_write_to_png_stream (closure->surface,
|
||||
closure->write_func,
|
||||
closure->closure);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = g_byte_array_new ();
|
||||
status = cairo_surface_write_to_png_stream (closure->surface,
|
||||
byte_array_write_func,
|
||||
bytes);
|
||||
}
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
fail (false, "Failed to write output: %s",
|
||||
cairo_status_to_string (status));
|
||||
|
||||
if (closure->protocol == image_protocol_t::NONE)
|
||||
return;
|
||||
|
||||
base64 = g_base64_encode (bytes->data, bytes->len);
|
||||
base64_len = strlen (base64);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
if (closure->protocol == image_protocol_t::ITERM2)
|
||||
{
|
||||
/* https://iterm2.com/documentation-images.html */
|
||||
g_string_printf (string, "\033]1337;File=inline=1;size=%zu:%s\a\n",
|
||||
base64_len, base64);
|
||||
}
|
||||
else if (closure->protocol == image_protocol_t::KITTY)
|
||||
{
|
||||
#define CHUNK_SIZE 4096
|
||||
/* https://sw.kovidgoyal.net/kitty/graphics-protocol.html */
|
||||
for (size_t pos = 0; pos < base64_len; pos += CHUNK_SIZE)
|
||||
{
|
||||
size_t len = base64_len - pos;
|
||||
|
||||
if (pos == 0)
|
||||
g_string_append (string, "\033_Ga=T,f=100,m=");
|
||||
else
|
||||
g_string_append (string, "\033_Gm=");
|
||||
|
||||
if (len > CHUNK_SIZE)
|
||||
{
|
||||
g_string_append (string, "1;");
|
||||
g_string_append_len (string, base64 + pos, CHUNK_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append (string, "0;");
|
||||
g_string_append_len (string, base64 + pos, len);
|
||||
}
|
||||
|
||||
g_string_append (string, "\033\\");
|
||||
}
|
||||
g_string_append (string, "\n");
|
||||
#undef CHUNK_SIZE
|
||||
}
|
||||
|
||||
closure->write_func (closure->closure, (unsigned char *) string->str, string->len);
|
||||
|
||||
g_byte_array_unref (bytes);
|
||||
g_free (base64);
|
||||
g_string_free (string, TRUE);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_png_surface_create_for_stream (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width,
|
||||
double height,
|
||||
cairo_content_t content,
|
||||
image_protocol_t protocol)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
int w = ceil (width);
|
||||
int h = ceil (height);
|
||||
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_A8, w, h);
|
||||
break;
|
||||
default:
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
|
||||
break;
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
|
||||
break;
|
||||
}
|
||||
cairo_status_t status = cairo_surface_status (surface);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
fail (false, "Failed to create cairo surface: %s",
|
||||
cairo_status_to_string (status));
|
||||
|
||||
finalize_closure_t *png_closure = g_new0 (finalize_closure_t, 1);
|
||||
png_closure->callback = finalize_png;
|
||||
png_closure->surface = surface;
|
||||
png_closure->write_func = write_func;
|
||||
png_closure->closure = closure;
|
||||
png_closure->protocol = protocol;
|
||||
|
||||
if (cairo_surface_set_user_data (surface,
|
||||
&finalize_closure_key,
|
||||
(void *) png_closure,
|
||||
(cairo_destroy_func_t) g_free))
|
||||
g_free ((void *) closure);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static cairo_status_t
|
||||
stdio_write_func (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int size)
|
||||
{
|
||||
FILE *fp = (FILE *) closure;
|
||||
|
||||
while (size) {
|
||||
size_t ret = fwrite (data, 1, size, fp);
|
||||
size -= ret;
|
||||
data += ret;
|
||||
if (size && ferror (fp))
|
||||
fail (false, "Failed to write output: %s", strerror (errno));
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const char *helper_cairo_supported_formats[] =
|
||||
{
|
||||
"ansi",
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
"png",
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
"svg",
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PDF_SURFACE
|
||||
"pdf",
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PS_SURFACE
|
||||
"ps",
|
||||
#ifdef HAS_EPS
|
||||
"eps",
|
||||
#endif
|
||||
#endif
|
||||
nullptr
|
||||
};
|
||||
|
||||
template <typename view_options_t,
|
||||
typename output_options_type>
|
||||
static inline cairo_t *
|
||||
helper_cairo_create_context (double w, double h,
|
||||
view_options_t *view_opts,
|
||||
output_options_type *out_opts,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_surface_t *(*constructor) (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width,
|
||||
double height) = nullptr;
|
||||
cairo_surface_t *(*constructor2) (cairo_write_func_t write_func,
|
||||
void *closure,
|
||||
double width,
|
||||
double height,
|
||||
cairo_content_t content,
|
||||
image_protocol_t protocol) = nullptr;
|
||||
|
||||
image_protocol_t protocol = image_protocol_t::NONE;
|
||||
const char *extension = out_opts->output_format;
|
||||
if (!extension) {
|
||||
#if HAVE_ISATTY
|
||||
if (isatty (fileno (out_opts->out_fp)))
|
||||
{
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
const char *name;
|
||||
/* https://gitlab.com/gnachman/iterm2/-/issues/7154 */
|
||||
if ((name = getenv ("LC_TERMINAL")) != nullptr &&
|
||||
0 == g_ascii_strcasecmp (name, "iTerm2"))
|
||||
{
|
||||
extension = "png";
|
||||
protocol = image_protocol_t::ITERM2;
|
||||
}
|
||||
else if ((name = getenv ("TERM_PROGRAM")) != nullptr &&
|
||||
0 == g_ascii_strcasecmp (name, "WezTerm"))
|
||||
{
|
||||
extension = "png";
|
||||
protocol = image_protocol_t::ITERM2;
|
||||
}
|
||||
else if ((name = getenv ("TERM")) != nullptr &&
|
||||
0 == g_ascii_strcasecmp (name, "xterm-kitty"))
|
||||
{
|
||||
extension = "png";
|
||||
protocol = image_protocol_t::KITTY;
|
||||
}
|
||||
else
|
||||
extension = "ansi";
|
||||
#else
|
||||
extension = "ansi";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
extension = "png";
|
||||
#else
|
||||
extension = "ansi";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (0)
|
||||
;
|
||||
else if (0 == g_ascii_strcasecmp (extension, "ansi"))
|
||||
constructor2 = _cairo_ansi_surface_create_for_stream;
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
else if (0 == g_ascii_strcasecmp (extension, "png"))
|
||||
constructor2 = _cairo_png_surface_create_for_stream;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
else if (0 == g_ascii_strcasecmp (extension, "svg"))
|
||||
constructor = cairo_svg_surface_create_for_stream;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PDF_SURFACE
|
||||
else if (0 == g_ascii_strcasecmp (extension, "pdf"))
|
||||
constructor = cairo_pdf_surface_create_for_stream;
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_PS_SURFACE
|
||||
else if (0 == g_ascii_strcasecmp (extension, "ps"))
|
||||
constructor = cairo_ps_surface_create_for_stream;
|
||||
#ifdef HAS_EPS
|
||||
else if (0 == g_ascii_strcasecmp (extension, "eps"))
|
||||
constructor = _cairo_eps_surface_create_for_stream;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
unsigned int fr, fg, fb, fa, br, bg, bb, ba;
|
||||
const char *color;
|
||||
br = bg = bb = ba = 255;
|
||||
color = view_opts->back ? view_opts->back : DEFAULT_BACK;
|
||||
parse_color (color, br, bg, bb, ba);
|
||||
fr = fg = fb = 0; fa = 255;
|
||||
color = view_opts->fore ? view_opts->fore : DEFAULT_FORE;
|
||||
parse_color (color, fr, fg, fb, fa);
|
||||
|
||||
if (content == CAIRO_CONTENT_ALPHA)
|
||||
{
|
||||
if (view_opts->show_extents ||
|
||||
br != bg || bg != bb ||
|
||||
fr != fg || fg != fb)
|
||||
content = CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
if (ba != 255)
|
||||
content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||
|
||||
cairo_surface_t *surface;
|
||||
FILE *f = out_opts->out_fp;
|
||||
if (constructor)
|
||||
surface = constructor (stdio_write_func, f, w, h);
|
||||
else if (constructor2)
|
||||
surface = constructor2 (stdio_write_func, f, w, h, content, protocol);
|
||||
else
|
||||
fail (false, "Unknown output format `%s'; supported formats are: %s%s",
|
||||
extension,
|
||||
g_strjoinv ("/", const_cast<char**> (helper_cairo_supported_formats)),
|
||||
out_opts->explicit_output_format ? "" :
|
||||
"\nTry setting format using --output-format");
|
||||
|
||||
cairo_t *cr = cairo_create (surface);
|
||||
content = cairo_surface_get_content (surface);
|
||||
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgba (cr, 1., 1., 1., br / 255.);
|
||||
cairo_paint (cr);
|
||||
cairo_set_source_rgba (cr, 1., 1., 1.,
|
||||
(fr / 255.) * (fa / 255.) + (br / 255) * (1 - (fa / 255.)));
|
||||
break;
|
||||
default:
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgba (cr, br / 255., bg / 255., bb / 255., ba / 255.);
|
||||
cairo_paint (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_set_source_rgba (cr, fr / 255., fg / 255., fb / 255., fa / 255.);
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
return cr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
helper_cairo_destroy_context (cairo_t *cr)
|
||||
{
|
||||
finalize_closure_t *closure = (finalize_closure_t *)
|
||||
cairo_surface_get_user_data (cairo_get_target (cr),
|
||||
&finalize_closure_key);
|
||||
if (closure)
|
||||
closure->callback (closure);
|
||||
|
||||
cairo_status_t status = cairo_status (cr);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
fail (false, "Failed: %s",
|
||||
cairo_status_to_string (status));
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
|
||||
struct helper_cairo_line_t {
|
||||
cairo_glyph_t *glyphs = nullptr;
|
||||
unsigned int num_glyphs = 0;
|
||||
char *utf8 = nullptr;
|
||||
unsigned int utf8_len = 0;
|
||||
cairo_text_cluster_t *clusters = nullptr;
|
||||
unsigned int num_clusters = 0;
|
||||
cairo_text_cluster_flags_t cluster_flags = (cairo_text_cluster_flags_t) 0;
|
||||
|
||||
helper_cairo_line_t (const char *utf8_,
|
||||
unsigned utf8_len_,
|
||||
hb_buffer_t *buffer,
|
||||
hb_bool_t utf8_clusters,
|
||||
unsigned subpixel_bits) :
|
||||
utf8 (utf8_ ? g_strndup (utf8_, utf8_len_) : nullptr),
|
||||
utf8_len (utf8_len_)
|
||||
{
|
||||
hb_cairo_glyphs_from_buffer (buffer,
|
||||
utf8_clusters,
|
||||
1 << subpixel_bits, 1 << subpixel_bits,
|
||||
0., 0.,
|
||||
utf8, utf8_len,
|
||||
&glyphs, &num_glyphs,
|
||||
&clusters, &num_clusters,
|
||||
&cluster_flags);
|
||||
}
|
||||
|
||||
void finish ()
|
||||
{
|
||||
if (glyphs)
|
||||
cairo_glyph_free (glyphs);
|
||||
if (clusters)
|
||||
cairo_text_cluster_free (clusters);
|
||||
g_free (utf8);
|
||||
}
|
||||
|
||||
void get_advance (double *x_advance, double *y_advance)
|
||||
{
|
||||
*x_advance = glyphs[num_glyphs].x;
|
||||
*y_advance = glyphs[num_glyphs].y;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
104
SDL2_ttf/external/harfbuzz/util/main-font-text.hh
vendored
Normal file
104
SDL2_ttf/external/harfbuzz/util/main-font-text.hh
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_MAIN_FONT_TEXT_HH
|
||||
#define HB_MAIN_FONT_TEXT_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
/* main() body for utilities taking font and processing text.*/
|
||||
|
||||
template <typename consumer_t,
|
||||
typename font_options_type,
|
||||
typename text_options_type>
|
||||
struct main_font_text_t :
|
||||
option_parser_t,
|
||||
font_options_type,
|
||||
text_options_type,
|
||||
consumer_t
|
||||
{
|
||||
int operator () (int argc, char **argv)
|
||||
{
|
||||
add_options ();
|
||||
parse (&argc, &argv);
|
||||
|
||||
this->init (this);
|
||||
|
||||
while (this->consume_line (*this))
|
||||
;
|
||||
|
||||
this->finish (this);
|
||||
|
||||
return this->failed ? 1 : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void add_options ()
|
||||
{
|
||||
font_options_type::add_options (this);
|
||||
text_options_type::add_options (this);
|
||||
consumer_t::add_options (this);
|
||||
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{G_OPTION_REMAINING, 0, G_OPTION_FLAG_IN_MAIN,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &collect_rest, nullptr, "[FONT-FILE] [TEXT]"},
|
||||
{nullptr}
|
||||
};
|
||||
add_main_group (entries, this);
|
||||
option_parser_t::add_options ();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static gboolean
|
||||
collect_rest (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
main_font_text_t *thiz = (main_font_text_t *) data;
|
||||
|
||||
if (!thiz->font_file)
|
||||
{
|
||||
thiz->font_file = g_strdup (arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!thiz->text && !thiz->text_file)
|
||||
{
|
||||
thiz->text = g_strdup (arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"Too many arguments on the command line");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
74
SDL2_ttf/external/harfbuzz/util/meson.build
vendored
Normal file
74
SDL2_ttf/external/harfbuzz/util/meson.build
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
hb_view_sources = [
|
||||
'hb-view.cc',
|
||||
]
|
||||
|
||||
hb_shape_sources = [
|
||||
'hb-shape.cc',
|
||||
]
|
||||
|
||||
hb_info_sources = [
|
||||
'hb-info.cc',
|
||||
]
|
||||
|
||||
hb_ot_shape_closure_sources = [
|
||||
'hb-ot-shape-closure.cc',
|
||||
]
|
||||
|
||||
hb_subset_cli_sources = [
|
||||
'hb-subset.cc',
|
||||
]
|
||||
|
||||
util_deps = [freetype_dep, cairo_dep, cairo_ft_dep, glib_dep]
|
||||
|
||||
if conf.get('HAVE_GLIB', 0) == 1
|
||||
if conf.get('HAVE_CAIRO', 0) == 1
|
||||
hb_view = executable('hb-view', hb_view_sources,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
dependencies: [util_deps, chafa_dep],
|
||||
link_with: [libharfbuzz, libharfbuzz_cairo],
|
||||
install: true,
|
||||
)
|
||||
meson.override_find_program('hb-view', hb_view)
|
||||
endif
|
||||
|
||||
hb_shape = executable('hb-shape', hb_shape_sources,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
dependencies: util_deps,
|
||||
link_with: [libharfbuzz],
|
||||
install: true,
|
||||
)
|
||||
meson.override_find_program('hb-shape', hb_shape)
|
||||
|
||||
hb_info = executable('hb-info', [hb_info_sources, gobject_enums_h],
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
dependencies: [util_deps, libharfbuzz_gobject_dep, chafa_dep],
|
||||
link_with: [libharfbuzz],
|
||||
install: true,
|
||||
)
|
||||
meson.override_find_program('hb-info', hb_info)
|
||||
|
||||
hb_subset = executable('hb-subset', hb_subset_cli_sources,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
dependencies: util_deps,
|
||||
link_with: [libharfbuzz, libharfbuzz_subset],
|
||||
install: true,
|
||||
)
|
||||
meson.override_find_program('hb-subset', hb_subset)
|
||||
|
||||
hb_ot_shape_closure = executable('hb-ot-shape-closure', hb_ot_shape_closure_sources,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
dependencies: util_deps,
|
||||
link_with: [libharfbuzz],
|
||||
install: true,
|
||||
)
|
||||
meson.override_find_program('hb-ot-shape-closure', hb_ot_shape_closure)
|
||||
else
|
||||
# Disable tests that use this
|
||||
hb_shape = disabler()
|
||||
hb_subset = disabler()
|
||||
endif
|
||||
288
SDL2_ttf/external/harfbuzz/util/options.hh
vendored
Normal file
288
SDL2_ttf/external/harfbuzz/util/options.hh
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef OPTIONS_HH
|
||||
#define OPTIONS_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <io.h> /* for setmode() under Windows */
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> /* for isatty() */
|
||||
#endif
|
||||
|
||||
|
||||
#include <hb-features.h>
|
||||
#include <hb.h>
|
||||
#include <hb-ot.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
|
||||
|
||||
static inline void fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
|
||||
|
||||
static inline void
|
||||
fail (hb_bool_t suggest_help, const char *format, ...)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
va_list vap;
|
||||
va_start (vap, format);
|
||||
msg = g_strdup_vprintf (format, vap);
|
||||
va_end (vap);
|
||||
const char *prgname = g_get_prgname ();
|
||||
g_printerr ("%s: %s\n", prgname, msg);
|
||||
if (suggest_help)
|
||||
g_printerr ("Try `%s --help' for more information.\n", prgname);
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
struct option_parser_t
|
||||
{
|
||||
option_parser_t (const char *parameter_string = nullptr)
|
||||
: context (g_option_context_new (parameter_string)),
|
||||
to_free (g_ptr_array_new ())
|
||||
{}
|
||||
|
||||
static void _g_free_g_func (void *p, void * G_GNUC_UNUSED) { g_free (p); }
|
||||
|
||||
~option_parser_t ()
|
||||
{
|
||||
g_option_context_free (context);
|
||||
g_ptr_array_foreach (to_free, _g_free_g_func, nullptr);
|
||||
g_ptr_array_free (to_free, TRUE);
|
||||
}
|
||||
|
||||
void add_options ();
|
||||
|
||||
static void
|
||||
post_parse_ (void *thiz, GError **error) {}
|
||||
template <typename Type>
|
||||
static auto
|
||||
post_parse_ (Type *thiz, GError **error) -> decltype (thiz->post_parse (error))
|
||||
{ thiz->post_parse (error); }
|
||||
template <typename Type>
|
||||
static gboolean
|
||||
post_parse (GOptionContext *context G_GNUC_UNUSED,
|
||||
GOptionGroup *group G_GNUC_UNUSED,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
option_parser_t::post_parse_ (static_cast<Type *> (data), error);
|
||||
return !*error;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void add_group (GOptionEntry *entries,
|
||||
const gchar *name,
|
||||
const gchar *description,
|
||||
const gchar *help_description,
|
||||
Type *closure,
|
||||
bool add_parse_hooks = true)
|
||||
{
|
||||
GOptionGroup *group = g_option_group_new (name, description, help_description,
|
||||
static_cast<gpointer>(closure), nullptr);
|
||||
g_option_group_add_entries (group, entries);
|
||||
if (add_parse_hooks)
|
||||
g_option_group_set_parse_hooks (group, nullptr, post_parse<Type>);
|
||||
g_option_context_add_group (context, group);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void add_main_group (GOptionEntry *entries,
|
||||
Type *closure)
|
||||
{
|
||||
GOptionGroup *group = g_option_group_new (nullptr, nullptr, nullptr,
|
||||
static_cast<gpointer>(closure), nullptr);
|
||||
g_option_group_add_entries (group, entries);
|
||||
/* https://gitlab.gnome.org/GNOME/glib/-/issues/2460 */
|
||||
//g_option_group_set_parse_hooks (group, nullptr, post_parse<Type>);
|
||||
g_option_context_set_main_group (context, group);
|
||||
}
|
||||
|
||||
void set_summary (const char *summary)
|
||||
{
|
||||
g_option_context_set_summary (context, summary);
|
||||
}
|
||||
void set_description (const char *description)
|
||||
{
|
||||
g_option_context_set_description (context, description);
|
||||
}
|
||||
|
||||
void free_later (char *p) {
|
||||
g_ptr_array_add (to_free, p);
|
||||
}
|
||||
|
||||
bool parse (int *argc, char ***argv, bool ignore_error = false);
|
||||
|
||||
GOptionContext *context;
|
||||
protected:
|
||||
GPtrArray *to_free;
|
||||
};
|
||||
|
||||
|
||||
static inline gchar *
|
||||
shapers_to_string ()
|
||||
{
|
||||
GString *shapers = g_string_new (nullptr);
|
||||
const char **shaper_list = hb_shape_list_shapers ();
|
||||
|
||||
for (; *shaper_list; shaper_list++) {
|
||||
g_string_append (shapers, *shaper_list);
|
||||
g_string_append_c (shapers, ',');
|
||||
}
|
||||
g_string_truncate (shapers, MAX (0, (gint)shapers->len - 1));
|
||||
|
||||
return g_string_free (shapers, false);
|
||||
}
|
||||
|
||||
static G_GNUC_NORETURN gboolean
|
||||
show_version (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
g_printf ("%s (%s) %s\n", g_get_prgname (), PACKAGE_NAME, PACKAGE_VERSION);
|
||||
|
||||
char *shapers = shapers_to_string ();
|
||||
g_printf ("Available shapers: %s\n", shapers);
|
||||
g_free (shapers);
|
||||
if (strcmp (HB_VERSION_STRING, hb_version_string ()))
|
||||
g_printf ("Linked HarfBuzz library has a different version: %s\n", hb_version_string ());
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
inline void
|
||||
option_parser_t::add_options ()
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"version", 0, G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &show_version, "Show version numbers", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
g_option_context_add_main_entries (context, entries, nullptr);
|
||||
}
|
||||
|
||||
inline bool
|
||||
option_parser_t::parse (int *argc, char ***argv, bool ignore_error)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
GError *parse_error = nullptr;
|
||||
if (!g_option_context_parse (context, argc, argv, &parse_error))
|
||||
{
|
||||
if (parse_error)
|
||||
{
|
||||
if (!ignore_error)
|
||||
fail (true, "%s", parse_error->message);
|
||||
g_error_free (parse_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ignore_error)
|
||||
fail (true, "Option parse error");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
|
||||
#if defined (_MSC_VER) && (_MSC_VER < 1800)
|
||||
|
||||
#ifndef FLT_RADIX
|
||||
#define FLT_RADIX 2
|
||||
#endif
|
||||
|
||||
__inline long double scalbn (long double x, int exp)
|
||||
{
|
||||
return x * (pow ((long double) FLT_RADIX, exp));
|
||||
}
|
||||
|
||||
__inline float scalbnf (float x, int exp)
|
||||
{
|
||||
return x * (pow ((float) FLT_RADIX, exp));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
parse_color (const char *s,
|
||||
unsigned &r,
|
||||
unsigned &g,
|
||||
unsigned &b,
|
||||
unsigned &a)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
while (*s == ' ') s++;
|
||||
if (*s == '#') s++;
|
||||
|
||||
unsigned sr, sg, sb, sa;
|
||||
sa = 255;
|
||||
if (sscanf (s, "%2x%2x%2x%2x", &sr, &sg, &sb, &sa) <= 2)
|
||||
{
|
||||
if (sscanf (s, "%1x%1x%1x%1x", &sr, &sg, &sb, &sa) >= 3)
|
||||
{
|
||||
sr *= 17;
|
||||
sg *= 17;
|
||||
sb *= 17;
|
||||
sa *= 17;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = true;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
r = sr;
|
||||
g = sg;
|
||||
b = sb;
|
||||
a = sa;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
117
SDL2_ttf/external/harfbuzz/util/output-options.hh
vendored
Normal file
117
SDL2_ttf/external/harfbuzz/util/output-options.hh
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef OUTPUT_OPTIONS_HH
|
||||
#define OUTPUT_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
template <bool default_stdout = true>
|
||||
struct output_options_t
|
||||
{
|
||||
~output_options_t ()
|
||||
{
|
||||
g_free (output_file);
|
||||
g_free (output_format);
|
||||
if (out_fp && out_fp != stdout)
|
||||
fclose (out_fp);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser,
|
||||
const char **supported_formats = nullptr)
|
||||
{
|
||||
const char *text = nullptr;
|
||||
|
||||
if (supported_formats)
|
||||
{
|
||||
char *items = g_strjoinv ("/", const_cast<char **> (supported_formats));
|
||||
text = g_strdup_printf ("Set output format\n\n Supported output formats are: %s", items);
|
||||
g_free (items);
|
||||
parser->free_later ((char *) text);
|
||||
}
|
||||
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"output-file", 'o', 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"},
|
||||
{"output-format", 'O', supported_formats ? 0 : G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_STRING, &this->output_format, text, "format"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"output",
|
||||
"Output destination & format options:",
|
||||
"Options for the destination & form of the output",
|
||||
this);
|
||||
}
|
||||
|
||||
void post_parse (GError **error)
|
||||
{
|
||||
if (output_format)
|
||||
explicit_output_format = true;
|
||||
|
||||
if (output_file && !output_format)
|
||||
{
|
||||
output_format = strrchr (output_file, '.');
|
||||
if (output_format)
|
||||
{
|
||||
output_format++; /* skip the dot */
|
||||
output_format = g_strdup (output_format);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_file && 0 != strcmp (output_file, "-"))
|
||||
out_fp = fopen (output_file, "wb");
|
||||
else
|
||||
{
|
||||
if (!default_stdout && !output_file)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"No output file was specified");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
setmode (fileno (stdout), O_BINARY);
|
||||
#endif
|
||||
out_fp = stdout;
|
||||
}
|
||||
if (!out_fp)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"Cannot open output file `%s': %s",
|
||||
g_filename_display_name (output_file), strerror (errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *output_file = nullptr;
|
||||
char *output_format = nullptr;
|
||||
|
||||
bool explicit_output_format = false;
|
||||
FILE *out_fp = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
104
SDL2_ttf/external/harfbuzz/util/shape-consumer.hh
vendored
Normal file
104
SDL2_ttf/external/harfbuzz/util/shape-consumer.hh
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_SHAPE_CONSUMER_HH
|
||||
#define HB_SHAPE_CONSUMER_HH
|
||||
|
||||
#include "font-options.hh"
|
||||
#include "shape-options.hh"
|
||||
#include "text-options.hh"
|
||||
|
||||
|
||||
template <typename output_t>
|
||||
struct shape_consumer_t : shape_options_t
|
||||
{
|
||||
void add_options (option_parser_t *parser)
|
||||
{
|
||||
shape_options_t::add_options (parser);
|
||||
output.add_options (parser);
|
||||
}
|
||||
|
||||
template <typename app_t>
|
||||
void init (const app_t *app)
|
||||
{
|
||||
failed = false;
|
||||
buffer = hb_buffer_create ();
|
||||
|
||||
output.init (buffer, app);
|
||||
}
|
||||
template <typename app_t>
|
||||
bool consume_line (app_t &app)
|
||||
{
|
||||
unsigned int text_len;
|
||||
const char *text;
|
||||
if (!(text = app.get_line (&text_len)))
|
||||
return false;
|
||||
|
||||
output.new_line ();
|
||||
|
||||
for (unsigned int n = num_iterations; n; n--)
|
||||
{
|
||||
populate_buffer (buffer, text, text_len, app.text_before, app.text_after, app.font);
|
||||
if (n == 1)
|
||||
output.consume_text (buffer, text, text_len, utf8_clusters);
|
||||
|
||||
const char *error = nullptr;
|
||||
if (!shape (app.font, buffer, &error))
|
||||
{
|
||||
failed = true;
|
||||
output.error (error);
|
||||
if (hb_buffer_get_content_type (buffer) == HB_BUFFER_CONTENT_TYPE_GLYPHS)
|
||||
break;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (glyphs)
|
||||
output.consume_glyphs (buffer, nullptr, 0, false);
|
||||
else
|
||||
output.consume_glyphs (buffer, text, text_len, utf8_clusters);
|
||||
return true;
|
||||
}
|
||||
template <typename app_t>
|
||||
void finish (const app_t *app)
|
||||
{
|
||||
output.finish (buffer, app);
|
||||
hb_buffer_destroy (buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
bool failed = false;
|
||||
|
||||
protected:
|
||||
output_t output;
|
||||
|
||||
hb_buffer_t *buffer = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
214
SDL2_ttf/external/harfbuzz/util/shape-format.hh
vendored
Normal file
214
SDL2_ttf/external/harfbuzz/util/shape-format.hh
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef SHAPE_FORMAT_OPTIONS_HH
|
||||
#define SHAPE_FORMAT_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
|
||||
struct shape_format_options_t
|
||||
{
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
void serialize (hb_buffer_t *buffer,
|
||||
hb_font_t *font,
|
||||
hb_buffer_serialize_format_t format,
|
||||
hb_buffer_serialize_flags_t flags,
|
||||
GString *gs);
|
||||
void serialize_line_no (unsigned int line_no,
|
||||
GString *gs);
|
||||
void serialize_buffer_of_text (hb_buffer_t *buffer,
|
||||
unsigned int line_no,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_font_t *font,
|
||||
GString *gs);
|
||||
void serialize_message (unsigned int line_no,
|
||||
const char *type,
|
||||
const char *msg,
|
||||
GString *gs);
|
||||
void serialize_buffer_of_glyphs (hb_buffer_t *buffer,
|
||||
unsigned int line_no,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_font_t *font,
|
||||
hb_buffer_serialize_format_t output_format,
|
||||
hb_buffer_serialize_flags_t format_flags,
|
||||
GString *gs);
|
||||
|
||||
|
||||
hb_bool_t show_glyph_names = true;
|
||||
hb_bool_t show_positions = true;
|
||||
hb_bool_t show_advances = true;
|
||||
hb_bool_t show_clusters = true;
|
||||
hb_bool_t show_text = false;
|
||||
hb_bool_t show_unicode = false;
|
||||
hb_bool_t show_line_num = false;
|
||||
hb_bool_t show_extents = false;
|
||||
hb_bool_t show_flags = false;
|
||||
hb_bool_t trace = false;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_verbose (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
shape_format_options_t *format_opts = (shape_format_options_t *) data;
|
||||
format_opts->show_text = format_opts->show_unicode = format_opts->show_line_num = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_ned (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
shape_format_options_t *format_opts = (shape_format_options_t *) data;
|
||||
format_opts->show_clusters = format_opts->show_advances = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
shape_format_options_t::serialize (hb_buffer_t *buffer,
|
||||
hb_font_t *font,
|
||||
hb_buffer_serialize_format_t output_format,
|
||||
hb_buffer_serialize_flags_t flags,
|
||||
GString *gs)
|
||||
{
|
||||
unsigned int num_glyphs = hb_buffer_get_length (buffer);
|
||||
unsigned int start = 0;
|
||||
|
||||
while (start < num_glyphs)
|
||||
{
|
||||
char buf[32768];
|
||||
unsigned int consumed;
|
||||
start += hb_buffer_serialize (buffer, start, num_glyphs,
|
||||
buf, sizeof (buf), &consumed,
|
||||
font, output_format, flags);
|
||||
if (!consumed)
|
||||
break;
|
||||
g_string_append (gs, buf);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
shape_format_options_t::serialize_line_no (unsigned int line_no,
|
||||
GString *gs)
|
||||
{
|
||||
if (show_line_num)
|
||||
g_string_append_printf (gs, "%u: ", line_no);
|
||||
}
|
||||
inline void
|
||||
shape_format_options_t::serialize_buffer_of_text (hb_buffer_t *buffer,
|
||||
unsigned int line_no,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_font_t *font,
|
||||
GString *gs)
|
||||
{
|
||||
if (show_text)
|
||||
{
|
||||
serialize_line_no (line_no, gs);
|
||||
g_string_append_c (gs, '(');
|
||||
g_string_append_len (gs, text, text_len);
|
||||
g_string_append_c (gs, ')');
|
||||
g_string_append_c (gs, '\n');
|
||||
}
|
||||
|
||||
if (show_unicode)
|
||||
{
|
||||
serialize_line_no (line_no, gs);
|
||||
serialize (buffer, font, HB_BUFFER_SERIALIZE_FORMAT_TEXT, HB_BUFFER_SERIALIZE_FLAG_DEFAULT, gs);
|
||||
g_string_append_c (gs, '\n');
|
||||
}
|
||||
}
|
||||
inline void
|
||||
shape_format_options_t::serialize_message (unsigned int line_no,
|
||||
const char *type,
|
||||
const char *msg,
|
||||
GString *gs)
|
||||
{
|
||||
serialize_line_no (line_no, gs);
|
||||
g_string_append_printf (gs, "%s: %s", type, msg);
|
||||
g_string_append_c (gs, '\n');
|
||||
}
|
||||
inline void
|
||||
shape_format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer,
|
||||
unsigned int line_no,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_font_t *font,
|
||||
hb_buffer_serialize_format_t output_format,
|
||||
hb_buffer_serialize_flags_t format_flags,
|
||||
GString *gs)
|
||||
{
|
||||
serialize_line_no (line_no, gs);
|
||||
serialize (buffer, font, output_format, format_flags, gs);
|
||||
g_string_append_c (gs, '\n');
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
shape_format_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Prefix each line of output with its corresponding input text", nullptr},
|
||||
{"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Prefix each line of output with its corresponding input codepoint(s)", nullptr},
|
||||
{"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Prefix each line of output with its corresponding input line number", nullptr},
|
||||
{"verbose", 'v', G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_verbose, "Prefix each line of output with all of the above", nullptr},
|
||||
{"no-glyph-names", 0, G_OPTION_FLAG_REVERSE,
|
||||
G_OPTION_ARG_NONE, &this->show_glyph_names, "Output glyph indices instead of names", nullptr},
|
||||
{"no-positions", 0, G_OPTION_FLAG_REVERSE,
|
||||
G_OPTION_ARG_NONE, &this->show_positions, "Do not output glyph positions", nullptr},
|
||||
{"no-advances", 0, G_OPTION_FLAG_REVERSE,
|
||||
G_OPTION_ARG_NONE, &this->show_advances, "Do not output glyph advances", nullptr},
|
||||
{"no-clusters", 0, G_OPTION_FLAG_REVERSE,
|
||||
G_OPTION_ARG_NONE, &this->show_clusters, "Do not output cluster indices", nullptr},
|
||||
{"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Output glyph extents", nullptr},
|
||||
{"show-flags", 0, 0, G_OPTION_ARG_NONE, &this->show_flags, "Output glyph flags", nullptr},
|
||||
{"ned", 'v', G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_ned, "No Extra Data; Do not output clusters or advances", nullptr},
|
||||
{"trace", 'V', 0, G_OPTION_ARG_NONE, &this->trace, "Output interim shaping results", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"output-syntax",
|
||||
"Output syntax:\n"
|
||||
" text: [<glyph name or index>=<glyph cluster index within input>@<horizontal displacement>,<vertical displacement>+<horizontal advance>,<vertical advance>|...]\n"
|
||||
" json: [{\"g\": <glyph name or index>, \"ax\": <horizontal advance>, \"ay\": <vertical advance>, \"dx\": <horizontal displacement>, \"dy\": <vertical displacement>, \"cl\": <glyph cluster index within input>}, ...]\n"
|
||||
"\nOutput syntax options:",
|
||||
"Options for the syntax of the output",
|
||||
this);
|
||||
}
|
||||
|
||||
#endif
|
||||
446
SDL2_ttf/external/harfbuzz/util/shape-options.hh
vendored
Normal file
446
SDL2_ttf/external/harfbuzz/util/shape-options.hh
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef SHAPE_OPTIONS_HH
|
||||
#define SHAPE_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
struct shape_options_t
|
||||
{
|
||||
~shape_options_t ()
|
||||
{
|
||||
g_free (direction);
|
||||
g_free (language);
|
||||
g_free (script);
|
||||
free (features);
|
||||
g_strfreev (shapers);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
void setup_buffer (hb_buffer_t *buffer)
|
||||
{
|
||||
hb_buffer_set_direction (buffer, hb_direction_from_string (direction, -1));
|
||||
hb_buffer_set_script (buffer, hb_script_from_string (script, -1));
|
||||
hb_buffer_set_language (buffer, hb_language_from_string (language, -1));
|
||||
hb_buffer_set_flags (buffer, (hb_buffer_flags_t)
|
||||
(HB_BUFFER_FLAG_DEFAULT |
|
||||
(bot ? HB_BUFFER_FLAG_BOT : 0) |
|
||||
(eot ? HB_BUFFER_FLAG_EOT : 0) |
|
||||
(verify ? HB_BUFFER_FLAG_VERIFY : 0) |
|
||||
(unsafe_to_concat ? HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT : 0) |
|
||||
(safe_to_insert_tatweel ? HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL : 0) |
|
||||
(preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0) |
|
||||
(remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) |
|
||||
0));
|
||||
hb_buffer_set_invisible_glyph (buffer, invisible_glyph);
|
||||
hb_buffer_set_not_found_glyph (buffer, not_found_glyph);
|
||||
hb_buffer_set_cluster_level (buffer, cluster_level);
|
||||
hb_buffer_guess_segment_properties (buffer);
|
||||
}
|
||||
|
||||
void populate_buffer (hb_buffer_t *buffer, const char *text, int text_len,
|
||||
const char *text_before, const char *text_after,
|
||||
hb_font_t *font)
|
||||
{
|
||||
hb_buffer_clear_contents (buffer);
|
||||
|
||||
if (glyphs)
|
||||
{
|
||||
/* Call the setup_buffer first while the buffer is empty,
|
||||
* as guess_segment_properties doesn't like glyphs in the buffer. */
|
||||
|
||||
setup_buffer (buffer);
|
||||
char *glyphs_text = (char *) text;
|
||||
int glyphs_len = text_len;
|
||||
if (glyphs_len < 0)
|
||||
glyphs_len = strlen (glyphs_text);
|
||||
|
||||
if (glyphs_len && glyphs_text[glyphs_len - 1] != ']')
|
||||
{
|
||||
glyphs_text = g_strdup_printf ("%*s]", glyphs_len, glyphs_text);
|
||||
glyphs_len = -1;
|
||||
}
|
||||
|
||||
hb_buffer_deserialize_glyphs (buffer,
|
||||
glyphs_text, glyphs_len,
|
||||
nullptr,
|
||||
font,
|
||||
HB_BUFFER_SERIALIZE_FORMAT_TEXT);
|
||||
|
||||
if (!strchr (glyphs_text, '+'))
|
||||
{
|
||||
scale_advances = false;
|
||||
unsigned count;
|
||||
hb_direction_t direction = hb_buffer_get_direction (buffer);
|
||||
hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, &count);
|
||||
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, &count);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
hb_font_get_glyph_advance_for_direction (font,
|
||||
infos[i].codepoint,
|
||||
direction,
|
||||
&positions[i].x_advance,
|
||||
&positions[i].y_advance);
|
||||
}
|
||||
|
||||
if (glyphs_text != text)
|
||||
g_free (glyphs_text);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (text_before) {
|
||||
unsigned int len = strlen (text_before);
|
||||
hb_buffer_add_utf8 (buffer, text_before, len, len, 0);
|
||||
}
|
||||
hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
|
||||
if (text_after) {
|
||||
hb_buffer_add_utf8 (buffer, text_after, -1, 0, 0);
|
||||
}
|
||||
|
||||
if (!utf8_clusters) {
|
||||
/* Reset cluster values to refer to Unicode character index
|
||||
* instead of UTF-8 index. */
|
||||
unsigned int num_glyphs = hb_buffer_get_length (buffer);
|
||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
|
||||
for (unsigned int i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
info->cluster = i;
|
||||
info++;
|
||||
}
|
||||
}
|
||||
|
||||
setup_buffer (buffer);
|
||||
}
|
||||
|
||||
hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer, const char **error=nullptr)
|
||||
{
|
||||
if (glyphs)
|
||||
{
|
||||
/* Scale positions. */
|
||||
int x_scale, y_scale;
|
||||
hb_font_get_scale (font, &x_scale, &y_scale);
|
||||
unsigned upem = hb_face_get_upem (hb_font_get_face (font));
|
||||
unsigned count;
|
||||
auto *positions = hb_buffer_get_glyph_positions (buffer, &count);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
auto &pos = positions[i];
|
||||
pos.x_offset = pos.x_offset * x_scale / upem;
|
||||
pos.y_offset = pos.y_offset * y_scale / upem;
|
||||
if (scale_advances)
|
||||
{
|
||||
pos.x_advance = pos.x_advance * x_scale / upem;
|
||||
pos.y_advance = pos.y_advance * y_scale / upem;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (advance <= 0)
|
||||
{
|
||||
if (!hb_shape_full (font, buffer, features, num_features, shapers))
|
||||
{
|
||||
if (error)
|
||||
*error = "Shaping failed.";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (advance < 0)
|
||||
{
|
||||
float unit = (1 << SUBPIXEL_BITS);
|
||||
|
||||
/* Calculate buffer advance */
|
||||
float w = 0;
|
||||
unsigned count = 0;
|
||||
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &count);
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (hb_buffer_get_direction (buffer)))
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
w += pos[i].x_advance;
|
||||
else
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
w += pos[i].y_advance;
|
||||
|
||||
printf ("Default size: %u\n", (unsigned) roundf (w / unit));
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
else
|
||||
{
|
||||
float unit = (1 << SUBPIXEL_BITS);
|
||||
float target_advance = advance * unit;
|
||||
float w = 0;
|
||||
hb_tag_t var_tag;
|
||||
float var_value;
|
||||
if (!hb_shape_justify (font, buffer, features, num_features, shapers,
|
||||
target_advance - unit * 0.5f, target_advance + unit * 0.5f,
|
||||
&w, &var_tag, &var_value))
|
||||
{
|
||||
if (error)
|
||||
*error = "Shaping failed.";
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (normalize_glyphs)
|
||||
hb_buffer_normalize_glyphs (buffer);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
void shape_closure (const char *text, int text_len,
|
||||
hb_font_t *font, hb_buffer_t *buffer,
|
||||
hb_set_t *glyphs)
|
||||
{
|
||||
hb_buffer_reset (buffer);
|
||||
hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
|
||||
setup_buffer (buffer);
|
||||
hb_ot_shape_glyphs_closure (font, buffer, features, num_features, glyphs);
|
||||
}
|
||||
|
||||
/* Buffer properties */
|
||||
char *direction = nullptr;
|
||||
char *language = nullptr;
|
||||
char *script = nullptr;
|
||||
|
||||
/* Buffer flags */
|
||||
hb_bool_t bot = false;
|
||||
hb_bool_t eot = false;
|
||||
hb_bool_t preserve_default_ignorables = false;
|
||||
hb_bool_t remove_default_ignorables = false;
|
||||
|
||||
hb_feature_t *features = nullptr;
|
||||
unsigned int num_features = 0;
|
||||
char **shapers = nullptr;
|
||||
signed advance = 0;
|
||||
hb_bool_t utf8_clusters = false;
|
||||
hb_codepoint_t invisible_glyph = 0;
|
||||
hb_codepoint_t not_found_glyph = 0;
|
||||
hb_buffer_cluster_level_t cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
|
||||
hb_bool_t normalize_glyphs = false;
|
||||
hb_bool_t glyphs = false;
|
||||
bool scale_advances = true;
|
||||
hb_bool_t verify = false;
|
||||
hb_bool_t unsafe_to_concat = false;
|
||||
hb_bool_t safe_to_insert_tatweel = false;
|
||||
unsigned int num_iterations = 1;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_shapers (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
shape_options_t *shape_opts = (shape_options_t *) data;
|
||||
char **shapers = g_strsplit (arg, ",", 0);
|
||||
|
||||
for (char **shaper = shapers; *shaper; shaper++)
|
||||
{
|
||||
bool found = false;
|
||||
for (const char **hb_shaper = hb_shape_list_shapers (); *hb_shaper; hb_shaper++) {
|
||||
if (strcmp (*shaper, *hb_shaper) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Unknown or unsupported shaper: %s", *shaper);
|
||||
g_strfreev (shapers);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (shape_opts->shapers);
|
||||
shape_opts->shapers = shapers;
|
||||
return true;
|
||||
}
|
||||
|
||||
static G_GNUC_NORETURN gboolean
|
||||
list_shapers (const char *name G_GNUC_UNUSED,
|
||||
const char *arg G_GNUC_UNUSED,
|
||||
gpointer data G_GNUC_UNUSED,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
for (const char **shaper = hb_shape_list_shapers (); *shaper; shaper++)
|
||||
g_printf ("%s\n", *shaper);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_features (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
shape_options_t *shape_opts = (shape_options_t *) data;
|
||||
char *s = (char *) arg;
|
||||
size_t l = strlen (s);
|
||||
char *p;
|
||||
|
||||
shape_opts->num_features = 0;
|
||||
g_free (shape_opts->features);
|
||||
shape_opts->features = nullptr;
|
||||
|
||||
/* if the string is quoted, strip the quotes */
|
||||
if (s[0] == s[l - 1] && (s[0] == '\"' || s[0] == '\''))
|
||||
{
|
||||
s[l - 1] = '\0';
|
||||
s++;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return true;
|
||||
|
||||
/* count the features first, so we can allocate memory */
|
||||
p = s;
|
||||
do {
|
||||
shape_opts->num_features++;
|
||||
p = strpbrk (p, ", ");
|
||||
if (p)
|
||||
p++;
|
||||
} while (p);
|
||||
|
||||
shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
|
||||
if (!shape_opts->features)
|
||||
return false;
|
||||
|
||||
/* now do the actual parsing */
|
||||
p = s;
|
||||
shape_opts->num_features = 0;
|
||||
while (p && *p) {
|
||||
char *end = strpbrk (p, ", ");
|
||||
if (hb_feature_from_string (p, end ? end - p : -1, &shape_opts->features[shape_opts->num_features]))
|
||||
shape_opts->num_features++;
|
||||
p = end ? end + 1 : nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
shape_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"list-shapers", 0, G_OPTION_FLAG_NO_ARG,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &list_shapers, "List available shapers and quit", nullptr},
|
||||
{"shaper", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Hidden duplicate of --shapers", nullptr},
|
||||
{"shapers", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Set comma-separated list of shapers to try","list"},
|
||||
{"direction", 0, 0, G_OPTION_ARG_STRING, &this->direction, "Set text direction (default: auto)", "ltr/rtl/ttb/btt"},
|
||||
{"language", 0, 0, G_OPTION_ARG_STRING, &this->language, "Set text language (default: $LANG)", "BCP 47 tag"},
|
||||
{"script", 0, 0, G_OPTION_ARG_STRING, &this->script, "Set text script (default: auto)", "ISO-15924 tag"},
|
||||
{"bot", 0, 0, G_OPTION_ARG_NONE, &this->bot, "Treat text as beginning-of-paragraph", nullptr},
|
||||
{"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", nullptr},
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
{"justify-to", 0, 0,
|
||||
G_OPTION_ARG_INT, &this->advance, "Target size to justify to", "SIZE, or -1"},
|
||||
#endif
|
||||
{"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", nullptr},
|
||||
{"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->remove_default_ignorables, "Remove Default-Ignorable characters", nullptr},
|
||||
{"invisible-glyph", 0, 0, G_OPTION_ARG_INT, &this->invisible_glyph, "Glyph value to replace Default-Ignorables with", nullptr},
|
||||
{"not-found-glyph", 0, 0, G_OPTION_ARG_INT, &this->not_found_glyph, "Glyph value to replace not-found characters with", nullptr},
|
||||
{"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr},
|
||||
{"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"},
|
||||
{"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr},
|
||||
{"unsafe-to-concat",0, 0, G_OPTION_ARG_NONE, &this->unsafe_to_concat, "Produce unsafe-to-concat glyph flag", nullptr},
|
||||
{"safe-to-insert-tatweel",0, 0, G_OPTION_ARG_NONE, &this->safe_to_insert_tatweel, "Produce safe-to-insert-tatweel glyph flag", nullptr},
|
||||
{"glyphs", 0, 0, G_OPTION_ARG_NONE, &this->glyphs, "Interpret input as glyph string", nullptr},
|
||||
{"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr},
|
||||
{"num-iterations", 'n',G_OPTION_FLAG_IN_MAIN,
|
||||
G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"shape",
|
||||
"Shape options:",
|
||||
"Options for the shaping process",
|
||||
this);
|
||||
|
||||
const gchar *features_help = "Comma-separated list of font features\n"
|
||||
"\n"
|
||||
" Features can be enabled or disabled, either globally or limited to\n"
|
||||
" specific character ranges. The format for specifying feature settings\n"
|
||||
" follows. All valid CSS font-feature-settings values other than 'normal'\n"
|
||||
" and the global values are also accepted, though not documented below.\n"
|
||||
" CSS string escapes are not supported."
|
||||
"\n"
|
||||
" The range indices refer to the positions between Unicode characters,\n"
|
||||
" unless the --utf8-clusters is provided, in which case range indices\n"
|
||||
" refer to UTF-8 byte indices. The position before the first character\n"
|
||||
" is always 0.\n"
|
||||
"\n"
|
||||
" The format is Python-esque. Here is how it all works:\n"
|
||||
"\n"
|
||||
" Syntax: Value: Start: End:\n"
|
||||
"\n"
|
||||
" Setting value:\n"
|
||||
" \"kern\" 1 0 ∞ # Turn feature on\n"
|
||||
" \"+kern\" 1 0 ∞ # Turn feature on\n"
|
||||
" \"-kern\" 0 0 ∞ # Turn feature off\n"
|
||||
" \"kern=0\" 0 0 ∞ # Turn feature off\n"
|
||||
" \"kern=1\" 1 0 ∞ # Turn feature on\n"
|
||||
" \"aalt=2\" 2 0 ∞ # Choose 2nd alternate\n"
|
||||
"\n"
|
||||
" Setting index:\n"
|
||||
" \"kern[]\" 1 0 ∞ # Turn feature on\n"
|
||||
" \"kern[:]\" 1 0 ∞ # Turn feature on\n"
|
||||
" \"kern[5:]\" 1 5 ∞ # Turn feature on, partial\n"
|
||||
" \"kern[:5]\" 1 0 5 # Turn feature on, partial\n"
|
||||
" \"kern[3:5]\" 1 3 5 # Turn feature on, range\n"
|
||||
" \"kern[3]\" 1 3 3+1 # Turn feature on, single char\n"
|
||||
"\n"
|
||||
" Mixing it all:\n"
|
||||
"\n"
|
||||
" \"aalt[3:5]=2\" 2 3 5 # Turn 2nd alternate on for range";
|
||||
|
||||
GOptionEntry entries2[] =
|
||||
{
|
||||
{"features", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_features, features_help, "list"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries2,
|
||||
"features",
|
||||
"Features options:",
|
||||
"Options for font features used",
|
||||
this);
|
||||
}
|
||||
|
||||
#endif
|
||||
159
SDL2_ttf/external/harfbuzz/util/shape-output.hh
vendored
Normal file
159
SDL2_ttf/external/harfbuzz/util/shape-output.hh
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright © 2010 Behdad Esfahbod
|
||||
* Copyright © 2011,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_SHAPE_OUTPUT_HH
|
||||
#define HB_SHAPE_OUTPUT_HH
|
||||
|
||||
#include "shape-format.hh"
|
||||
#include "output-options.hh"
|
||||
|
||||
|
||||
struct shape_output_t : output_options_t<>
|
||||
{
|
||||
void add_options (option_parser_t *parser)
|
||||
{
|
||||
parser->set_summary ("Shape text with given font.");
|
||||
output_options_t::add_options (parser, hb_buffer_serialize_list_formats ());
|
||||
format.add_options (parser);
|
||||
}
|
||||
|
||||
void init (hb_buffer_t *buffer, const font_options_t *font_opts)
|
||||
{
|
||||
gs = g_string_new (nullptr);
|
||||
line_no = 0;
|
||||
font = hb_font_reference (font_opts->font);
|
||||
|
||||
if (!output_format)
|
||||
serialize_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
|
||||
else
|
||||
serialize_format = hb_buffer_serialize_format_from_string (output_format, -1);
|
||||
/* An empty "output_format" parameter basically skips output generating.
|
||||
* Useful for benchmarking. */
|
||||
if ((!output_format || *output_format) &&
|
||||
!hb_buffer_serialize_format_to_string (serialize_format))
|
||||
{
|
||||
if (explicit_output_format)
|
||||
fail (false, "Unknown output format `%s'; supported formats are: %s",
|
||||
output_format,
|
||||
g_strjoinv ("/", const_cast<char**> (hb_buffer_serialize_list_formats ())));
|
||||
else
|
||||
/* Just default to TEXT if not explicitly requested and the
|
||||
* file extension is not recognized. */
|
||||
serialize_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
|
||||
}
|
||||
|
||||
unsigned int flags = HB_BUFFER_SERIALIZE_FLAG_DEFAULT;
|
||||
if (!format.show_glyph_names)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES;
|
||||
if (!format.show_clusters)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS;
|
||||
if (!format.show_positions)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
|
||||
if (!format.show_advances)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES;
|
||||
if (format.show_extents)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS;
|
||||
if (format.show_flags)
|
||||
flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS;
|
||||
serialize_flags = (hb_buffer_serialize_flags_t) flags;
|
||||
|
||||
if (format.trace)
|
||||
hb_buffer_set_message_func (buffer, message_func, this, nullptr);
|
||||
}
|
||||
void new_line () { line_no++; }
|
||||
void consume_text (hb_buffer_t *buffer,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_bool_t utf8_clusters)
|
||||
{
|
||||
g_string_set_size (gs, 0);
|
||||
format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
|
||||
fprintf (out_fp, "%s", gs->str);
|
||||
}
|
||||
void error (const char *message)
|
||||
{
|
||||
g_string_set_size (gs, 0);
|
||||
format.serialize_message (line_no, "error", message, gs);
|
||||
fprintf (out_fp, "%s", gs->str);
|
||||
}
|
||||
void consume_glyphs (hb_buffer_t *buffer,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_bool_t utf8_clusters)
|
||||
{
|
||||
g_string_set_size (gs, 0);
|
||||
format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
|
||||
serialize_format, serialize_flags, gs);
|
||||
fprintf (out_fp, "%s", gs->str);
|
||||
}
|
||||
void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
|
||||
{
|
||||
hb_buffer_set_message_func (buffer, nullptr, nullptr, nullptr);
|
||||
hb_font_destroy (font);
|
||||
g_string_free (gs, true);
|
||||
gs = nullptr;
|
||||
font = nullptr;
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
message_func (hb_buffer_t *buffer,
|
||||
hb_font_t *font,
|
||||
const char *message,
|
||||
void *user_data)
|
||||
{
|
||||
shape_output_t *that = (shape_output_t *) user_data;
|
||||
that->trace (buffer, font, message);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
trace (hb_buffer_t *buffer,
|
||||
hb_font_t *font,
|
||||
const char *message)
|
||||
{
|
||||
g_string_set_size (gs, 0);
|
||||
format.serialize_line_no (line_no, gs);
|
||||
g_string_append_printf (gs, "trace: %s buffer: ", message);
|
||||
format.serialize (buffer, font, serialize_format, serialize_flags, gs);
|
||||
g_string_append_c (gs, '\n');
|
||||
fprintf (stderr, "%s", gs->str);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
shape_format_options_t format;
|
||||
|
||||
GString *gs = nullptr;
|
||||
unsigned int line_no = 0;
|
||||
hb_font_t *font = nullptr;
|
||||
hb_buffer_serialize_format_t serialize_format = HB_BUFFER_SERIALIZE_FORMAT_INVALID;
|
||||
hb_buffer_serialize_flags_t serialize_flags = HB_BUFFER_SERIALIZE_FLAG_DEFAULT;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
370
SDL2_ttf/external/harfbuzz/util/text-options.hh
vendored
Normal file
370
SDL2_ttf/external/harfbuzz/util/text-options.hh
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef TEXT_OPTIONS_HH
|
||||
#define TEXT_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
struct text_options_t
|
||||
{
|
||||
text_options_t ()
|
||||
: gs (g_string_new (nullptr))
|
||||
{}
|
||||
~text_options_t ()
|
||||
{
|
||||
g_free (text);
|
||||
g_free (text_file);
|
||||
if (gs)
|
||||
g_string_free (gs, true);
|
||||
if (in_fp && in_fp != stdin)
|
||||
fclose (in_fp);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
void post_parse (GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
if (!text && !text_file)
|
||||
text_file = g_strdup ("-");
|
||||
|
||||
if (text && text_file)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Only one of text and text-file can be set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (text_file)
|
||||
{
|
||||
if (0 != strcmp (text_file, "-"))
|
||||
in_fp = fopen (text_file, "r");
|
||||
else
|
||||
in_fp = stdin;
|
||||
|
||||
if (!in_fp)
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||
"Failed opening text file `%s': %s",
|
||||
text_file, strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_line (unsigned int *len);
|
||||
|
||||
int text_len = -1;
|
||||
char *text = nullptr;
|
||||
char *text_file = nullptr;
|
||||
|
||||
private:
|
||||
FILE *in_fp = nullptr;
|
||||
GString *gs = nullptr;
|
||||
char *line = nullptr;
|
||||
unsigned line_len = UINT_MAX;
|
||||
hb_bool_t single_par = false;
|
||||
};
|
||||
|
||||
struct shape_text_options_t : text_options_t
|
||||
{
|
||||
~shape_text_options_t ()
|
||||
{
|
||||
g_free (text_before);
|
||||
g_free (text_after);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
char *text_before = nullptr;
|
||||
char *text_after = nullptr;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_text (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
text_options_t *text_opts = (text_options_t *) data;
|
||||
|
||||
if (text_opts->text)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text or --unicodes can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
text_opts->text_len = -1;
|
||||
text_opts->text = g_strdup (arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
encode_unicodes (const char *unicodes,
|
||||
GString *gs,
|
||||
GError **error)
|
||||
{
|
||||
#define DELIMITERS "<+-|>{},;&#\\xXuUnNiI\n\t\v\f\r "
|
||||
|
||||
char *s = (char *) unicodes;
|
||||
char *p;
|
||||
|
||||
while (s && *s)
|
||||
{
|
||||
while (*s && strchr (DELIMITERS, *s))
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
|
||||
errno = 0;
|
||||
hb_codepoint_t u = strtoul (s, &p, 16);
|
||||
if (errno || s == p)
|
||||
{
|
||||
g_string_free (gs, TRUE);
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Failed parsing Unicode value at: '%s'", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_string_append_unichar (gs, u);
|
||||
|
||||
s = p;
|
||||
}
|
||||
|
||||
#undef DELIMITERS
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_unicodes (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
text_options_t *text_opts = (text_options_t *) data;
|
||||
|
||||
if (text_opts->text)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text or --unicodes can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
GString *gs = g_string_new (nullptr);
|
||||
if (0 == strcmp (arg, "*"))
|
||||
g_string_append_c (gs, '*');
|
||||
else
|
||||
if (!encode_unicodes (arg, gs, error))
|
||||
return false;
|
||||
|
||||
text_opts->text_len = gs->len;
|
||||
text_opts->text = g_string_free (gs, FALSE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_text_before (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
auto *opts = (shape_text_options_t *) data;
|
||||
|
||||
if (opts->text_before)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text-before or --unicodes-before can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
opts->text_before = g_strdup (arg);
|
||||
fprintf(stderr, "%s\n", opts->text_before);
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_unicodes_before (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
auto *opts = (shape_text_options_t *) data;
|
||||
|
||||
if (opts->text_before)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text-before or --unicodes-before can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
GString *gs = g_string_new (nullptr);
|
||||
if (!encode_unicodes (arg, gs, error))
|
||||
return false;
|
||||
|
||||
opts->text_before = g_string_free (gs, FALSE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_text_after (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
auto *opts = (shape_text_options_t *) data;
|
||||
|
||||
if (opts->text_after)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text-after or --unicodes-after can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
opts->text_after = g_strdup (arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_unicodes_after (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
auto *opts = (shape_text_options_t *) data;
|
||||
|
||||
if (opts->text_after)
|
||||
{
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"Either --text-after or --unicodes-after can be provided but not both");
|
||||
return false;
|
||||
}
|
||||
|
||||
GString *gs = g_string_new (nullptr);
|
||||
if (!encode_unicodes (arg, gs, error))
|
||||
return false;
|
||||
|
||||
opts->text_after = g_string_free (gs, FALSE);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *
|
||||
text_options_t::get_line (unsigned int *len)
|
||||
{
|
||||
if (text)
|
||||
{
|
||||
if (!line)
|
||||
{
|
||||
line = text;
|
||||
line_len = text_len;
|
||||
}
|
||||
if (line_len == UINT_MAX)
|
||||
line_len = strlen (line);
|
||||
|
||||
if (!line_len)
|
||||
{
|
||||
*len = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *ret = line;
|
||||
const char *p = single_par ? nullptr : (const char *) memchr (line, '\n', line_len);
|
||||
unsigned int ret_len;
|
||||
if (!p)
|
||||
{
|
||||
ret_len = line_len;
|
||||
line += ret_len;
|
||||
line_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_len = p - ret;
|
||||
line += ret_len + 1;
|
||||
line_len -= ret_len + 1;
|
||||
}
|
||||
|
||||
*len = ret_len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_string_set_size (gs, 0);
|
||||
char buf[BUFSIZ];
|
||||
while (fgets (buf, sizeof (buf), in_fp))
|
||||
{
|
||||
unsigned bytes = strlen (buf);
|
||||
if (!single_par && bytes && buf[bytes - 1] == '\n')
|
||||
{
|
||||
bytes--;
|
||||
g_string_append_len (gs, buf, bytes);
|
||||
break;
|
||||
}
|
||||
g_string_append_len (gs, buf, bytes);
|
||||
}
|
||||
if (ferror (in_fp))
|
||||
fail (false, "Failed reading text: %s", strerror (errno));
|
||||
*len = gs->len;
|
||||
return !*len && feof (in_fp) ? nullptr : gs->str;
|
||||
}
|
||||
|
||||
void
|
||||
text_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"},
|
||||
{"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name", "filename"},
|
||||
{"unicodes", 'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"},
|
||||
{"single-par", 0, 0, G_OPTION_ARG_NONE, &this->single_par, "Treat text as single paragraph", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"text",
|
||||
"Text options:\n\nIf no text is provided, standard input is used for input.\n",
|
||||
"Options for the input text",
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
shape_text_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
text_options_t::add_options (parser);
|
||||
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"text-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_before, "Set text context before each line", "string"},
|
||||
{"text-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_after, "Set text context after each line", "string"},
|
||||
{"unicodes-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_before, "Set Unicode codepoints context before each line", "list of hex numbers"},
|
||||
{"unicodes-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_after, "Set Unicode codepoints context after each line", "list of hex numbers"},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"text-context",
|
||||
"Textual context options:",
|
||||
"Options for the input context text",
|
||||
this);
|
||||
}
|
||||
|
||||
#endif
|
||||
220
SDL2_ttf/external/harfbuzz/util/view-cairo.hh
vendored
Normal file
220
SDL2_ttf/external/harfbuzz/util/view-cairo.hh
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef VIEW_CAIRO_HH
|
||||
#define VIEW_CAIRO_HH
|
||||
|
||||
#include "view-options.hh"
|
||||
#include "output-options.hh"
|
||||
#include "helper-cairo.hh"
|
||||
|
||||
struct view_cairo_t : view_options_t, output_options_t<>
|
||||
{
|
||||
~view_cairo_t ()
|
||||
{
|
||||
cairo_debug_reset_static_data ();
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser)
|
||||
{
|
||||
parser->set_summary ("View text with given font.");
|
||||
view_options_t::add_options (parser);
|
||||
output_options_t::add_options (parser, helper_cairo_supported_formats);
|
||||
}
|
||||
|
||||
void init (hb_buffer_t *buffer, const font_options_t *font_opts)
|
||||
{
|
||||
lines = g_array_new (false, false, sizeof (helper_cairo_line_t));
|
||||
subpixel_bits = font_opts->subpixel_bits;
|
||||
}
|
||||
void new_line () {}
|
||||
void consume_text (hb_buffer_t *buffer,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_bool_t utf8_clusters) {}
|
||||
void error (const char *message)
|
||||
{ g_printerr ("%s: %s\n", g_get_prgname (), message); }
|
||||
void consume_glyphs (hb_buffer_t *buffer,
|
||||
const char *text,
|
||||
unsigned int text_len,
|
||||
hb_bool_t utf8_clusters)
|
||||
{
|
||||
direction = hb_buffer_get_direction (buffer);
|
||||
helper_cairo_line_t l (text, text_len, buffer, utf8_clusters, subpixel_bits);
|
||||
g_array_append_val (lines, l);
|
||||
}
|
||||
void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
|
||||
{
|
||||
render (font_opts);
|
||||
|
||||
for (unsigned int i = 0; i < lines->len; i++) {
|
||||
helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
|
||||
line.finish ();
|
||||
}
|
||||
#if GLIB_CHECK_VERSION (2, 22, 0)
|
||||
g_array_unref (lines);
|
||||
#else
|
||||
g_array_free (lines, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void render (const font_options_t *font_opts);
|
||||
|
||||
hb_direction_t direction = HB_DIRECTION_INVALID; // Remove this, make segment_properties accessible
|
||||
GArray *lines = nullptr;
|
||||
unsigned subpixel_bits = 0;
|
||||
};
|
||||
|
||||
inline void
|
||||
view_cairo_t::render (const font_options_t *font_opts)
|
||||
{
|
||||
bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
|
||||
int vert = vertical ? 1 : 0;
|
||||
int horiz = vertical ? 0 : 1;
|
||||
|
||||
int x_sign = font_opts->font_size_x < 0 ? -1 : +1;
|
||||
int y_sign = font_opts->font_size_y < 0 ? -1 : +1;
|
||||
|
||||
hb_font_t *font = font_opts->font;
|
||||
|
||||
if (!have_font_extents)
|
||||
{
|
||||
hb_font_extents_t hb_extents;
|
||||
hb_font_get_extents_for_direction (font, direction, &hb_extents);
|
||||
font_extents.ascent = scalbn ((double) hb_extents.ascender, - (int) subpixel_bits);
|
||||
font_extents.descent = -scalbn ((double) hb_extents.descender, - (int) subpixel_bits);
|
||||
font_extents.line_gap = scalbn ((double) hb_extents.line_gap, - (int) subpixel_bits);
|
||||
have_font_extents = true;
|
||||
}
|
||||
|
||||
double ascent = y_sign * font_extents.ascent;
|
||||
double descent = y_sign * font_extents.descent;
|
||||
double line_gap = y_sign * font_extents.line_gap + line_space;
|
||||
double leading = ascent + descent + line_gap;
|
||||
|
||||
/* Calculate surface size. */
|
||||
double w = 0, h = 0;
|
||||
(vertical ? w : h) = (int) lines->len * leading - (font_extents.line_gap + line_space);
|
||||
(vertical ? h : w) = 0;
|
||||
for (unsigned int i = 0; i < lines->len; i++) {
|
||||
helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
|
||||
double x_advance, y_advance;
|
||||
line.get_advance (&x_advance, &y_advance);
|
||||
if (vertical)
|
||||
h = MAX (h, y_sign * y_advance);
|
||||
else
|
||||
w = MAX (w, x_sign * x_advance);
|
||||
}
|
||||
|
||||
cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts,
|
||||
this);
|
||||
|
||||
/* See if font needs color. */
|
||||
cairo_content_t content = CAIRO_CONTENT_ALPHA;
|
||||
if (helper_cairo_scaled_font_has_color (scaled_font))
|
||||
content = CAIRO_CONTENT_COLOR;
|
||||
|
||||
/* Create surface. */
|
||||
cairo_t *cr = helper_cairo_create_context (w + margin.l + margin.r,
|
||||
h + margin.t + margin.b,
|
||||
this,
|
||||
this,
|
||||
content);
|
||||
cairo_set_scaled_font (cr, scaled_font);
|
||||
|
||||
/* Setup coordinate system. */
|
||||
cairo_translate (cr, margin.l, margin.t);
|
||||
if (vertical)
|
||||
cairo_translate (cr,
|
||||
w - ascent, /* We currently always stack lines right to left */
|
||||
y_sign < 0 ? h : 0);
|
||||
else
|
||||
{
|
||||
cairo_translate (cr,
|
||||
x_sign < 0 ? w : 0,
|
||||
y_sign < 0 ? descent : ascent);
|
||||
}
|
||||
|
||||
/* Draw. */
|
||||
cairo_translate (cr, +vert * leading, -horiz * leading);
|
||||
for (unsigned int i = 0; i < lines->len; i++)
|
||||
{
|
||||
helper_cairo_line_t &l = g_array_index (lines, helper_cairo_line_t, i);
|
||||
|
||||
cairo_translate (cr, -vert * leading, +horiz * leading);
|
||||
|
||||
if (show_extents)
|
||||
{
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_set_source_rgba (cr, 1., 0., 0., .5);
|
||||
cairo_set_line_width (cr, 10);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
for (unsigned i = 0; i < l.num_glyphs; i++) {
|
||||
cairo_move_to (cr, l.glyphs[i].x, l.glyphs[i].y);
|
||||
cairo_rel_line_to (cr, 0, 0);
|
||||
}
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_set_source_rgba (cr, 1., 0., 1., .5);
|
||||
cairo_set_line_width (cr, 3);
|
||||
for (unsigned i = 0; i < l.num_glyphs; i++)
|
||||
{
|
||||
hb_glyph_extents_t hb_extents;
|
||||
hb_font_get_glyph_extents (font, l.glyphs[i].index, &hb_extents);
|
||||
double x1 = scalbn ((double) hb_extents.x_bearing, - (int) subpixel_bits);
|
||||
double y1 = -scalbn ((double) hb_extents.y_bearing, - (int) subpixel_bits);
|
||||
double width = scalbn ((double) hb_extents.width, - (int) subpixel_bits);
|
||||
double height = -scalbn ((double) hb_extents.height, - (int) subpixel_bits);
|
||||
|
||||
cairo_rectangle (cr, l.glyphs[i].x + x1, l.glyphs[i].y + y1, width, height);
|
||||
}
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (l.num_clusters)
|
||||
cairo_show_text_glyphs (cr,
|
||||
l.utf8, l.utf8_len,
|
||||
l.glyphs, l.num_glyphs,
|
||||
l.clusters, l.num_clusters,
|
||||
l.cluster_flags);
|
||||
else
|
||||
cairo_show_glyphs (cr, l.glyphs, l.num_glyphs);
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
helper_cairo_destroy_context (cr);
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
}
|
||||
|
||||
#endif
|
||||
130
SDL2_ttf/external/harfbuzz/util/view-options.hh
vendored
Normal file
130
SDL2_ttf/external/harfbuzz/util/view-options.hh
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright © 2011 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef VIEW_OPTIONS_HH
|
||||
#define VIEW_OPTIONS_HH
|
||||
|
||||
#include "options.hh"
|
||||
|
||||
#define DEFAULT_MARGIN 16
|
||||
#define DEFAULT_FORE "#000000"
|
||||
#define DEFAULT_BACK "#FFFFFF"
|
||||
|
||||
struct view_options_t
|
||||
{
|
||||
~view_options_t ()
|
||||
{
|
||||
g_free (fore);
|
||||
g_free (back);
|
||||
g_free (custom_palette);
|
||||
}
|
||||
|
||||
void add_options (option_parser_t *parser);
|
||||
|
||||
char *fore = nullptr;
|
||||
char *back = nullptr;
|
||||
unsigned int palette = 0;
|
||||
char *custom_palette = nullptr;
|
||||
double line_space = 0;
|
||||
bool have_font_extents = false;
|
||||
struct font_extents_t {
|
||||
double ascent, descent, line_gap;
|
||||
} font_extents = {0., 0., 0.};
|
||||
struct margin_t {
|
||||
double t, r, b, l;
|
||||
} margin = {DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN};
|
||||
hb_bool_t show_extents = false;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_font_extents (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
view_options_t *view_opts = (view_options_t *) data;
|
||||
view_options_t::font_extents_t &e = view_opts->font_extents;
|
||||
switch (sscanf (arg, "%lf%*[ ,]%lf%*[ ,]%lf", &e.ascent, &e.descent, &e.line_gap)) {
|
||||
case 1: HB_FALLTHROUGH;
|
||||
case 2: HB_FALLTHROUGH;
|
||||
case 3:
|
||||
view_opts->have_font_extents = true;
|
||||
return true;
|
||||
default:
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"%s argument should be one to three space-separated numbers",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_margin (const char *name G_GNUC_UNUSED,
|
||||
const char *arg,
|
||||
gpointer data,
|
||||
GError **error G_GNUC_UNUSED)
|
||||
{
|
||||
view_options_t *view_opts = (view_options_t *) data;
|
||||
view_options_t::margin_t &m = view_opts->margin;
|
||||
switch (sscanf (arg, "%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf", &m.t, &m.r, &m.b, &m.l)) {
|
||||
case 1: m.r = m.t; HB_FALLTHROUGH;
|
||||
case 2: m.b = m.t; HB_FALLTHROUGH;
|
||||
case 3: m.l = m.r; HB_FALLTHROUGH;
|
||||
case 4: return true;
|
||||
default:
|
||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||
"%s argument should be one to four space-separated numbers",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
view_options_t::add_options (option_parser_t *parser)
|
||||
{
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{"annotate", 0, G_OPTION_FLAG_HIDDEN,
|
||||
G_OPTION_ARG_NONE, &this->show_extents, "Annotate output rendering", nullptr},
|
||||
{"background", 0, 0, G_OPTION_ARG_STRING, &this->back, "Set background color (default: " DEFAULT_BACK ")", "rrggbb/rrggbbaa"},
|
||||
{"foreground", 0, 0, G_OPTION_ARG_STRING, &this->fore, "Set foreground color (default: " DEFAULT_FORE ")", "rrggbb/rrggbbaa"},
|
||||
{"font-palette", 0, 0, G_OPTION_ARG_INT, &this->palette, "Set font palette (default: 0)", "index"},
|
||||
{"custom-palette", 0, 0, G_OPTION_ARG_STRING, &this->custom_palette, "Custom palette", "comma-separated colors"},
|
||||
{"line-space", 0, 0, G_OPTION_ARG_DOUBLE, &this->line_space, "Set space between lines (default: 0)", "units"},
|
||||
{"font-extents", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_extents, "Set font ascent/descent/line-gap (default: auto)","one to three numbers"},
|
||||
{"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"},
|
||||
{"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Draw glyph extents", nullptr},
|
||||
{nullptr}
|
||||
};
|
||||
parser->add_group (entries,
|
||||
"view",
|
||||
"View options:",
|
||||
"Options for output rendering",
|
||||
this);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user