Files
RedBear-OS/local/recipes/libs/pango/source/utils/pango-segmentation.c
T

252 lines
6.3 KiB
C

/* Pango
* pango-segmentation.c: Test Pango line breaking
*
* Copyright (C) 2021 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glib.h>
#include <pango/pangocairo.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#ifndef G_OS_WIN32
#include <unistd.h>
#endif
typedef enum {
GRAPHEME,
WORD,
WORD_START_END,
LINE,
SENTENCE,
SENTENCE_START_END,
} BreakKind;
static BreakKind
kind_from_string (const char *str)
{
if (strcmp (str, "grapheme") == 0)
return GRAPHEME;
else if (strcmp (str, "word") == 0)
return WORD;
else if (strcmp (str, "words") == 0)
return WORD_START_END;
else if (strcmp (str, "line") == 0)
return LINE;
else if (strcmp (str, "sentence") == 0)
return SENTENCE;
else if (strcmp (str, "sentences") == 0)
return SENTENCE_START_END;
else
{
g_printerr ("Not a segmentation: %s", str);
return 0;
}
}
enum {
NONE,
BREAK,
START,
END
};
static gboolean
show_segmentation (const char *input,
BreakKind kind)
{
GString *string;
PangoContext *context;
gsize length;
GError *error = NULL;
PangoLogAttr *attrs;
int len;
char *p;
int i;
char *text;
PangoAttrList *attributes;
PangoLayout *layout;
context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
string = g_string_new ("");
length = strlen (input);
len = g_utf8_strlen (input, -1) + 1;
pango_parse_markup (input, -1, 0, &attributes, &text, NULL, &error);
g_assert_no_error (error);
layout = pango_layout_new (context);
pango_layout_set_text (layout, text, length);
pango_layout_set_attributes (layout, attributes);
pango_layout_get_log_attrs (layout, &attrs, &len);
for (i = 0, p = text; i < len; i++, p = g_utf8_next_char (p))
{
PangoLogAttr log = attrs[i];
int indicator = NONE;
switch (kind)
{
case GRAPHEME:
if (log.is_cursor_position)
indicator = BREAK;
break;
case WORD:
if (log.is_word_boundary)
indicator = BREAK;
break;
case WORD_START_END:
if (log.is_word_start && log.is_word_end)
indicator = BREAK;
else if (log.is_word_start)
indicator = START;
else if (log.is_word_end)
indicator = END;
break;
case LINE:
if (log.is_line_break)
indicator = BREAK;
break;
case SENTENCE:
if (log.is_sentence_boundary)
indicator = BREAK;
break;
case SENTENCE_START_END:
if (log.is_sentence_start && log.is_sentence_end)
indicator = BREAK;
else if (log.is_sentence_start)
indicator = START;
else if (log.is_sentence_end)
indicator = END;
break;
default:
g_assert_not_reached ();
}
switch (indicator)
{
case BREAK:
g_string_append (string, "|");
break;
case START:
g_string_append (string, "");
break;
case END:
g_string_append (string, "");
break;
case NONE:
default:
break;
}
if (i < len - 1)
{
gunichar ch = g_utf8_get_char (p);
if (ch == 0x20)
g_string_append (string, " ");
else if (g_unichar_isgraph (ch) ||
ch == '\n' ||
g_unichar_type (ch) == G_UNICODE_LINE_SEPARATOR ||
g_unichar_type (ch) == G_UNICODE_PARAGRAPH_SEPARATOR)
g_string_append_unichar (string, ch);
else
g_string_append_printf (string, "[%#04x]", ch);
}
}
g_object_unref (layout);
g_free (attrs);
g_free (text);
pango_attr_list_unref (attributes);
g_print ("%s\n", string->str);
g_string_free (string, TRUE);
return TRUE;
}
int
main (int argc, char *argv[])
{
const char *opt_kind = "grapheme";
const char *opt_text = NULL;
gboolean opt_version = FALSE;
GOptionEntry entries[] = {
{ "kind", 0, 0, G_OPTION_ARG_STRING, &opt_kind, "Boundary (grapheme/word/words/line/sentence/sentences)", "KIND" },
{ "text", 0, 0, G_OPTION_ARG_STRING, &opt_text, "Text to display", "STRING" },
{ "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Show version" },
{ NULL, },
};
GOptionContext *context;
GError *error = NULL;
char *text;
gsize len;
g_set_prgname ("pango-segmentation");
setlocale (LC_ALL, "");
context = g_option_context_new ("[FILE]");
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_set_description (context,
"Show text segmentation as determined by Pango:\n"
" grapheme - Cursor positions\n"
" word - Word boundaries\n"
" words - Word starts and ends\n"
" line - Possible line breaks\n"
" sentence - Sentence boundaries\n"
" sentences - Sentence starts and ends");
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_printerr ("%s\n", error->message);
exit (1);
}
if (opt_version)
{
g_print ("%s (%s) %s\n", g_get_prgname (), PACKAGE_NAME, PACKAGE_VERSION);
exit (0);
}
if (opt_text)
{
text = (char *)opt_text;
}
else if (argc > 1)
{
if (!g_file_get_contents (argv[1], &text, &len, &error))
{
g_printerr ("%s\n", error->message);
exit (1);
}
}
else
{
g_printerr ("Usage: pango-segmentation [OPTIONS…] FILE\n");
exit (1);
}
show_segmentation (text, kind_from_string (opt_kind));
return 0;
}