Resolve symbols in pattern values to Fontconfig constants

This commit is contained in:
Emery Hemingway 2023-03-29 22:37:14 -05:00
parent 2cce84eb49
commit d65377fe03
2 changed files with 21 additions and 8 deletions

View File

@ -6,13 +6,13 @@ The actor responds to observations of font properties by asserting what it deter
The assertion format is `<fontconfig {pattern…} {attributes…}>` (see [protocol.prs](./protocol.prs)). The `pattern` field is a dictionary of properties to match fonts against and the `attributes` field is a dictionary of the properties of a font selected by Fontconfig. An application observes a `pattern` and takes the `file` and `index` fields of a corresponding assertion and reads font data from the file-system. In the case that `pattern` does not match any fonts an assertion will still be made, so it is possible that all of the properties in `pattern` will be contradicted in `attributes`.
For a list of possibly supported properties see the [Fontconfig documentation](https://www.freedesktop.org/software/fontconfig/fontconfig-devel/x19.html).
For a list of possibly supported properties see the [Fontconfig documentation](https://www.freedesktop.org/software/fontconfig/fontconfig-devel/x19.html). When the value of a property is a Preserves symbol (rather than a string in double-quotes) it will be resolved to a Fontconfig constant if possible. Constants are not resolved from integers to symbols in the `attributes` field. For example, `{slant: oblique}` is transformed to `{slant: 110}` from `pattern` to `attributes`.
Example [Syndicate server](https://git.syndicate-lang.org/syndicate-lang/syndicate-rs) configuration:
```
<require-service <daemon fontconfig_actor>>
<daemon fontconfig_actor {
argv: [ "/home/emery/src/bin/fontconfig_actor" ]
argv: [ "/usr/local/bin/fontconfig_actor" ]
protocol: application/syndicate
}>
@ -24,8 +24,8 @@ let ?fontspace = dataspace
]
$fontspace [
? <fontconfig {family: "Gentium Book Plus"} ?attributes> [
$log ! <log "-" { line: <fontconfig $attributes> }>
? <fontconfig {size: 8.0, spacing: proportional} ?properties> [
$log ! <log "-" { line: <fontconfig $properties> }>
]
]
```

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, options, os, strutils, tables]
import std/[asyncdispatch, options, os, tables]
import preserves, syndicate, syndicate/[patterns]
import ./protocol
@ -47,6 +47,9 @@ type
FcConfig = distinct pointer
FcConstant {.importc.} = ptr object
value: cint
const
(FcFalse, FcTrue) = (cint 0, cint 1)
@ -61,7 +64,7 @@ proc PatternAddDouble(p: FcPattern; obj: cstring; d: cdouble): FcBool {.importFc
proc PatternAddString(p: FcPattern; obj: cstring; s: cstring): FcBool {.importFc.}
proc PatternAddBool(p: FcPattern; obj: cstring; b: bool): FcBool {.importFc.}
proc DefaultSubstitute(p: FcPattern) {.importFc.}
proc PatternPrint(p: FcPattern) {.importFc.}
# proc PatternPrint(p: FcPattern) {.importFc.}
proc FontMatch(cfg: FcConfig; p: FcPattern; r: var FcResult): FcPattern {.importFc.}
@ -72,6 +75,10 @@ proc PatternIterIsValid(p: FcPattern; iter: ptr FcPatternIter): FcBool {.importF
proc PatternIterGetObject(p: FcPattern; iter: ptr FcPatternIter): cstring {.importFc.}
proc PatternIterGetValue(p: FcPattern; iter: ptr FcPatternIter; id: cint; v: ptr FcValue; b: pointer): FcResult {.importFc.}
# proc NameGetConstantFor(str: ptr FcChar8; obj: cstring): FcConstant {.importFc.}
proc NameGetConstant(str: cstring): FcConstant {.importFc,
deprecated: "update to Fontconfig 2.14.2 API and use NameGetConstantFor".}
proc getValue(pat: FcPattern; iter: ptr FcPatternIter; i: cint): Option[Preserve[void]] =
var fcVal: FcValue
if PatternIterGetValue(pat, iter, i, addr fcVal, nil) == FcResultMatch:
@ -118,17 +125,23 @@ proc fillPattern(properties: Properties): FcPattern =
of pkSignedInteger: PatternAddInteger(result, key, cint val.int)
of pkString:
PatternAddString(result, key, val.string)
of pkSymbol:
let constant = NameGetConstant(val.symbol.cstring)
if not constant.isNil: PatternAddInteger(result, key, constant.value)
else:
logError("invalid constant: ", val)
FcFalse
else:
logError("invalid property: ", val)
FcFalse
if recognized == FcFalse:
logError("unrecognized property: ", key.escape)
logError("unrecognized property {", key, ": ", val, "}")
DefaultSubstitute(result)
template withFontconfig(body: untyped): untyped =
## Initialize and deinitialize the Fontconfig library for the scope of `body`.
if Init() == FcFalse:
quit"Failed to initialize FontConfig"
logError "Failed to initialize FontConfig"
else:
body
Fini()