Started writing the code for processing font variations for Core Text so we can process Skia correctly.

This commit is contained in:
Pietro Gagliardi 2017-11-02 19:27:57 -04:00
parent 2e5f2c273b
commit b7e6311621
2 changed files with 219 additions and 0 deletions

161
doc/export/fontvariation.m Normal file
View File

@ -0,0 +1,161 @@
// 2 november 2017
#import "uipriv_darwin.h"
// references:
// - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html
// - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html
// - https://www.microsoft.com/typography/otspec/fvar.htm
// - https://www.microsoft.com/typography/otspec/otvaroverview.htm#CSN
// - https://www.microsoft.com/typography/otspec/otff.htm
// - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html#Types
// - https://www.microsoft.com/typography/otspec/avar.htm
typedef uint32_t fixed1616;
typedef uint16_t fixed214;
static fixed1616 doubleToFixed1616(double d)
{
double ipart, fpart;
long flong;
int16_t i16;
uint32_t ret;
fpart = fabs(modf(d, &ipart));
fpart *= 65536;
flong = lround(fpart);
i16 = (int16_t) ipart;
ret = (uint32_t) ((uint16_t) i16);
ret <<= 16;
ret |= (uint16_t) (flong & 0xFFFF);
return (fixed1616) ret;
}
static double fixed1616ToDouble(fixed1616 f)
{
int16_t base;
double frac;
base = (int16_t) ((f >> 16) & 0xFFFF);
frac = ((double) (f & 0xFFFF)) / 65536;
return ((double) base) + frac;
}
static fixed214 fixed1616ToFixed214(fixed1616 f)
{
uint32_t t;
uint32_t topbit;
t = f + 0x00000002;
topbit = t & 0x80000000;
t >>= 2;
if (topbit != 0)
t |= 0xC000000;
return (fixed214) (t & 0xFFFF);
}
static double fixed214ToDouble(fixed214 f)
{
double base;
double frac;
switch ((f >> 14) & 0x3) {
case 0:
base = 0;
break;
case 1:
base = 1;
break;
case 2:
base = -2:
break;
case 3:
base = -1;
}
frac = ((double) (f & 0x3FFF)) / 16384;
return base + frac;
}
static fixed1616 fixed214ToFixed1616(fixed214 f)
{
int32_t t;
uint32_t x;
t = (int32_t) ((int16_t) f);
t <<= 2;
x = (uint32_t) t;
return (float1616) (x - 0x00000002);
}
static const fixed1616Negative1 = 0xFFFF0000;
static const fixed1616Zero = 0x00000000;
static const fixed1616Positive1 = 0x00010000;
static fixed1616 normalize1616(fixed1616 val, fixed1616 min, fixed1616 max, fixed1616 def)
{
if (val < min)
val = min;
if (val > max)
val = max;
if (val < def)
return -(def - val) / (def - min);
if (val > def)
return (val - def) / (max - def);
return fixed1616Zero;
}
static fixed214 normalizedTo214(fixed1616 val, const fixed1616 *avarMappings, size_t avarCount)
{
if (val < fixed1616Negative1)
val = fixed1616Negative1;
if (val > fixed1616Positive1)
val = fixed1616Positive1;
if (avarCount != 0) {
size_t start, end;
float1616 startFrom, endFrom;
float1616 startTo, endTo;
for (end = 0; end < avarCount; end += 2) {
endFrom = avarMappings[end];
endTo = avarMappings[end + 1];
if (endFrom >= val)
break;
}
if (endFrom == val)
val = endTo;
else {
start = end - 2;
startFrom = avarMappings[start];
startTo = avarMappings[start + 1];
val = (val - startFrom) / (endFrom - startFrom);
val *= (endTo - startTo);
val += startTo;
}
}
return fixed1616ToFixed214(val);
}
fixed1616 *avarExtract(CFDataRef table, size_t index, size_t *n)
{
const UInt8 *b;
size_t off;
size_t i, nEntries;
fixed1616 *entries;
fixed1616 *p;
b = CFDataGetBytePtr(table);
off = 8;
#define nextuint16be() ((((uint16_t) (b[off])) << 8) | ((uint16_t) (b[off + 1])))
for (; index > 0; index--) {
nEntries = (size_t) nextuint16be();
off += 2;
off += 4 * nEntries;
}
nEntries = nextuint16be();
*n = nEntries * 2;
entries = (fixed1616 *) uiAlloc(*n * sizeof (fixed1616), "fixed1616[]");
for (i = 0; i < *n; i++) {
*p++ = fixed214ToFixed1616((fixed214) nextuint16be());
off += 2;
}
return entries;
}

58
doc/export/ttfixedtest.go Normal file
View File

@ -0,0 +1,58 @@
// 2 november 2017
package main
import (
"fmt"
)
type fixed1616 uint32
type fixed214 uint16
func fixed1616To214(f fixed1616) fixed214 {
f += 0x00000002
g := int32(f) >> 2
return fixed214(uint32(g) & 0xFFFF)
}
func (f fixed1616) In214Range() bool {
base := int16((f >> 16) & 0xFFFF)
return base >= -2 && base < 2
}
func (f fixed1616) String() string {
base := int16((f >> 16) & 0xFFFF)
frac := float64(f & 0xFFFF) / 65536
res := float64(base) + frac
return fmt.Sprintf("%f 0x%08X", res, uint32(f))
}
func (f fixed214) String() string {
base := []int16{
0,
1,
-2,
-1,
}[(f & 0xC000) >> 14]
frac := float64(f & 0x3FFF) / 16384
res := float64(base) + frac
return fmt.Sprintf("%f 0x%04X", res, uint16(f))
}
func main() {
fmt.Println(fixed214(0x7fff))
fmt.Println(fixed214(0x8000))
fmt.Println(fixed214(0x4000))
fmt.Println(fixed214(0xc000))
fmt.Println(fixed214(0x7000))
fmt.Println(fixed214(0x0000))
fmt.Println(fixed214(0x0001))
fmt.Println(fixed214(0xffff))
fmt.Println()
for i := uint64(0x00000000); i <= 0xFFFFFFFF; i++ {
j := fixed1616(i)
if !j.In214Range() { continue }
fmt.Println(j, "->", fixed1616To214(j))
}
}