From d65377fe035e7bf6cde5942fae4033826ff3c6ae Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Wed, 29 Mar 2023 22:37:14 -0500 Subject: [PATCH] Resolve symbols in pattern values to Fontconfig constants --- README.md | 8 ++++---- src/fontconfig_actor.nim | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index dd91750..018a064 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ The actor responds to observations of font properties by asserting what it deter The assertion format is `` (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: ``` > @@ -24,8 +24,8 @@ let ?fontspace = dataspace ] $fontspace [ - ? [ - $log ! }> + ? [ + $log ! }> ] ] ``` diff --git a/src/fontconfig_actor.nim b/src/fontconfig_actor.nim index b9dca40..a89eca9 100644 --- a/src/fontconfig_actor.nim +++ b/src/fontconfig_actor.nim @@ -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()