From: Steven Rostedt <rostedt@goodmis.org>
To: "Yordan Karadzhov (VMware)" <y.karadz@gmail.com>
Cc: linux-trace-devel@vger.kernel.org
Subject: Re: [PATCH 1/4] kernel-shark: Add support for drawing text
Date: Fri, 4 Dec 2020 18:31:27 -0500 [thread overview]
Message-ID: <20201204183127.186a7f87@gandalf.local.home> (raw)
In-Reply-To: <20201120095031.271735-2-y.karadz@gmail.com>
On Fri, 20 Nov 2020 11:50:28 +0200
"Yordan Karadzhov (VMware)" <y.karadz@gmail.com> wrote:
> OpenGL doesn't provide support for text rendering. Here we first
> re-enable the compilation of the OpenGL wrapper and add the capability
> of printing text to the OpenGL scene by using the single-file public
> domain library "stb_truetype":
> https://github.com/nothings/stb/blob/master/stb_truetype.h
>
> Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
> ---
> CMakeLists.txt | 6 +-
> Documentation/doxygen/dox_config | 1 +
> src/CMakeLists.txt | 4 +-
> src/libkshark-plot.c | 244 +-
> src/libkshark-plot.h | 57 +
> src/stb_truetype.h | 5011 ++++++++++++++++++++++++++++++
> 6 files changed, 5312 insertions(+), 11 deletions(-)
> create mode 100644 src/stb_truetype.h
>
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index ccca95c1..3d179778 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -26,9 +26,9 @@ include(${KS_DIR}/build/FindJSONC.cmake)
>
> find_package(Doxygen)
>
> -# set(OpenGL_GL_PREFERENCE LEGACY)
> -# find_package(OpenGL)
> -# find_package(GLUT)
> +set(OpenGL_GL_PREFERENCE LEGACY)
> +find_package(OpenGL)
> +find_package(GLUT)
>
> # find_package(Qt5Widgets 5.7.1)
> # find_package(Qt5Network)
> diff --git a/Documentation/doxygen/dox_config b/Documentation/doxygen/dox_config
> index 89b92842..0bbeb3f0 100644
> --- a/Documentation/doxygen/dox_config
> +++ b/Documentation/doxygen/dox_config
> @@ -14,3 +14,4 @@ SORT_MEMBER_DOCS = NO
> STRICT_PROTO_MATCHING = YES
> DOT_MULTI_TARGETS = YES
> PROJECT_LOGO = ../../icons/KS_logo_stacked.svg
> +EXCLUDE = ../../src/stb_truetype.h
> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
> index ae5de54d..3a07d824 100644
> --- a/src/CMakeLists.txt
> +++ b/src/CMakeLists.txt
> @@ -22,8 +22,8 @@ install(TARGETS kshark LIBRARY DESTINATION ${_LIBDIR}/${KS_APP_NAME})
> if (OPENGL_FOUND AND GLUT_FOUND)
>
> message(STATUS "libkshark-plot")
> - add_library(kshark-plot SHARED libkshark-plot.c
> - KsPlotTools.cpp)
> + add_library(kshark-plot SHARED libkshark-plot.c)
> +# KsPlotTools.cpp)
>
> target_link_libraries(kshark-plot kshark
> ${GLUT_LIBRARY}
> diff --git a/src/libkshark-plot.c b/src/libkshark-plot.c
> index 17d3b903..06483334 100644
> --- a/src/libkshark-plot.c
> +++ b/src/libkshark-plot.c
> @@ -1,13 +1,22 @@
> /* SPDX-License-Identifier: LGPL-2.1 */
>
> /*
> - * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
> + * Copyright (C) 2018 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
> */
>
> - /**
> - * @file libkshark-plot.c
> - * @brief Basic tools for OpenGL plotting.
> - */
> +/**
> + * @file libkshark-plot.c
> + * @brief Basic tools for OpenGL plotting.
> + */
> +
> +// C
> +#ifndef _GNU_SOURCE
> +/** Use GNU C Library. */
> +#define _GNU_SOURCE
> +#endif // _GNU_SOURCE
> +
> +#include <string.h>
> +#include <stdio.h>
>
> // OpenGL
> #include <GL/freeglut.h>
> @@ -16,6 +25,17 @@
> // KernelShark
> #include "libkshark-plot.h"
>
> +/*
> + * STB TrueType (single-file public domain library)
> + * https://github.com/nothings/stb
> + */
> +/** Generate implementation. */
> +#define STB_TRUETYPE_IMPLEMENTATION
> +
> +/** Make the implementation private. */
> +#define STBTT_STATIC
> +#include "stb_truetype.h"
> +
> /**
> * @brief Create an empty scene for drawing.
> *
> @@ -66,7 +86,7 @@ void ksplot_init_opengl(int dpr)
> glEnable(GL_POLYGON_SMOOTH);
> glLineWidth(1.5 * dpr);
> glPointSize(2.5 * dpr);
> - glClearColor(1, 1, 1, 1);
> + glClearColor(1, 1, 1, 1); // White
> }
>
> /**
> @@ -210,3 +230,215 @@ void ksplot_draw_polygon_contour(const struct ksplot_point *points,
> col,
> size);
> }
> +
> +/**
> + * @brief Find a TrueType font file.
> + *
> + * @param font_family: The family name of the font.
> + * @param font_name: The name of the font file without the extention.
> + *
> + * @returns A string containing the absolute path to the TrueType font file
> + * on success, or NULL on failure. The user is responsible for freeing
> + * the string.
> + */
> +char *ksplot_find_font_file(const char *font_family, const char *font_name)
> +{
> + char buffer[1024], *end;
> + char *cmd = NULL;
> + int ret;
> + FILE *f;
> +
> + ret = asprintf(&cmd, "fc-list \'%s\' |grep %s.ttf", font_family,
> + font_name);
This is sorta a hack, but for now we can keep it and improve it later, as
it is wrapped in this function.
Perhaps add a comment /* FIXME: Do this a bit more properly */
> + if (ret <= 0)
> + goto fail;
> +
> + f = popen(cmd, "r");
> + free(cmd);
> + if (f == NULL)
> + goto fail;
> +
> + end = fgets(buffer, sizeof(buffer), f);
> + pclose(f);
> + if (!end)
> + goto fail;
> +
> + end = strchr(buffer, ':');
> + if (!end)
> + goto fail;
> +
> + return strndup(buffer, end - buffer);
> +
> + fail:
> + fprintf(stderr, "Failed to find font file.\n" );
> + return NULL;
> +}
> +
> +/** The size of the bitmap matrix used to load the font. */
> +#define KS_FONT_BITMAP_SIZE 1024
> +
> +/**
> + * @brief Initialize a font.
> + *
> + * @param font: Output location for the font descriptor.
> + * @param size: The size of the font.
> + * @param file: Input location for the truetype font file.
> + */
> +bool ksplot_init_font(struct ksplot_font *font, float size, const char *file)
> +{
> + unsigned char bitmap[KS_FONT_BITMAP_SIZE * KS_FONT_BITMAP_SIZE];
> + int ascent, descent, line_gap, lsb;
> + ssize_t buff_size, ret;
> + unsigned char *buffer;
> + stbtt_fontinfo info;
> + FILE *font_file;
> + float scale;
> +
> + font_file = fopen(file, "rb");
> + if (!font_file) {
> + fprintf(stderr, "Failed to open font file!\n");
> + return false;
> + }
> +
> + /* Get the size of the file. */
> + fseek(font_file, 0, SEEK_END);
> + buff_size = ftell(font_file);
I would use stat(2) to find the file size.
> + fseek(font_file, 0, SEEK_SET);
> +
> + buffer = malloc(buff_size);
> + if (!buffer) {
> + fprintf(stderr, "Failed to allocat memory for font!\n");
> + goto close_file;
> + }
> +
> + ret = fread(buffer, buff_size, 1, font_file);
> + fclose(font_file);
> +
> + if (ret == 0) {
> + fprintf(stderr, "Failed to read from font file!\n");
> + goto free_buffer;
> + }
> +
> + if (!stbtt_InitFont(&info, buffer, 0)) {
> + fprintf(stderr, "Failed to init font!\n");
> + goto free_buffer;
> + }
> +
> + /* Get the font's metrics. */
> + scale = stbtt_ScaleForMappingEmToPixels(&info, size);
> + stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap);
> + if (line_gap == 0)
> + line_gap = - descent;
> + /*
> + * Calculate the dimensions of the font. Note that the descent has
> + * a negative value.
> + */
> + font->height = (- descent + ascent + line_gap) * scale;
> + font->base = (- descent + line_gap / 2) * scale;
> + font->size = size;
> +
> + /*
> + * The width of the 'z' character will be considered as an average
> + * character width.
> + */
> + stbtt_GetCodepointHMetrics(&info, 'z', &font->char_width, &lsb);
> + font->char_width *= scale;
> +
> + ret = stbtt_BakeFontBitmap(buffer,
> + 0,
> + size,
> + bitmap,
> + KS_FONT_BITMAP_SIZE,
> + KS_FONT_BITMAP_SIZE,
> + KS_SPACE_CHAR,
> + KS_N_CHAR,
> + font->cdata);
> +
> + if (ret <= 0) {
> + fprintf(stderr, "Failed to bake font bitmap!\n");
> + goto free_buffer;
> + }
> +
> + free(buffer);
> +
> + glGenTextures(1, &font->texture_id);
> + glBindTexture(GL_TEXTURE_2D, font->texture_id);
> +
> + glTexImage2D(GL_TEXTURE_2D,
> + 0,
> + GL_ALPHA,
> + KS_FONT_BITMAP_SIZE,
> + KS_FONT_BITMAP_SIZE,
> + 0,
> + GL_ALPHA,
> + GL_UNSIGNED_BYTE,
> + bitmap);
> +
> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
> +
I don't really understand any of the above, so I'm assuming you know what
it is doing ;-)
> + return true;
> +
> + close_file:
> + fclose(font_file);
> +
> + free_buffer:
> + free(buffer);
> + return false;
> +}
> +
> +/**
> + * @brief Print(draw) a text.
> + *
> + * @param font: Intput location for the font descriptor.
> + * @param col: The color of the polygon.
> + * @param x: Horizontal coordinate of the beginning of the text.
> + * @param y: Verticalal coordinate of the beginning of the text.
> + * @param text: The text to be drawn.
> + */
> +void ksplot_print_text(const struct ksplot_font *font,
> + const struct ksplot_color *col,
> + float x, float y,
> + const char *text)
> +{
> + glEnable(GL_TEXTURE_2D);
> +
> + /* Set the color of the text. */
> + if (col)
> + glColor3ub(col->red, col->green, col->blue);
> + else
> + glColor3ub(0, 0, 0); // Black
> +
> + glBindTexture(GL_TEXTURE_2D, font->texture_id);
> + glBegin(GL_QUADS);
> + for (; *text; ++text) {
> + if (*text < KS_SPACE_CHAR && *text > KS_TILDA_CHAR)
> + continue;
> +
> + stbtt_aligned_quad quad;
> + stbtt_GetBakedQuad(font->cdata,
> + KS_FONT_BITMAP_SIZE,
> + KS_FONT_BITMAP_SIZE,
> + *text - KS_SPACE_CHAR,
> + &x, &y,
> + &quad,
> + 1);
> +
> + glTexCoord2f(quad.s0, quad.t1);
> + glVertex2f(quad.x0, quad.y1);
> +
> + glTexCoord2f(quad.s1, quad.t1);
> + glVertex2f(quad.x1, quad.y1);
> +
> + glTexCoord2f(quad.s1, quad.t0);
> + glVertex2f(quad.x1, quad.y0);
> +
> + glTexCoord2f(quad.s0, quad.t0);
> + glVertex2f(quad.x0, quad.y0);
How is the x and y moved to the next location?
> + }
> +
> + glEnd();
> + glDisable(GL_TEXTURE_2D);
> +}
> diff --git a/src/libkshark-plot.h b/src/libkshark-plot.h
> index 9a4dbc02..0edf5d50 100644
> --- a/src/libkshark-plot.h
> +++ b/src/libkshark-plot.h
> @@ -12,6 +12,15 @@
> #ifndef _LIB_KSHARK_PLOT_H
> #define _LIB_KSHARK_PLOT_H
>
> +// C
> +#include <stdbool.h>
> +
> +/*
> + * STB TrueType (single-file public domain library)
> + * https://github.com/nothings/stb
> + */
> +#include "stb_truetype.h"
> +
> #ifdef __cplusplus
> extern "C" {
> #endif
> @@ -62,6 +71,54 @@ void ksplot_draw_polygon_contour(const struct ksplot_point *points,
> const struct ksplot_color *col,
> float size);
>
> +/** The index of the "Space" character. */
> +#define KS_SPACE_CHAR 32
> +
> +/** The index of the "Tilda" character. */
> +#define KS_TILDA_CHAR 126
> +
> +/** Total number of characters supported for drawing. */
> +#define KS_N_CHAR (KS_TILDA_CHAR - KS_SPACE_CHAR + 1)
> +
> +/** Structure defining a font. */
> +struct ksplot_font {
> + /** Identifier of the font's texture. */
> + GLuint texture_id;
> +
> + /** Font's texture baking data. */
> + stbtt_bakedchar cdata[KS_N_CHAR];
> +
> + /** The height of a text line. */
> + int height;
> +
> + /** The vertical position of the font's baseline. */
> + int base;
> +
> + /** The size of the font. */
> + int size;
> +
> + /**
> + * The width of the 'z' character. To be use as an average character
> + * width.
> + */
> + int char_width;
> +};
> +
> +/** Check if the texture of the font is loaded. */
> +static inline bool ksplot_font_is_loaded(struct ksplot_font *f)
> +{
> + return f->texture_id > 1;
> +}
> +
> +char *ksplot_find_font_file(const char *font_family, const char *font_name);
> +
> +bool ksplot_init_font(struct ksplot_font *font, float size, const char *file);
> +
> +void ksplot_print_text(const struct ksplot_font *font,
> + const struct ksplot_color *col,
> + float x, float y,
> + const char *text);
> +
> #ifdef __cplusplus
> }
> #endif
> diff --git a/src/stb_truetype.h b/src/stb_truetype.h
> new file mode 100644
> index 00000000..62595a15
> --- /dev/null
> +++ b/src/stb_truetype.h
I'm assuming the rest is what you took from public domain?
> @@ -0,0 +1,5011 @@
> +// stb_truetype.h - v1.24 - public domain
> +// authored from 2009-2020 by Sean Barrett / RAD Game Tools
> +//
> +// =======================================================================
> +//
> +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
> +//
> +// This library does no range checking of the offsets found in the file,
> +// meaning an attacker can use it to read arbitrary memory.
> +//
> +// =======================================================================
> +//
> +// This library processes TrueType files:
> +// parse files
> +// extract glyph metrics
> +// extract glyph shapes
> +// render glyphs to one-channel bitmaps with antialiasing (box filter)
> +// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
> +//
> +// Todo:
> +// non-MS cmaps
> +// crashproof on bad data
> +// hinting? (no longer patented)
> +// cleartype-style AA?
> +// optimize: use simple memory allocator for intermediates
> +// optimize: build edge-list directly from curves
> +// optimize: rasterize directly from curves?
> +//
> +// ADDITIONAL CONTRIBUTORS
> +//
> +// Mikko Mononen: compound shape support, more cmap formats
> +// Tor Andersson: kerning, subpixel rendering
> +// Dougall Johnson: OpenType / Type 2 font handling
> +// Daniel Ribeiro Maciel: basic GPOS-based kerning
[..]
next prev parent reply other threads:[~2020-12-04 23:32 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-20 9:50 [PATCH 0/4] Upgrade the OpenGL wrapper for KernelShark v2.0 Yordan Karadzhov (VMware)
2020-11-20 9:50 ` [PATCH 1/4] kernel-shark: Add support for drawing text Yordan Karadzhov (VMware)
2020-12-04 23:31 ` Steven Rostedt [this message]
2020-12-09 13:30 ` Yordan Karadzhov (VMware)
2020-12-09 14:14 ` Yordan Karadzhov (VMware)
2020-12-09 16:34 ` Steven Rostedt
2020-11-20 9:50 ` [PATCH 2/4] kernel-shark: Make GLUT optional dependency Yordan Karadzhov (VMware)
2020-11-20 9:50 ` [PATCH 3/4] kernel-shark: Add ksplot_draw_polyline() Yordan Karadzhov (VMware)
2020-11-20 9:50 ` [PATCH 4/4] kernel-shark: Optimize ksplot_draw_polygon() Yordan Karadzhov (VMware)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201204183127.186a7f87@gandalf.local.home \
--to=rostedt@goodmis.org \
--cc=linux-trace-devel@vger.kernel.org \
--cc=y.karadz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).