From b3863fa5f18b0a8836035f990ad3585a4d7269dc Mon Sep 17 00:00:00 2001 From: MoHadiShibli <142665133+MoHadiShibli@users.noreply.github.com> Date: Sun, 4 Oct 2026 19:53:45 +0300 Subject: [PATCH] Launcher app: home-screen PKG to start, check and stop Control4Free An OpenOrbis app that sends the bundled payload to GoldHEN's PayLoader, shows its address and a QR code, and stops it through the loopback API. It draws its screen in software in the controller page's style (stb_truetype with Roboto), and its icon with the same code. The package (title ID CFRE00001) carries OpenOrbis's stub libc.prx and libSceFios2.prx in sce_module/, as the toolchain asks. The README covers GoldHEN AutoRun, the launcher, the page and the build. --- README.md | 155 + THIRD_PARTY.md | 33 + docker/Dockerfile.launcher | 14 + launcher/Makefile | 36 + launcher/draw.c | 348 ++ launcher/draw.h | 52 + launcher/main.cpp | 192 ++ launcher/screen.c | 560 ++++ launcher/screen.h | 24 + launcher/service.c | 202 ++ launcher/service.h | 20 + launcher/stb_truetype.c | 3 + tools/build-launcher.ps1 | 15 + tools/embed_file.py | 15 + tools/launcher_art.c | 56 + tools/package_launcher.py | 132 + vendor/qrcodegen/qrcodegen.c | 1022 ++++++ vendor/qrcodegen/qrcodegen.h | 385 +++ vendor/roboto/LICENSE | 201 ++ vendor/roboto/Roboto-Light.ttf | Bin 0 -> 350028 bytes vendor/roboto/Roboto-Regular.ttf | Bin 0 -> 349400 bytes vendor/stb/stb_truetype.h | 5079 ++++++++++++++++++++++++++++++ 22 files changed, 8544 insertions(+) create mode 100644 README.md create mode 100644 THIRD_PARTY.md create mode 100644 docker/Dockerfile.launcher create mode 100644 launcher/Makefile create mode 100644 launcher/draw.c create mode 100644 launcher/draw.h create mode 100644 launcher/main.cpp create mode 100644 launcher/screen.c create mode 100644 launcher/screen.h create mode 100644 launcher/service.c create mode 100644 launcher/service.h create mode 100644 launcher/stb_truetype.c create mode 100644 tools/build-launcher.ps1 create mode 100644 tools/embed_file.py create mode 100644 tools/launcher_art.c create mode 100644 tools/package_launcher.py create mode 100644 vendor/qrcodegen/qrcodegen.c create mode 100644 vendor/qrcodegen/qrcodegen.h create mode 100644 vendor/roboto/LICENSE create mode 100644 vendor/roboto/Roboto-Light.ttf create mode 100644 vendor/roboto/Roboto-Regular.ttf create mode 100644 vendor/stb/stb_truetype.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..2af31c1 --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +# Control4Free + +A GoldHEN payload for controlling the PS4 from a phone or PC, using touch, +keyboard, or an Xbox/other controller exposed by the browser's Gamepad API. +Virtual controllers use the PS4's native user-selection screen, so they work on +the home screen, at sign-in and in games. + +**Status: the browser controller works on the development console; the launcher +app and GoldHEN AutoRun start are ready for their first console test.** Native +user sign-in, menu control and gameplay have been confirmed by the tester. Four +virtual slots are exposed; the console's device limits apply. + +## Requirements + +- A PS4 running GoldHEN. Development console: firmware 10.01, GoldHEN 2.4b18.10. + Starting Control4Free from GoldHEN itself (LaunchPad or AutoRun) needs 2.4b18.10 + or later; the launcher app and PC sending need PayLoader. +- GoldHEN's klog server, which 2.4b18 always runs. Device creation relies on + kernel-log events to recover the virtual device's handle. +- A phone or PC on the same network. +- Turn off other GoldHEN controller plugins in games you play with Control4Free. A + plugin that takes over a signed-in user's controller can stop games from reading + the virtual controllers. + +## Start it with GoldHEN (AutoRun) + +GoldHEN 2.4b18.10 can run payloads on its own, from its **Payloader LaunchPad**, and +automatically each time GoldHEN starts (**AutoRun**). Set this up once and no PC or +PayLoader is needed to start Control4Free. + +1. Put `control4free.elf` in `/data/payloads/` on the PS4, for example through + GoldHEN's FTP server (port 2121). GoldHEN also lists payloads in a `Payloads` + folder on a USB drive, but keep the AutoRun copy on the console. +2. In GoldHEN, open **Payloads > Payloader LaunchPad** and select + `control4free.elf` to start it now. +3. Press **Square** on it to add it to the AutoRun queue. GoldHEN then starts it + every time GoldHEN loads. + +When you update Control4Free, replace `/data/payloads/control4free.elf` as well. + +## Install the launcher app + +The launcher is a home-screen app that shows whether Control4Free is running, its +address and a QR code for your phone, and can start or stop it. + +1. Copy `build/Control4Free-0.2.0.pkg` to a USB drive and install it using the + PS4's Package Installer with GoldHEN active. +2. Open **Control4Free** from the home screen. If AutoRun already started it, the + app shows **Running**. Otherwise turn on GoldHEN's PayLoader and press + **Cross**. +3. Scan the QR code or enter the address on your phone. Select a controller there + and sign in through the PS4 screen. +4. Press **Circle** to close the app. Control4Free keeps running on its own. Reopen + the app to see the address again, or press **Square**, then **Cross**, to stop it + and disconnect all its controllers. + +The app does not turn on GoldHEN or PayLoader, and does not start after a reboot by +itself; AutoRun does that. + +**Upgrading from the original test payload:** disconnect controllers and use +**Stop Control4Free** in the phone menu before starting from the launcher. The +old payload has no launcher-management API, so the app refuses to start a second +copy over it. Rebooting the console also clears that old instance. + +## Use + +1. Stop any older Control4Free payload before loading another. They all use port + 4264. +2. Start Control4Free: from GoldHEN (above), from the launcher app, or by sending + `build/control4free.elf` from a PC to GoldHEN's PayLoader on port 9090 with a + payload sender. The payload serves its own page; no PC web server is needed. +3. Open `http://YOUR-PS4-IP:4264` in the phone or PC browser. +4. Select a free controller. This creates it and opens native PS4 user selection. + Use Left/Right and Cross to select a user or follow the PS4's guest flow. + **Do not press PS while the initial user-selection screen is open:** in the + hardware experiment this cancelled selection. PS works after sign-in. +5. Test the home screen and then a game before adding another controller. + +For an Xbox or other physical controller, connect it to the phone/PC, press a +button so the browser detects it, then choose its virtual-controller slot under +connected controllers. Sign it in through the same PS4 screen. Add and sign in +controllers one at a time. Touch and keyboard can also operate the selected slot. + +The corner menu provides local layout/keyboard preferences, **Disconnect +controller**, and **Stop Control4Free**. PS and Share send actual controller +buttons. The PS4 assigns users; there are no pad or user settings on the page. + +Some browsers restrict Gamepad API access on an HTTP page. If the page reports +that restriction, try opening a saved copy of `client/index.html` locally and +entering `YOUR-PS4-IP:4264` in its connection settings. Browser support for local +files varies. Keep the controller page in the foreground while playing. + +## Connection behavior + +- Opening the page does not create a controller. Creation follows an explicit + controller selection; the payload never presses sign-in buttons automatically. +- Each virtual slot has one browser owner. Multiple local inputs may share that + browser's selected slot, or use separate slots. +- A lost connection releases held buttons. After 3 seconds without updates, + inputs become neutral; after 15 seconds the controller is removed. A short + disconnect leaves a 15-second window to select that controller again. +- Explicit disconnect removes the controller immediately. Stopping the payload + removes all controllers and restores the saved host credentials. Browser Stop + refuses while another browser owns a controller. The launcher's confirmed Stop + can disconnect all controllers through its loopback-only API. +- If the kernel log is not available yet when Control4Free starts (AutoRun can + start it early), it connects to it when the first controller is created. +- There is no time limit. Rebooting the console ends it; AutoRun, the launcher or + a PC starts it again. + +## Build + +The [ps4-payload-sdk](https://github.com/ps4-payload-dev/sdk) toolchain is pinned +in the Docker image: + +```sh +docker build -t control4free-build docker/ +docker run --rm -v "$PWD:/src" -w /src control4free-build make +``` + +Output: `build/control4free.elf`, with the compressed page embedded. `C4F_STAGE=0` +is the default browser build. Stages 1-8 remain available as diagnostics, with +separate `control4free-stageN.elf` outputs. + +To build the installable launcher after the payload image is available: + +```sh +docker build -t control4free-launcher-build -f docker/Dockerfile.launcher docker/ +docker run --rm -v "$PWD:/src" -w /src control4free-launcher-build bash -lc 'make && make -C launcher' +``` + +Output: `build/Control4Free-0.2.0.pkg` (title ID `CFRE00001`). On Windows, +`tools/build-launcher.ps1` runs both image builds and the package build. It does +not send anything to a console. Packaging uses OpenOrbis and LibOrbisPkg. The +launcher draws its screen and its icon in software, in the controller page's style. + +## Current limits + +Rumble, lightbar feedback and motion input are not implemented. Rest-mode +recovery and multiple native user sessions are unverified. User-assignment status +comes from kernel-log events and may lag or miss an event; check the TV. +Logs are written to `/data/control4free/spike.log` on the console. + +## Credits and license + +The VDA code is ported from [seregonwar/SplashDown](https://github.com/seregonwar/SplashDown). +The build uses John Törnblom's [ps4-payload-sdk](https://github.com/ps4-payload-dev/sdk) +and the [OpenOrbis PS4 Toolchain](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain). +[Ghostcontrol](https://github.com/srbraboo/Ghostcontrol-PS5-USB-Controller-Patcher) +was a research reference. JSON parsing uses [jsmn](https://github.com/zserge/jsmn); +the launcher uses [QR Code generator](https://github.com/nayuki/QR-Code-generator), +[stb_truetype](https://github.com/nothings/stb) and the +[Roboto](https://github.com/googlefonts/roboto) font. + +GPL-3.0; see [LICENSE](LICENSE) and [THIRD_PARTY.md](THIRD_PARTY.md). diff --git a/THIRD_PARTY.md b/THIRD_PARTY.md new file mode 100644 index 0000000..05be07e --- /dev/null +++ b/THIRD_PARTY.md @@ -0,0 +1,33 @@ +# Third-party material + +- The virtual-device implementation derives from seregonwar/SplashDown's + `psbutton.c` (https://github.com/seregonwar/SplashDown), GPL-3.0. +- `vendor/jsmn/jsmn.h` is from https://github.com/zserge/jsmn, copyright Serge + Zaitsev, under the MIT license included in `vendor/jsmn/LICENSE`. + Retrieved 2026-10-04; SHA-256: + `c04533e9181e1e33baceb0f55ac449b05145bb936e8c68cc77dfe0d8277514fb`. +- The toolchain uses https://github.com/ps4-payload-dev/sdk; its version is pinned + in `docker/Dockerfile` and it retains its own licensing. +- The native launcher uses the OpenOrbis PS4 Toolchain and its software-display + initialization pattern (https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain, + GPL-3.0). The toolchain supplies `sce_sys/about/right.sprx` and its stub + `sce_module/libc.prx` and `sce_module/libSceFios2.prx`; LibOrbisPkg produces the + package. `docker/Dockerfile.launcher` pins the OpenOrbis image by digest. +- `vendor/qrcodegen/qrcodegen.c` and `.h` are Project Nayuki's QR generator v1.8.0 + (https://github.com/nayuki/QR-Code-generator/tree/v1.8.0/c), MIT. The full license + is retained at the top of each file. SHA-256 for `.c`: + `300eff07ee25baaa7578f20284411638154716379437391e7e689c0e6ce81403`; + for `.h`: `e82df4bff37d18b5863b9e7486fe6bda1b6cda8c3b9ecebfec473907265cb589`. +- `vendor/stb/stb_truetype.h` is Sean Barrett's stb_truetype v1.26 + (https://github.com/nothings/stb), public domain or MIT, as chosen at the end of + the file. Retrieved 2026-10-04; SHA-256: + `ecd30b05e0dd4fea3a13c26810dd9e1992dc379049482c393d5a19e6b5090aab`. +- `vendor/roboto/` holds Roboto Light and Regular v2.138 + (https://github.com/googlefonts/roboto), Apache License 2.0 + (`vendor/roboto/LICENSE`). The launcher draws its text with them. SHA-256: + `Roboto-Light.ttf` `a08729d794801eaa158c53b1558f4cc351c3b1791eb3d22faf7058b2b7df9c8c`, + `Roboto-Regular.ttf` `f3edb8058e523f5612bfd99d0745e661568ad85e1b6217bc62f786fabae624c6`. + +These license notices are also included inside the package. + +The HTTP/WebSocket transport in `src/net.c` is a new implementation. diff --git a/docker/Dockerfile.launcher b/docker/Dockerfile.launcher new file mode 100644 index 0000000..bf95cea --- /dev/null +++ b/docker/Dockerfile.launcher @@ -0,0 +1,14 @@ +# Reuse the pinned OpenOrbis release from the existing plugin toolchain image. +ARG OPENORBIS_IMAGE=xfangfang/goldhen_plugin@sha256:e3d2acad69a1905472bd9d73e373d1d0fb6d3ca293d9f9a6ba957b9b2f49fffc +FROM ${OPENORBIS_IMAGE} AS openorbis +FROM ubuntu:20.04 AS pkgcompat +RUN apt-get update && apt-get install -y --no-install-recommends libssl1.1 \ + && rm -rf /var/lib/apt/lists/* +FROM control4free-build:latest +COPY --from=openorbis /opt/OpenOrbis/PS4Toolchain /opt/OpenOrbis/PS4Toolchain +# The SDK's self-contained LibOrbisPkg runtime expects OpenSSL 1.1. +COPY --from=pkgcompat /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/ +COPY --from=pkgcompat /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/ +ENV OO_PS4_TOOLCHAIN=/opt/OpenOrbis/PS4Toolchain +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 +WORKDIR /src diff --git a/launcher/Makefile b/launcher/Makefile new file mode 100644 index 0000000..e6146cf --- /dev/null +++ b/launcher/Makefile @@ -0,0 +1,36 @@ +ifndef OO_PS4_TOOLCHAIN +$(error OO_PS4_TOOLCHAIN is undefined; use the launcher Docker image) +endif +SDK := $(OO_PS4_TOOLCHAIN) +OUT := ../build/launcher +PKGDIR := $(OUT)/pkg +CC := clang-18 +CXX := clang++-18 +LD := ld.lld-18 +CFLAGS := --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -O2 -Wall -Wextra -Werror -MMD -MP -D_DEFAULT_SOURCE -isysroot $(SDK) -isystem $(SDK)/include -I../vendor/jsmn -I../vendor/qrcodegen -I../vendor/stb +OBJECTS := $(OUT)/main.o $(OUT)/screen.o $(OUT)/draw.o $(OUT)/service.o $(OUT)/qrcodegen.o $(OUT)/stb_truetype.o $(OUT)/fonts.o +LIBS := -lc -lkernel -lSceVideoOut -lScePad -lSceUserService -lSceSystemService -lSceNetCtl +FONTS := ../vendor/roboto/Roboto-Light.ttf ../vendor/roboto/Roboto-Regular.ttf +.PHONY: all package +.DEFAULT_GOAL := all +-include $(OBJECTS:.o=.d) +all: package +$(OUT): + mkdir -p $@ +$(OUT)/%.o: %.c | $(OUT) + $(CC) $(CFLAGS) -std=gnu11 -c $< -o $@ +$(OUT)/main.o: main.cpp | $(OUT) + $(CXX) $(CFLAGS) -std=c++17 -fno-exceptions -fno-rtti -c $< -o $@ +$(OUT)/qrcodegen.o: ../vendor/qrcodegen/qrcodegen.c | $(OUT) + $(CC) $(CFLAGS) -std=gnu11 -c $< -o $@ +# Vendor code, built with its warnings off. +$(OUT)/stb_truetype.o: stb_truetype.c | $(OUT) + $(CC) $(CFLAGS) -std=gnu11 -w -c $< -o $@ +$(OUT)/fonts.c: $(FONTS) ../tools/embed_file.py | $(OUT) + python3 ../tools/embed_file.py $@ c4fFontLight=../vendor/roboto/Roboto-Light.ttf c4fFontRegular=../vendor/roboto/Roboto-Regular.ttf +$(OUT)/fonts.o: $(OUT)/fonts.c + $(CC) $(CFLAGS) -std=gnu11 -c $< -o $@ +$(OUT)/launcher.elf: $(OBJECTS) + $(LD) -m elf_x86_64 -pie --script $(SDK)/link.x --eh-frame-hdr -o $@ $(OBJECTS) -L$(SDK)/lib $(LIBS) $(SDK)/lib/crt1.o +package: $(OUT)/launcher.elf ../build/control4free.elf + python3 ../tools/package_launcher.py --sdk $(SDK) diff --git a/launcher/draw.c b/launcher/draw.c new file mode 100644 index 0000000..ac8f624 --- /dev/null +++ b/launcher/draw.c @@ -0,0 +1,348 @@ +/* Software drawing for the native launcher. Shape coverage comes from signed + * distances, text from stb_truetype; everything is blended in 8-bit ARGB. */ +#include "draw.h" +#include +#include +#include +#include "stb_truetype.h" + +extern const unsigned char c4fFontLight[], c4fFontRegular[]; + +typedef struct { unsigned char *bitmap; int w, h, x0, y0, ready; float advance; } C4fGlyph; +typedef struct { int font, size; float scale; C4fGlyph glyph[95]; } C4fFace; + +static stbtt_fontinfo c4fFonts[C4F_FONT_COUNT]; +static C4fFace c4fFaces[24]; +static int c4fFaceCount; +static uint8_t c4fTextGamma[256]; + +int c4fDrawInit(void) +{ + const unsigned char *data[C4F_FONT_COUNT] = { c4fFontLight, c4fFontRegular }; + for (int i = 0; i < C4F_FONT_COUNT; i++) + if (!stbtt_InitFont(&c4fFonts[i], data[i], stbtt_GetFontOffsetForIndex(data[i], 0))) return -1; + /* Light strokes on a dark background read thinner than a browser draws + * them; lift partial coverage a little. */ + for (int i = 0; i < 256; i++) c4fTextGamma[i] = (uint8_t)(powf(i / 255.0f, 0.8f) * 255.0f + 0.5f); + return 0; +} + +static float c4fClamp01(float v) { return v < 0 ? 0 : v > 1 ? 1 : v; } +static int c4fMinI(int a, int b) { return a < b ? a : b; } +static int c4fMaxI(int a, int b) { return a > b ? a : b; } + +void c4fBlend(C4fCanvas *c, int x, int y, C4fColor color, float coverage) +{ + if ((unsigned)x >= (unsigned)c->w || (unsigned)y >= (unsigned)c->h) return; + int a = (int)(coverage * color.a + 0.5f); + if (a <= 0) return; + uint32_t *p = &c->px[(size_t)y * c->w + x]; + if (a >= 255) { *p = 0xff000000u | (uint32_t)color.r << 16 | (uint32_t)color.g << 8 | color.b; return; } + uint32_t d = *p; + unsigned inv = 255u - (unsigned)a; + unsigned r = (((d >> 16) & 255u) * inv + color.r * (unsigned)a + 127u) / 255u; + unsigned g = (((d >> 8) & 255u) * inv + color.g * (unsigned)a + 127u) / 255u; + unsigned b = ((d & 255u) * inv + color.b * (unsigned)a + 127u) / 255u; + *p = 0xff000000u | r << 16 | g << 8 | b; +} + +void c4fFillRect(C4fCanvas *c, int x, int y, int w, int h, C4fColor color) +{ + for (int py = c4fMaxI(y, 0); py < c4fMinI(y + h, c->h); py++) + for (int px = c4fMaxI(x, 0); px < c4fMinI(x + w, c->w); px++) c4fBlend(c, px, py, color, 1); +} + +typedef struct { int x0, y0, x1, y1; } C4fBox; + +static int c4fClip(const C4fCanvas *c, float x0, float y0, float x1, float y1, C4fBox *b) +{ + b->x0 = c4fMaxI((int)floorf(x0), 0); + b->y0 = c4fMaxI((int)floorf(y0), 0); + b->x1 = c4fMinI((int)ceilf(x1), c->w); + b->y1 = c4fMinI((int)ceilf(y1), c->h); + return b->x0 < b->x1 && b->y0 < b->y1; +} + +/* Signed distance to a rounded box (centre, half size, corner radius). */ +float c4fRoundBoxDistance(float px, float py, float cx, float cy, float hx, float hy, float r) +{ + float qx = fabsf(px - cx) - (hx - r), qy = fabsf(py - cy) - (hy - r); + float ox = qx > 0 ? qx : 0, oy = qy > 0 ? qy : 0, inner = qx > qy ? qx : qy; + return sqrtf(ox * ox + oy * oy) + (inner < 0 ? inner : 0) - r; +} + +typedef struct { float cx, cy, hx, hy, r; } C4fShape; + +static C4fShape c4fShape(float x, float y, float w, float h, float r) +{ + C4fShape s = { x + w / 2, y + h / 2, w / 2, h / 2, r }; + if (s.r > s.hx) s.r = s.hx; + if (s.r > s.hy) s.r = s.hy; + if (s.r < 0) s.r = 0; + return s; +} + +static float c4fShapeDistance(const C4fShape *s, int px, int py) +{ + return c4fRoundBoxDistance(px + 0.5f, py + 0.5f, s->cx, s->cy, s->hx, s->hy, s->r); +} + +void c4fFillRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, C4fColor fill) +{ + C4fShape s = c4fShape(x, y, w, h, r); + C4fBox b; + if (!c4fClip(c, x - 1, y - 1, x + w + 1, y + h + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float cov = c4fClamp01(0.5f - c4fShapeDistance(&s, px, py)); + if (cov > 0) c4fBlend(c, px, py, fill, cov); + } +} + +void c4fInsetRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float width, C4fColor line) +{ + C4fShape s = c4fShape(x, y, w, h, r); + C4fBox b; + if (!c4fClip(c, x - 1, y - 1, x + w + 1, y + h + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float d = c4fShapeDistance(&s, px, py); + float cov = c4fClamp01(0.5f - d) - c4fClamp01(0.5f - (d + width)); + if (cov > 0) c4fBlend(c, px, py, line, cov); + } +} + +void c4fSheenRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float angle, + C4fColor color, float a0, float a1, float stop) +{ + C4fShape s = c4fShape(x, y, w, h, r); + C4fBox b; + /* CSS gradient angles: 0deg points up, clockwise. */ + float rad = angle * 3.14159265f / 180.0f, dx = sinf(rad), dy = -cosf(rad); + float length = fabsf(w * dx) + fabsf(h * dy); + if (!c4fClip(c, x - 1, y - 1, x + w + 1, y + h + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float cov = c4fClamp01(0.5f - c4fShapeDistance(&s, px, py)); + if (cov <= 0) continue; + float t = ((px + 0.5f - s.cx) * dx + (py + 0.5f - s.cy) * dy) / length + 0.5f; + float a = t >= stop ? a1 : t <= 0 ? a0 : a0 + (a1 - a0) * (t / stop); + c4fBlend(c, px, py, color, cov * a); + } +} + +void c4fBandRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float height, C4fColor color) +{ + C4fShape s = c4fShape(x, y, w, h, r); + C4fBox b; + if (!c4fClip(c, x - 1, y - 1, x + w + 1, y + height + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) { + float band = c4fClamp01(fminf(py + 1.0f, y + height) - fmaxf((float)py, y)); + if (band <= 0) continue; + for (int px = b.x0; px < b.x1; px++) { + float cov = c4fClamp01(0.5f - c4fShapeDistance(&s, px, py)) * band; + if (cov > 0) c4fBlend(c, px, py, color, cov); + } + } +} + +/* A blurred edge: the normal CDF, approximated by a logistic curve. */ +static float c4fSoftEdge(float distance, float sigma) +{ + return 1.0f / (1.0f + expf(1.702f * distance / sigma)); +} + +void c4fShadowRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, + float dx, float dy, float blur, float spread, C4fColor color) +{ + float sigma = blur > 1 ? blur / 2 : 0.5f, reach = 3 * sigma; + C4fShape own = c4fShape(x, y, w, h, r); + C4fShape shadow = c4fShape(x + dx - spread, y + dy - spread, w + 2 * spread, h + 2 * spread, r + spread); + C4fBox b; + if (shadow.hx <= 0 || shadow.hy <= 0) return; + if (!c4fClip(c, fminf(x, x + dx - spread) - reach, fminf(y, y + dy - spread) - reach, + fmaxf(x + w, x + dx + w + spread) + reach, fmaxf(y + h, y + dy + h + spread) + reach, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + /* An outer box-shadow is never painted under the element itself. */ + float inside = c4fClamp01(0.5f - c4fShapeDistance(&own, px, py)); + if (inside >= 1) continue; + float d = c4fShapeDistance(&shadow, px, py); + if (d > reach) continue; + c4fBlend(c, px, py, color, c4fSoftEdge(d, sigma) * (1 - inside)); + } +} + +void c4fFillCircle(C4fCanvas *c, float cx, float cy, float r, C4fColor fill) +{ + C4fBox b; + if (!c4fClip(c, cx - r - 1, cy - r - 1, cx + r + 1, cy + r + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float cov = c4fClamp01(0.5f - (hypotf(px + 0.5f - cx, py + 0.5f - cy) - r)); + if (cov > 0) c4fBlend(c, px, py, fill, cov); + } +} + +void c4fRing(C4fCanvas *c, float cx, float cy, float r, float width, C4fColor line) +{ + C4fBox b; + if (!c4fClip(c, cx - r - 1, cy - r - 1, cx + r + 1, cy + r + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float d = hypotf(px + 0.5f - cx, py + 0.5f - cy) - r; + float cov = c4fClamp01(0.5f - d) - c4fClamp01(0.5f - (d + width)); + if (cov > 0) c4fBlend(c, px, py, line, cov); + } +} + +void c4fGlowCircle(C4fCanvas *c, float cx, float cy, float r, float blur, float spread, C4fColor color) +{ + float sigma = blur > 1 ? blur / 2 : 0.5f, reach = r + spread + 3 * sigma; + C4fBox b; + if (!c4fClip(c, cx - reach, cy - reach, cx + reach, cy + reach, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float distance = hypotf(px + 0.5f - cx, py + 0.5f - cy); + float inside = c4fClamp01(0.5f - (distance - r)); + if (inside >= 1) continue; + c4fBlend(c, px, py, color, c4fSoftEdge(distance - (r + spread), sigma) * (1 - inside)); + } +} + +void c4fSegment(C4fCanvas *c, float x0, float y0, float x1, float y1, float width, C4fColor color) +{ + float hw = width / 2, vx = x1 - x0, vy = y1 - y0, length2 = vx * vx + vy * vy; + C4fBox b; + if (!c4fClip(c, fminf(x0, x1) - hw - 1, fminf(y0, y1) - hw - 1, fmaxf(x0, x1) + hw + 1, fmaxf(y0, y1) + hw + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float fx = px + 0.5f - x0, fy = py + 0.5f - y0; + float t = length2 > 0 ? c4fClamp01((fx * vx + fy * vy) / length2) : 0; + float cov = c4fClamp01(0.5f - (hypotf(fx - t * vx, fy - t * vy) - hw)); + if (cov > 0) c4fBlend(c, px, py, color, cov); + } +} + +void c4fSquareOutline(C4fCanvas *c, float cx, float cy, float half, float width, C4fColor color) +{ + float reach = half + width; + C4fBox b; + if (!c4fClip(c, cx - reach - 1, cy - reach - 1, cx + reach + 1, cy + reach + 1, &b)) return; + for (int py = b.y0; py < b.y1; py++) + for (int px = b.x0; px < b.x1; px++) { + float d = c4fRoundBoxDistance(px + 0.5f, py + 0.5f, cx, cy, half, half, width * 0.4f); + float cov = c4fClamp01(0.5f - (fabsf(d) - width / 2)); + if (cov > 0) c4fBlend(c, px, py, color, cov); + } +} + +/* ---- text ---- */ + +static C4fFace *c4fFace(int font, float size) +{ + int pixels = (int)(size + 0.5f); + for (int i = 0; i < c4fFaceCount; i++) + if (c4fFaces[i].font == font && c4fFaces[i].size == pixels) return &c4fFaces[i]; + if (font < 0 || font >= C4F_FONT_COUNT || c4fFaceCount == (int)(sizeof(c4fFaces) / sizeof(c4fFaces[0]))) return NULL; + C4fFace *face = &c4fFaces[c4fFaceCount++]; + memset(face, 0, sizeof(*face)); + face->font = font; + face->size = pixels; + /* CSS font-size is the em size. */ + face->scale = stbtt_ScaleForMappingEmToPixels(&c4fFonts[font], (float)pixels); + return face; +} + +static int c4fCodepoint(unsigned char ch) { return ch < 32 || ch > 126 ? '?' : ch; } + +static C4fGlyph *c4fGlyph(C4fFace *face, int ch) +{ + C4fGlyph *g = &face->glyph[ch - 32]; + if (!g->ready) { + const stbtt_fontinfo *font = &c4fFonts[face->font]; + int advance, bearing, x0, y0, x1, y1; + stbtt_GetCodepointHMetrics(font, ch, &advance, &bearing); + stbtt_GetCodepointBitmapBox(font, ch, face->scale, face->scale, &x0, &y0, &x1, &y1); + g->advance = advance * face->scale; + g->x0 = x0; + g->y0 = y0; + g->w = x1 - x0; + g->h = y1 - y0; + if (g->w > 0 && g->h > 0 && (g->bitmap = malloc((size_t)g->w * (size_t)g->h))) + stbtt_MakeCodepointBitmap(font, g->bitmap, g->w, g->h, g->w, face->scale, face->scale, ch); + g->ready = 1; + } + return g; +} + +static float c4fTextWidthN(int font, float size, const char *text, int length) +{ + C4fFace *face = c4fFace(font, size); + float width = 0; + int previous = 0; + if (!face) return 0; + for (int i = 0; i < length && text[i]; i++) { + int ch = c4fCodepoint((unsigned char)text[i]); + if (previous) width += stbtt_GetCodepointKernAdvance(&c4fFonts[font], previous, ch) * face->scale; + width += c4fGlyph(face, ch)->advance; + previous = ch; + } + return width; +} + +float c4fTextWidth(int font, float size, const char *text) +{ + return c4fTextWidthN(font, size, text, (int)strlen(text)); +} + +float c4fTextN(C4fCanvas *c, int font, float size, float x, float y, C4fColor color, const char *text, int length) +{ + C4fFace *face = c4fFace(font, size); + float pen = x; + int previous = 0, baseline = (int)floorf(y + 0.5f); + if (!face) return 0; + for (int i = 0; i < length && text[i]; i++) { + int ch = c4fCodepoint((unsigned char)text[i]); + if (previous) pen += stbtt_GetCodepointKernAdvance(&c4fFonts[font], previous, ch) * face->scale; + C4fGlyph *g = c4fGlyph(face, ch); + if (g->bitmap) { + int gx = (int)floorf(pen + 0.5f) + g->x0, gy = baseline + g->y0; + for (int row = 0; row < g->h; row++) + for (int col = 0; col < g->w; col++) { + unsigned value = g->bitmap[row * g->w + col]; + if (value) c4fBlend(c, gx + col, gy + row, color, c4fTextGamma[value] / 255.0f); + } + } + pen += g->advance; + previous = ch; + } + return pen - x; +} + +float c4fText(C4fCanvas *c, int font, float size, float x, float y, C4fColor color, const char *text) +{ + return c4fTextN(c, font, size, x, y, color, text, (int)strlen(text)); +} + +int c4fTextWrapped(C4fCanvas *c, int font, float size, float x, float y, float maxWidth, + float lineHeight, int maxLines, C4fColor color, const char *text) +{ + int lines = 0; + while (*text && lines < maxLines) { + while (*text == ' ') text++; + if (!*text) break; + int fit = 0, end = 0; + for (;;) { + while (text[end] && text[end] != ' ') end++; + if (fit && c4fTextWidthN(font, size, text, end) > maxWidth) break; + fit = end; + if (!text[end]) break; + end++; + } + if (c) c4fTextN(c, font, size, x, y + lines * lineHeight, color, text, fit); + lines++; + text += fit; + } + return lines; +} diff --git a/launcher/draw.h b/launcher/draw.h new file mode 100644 index 0000000..0a0f826 --- /dev/null +++ b/launcher/draw.h @@ -0,0 +1,52 @@ +#ifndef C4F_LAUNCHER_DRAW_H +#define C4F_LAUNCHER_DRAW_H +/* Software drawing into a cached ARGB buffer: anti-aliased shapes and text. + * Blending reads the destination, so never draw straight into the + * write-combined framebuffer. */ +#include + +typedef struct { uint32_t *px; int w, h; } C4fCanvas; +typedef struct { uint8_t r, g, b, a; } C4fColor; +#define C4F_RGBA(r, g, b, a) ((C4fColor){ (r), (g), (b), (uint8_t)((a) * 255.0f + 0.5f) }) + +enum { C4F_FONT_LIGHT, C4F_FONT_REGULAR, C4F_FONT_COUNT }; + +int c4fDrawInit(void); + +/* Signed distance to a rounded box: centre, half size, corner radius. */ +float c4fRoundBoxDistance(float px, float py, float cx, float cy, float hx, float hy, float r); + +void c4fBlend(C4fCanvas *c, int x, int y, C4fColor color, float coverage); +void c4fFillRect(C4fCanvas *c, int x, int y, int w, int h, C4fColor color); + +/* Rounded rectangles; x/y/w/h/r in pixels, fractions allowed. */ +void c4fFillRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, C4fColor fill); +/* A CSS "inset 0 0 0 px" line along the inside edge. */ +void c4fInsetRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float width, C4fColor line); +/* A linear gradient clipped to the shape: alpha a0 at the start, a1 from + * `stop` on, along a CSS angle in degrees. */ +void c4fSheenRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float angle, + C4fColor color, float a0, float a1, float stop); +/* The part of the shape between top and top+height (a tile's colour bar). */ +void c4fBandRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, float height, C4fColor color); +/* A CSS outer box-shadow: drawn only outside the shape itself. */ +void c4fShadowRoundRect(C4fCanvas *c, float x, float y, float w, float h, float r, + float dx, float dy, float blur, float spread, C4fColor color); + +void c4fFillCircle(C4fCanvas *c, float cx, float cy, float r, C4fColor fill); +void c4fRing(C4fCanvas *c, float cx, float cy, float r, float width, C4fColor line); +/* Soft halo around a circle, like box-shadow 0 0 px px. */ +void c4fGlowCircle(C4fCanvas *c, float cx, float cy, float r, float blur, float spread, C4fColor color); +/* A line with round caps. */ +void c4fSegment(C4fCanvas *c, float x0, float y0, float x1, float y1, float width, C4fColor color); +void c4fSquareOutline(C4fCanvas *c, float cx, float cy, float half, float width, C4fColor color); + +/* Text on a baseline. Sizes are CSS font-size in pixels. ASCII only. */ +float c4fText(C4fCanvas *c, int font, float size, float x, float y, C4fColor color, const char *text); +float c4fTextN(C4fCanvas *c, int font, float size, float x, float y, C4fColor color, const char *text, int length); +float c4fTextWidth(int font, float size, const char *text); +/* Word-wrapped text; returns the number of lines (drawn only if c is set). */ +int c4fTextWrapped(C4fCanvas *c, int font, float size, float x, float y, float maxWidth, + float lineHeight, int maxLines, C4fColor color, const char *text); + +#endif diff --git a/launcher/main.cpp b/launcher/main.cpp new file mode 100644 index 0000000..6bb08bc --- /dev/null +++ b/launcher/main.cpp @@ -0,0 +1,192 @@ +/* Native PS4 launcher. The controller service runs outside this application. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "screen.h" +#include "service.h" + +static pthread_mutex_t c4fMutex = PTHREAD_MUTEX_INITIALIZER; +static C4fLauncherScreen c4fScreen; +static int c4fCommand, c4fQuit; + +static void *c4fWorker(void *) +{ + uint64_t nextCheck = 0; + int first = 1; + for (;;) { + pthread_mutex_lock(&c4fMutex); + int command = c4fCommand, quit = c4fQuit; + c4fCommand = 0; + pthread_mutex_unlock(&c4fMutex); + if (quit) return NULL; + if (command || c4fLauncherTimeMs() >= nextCheck) { + char message[160] = {0}, address[64] = {0}; + int result = 0; + if (command == 1) result = c4fLauncherStart("/app0/assets/control4free.elf", message, sizeof(message)); + if (command == 2) result = c4fLauncherStop(message, sizeof(message)); + C4fServiceStatus status; + int running = c4fLauncherProbe(&status); + OrbisNetCtlInfo info; + memset(&info, 0, sizeof(info)); + if (sceNetCtlGetInfo(ORBIS_NET_CTL_INFO_IP_ADDRESS, &info) == 0 && + info.ip_address[0] && strcmp(info.ip_address, "0.0.0.0")) + snprintf(address, sizeof(address), "http://%.15s:4264", info.ip_address); + pthread_mutex_lock(&c4fMutex); + if (result == -2) c4fScreen.locked = 1; + if (command) snprintf(c4fScreen.message, sizeof(c4fScreen.message), "%s", message); + else if (!c4fScreen.locked && (first || running != c4fScreen.running)) { + snprintf(c4fScreen.message, sizeof(c4fScreen.message), "%s", + running == 1 ? "Ready. Scan the code or open the address on your phone." : + running == 0 ? "Not running. Press Cross to start it." : + "Something else answers on port 4264. Stop the old copy from its phone page."); + } + c4fScreen.running = running; + c4fScreen.controllers = status.controllers; + snprintf(c4fScreen.address, sizeof(c4fScreen.address), "%s", address); + /* A queued click while a periodic probe was in flight remains busy. */ + if (!c4fCommand) c4fScreen.busy = 0; + pthread_mutex_unlock(&c4fMutex); + first = 0; nextCheck = c4fLauncherTimeMs() + 2000; + } + usleep(100000); + } +} + +static int c4fVideo = -1; +static OrbisKernelEqueue c4fFlipQueue; +static int c4fHasQueue, c4fBufferRegistration = -1; +static void *c4fVideoMemory; +static off_t c4fVideoOffset; +static size_t c4fVideoSize; +static void *c4fBuffers[2]; + +static int c4fInitVideo(void) +{ + c4fVideo = sceVideoOutOpen(ORBIS_VIDEO_USER_MAIN, ORBIS_VIDEO_OUT_BUS_MAIN, 0, NULL); + if (c4fVideo < 0) return -1; + if (sceKernelCreateEqueue(&c4fFlipQueue, "Control4Free screen") < 0) return -1; + c4fHasQueue = 1; + if (sceVideoOutAddFlipEvent(c4fFlipQueue, c4fVideo, NULL) < 0) return -1; + const size_t frameSize = C4F_SCREEN_WIDTH * C4F_SCREEN_HEIGHT * sizeof(uint32_t); + const size_t alignment = 0x200000; + size_t size = (frameSize * 2 + alignment - 1) & ~(alignment - 1); + if (sceKernelAllocateDirectMemory(0, sceKernelGetDirectMemorySize(), size, alignment, 3, &c4fVideoOffset) < 0) return -1; + c4fVideoSize = size; + if (sceKernelMapDirectMemory(&c4fVideoMemory, size, 0x33, 0, c4fVideoOffset, alignment) < 0) return -1; + c4fBuffers[0] = c4fVideoMemory; + c4fBuffers[1] = (char *)c4fVideoMemory + frameSize; + OrbisVideoOutBufferAttribute attr; + memset(&attr, 0, sizeof(attr)); + /* Same linear ARGB format as the OpenOrbis software-rendering sample. */ + sceVideoOutSetBufferAttribute(&attr, 0x80000000, 1, 0, C4F_SCREEN_WIDTH, C4F_SCREEN_HEIGHT, C4F_SCREEN_WIDTH); + c4fBufferRegistration = sceVideoOutRegisterBuffers(c4fVideo, 0, c4fBuffers, 2, &attr); + if (c4fBufferRegistration < 0) return -1; + return sceVideoOutSetFlipRate(c4fVideo, 1); /* 30 Hz is enough for a launcher. */ +} + +static void c4fCloseVideo(void) +{ + if (c4fVideo >= 0) { + if (c4fBufferRegistration >= 0) sceVideoOutUnregisterBuffers(c4fVideo, c4fBufferRegistration); + sceVideoOutClose(c4fVideo); + } + if (c4fHasQueue) sceKernelDeleteEqueue(c4fFlipQueue); + if (c4fVideoMemory) sceKernelMunmap(c4fVideoMemory, c4fVideoSize); + if (c4fVideoSize) sceKernelReleaseDirectMemory(c4fVideoOffset, c4fVideoSize); +} + +int main(void) +{ + const size_t frameBytes = (size_t)C4F_SCREEN_WIDTH * C4F_SCREEN_HEIGHT * sizeof(uint32_t); + setvbuf(stdout, NULL, _IONBF, 0); + printf("[c4f-launcher] start " C4F_LAUNCHER_VERSION "\n"); + /* Frames are composed in cached memory: blending reads pixels back, which + * is very slow from the write-combined framebuffers. */ + uint32_t *canvas = (uint32_t *)malloc(frameBytes); + if (!canvas || c4fScreenInit() < 0 || c4fInitVideo() < 0) { + printf("[c4f-launcher] display initialization failed\n"); + c4fCloseVideo(); free(canvas); return 1; + } + sceNetCtlInit(); + OrbisUserServiceInitializeParams params = {}; + params.priority = ORBIS_KERNEL_PRIO_FIFO_LOWEST; + sceUserServiceInitialize(¶ms); + int32_t user = -1, pad = -1; + if (scePadInit() == 0 && sceUserServiceGetInitialUser(&user) == 0) + pad = scePadOpen(user, ORBIS_PAD_PORT_TYPE_STANDARD, 0, NULL); + c4fScreen.running = -1; c4fScreen.busy = 1; + snprintf(c4fScreen.message, sizeof(c4fScreen.message), "Checking Control4Free..."); + pthread_t worker; + int workerStarted = pthread_create(&worker, NULL, c4fWorker, NULL) == 0; + if (!workerStarted || pad < 0) { + pthread_mutex_lock(&c4fMutex); + c4fScreen.locked = 1; + snprintf(c4fScreen.message, sizeof(c4fScreen.message), "Could not initialize launcher. Close with PS and retry."); + pthread_mutex_unlock(&c4fMutex); + } + sceSystemServiceHideSplashScreen(); + uint32_t previous = 0; + int buffer = 0, done = 0, drawn = 0, shown[2] = { 0, 0 }; + int64_t frame = 1; + C4fLauncherScreen drawnState; + memset(&drawnState, 0, sizeof(drawnState)); + while (!done) { + OrbisPadData input; + memset(&input, 0, sizeof(input)); + uint32_t buttons = pad >= 0 && scePadReadState(pad, &input) == 0 && input.connected ? input.buttons : 0; + uint32_t pressed = buttons & ~previous; + previous = buttons; + pthread_mutex_lock(&c4fMutex); + if (!c4fScreen.busy) { + if (pressed & ORBIS_PAD_BUTTON_CIRCLE) { + if (c4fScreen.confirmStop) c4fScreen.confirmStop = 0; + else done = 1; + } else if (pressed & ORBIS_PAD_BUTTON_CROSS) { + if (c4fScreen.confirmStop) { + c4fCommand = 2; c4fScreen.confirmStop = 0; c4fScreen.busy = 1; + snprintf(c4fScreen.message, sizeof(c4fScreen.message), "Stopping and releasing controllers..."); + } else if (!c4fScreen.locked && c4fScreen.running != 1) { + c4fCommand = 1; c4fScreen.busy = 1; + snprintf(c4fScreen.message, sizeof(c4fScreen.message), "Starting Control4Free. Please wait..."); + } + } else if ((pressed & ORBIS_PAD_BUTTON_SQUARE) && c4fScreen.running == 1) c4fScreen.confirmStop = 1; + } + C4fLauncherScreen snapshot = c4fScreen; + pthread_mutex_unlock(&c4fMutex); + /* Redraw only when something changed, then copy it to each buffer once. */ + if (!drawn || memcmp(&snapshot, &drawnState, sizeof(snapshot))) { + c4fDrawLauncher(canvas, &snapshot); + drawnState = snapshot; drawn = 1; shown[0] = shown[1] = 0; + } + if (!shown[buffer]) { memcpy(c4fBuffers[buffer], canvas, frameBytes); shown[buffer] = 1; } + if (sceVideoOutSubmitFlip(c4fVideo, buffer, ORBIS_VIDEO_OUT_FLIP_VSYNC, frame) < 0) break; + for (;;) { + OrbisVideoOutFlipStatus status; + memset(&status, 0, sizeof(status)); + if (sceVideoOutGetFlipStatus(c4fVideo, &status) < 0) { done = 1; break; } + if (status.flipArg >= frame) break; + OrbisKernelEvent event; + int count; + OrbisKernelUseconds timeout = 100000; + sceKernelWaitEqueue(c4fFlipQueue, &event, 1, &count, &timeout); + } + buffer ^= 1; frame++; + } + pthread_mutex_lock(&c4fMutex); c4fQuit = 1; pthread_mutex_unlock(&c4fMutex); + if (workerStarted) pthread_join(worker, NULL); + if (pad >= 0) scePadClose(pad); + sceNetCtlTerm(); + c4fCloseVideo(); + free(canvas); + /* Closing this app intentionally does not stop the external payload. */ + sceSystemServiceLoadExec("exit", NULL); + return 0; +} diff --git a/launcher/screen.c b/launcher/screen.c new file mode 100644 index 0000000..9a6d906 --- /dev/null +++ b/launcher/screen.c @@ -0,0 +1,560 @@ +/* The launcher screen, drawn in the controller page's style (client/index.html): + * the same blue backdrop with light waves, tiles, panels and colours, at 1.5x + * the page's CSS sizes for a 1080p TV. */ +#include "screen.h" +#include +#include +#include +#include +#include "draw.h" +#include "qrcodegen.h" + +/* Page CSS pixels to TV pixels. */ +#define C4F_S 1.5f + +/* Layout, in TV pixels. */ +#define C4F_LEFT 150.0f +#define C4F_RIGHT 1770.0f +#define C4F_ROW_TOP 336.0f +#define C4F_ROW_HEIGHT 444.0f +#define C4F_ROW_GAP 30.0f +#define C4F_QR_WIDTH 520.0f +#define C4F_MAIN_WIDTH (C4F_RIGHT - C4F_LEFT - C4F_ROW_GAP - C4F_QR_WIDTH) +#define C4F_QR_LEFT (C4F_LEFT + C4F_MAIN_WIDTH + C4F_ROW_GAP) +#define C4F_PANEL_TOP (C4F_ROW_TOP + C4F_ROW_HEIGHT + 28) +#define C4F_PANEL_HEIGHT 128.0f + +/* The page's palette (:root). */ +#define C4F_TEXT C4F_RGBA(244, 247, 255, 1) +#define C4F_MUTED C4F_RGBA(226, 236, 255, .72f) +#define C4F_FAINT C4F_RGBA(226, 236, 255, .46f) +#define C4F_LINE C4F_RGBA(255, 255, 255, .16f) +#define C4F_LINE_SOFT C4F_RGBA(255, 255, 255, .09f) +#define C4F_PANEL C4F_RGBA(3, 16, 44, .55f) +#define C4F_PANEL_STRONG C4F_RGBA(2, 11, 31, .86f) +#define C4F_TILE C4F_RGBA(12, 40, 98, .5f) +#define C4F_ACCENT C4F_RGBA(58, 140, 255, 1) +#define C4F_OK C4F_RGBA(69, 224, 138, 1) +#define C4F_WARN C4F_RGBA(255, 208, 77, 1) +#define C4F_BAD C4F_RGBA(255, 107, 125, 1) +#define C4F_CIRCLE_KEY C4F_RGBA(255, 102, 128, 1) +#define C4F_CROSS_KEY C4F_RGBA(134, 182, 255, 1) +#define C4F_SQUARE_KEY C4F_RGBA(255, 146, 220, 1) +#define C4F_WHITE C4F_RGBA(255, 255, 255, 1) + +static uint32_t *c4fBackdrop; + +static float c4fClamp(float v) { return v < 0 ? 0 : v > 1 ? 1 : v; } + +/* ---- backdrop (.backdrop, .waves, .sparkles) ---- */ + +static float c4fNoise(int x, int y) +{ + uint32_t h = (uint32_t)x * 374761393u + (uint32_t)y * 668265263u; + h = (h ^ (h >> 13)) * 1274126177u; + return (float)((h ^ (h >> 16)) & 0xffffu) / 65536.0f - 0.5f; +} + +static void c4fMix(float rgb[3], float r, float g, float b, float a) +{ + rgb[0] += (r - rgb[0]) * a; + rgb[1] += (g - rgb[1]) * a; + rgb[2] += (b - rgb[2]) * a; +} + +static void c4fPaintGradient(C4fCanvas *c) +{ + static const float stops[4][4] = { + { 0.00f, 0x02, 0x0f, 0x2b }, { 0.45f, 0x06, 0x27, 0x66 }, + { 0.72f, 0x0b, 0x3f, 0x9c }, { 1.00f, 0x04, 0x19, 0x4a }, + }; + const float w = (float)c->w, h = (float)c->h; + /* linear-gradient(165deg): CSS angles point up at 0 and turn clockwise. */ + const float dx = 0.258819f, dy = 0.965926f, length = w * dx + h * dy; + for (int y = 0; y < c->h; y++) + for (int x = 0; x < c->w; x++) { + float px = x + 0.5f, py = y + 0.5f, rgb[3]; + float t = c4fClamp(((px - w / 2) * dx + (py - h / 2) * dy) / length + 0.5f); + int i = t > stops[2][0] ? 2 : t > stops[1][0] ? 1 : 0; + float f = (t - stops[i][0]) / (stops[i + 1][0] - stops[i][0]); + for (int k = 0; k < 3; k++) rgb[k] = stops[i][k + 1] + (stops[i + 1][k + 1] - stops[i][k + 1]) * f; + /* radial-gradient(80% 60% at 0% -10%, rgba(25, 90, 200, .55), transparent 60%) */ + float ex = px / (0.8f * w), ey = (py + 0.1f * h) / (0.6f * h); + c4fMix(rgb, 25, 90, 200, 0.55f * c4fClamp(1 - sqrtf(ex * ex + ey * ey) / 0.6f)); + /* radial-gradient(120% 70% at 75% 115%, rgba(70, 150, 255, .5), transparent 62%), on top */ + ex = (px - 0.75f * w) / (1.2f * w); + ey = (py - 1.15f * h) / (0.7f * h); + c4fMix(rgb, 70, 150, 255, 0.5f * c4fClamp(1 - sqrtf(ex * ex + ey * ey) / 0.62f)); + /* Dither, so the dark gradient does not band on a TV. */ + float noise = c4fNoise(x, y); + uint32_t out = 0xff000000u; + for (int k = 0; k < 3; k++) { + int v = (int)floorf(rgb[k] + noise + 0.5f); + out |= (uint32_t)(v < 0 ? 0 : v > 255 ? 255 : v) << (16 - 8 * k); + } + c->px[(size_t)y * c->w + x] = out; + } +} + +/* The page's wave paths (viewBox 0 0 3200 400): the start y, then four cubic + * segments (c1x c1y c2x c2y x y) with every "S" expanded. */ +static const float c4fWaveA[25] = { 230, 200, 150, 400, 310, 800, 230, 1200, 150, 1400, 150, 1600, 230, + 1800, 150, 2000, 310, 2400, 230, 2800, 150, 3000, 150, 3200, 230 }; +static const float c4fWaveB[25] = { 260, 250, 200, 550, 330, 800, 260, 1050, 190, 1350, 190, 1600, 260, + 1850, 200, 2150, 330, 2400, 260, 2650, 190, 2950, 190, 3200, 260 }; +static const float c4fWaveC[25] = { 200, 300, 110, 500, 300, 800, 200, 1100, 100, 1300, 100, 1600, 200, + 1900, 110, 2100, 300, 2400, 200, 2700, 100, 2900, 100, 3200, 200 }; +static const float c4fWaveD[25] = { 215, 300, 140, 520, 290, 800, 215, 1080, 140, 1320, 130, 1600, 215, + 1900, 140, 2120, 290, 2400, 215, 2680, 140, 2920, 130, 3200, 215 }; +static const float c4fWaveE[25] = { 240, 280, 170, 540, 330, 800, 240, 1060, 150, 1330, 160, 1600, 240, + 1880, 170, 2140, 330, 2400, 240, 2660, 150, 2930, 160, 3200, 240 }; + +/* Gradient stops: offset, r, g, b, alpha. */ +typedef float C4fWaveStops[3][5]; +static const C4fWaveStops c4fSlowStops = { { 0, 255, 255, 255, 0 }, { .5f, 188, 216, 255, .55f }, { 1, 255, 255, 255, 0 } }; +static const C4fWaveStops c4fMainStops = { { 0, 127, 178, 255, .1f }, { .5f, 255, 255, 255, .5f }, { 1, 127, 178, 255, .1f } }; + +static C4fColor c4fWaveColor(const C4fWaveStops stops, float t, float opacity) +{ + const float *a = stops[0], *b = stops[1]; + t = c4fClamp(t); + if (t > stops[1][0]) { a = stops[1]; b = stops[2]; } + float f = (t - a[0]) / (b[0] - a[0]); + /* Interpolate premultiplied, as browsers do. */ + float alpha = a[4] + (b[4] - a[4]) * f, rgb[3]; + for (int k = 0; k < 3; k++) { + float v = a[k + 1] * a[4] + (b[k + 1] * b[4] - a[k + 1] * a[4]) * f; + rgb[k] = alpha > 0 ? v / alpha : a[k + 1]; + } + return (C4fColor){ (uint8_t)rgb[0], (uint8_t)rgb[1], (uint8_t)rgb[2], (uint8_t)(alpha * opacity * 255 + 0.5f) }; +} + +static void c4fPaintWave(C4fCanvas *c, const float path[25], float offset, float top, float sx, float sy, + float stroke, float opacity, const C4fWaveStops stops) +{ + enum { STEPS = 48, POINTS = 4 * STEPS + 1 }; + float px[POINTS], py[POINTS], x0 = 0, y0 = path[0]; + int n = 1; + px[0] = offset; + py[0] = top + y0 * sy; + for (int s = 0; s < 4; s++) { + const float *k = path + 1 + s * 6; + for (int i = 1; i <= STEPS; i++) { + float t = (float)i / STEPS, u = 1 - t; + float bx = u * u * u * x0 + 3 * u * u * t * k[0] + 3 * u * t * t * k[2] + t * t * t * k[4]; + float by = u * u * u * y0 + 3 * u * u * t * k[1] + 3 * u * t * t * k[3] + t * t * t * k[5]; + px[n] = offset + bx * sx; + py[n] = top + by * sy; + n++; + } + x0 = k[4]; + y0 = k[5]; + } + /* The paths only ever move right, so each column crosses a path once. */ + float half = fmaxf(stroke * sy / 2, 0.35f); + int seg = 0; + for (int x = 0; x < c->w; x++) { + float fx = x + 0.5f; + if (fx < px[0] || fx > px[n - 1]) continue; + while (seg < n - 2 && px[seg + 1] < fx) seg++; + float span = px[seg + 1] - px[seg]; + float slope = span > 0 ? (py[seg + 1] - py[seg]) / span : 0; + float yc = py[seg] + slope * (fx - px[seg]), norm = sqrtf(1 + slope * slope); + C4fColor color = c4fWaveColor(stops, (fx - offset) / (sx * 3200), opacity); + for (int y = (int)floorf(yc - (half + 1) * norm); y <= (int)ceilf(yc + (half + 1) * norm); y++) { + float cov = c4fClamp(half + 0.5f - fabsf(y + 0.5f - yc) / norm); + if (cov > 0) c4fBlend(c, x, y, color, cov); + } + } +} + +static void c4fPaintBackdrop(C4fCanvas *c, float scale) +{ + const float w = (float)c->w, h = (float)c->h, sx = 2 * w / 3200; + c4fPaintGradient(c); + /* A still from the drifting animation, the brightest part mid-screen. + * .waves.slow: bottom 14%, height 50%, opacity .7. */ + float top = 0.36f * h, sy = 0.5f * h / 400, offset = -0.70f * w; + c4fPaintWave(c, c4fWaveA, offset, top, sx, sy, 1.2f, 0.7f, c4fSlowStops); + c4fPaintWave(c, c4fWaveB, offset, top, sx, sy, 2.0f, 0.7f * 0.6f, c4fSlowStops); + /* .waves: bottom 4%, height 62%. */ + top = 0.34f * h; + sy = 0.62f * h / 400; + offset = -0.38f * w; + c4fPaintWave(c, c4fWaveC, offset, top, sx, sy, 1.5f, 1.0f, c4fMainStops); + c4fPaintWave(c, c4fWaveD, offset, top, sx, sy, 1.0f, 0.7f, c4fMainStops); + c4fPaintWave(c, c4fWaveE, offset, top, sx, sy, 3.0f, 0.35f, c4fMainStops); + /* .sparkles spans -10% to 110% of the height. */ + static const float dots[8][4] = { + { .12f, .22f, 1.5f, .70f }, { .28f, .64f, 1.0f, .55f }, { .47f, .38f, 1.5f, .60f }, { .63f, .76f, 1.0f, .50f }, + { .78f, .30f, 2.0f, .45f }, { .88f, .58f, 1.0f, .60f }, { .36f, .88f, 1.5f, .50f }, { .92f, .12f, 1.0f, .55f }, + }; + for (int i = 0; i < 8; i++) { + float cx = dots[i][0] * w, cy = -0.1f * h + dots[i][1] * 1.2f * h, r = fmaxf(dots[i][2] * scale, 1.5f); + for (int y = (int)floorf(cy - r); y <= (int)ceilf(cy + r); y++) + for (int x = (int)floorf(cx - r); x <= (int)ceilf(cx + r); x++) { + float d = hypotf(x + 0.5f - cx, y + 0.5f - cy); + if (d < r) c4fBlend(c, x, y, C4F_RGBA(255, 255, 255, dots[i][3]), 1 - d / r); + } + } +} + +static int c4fClampI(int v, int lo, int hi) { return v < lo ? lo : v > hi ? hi : v; } + +/* One box-blur pass along rows or columns of an RGB buffer, edges clamped. */ +static void c4fBoxPass(const uint8_t *src, uint8_t *dst, int w, int h, int radius, int horizontal) +{ + const int n = horizontal ? w : h, lines = horizontal ? h : w, divisor = 2 * radius + 1; + const int step = horizontal ? 3 : w * 3, lineStep = horizontal ? w * 3 : 3; + for (int line = 0; line < lines; line++) { + const uint8_t *s = src + (size_t)line * lineStep; + uint8_t *d = dst + (size_t)line * lineStep; + for (int k = 0; k < 3; k++) { + int sum = 0; + for (int i = -radius; i <= radius; i++) sum += s[c4fClampI(i, 0, n - 1) * step + k]; + for (int i = 0; i < n; i++) { + d[i * step + k] = (uint8_t)((sum + divisor / 2) / divisor); + sum += s[c4fClampI(i + radius + 1, 0, n - 1) * step + k] - s[c4fClampI(i - radius, 0, n - 1) * step + k]; + } + } + } +} + +/* backdrop-filter: blur(sigma) under a tile. The backdrop never changes, so + * this is done once, clipped to the tile's rounded shape. */ +static void c4fBlurUnder(C4fCanvas *c, float x, float y, float w, float h, float r, float sigma) +{ + /* Three box passes of this radius approximate a Gaussian of that sigma. */ + const int radius = (int)((sqrtf(4 * sigma * sigma + 1) - 1) / 2 + 0.5f), margin = 3 * radius; + const int x0 = c4fClampI((int)floorf(x) - margin, 0, c->w), y0 = c4fClampI((int)floorf(y) - margin, 0, c->h); + const int x1 = c4fClampI((int)ceilf(x + w) + margin, 0, c->w), y1 = c4fClampI((int)ceilf(y + h) + margin, 0, c->h); + const int bw = x1 - x0, bh = y1 - y0; + if (bw <= 0 || bh <= 0 || radius < 1) return; + uint8_t *buffer = malloc((size_t)bw * bh * 3), *scratch = malloc((size_t)bw * bh * 3); + if (buffer && scratch) { + for (int py = 0; py < bh; py++) + for (int px = 0; px < bw; px++) { + uint32_t v = c->px[(size_t)(y0 + py) * c->w + x0 + px]; + uint8_t *o = buffer + ((size_t)py * bw + px) * 3; + o[0] = (uint8_t)(v >> 16); o[1] = (uint8_t)(v >> 8); o[2] = (uint8_t)v; + } + for (int pass = 0; pass < 3; pass++) { + c4fBoxPass(buffer, scratch, bw, bh, radius, 1); + c4fBoxPass(scratch, buffer, bw, bh, radius, 0); + } + const float cx = x + w / 2, cy = y + h / 2; + for (int py = 0; py < bh; py++) + for (int px = 0; px < bw; px++) { + int gx = x0 + px, gy = y0 + py; + float cov = c4fClamp(0.5f - c4fRoundBoxDistance(gx + 0.5f, gy + 0.5f, cx, cy, w / 2, h / 2, r)); + if (cov <= 0) continue; + uint32_t *p = &c->px[(size_t)gy * c->w + gx], out = 0xff000000u; + const uint8_t *b = buffer + ((size_t)py * bw + px) * 3; + float noise = c4fNoise(gx, gy); + for (int k = 0; k < 3; k++) { + float old = (float)((*p >> (16 - 8 * k)) & 255u); + int v = (int)floorf(old + (b[k] - old) * cov + noise + 0.5f); + out |= (uint32_t)c4fClampI(v, 0, 255) << (16 - 8 * k); + } + *p = out; + } + } + free(buffer); + free(scratch); +} + +/* ---- pieces of the page ---- */ + +static float c4fCapsuleDistance(float x, float y, float ax, float ay, float bx, float by, float r) +{ + float vx = bx - ax, vy = by - ay, fx = x - ax, fy = y - ay; + float t = c4fClamp((fx * vx + fy * vy) / (vx * vx + vy * vy)); + return hypotf(fx - t * vx, fy - t * vy) - r; +} + +/* The page's controller mark (.app-mark, viewBox 0 0 32 32) from simple shapes. */ +static float c4fMarkDistance(float x, float y) +{ + float body = c4fRoundBoxDistance(x, y, 16, 15, 12.9f, 5, 5); + float grips = fminf(c4fCapsuleDistance(x, y, 6.4f, 16.5f, 7.6f, 21.2f, 3.3f), + c4fCapsuleDistance(x, y, 25.6f, 16.5f, 24.4f, 21.2f, 3.3f)); + float dpad = fminf(c4fRoundBoxDistance(x, y, 11, 17, 1, 3, 0.3f), c4fRoundBoxDistance(x, y, 11, 17, 3, 1, 0.3f)); + float buttons = fminf(hypotf(x - 21.5f, y - 15.5f), hypotf(x - 19, y - 19)) - 1.5f; + return fmaxf(fminf(body, grips), -fminf(dpad, buttons)); +} + +static void c4fMark(C4fCanvas *c, float cx, float cy, float unit, C4fColor color) +{ + for (int y = (int)floorf(cy - 8 * unit); y <= (int)ceilf(cy + 8 * unit); y++) + for (int x = (int)floorf(cx - 14 * unit); x <= (int)ceilf(cx + 14 * unit); x++) { + float d = c4fMarkDistance(16 + (x + 0.5f - cx) / unit, 17.3f + (y + 0.5f - cy) / unit) * unit; + float cov = c4fClamp(0.5f - d); + if (cov > 0) c4fBlend(c, x, y, color, cov); + } +} + +static void c4fTextCentered(C4fCanvas *c, int font, float size, float cx, float y, C4fColor color, const char *text) +{ + c4fText(c, font, size, cx - c4fTextWidth(font, size, text) / 2, y, color, text); +} + +/* .tile: --tile with a light sheen, a 1px line, a drop shadow and the colour bar. */ +static void c4fTile(C4fCanvas *c, float x, float y, float w, float h, C4fColor bar) +{ + const float r = 6 * C4F_S; + c4fShadowRoundRect(c, x, y, w, h, r, 0, 16 * C4F_S, 34 * C4F_S, -18 * C4F_S, C4F_RGBA(0, 0, 0, .9f)); + c4fFillRoundRect(c, x, y, w, h, r, C4F_TILE); + c4fSheenRoundRect(c, x, y, w, h, r, 160, C4F_WHITE, .13f, .02f, .55f); + c4fInsetRoundRect(c, x, y, w, h, r, 1 * C4F_S, C4F_LINE); + bar.a = (uint8_t)(bar.a * .9f); + c4fBandRoundRect(c, x, y, w, h, r, 3 * C4F_S, bar); +} + +/* .panel */ +static void c4fPanel(C4fCanvas *c, float x, float y, float w, float h, C4fColor fill, C4fColor line) +{ + c4fFillRoundRect(c, x, y, w, h, 6 * C4F_S, fill); + c4fInsetRoundRect(c, x, y, w, h, 6 * C4F_S, 1 * C4F_S, line); +} + +/* .ring: the numbered circle on a controller tile. */ +static void c4fRingBadge(C4fCanvas *c, float cx, float cy, C4fColor color, const char *label) +{ + const float r = 26 * C4F_S, hx = cx, hy = cy - 0.3f * r, far = hypotf(r, 1.3f * r); + c4fGlowCircle(c, cx, cy, r, 18 * C4F_S, -4 * C4F_S, color); + /* radial-gradient(circle at 50% 35%, rgba(255, 255, 255, .18), rgba(255, 255, 255, .03)) */ + for (int y = (int)floorf(cy - r - 1); y <= (int)ceilf(cy + r + 1); y++) + for (int x = (int)floorf(cx - r - 1); x <= (int)ceilf(cx + r + 1); x++) { + float inside = c4fClamp(0.5f - (hypotf(x + 0.5f - cx, y + 0.5f - cy) - r)); + if (inside <= 0) continue; + float t = c4fClamp(hypotf(x + 0.5f - hx, y + 0.5f - hy) / far); + c4fBlend(c, x, y, C4F_RGBA(255, 255, 255, .18f + (.03f - .18f) * t), inside); + } + c4fRing(c, cx, cy, r, 3 * C4F_S, color); + c4fTextCentered(c, C4F_FONT_LIGHT, 24 * C4F_S, cx, cy + 24 * C4F_S * 0.36f, C4F_TEXT, label); +} + +/* .dot, with the glow the page gives a live connection. */ +static void c4fDot(C4fCanvas *c, float cx, float cy, C4fColor color, int glow) +{ + if (glow) c4fGlowCircle(c, cx, cy, 4 * C4F_S, 10 * C4F_S, 0, color); + c4fFillCircle(c, cx, cy, 4 * C4F_S, color); +} + +/* Button guide in the PS4's manner, with the page's face-button colours. */ +enum { C4F_KEY_CROSS, C4F_KEY_CIRCLE, C4F_KEY_SQUARE }; +typedef struct { int key; const char *label; } C4fHint; +#define C4F_HINT_RADIUS 22.0f +#define C4F_HINT_GAP 14.0f +#define C4F_HINT_SPACING 40.0f +#define C4F_HINT_SIZE 26.0f + +static void c4fHints(C4fCanvas *c, float right, float cy, const C4fHint *hints, int count) +{ + float x = right; + for (int i = 0; i < count; i++) + x -= (i ? C4F_HINT_SPACING : 0) + 2 * C4F_HINT_RADIUS + C4F_HINT_GAP + + c4fTextWidth(C4F_FONT_REGULAR, C4F_HINT_SIZE, hints[i].label); + for (int i = 0; i < count; i++) { + float cx = x + C4F_HINT_RADIUS; + c4fFillCircle(c, cx, cy, C4F_HINT_RADIUS, C4F_RGBA(255, 255, 255, .08f)); + c4fRing(c, cx, cy, C4F_HINT_RADIUS, 1 * C4F_S, C4F_LINE_SOFT); + if (hints[i].key == C4F_KEY_CROSS) { + c4fSegment(c, cx - 8.5f, cy - 8.5f, cx + 8.5f, cy + 8.5f, 3.6f, C4F_CROSS_KEY); + c4fSegment(c, cx - 8.5f, cy + 8.5f, cx + 8.5f, cy - 8.5f, 3.6f, C4F_CROSS_KEY); + } else if (hints[i].key == C4F_KEY_CIRCLE) { + c4fRing(c, cx, cy, 10.5f, 3.6f, C4F_CIRCLE_KEY); + } else { + c4fSquareOutline(c, cx, cy, 8.5f, 3.4f, C4F_SQUARE_KEY); + } + x += 2 * C4F_HINT_RADIUS + C4F_HINT_GAP; + x += c4fText(c, C4F_FONT_REGULAR, C4F_HINT_SIZE, x, cy + C4F_HINT_SIZE * 0.36f, C4F_TEXT, hints[i].label); + x += C4F_HINT_SPACING; + } +} + +static void c4fQrCard(C4fCanvas *c, float x, float y, float size, const char *address) +{ + static char lastAddress[64]; + static uint8_t qr[qrcodegen_BUFFER_LEN_FOR_VERSION(5)]; + static int qrSize; + if (strcmp(lastAddress, address)) { + uint8_t temp[sizeof(qr)]; + qrSize = qrcodegen_encodeText(address, temp, qr, qrcodegen_Ecc_MEDIUM, 1, 5, qrcodegen_Mask_AUTO, true) + ? qrcodegen_getSize(qr) : 0; + snprintf(lastAddress, sizeof(lastAddress), "%s", address); + } + c4fFillRoundRect(c, x, y, size, size, 6 * C4F_S, C4F_WHITE); + if (!qrSize) return; + /* Whole pixels per module and a four-module quiet zone keep it scannable. */ + int scale = (int)(size / (float)(qrSize + 8)), drawn = qrSize * scale; + int left = (int)(x + (size - drawn) / 2), top = (int)(y + (size - drawn) / 2); + for (int row = 0; row < qrSize; row++) + for (int col = 0; col < qrSize; col++) + if (qrcodegen_getModule(qr, col, row)) + c4fFillRect(c, left + col * scale, top + row * scale, scale, scale, C4F_RGBA(4, 14, 40, 1)); +} + +/* ---- the screen ---- */ + +typedef struct { + const char *pill, *title, *subtitle, *meta; + C4fColor dot, bar; + int glow; +} C4fLook; + +static C4fLook c4fLookFor(const C4fLauncherScreen *s, char *meta, size_t metaSize) +{ + C4fLook look = { "Not responding", "Check Control4Free", + "Another program answers on port 4264, or nothing replied in time. Stop the old copy from " + "its phone page, or restart the PS4.", + "Not responding", C4F_BAD, C4F_BAD, 0 }; + if (s->locked) { + look.pill = look.meta = "Restart needed"; + look.title = "Restart the PS4"; + look.subtitle = "Control4Free was sent but never answered. Restart the console before you try again, so " + "two copies never run at once."; + } else if (s->busy) { + look = (C4fLook){ "Working", "Please wait", s->message, "Checking", C4F_WARN, C4F_ACCENT, 0 }; + } else if (s->running == 1) { + if (s->controllers == 1) snprintf(meta, metaSize, "1 controller connected"); + else snprintf(meta, metaSize, "%d controllers connected", s->controllers); + look = (C4fLook){ "Running", "Control4Free is running", + "Open the address or scan the code on your phone or PC. Pick a controller there, then " + "choose its user on the PS4.", + meta, C4F_OK, C4F_ACCENT, 1 }; + } else if (s->running == 0) { + look = (C4fLook){ "Stopped", "Start Control4Free", + "Press Cross with GoldHEN's PayLoader turned on, or start it from GoldHEN's Payloader " + "LaunchPad. Add it to AutoRun there and it starts with GoldHEN.", + "Not running", C4F_FAINT, C4F_FAINT, 0 }; + } + return look; +} + +void c4fDrawLauncher(uint32_t *pixels, const C4fLauncherScreen *s) +{ + C4fCanvas c = { pixels, C4F_SCREEN_WIDTH, C4F_SCREEN_HEIGHT }; + const float left = C4F_LEFT, right = C4F_RIGHT, top = C4F_ROW_TOP, height = C4F_ROW_HEIGHT; + const float qrWidth = C4F_QR_WIDTH, mainWidth = C4F_MAIN_WIDTH, pad = 16 * C4F_S; + char meta[48], count[8]; + C4fLook look = c4fLookFor(s, meta, sizeof(meta)); + int live = s->running == 1 && !s->locked; + + if (c4fBackdrop) memcpy(pixels, c4fBackdrop, (size_t)c.w * (size_t)c.h * sizeof(uint32_t)); + else memset(pixels, 0, (size_t)c.w * (size_t)c.h * sizeof(uint32_t)); + + /* .topbar: the app mark, the name and the state. */ + c4fMark(&c, 64 + 13 * C4F_S, 54, 26 * C4F_S / 32, C4F_WHITE); + float x = 64 + 26 * C4F_S + 10 * C4F_S; + x += c4fText(&c, C4F_FONT_LIGHT, 17 * C4F_S, x, 63, C4F_TEXT, "Control4Free") + 14 * C4F_S; + c4fDot(&c, x + 4 * C4F_S, 55, look.dot, look.glow); + c4fText(&c, C4F_FONT_LIGHT, 13 * C4F_S, x + 16 * C4F_S, 62, C4F_MUTED, look.pill); + + /* .screen-title and .screen-sub */ + c4fText(&c, C4F_FONT_LIGHT, 40 * C4F_S, left, 196, C4F_TEXT, look.title); + c4fTextWrapped(&c, C4F_FONT_LIGHT, 26, left, 250, 1500, 39, 2, C4F_MUTED, look.subtitle); + + /* Where to connect, as a controller tile. */ + c4fTile(&c, left, top, mainWidth, height, look.bar); + if (s->running == 1) snprintf(count, sizeof(count), "%d", s->controllers); + else snprintf(count, sizeof(count), "-"); + c4fRingBadge(&c, left + pad + 26 * C4F_S, top + pad + 26 * C4F_S + 4, look.bar, count); + float textX = left + pad + 52 * C4F_S + 22; + c4fText(&c, C4F_FONT_REGULAR, 30, textX, top + 66, C4F_TEXT, "Open on your phone or PC"); + c4fText(&c, C4F_FONT_LIGHT, 23, textX, top + 102, C4F_MUTED, look.meta); + + float fieldX = left + pad, fieldY = top + 150, fieldWidth = mainWidth - 2 * pad, fieldHeight = 88; + c4fFillRoundRect(&c, fieldX, fieldY, fieldWidth, fieldHeight, 4 * C4F_S, C4F_RGBA(0, 0, 0, .3f)); + c4fInsetRoundRect(&c, fieldX, fieldY, fieldWidth, fieldHeight, 4 * C4F_S, 1 * C4F_S, C4F_LINE); + if (s->address[0]) + c4fText(&c, C4F_FONT_REGULAR, 40, fieldX + 28, fieldY + fieldHeight / 2 + 14, live ? C4F_TEXT : C4F_MUTED, s->address); + else + c4fText(&c, C4F_FONT_LIGHT, 28, fieldX + 28, fieldY + fieldHeight / 2 + 10, C4F_MUTED, + "Connect the PS4 to your home network"); + c4fTextWrapped(&c, C4F_FONT_LIGHT, 24, fieldX, fieldY + fieldHeight + 44, fieldWidth, 36, 2, C4F_MUTED, + "Use the same network as the PS4. Touch, a keyboard and controllers connected to the phone " + "or PC all work."); + + /* The last result along the bottom of the tile. */ + float lineY = top + height - 104; + c4fFillRoundRect(&c, fieldX, lineY, fieldWidth, 1 * C4F_S, 0, C4F_LINE_SOFT); + c4fDot(&c, fieldX + 4 * C4F_S, lineY + 44, look.dot, look.glow); + c4fTextWrapped(&c, C4F_FONT_LIGHT, 24, fieldX + 24, lineY + 52, fieldWidth - 24, 34, 2, C4F_TEXT, + s->busy ? "Working..." : s->message); + + /* The QR code tile. */ + float qrX = C4F_QR_LEFT, card = 340, cardX = qrX + (qrWidth - card) / 2, cardY = top + 34; + c4fTile(&c, qrX, top, qrWidth, height, look.bar); + if (live && s->address[0]) { + c4fQrCard(&c, cardX, cardY, card, s->address); + c4fTextCentered(&c, C4F_FONT_LIGHT, 24, qrX + qrWidth / 2, cardY + card + 50, C4F_MUTED, + "Scan with your phone's camera"); + } else { + c4fFillRoundRect(&c, cardX, cardY, card, card, 6 * C4F_S, C4F_RGBA(0, 0, 0, .3f)); + c4fInsetRoundRect(&c, cardX, cardY, card, card, 6 * C4F_S, 1 * C4F_S, C4F_LINE_SOFT); + c4fMark(&c, cardX + card / 2, cardY + card / 2, 5, C4F_FAINT); + c4fTextCentered(&c, C4F_FONT_LIGHT, 24, qrX + qrWidth / 2, cardY + card + 50, C4F_MUTED, + "The code appears once it runs"); + } + + /* .panel with the one thing worth knowing. */ + float panelY = C4F_PANEL_TOP; + c4fPanel(&c, left, panelY, right - left, C4F_PANEL_HEIGHT, C4F_PANEL, C4F_LINE_SOFT); + c4fText(&c, C4F_FONT_LIGHT, 19 * C4F_S, left + 20 * C4F_S, panelY + 52, C4F_TEXT, + "Closing this app leaves your controllers running"); + c4fTextWrapped(&c, C4F_FONT_LIGHT, 23, left + 20 * C4F_S, panelY + 94, right - left - 40 * C4F_S, 34, 1, C4F_MUTED, + "Open it again any time to see the address or to stop Control4Free. Turn off other " + "controller plugins in your games."); + + /* .home-foot and the button guide. */ + c4fText(&c, C4F_FONT_LIGHT, 20, left, 1030, C4F_FAINT, "Control4Free " C4F_LAUNCHER_VERSION); + if (!s->confirmStop && !s->busy) { + C4fHint hints[2]; + int n = 0; + if (!s->locked) { + hints[n].key = live ? C4F_KEY_SQUARE : C4F_KEY_CROSS; + hints[n++].label = live ? "Stop" : "Start"; + } + hints[n].key = C4F_KEY_CIRCLE; + hints[n++].label = "Close"; + c4fHints(&c, right, 1022, hints, n); + } + + if (s->confirmStop) { + const float dw = 980, dh = 330, dx = (c.w - dw) / 2, dy = (c.h - dh) / 2; + static const C4fHint hints[2] = { { C4F_KEY_CROSS, "Stop" }, { C4F_KEY_CIRCLE, "Cancel" } }; + c4fFillRect(&c, 0, 0, c.w, c.h, C4F_RGBA(2, 11, 31, .6f)); + c4fShadowRoundRect(&c, dx, dy, dw, dh, 6 * C4F_S, 0, 16 * C4F_S, 34 * C4F_S, -18 * C4F_S, C4F_RGBA(0, 0, 0, .9f)); + /* A little more opaque than --panel-strong, so the tiles do not ghost through. */ + c4fPanel(&c, dx, dy, dw, dh, C4F_RGBA(2, 11, 31, .94f), C4F_LINE); + c4fText(&c, C4F_FONT_LIGHT, 48, dx + 48, dy + 96, C4F_TEXT, "Stop Control4Free?"); + c4fTextWrapped(&c, C4F_FONT_LIGHT, 26, dx + 48, dy + 152, dw - 96, 39, 2, C4F_MUTED, + "Every controller disconnects. You can start Control4Free again from this screen."); + c4fHints(&c, dx + dw - 48, dy + dh - 58, hints, 2); + } +} + +void c4fDrawIcon(uint32_t *pixels, int size) +{ + C4fCanvas c = { pixels, size, size }; + c4fPaintBackdrop(&c, size / 360.0f); + c4fMark(&c, size / 2.0f, size * 0.40f, size * 0.60f / 26, C4F_WHITE); + c4fTextCentered(&c, C4F_FONT_LIGHT, size * 0.105f, size / 2.0f, size * 0.80f, C4F_TEXT, "Control4Free"); +} + +int c4fScreenInit(void) +{ + if (c4fDrawInit()) return -1; + if (!c4fBackdrop) { + c4fBackdrop = malloc((size_t)C4F_SCREEN_WIDTH * C4F_SCREEN_HEIGHT * sizeof(uint32_t)); + if (!c4fBackdrop) return -1; + C4fCanvas c = { c4fBackdrop, C4F_SCREEN_WIDTH, C4F_SCREEN_HEIGHT }; + c4fPaintBackdrop(&c, C4F_S); + /* .tile has backdrop-filter: blur(6px), .panel blur(10px). */ + c4fBlurUnder(&c, C4F_LEFT, C4F_ROW_TOP, C4F_MAIN_WIDTH, C4F_ROW_HEIGHT, 6 * C4F_S, 6 * C4F_S); + c4fBlurUnder(&c, C4F_QR_LEFT, C4F_ROW_TOP, C4F_QR_WIDTH, C4F_ROW_HEIGHT, 6 * C4F_S, 6 * C4F_S); + c4fBlurUnder(&c, C4F_LEFT, C4F_PANEL_TOP, C4F_RIGHT - C4F_LEFT, C4F_PANEL_HEIGHT, 6 * C4F_S, 10 * C4F_S); + } + return 0; +} diff --git a/launcher/screen.h b/launcher/screen.h new file mode 100644 index 0000000..e42b048 --- /dev/null +++ b/launcher/screen.h @@ -0,0 +1,24 @@ +#ifndef C4F_LAUNCHER_SCREEN_H +#define C4F_LAUNCHER_SCREEN_H +#include +#define C4F_LAUNCHER_VERSION "0.2.0" +#define C4F_SCREEN_WIDTH 1920 +#define C4F_SCREEN_HEIGHT 1080 +typedef struct { + int running, busy, controllers, confirmStop, locked; + char address[64], message[160]; +} C4fLauncherScreen; +#ifdef __cplusplus +extern "C" { +#endif +/* Loads the fonts and paints the backdrop once. 0 on success. */ +int c4fScreenInit(void); +/* Draws a whole frame. Blending reads pixels back, so pass cached memory, + * never the write-combined framebuffer. */ +void c4fDrawLauncher(uint32_t *pixels, const C4fLauncherScreen *state); +/* The package icon (size x size), in the same style. */ +void c4fDrawIcon(uint32_t *pixels, int size); +#ifdef __cplusplus +} +#endif +#endif diff --git a/launcher/service.c b/launcher/service.c new file mode 100644 index 0000000..f965cb1 --- /dev/null +++ b/launcher/service.c @@ -0,0 +1,202 @@ +/* Local-only launcher transport. No controller creation or input injection. */ +#include "service.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define JSMN_STATIC +#define JSMN_STRICT +#include "jsmn.h" + +#ifndef C4F_SERVICE_PORT +#define C4F_SERVICE_PORT 4264 +#endif +#ifndef C4F_PAYLOADER_PORT +#define C4F_PAYLOADER_PORT 9090 +#endif + +uint64_t c4fLauncherTimeMs(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return (uint64_t)t.tv_sec * 1000 + t.tv_nsec / 1000000; +} + +static int c4fWaitSocket(int fd, int writeReady, uint64_t deadline) +{ + for (;;) { + uint64_t now = c4fLauncherTimeMs(); + if (now >= deadline) { errno = ETIMEDOUT; return -1; } + fd_set set; FD_ZERO(&set); FD_SET(fd, &set); + unsigned remaining = (unsigned)(deadline - now); + struct timeval tv = { remaining / 1000, (remaining % 1000) * 1000 }; + int ret = select(fd + 1, writeReady ? NULL : &set, writeReady ? &set : NULL, NULL, &tv); + if (ret > 0) return 0; + if (ret < 0 && errno == EINTR) continue; + if (ret == 0) errno = ETIMEDOUT; + return -1; + } +} + +static int c4fConnect(int port) +{ + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) return -1; + int savedError; + if (fd >= (int)FD_SETSIZE || fcntl(fd, F_SETFL, O_NONBLOCK) < 0) goto fail; +#ifdef SO_NOSIGPIPE + int one = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); +#endif + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) return fd; + if (errno != EINPROGRESS) goto fail; + if (c4fWaitSocket(fd, 1, c4fLauncherTimeMs() + 700)) goto fail; + int error = 0; socklen_t size = sizeof(error); + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &size) < 0) goto fail; + if (error) { errno = error; goto fail; } + return fd; +fail: + savedError = errno; close(fd); errno = savedError; return -1; +} + +static int c4fSendAll(int fd, const void *data, size_t size, uint64_t deadline) +{ + const char *p = data; + while (size) { + if (c4fWaitSocket(fd, 1, deadline)) return -1; + int flags = 0; +#ifdef MSG_NOSIGNAL + flags = MSG_NOSIGNAL; +#endif + ssize_t n = send(fd, p, size, flags); + if (n < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) continue; + if (n <= 0) return -1; + p += n; size -= (size_t)n; + } + return 0; +} + +static int c4fHttp(const char *method, const char *path, char *body, size_t capacity) +{ + int fd = c4fConnect(C4F_SERVICE_PORT); + if (fd < 0) return errno == ECONNREFUSED ? 0 : -1; + char request[256], response[2048]; + int n = snprintf(request, sizeof(request), "%s %s HTTP/1.1\r\nHost: 127.0.0.1:%d\r\nX-Control4Free-Launcher: 1\r\nContent-Length: 0\r\nConnection: close\r\n\r\n", method, path, C4F_SERVICE_PORT); + uint64_t deadline = c4fLauncherTimeMs() + 1500; + if (c4fSendAll(fd, request, (size_t)n, deadline)) { close(fd); return -1; } + size_t used = 0; + int complete = 0; + while (used < sizeof(response) - 1) { + if (c4fWaitSocket(fd, 0, deadline)) break; + ssize_t count = recv(fd, response + used, sizeof(response) - 1 - used, 0); + if (count < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) continue; + if (count == 0) { complete = 1; break; } + if (count < 0) break; + used += (size_t)count; + } + close(fd); response[used] = 0; + char *start = strstr(response, "\r\n\r\n"); + if (!complete || strncmp(response, "HTTP/1.1 200 OK\r\n", 17) || !start) return -1; + start += 4; + size_t length = used - (size_t)(start - response); + if (!length || length >= capacity || memchr(start, 0, length)) return -1; + memcpy(body, start, length); body[length] = 0; + return 1; +} + +static int c4fEquals(const char *json, const jsmntok_t *token, const char *value) +{ + return token->end - token->start == (int)strlen(value) && !memcmp(json + token->start, value, strlen(value)); +} + +int c4fLauncherProbe(C4fServiceStatus *status) +{ + char body[512]; jsmntok_t tokens[24]; jsmn_parser parser; + memset(status, 0, sizeof(*status)); + int result = c4fHttp("GET", "/api/status", body, sizeof(body)); + if (result <= 0) return result; + jsmn_init(&parser); + int count = jsmn_parse(&parser, body, strlen(body), tokens, 24); + if (count < 1 || tokens[0].type != JSMN_OBJECT || tokens[0].end != (int)strlen(body)) return -1; + int app = 0, api = 0, controllers = 0, stopping = 0; + for (int i = 1; i + 1 < count; i += 2) { + jsmntok_t *key = &tokens[i], *value = &tokens[i+1]; + if (key->type != JSMN_STRING || (value->type != JSMN_STRING && value->type != JSMN_PRIMITIVE)) return -1; + if (c4fEquals(body, key, "application")) app = value->type == JSMN_STRING && c4fEquals(body, value, "Control4Free"); + else if (c4fEquals(body, key, "api")) api = value->type == JSMN_PRIMITIVE && c4fEquals(body, value, "1"); + else if (c4fEquals(body, key, "controllers")) { + if (value->type != JSMN_PRIMITIVE || value->end - value->start != 1 || body[value->start] < '0' || body[value->start] > '4') return -1; + status->controllers = body[value->start] - '0'; controllers = 1; + } else if (c4fEquals(body, key, "stopping")) { + if (value->type != JSMN_PRIMITIVE || (!c4fEquals(body, value, "true") && !c4fEquals(body, value, "false"))) return -1; + status->stopping = c4fEquals(body, value, "true"); stopping = 1; + } else if (c4fEquals(body, key, "version")) { + int size = value->end - value->start; + if (value->type != JSMN_STRING || size >= (int)sizeof(status->version)) return -1; + memcpy(status->version, body + value->start, (size_t)size); + } + } + return app && api && controllers && stopping ? 1 : -1; +} + +int c4fLauncherStart(const char *payload, char *message, size_t size) +{ + C4fServiceStatus status; + int probe = c4fLauncherProbe(&status); + if (probe == 1) { snprintf(message, size, "Already running. Scan the code to connect."); return 0; } + if (probe != 0) { snprintf(message, size, "Existing service detected. Stop it from the phone first."); return -1; } + FILE *file = fopen(payload, "rb"); + if (!file) { snprintf(message, size, "Payload missing. Reinstall the Control4Free package."); return -1; } + unsigned char buffer[16384]; + size_t first = fread(buffer, 1, sizeof(buffer), file); + if (first < 64 || memcmp(buffer, "\177ELF", 4) || buffer[4] != 2 || buffer[5] != 1) { + fclose(file); snprintf(message, size, "Invalid bundled payload. Reinstall this package."); return -1; + } + int fd = c4fConnect(C4F_PAYLOADER_PORT); + if (fd < 0) { fclose(file); snprintf(message, size, "Turn on GoldHEN's PayLoader, then press Cross again."); return -1; } + uint64_t deadline = c4fLauncherTimeMs() + 10000; + int failed = c4fSendAll(fd, buffer, first, deadline); + while (!failed) { + size_t count = fread(buffer, 1, sizeof(buffer), file); + if (!count) { failed = ferror(file); break; } + failed = c4fSendAll(fd, buffer, count, deadline); + } + fclose(file); shutdown(fd, SHUT_WR); close(fd); + if (failed) { snprintf(message, size, "Transfer interrupted. Restart the PS4 before retrying."); return -2; } + deadline = c4fLauncherTimeMs() + 20000; + while (c4fLauncherTimeMs() < deadline) { + if (c4fLauncherProbe(&status) == 1 && !status.stopping) { + snprintf(message, size, "Ready. Scan the code or open the address on your phone."); return 0; + } + usleep(250000); + } + snprintf(message, size, "Sent, but no reply. Restart the PS4 before retrying."); + return -2; /* Caller locks further sends until restart, avoiding duplicates. */ +} + +int c4fLauncherStop(char *message, size_t size) +{ + C4fServiceStatus status; + int probe = c4fLauncherProbe(&status); + if (probe == 0) { snprintf(message, size, "Stopped. Press Cross to start it again."); return 0; } + if (probe != 1) { snprintf(message, size, "Older service detected. Stop it from the phone."); return -1; } + char reply[256]; + int ret = c4fHttp("POST", "/api/stop", reply, sizeof(reply)); + if (ret != 1) { snprintf(message, size, "Stop was not confirmed. Check the phone page."); return -1; } + uint64_t deadline = c4fLauncherTimeMs() + 5000; + while (c4fLauncherTimeMs() < deadline) { + if (c4fLauncherProbe(&status) == 0) { snprintf(message, size, "Stopped. Press Cross to start it again."); return 0; } + usleep(100000); + } + snprintf(message, size, "Still stopping. Wait before trying again."); return -1; +} diff --git a/launcher/service.h b/launcher/service.h new file mode 100644 index 0000000..1e9bbb4 --- /dev/null +++ b/launcher/service.h @@ -0,0 +1,20 @@ +#ifndef C4F_LAUNCHER_SERVICE_H +#define C4F_LAUNCHER_SERVICE_H +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +enum { C4F_SERVICE_UNKNOWN = -1, C4F_SERVICE_DOWN = 0, C4F_SERVICE_RUNNING = 1 }; +typedef struct { int controllers, stopping; char version[24]; } C4fServiceStatus; +uint64_t c4fLauncherTimeMs(void); +/* DOWN is returned only for a refused local connection. Ambiguous responses + * must not authorize starting another copy in the shared payload host. */ +int c4fLauncherProbe(C4fServiceStatus *status); +int c4fLauncherStart(const char *payload, char *message, size_t size); +int c4fLauncherStop(char *message, size_t size); +#ifdef __cplusplus +} +#endif +#endif diff --git a/launcher/stb_truetype.c b/launcher/stb_truetype.c new file mode 100644 index 0000000..6a0dda2 --- /dev/null +++ b/launcher/stb_truetype.c @@ -0,0 +1,3 @@ +/* stb_truetype's implementation, built on its own with warnings off (vendor code). */ +#define STB_TRUETYPE_IMPLEMENTATION +#include "stb_truetype.h" diff --git a/tools/build-launcher.ps1 b/tools/build-launcher.ps1 new file mode 100644 index 0000000..32f08f9 --- /dev/null +++ b/tools/build-launcher.ps1 @@ -0,0 +1,15 @@ +<# Build the payload and installable PS4 launcher locally. Requires Docker. #> +$ErrorActionPreference = 'Stop' +$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +Push-Location $projectRoot +try { + docker build -t control4free-build -f docker/Dockerfile docker + if ($LASTEXITCODE -ne 0) { throw 'Payload toolchain build failed.' } + docker build -t control4free-launcher-build -f docker/Dockerfile.launcher docker + if ($LASTEXITCODE -ne 0) { throw 'Launcher toolchain build failed.' } + docker run --rm --network none -v "${projectRoot}:/src" -w /src control4free-launcher-build bash -lc 'make && make -C launcher' + if ($LASTEXITCODE -ne 0) { throw 'Launcher package build failed.' } + Get-Item -LiteralPath (Join-Path $projectRoot 'build/Control4Free-0.2.0.pkg') | Select-Object FullName,Length +} finally { + Pop-Location +} diff --git a/tools/embed_file.py b/tools/embed_file.py new file mode 100644 index 0000000..63674dc --- /dev/null +++ b/tools/embed_file.py @@ -0,0 +1,15 @@ +"""Embed binary files in a C source: embed_file.py out.c symbol=path [symbol=path ...]""" +import sys +from pathlib import Path + +out, pairs = Path(sys.argv[1]), [arg.split('=', 1) for arg in sys.argv[2:]] +lines = ['/* Generated by tools/embed_file.py; do not edit. */', '#include '] +for symbol, path in pairs: + data = Path(path).read_bytes() + lines.append(f'/* {Path(path).name} */') + lines.append(f'__attribute__((aligned(4))) const unsigned char {symbol}[] = {{') + for i in range(0, len(data), 24): + lines.append(''.join(f'{b},' for b in data[i:i + 24])) + lines.append('};') + lines.append(f'const size_t {symbol}Size = {len(data)};') +out.write_text('\n'.join(lines) + '\n') diff --git a/tools/launcher_art.c b/tools/launcher_art.c new file mode 100644 index 0000000..4832223 --- /dev/null +++ b/tools/launcher_art.c @@ -0,0 +1,56 @@ +/* Renders launcher artwork on the build machine with the launcher's own drawing + * code: the package icon, and screen states for review. Writes raw RGBA. + * launcher_art icon + * launcher_art screen */ +#include +#include +#include +#include "screen.h" + +static int c4fWrite(const char *path, const uint32_t *pixels, size_t count) +{ + FILE *out = fopen(path, "wb"); + if (!out) return 1; + for (size_t i = 0; i < count; i++) { + unsigned char rgba[4] = { (unsigned char)(pixels[i] >> 16), (unsigned char)(pixels[i] >> 8), + (unsigned char)pixels[i], (unsigned char)(pixels[i] >> 24) }; + fwrite(rgba, 1, 4, out); + } + return fclose(out) != 0; +} + +int main(int argc, char **argv) +{ + if (argc != 4 || c4fScreenInit()) return 2; + if (!strcmp(argv[1], "icon")) { + int size = atoi(argv[2]); + uint32_t *pixels = size > 0 && size <= 4096 ? calloc((size_t)size * size, sizeof(uint32_t)) : NULL; + if (!pixels) return 2; + c4fDrawIcon(pixels, size); + return c4fWrite(argv[3], pixels, (size_t)size * size); + } + if (strcmp(argv[1], "screen")) return 2; + C4fLauncherScreen s; + memset(&s, 0, sizeof(s)); + snprintf(s.address, sizeof(s.address), "http://192.168.1.20:4264"); + const char *state = argv[2], *message = ""; + if (!strcmp(state, "running") || !strcmp(state, "confirm")) { + s.running = 1; s.controllers = 2; s.confirmStop = !strcmp(state, "confirm"); + message = "Ready. Scan the code or open the address on your phone."; + } else if (!strcmp(state, "stopped")) { + message = "Not running. Press Cross to start it."; + } else if (!strcmp(state, "busy")) { + s.running = -1; s.busy = 1; message = "Starting Control4Free. Please wait..."; + } else if (!strcmp(state, "locked")) { + s.running = -1; s.locked = 1; message = "Sent, but no reply. Restart the PS4 before retrying."; + } else if (!strcmp(state, "unknown")) { + s.running = -1; message = "Existing service detected. Stop it from the phone first."; + } else { + return 2; + } + snprintf(s.message, sizeof(s.message), "%s", message); + uint32_t *pixels = calloc((size_t)C4F_SCREEN_WIDTH * C4F_SCREEN_HEIGHT, sizeof(uint32_t)); + if (!pixels) return 2; + c4fDrawLauncher(pixels, &s); + return c4fWrite(argv[3], pixels, (size_t)C4F_SCREEN_WIDTH * C4F_SCREEN_HEIGHT); +} diff --git a/tools/package_launcher.py b/tools/package_launcher.py new file mode 100644 index 0000000..4412b85 --- /dev/null +++ b/tools/package_launcher.py @@ -0,0 +1,132 @@ +"""Build the native launcher package using OpenOrbis/LibOrbisPkg only.""" +import argparse +import binascii +import shutil +import struct +import subprocess +import zlib +import xml.etree.ElementTree as ET +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +OUT = ROOT / 'build/launcher' +STAGE = OUT / 'pkg' +ART = OUT / 'launcher-art' +FONTS = OUT / 'fonts.c' +TITLE_ID = 'CFRE00001' # 4 letters + 5 digits, the usual title ID format +CONTENT_ID = f'IV0000-{TITLE_ID}_00-CONTROL4FREE0000' +assert len(CONTENT_ID) == 36 + + +def embed_fonts(): + sources = [ROOT / 'vendor/roboto/Roboto-Light.ttf', ROOT / 'vendor/roboto/Roboto-Regular.ttf'] + if FONTS.exists() and all(FONTS.stat().st_mtime >= s.stat().st_mtime for s in sources): + return + OUT.mkdir(parents=True, exist_ok=True) + subprocess.run(['python3', str(ROOT / 'tools/embed_file.py'), str(FONTS), + f'c4fFontLight={sources[0]}', f'c4fFontRegular={sources[1]}'], check=True) + + +def build_art_tool(): + """Host build of the launcher's drawing code, for the icon and previews.""" + embed_fonts() + flags = ['clang-18', '-std=gnu11', '-O2', '-D_DEFAULT_SOURCE', f'-I{ROOT}/launcher', + f'-I{ROOT}/vendor/stb', f'-I{ROOT}/vendor/qrcodegen'] + stb = OUT / 'stb_truetype-host.o' + subprocess.run([*flags, '-w', '-c', str(ROOT / 'launcher/stb_truetype.c'), '-o', str(stb)], check=True) + subprocess.run([*flags, '-Wall', '-Wextra', '-Werror', str(ROOT / 'tools/launcher_art.c'), + str(ROOT / 'launcher/screen.c'), str(ROOT / 'launcher/draw.c'), + str(ROOT / 'vendor/qrcodegen/qrcodegen.c'), str(FONTS), str(stb), '-lm', '-o', str(ART)], + check=True) + + +def write_png(path, width, height, rgba, alpha=False): + def chunk(kind, data): + return struct.pack('>I', len(data)) + kind + data + struct.pack('>I', binascii.crc32(kind + data) & 0xffffffff) + pixels = rgba if alpha else bytes(b for i, b in enumerate(rgba) if i % 4 != 3) + stride = width * (4 if alpha else 3) + scanlines = b''.join(b'\0' + pixels[y * stride:(y + 1) * stride] for y in range(height)) + header = struct.pack('>IIBBBBB', width, height, 8, 6 if alpha else 2, 0, 0, 0) + Path(path).write_bytes(b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', header) + + chunk(b'IDAT', zlib.compress(scanlines, 9)) + chunk(b'IEND', b'')) + + +def render(args, path, width, height): + """Draw with the art tool (build_art_tool first) and save a PNG.""" + raw = OUT / 'art.rgba' + subprocess.run([str(ART), *args, str(raw)], check=True) + write_png(path, width, height, raw.read_bytes()) + raw.unlink() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--sdk', required=True, type=Path) + sdk = parser.parse_args().sdk + binary = sdk / 'bin/linux' + # Start clean, so nothing left over from an older build gets packaged. + shutil.rmtree(STAGE, ignore_errors=True) + for directory in ('sce_sys/about', 'sce_module', 'assets', 'assets/licenses'): + (STAGE / directory).mkdir(parents=True, exist_ok=True) + run = lambda *args: subprocess.run([str(arg) for arg in args], cwd=STAGE, check=True) + run(binary / 'create-fself', '-in=' + str(OUT / 'launcher.elf'), '-out=' + str(OUT / 'launcher.oelf'), + '--eboot', 'eboot.bin', '--paid', '0x3800000000000011') + shutil.copyfile(ROOT / 'build/control4free.elf', STAGE / 'assets/control4free.elf') + shutil.copyfile(sdk / 'samples/graphics/sce_sys/about/right.sprx', STAGE / 'sce_sys/about/right.sprx') + # OpenOrbis's stub modules. Its CHANGELOG (v0.5) says homebrew packages + # should carry them in sce_module/, and every sample does. + for name in ('libc.prx', 'libSceFios2.prx'): + shutil.copyfile(sdk / 'samples/graphics/sce_module' / name, STAGE / 'sce_module' / name) + licenses = STAGE / 'assets/licenses' + shutil.copyfile(ROOT / 'LICENSE', licenses / 'Control4Free-GPL-3.0.txt') + shutil.copyfile(ROOT / 'THIRD_PARTY.md', licenses / 'THIRD_PARTY.txt') + shutil.copyfile(ROOT / 'vendor/jsmn/LICENSE', licenses / 'jsmn-MIT.txt') + shutil.copyfile(ROOT / 'vendor/roboto/LICENSE', licenses / 'Roboto-Apache-2.0.txt') + qrcodegen = (ROOT / 'vendor/qrcodegen/qrcodegen.h').read_text() + (licenses / 'qrcodegen-MIT.txt').write_text(qrcodegen.split('*/', 1)[0] + '*/\n') + stb = (ROOT / 'vendor/stb/stb_truetype.h').read_text() + (licenses / 'stb_truetype.txt').write_text(stb[stb.index('This software is available under 2 licenses'):]) + # The home-screen icon comes from the launcher's own drawing code. + build_art_tool() + render(['icon', '512'], STAGE / 'sce_sys/icon0.png', 512, 512) + pkgtool = binary / 'PkgTool.Core' + sfo = 'sce_sys/param.sfo' + run(pkgtool, 'sfo_new', sfo) + entries = { + 'APP_TYPE': ('Integer', 4, '1'), 'APP_VER': ('Utf8', 8, '00.20'), + 'ATTRIBUTE': ('Integer', 4, '0'), 'CATEGORY': ('Utf8', 4, 'gd'), + 'CONTENT_ID': ('Utf8', 48, CONTENT_ID), 'DOWNLOAD_DATA_SIZE': ('Integer', 4, '0'), + 'SYSTEM_VER': ('Integer', 4, '0'), 'TITLE': ('Utf8', 128, 'Control4Free'), + 'TITLE_ID': ('Utf8', 12, TITLE_ID), 'VERSION': ('Utf8', 8, '00.20'), + } + for key, (kind, size, value) in entries.items(): + run(pkgtool, 'sfo_setentry', sfo, key, '--type', kind, '--maxsize', size, '--value', value) + files = ['eboot.bin', 'sce_sys/param.sfo', 'sce_sys/icon0.png', 'sce_sys/about/right.sprx', + 'sce_module/libc.prx', 'sce_module/libSceFios2.prx', 'assets/control4free.elf'] + files += sorted(str(p.relative_to(STAGE)) for p in (STAGE / 'assets/licenses').iterdir()) + project = STAGE / 'launcher.gp4' + run(binary / 'create-gp4', '-out', project, '--content-id=' + CONTENT_ID, '--files', ' '.join(files)) + # create-gp4 ships a sample directory tree. Describe the actual package, + # including nested license files, and keep source paths relative to it. + tree = ET.parse(project) + rootdir = tree.getroot().find('rootdir') + rootdir.clear() + for filename in files: + parent = rootdir + for part in Path(filename).parts[:-1]: + child = next((p for p in parent if p.get('targ_name') == part), None) + if child is None: + child = ET.SubElement(parent, 'dir', targ_name=part) + parent = child + ET.indent(tree) + tree.write(project, encoding='utf-8', xml_declaration=True) + shutil.copyfile(project, OUT / 'launcher.gp4') + run(pkgtool, 'pkg_build', project, OUT) + generated = OUT / (CONTENT_ID + '.pkg') + target = ROOT / 'build/Control4Free-0.2.0.pkg' + shutil.copyfile(generated, target) + print(f'Built {target} ({target.stat().st_size:,} bytes)', flush=True) + + +if __name__ == '__main__': + main() diff --git a/vendor/qrcodegen/qrcodegen.c b/vendor/qrcodegen/qrcodegen.c new file mode 100644 index 0000000..8617044 --- /dev/null +++ b/vendor/qrcodegen/qrcodegen.c @@ -0,0 +1,1022 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include +#include "qrcodegen.h" + +#ifndef QRCODEGEN_TEST + #define testable static // Keep functions private +#else + #define testable // Expose private functions +#endif + + +/*---- Forward declarations for private functions ----*/ + +// Regarding all public and private functions defined in this source file: +// - They require all pointer/array arguments to be not null unless the array length is zero. +// - They only read input scalar/array arguments, write to output pointer/array +// arguments, and return scalar values; they are "pure" functions. +// - They don't read mutable global variables or write to any global variables. +// - They don't perform I/O, read the clock, print to console, etc. +// - They allocate a small and constant amount of stack memory. +// - They don't allocate or free any memory on the heap. +// - They don't recurse or mutually recurse. All the code +// could be inlined into the top-level public functions. +// - They run in at most quadratic time with respect to input arguments. +// Most functions run in linear time, and some in constant time. +// There are no unbounded loops or non-obvious termination conditions. +// - They are completely thread-safe if the caller does not give the +// same writable buffer to concurrent calls to these functions. + +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); + +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); +testable int getNumRawDataModules(int ver); + +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); +testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]); +testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y); + +testable void initializeFunctionModules(int version, uint8_t qrcode[]); +static void drawLightFunctionModules(uint8_t qrcode[], int version); +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); +testable int getAlignmentPatternPositions(int version, uint8_t result[7]); +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); + +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); +static long getPenaltyScore(const uint8_t qrcode[]); +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); +static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize); +static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize); + +testable bool getModuleBounded(const uint8_t qrcode[], int x, int y); +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark); +testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark); +static bool getBit(int x, int i); + +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); +static int numCharCountBits(enum qrcodegen_Mode mode, int version); + + + +/*---- Private tables of constants ----*/ + +// The set of all legal characters in alphanumeric mode, where each character +// value maps to the index in the string. For checking text and encoding segments. +static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + +// For generating error correction codes. +testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High +}; + +#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above + +// For generating error correction codes. +testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High +}; + +// For automatic mask pattern selection. +static const int PENALTY_N1 = 3; +static const int PENALTY_N2 = 3; +static const int PENALTY_N3 = 40; +static const int PENALTY_N4 = 10; + + + +/*---- High-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { + + size_t textLen = strlen(text); + if (textLen == 0) + return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); + + struct qrcodegen_Segment seg; + if (qrcodegen_isNumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) + goto fail; + seg = qrcodegen_makeNumeric(text, tempBuffer); + } else if (qrcodegen_isAlphanumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) + goto fail; + seg = qrcodegen_makeAlphanumeric(text, tempBuffer); + } else { + if (textLen > bufLen) + goto fail; + for (size_t i = 0; i < textLen; i++) + tempBuffer[i] = (uint8_t)text[i]; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, textLen); + if (seg.bitLength == -1) + goto fail; + seg.numChars = (int)textLen; + seg.data = tempBuffer; + } + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + +fail: + qrcode[0] = 0; // Set size to invalid value for safety + return false; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { + + struct qrcodegen_Segment seg; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); + if (seg.bitLength == -1) { + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + seg.numChars = (int)dataLen; + seg.data = dataAndTemp; + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); +} + + +// Appends the given number of low-order bits of the given value to the given byte-based +// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { + assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); + for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) + buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); +} + + + +/*---- Low-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { + return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, + qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { + assert(segs != NULL || len == 0); + assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); + assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); + + // Find the minimal version number to use + int version, dataUsedBits; + for (version = minVersion; ; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = getTotalBits(segs, len, version); + if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) + break; // This version number is found to be suitable + if (version >= maxVersion) { // All versions in the range could not fit the given data + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + } + assert(dataUsedBits != -1); + + // Increase the error correction level while the data still fits in the current version number + for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high + if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) + ecl = (enum qrcodegen_Ecc)i; + } + + // Concatenate all segments to create the data bit string + memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); + int bitLen = 0; + for (size_t i = 0; i < len; i++) { + const struct qrcodegen_Segment *seg = &segs[i]; + appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen); + appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); + for (int j = 0; j < seg->bitLength; j++) { + int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; + appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen); + } + } + assert(bitLen == dataUsedBits); + + // Add terminator and pad up to a byte if applicable + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; + assert(bitLen <= dataCapacityBits); + int terminatorBits = dataCapacityBits - bitLen; + if (terminatorBits > 4) + terminatorBits = 4; + appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); + appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); + assert(bitLen % 8 == 0); + + // Pad with alternating bytes until data capacity is reached + for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) + appendBitsToBuffer(padByte, 8, qrcode, &bitLen); + + // Compute ECC, draw modules + addEccAndInterleave(qrcode, version, ecl, tempBuffer); + initializeFunctionModules(version, qrcode); + drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); + drawLightFunctionModules(qrcode, version); + initializeFunctionModules(version, tempBuffer); + + // Do masking + if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for (int i = 0; i < 8; i++) { + enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; + applyMask(tempBuffer, qrcode, msk); + drawFormatBits(ecl, msk, qrcode); + long penalty = getPenaltyScore(qrcode); + if (penalty < minPenalty) { + mask = msk; + minPenalty = penalty; + } + applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR + } + } + assert(0 <= (int)mask && (int)mask <= 7); + applyMask(tempBuffer, qrcode, mask); // Apply the final choice of mask + drawFormatBits(ecl, mask, qrcode); // Overwrite old format bits + return true; +} + + + +/*---- Error correction code generation functions ----*/ + +// Appends error correction bytes to each block of the given data array, then interleaves +// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains +// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will +// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { + // Calculate parameter numbers + assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int dataLen = getNumDataCodewords(version, ecl); + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; + + // Split data into blocks, calculate ECC, and interleave + // (not concatenate) the bytes into a single sequence + uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; + reedSolomonComputeDivisor(blockEccLen, rsdiv); + const uint8_t *dat = data; + for (int i = 0; i < numBlocks; i++) { + int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); + uint8_t *ecc = &data[dataLen]; // Temporary storage + reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); + for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data + if (j == shortBlockDataLen) + k -= numShortBlocks; + result[k] = dat[j]; + } + for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC + result[k] = ecc[j]; + dat += datLen; + } +} + + +// Returns the number of 8-bit codewords that can be used for storing data (not ECC), +// for the given version number and error correction level. The result is in the range [9, 2956]. +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { + int v = version, e = (int)ecl; + assert(0 <= e && e < 4); + return getNumRawDataModules(v) / 8 + - ECC_CODEWORDS_PER_BLOCK [e][v] + * NUM_ERROR_CORRECTION_BLOCKS[e][v]; +} + + +// Returns the number of data bits that can be stored in a QR Code of the given version number, after +// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. +// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. +testable int getNumRawDataModules(int ver) { + assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); + int result = (16 * ver + 128) * ver + 64; + if (ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) + result -= 36; + } + assert(208 <= result && result <= 29648); + return result; +} + + + +/*---- Reed-Solomon ECC generator functions ----*/ + +// Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : degree]. +// This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) { + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. + // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. + memset(result, 0, (size_t)degree * sizeof(result[0])); + result[degree - 1] = 1; // Start off with the monomial x^0 + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest monomial term which is always 1x^degree. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for (int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (int j = 0; j < degree; j++) { + result[j] = reedSolomonMultiply(result[j], root); + if (j + 1 < degree) + result[j] ^= result[j + 1]; + } + root = reedSolomonMultiply(root, 0x02); + } +} + + +// Computes the Reed-Solomon error correction codeword for the given data and divisor polynomials. +// The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : degree]. +// All polynomials are in big endian, and the generator has an implicit leading 1 term. +testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]) { + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + memset(result, 0, (size_t)degree * sizeof(result[0])); + for (int i = 0; i < dataLen; i++) { // Polynomial division + uint8_t factor = data[i] ^ result[0]; + memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0])); + result[degree - 1] = 0; + for (int j = 0; j < degree; j++) + result[j] ^= reedSolomonMultiply(generator[j], factor); + } +} + +#undef qrcodegen_REED_SOLOMON_DEGREE_MAX + + +// Returns the product of the two given field elements modulo GF(2^8/0x11D). +// All inputs are valid. This could be implemented as a 256*256 lookup table. +testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) { + // Russian peasant multiplication + uint8_t z = 0; + for (int i = 7; i >= 0; i--) { + z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); + z ^= ((y >> i) & 1) * x; + } + return z; +} + + + +/*---- Drawing function modules ----*/ + +// Clears the given QR Code grid with light modules for the given +// version's size, then marks every function module as dark. +testable void initializeFunctionModules(int version, uint8_t qrcode[]) { + // Initialize QR Code + int qrsize = version * 4 + 17; + memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); + qrcode[0] = (uint8_t)qrsize; + + // Fill horizontal and vertical timing patterns + fillRectangle(6, 0, 1, qrsize, qrcode); + fillRectangle(0, 6, qrsize, 1, qrcode); + + // Fill 3 finder patterns (all corners except bottom right) and format bits + fillRectangle(0, 0, 9, 9, qrcode); + fillRectangle(qrsize - 8, 0, 8, 9, qrcode); + fillRectangle(0, qrsize - 8, 9, 8, qrcode); + + // Fill numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) + fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); + } + } + + // Fill version blocks + if (version >= 7) { + fillRectangle(qrsize - 11, 0, 3, 6, qrcode); + fillRectangle(0, qrsize - 11, 6, 3, qrcode); + } +} + + +// Draws light function modules and possibly some dark modules onto the given QR Code, without changing +// non-function modules. This does not draw the format bits. This requires all function modules to be previously +// marked dark (namely by initializeFunctionModules()), because this may skip redrawing dark function modules. +static void drawLightFunctionModules(uint8_t qrcode[], int version) { + // Draw horizontal and vertical timing patterns + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 7; i < qrsize - 7; i += 2) { + setModuleBounded(qrcode, 6, i, false); + setModuleBounded(qrcode, i, 6, false); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + for (int dy = -4; dy <= 4; dy++) { + for (int dx = -4; dx <= 4; dx++) { + int dist = abs(dx); + if (abs(dy) > dist) + dist = abs(dy); + if (dist == 2 || dist == 4) { + setModuleUnbounded(qrcode, 3 + dx, 3 + dy, false); + setModuleUnbounded(qrcode, qrsize - 4 + dx, 3 + dy, false); + setModuleUnbounded(qrcode, 3 + dx, qrsize - 4 + dy, false); + } + } + } + + // Draw numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) + continue; // Don't draw on the three finder corners + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) + setModuleBounded(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); + } + } + } + + // Draw version blocks + if (version >= 7) { + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for (int i = 0; i < 12; i++) + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + long bits = (long)version << 12 | rem; // uint18 + assert(bits >> 18 == 0); + + // Draw two copies + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 3; j++) { + int k = qrsize - 11 + j; + setModuleBounded(qrcode, k, i, (bits & 1) != 0); + setModuleBounded(qrcode, i, k, (bits & 1) != 0); + bits >>= 1; + } + } + } +} + + +// Draws two copies of the format bits (with its own error correction code) based +// on the given mask and error correction level. This always draws all modules of +// the format bits, unlike drawLightFunctionModules() which might skip dark modules. +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { + // Calculate error correction code and pack bits + assert(0 <= (int)mask && (int)mask <= 7); + static const int table[] = {1, 0, 3, 2}; + int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 + int rem = data; + for (int i = 0; i < 10; i++) + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + assert(bits >> 15 == 0); + + // Draw first copy + for (int i = 0; i <= 5; i++) + setModuleBounded(qrcode, 8, i, getBit(bits, i)); + setModuleBounded(qrcode, 8, 7, getBit(bits, 6)); + setModuleBounded(qrcode, 8, 8, getBit(bits, 7)); + setModuleBounded(qrcode, 7, 8, getBit(bits, 8)); + for (int i = 9; i < 15; i++) + setModuleBounded(qrcode, 14 - i, 8, getBit(bits, i)); + + // Draw second copy + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 0; i < 8; i++) + setModuleBounded(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); + for (int i = 8; i < 15; i++) + setModuleBounded(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); + setModuleBounded(qrcode, 8, qrsize - 8, true); // Always dark +} + + +// Calculates and stores an ascending list of positions of alignment patterns +// for this version number, returning the length of the list (in the range [0,7]). +// Each position is in the range [0,177), and are used on both the x and y axes. +// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. +testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { + if (version == 1) + return 0; + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; + for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) + result[i] = (uint8_t)pos; + result[0] = 6; + return numAlign; +} + + +// Sets every module in the range [left : left + width] * [top : top + height] to dark. +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { + for (int dy = 0; dy < height; dy++) { + for (int dx = 0; dx < width; dx++) + setModuleBounded(qrcode, left + dx, top + dy, true); + } +} + + + +/*---- Drawing data modules and masking ----*/ + +// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of +// the QR Code to be dark at function modules and light at codeword modules (including unused remainder bits). +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { + int qrsize = qrcodegen_getSize(qrcode); + int i = 0; // Bit index into the data + // Do the funny zigzag scan + for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) + right = 5; + for (int vert = 0; vert < qrsize; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + int x = right - j; // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate + if (!getModuleBounded(qrcode, x, y) && i < dataLen * 8) { + bool dark = getBit(data[i >> 3], 7 - (i & 7)); + setModuleBounded(qrcode, x, y, dark); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/light by the constructor and are left unchanged by this method + } + } + } + assert(i == dataLen * 8); +} + + +// XORs the codeword modules in this QR Code with the given mask pattern +// and given pattern of function modules. The codeword bits must be drawn +// before masking. Due to the arithmetic of XOR, calling applyMask() with +// the same mask value a second time will undo the mask. A final well-formed +// QR Code needs exactly one (not zero, two, etc.) mask applied. +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { + assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO + int qrsize = qrcodegen_getSize(qrcode); + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(functionModules, x, y)) + continue; + bool invert; + switch ((int)mask) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + default: assert(false); return; + } + bool val = getModuleBounded(qrcode, x, y); + setModuleBounded(qrcode, x, y, val ^ invert); + } + } +} + + +// Calculates and returns the penalty score based on state of the given QR Code's current modules. +// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. +static long getPenaltyScore(const uint8_t qrcode[]) { + int qrsize = qrcodegen_getSize(qrcode); + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for (int y = 0; y < qrsize; y++) { + bool runColor = false; + int runX = 0; + int runHistory[7] = {0}; + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(qrcode, x, y) == runColor) { + runX++; + if (runX == 5) + result += PENALTY_N1; + else if (runX > 5) + result++; + } else { + finderPenaltyAddHistory(runX, runHistory, qrsize); + if (!runColor) + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + runColor = getModuleBounded(qrcode, x, y); + runX = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runX, runHistory, qrsize) * PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for (int x = 0; x < qrsize; x++) { + bool runColor = false; + int runY = 0; + int runHistory[7] = {0}; + for (int y = 0; y < qrsize; y++) { + if (getModuleBounded(qrcode, x, y) == runColor) { + runY++; + if (runY == 5) + result += PENALTY_N1; + else if (runY > 5) + result++; + } else { + finderPenaltyAddHistory(runY, runHistory, qrsize); + if (!runColor) + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + runColor = getModuleBounded(qrcode, x, y); + runY = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runY, runHistory, qrsize) * PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for (int y = 0; y < qrsize - 1; y++) { + for (int x = 0; x < qrsize - 1; x++) { + bool color = getModuleBounded(qrcode, x, y); + if ( color == getModuleBounded(qrcode, x + 1, y) && + color == getModuleBounded(qrcode, x, y + 1) && + color == getModuleBounded(qrcode, x + 1, y + 1)) + result += PENALTY_N2; + } + } + + // Balance of dark and light modules + int dark = 0; + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModuleBounded(qrcode, x, y)) + dark++; + } + } + int total = qrsize * qrsize; // Note that size is odd, so dark/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% + int k = (int)((labs(dark * 20L - total * 10L) + total - 1) / total) - 1; + assert(0 <= k && k <= 9); + result += k * PENALTY_N4; + assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 + return result; +} + + +// Can only be called immediately after a light run is added, and +// returns either 0, 1, or 2. A helper function for getPenaltyScore(). +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) { + int n = runHistory[1]; + assert(n <= qrsize * 3); (void)qrsize; + bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n; + // The maximum QR Code size is 177, hence the dark run length n <= 177. + // Arithmetic is promoted to int, so n*4 will not overflow. + return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); +} + + +// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). +static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) { + if (currentRunColor) { // Terminate dark run + finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); + currentRunLength = 0; + } + currentRunLength += qrsize; // Add light border to final run + finderPenaltyAddHistory(currentRunLength, runHistory, qrsize); + return finderPenaltyCountPatterns(runHistory, qrsize); +} + + +// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). +static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7], int qrsize) { + if (runHistory[0] == 0) + currentRunLength += qrsize; // Add light border to initial run + memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); + runHistory[0] = currentRunLength; +} + + + +/*---- Basic QR Code information ----*/ + +// Public function - see documentation comment in header file. +int qrcodegen_getSize(const uint8_t qrcode[]) { + assert(qrcode != NULL); + int result = qrcode[0]; + assert((qrcodegen_VERSION_MIN * 4 + 17) <= result + && result <= (qrcodegen_VERSION_MAX * 4 + 17)); + return result; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { + assert(qrcode != NULL); + int qrsize = qrcode[0]; + return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModuleBounded(qrcode, x, y); +} + + +// Returns the color of the module at the given coordinates, which must be in bounds. +testable bool getModuleBounded(const uint8_t qrcode[], int x, int y) { + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + return getBit(qrcode[(index >> 3) + 1], index & 7); +} + + +// Sets the color of the module at the given coordinates, which must be in bounds. +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isDark) { + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + int bitIndex = index & 7; + int byteIndex = (index >> 3) + 1; + if (isDark) + qrcode[byteIndex] |= 1 << bitIndex; + else + qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; +} + + +// Sets the color of the module at the given coordinates, doing nothing if out of bounds. +testable void setModuleUnbounded(uint8_t qrcode[], int x, int y, bool isDark) { + int qrsize = qrcode[0]; + if (0 <= x && x < qrsize && 0 <= y && y < qrsize) + setModuleBounded(qrcode, x, y, isDark); +} + + +// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. +static bool getBit(int x, int i) { + return ((x >> i) & 1) != 0; +} + + + +/*---- Segment handling ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_isNumeric(const char *text) { + assert(text != NULL); + for (; *text != '\0'; text++) { + if (*text < '0' || *text > '9') + return false; + } + return true; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_isAlphanumeric(const char *text) { + assert(text != NULL); + for (; *text != '\0'; text++) { + if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) + return false; + } + return true; +} + + +// Public function - see documentation comment in header file. +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { + int temp = calcSegmentBitLength(mode, numChars); + if (temp == -1) + return SIZE_MAX; + assert(0 <= temp && temp <= INT16_MAX); + return ((size_t)temp + 7) / 8; +} + + +// Returns the number of data bits needed to represent a segment +// containing the given number of characters using the given mode. Notes: +// - Returns -1 on failure, i.e. numChars > INT16_MAX or +// the number of needed bits exceeds INT16_MAX (i.e. 32767). +// - Otherwise, all valid results are in the range [0, INT16_MAX]. +// - For byte mode, numChars measures the number of bytes, not Unicode code points. +// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. +// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { + // All calculations are designed to avoid overflow on all platforms + if (numChars > (unsigned int)INT16_MAX) + return -1; + long result = (long)numChars; + if (mode == qrcodegen_Mode_NUMERIC) + result = (result * 10 + 2) / 3; // ceil(10/3 * n) + else if (mode == qrcodegen_Mode_ALPHANUMERIC) + result = (result * 11 + 1) / 2; // ceil(11/2 * n) + else if (mode == qrcodegen_Mode_BYTE) + result *= 8; + else if (mode == qrcodegen_Mode_KANJI) + result *= 13; + else if (mode == qrcodegen_Mode_ECI && numChars == 0) + result = 3 * 8; + else { // Invalid argument + assert(false); + return -1; + } + assert(result >= 0); + if (result > INT16_MAX) + return -1; + return (int)result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { + assert(data != NULL || len == 0); + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_BYTE; + result.bitLength = calcSegmentBitLength(result.mode, len); + assert(result.bitLength != -1); + result.numChars = (int)len; + if (len > 0) + memcpy(buf, data, len * sizeof(buf[0])); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { + assert(digits != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(digits); + result.mode = qrcodegen_Mode_NUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int)len; + if (bitLen > 0) + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *digits != '\0'; digits++) { + char c = *digits; + assert('0' <= c && c <= '9'); + accumData = accumData * 10 + (unsigned int)(c - '0'); + accumCount++; + if (accumCount == 3) { + appendBitsToBuffer(accumData, 10, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 or 2 digits remaining + appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); + assert(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { + assert(text != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(text); + result.mode = qrcodegen_Mode_ALPHANUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int)len; + if (bitLen > 0) + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *text != '\0'; text++) { + const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); + assert(temp != NULL); + accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); + accumCount++; + if (accumCount == 2) { + appendBitsToBuffer(accumData, 11, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 character remaining + appendBitsToBuffer(accumData, 6, buf, &result.bitLength); + assert(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_ECI; + result.numChars = 0; + result.bitLength = 0; + if (assignVal < 0) + assert(false); + else if (assignVal < (1 << 7)) { + memset(buf, 0, 1 * sizeof(buf[0])); + appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength); + } else if (assignVal < (1 << 14)) { + memset(buf, 0, 2 * sizeof(buf[0])); + appendBitsToBuffer(2, 2, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength); + } else if (assignVal < 1000000L) { + memset(buf, 0, 3 * sizeof(buf[0])); + appendBitsToBuffer(6, 3, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength); + } else + assert(false); + result.data = buf; + return result; +} + + +// Calculates the number of bits needed to encode the given segments at the given version. +// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too +// many characters to fit its length field, or the total bits exceeds INT16_MAX. +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { + assert(segs != NULL || len == 0); + long result = 0; + for (size_t i = 0; i < len; i++) { + int numChars = segs[i].numChars; + int bitLength = segs[i].bitLength; + assert(0 <= numChars && numChars <= INT16_MAX); + assert(0 <= bitLength && bitLength <= INT16_MAX); + int ccbits = numCharCountBits(segs[i].mode, version); + assert(0 <= ccbits && ccbits <= 16); + if (numChars >= (1L << ccbits)) + return -1; // The segment's length doesn't fit the field's bit width + result += 4L + ccbits + bitLength; + if (result > INT16_MAX) + return -1; // The sum might overflow an int type + } + assert(0 <= result && result <= INT16_MAX); + return (int)result; +} + + +// Returns the bit width of the character count field for a segment in the given mode +// in a QR Code at the given version number. The result is in the range [0, 16]. +static int numCharCountBits(enum qrcodegen_Mode mode, int version) { + assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int i = (version + 7) / 17; + switch (mode) { + case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } + case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } + case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } + case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } + case qrcodegen_Mode_ECI : return 0; + default: assert(false); return -1; // Dummy value + } +} diff --git a/vendor/qrcodegen/qrcodegen.h b/vendor/qrcodegen/qrcodegen.h new file mode 100644 index 0000000..6bbc157 --- /dev/null +++ b/vendor/qrcodegen/qrcodegen.h @@ -0,0 +1,385 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * This library creates QR Code symbols, which is a type of two-dimension barcode. + * Invented by Denso Wave and described in the ISO/IEC 18004 standard. + * A QR Code structure is an immutable square grid of dark and light cells. + * The library provides functions to create a QR Code from text or binary data. + * The library covers the QR Code Model 2 specification, supporting all versions (sizes) + * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. + * + * Ways to create a QR Code object: + * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). + * - Low level: Custom-make the list of segments and call + * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). + * (Note that all ways require supplying the desired error correction level and various byte buffers.) + */ + + +/*---- Enum and struct types----*/ + +/* + * The error correction level in a QR Code symbol. + */ +enum qrcodegen_Ecc { + // Must be declared in ascending order of error protection + // so that an internal qrcodegen function works properly + qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords + qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords + qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords +}; + + +/* + * The mask pattern used in a QR Code symbol. + */ +enum qrcodegen_Mask { + // A special value to tell the QR Code encoder to + // automatically select an appropriate mask pattern + qrcodegen_Mask_AUTO = -1, + // The eight actual mask patterns + qrcodegen_Mask_0 = 0, + qrcodegen_Mask_1, + qrcodegen_Mask_2, + qrcodegen_Mask_3, + qrcodegen_Mask_4, + qrcodegen_Mask_5, + qrcodegen_Mask_6, + qrcodegen_Mask_7, +}; + + +/* + * Describes how a segment's data bits are interpreted. + */ +enum qrcodegen_Mode { + qrcodegen_Mode_NUMERIC = 0x1, + qrcodegen_Mode_ALPHANUMERIC = 0x2, + qrcodegen_Mode_BYTE = 0x4, + qrcodegen_Mode_KANJI = 0x8, + qrcodegen_Mode_ECI = 0x7, +}; + + +/* + * A segment of character/binary/control data in a QR Code symbol. + * The mid-level way to create a segment is to take the payload data + * and call a factory function such as qrcodegen_makeNumeric(). + * The low-level way to create a segment is to custom-make the bit buffer + * and initialize a qrcodegen_Segment struct with appropriate values. + * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. + * Any segment longer than this is meaningless for the purpose of generating QR Codes. + * Moreover, the maximum allowed bit length is 32767 because + * the largest QR Code (version 40) has 31329 modules. + */ +struct qrcodegen_Segment { + // The mode indicator of this segment. + enum qrcodegen_Mode mode; + + // The length of this segment's unencoded data. Measured in characters for + // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + // Always zero or positive. Not the same as the data's bit length. + int numChars; + + // The data bits of this segment, packed in bitwise big endian. + // Can be null if the bit length is zero. + uint8_t *data; + + // The number of valid data bits used in the buffer. Requires + // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. + // The character count (numChars) must agree with the mode and the bit buffer length. + int bitLength; +}; + + + +/*---- Macro constants and functions ----*/ + +#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard +#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard + +// Calculates the number of bytes needed to store any QR Code up to and including the given version number, +// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' +// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). +// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. +#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) + +// The worst-case number of bytes needed to store one QR Code, up to and including +// version 40. This value equals 3918, which is just under 4 kilobytes. +// Use this more convenient value to avoid calculating tighter memory bounds for buffers. +#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) + + + +/*---- Functions (high level) to generate QR Codes ----*/ + +/* + * Encodes the given text string to a QR Code, returning true if successful. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * + * The input text must be encoded in UTF-8 and contain no NULs. + * Requires 1 <= minVersion <= maxVersion <= 40. + * + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or + * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). + * + * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion): + * - Before calling the function: + * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow + * reading and writing; hence each array must have a length of at least len. + * - The two ranges must not overlap (aliasing). + * - The initial state of both ranges can be uninitialized + * because the function always writes before reading. + * - After the function returns: + * - Both ranges have no guarantee on which elements are initialized and what values are stored. + * - tempBuffer contains no useful data and should be treated as entirely uninitialized. + * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). + * + * If successful, the resulting QR Code may use numeric, + * alphanumeric, or byte mode to encode the text. + * + * In the most optimistic case, a QR Code at version 40 with low ECC + * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string + * up to 4296 characters, or any digit string up to 7089 characters. + * These numbers represent the hard upper limit of the QR Code standard. + * + * Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/* + * Encodes the given binary data to a QR Code, returning true if successful. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * + * Requires 1 <= minVersion <= maxVersion <= 40. + * + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or + * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). + * + * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion): + * - Before calling the function: + * - The array ranges dataAndTemp[0 : len] and qrcode[0 : len] must allow + * reading and writing; hence each array must have a length of at least len. + * - The two ranges must not overlap (aliasing). + * - The input array range dataAndTemp[0 : dataLen] should normally be + * valid UTF-8 text, but is not required by the QR Code standard. + * - The initial state of dataAndTemp[dataLen : len] and qrcode[0 : len] + * can be uninitialized because the function always writes before reading. + * - After the function returns: + * - Both ranges have no guarantee on which elements are initialized and what values are stored. + * - dataAndTemp contains no useful data and should be treated as entirely uninitialized. + * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). + * + * If successful, the resulting QR Code will use byte mode to encode the data. + * + * In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte + * sequence up to length 2953. This is the hard upper limit of the QR Code standard. + * + * Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/*---- Functions (low level) to generate QR Codes ----*/ + +/* + * Encodes the given segments to a QR Code, returning true if successful. + * If the data is too long to fit in any version at the given ECC level, + * then false is returned. + * + * The smallest possible QR Code version is automatically chosen for + * the output. The ECC level of the result may be higher than the + * ecl argument if it can be done without increasing the version. + * + * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX): + * - Before calling the function: + * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow + * reading and writing; hence each array must have a length of at least len. + * - The two ranges must not overlap (aliasing). + * - The initial state of both ranges can be uninitialized + * because the function always writes before reading. + * - The input array segs can contain segments whose data buffers overlap with tempBuffer. + * - After the function returns: + * - Both ranges have no guarantee on which elements are initialized and what values are stored. + * - tempBuffer contains no useful data and should be treated as entirely uninitialized. + * - Any segment whose data buffer overlaps with tempBuffer[0 : len] + * must be treated as having invalid values in that array. + * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). + * + * Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + * + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + */ +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Encodes the given segments to a QR Code, returning true if successful. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * + * Requires 1 <= minVersion <= maxVersion <= 40. + * + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or + * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). + * + * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX): + * - Before calling the function: + * - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow + * reading and writing; hence each array must have a length of at least len. + * - The two ranges must not overlap (aliasing). + * - The initial state of both ranges can be uninitialized + * because the function always writes before reading. + * - The input array segs can contain segments whose data buffers overlap with tempBuffer. + * - After the function returns: + * - Both ranges have no guarantee on which elements are initialized and what values are stored. + * - tempBuffer contains no useful data and should be treated as entirely uninitialized. + * - Any segment whose data buffer overlaps with tempBuffer[0 : len] + * must be treated as having invalid values in that array. + * - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule(). + * + * Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + * + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + */ +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Tests whether the given string can be encoded as a segment in numeric mode. + * A string is encodable iff each character is in the range 0 to 9. + */ +bool qrcodegen_isNumeric(const char *text); + + +/* + * Tests whether the given string can be encoded as a segment in alphanumeric mode. + * A string is encodable iff each character is in the following set: 0 to 9, A to Z + * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +bool qrcodegen_isAlphanumeric(const char *text); + + +/* + * Returns the number of bytes (uint8_t) needed for the data buffer of a segment + * containing the given number of characters using the given mode. Notes: + * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or the internal + * calculation of the number of needed bits exceeds INT16_MAX (i.e. 32767). + * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. + * - It is okay for the user to allocate more bytes for the buffer than needed. + * - For byte mode, numChars measures the number of bytes, not Unicode code points. + * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. + * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. + */ +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); + + +/* + * Returns a segment representing the given binary data encoded in + * byte mode. All input byte arrays are acceptable. Any text string + * can be converted to UTF-8 bytes and encoded as a byte mode segment. + */ +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); + + +/* + * Returns a segment representing the given string of decimal digits encoded in numeric mode. + */ +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); + + +/* + * Returns a segment representing the given text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); + + +/* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); + + +/*---- Functions to extract raw data from QR Codes ----*/ + +/* + * Returns the side length of the given QR Code, assuming that encoding succeeded. + * The result is in the range [21, 177]. Note that the length of the array buffer + * is related to the side length - every 'uint8_t qrcode[]' must have length at least + * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). + */ +int qrcodegen_getSize(const uint8_t qrcode[]); + + +/* + * Returns the color of the module (pixel) at the given coordinates, which is false + * for light or true for dark. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (light) is returned. + */ +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); + + +#ifdef __cplusplus +} +#endif diff --git a/vendor/roboto/LICENSE b/vendor/roboto/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/roboto/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/roboto/Roboto-Light.ttf b/vendor/roboto/Roboto-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8b1e7e1285d7602ec804a850dd7e089ae6a2703d GIT binary patch literal 350028 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 z zltckIv>T&&6#^3kr%@BlVHIWUtV1v~y6&;D<53Fvk8o`I(P0avRSjKVvsS6mL0ZM5 z1M)e=S~V8a`|~_XG2T$$7}?OBowQbibAsPRQO{`)X$u?*@O99rkK+;nI_PN#_d&oD z6ay@*G}ctANpr-%4LFE2ynz%nHxmJbn{yUkT57 z$oVeui+XN~JfPDZNj;~HmN*UgJk#ah)KByqq8N-=U4RZCLt5mlu(Vu*#rLd*N?PO? zu(SYg$J$2eg#EpR0q5REZQFUzvoD^e{=|InF+t_=8HWo4dt=w+3&RD{7hug?Hl+5_AW5)ZC-N4z3^QPnm?t#U* z&DgL#ES3F?y${1BVSrEN#g`h9A6WR_!>-GsCecU##CdvH_<%2`eQk3D zFR}5DxW4B06b9eNJ>6~mBM4{*k7fR0;~&F_ryV1rALD_RDt^4jFyd(xD1J`a_+O!? ziz$52$0#uIzjDn8PzZ_T!OaesKfah(z|HhsTM{~O%;MF+`L`=8kOKLNkF zjla*v{|WfH2%q%Bw!opVfHoJX$m2d~)lXSycx zku$=d<^9OQhu$59(mL9 zFJANBwXu)kaBO{(dN^yNqJ9kCDQTnPo}^cvMydBJ*Jq-%!UuKIMn(Or38afGOFn}_ z*raPXddsqQ$dq-FO3`=t!2Dgw_AqAWdtQ=lC8`bgFm`0wE&=?QXCUCSO!!MUNe$bA ztGj!0-zoegy$kE;EP2LpY6N|)SK>Y$FOOr5LbEK-03wM_OMp&Sc^C_2>g#q)KgpQN zn=op|_`=5DV>}Uk2_Iv(glCkEzsGpX^&;R3f3=10J&bFR8<_Y#xG$JK`ffoW*~VXG z;~&9^qh^5TVfx)H`rae1NxXZj=+jtc{$VpDk0s)#u4j{te+-8&$yO=+OE&&jt`t$; z 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 Co4rB+ literal 0 HcmV?d00001 diff --git a/vendor/roboto/Roboto-Regular.ttf b/vendor/roboto/Roboto-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..54a284dca14ec4ba84bbb59d0ae11de02af844a0 GIT binary patch literal 349400 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

@bp7L{OFzDD_{8pyqia=N8WymFuXbi?UV~c~ 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

5dZc(`9n(UHgaS)v^xUNT2JtTYNt7)p5b3X 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 literal 0 HcmV?d00001 diff --git a/vendor/stb/stb_truetype.h b/vendor/stb/stb_truetype.h new file mode 100644 index 0000000..90a5c2e --- /dev/null +++ b/vendor/stb/stb_truetype.h @@ -0,0 +1,5079 @@ +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 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 +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) Yakov Galka +// +// VERSION HISTORY +// +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start, last; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = (sy1 - sy0) * e->direction; + STBTT_assert(x >= 0 && x < len); + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, y_final, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; + + sign = e->direction; + + // area of the rectangle covered from sy0..y_crossing + area = sign * (y_crossing-sy0); + + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 + area += step; + } + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); + + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + + // the rest of the line is filled based on the total height of the line segment in this pixel + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + // distance from singular values (in the same units as the pixel grid) + const float eps = 1./1024, eps2 = eps*eps; + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 >= eps2) + precompute[i] = 1.0f / len2; + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear + if (STBTT_fabs(b) >= eps2) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/