Initial commit

This commit is contained in:
Emery Hemingway 2023-03-26 22:37:38 -05:00
commit ad67ab3f84
6 changed files with 151 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.envrc
/.direnv

13
fontconfig_actor.nimble Normal file
View File

@ -0,0 +1,13 @@
# Package
version = "20230326"
author = "Emery Hemingway"
description = "Syndicate actor for asserting Fontconfig information"
license = "Unlicense"
srcDir = "src"
bin = @["fontconfig_actor"]
# Dependencies
requires "nim >= 1.6.10"

3
protocol.prs Normal file
View File

@ -0,0 +1,3 @@
version 1 .
Serve = <serve @cap #!any> .
FontAssertion = <fontconfig @properties {symbol: any ...:...} @file string @index int> .

3
src/Tupfile Normal file
View File

@ -0,0 +1,3 @@
include_rules
: foreach ../*.prs |> !preserves_schema_nim |> {schema}
: fontconfig_actor.nim | {schema} $(SYNDICATE_PROTOCOL) |> !nim_bin |>

112
src/fontconfig_actor.nim Normal file
View File

@ -0,0 +1,112 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, os, osproc, strutils]
import preserves, syndicate, syndicate/[patterns]
import ./protocol
{.passC: staticExec("pkg-config --cflags fontconfig").}
{.passL: staticExec("pkg-config --libs fontconfig").}
{.pragma: fcHeader, header: "<fontconfig/fontconfig.h>".}
{.pragma: importFc, fcHeader, importc: "Fc$1".}
const
FcFalse = cint 0
FC_FAMILY = "family"
FC_STYLE = "style"
FC_WEIGHT = "weight"
FC_SIZE = "size"
FC_FILE = "file"
type
FcChar8* = uint8
FcBool* = cint
FcResult {.importc.} = enum
FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId,
FcResultOutOfMemory
FcPattern = distinct pointer
FcConfig = distinct pointer
proc Init(): FcBool {.importFc.} ## Initialize fontconfig library
proc Fini() {.importFc.} ## Finalize fontconfig library.
proc PatternCreate(): FcPattern {.importFc.}
proc PatternDestroy(p: FcPattern) {.importFc.}
proc PatternAddInteger(p: FcPattern; obj: cstring; i: cint): FcBool {.importFc.}
proc PatternAddDouble(p: FcPattern; obj: cstring; d: cdouble): FcBool {.importFc.}
proc PatternAddString(p: FcPattern; obj, s: cstring): FcBool {.importFc.}
proc DefaultSubstitute(p: FcPattern) {.importFc.}
proc PatternPrint(p: FcPattern) {.importFc.}
proc FontMatch(cfg: FcConfig; p: FcPattern; r: var FcResult): FcPattern {.importFc.}
proc PatternGetString(p: FcPattern; obj: cstring; n: cint;
s: ptr cstring): FcResult {.importFc.}
proc findSystemTypeface*(family = ""; style = ""; weight = 0; size = 0.0): string =
## Find a path to an appropriate system typeface for the given parameters.
## This proc always returns a path to a typeface file, results may vary.
# TODO: only return font in supported formats
if Init() == FcFalse:
raise newException(IOError, "Failed to initialize FontConfig")
var pat = PatternCreate()
DefaultSubstitute(pat)
if family != "":
discard PatternAddString(pat, FC_FAMILY, family);
if style != "":
discard PatternAddString(pat, FC_STYLE, style);
if weight != 0:
discard PatternAddInteger(pat, FC_WEIGHT, cint weight);
if size != 0.0:
discard PatternAddDouble(pat, FC_SIZE, size);
var
res = FcResultNoMatch
font = FontMatch(nil, pat, res)
if res == FcResultMatch:
# PatternPrint(font);
var path: cstring
if PatternGetString(font, FC_FILE, 0, addr path) == FcResultMatch:
result = $path
PatternDestroy(font)
PatternDestroy(pat)
Fini()
if result == "":
raise newException(IOError, "Failed to find a system typeface")
proc serve(ds: Ref; turn: var Turn) =
let observation = ?Observe(pattern: !FontAssertion) ?? {0: grabDict()}
during(turn, ds, observation) do (properties: Assertion):
stderr.writeLine "looking for ", properties
#[
let propPat = { toSymbol("family", Ref) : ?"Foo" }.dictionaryPattern
let testPat = FontAssertion ? { 0: propPat, 1: grab(), 2: grab() }
onPublish(turn, ds, testPat) do (file: string, index: int):
stderr.writeLine "found file ", file, " with index ", index
during(turn, ds, Observe ? { 0: grab() }) do (pat: Assertion):
stderr.writeLine "observed request for ", pat
during(turn, ds, Observe ? { 0: ?(FontAssertion ? { 0: drop()}) }) do:
stderr.writeLine "fontconfig observe found! "
]#
bootDataspace("main") do (root: Ref; turn: var Turn):
connectStdio(root, turn)
if Init() == FcFalse:
quit"Failed to initialize FontConfig"
during(turn, root, ?Serve) do (ds: Ref):
serve(ds, turn)
runForever()

18
src/protocol.nim Normal file
View File

@ -0,0 +1,18 @@
import
std/typetraits, preserves, std/tables
type
Serve* {.preservesRecord: "serve".} = object
`cap`* {.preservesEmbedded.}: Preserve[void]
FontAssertion* {.preservesRecord: "fontconfig".} = object
`properties`*: Table[Symbol, Preserve[void]]
`file`*: string
`index`*: BiggestInt
proc `$`*(x: Serve | FontAssertion): string =
`$`(toPreserve(x))
proc encode*(x: Serve | FontAssertion): seq[byte] =
encode(toPreserve(x))