ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
237 lines
7.7 KiB
Python
Executable File
237 lines
7.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# fontconfig/fc-case/fc-case.py
|
|
#
|
|
# Copyright © 2004 Keith Packard
|
|
# Copyright © 2019 Tim-Philipp Müller
|
|
#
|
|
# Permission to use, copy, modify, distribute, and sell this software and its
|
|
# documentation for any purpose is hereby granted without fee, provided that
|
|
# the above copyright notice appear in all copies and that both that
|
|
# copyright notice and this permission notice appear in supporting
|
|
# documentation, and that the name of the author(s) not be used in
|
|
# advertising or publicity pertaining to distribution of the software without
|
|
# specific, written prior permission. The authors make no
|
|
# representations about the suitability of this software for any purpose. It
|
|
# is provided "as is" without express or implied warranty.
|
|
#
|
|
# THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
# EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
# PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
from enum import Enum
|
|
import argparse
|
|
import string
|
|
import sys
|
|
|
|
|
|
class CaseFoldClass(Enum):
|
|
COMMON = 1
|
|
FULL = 2
|
|
SIMPLE = 3
|
|
TURKIC = 4
|
|
|
|
|
|
class CaseFoldMethod(Enum):
|
|
RANGE = 0
|
|
EVEN_ODD = 1
|
|
FULL = 2
|
|
|
|
|
|
caseFoldClassMap = {
|
|
'C': CaseFoldClass.COMMON,
|
|
'F': CaseFoldClass.FULL,
|
|
'S': CaseFoldClass.SIMPLE,
|
|
'T': CaseFoldClass.TURKIC
|
|
}
|
|
|
|
folds = []
|
|
|
|
def ucs4_to_utf8(ucs4):
|
|
utf8_rep = []
|
|
|
|
if ucs4 < 0x80:
|
|
utf8_rep.append(ucs4)
|
|
bits = -6
|
|
elif ucs4 < 0x800:
|
|
utf8_rep.append(((ucs4 >> 6) & 0x1F) | 0xC0)
|
|
bits = 0
|
|
elif ucs4 < 0x10000:
|
|
utf8_rep.append(((ucs4 >> 12) & 0x0F) | 0xE0)
|
|
bits = 6
|
|
elif ucs4 < 0x200000:
|
|
utf8_rep.append(((ucs4 >> 18) & 0x07) | 0xF0)
|
|
bits = 12
|
|
elif ucs4 < 0x4000000:
|
|
utf8_rep.append(((ucs4 >> 24) & 0x03) | 0xF8)
|
|
bits = 18
|
|
elif ucs4 < 0x80000000:
|
|
utf8_rep.append(((ucs4 >> 30) & 0x01) | 0xFC)
|
|
bits = 24
|
|
else:
|
|
return []
|
|
|
|
while bits >= 0:
|
|
utf8_rep.append(((ucs4 >> bits) & 0x3F) | 0x80)
|
|
bits -= 6
|
|
|
|
return utf8_rep
|
|
|
|
|
|
def utf8_size(ucs4):
|
|
return len(ucs4_to_utf8(ucs4))
|
|
|
|
|
|
case_fold_method_name_map = {
|
|
CaseFoldMethod.RANGE: 'FC_CASE_FOLD_RANGE,',
|
|
CaseFoldMethod.EVEN_ODD: 'FC_CASE_FOLD_EVEN_ODD,',
|
|
CaseFoldMethod.FULL: 'FC_CASE_FOLD_FULL,',
|
|
}
|
|
|
|
if __name__=='__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('case_folding_file')
|
|
parser.add_argument('--template', dest='template_file', default=None)
|
|
parser.add_argument('--output', dest='output_file', default=None)
|
|
|
|
args = parser.parse_args()
|
|
|
|
minFoldChar = None
|
|
maxFoldChar = None
|
|
fold = None
|
|
|
|
foldChars = []
|
|
maxFoldChars = 0
|
|
|
|
maxExpand = 0
|
|
|
|
# Read the standard Unicode CaseFolding.txt file
|
|
with open(args.case_folding_file, 'r', encoding='utf-8') as casefile:
|
|
for cnt, line in enumerate(casefile):
|
|
if not line or not line[0] in string.hexdigits:
|
|
continue
|
|
|
|
# print('Line {}: {}'.format(cnt, line.strip()))
|
|
|
|
tokens = line.split('; ')
|
|
|
|
if len(tokens) < 3:
|
|
print('Not enough tokens in line {}'.format(cnt),
|
|
file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# Get upper case value
|
|
upper = int(tokens.pop(0), 16)
|
|
|
|
# Get class
|
|
cfclass = caseFoldClassMap[tokens.pop(0)]
|
|
|
|
# Get list of result characters
|
|
lower = list(map(lambda s: int(s, 16), tokens.pop(0).split()))
|
|
|
|
# print('\t----> {:04X} {} {}'.format(upper, cfclass, lower))
|
|
|
|
if not minFoldChar:
|
|
minFoldChar = upper
|
|
|
|
maxFoldChar = upper
|
|
|
|
if cfclass in [CaseFoldClass.COMMON, CaseFoldClass.FULL]:
|
|
if len(lower) == 1:
|
|
# foldExtends
|
|
if fold and fold['method'] == CaseFoldMethod.RANGE:
|
|
foldExtends = (lower[0] - upper) == fold['offset'] and upper == fold['upper'] + fold['count']
|
|
elif fold and fold['method'] == CaseFoldMethod.EVEN_ODD:
|
|
foldExtends = (lower[0] - upper) == 1 and upper == (fold['upper'] + fold['count'] + 1)
|
|
else:
|
|
foldExtends = False
|
|
|
|
if foldExtends:
|
|
# This modifies the last fold item in the array too
|
|
fold['count'] = upper - fold['upper'] + 1
|
|
else:
|
|
fold = {}
|
|
fold['upper'] = upper
|
|
fold['offset'] = lower[0] - upper
|
|
if fold['offset'] == 1:
|
|
fold['method'] = CaseFoldMethod.EVEN_ODD
|
|
else:
|
|
fold['method'] = CaseFoldMethod.RANGE
|
|
fold['count'] = 1
|
|
folds.append(fold)
|
|
expand = utf8_size(lower[0]) - utf8_size(upper)
|
|
else:
|
|
fold = {}
|
|
fold['upper'] = upper
|
|
fold['method'] = CaseFoldMethod.FULL
|
|
fold['offset'] = len(foldChars)
|
|
|
|
# add chars
|
|
for c in lower:
|
|
utf8_rep = ucs4_to_utf8(c)
|
|
# print('{} -> {}'.format(c,utf8_rep))
|
|
for utf8_char in utf8_rep:
|
|
foldChars.append(utf8_char)
|
|
|
|
fold['count'] = len(foldChars) - fold['offset']
|
|
folds.append(fold)
|
|
|
|
if fold['count'] > maxFoldChars:
|
|
maxFoldChars = fold['count']
|
|
|
|
expand = fold['count'] - utf8_size(upper)
|
|
if expand > maxExpand:
|
|
maxExpand = expand
|
|
|
|
# Open output file
|
|
if args.output_file:
|
|
sys.stdout = open(args.output_file, 'w', encoding='utf-8')
|
|
|
|
print('/*')
|
|
print(' * This file was generated against CaseFolding.txt from'
|
|
' Unicode.org.')
|
|
print(' * All the data in array is a part of them and licensed'
|
|
' under a terms of use:')
|
|
print(' * https://www.unicode.org/terms_of_use.html')
|
|
print(' */')
|
|
print('')
|
|
# Dump these tables
|
|
print('#define FC_NUM_CASE_FOLD\t{}'.format(len(folds)))
|
|
print('#define FC_NUM_CASE_FOLD_CHARS\t{}'.format(len(foldChars)))
|
|
print('#define FC_MAX_CASE_FOLD_CHARS\t{}'.format(maxFoldChars))
|
|
print('#define FC_MAX_CASE_FOLD_EXPAND\t{}'.format(maxExpand))
|
|
print('#define FC_MIN_FOLD_CHAR\t0x{:08x}'.format(minFoldChar))
|
|
print('#define FC_MAX_FOLD_CHAR\t0x{:08x}'.format(maxFoldChar))
|
|
print('')
|
|
|
|
# Dump out ranges
|
|
print('static const FcCaseFold fcCaseFold[FC_NUM_CASE_FOLD] = {')
|
|
for f in folds:
|
|
short_offset = f['offset']
|
|
if short_offset < -32367:
|
|
short_offset += 65536
|
|
if short_offset > 32368:
|
|
short_offset -= 65536
|
|
print(f' {{ 0x{f["upper"]:08x}, '
|
|
f'{case_fold_method_name_map[f["method"]]:22s} '
|
|
f'0x{f["count"]:04x}, {short_offset:6d} }},')
|
|
print('};\n')
|
|
|
|
# Dump out "other" values
|
|
print('static const FcChar8\tfcCaseFoldChars[FC_NUM_CASE_FOLD_CHARS] = {')
|
|
for n, c in enumerate(foldChars):
|
|
if n == len(foldChars) - 1:
|
|
end = ''
|
|
elif n % 16 == 15:
|
|
end = ',\n'
|
|
else:
|
|
end = ','
|
|
print('0x{:02x}'.format(c), end=end)
|
|
print('\n};')
|
|
|
|
sys.stdout.flush()
|