165 lines
3.6 KiB
Objective-C
165 lines
3.6 KiB
Objective-C
// 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
|
|
|
|
#define fvarWeight 0x77676874
|
|
#define fvarWidth 0x77647468
|
|
|
|
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;
|
|
}
|