• Stars
    star
    151
  • Rank 246,057 (Top 5 %)
  • Language
    Nim
  • License
    MIT License
  • Created over 6 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Fonts, Typesetting and Rasterization.

Typography - Fonts, Typesetting and Rasterization.

⚠️ Typography has been integrated into Pixie, a full-featured 2D graphics library for Nim. This repo is no longer being actively worked on. ⚠️

Pixie supports more TrueType / OpenType font features as well as rich text layout and rasterizizing through spans.

Consider migrating projects from Typography to Pixie for additional functionality and future improvements. 🚀🚀🚀🚀🚀


nimble install typography

Run tests

API reference

About

Typography is pure nim implementation for font rasterization (letter drawing) and text typesetting (text layout). It does not rely on any external library such as FreeType, stb_truetype, pango or HarfBuzz.

See api reference: https://treeform.github.io/typography/typography.html

Font file formats:

  • SVG fonts - Most features are supported.
  • TTF fonts - Fair support. Most modern features are supported but font format came out in 1994 and has a bunch of formats for different OSes that are not supported.
  • OTF fonts - Basic TTF outline support only. No support for CFF or SVG outlines.

Requred Packages

  • vmath - vector stuff, vec2 and matrices.
  • pixie - image stuff, saving and loading PNGs.
  • chroma - color stuff, mostly to save and add rgba colors.
  • print - better logging.
  • bumpy - geometry stuff.
  • flatty - dealing with binary encoding.

Basic usage

var font = readFontSvg("fonts/Ubuntu.svg")
font.drawText(image, vec2(10, 50), "The quick brown fox jumps over the lazy dog.")

example output

var font = readFontTtf("fonts/Ubuntu.ttf")
font.drawText(image, vec2(10, 50), "The quick brown fox jumps over the lazy dog.")

example output

font.size = 8
font.drawText(image, vec2(10, 10), "The quick brown fox jumps over the lazy dog.")
font.size = 10
font.drawText(image, vec2(10, 25), "The quick brown fox jumps over the lazy dog.")
font.size = 14
font.drawText(image, vec2(10, 45), "The quick brown fox jumps over the lazy dog.")
font.size = 22
font.drawText(image, vec2(10, 75), "The quick brown fox jumps over the lazy dog.")

example output

font.drawText(image, vec2(10, 10), readFile("examples/sample.ru.txt"))

example output

Dealing with Glyphs

Each font has an table of glyphs.

font.glyphs["Q"]

And for each glyphs, you can see what the SVG path of a glyph looks like:

echo font.glyphs["Q"].path
M754,236 Q555,236 414,377  Q273,518 273,717  Q273,916 414,1057  Q555,1198 754,1198  Q953,1198 1094,1057  Q1235,916 1235,717  Q1235,593 1175,485  L1096,565  Q1062,599 1013,599  Q964,599 929,565  Q895,530 895,481  Q895,432 929,398  L1014,313  Q895,236 754,236  Z M1347,314  Q1471,496 1471,717  Q1471,1014 1261,1224  Q1051,1434 754,1434  Q458,1434 247,1224 Q37,1014 37,717  Q37,421 247,210  Q458,0 754,0  Q993,0 1184,143  L1292,35  Q1327,0 1376,0  Q1425,0 1459,35  Q1494,69 1494,118  Q1494,167 1459,201  Z

You can also draw this path to see all of the paths and all of the curve contorl points:

font.getGlyphOutlineImage("Q")

example output

Most of the time you would like to just get the image instead:

font.getGlyphImage("Q")

example output

You can then use this image in openGL, canvas, or even HTML.

Subpixel glyphs with subpixel layout:

Each glyphs can be rendered with a subpixel offset, so that it fits into the layout:

example output

Note how many of the "o"s and "m"s are different from each other. This happens because spaces between letters are not an integer number of pixels so glyphs must be rendred shifted by fraction of a pixel.

Here is how glyph changes with different subpixel offsets:

example output

var glyphOffset # this is an offset of the image from the 0,0 position
var image = font.getGlyphImage(glyph, glyphOffset, subPixelShift=X)

Typesetting

Before glyphs can be rendered they need to be typeset:

