blob: c7af0d6dde30f2baef4e944fb8a9f4fd884d667c [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense
// Common data structures and functions for the path tag stream.
// This is the layout for tag bytes in the path stream. See
// doc/pathseg.md for an explanation.
#define PATH_TAG_PATHSEG_BITS 0xf
#define PATH_TAG_PATH 0x10
#define PATH_TAG_TRANSFORM 0x20
#define PATH_TAG_LINEWIDTH 0x40
struct TagMonoid {
uint trans_ix;
uint linewidth_ix;
uint pathseg_ix;
uint path_ix;
uint pathseg_offset;
};
TagMonoid tag_monoid_identity() {
return TagMonoid(0, 0, 0, 0, 0);
}
TagMonoid combine_tag_monoid(TagMonoid a, TagMonoid b) {
TagMonoid c;
c.trans_ix = a.trans_ix + b.trans_ix;
c.linewidth_ix = a.linewidth_ix + b.linewidth_ix;
c.pathseg_ix = a.pathseg_ix + b.pathseg_ix;
c.path_ix = a.path_ix + b.path_ix;
c.pathseg_offset = a.pathseg_offset + b.pathseg_offset;
return c;
}
TagMonoid reduce_tag(uint tag_word) {
TagMonoid c;
// Some fun bit magic here, see doc/pathseg.md for explanation.
uint point_count = tag_word & 0x3030303;
c.pathseg_ix = bitCount((point_count * 7) & 0x4040404);
c.linewidth_ix = bitCount(tag_word & (PATH_TAG_LINEWIDTH * 0x1010101));
c.path_ix = bitCount(tag_word & (PATH_TAG_PATH * 0x1010101));
c.trans_ix = bitCount(tag_word & (PATH_TAG_TRANSFORM * 0x1010101));
uint n_points = point_count + ((tag_word >> 2) & 0x1010101);
uint a = n_points + (n_points & (((tag_word >> 3) & 0x1010101) * 15));
a += a >> 8;
a += a >> 16;
c.pathseg_offset = a & 0xff;
return c;
}