#!/usr/bin/env dub
/+ dub.sdl:
name "font_libraries_ligature_cells"
targetPath "build"
libs "harfbuzz"
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
+/
/**
* Do programming-font ligatures fit a cell grid? Shapes 160 ligature
* sequences, the union of the Fira Code, JetBrains Mono, Cascadia Code and
* Maple Mono inventories, each as `a<seq>b`, with `calt`+`liga` on and off,
* and reports per face:
*
* 1. how many sequences shape differently with the features on;
* 2. how many change the glyph count — a ligature that merges characters
* into fewer glyphs would need multi-cell glyph placement in a terminal;
* 3. how many produce an advance other than the cell (the advance of `0`);
* 4. how many draw ink outside a glyph's own cell, and the worst reach in
* cells — a renderer that clips each glyph to its cell cuts these.
*
* Spike S3 of docs/specs/font/PLAN.md; decision FTX7 in
* docs/specs/font/decisions.md records the result.
*
* Run with: dub run --single ligature-cells.d [-- font.ttf ...]
*
* Font resolution: the arguments if given, else `fc-match -f %{file}
* monospace`. If neither yields a readable file, prints a `SKIP:` line and
* exits 0 so CI stays green.
*/
module (module) font_libraries_ligature_cellsDo programming-font ligatures fit a cell grid? Shapes 160 ligature
sequences, the union of the Fira Code, JetBrains Mono, Cascadia Code and
Maple Mono inventories, each as a<seq>b, with calt+liga on and off,
and reports per face:
how many sequences shape differently with the features on;
how many change the glyph count — a ligature that merges characters
into fewer glyphs would need multi-cell glyph placement in a terminal;
how many produce an advance other than the cell (the advance of 0);
how many draw ink outside a glyph's own cell, and the worst reach in
cells — a renderer that clips each glyph to its cell cuts these.
Spike S3 of docs/specs/font/PLAN.md; decision FTX7 in
docs/specs/font/decisions.md records the result.
Run with: dub run --single ligature-cells.d [-- font.ttf ...]
Font resolution: the arguments if given, else fc-match -f %{file}
monospace. If neither yields a readable file, prints a SKIP: line and
exits 0 so CI stays green.
font_libraries_ligature_cells;
import (package) stdstd.(module) std.algorithmThis package implements generic algorithms oriented towards the processing of
sequences. Sequences processed by these functions define range-based
interfaces. See also Reference on ranges and
tutorial on ranges.
Algorithms are categorized into the following submodules:
Submodule Functions
| Searching |
all
any
balancedParens
boyerMooreFinder
canFind
commonPrefix
count
countUntil
endsWith
find
findAdjacent
findAmong
findSkip
findSplit
findSplitAfter
findSplitBefore
minCount
maxCount
minElement
maxElement
minIndex
maxIndex
minPos
maxPos
skipOver
startsWith
until
|
| Comparison |
among
castSwitch
clamp
cmp
either
equal
isPermutation
isSameLength
levenshteinDistance
levenshteinDistanceAndPath
max
min
mismatch
predSwitch
|
| Iteration |
cache
cacheBidirectional
chunkBy
cumulativeFold
each
filter
filterBidirectional
fold
group
joiner
map
mean
permutations
reduce
splitWhen
splitter
substitute
sum
uniq
|
| Sorting |
completeSort
isPartitioned
isSorted
isStrictlyMonotonic
ordered
strictlyOrdered
makeIndex
merge
multiSort
nextEvenPermutation
nextPermutation
nthPermutation
partialSort
partition
partition3
schwartzSort
sort
topN
topNCopy
topNIndex
|
| Set operations (setops) |
cartesianProduct
largestPartialIntersection
largestPartialIntersectionWeighted
multiwayMerge
multiwayUnion
setDifference
setIntersection
setSymmetricDifference
|
| Mutation |
bringToFront
copy
fill
initializeAll
move
moveAll
moveSome
moveEmplace
moveEmplaceAll
moveEmplaceSome
remove
reverse
strip
stripLeft
stripRight
swap
swapRanges
uninitializedFill
|
Many functions in this package are parameterized with a predicate.
The predicate may be any suitable callable type
(a function, a delegate, a functor, or a lambda), or a
compile-time string. The string may consist of any legal D
expression that uses the symbol a (for unary functions) or the
symbols a and b (for binary functions). These names will NOT
interfere with other homonym symbols in user code because they are
evaluated in a different context. The default for all binary
comparison predicates is "a == b" for unordered operations and
"a < b" for ordered operations.
Example
int[] a = ...;
static bool greater(int a, int b)
{
return a > b;
}
sort!greater(a); // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a); // predicate as string
// (no ambiguity with array name)
sort(a); // no predicate, "a < b" is implicit
Source
std/algorithm/package.d
algorithm : (alias template) font_libraries_ligature_cells.equal = std.algorithm.comparison.equal(alias pred = "a == b")Compares two or more ranges for equality, as defined by predicate pred
(which is == by default).
equal, (alias template) font_libraries_ligature_cells.filter = std.algorithm.iteration.filter(alias predicate) if (is(typeof(unaryFun!predicate)))``filter!(predicate)(range) returns a new range containing only elements x in range for
which predicate(x) returns true.
The predicate is passed to unaryFun, and can be either a string, or
any callable that can be executed via pred(element).
filter, (alias template) font_libraries_ligature_cells.map = std.algorithm.iteration.map(fun...) if (fun.length >= 1)Implements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
map, (alias template) font_libraries_ligature_cells.max = std.algorithm.comparison.max(T...)(T args) if (T.length >= 2 && !is(CommonType!T == void))Iterates the passed arguments and returns the maximum value.
max;
import (package) stdstd.(module) std.arrayFunctions and types that manipulate built-in arrays and associative arrays.
This module provides all kinds of functions to create, manipulate or convert arrays:
Function Name Description
| array |
Returns a copy of the input in a newly allocated dynamic array.
|
| appender |
Returns a new Appender or RefAppender initialized with a given array.
|
| assocArray |
Returns a newly allocated associative array from a range/ranges of keys and values.
|
| byPair |
Construct a range iterating over an associative array by key/value tuples.
|
| insertInPlace |
Inserts into an existing array at a given position.
|
| join |
Concatenates a range of ranges into one array.
|
| minimallyInitializedArray |
Returns a new array of type T.
|
| replace |
Returns a new array with all occurrences of a certain subrange replaced.
|
| replaceFirst |
Returns a new array with the first occurrence of a certain subrange replaced.
|
| replaceInPlace |
Replaces all occurrences of a certain subrange and puts the result into a given array.
|
| replaceInto |
Replaces all occurrences of a certain subrange and puts the result into an output range.
|
| replaceLast |
Returns a new array with the last occurrence of a certain subrange replaced.
|
| replaceSlice |
Returns a new array with a given slice replaced.
|
| replicate |
Creates a new array out of several copies of an input array or range.
|
| sameHead |
Checks if the initial segments of two arrays refer to the same
place in memory.
|
| sameTail |
Checks if the final segments of two arrays refer to the same place
in memory.
|
| split |
Eagerly split a range or string into an array.
|
| staticArray |
Creates a new static array from given data.
|
| uninitializedArray |
Returns a new array of type T without initializing its elements.
|
Source
std/array.d
array : (alias template) font_libraries_ligature_cells.array = std.array.array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)Allocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array;
import (package) stdstd.(module) std.fileUtilities for manipulating files and scanning directories. Functions
in this module handle files as a unit, e.g., read or write one file
at a time. For opening files and manipulating them via handles refer
to module std.stdio.
Category Functions General exists isDir isFile isSymlink rename thisExePath Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir Files append copy read readText remove slurp write Symlinks symlink readLink Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace
Source
std/file.d
file : (alias template) font_libraries_ligature_cells.exists = std.file.exists(R)(R name) if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)Determine whether the given file (or directory) exists.
exists;
import (package) stdstd.(module) std.pathThis module is used to manipulate path strings.
All functions, with the exception of expandTilde (and in some
cases absolutePath and relativePath), are pure
string manipulation functions; they don't depend on any state outside
the program, nor do they perform any actual file system actions.
This has the consequence that the module does not make any distinction
between a path that points to a directory and a path that points to a
file, and it does not know whether or not the object pointed to by the
path actually exists in the file system.
To differentiate between these cases, use isDir and
exists.
Note that on Windows, both the backslash (\) and the slash (/)
are in principle valid directory separators. This module treats them
both on equal footing, but in cases where a new separator is
added, a backslash will be used. Furthermore, the buildNormalizedPath
function will replace all slashes with backslashes on that platform.
In general, the functions in this module assume that the input paths
are well-formed. (That is, they should not contain invalid characters,
they should follow the file system's path format, etc.) The result
of calling a function on an ill-formed path is undefined. When there
is a chance that a path or a file name is invalid (for instance, when it
has been input by the user), it may sometimes be desirable to use the
isValidFilename and isValidPath functions to check
this.
Most functions do not perform any memory allocations, and if a string is
returned, it is usually a slice of an input string. If a function
allocates, this is explicitly mentioned in the documentation.
Category Functions Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension Other filenameCharCmp filenameCmp globMatch CaseSensitive
Source
std/path.d
path : (alias template) font_libraries_ligature_cells.baseName = std.path.baseName(R)(return scope R path) if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) && !isSomeString!R)Note
This function only strips away the specified suffix, which
doesn't necessarily have to represent an extension.
To remove the extension from a path, regardless of what the extension
is, use stripExtension.
To obtain the filename without leading directories and without
an extension, combine the functions like this:
assert(baseName(stripExtension("dir/file.ext")) == "file");
baseName;
import (package) stdstd.(module) std.processFunctions for starting and interacting with other processes, and for
working with the current process' execution environment.
Process handling
`spawnProcess` spawns a new `process`, optionally assigning it an
arbitrary set of standard input, output, and error streams.
The function returns immediately, leaving the child process to execute
in parallel with its parent. All other functions in this module that
spawn processes are built around spawnProcess.
`wait` makes the parent `process` wait for a child `process` to
terminate. In general one should always do this, to avoid
child processes becoming "zombies" when the parent process exits.
Scope guards are perfect for this – see the spawnProcess
documentation for examples. tryWait is similar to wait,
but does not block if the process has not yet terminated.
`pipeProcess` also spawns a child `process` which runs
in parallel with its parent. However, instead of taking
arbitrary streams, it automatically creates a set of
pipes that allow the parent to communicate with the child
through the child's standard input, output, and/or error streams.
This function corresponds roughly to C's popen function.
`execute` starts a new `process` and waits for it
to complete before returning. Additionally, it captures
the process' standard output and error streams and returns
the output of these as a string.
`spawnShell`, `pipeShell` and `executeShell` work like
spawnProcess, pipeProcess and execute, respectively,
except that they take a single command string and run it through
the current user's default command interpreter.
executeShell corresponds roughly to C's system function.
`kill` attempts to terminate a running `process`.
The following table compactly summarises the different process creation
functions and how they relate to each other:
Runs program directly
Runs shell command Low-level process creation spawnProcess spawnShell Automatic input/output redirection using pipes pipeProcess pipeShell Execute and wait for completion, collect output execute executeShell
Other functionality
`pipe` is used to create unidirectional pipes.
`environment` is an interface through which the current `process`'
environment variables can be read and manipulated.
`escapeShellCommand` and `escapeShellFileName` are useful
for constructing shell command lines in a portable way.
Source
std/process.d
Note
Most of the functionality in this module is not available on iOS, tvOS
and watchOS. The only functions available on those platforms are:
environment, thisProcessID and thisThreadID.
process : (alias) font_libraries_ligature_cells.execute = std.typecons.Tuple!(int, "status", string, "output") std.process.execute(scope const(char[])[] args, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null) @safeExecutes the given program or shell command and returns its exit
code and output.
execute and executeShell start a new process using
spawnProcess and spawnShell, respectively, and wait
for the process to complete before returning. The functions capture
what the child process prints to both its standard output and
standard error streams, and return this together with its exit code.
auto dmd = execute(["dmd", "myapp.d"]);
if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
auto ls = executeShell("ls -l");
if (ls.status != 0) writeln("Failed to retrieve file listing");
else writeln(ls.output);
The args/program/command, env and config
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.
POSIX specific
If the process is terminated by a signal, the status field of
the return value will contain a negative number whose absolute
value is the signal number. (See wait for details.)
execute;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) font_libraries_ligature_cells.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to writef(fmt, args, '\n').
writefln, (alias template) font_libraries_ligature_cells.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) font_libraries_ligature_cells.strip = std.string.strip(Range)(Range str) if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range))Strips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
strip, (alias) font_libraries_ligature_cells.toStringz = immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trustedtoStringz;
import (package) stdstd.(module) std.utfEncode and decode UTF-8, UTF-16 and UTF-32 strings.
UTF character support is restricted to
'\u0000' <= character <= '\U0010FFFF'.
Category Functions Decode decode decodeFront Lazy decode byCodeUnit byChar byWchar byDchar byUTF Encode encode toUTF8 toUTF16 toUTF32 toUTFz toUTF16z Length codeLength count stride strideBack Index toUCSindex toUTFindex Validation isValidDchar isValidCodepoint validate Miscellaneous replacementDchar UseReplacementDchar UTFException
Source
std/utf.d
utf : (alias template) font_libraries_ligature_cells.count = std.utf.count(C)(const(C)[] str) if (isSomeChar!C)Returns the total number of code points encoded in str.
Supercedes
This function supercedes toUCSindex.
count;
// ---------------------------------------------------------------------------
// HarfBuzz C ABI, the subset this program needs. Layouts follow hb-common.h,
// hb-buffer.h and hb-font.h: every field is a 32-bit scalar.
// ---------------------------------------------------------------------------
extern (C) nothrow @nogc
{
struct (struct) font_libraries_ligature_cells.hb_blob_thb_blob_t;
struct (struct) font_libraries_ligature_cells.hb_face_thb_face_t;
struct (struct) font_libraries_ligature_cells.hb_font_thb_font_t;
struct (struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t;
alias (alias) font_libraries_ligature_cells.hb_codepoint_t = uinthb_codepoint_t = uint;
alias (alias) font_libraries_ligature_cells.hb_position_t = inthb_position_t = int;
alias (alias) font_libraries_ligature_cells.hb_tag_t = uinthb_tag_t = uint;
alias (alias) font_libraries_ligature_cells.hb_bool_t = inthb_bool_t = int;
struct (struct) font_libraries_ligature_cells.hb_glyph_info_thb_glyph_info_t
{
(alias) font_libraries_ligature_cells.hb_codepoint_t = uinthb_codepoint_t (field) uint font_libraries_ligature_cells.hb_glyph_info_t.codepointcodepoint; // glyph id after shaping
uint (field) uint font_libraries_ligature_cells.hb_glyph_info_t.maskmask;
uint (field) uint font_libraries_ligature_cells.hb_glyph_info_t.clustercluster;
uint (field) uint font_libraries_ligature_cells.hb_glyph_info_t.var1var1, (field) uint font_libraries_ligature_cells.hb_glyph_info_t.var2var2; // private
}
struct (struct) font_libraries_ligature_cells.hb_glyph_position_thb_glyph_position_t
{
(alias) font_libraries_ligature_cells.hb_position_t = inthb_position_t (field) int font_libraries_ligature_cells.hb_glyph_position_t.x_advancex_advance, (field) int font_libraries_ligature_cells.hb_glyph_position_t.y_advancey_advance, (field) int font_libraries_ligature_cells.hb_glyph_position_t.x_offsetx_offset, (field) int font_libraries_ligature_cells.hb_glyph_position_t.y_offsety_offset;
uint (field) uint font_libraries_ligature_cells.hb_glyph_position_t.varvar; // private
}
struct (struct) font_libraries_ligature_cells.hb_feature_thb_feature_t
{
(alias) font_libraries_ligature_cells.hb_tag_t = uinthb_tag_t (field) uint font_libraries_ligature_cells.hb_feature_t.tagtag;
uint (field) uint font_libraries_ligature_cells.hb_feature_t.valuevalue;
uint (field) uint font_libraries_ligature_cells.hb_feature_t.startstart, (field) uint font_libraries_ligature_cells.hb_feature_t.endend;
}
struct (struct) font_libraries_ligature_cells.hb_glyph_extents_thb_glyph_extents_t
{
(alias) font_libraries_ligature_cells.hb_position_t = inthb_position_t (field) int font_libraries_ligature_cells.hb_glyph_extents_t.x_bearingx_bearing, (field) int font_libraries_ligature_cells.hb_glyph_extents_t.y_bearingy_bearing, (field) int font_libraries_ligature_cells.hb_glyph_extents_t.widthwidth, (field) int font_libraries_ligature_cells.hb_glyph_extents_t.heightheight;
}
(struct) font_libraries_ligature_cells.hb_blob_thb_blob_t* font_libraries_ligature_cells.hb_blob_t* font_libraries_ligature_cells.hb_blob_create_from_file(const(char)* file_name) nothrow @nogchb_blob_create_from_file(const(char)* (parameter) const(char)* file_namefile_name);
void void font_libraries_ligature_cells.hb_blob_destroy(font_libraries_ligature_cells.hb_blob_t*) nothrow @nogchb_blob_destroy((struct) font_libraries_ligature_cells.hb_blob_thb_blob_t*);
uint uint font_libraries_ligature_cells.hb_blob_get_length(font_libraries_ligature_cells.hb_blob_t*) nothrow @nogchb_blob_get_length((struct) font_libraries_ligature_cells.hb_blob_thb_blob_t*);
(struct) font_libraries_ligature_cells.hb_face_thb_face_t* font_libraries_ligature_cells.hb_face_t* font_libraries_ligature_cells.hb_face_create(font_libraries_ligature_cells.hb_blob_t*, uint index) nothrow @nogchb_face_create((struct) font_libraries_ligature_cells.hb_blob_thb_blob_t*, uint (parameter) uint indexindex);
void void font_libraries_ligature_cells.hb_face_destroy(font_libraries_ligature_cells.hb_face_t*) nothrow @nogchb_face_destroy((struct) font_libraries_ligature_cells.hb_face_thb_face_t*);
uint uint font_libraries_ligature_cells.hb_face_get_upem(const(font_libraries_ligature_cells.hb_face_t)*) nothrow @nogchb_face_get_upem(const((struct) font_libraries_ligature_cells.hb_face_thb_face_t)*);
(struct) font_libraries_ligature_cells.hb_font_thb_font_t* font_libraries_ligature_cells.hb_font_t* font_libraries_ligature_cells.hb_font_create(font_libraries_ligature_cells.hb_face_t*) nothrow @nogchb_font_create((struct) font_libraries_ligature_cells.hb_face_thb_face_t*);
void void font_libraries_ligature_cells.hb_font_destroy(font_libraries_ligature_cells.hb_font_t*) nothrow @nogchb_font_destroy((struct) font_libraries_ligature_cells.hb_font_thb_font_t*);
void void font_libraries_ligature_cells.hb_ot_font_set_funcs(font_libraries_ligature_cells.hb_font_t*) nothrow @nogchb_ot_font_set_funcs((struct) font_libraries_ligature_cells.hb_font_thb_font_t*);
void void font_libraries_ligature_cells.hb_font_set_scale(font_libraries_ligature_cells.hb_font_t*, int x_scale, int y_scale) nothrow @nogchb_font_set_scale((struct) font_libraries_ligature_cells.hb_font_thb_font_t*, int (parameter) int x_scalex_scale, int (parameter) int y_scaley_scale);
(alias) font_libraries_ligature_cells.hb_bool_t = inthb_bool_t int font_libraries_ligature_cells.hb_font_get_glyph_extents(font_libraries_ligature_cells.hb_font_t*, uint glyph, font_libraries_ligature_cells.hb_glyph_extents_t* extents) nothrow @nogchb_font_get_glyph_extents((struct) font_libraries_ligature_cells.hb_font_thb_font_t*, (alias) font_libraries_ligature_cells.hb_codepoint_t = uinthb_codepoint_t (parameter) uint glyphglyph, (struct) font_libraries_ligature_cells.hb_glyph_extents_thb_glyph_extents_t* (parameter) font_libraries_ligature_cells.hb_glyph_extents_t* extentsextents);
(struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t* font_libraries_ligature_cells.hb_buffer_t* font_libraries_ligature_cells.hb_buffer_create() nothrow @nogchb_buffer_create();
void void font_libraries_ligature_cells.hb_buffer_destroy(font_libraries_ligature_cells.hb_buffer_t*) nothrow @nogchb_buffer_destroy((struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*);
void void font_libraries_ligature_cells.hb_buffer_add_utf8(font_libraries_ligature_cells.hb_buffer_t*, const(char)* text, int text_length, uint item_offset, int item_length) nothrow @nogchb_buffer_add_utf8((struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*, const(char)* (parameter) const(char)* texttext, int (parameter) int text_lengthtext_length,
uint (parameter) uint item_offsetitem_offset, int (parameter) int item_lengthitem_length);
void void font_libraries_ligature_cells.hb_buffer_guess_segment_properties(font_libraries_ligature_cells.hb_buffer_t*) nothrow @nogchb_buffer_guess_segment_properties((struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*);
(struct) font_libraries_ligature_cells.hb_glyph_info_thb_glyph_info_t* font_libraries_ligature_cells.hb_glyph_info_t* font_libraries_ligature_cells.hb_buffer_get_glyph_infos(font_libraries_ligature_cells.hb_buffer_t*, uint* length) nothrow @nogchb_buffer_get_glyph_infos((struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*, uint* (parameter) uint* lengthlength);
(struct) font_libraries_ligature_cells.hb_glyph_position_thb_glyph_position_t* font_libraries_ligature_cells.hb_glyph_position_t* font_libraries_ligature_cells.hb_buffer_get_glyph_positions(font_libraries_ligature_cells.hb_buffer_t*, uint* length) nothrow @nogchb_buffer_get_glyph_positions((struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*, uint* (parameter) uint* lengthlength);
void void font_libraries_ligature_cells.hb_shape(font_libraries_ligature_cells.hb_font_t*, font_libraries_ligature_cells.hb_buffer_t*, const(font_libraries_ligature_cells.hb_feature_t)* features, uint num_features) nothrow @nogchb_shape((struct) font_libraries_ligature_cells.hb_font_thb_font_t*, (struct) font_libraries_ligature_cells.hb_buffer_thb_buffer_t*, const((struct) font_libraries_ligature_cells.hb_feature_thb_feature_t)* (parameter) const(font_libraries_ligature_cells.hb_feature_t)* featuresfeatures, uint (parameter) uint num_featuresnum_features);
} // extern (C)
/// `HB_TAG('c','a','l','t')` as a D function: big-endian packed ASCII.
(alias) font_libraries_ligature_cells.hb_tag_t = uinthb_tag_t uint font_libraries_ligature_cells.tag(string s) pure nothrow @nogc @safeHB_TAG('c','a','l','t') as a D function: big-endian packed ASCII.
tag((alias) object.string = stringstring (parameter) string ss) @safe pure nothrow @nogc
in ((parameter) string ss.(field) ulong string.lengthlength == 4)
=> (uint((parameter) string ss[0]) << 24) | (uint((parameter) string ss[1]) << 16) | (uint((parameter) string ss[2]) << 8) | uint((parameter) string ss[3]);
/// The union of four fonts' ligature inventories, plus Latin `liga` pairs.
immutable (alias) object.string = stringstring[] (immutable global) immutable(string[]) font_libraries_ligature_cells.corpusThe union of four fonts' ligature inventories, plus Latin liga pairs.
corpus = [
"->", "-->", "<-", "<--", "<->", "=>", "==>", "<=", ">=", "<=>", "<==>",
"!=", "!==", "==", "===", "=/=", "/=", "&&", "||", "|||", "::", ":::",
":=", "::=", "=:", "?:", "?.", "??", "?=", "!!", "..", "...", "..<", "..=",
".=", ".-", ".?", "++", "+++", "--", "---", "**", "***", "//", "///", "/*",
"*/", "/**", "<!--", "<!---", "|>", "<|", "<|>", "||>", "<||", "|=", "|-",
"-|", "~>", "<~", "~~", "~~>", "~-", "-~", "~@", "<<", "<<<", ">>", ">>>",
"<<=", ">>=", ">>-", "-<<", "<*", "*>", "<*>", "<$", "$>", "<$>", "<+",
"+>", "<+>", "</", "/>", "</>", "#{", "#[", "#(", "#?", "#!", "#_", "#_(",
"#:", "#=", "##", "###", "####", "]#", "{|", "|}", "[|", "|]", "%%", "^=",
"=<<", ">=>", "<=<", "=!=", "<<-", "->>", "=>>", "<<~", "~~~", ";;", ";;;",
"__", "___", "0x", "0xFF", "1x2", "www", "ff", "fi", "fl", "ffi", "ffl",
"Fl", "Tl", "Il", `\\`, `\n`, "[INFO]", "[ERROR]", "[TODO]", "todo))",
"fixme))", ">-", "-<", "<:", ":>", "<:<", ">:", ":<", "=~", "!~", "|||>",
"<|||", "<!", "!>", "&=", "%=", "$(", "@_", "_|_", "-->>", "=>=", "<===",
"===>", "<-<", ">->",
];
struct (struct) font_libraries_ligature_cells.ShapedShaped
{
(struct) font_libraries_ligature_cells.hb_glyph_info_thb_glyph_info_t[] (field) font_libraries_ligature_cells.hb_glyph_info_t[] font_libraries_ligature_cells.Shaped.infosinfos;
(struct) font_libraries_ligature_cells.hb_glyph_position_thb_glyph_position_t[] (field) font_libraries_ligature_cells.hb_glyph_position_t[] font_libraries_ligature_cells.Shaped.positionspositions;
}
(struct) font_libraries_ligature_cells.ShapedShaped font_libraries_ligature_cells.Shaped font_libraries_ligature_cells.shape(font_libraries_ligature_cells.hb_font_t* font, string text, const(font_libraries_ligature_cells.hb_feature_t)[] features) @trustedshape((struct) font_libraries_ligature_cells.hb_font_thb_font_t* (parameter) font_libraries_ligature_cells.hb_font_t* fontfont, (alias) object.string = stringstring (parameter) string texttext, const((struct) font_libraries_ligature_cells.hb_feature_thb_feature_t)[] (parameter) const(font_libraries_ligature_cells.hb_feature_t)[] featuresfeatures) @trusted
{
auto (local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf = font_libraries_ligature_cells.hb_buffer_t* font_libraries_ligature_cells.hb_buffer_create() nothrow @nogchb_buffer_create();
scope (exit) void font_libraries_ligature_cells.hb_buffer_destroy(font_libraries_ligature_cells.hb_buffer_t*) nothrow @nogchb_buffer_destroy((local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf);
void font_libraries_ligature_cells.hb_buffer_add_utf8(font_libraries_ligature_cells.hb_buffer_t*, const(char)* text, int text_length, uint item_offset, int item_length) nothrow @nogchb_buffer_add_utf8((local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf, (parameter) string texttext.(field) immutable(char)* string.ptrptr, cast(int) (parameter) string texttext.(field) ulong string.lengthlength, 0, cast(int) (parameter) string texttext.(field) ulong string.lengthlength);
void font_libraries_ligature_cells.hb_buffer_guess_segment_properties(font_libraries_ligature_cells.hb_buffer_t*) nothrow @nogchb_buffer_guess_segment_properties((local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf);
void font_libraries_ligature_cells.hb_shape(font_libraries_ligature_cells.hb_font_t*, font_libraries_ligature_cells.hb_buffer_t*, const(font_libraries_ligature_cells.hb_feature_t)* features, uint num_features) nothrow @nogchb_shape((parameter) font_libraries_ligature_cells.hb_font_t* fontfont, (local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf, (parameter) const(font_libraries_ligature_cells.hb_feature_t)[] featuresfeatures.(field) const(font_libraries_ligature_cells.hb_feature_t)* const(font_libraries_ligature_cells.hb_feature_t)[].ptrptr, cast(uint) (parameter) const(font_libraries_ligature_cells.hb_feature_t)[] featuresfeatures.(field) ulong const(font_libraries_ligature_cells.hb_feature_t)[].lengthlength);
uint (local variable) uint nn;
auto (local variable) font_libraries_ligature_cells.hb_glyph_info_t[] infosinfos = font_libraries_ligature_cells.hb_glyph_info_t* font_libraries_ligature_cells.hb_buffer_get_glyph_infos(font_libraries_ligature_cells.hb_buffer_t*, uint* length) nothrow @nogchb_buffer_get_glyph_infos((local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf, &(local variable) uint nn)[0 .. (local variable) uint nn].font_libraries_ligature_cells.hb_glyph_info_t[] object.dup!(font_libraries_ligature_cells.hb_glyph_info_t)(const(font_libraries_ligature_cells.hb_glyph_info_t)[] a) pure nothrow @property @safedup;
auto (local variable) font_libraries_ligature_cells.hb_glyph_position_t[] positionspositions = font_libraries_ligature_cells.hb_glyph_position_t* font_libraries_ligature_cells.hb_buffer_get_glyph_positions(font_libraries_ligature_cells.hb_buffer_t*, uint* length) nothrow @nogchb_buffer_get_glyph_positions((local variable) font_libraries_ligature_cells.hb_buffer_t* bufbuf, &(local variable) uint nn)[0 .. (local variable) uint nn].font_libraries_ligature_cells.hb_glyph_position_t[] object.dup!(font_libraries_ligature_cells.hb_glyph_position_t)(const(font_libraries_ligature_cells.hb_glyph_position_t)[] a) pure nothrow @property @safedup;
return (struct) font_libraries_ligature_cells.ShapedShaped((local variable) font_libraries_ligature_cells.hb_glyph_info_t[] infosinfos, (local variable) font_libraries_ligature_cells.hb_glyph_position_t[] positionspositions);
}
/// How far, in font units, a glyph's ink reaches outside `[0, cell)`.
int int font_libraries_ligature_cells.spill(font_libraries_ligature_cells.hb_font_t* font, font_libraries_ligature_cells.hb_glyph_info_t info, font_libraries_ligature_cells.hb_glyph_position_t pos, int cell) @trustedHow far, in font units, a glyph's ink reaches outside [0, cell).
spill((struct) font_libraries_ligature_cells.hb_font_thb_font_t* (parameter) font_libraries_ligature_cells.hb_font_t* fontfont, (struct) font_libraries_ligature_cells.hb_glyph_info_thb_glyph_info_t (parameter) font_libraries_ligature_cells.hb_glyph_info_t infoinfo, (struct) font_libraries_ligature_cells.hb_glyph_position_thb_glyph_position_t (parameter) font_libraries_ligature_cells.hb_glyph_position_t pospos, int (parameter) int cellcell) @trusted
{
(struct) font_libraries_ligature_cells.hb_glyph_extents_thb_glyph_extents_t (local variable) font_libraries_ligature_cells.hb_glyph_extents_t ee;
if (!int font_libraries_ligature_cells.hb_font_get_glyph_extents(font_libraries_ligature_cells.hb_font_t*, uint glyph, font_libraries_ligature_cells.hb_glyph_extents_t* extents) nothrow @nogchb_font_get_glyph_extents((parameter) font_libraries_ligature_cells.hb_font_t* fontfont, (parameter) font_libraries_ligature_cells.hb_glyph_info_t infoinfo.(field) uint font_libraries_ligature_cells.hb_glyph_info_t.codepointcodepoint, &(local variable) font_libraries_ligature_cells.hb_glyph_extents_t ee) || (local variable) font_libraries_ligature_cells.hb_glyph_extents_t ee.(field) int font_libraries_ligature_cells.hb_glyph_extents_t.widthwidth == 0)
return 0;
const (local variable) const(int) leftleft = (parameter) font_libraries_ligature_cells.hb_glyph_position_t pospos.(field) int font_libraries_ligature_cells.hb_glyph_position_t.x_offsetx_offset + (local variable) font_libraries_ligature_cells.hb_glyph_extents_t ee.(field) int font_libraries_ligature_cells.hb_glyph_extents_t.x_bearingx_bearing;
return int std.algorithm.comparison.max!(int, const(int), int)(int __param_0, const(int) __param_1, int __param_2) pure nothrow @nogc @safeIterates the passed arguments and returns the maximum value.
max(0, -(local variable) const(int) leftleft, (local variable) const(int) leftleft + (local variable) font_libraries_ligature_cells.hb_glyph_extents_t ee.(field) int font_libraries_ligature_cells.hb_glyph_extents_t.widthwidth - (parameter) int cellcell);
}
void void font_libraries_ligature_cells.measure(string path) @trustedmeasure((alias) object.string = stringstring (parameter) string pathpath) @trusted
{
auto (local variable) font_libraries_ligature_cells.hb_blob_t* blobblob = font_libraries_ligature_cells.hb_blob_t* font_libraries_ligature_cells.hb_blob_create_from_file(const(char)* file_name) nothrow @nogchb_blob_create_from_file((parameter) string pathpath.immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trustedExamples
import core.stdc.string : strlen;
import std.conv : to;
auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);
string test = "";
p = toStringz(test);
assert(*p == 0);
test = "\0";
p = toStringz(test);
assert(*p == 0);
test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);
const string test2 = "";
p = toStringz(test2);
assert(*p == 0);
assert(toStringz([]) is toStringz(""));
toStringz);
scope (exit) void font_libraries_ligature_cells.hb_blob_destroy(font_libraries_ligature_cells.hb_blob_t*) nothrow @nogchb_blob_destroy((local variable) font_libraries_ligature_cells.hb_blob_t* blobblob);
if (uint font_libraries_ligature_cells.hb_blob_get_length(font_libraries_ligature_cells.hb_blob_t*) nothrow @nogchb_blob_get_length((local variable) font_libraries_ligature_cells.hb_blob_t* blobblob) == 0)
{
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("SKIP: empty blob for ", (parameter) string pathpath);
return;
}
auto (local variable) font_libraries_ligature_cells.hb_face_t* faceface = font_libraries_ligature_cells.hb_face_t* font_libraries_ligature_cells.hb_face_create(font_libraries_ligature_cells.hb_blob_t*, uint index) nothrow @nogchb_face_create((local variable) font_libraries_ligature_cells.hb_blob_t* blobblob, 0);
scope (exit) void font_libraries_ligature_cells.hb_face_destroy(font_libraries_ligature_cells.hb_face_t*) nothrow @nogchb_face_destroy((local variable) font_libraries_ligature_cells.hb_face_t* faceface);
auto (local variable) font_libraries_ligature_cells.hb_font_t* fontfont = font_libraries_ligature_cells.hb_font_t* font_libraries_ligature_cells.hb_font_create(font_libraries_ligature_cells.hb_face_t*) nothrow @nogchb_font_create((local variable) font_libraries_ligature_cells.hb_face_t* faceface);
scope (exit) void font_libraries_ligature_cells.hb_font_destroy(font_libraries_ligature_cells.hb_font_t*) nothrow @nogchb_font_destroy((local variable) font_libraries_ligature_cells.hb_font_t* fontfont);
void font_libraries_ligature_cells.hb_ot_font_set_funcs(font_libraries_ligature_cells.hb_font_t*) nothrow @nogchb_ot_font_set_funcs((local variable) font_libraries_ligature_cells.hb_font_t* fontfont);
const (local variable) const(uint) upemupem = uint font_libraries_ligature_cells.hb_face_get_upem(const(font_libraries_ligature_cells.hb_face_t)*) nothrow @nogchb_face_get_upem((local variable) font_libraries_ligature_cells.hb_face_t* faceface);
void font_libraries_ligature_cells.hb_font_set_scale(font_libraries_ligature_cells.hb_font_t*, int x_scale, int y_scale) nothrow @nogchb_font_set_scale((local variable) font_libraries_ligature_cells.hb_font_t* fontfont, (local variable) const(uint) upemupem, (local variable) const(uint) upemupem); // design units
const (local variable) const(int) cellcell = font_libraries_ligature_cells.Shaped font_libraries_ligature_cells.shape(font_libraries_ligature_cells.hb_font_t* font, string text, const(font_libraries_ligature_cells.hb_feature_t)[] features) @trustedshape((local variable) font_libraries_ligature_cells.hb_font_t* fontfont, "0", null).(field) font_libraries_ligature_cells.hb_glyph_position_t[] font_libraries_ligature_cells.Shaped.positionspositions[0].(field) int font_libraries_ligature_cells.hb_glyph_position_t.x_advancex_advance;
const (local variable) const(font_libraries_ligature_cells.hb_feature_t[]) onon = [(struct) font_libraries_ligature_cells.hb_feature_thb_feature_t(uint font_libraries_ligature_cells.tag(string s) pure nothrow @nogc @safeHB_TAG('c','a','l','t') as a D function: big-endian packed ASCII.
tag("calt"), 1, 0, uint.(constant) uint uint.max = 4294967295umax), (struct) font_libraries_ligature_cells.hb_feature_thb_feature_t(uint font_libraries_ligature_cells.tag(string s) pure nothrow @nogc @safeHB_TAG('c','a','l','t') as a D function: big-endian packed ASCII.
tag("liga"), 1, 0, uint.(constant) uint uint.max = 4294967295umax)];
const (local variable) const(font_libraries_ligature_cells.hb_feature_t[]) offoff = [(struct) font_libraries_ligature_cells.hb_feature_thb_feature_t(uint font_libraries_ligature_cells.tag(string s) pure nothrow @nogc @safeHB_TAG('c','a','l','t') as a D function: big-endian packed ASCII.
tag("calt"), 0, 0, uint.(constant) uint uint.max = 4294967295umax), (struct) font_libraries_ligature_cells.hb_feature_thb_feature_t(uint font_libraries_ligature_cells.tag(string s) pure nothrow @nogc @safeHB_TAG('c','a','l','t') as a D function: big-endian packed ASCII.
tag("liga"), 0, 0, uint.(constant) uint uint.max = 4294967295umax)];
(alias) object.size_t = ulongsize_t (local variable) ulong changedchanged, (local variable) ulong countChangedcountChanged, (local variable) ulong offGridoffGrid, (local variable) ulong spilledspilled;
int (local variable) int worstworst;
(alias) object.string = stringstring (local variable) string worstSeqworstSeq;
foreach ((parameter) immutable(string) seqseq; (immutable global) immutable(string[]) font_libraries_ligature_cells.corpusThe union of four fonts' ligature inventories, plus Latin liga pairs.
corpus)
{
const (local variable) const(string) texttext = "a" ~ (local variable) immutable(string) seqseq ~ "b";
const (local variable) const(font_libraries_ligature_cells.Shaped) aa = font_libraries_ligature_cells.Shaped font_libraries_ligature_cells.shape(font_libraries_ligature_cells.hb_font_t* font, string text, const(font_libraries_ligature_cells.hb_feature_t)[] features) @trustedshape((local variable) font_libraries_ligature_cells.hb_font_t* fontfont, (local variable) const(string) texttext, (local variable) const(font_libraries_ligature_cells.hb_feature_t[]) onon), (local variable) const(font_libraries_ligature_cells.Shaped) bb = font_libraries_ligature_cells.Shaped font_libraries_ligature_cells.shape(font_libraries_ligature_cells.hb_font_t* font, string text, const(font_libraries_ligature_cells.hb_feature_t)[] features) @trustedshape((local variable) font_libraries_ligature_cells.hb_font_t* fontfont, (local variable) const(string) texttext, (local variable) const(font_libraries_ligature_cells.hb_feature_t[]) offoff);
if ((local variable) const(font_libraries_ligature_cells.Shaped) aa.(field) font_libraries_ligature_cells.hb_glyph_info_t[] font_libraries_ligature_cells.Shaped.infosinfos.(field) ulong const(font_libraries_ligature_cells.hb_glyph_info_t[]).lengthlength != (local variable) const(string) texttext.ulong std.utf.count!char(const(char)[] str) pure nothrow @nogc @safeReturns the total number of code points encoded in str.
Supercedes
This function supercedes toUCSindex.
Examples
assert(count("") == 0);
assert(count("a") == 1);
assert(count("abc") == 3);
assert(count("\u20AC100") == 4);
count)
++(local variable) ulong countChangedcountChanged;
if ((local variable) const(font_libraries_ligature_cells.Shaped) aa.(field) font_libraries_ligature_cells.hb_glyph_position_t[] font_libraries_ligature_cells.Shaped.positionspositions.font_libraries_ligature_cells.measure.MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[]) font_libraries_ligature_cells.measure.map!(const(font_libraries_ligature_cells.hb_glyph_position_t)[])(const(font_libraries_ligature_cells.hb_glyph_position_t)[] r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(p => p.x_advance).font_libraries_ligature_cells.measure.FilterResult!(__lambda_L195_C56, MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[])) font_libraries_ligature_cells.measure.filter!(font_libraries_ligature_cells.measure.MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[]))(font_libraries_ligature_cells.measure.MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[]) range) pure nothrow @nogc @safefilter`!(predicate)(`range`)` returns a new `range` containing only elements `x` in range`` for
which predicate(x) returns true.
The predicate is passed to unaryFun, and can be either a string, or
any callable that can be executed via pred(element).
Examples
import std.algorithm.comparison : equal;
import std.math.operations : isClose;
import std.range;
int[] arr = [ 1, 2, 3, 4, 5 ];
// Filter below 3
auto small = filter!(a => a < 3)(arr);
assert(equal(small, [ 1, 2 ]));
// Filter again, but with Uniform Function Call Syntax (UFCS)
auto sum = arr.filter!(a => a < 3);
assert(equal(sum, [ 1, 2 ]));
// In combination with chain() to span multiple ranges
int[] a = [ 3, -2, 400 ];
int[] b = [ 100, -101, 102 ];
auto r = chain(a, b).filter!(a => a > 0);
assert(equal(r, [ 3, 400, 100, 102 ]));
// Mixing convertible types is fair game, too
double[] c = [ 2.5, 3.0 ];
auto r1 = chain(c, a, b).filter!(a => cast(int) a != a);
assert(isClose(r1, [ 2.5 ]));
filter!(x => x != cell).const(int)[] std.array.array!(font_libraries_ligature_cells.measure.FilterResult!(__lambda_L195_C56, MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[])))(font_libraries_ligature_cells.measure.FilterResult!(__lambda_L195_C56, MapResult!(__lambda_L195_C30, const(hb_glyph_position_t)[])) r) pure nothrow @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array.(field) ulong const(int)[].lengthlength)
++(local variable) ulong offGridoffGrid;
if (bool std.algorithm.comparison.equal!().equal!(font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C32, const(hb_glyph_info_t)[]), font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C64, const(hb_glyph_info_t)[]))(font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C32, const(hb_glyph_info_t)[]) __param_0, font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C64, const(hb_glyph_info_t)[]) __param_1) pure nothrow @nogc @safeCompares two or more ranges for equality, as defined by predicate pred
(which is == by default).
Compares two or more ranges for equality. The ranges may have
different element types, as long as all are comparable by means of
the pred.
Performs O(min(rs[0].length, rs[1].length, ...)) evaluations of pred. However, if
equal is invoked with the default predicate, the implementation may take the liberty
to use faster implementations that have the theoretical worst-case
O(max(rs[0].length, rs[1].length, ...)).
At least one of the ranges must be finite. If one range involved is infinite, the result is
(statically known to be) false.
If the ranges have different kinds of UTF code unit (char, wchar, or
dchar), then they are compared using UTF decoding to avoid
accidentally integer-promoting units.
Examples
import std.algorithm.comparison : equal;
import std.math.operations : isClose;
int[4] a = [ 1, 2, 4, 3 ];
assert(!equal(a[], a[1..$]));
assert(equal(a[], a[]));
assert(equal!((a, b) => a == b)(a[], a[]));
// different types
double[4] b = [ 1.0, 2, 4, 3];
assert(!equal(a[], b[1..$]));
assert(equal(a[], b[]));
// predicated: ensure that two vectors are approximately equal
double[4] c = [ 1.0000000005, 2, 4, 3];
assert(equal!isClose(b[], c[]));
Tip
equal can itself be used as a predicate to other functions.
This can be very useful when the element type of a range is itself a
range. In particular, equal can be its own predicate, allowing
range of range (of range...) comparisons.
import std.algorithm.comparison : equal;
import std.range : iota, chunks;
assert(equal!(equal!equal)(
[[[0, 1], [2, 3]], [[4, 5], [6, 7]]],
iota(0, 8).chunks(2).chunks(2)
));
equal((local variable) const(font_libraries_ligature_cells.Shaped) aa.(field) font_libraries_ligature_cells.hb_glyph_info_t[] font_libraries_ligature_cells.Shaped.infosinfos.font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C32, const(hb_glyph_info_t)[]) font_libraries_ligature_cells.measure.map!(const(font_libraries_ligature_cells.hb_glyph_info_t)[])(const(font_libraries_ligature_cells.hb_glyph_info_t)[] r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(i => i.codepoint), (local variable) const(font_libraries_ligature_cells.Shaped) bb.(field) font_libraries_ligature_cells.hb_glyph_info_t[] font_libraries_ligature_cells.Shaped.infosinfos.font_libraries_ligature_cells.measure.MapResult!(__lambda_L197_C64, const(hb_glyph_info_t)[]) font_libraries_ligature_cells.measure.map!(const(font_libraries_ligature_cells.hb_glyph_info_t)[])(const(font_libraries_ligature_cells.hb_glyph_info_t)[] r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!(i => i.codepoint)))
continue;
++(local variable) ulong changedchanged;
int (local variable) int reachreach;
foreach ((parameter) ulong ii, (parameter) const(font_libraries_ligature_cells.hb_glyph_info_t) infoinfo; (local variable) const(font_libraries_ligature_cells.Shaped) aa.(field) font_libraries_ligature_cells.hb_glyph_info_t[] font_libraries_ligature_cells.Shaped.infosinfos)
(local variable) int reachreach = int std.algorithm.comparison.max!(int, int)(int a, int b) pure nothrow @nogc @safeIterates the passed arguments and returns the maximum value.
Examples
int a = 5;
short b = 6;
double c = 2;
auto d = max(a, b);
assert(is(typeof(d) == int));
assert(d == 6);
auto e = min(a, b, c);
assert(is(typeof(e) == double));
assert(e == 2);
max((local variable) int reachreach, int font_libraries_ligature_cells.spill(font_libraries_ligature_cells.hb_font_t* font, font_libraries_ligature_cells.hb_glyph_info_t info, font_libraries_ligature_cells.hb_glyph_position_t pos, int cell) @trustedHow far, in font units, a glyph's ink reaches outside [0, cell).
spill((local variable) font_libraries_ligature_cells.hb_font_t* fontfont, (local variable) const(font_libraries_ligature_cells.hb_glyph_info_t) infoinfo, (local variable) const(font_libraries_ligature_cells.Shaped) aa.(field) font_libraries_ligature_cells.hb_glyph_position_t[] font_libraries_ligature_cells.Shaped.positionspositions[(local variable) ulong ii], (local variable) const(int) cellcell));
if ((local variable) int reachreach > 0)
++(local variable) ulong spilledspilled;
if ((local variable) int reachreach > (local variable) int worstworst)
{
(local variable) int worstworst = (local variable) int reachreach;
(local variable) string worstSeqworstSeq = (local variable) immutable(string) seqseq;
}
}
void std.stdio.writefln!(char, string, const(uint), const(int))(in char[] fmt, string __param_1, const(uint) __param_2, const(int) __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln("%s: upem %d, cell %d", (parameter) string pathpath.string std.path.baseName!(immutable(char))(return scope string path) pure nothrow @nogc @safeNote
This function only strips away the specified suffix, which
doesn't necessarily have to represent an extension.
To remove the extension from a path, regardless of what the extension
is, use stripExtension.
To obtain the filename without leading directories and without
an extension, combine the functions like this:
assert(baseName(stripExtension("dir/file.ext")) == "file");
baseName, (local variable) const(uint) upemupem, (local variable) const(int) cellcell);
void std.stdio.writefln!(char, ulong, ulong, ulong, ulong)(in char[] fmt, ulong __param_1, ulong __param_2, ulong __param_3, ulong __param_4) @safeEquivalent to writef(fmt, args, '\n').
writefln(" %d of %d sequences shape differently; %d change the glyph count; "
~ "%d have an off-cell advance", (local variable) ulong changedchanged, (immutable global) immutable(string[]) font_libraries_ligature_cells.corpusThe union of four fonts' ligature inventories, plus Latin liga pairs.
corpus.(field) ulong immutable(string[]).lengthlength, (local variable) ulong countChangedcountChanged, (local variable) ulong offGridoffGrid);
void std.stdio.writefln!(char, ulong, double, string)(in char[] fmt, ulong __param_1, double __param_2, string __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln(" %d draw ink outside a glyph's own cell; worst reach %.2f cells (%s)",
(local variable) ulong spilledspilled, double((local variable) int worstworst) / (local variable) const(int) cellcell, (local variable) string worstSeqworstSeq);
}
(alias) object.string = stringstring[] string[] font_libraries_ligature_cells.resolveFonts(string[] args) @saferesolveFonts((alias) object.string = stringstring[] (parameter) string[] argsargs) @safe
{
auto (local variable) string[] givengiven = (parameter) string[] argsargs[1 .. $].std.algorithm.iteration.FilterResult!(exists, string[]) std.algorithm.iteration.filter!(exists).filter!(string[])(string[] range) pure nothrow @nogc @safefilter`!(predicate)(`range`)` returns a new `range` containing only elements `x` in range`` for
which predicate(x) returns true.
The predicate is passed to unaryFun, and can be either a string, or
any callable that can be executed via pred(element).
Examples
import std.algorithm.comparison : equal;
import std.math.operations : isClose;
import std.range;
int[] arr = [ 1, 2, 3, 4, 5 ];
// Filter below 3
auto small = filter!(a => a < 3)(arr);
assert(equal(small, [ 1, 2 ]));
// Filter again, but with Uniform Function Call Syntax (UFCS)
auto sum = arr.filter!(a => a < 3);
assert(equal(sum, [ 1, 2 ]));
// In combination with chain() to span multiple ranges
int[] a = [ 3, -2, 400 ];
int[] b = [ 100, -101, 102 ];
auto r = chain(a, b).filter!(a => a > 0);
assert(equal(r, [ 3, 400, 100, 102 ]));
// Mixing convertible types is fair game, too
double[] c = [ 2.5, 3.0 ];
auto r1 = chain(c, a, b).filter!(a => cast(int) a != a);
assert(isClose(r1, [ 2.5 ]));
filter!(template) std.file.exists(R)(R name) if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)Determine whether the given file (or directory) exists.
exists.string[] std.array.array!(std.algorithm.iteration.FilterResult!(exists, string[]))(std.algorithm.iteration.FilterResult!(exists, string[]) r) nothrow @safeAllocates an array and initializes it with copies of the elements
of range r.
Narrow strings are handled as follows:
If autodecoding is turned on (default), then they are handled as a separate overload.
If autodecoding is turned off, then this is equivalent to duplicating the array.
array;
if ((local variable) string[] givengiven.(field) ulong string[].lengthlength)
return (local variable) string[] givengiven;
try
{
auto (local variable) std.typecons.Tuple!(int, "status", string, "output") rr = std.typecons.Tuple!(int, "status", string, "output") std.process.execute(scope const(char[])[] args, const(string[string]) env = cast(const(string[string]))null, std.process.Config config = Config(Flags.none, null, null), ulong maxOutput = 18446744073709551615LU, scope const(char)[] workDir = null) @safeExecutes the given program or shell command and returns its exit
code and output.
execute and executeShell start a new process using
spawnProcess and spawnShell, respectively, and wait
for the process to complete before returning. The functions capture
what the child process prints to both its standard output and
standard error streams, and return this together with its exit code.
auto dmd = execute(["dmd", "myapp.d"]);
if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
auto ls = executeShell("ls -l");
if (ls.status != 0) writeln("Failed to retrieve file listing");
else writeln(ls.output);
The args/program/command, env and config
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.
POSIX specific
If the process is terminated by a signal, the status field of
the return value will contain a negative number whose absolute
value is the signal number. (See wait for details.)
execute(["fc-match", "-f", "%{file}", "monospace"]);
if ((local variable) std.typecons.Tuple!(int, "status", string, "output") rr.status == 0 && (field) int std.typecons.Tuple!(int, "status", string, "output").__expand_field_0r.output.string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip.(field) string std.typecons.Tuple!(int, "status", string, "output").__expand_field_1length && bool std.file.exists!string(string name) nothrow @nogc @safeDetermine whether the given file (or directory) exists.
exists((local variable) std.typecons.Tuple!(int, "status", string, "output") rr.output.string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip))
return [(local variable) std.typecons.Tuple!(int, "status", string, "output") rr.output.string std.string.strip!string(string str) pure nothrow @nogc @safeStrips both leading and trailing whitespace (as defined by
isWhite) or as specified in the second argument.
Examples
import std.uni : lineSep, paraSep;
assert(strip(" hello world ") ==
"hello world");
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
"hello world");
assert(strip("hello world") ==
"hello world");
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
"hello world");
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
"hello world");
strip];
}
catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception) {}
return null;
}
int int D main(string[] args)main((alias) object.string = stringstring[] (parameter) string[] argsargs)
{
const (local variable) const(string[]) fontsfonts = string[] font_libraries_ligature_cells.resolveFonts(string[] args) @saferesolveFonts((parameter) string[] argsargs);
if (!(local variable) const(string[]) fontsfonts.(field) ulong const(string[]).lengthlength)
{
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("SKIP: no font file resolved (pass paths, or install fontconfig)");
return 0;
}
foreach ((parameter) const(string) pathpath; (local variable) const(string[]) fontsfonts)
void font_libraries_ligature_cells.measure(string path) @trustedmeasure((local variable) const(string) pathpath);
return 0;
}