var layout = font.typeset("""
Two roads diverged in a yellow wood,
And sorry I could not travel both
And be one traveler, long I stood
And looked down one as far as I could
To where it bent in the undergrowth;""")

This produces a layout.

example output

Drawing the layout

You can then use the simple drawing included to draw to an image, or use some other graphical librarry like openGL, canvas, or even HTML:

image.drawText(layout)

example output

Wrapping and Clipping

You can also give the typeset region width and height so that text wraps and clips:

font.typeset(
  readFile("sample.wrap.txt"),
  pos=vec2(100, 20),
  size=vec2(300, 160)
)

example output

Alignment

There are 3 horizontal and 3 vertical alignment modes:

font.typeset("Center, Bottom",
  pos=vec2(20, 20),
  size=vec2(460, 160),
  hAlign=Center,
  vAlign=Bottom
)

example output

Selection

When selecting text is useful to know where to highlighting rectangles.

layout.getSelection(23, 120) # selects char 23 to char 120 (not glyphs)

example output

Picking

When clicking on text is useful to know where to highlighting what glyph and what is the string index.

layout.pickGlyphAt(vec2(120, 48)) # selects glyph at cordiantes

example output

Comparison to different OSs.

At the large font sizes (more then 24 pixels) the fonts on most operating system looks nearly identical. But when you scale the font below 24px different OSs take different approaches.

  • OSX - tries to render fonts most true to how font designer intended even if they look a blurry.
  • Windows - tries to render fonts to a pixel grid making them look sharper.
  • Linux - configurable and somewhere between the two.
  • iOS, Android - it really does not matter how the font is rendered because its almost always above 24px because of high resolution screens phones have.
   var font = readFontSvg("fonts/DejaVuSans.svg")
   font.size = 11 # 11px or 8pt
   font.drawText(image, vec2(10, 15), "The quick brown fox jumps over the lazy dog.")

Typography renderer - this library (4x):

example output

Apple Core Text renderer (4x):

example output

Paint.net renderer (4x):

example output

Bohemian Sketch renderer (4x):

example output

Window ClearType renderer (4x):

example output

How the font should look on screen is very subjective, some people love the crisp windows fonts, others swear by the apples adherence to design. But my opinion is it's all related a lot with familiarity. What you are used to is what you would like best, and when a person switches to a different screen with a different font rendering style brain immediately rejects it.

Subpixel Antialising is on its way out

About a decade ago use of Subpixel Antialising improved readability of fonts. It would leak a bit of color to the left and right of text because color pixels were not square. The monitors followed predictable pixel patterns first in CRTs then in LCDs.

example output

Then everything changed. Today our pixels small and they don't follow a typical CRT or LCD orientation.

example output

The fact that there is no standard pixel layout grid anymore. And the fact that high resolution displays are everywhere makes subpixeling obsolete. Apple, Adobe, Bohemian and others in the typography space are abandoning subpixeling.

This library does not support Subpixel Antialising.

Neat tricks with Subpixel rendering

Apple removes Subpixel Antialising

Text Boxes

Full backend implementation of a text area. You need to connect your own rendering, keyboard and mouse input.

Often when displaying text you also need to edit text. This is where the textbox part of this library comes in. This implemented the backend of a text box/text area/input element/text field. Text boxes are surprisingly hard to implement right because the users are very familiar with how they work, so any missing features or inconsistencies are painfully obvious.

Here is a small list of some of the features:

  • Typing, arrow keys, backspace and delete.
  • Mouse clicking, dragging to select.
  • Almost everything can be used to select with shift.
  • Double click to select word, triple click to select paragraph, quad click to select all.
  • Page up and page down.
  • Move left/right by word.
  • Move to start or end of lines.
  • Copy, Cut and Paste.
  • Scrolling and scroll to cursor when typing or selecting.
  • Resizing of the text box while it’s being added.
  • Remember your horizontal position when going up or down with short lines.

example output

example output

How to convert any font to SVG font using FontForge:

SVG fonts are really nice. The are simple to parse and understand and debug. They are very uncommon though. But they are good as a debug input, output, or intermediate step.

$ fontforge -c 'Open($1); Generate($2)' foo.ttf foo.svg

More Repositories

