TTF parser and rasterizer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

198 lines
5.7 KiB

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <wchar.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#define ASSERT(expr) if (!expr) { fprintf(stderr, "[ASSERT] Assertion fail %s:%d\n", __FILE__, __LINE__); abort(); }
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX_INTERSECTIONS 16
#define F32EPS 1e-5f
#define MAX_CONTOURS 256
#define TTF_ENGINE_STACK 4096
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef float f32;
typedef double f64;
static int
clamp_u32(u32 val, u32 cap)
{
u32 result = val;
if (val > cap) result = cap;
return(result);
}
static f32
abs_f32(f32 v)
{
f32 result = (v > 0 ? v : -v);
return(result);
}
static int
round_f32(f32 v)
{
int towards_zero = (int) v;
f32 diff = abs_f32(v - towards_zero);
if (diff >= 0.5f) {
return(v > 0 ? towards_zero + 1 : towards_zero - 1);
} else {
return(towards_zero);
}
}
static int
ceil_f32(f32 v)
{
int trunc = v;
if (v - trunc < F32EPS) {
return(trunc);
}
return(trunc + 1);
}
#include "ttf.h"
#include "ttf_engine.c"
#include "ttf-parse.c"
#include "ttf-rasterize.c"
static Display *display;
static Window window;
static GC default_gc;
static XImage* xwindow_buffer;
int
main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: %s filename.ttf\n", argv[0]);
return(1);
}
display = XOpenDisplay(0);
Window root_window = DefaultRootWindow(display);
int default_screen = DefaultScreen(display);
int screen_bit_depth = 24;
int width = 1280;
int height = 720;
XVisualInfo visinfo = { 0 };
XMatchVisualInfo(display, default_screen, screen_bit_depth, TrueColor, &visinfo);
XSetWindowAttributes window_attr;
window_attr.bit_gravity = StaticGravity;
window_attr.background_pixel = 0;
window_attr.colormap = XCreateColormap(display, root_window, visinfo.visual, AllocNone);
window_attr.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask;
unsigned long attribute_mask = CWBitGravity | CWBackPixel | CWColormap | CWEventMask;
window = XCreateWindow(display, root_window,
0, 0,
width, height, 0,
visinfo.depth, InputOutput,
visinfo.visual, attribute_mask, &window_attr);
XGrabPointer(display, window, False, ButtonPressMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
XSelectInput(display, window, KeyPress | KeyRelease | ButtonRelease | PointerMotionMask);
XStoreName(display, window, "ttf");
XMapWindow(display, window);
XFlush(display);
Atom WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &WM_DELETE_WINDOW, 1);
int pixel_bits = 32;
int pixel_bytes = pixel_bits / 8;
int window_buffer_size = width * height * pixel_bytes;
void *hc_vram = malloc(window_buffer_size);
xwindow_buffer = XCreateImage(display, visinfo.visual, visinfo.depth, ZPixmap, 0, hc_vram, width, height,
pixel_bits, 0);
default_gc = DefaultGC(display, default_screen);
struct ttf_font font = parse_ttf_file(argv[1], "Inter");
printf("Loaded font\n");
u32 *pixels = hc_vram;
int t = 0;
for (;;) {
//memset(pixels, 0xFF, width * height * 4);
//memset(pixels, 0xFF, width * height * 4);
memset(pixels, 0x00, width * height * 4);
int wrap = 100 + (t * 4 % width);
int at = 75;
struct v2 box;
//render_utf_string(font, 18, pixels, width, L"The quick brown fox jumps over the lazy dog", 100, 150);
//render_utf_string(font, 12, pixels, width, L"This text is seriously small", 100, at); at += 12;
//render_utf_string(font, 13, pixels, width, L"This text is seriously small", 100, at); at += 13;
box = render_utf_string(font, 12, pixels, width, L"This text is seriously small", wrap, 100, at);
at += box.y;
box = render_utf_string(font, 18, pixels, width, L"aolo2@avx:~/Documents/code/ttf-test (master) $", wrap, 100, at); at += 20;
at += box.y;
box = render_utf_string(font, 26, pixels, width, L"render_utf_string(font, 32, pixels, width, string3, 10 + w1 + w2, at);", wrap, 10, at); at += 24;
at += box.y;
box = render_utf_string(font, 24, pixels, width, L"The quick brown fox jumps over the lazy dog", wrap, 10, at); at += 24;
wchar_t *string1 = L"iiiiiiiiiiiiiiiiiii";
wchar_t *string2 = L"something-some";
wchar_t *string3 = L"MORE MORE";
//get_string_width(&font, 32, string1, wcslen(string1));
//get_string_width(&font, 32, string2, wcslen(string2));
//render_utf_string(font, 32, pixels, width, string1, 200, 10, at);
//render_utf_string(font, 32, pixels, width, string2, 200, 10 + w1, at);
//render_utf_string(font, 32, pixels, width, string3, 200, 10 + w1 + w2, at);
//at += 80;
//render_utf_string(font, 80, pixels, width, L"~!@#$%^&*()_+;:,./\\||||", 200, 10, at);
XPutImage(display, window, default_gc, xwindow_buffer, 0, 0, 0, 0, width, height);
usleep(16667);
++t;
}
return(0);
}