1

fidget

Figma based UI library for nim, with HTML and OpenGL backends.
Nim
765
star
2

pixie

Full-featured 2d graphics library for Nim.
Nim
741
star
3

jsony

A loose, direct to object json parser with hooks.
Nim
270
star
4

ws

Simple WebSocket library for Nim.
Nim
253
star
5

genny

Generate a shared library and bindings for many languages.
Nim
224
star
6

puppy

Puppy fetches via HTTP and HTTPS
Nim
187
star
7

shady

Nim to GPU shader language compiler and supporting utilities.
Nim
150
star
8

netty

Netty - reliable UDP connection library for games in Nim.
Nim
121
star
9

windy

Windowing library for Nim using OS native APIs.
Nim
117
star
10

nimtemplate

You can use this Nim template to jump start your Nim library or project.
Nim
110
star
11

chroma

Everything you want to do with colors, in Nim.
Nim
107
star
12

print

Print is a set of pretty print macros, useful for print-debugging.
Nim
105
star
13

boxy

2D GPU rendering with a tiling atlas.
Nim
103
star
14

vmath

Math vector library for graphical things.
Nim
98
star
15

pixie-python

Full-featured 2D graphics library for Python.
Python
96
star
16

flatty

Flatty - tools and serializer for plain flat binary files.
Nim
87
star
17

nim_emscripten_tutorial

Nim emscripten tutorial.
JavaScript
82
star
18

chrono

Chrono a Timestamps, Calendars, and Timezones library for nim.
Nim
78
star
19

spacy

Spatial data structures for Nim.
Nim
69
star
20

debby

Database ORM layer for Nim
Nim
67
star
21

flippy

Flippy is a simple 2d image and drawing library.
Nim
59
star
22

benchy

Benchmarking.
Nim
52
star
23

orbits

Orbits - orbital mechanics library for nim.
Nim
51
star
24

urlly

URL and URI parsing for Nim for C/JS backends. Similar api to browsers's window.location.
Nim
47
star
25

pretty

Pretty printer for Nim used for debugging.
Nim
47
star
26

steganography

Steganography - hide data inside an image.
Nim
46
star
27

hottie

Sampling profiler that finds hot paths in your code.
Nim
43
star
28

bumpy

2d collision library for Nim.
Nim
42
star
29

webby

Web utilities - HTTP headers, query parsing etc
Nim
42
star
30

thready

Alternative Interface for threads in Nim.
Nim
42
star
31

pg

Very simple PostgreSQL async api for nim.
Nim
38
star
32

slappy

3d sound api for nim.
C
37
star
33

glfm

Wrapper of GLFM (OpenGL ES and input for iOS and Android) library for Nim.
Nim
37
star
34

pixiebook

Nim
36
star
35

greenlet

Greenlet - Coroutines library for nim similar to python's greenlet.
C
34
star
36

googleapi

GoogleAPI access from nim.
Nim
33
star
37

word2vec

Word2vec implemented in nim.
Nim
32
star
38

llama2.nim

Inference Llama 2 in pure Nim
Nim
32
star
39

dumpincludes

See where your exe size comes from.
Nim
30
star
40

guardmons

Collection of nim shell utilities and libraries.
Nim
30
star
41

taggy

Everything to do with HTML and XML.
Nim
27
star
42

steamworks

Nim bindings to steamworks, valve's steam sdk.
Nim
26
star
43

asyncssh

SSH and run commands on other servers asynchronously for Nim.
Nim
25
star
44

sysinfo

Cross-platform way to find common system resources like, os, os version, machine name, cpu stats...
Nim
24
star
45

nimdocs

Automatic Nim document generator.
Nim
23
star
46

morepretty

Morepretty - like nimpretty but with more stuff.
Nim
22
star
47

icons2font

This utility takes vector icons in svg format and convert them to icon fonts (svg,ttf,waff,eot) to be display in all browsers.
Python
21
star
48

forematics

Formatics - Metamath verifier written in Nim.
Nim
20
star
49

openal

An OpenAL wrapper for nim.
Nim
18
star
50

globby

Glob pattern matching for Nim.
Nim
18
star
51

tabby

Direct to object CSV/TSV/tabulated data parser with hooks.
Nim
18
star
52

simple-fps

simple fps demo for panda3d
16
star
53

obj2egg

converts obj to egg format for panda3d
16
star
54

hobby

Treeform's hobby is to create Nim libraries that end with y.
14
star
55

nimby

Nimby is a very simple and unofficial package manager for nim language.
Nim
14
star
56

encode

Encode/decode utf8 utf16 and utf32.
Nim
14
star
57

miniz

Miniz wrapper for nim.
C
13
star
58

ptest

Print-testing for nim.
Nim
12
star
59

bitty

Tightly packed 1d and 2d bit arrays.
Nim
12
star
60

mddoc

Generated Nim's API docs in markdown for github's README.md files. Great for small libraries with simple APIs.
Nim
12
star
61

quickcairo

Nim Cairo bindings
Nim
11
star
62

digitalocean

Wrapper for DigitalOcean HTTP API.
Nim
10
star
63

useragents

User Agent parser for nim.
Nim
9
star
64

webkit2.net

My take on embedded webkit for .net (based on open-webkit-sharp, which is based on webkit.net)
JavaScript
8
star
65

statistics

Common and uncommon statistical functions for Nim.
Nim
8
star
66

jsutils

A library for nim that makes working with JS easier.
Nim
7
star
67

vt100terminal

Terminal VT100 emulation in pure Nim.
Nim
7
star
68

ssh

Connect to machines over SSH and run commands there from nim.
Nim
7
star
69

mpeg

Nim wrapper for pl_mpeg single header mpeg library.
C
7
star
70

onecup

Plain coffee script HTML templeting library.
CoffeeScript
6
star
71

supreme-tictactoe

Multi player tick tack toe web game using tornado, JQuery, and Jinja.
Python
5
star
72

proffy

Profiler for nim.
Nim
5
star
73

panda3d-CSM

panda3d's cascading shadowmaps sample thing
Python
5
star
74

meshDrawer

explains mesh Drawer element to panda3d folks
Python
5
star
75

istrolid-bugs

Official Istrolid Bug Tracking
4
star
76

freefrontfinder

A file that maps font names to where you can download them.
Nim
4
star
77

fidgetfonts

Collection of fonts that might be useful with fidget.
4
star
78

pystorm

pystrom is a python to javascript compiler based on Niall McCarroll's py2js released under MIT licence.
Python
4
star
79

asterisk

Web based code editor.
CoffeeScript
3
star
80

re.edit

Simple web editor based on Code Mirror
CoffeeScript
3
star
81

zlibstatic

Zlib Static - statically link zlib for nim.
C
3
star
82

consfyre

HTML5 2d spaceship building and flying game.
JavaScript
3
star
83

treescript

LISP like language that compiles to javascript.
JavaScript
3
star
84

panda3d-sample-models

I hope to come up with some nice models to use for panda3d
3
star
85

mysqler

a better command line client for mysql to replace the "the MySQL command-line tool"
Python
2
star
86

ddbase

Very dumb disk key-value store.
Python
2
star
87

Atomic4

May 10, 2004 - My first cool project.
Assembly
2
star
88

Re-edit

Client-server, in browser, code editor based on concept of shifting "boards"
Python
2
star
89

Java-Doc-Test

Simple implementation of Doc Tests for Java using Bean Shell
2
star
90

randcss

Generates a random CSS/HTML layout and style
2
star
91

basic-coffee-2d-html5-game-starter

for what you want to start a project with coffee quickly
2
star
92

eggOctree

eggOctree script for panda3d
2
star
93

treeterm

clone of ajaxterm and some changes
1
star
94

libuv

nimuv is libuv dynamic bind for nim.
C
1
star
95

nimbench

Set of nim benchmarks.
JavaScript
1
star
96

new-ajaxterm

My fork of ajaxterm.
Python
1
star
97

Java-Forms

Django-like "forms" implementation for java
1
star
98

strapless

easy coffeescript dynamic HTML MVC
JavaScript
1
star
99

panda3dmanual

converting panda3d manual from wiki-html mess into nice RST format
1
star
100

orekit

Fork of a free low-level space dynamics library: https://www.orekit.org/
Java
1
star