initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
2
modules/text_server_adv/.gitignore
vendored
Normal file
2
modules/text_server_adv/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Godot-cpp headers
|
||||
gdextension_build/godot-cpp
|
540
modules/text_server_adv/SCsub
Normal file
540
modules/text_server_adv/SCsub
Normal file
@@ -0,0 +1,540 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
import text_server_adv_builders
|
||||
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
env_text_server_adv = env_modules.Clone()
|
||||
|
||||
# Thirdparty source files
|
||||
|
||||
thirdparty_obj = []
|
||||
freetype_enabled = "freetype" in env.module_list
|
||||
msdfgen_enabled = "msdfgen" in env.module_list
|
||||
|
||||
if "svg" in env.module_list:
|
||||
env_text_server_adv.Prepend(
|
||||
CPPEXTPATH=[
|
||||
"#thirdparty/thorvg/inc",
|
||||
"#thirdparty/thorvg/src/common",
|
||||
"#thirdparty/thorvg/src/renderer",
|
||||
]
|
||||
)
|
||||
# Enable ThorVG static object linking.
|
||||
env_text_server_adv.Append(CPPDEFINES=["TVG_STATIC"])
|
||||
|
||||
if env["builtin_icu4c"]:
|
||||
env_text_server_adv.Append(CPPDEFINES=["HAVE_ICU_BUILTIN"])
|
||||
|
||||
if env["builtin_harfbuzz"]:
|
||||
env_harfbuzz = env_modules.Clone()
|
||||
env_harfbuzz.disable_warnings()
|
||||
|
||||
thirdparty_dir = "#thirdparty/harfbuzz/"
|
||||
thirdparty_sources = [
|
||||
"src/hb-aat-layout.cc",
|
||||
"src/hb-aat-map.cc",
|
||||
"src/hb-blob.cc",
|
||||
"src/hb-buffer-serialize.cc",
|
||||
"src/hb-buffer-verify.cc",
|
||||
"src/hb-buffer.cc",
|
||||
# "src/hb-cairo-utils.cc",
|
||||
# "src/hb-cairo.cc",
|
||||
"src/hb-common.cc",
|
||||
# "src/hb-coretext-font.cc",
|
||||
# "src/hb-coretext-shape.cc",
|
||||
# "src/hb-directwrite.cc",
|
||||
"src/hb-draw.cc",
|
||||
"src/hb-face-builder.cc",
|
||||
"src/hb-face.cc",
|
||||
"src/hb-fallback-shape.cc",
|
||||
"src/hb-font.cc",
|
||||
# "src/hb-gdi.cc",
|
||||
# "src/hb-glib.cc",
|
||||
# "src/hb-gobject-structs.cc",
|
||||
"src/hb-icu.cc",
|
||||
"src/hb-map.cc",
|
||||
"src/hb-number.cc",
|
||||
"src/hb-ot-cff1-table.cc",
|
||||
"src/hb-ot-cff2-table.cc",
|
||||
"src/hb-ot-color.cc",
|
||||
"src/hb-ot-face.cc",
|
||||
"src/hb-ot-font.cc",
|
||||
"src/hb-ot-layout.cc",
|
||||
"src/hb-ot-map.cc",
|
||||
"src/hb-ot-math.cc",
|
||||
"src/hb-ot-meta.cc",
|
||||
"src/hb-ot-metrics.cc",
|
||||
"src/hb-ot-name.cc",
|
||||
"src/hb-ot-shaper-arabic.cc",
|
||||
"src/hb-ot-shaper-default.cc",
|
||||
"src/hb-ot-shaper-hangul.cc",
|
||||
"src/hb-ot-shaper-hebrew.cc",
|
||||
"src/hb-ot-shaper-indic-table.cc",
|
||||
"src/hb-ot-shaper-indic.cc",
|
||||
"src/hb-ot-shaper-khmer.cc",
|
||||
"src/hb-ot-shaper-myanmar.cc",
|
||||
"src/hb-ot-shaper-syllabic.cc",
|
||||
"src/hb-ot-shaper-thai.cc",
|
||||
"src/hb-ot-shaper-use.cc",
|
||||
"src/hb-ot-shaper-vowel-constraints.cc",
|
||||
"src/hb-ot-shape-fallback.cc",
|
||||
"src/hb-ot-shape-normalize.cc",
|
||||
"src/hb-ot-shape.cc",
|
||||
"src/hb-ot-tag.cc",
|
||||
"src/hb-ot-var.cc",
|
||||
"src/hb-outline.cc",
|
||||
"src/hb-paint-bounded.cc",
|
||||
"src/hb-paint-extents.cc",
|
||||
"src/hb-paint.cc",
|
||||
"src/hb-set.cc",
|
||||
"src/hb-shape-plan.cc",
|
||||
"src/hb-shape.cc",
|
||||
"src/hb-shaper.cc",
|
||||
"src/hb-static.cc",
|
||||
"src/hb-style.cc",
|
||||
"src/hb-subset-cff-common.cc",
|
||||
"src/hb-subset-cff1.cc",
|
||||
"src/hb-subset-cff2.cc",
|
||||
"src/hb-subset-input.cc",
|
||||
"src/hb-subset-instancer-iup.cc",
|
||||
"src/hb-subset-instancer-solver.cc",
|
||||
"src/hb-subset-plan.cc",
|
||||
"src/hb-subset-serialize.cc",
|
||||
"src/hb-subset.cc",
|
||||
"src/hb-ucd.cc",
|
||||
"src/hb-unicode.cc",
|
||||
# "src/hb-uniscribe.cc",
|
||||
"src/OT/Var/VARC/VARC.cc",
|
||||
]
|
||||
|
||||
if freetype_enabled:
|
||||
thirdparty_sources += [
|
||||
"src/hb-ft.cc",
|
||||
]
|
||||
if env["graphite"]:
|
||||
thirdparty_sources += [
|
||||
"src/hb-graphite2.cc",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
env_harfbuzz.Prepend(CPPEXTPATH=["#thirdparty/harfbuzz/src"])
|
||||
|
||||
env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"])
|
||||
if env["builtin_icu4c"]:
|
||||
env_harfbuzz.Prepend(CPPEXTPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
|
||||
env_harfbuzz.Append(
|
||||
CCFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
"-DHAVE_ICU_BUILTIN",
|
||||
]
|
||||
)
|
||||
|
||||
if freetype_enabled:
|
||||
env_harfbuzz.Append(
|
||||
CCFLAGS=[
|
||||
"-DHAVE_FREETYPE",
|
||||
]
|
||||
)
|
||||
if env["graphite"]:
|
||||
env_harfbuzz.Append(
|
||||
CCFLAGS=[
|
||||
"-DHAVE_GRAPHITE2",
|
||||
]
|
||||
)
|
||||
if env["builtin_freetype"]:
|
||||
env_harfbuzz.Prepend(CPPEXTPATH=["#thirdparty/freetype/include"])
|
||||
if env["builtin_graphite"] and env["graphite"]:
|
||||
env_harfbuzz.Prepend(CPPEXTPATH=["#thirdparty/graphite/include"])
|
||||
env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"])
|
||||
|
||||
if env["platform"] in ["android", "linuxbsd", "web"]:
|
||||
env_harfbuzz.Append(CCFLAGS=["-DHAVE_PTHREAD"])
|
||||
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/harfbuzz/src"])
|
||||
|
||||
lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources)
|
||||
thirdparty_obj += lib
|
||||
|
||||
# Needs to be appended to arrive after libscene in the linker call,
|
||||
# but we don't want it to arrive *after* system libs, so manual hack
|
||||
# LIBS contains first SCons Library objects ("SCons.Node.FS.File object")
|
||||
# and then plain strings for system library. We insert between the two.
|
||||
inserted = False
|
||||
for idx, linklib in enumerate(env["LIBS"]):
|
||||
if isinstance(linklib, (str, bytes)): # first system lib such as "X11", otherwise SCons lib object
|
||||
env["LIBS"].insert(idx, lib)
|
||||
inserted = True
|
||||
break
|
||||
if not inserted:
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
|
||||
if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
|
||||
env_graphite = env_modules.Clone()
|
||||
env_graphite.disable_warnings()
|
||||
|
||||
thirdparty_dir = "#thirdparty/graphite/"
|
||||
thirdparty_sources = [
|
||||
"src/gr_char_info.cpp",
|
||||
"src/gr_face.cpp",
|
||||
"src/gr_features.cpp",
|
||||
"src/gr_font.cpp",
|
||||
"src/gr_logging.cpp",
|
||||
"src/gr_segment.cpp",
|
||||
"src/gr_slot.cpp",
|
||||
"src/CmapCache.cpp",
|
||||
"src/Code.cpp",
|
||||
"src/Collider.cpp",
|
||||
"src/Decompressor.cpp",
|
||||
"src/Face.cpp",
|
||||
#'src/FileFace.cpp',
|
||||
"src/FeatureMap.cpp",
|
||||
"src/Font.cpp",
|
||||
"src/GlyphCache.cpp",
|
||||
"src/GlyphFace.cpp",
|
||||
"src/Intervals.cpp",
|
||||
"src/Justifier.cpp",
|
||||
"src/NameTable.cpp",
|
||||
"src/Pass.cpp",
|
||||
"src/Position.cpp",
|
||||
"src/Segment.cpp",
|
||||
"src/Silf.cpp",
|
||||
"src/Slot.cpp",
|
||||
"src/Sparse.cpp",
|
||||
"src/TtfUtil.cpp",
|
||||
"src/UtfCodec.cpp",
|
||||
"src/FileFace.cpp",
|
||||
"src/json.cpp",
|
||||
]
|
||||
if not env_graphite.msvc:
|
||||
thirdparty_sources += ["src/direct_machine.cpp"]
|
||||
else:
|
||||
thirdparty_sources += ["src/call_machine.cpp"]
|
||||
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
env_graphite.Prepend(CPPEXTPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"])
|
||||
env_graphite.Append(
|
||||
CCFLAGS=[
|
||||
"-DGRAPHITE2_STATIC",
|
||||
"-DGRAPHITE2_NTRACING",
|
||||
"-DGRAPHITE2_NFILEFACE",
|
||||
]
|
||||
)
|
||||
|
||||
lib = env_graphite.add_library("graphite_builtin", thirdparty_sources)
|
||||
thirdparty_obj += lib
|
||||
|
||||
# Needs to be appended to arrive after libscene in the linker call,
|
||||
# but we don't want it to arrive *after* system libs, so manual hack
|
||||
# LIBS contains first SCons Library objects ("SCons.Node.FS.File object")
|
||||
# and then plain strings for system library. We insert between the two.
|
||||
inserted = False
|
||||
for idx, linklib in enumerate(env["LIBS"]):
|
||||
if isinstance(linklib, (str, bytes)): # first system lib such as "X11", otherwise SCons lib object
|
||||
env["LIBS"].insert(idx, lib)
|
||||
inserted = True
|
||||
break
|
||||
if not inserted:
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
|
||||
if env["builtin_icu4c"]:
|
||||
env_icu = env_modules.Clone()
|
||||
env_icu.disable_warnings()
|
||||
|
||||
thirdparty_dir = "#thirdparty/icu4c/"
|
||||
thirdparty_sources = [
|
||||
"common/appendable.cpp",
|
||||
"common/bmpset.cpp",
|
||||
"common/brkeng.cpp",
|
||||
"common/brkiter.cpp",
|
||||
"common/bytesinkutil.cpp",
|
||||
"common/bytestream.cpp",
|
||||
"common/bytestrie.cpp",
|
||||
"common/bytestriebuilder.cpp",
|
||||
"common/bytestrieiterator.cpp",
|
||||
"common/caniter.cpp",
|
||||
"common/characterproperties.cpp",
|
||||
"common/chariter.cpp",
|
||||
"common/charstr.cpp",
|
||||
"common/cmemory.cpp",
|
||||
"common/cstr.cpp",
|
||||
"common/cstring.cpp",
|
||||
"common/cwchar.cpp",
|
||||
"common/dictbe.cpp",
|
||||
"common/dictionarydata.cpp",
|
||||
"common/dtintrv.cpp",
|
||||
"common/edits.cpp",
|
||||
"common/emojiprops.cpp",
|
||||
"common/errorcode.cpp",
|
||||
"common/filteredbrk.cpp",
|
||||
"common/filterednormalizer2.cpp",
|
||||
"common/icudataver.cpp",
|
||||
"common/icuplug.cpp",
|
||||
"common/loadednormalizer2impl.cpp",
|
||||
"common/localebuilder.cpp",
|
||||
"common/localematcher.cpp",
|
||||
"common/localeprioritylist.cpp",
|
||||
"common/locavailable.cpp",
|
||||
"common/locbased.cpp",
|
||||
"common/locdispnames.cpp",
|
||||
"common/locdistance.cpp",
|
||||
"common/locdspnm.cpp",
|
||||
"common/locid.cpp",
|
||||
"common/loclikely.cpp",
|
||||
"common/loclikelysubtags.cpp",
|
||||
"common/locmap.cpp",
|
||||
"common/locresdata.cpp",
|
||||
"common/locutil.cpp",
|
||||
"common/lsr.cpp",
|
||||
"common/lstmbe.cpp",
|
||||
"common/messagepattern.cpp",
|
||||
"common/mlbe.cpp",
|
||||
"common/normalizer2.cpp",
|
||||
"common/normalizer2impl.cpp",
|
||||
"common/normlzr.cpp",
|
||||
"common/parsepos.cpp",
|
||||
"common/patternprops.cpp",
|
||||
"common/pluralmap.cpp",
|
||||
"common/propname.cpp",
|
||||
"common/propsvec.cpp",
|
||||
"common/punycode.cpp",
|
||||
"common/putil.cpp",
|
||||
"common/rbbi.cpp",
|
||||
"common/rbbi_cache.cpp",
|
||||
"common/rbbidata.cpp",
|
||||
"common/rbbinode.cpp",
|
||||
"common/rbbirb.cpp",
|
||||
"common/rbbiscan.cpp",
|
||||
"common/rbbisetb.cpp",
|
||||
"common/rbbistbl.cpp",
|
||||
"common/rbbitblb.cpp",
|
||||
"common/resbund.cpp",
|
||||
"common/resbund_cnv.cpp",
|
||||
"common/resource.cpp",
|
||||
"common/restrace.cpp",
|
||||
"common/ruleiter.cpp",
|
||||
"common/schriter.cpp",
|
||||
"common/serv.cpp",
|
||||
"common/servlk.cpp",
|
||||
"common/servlkf.cpp",
|
||||
"common/servls.cpp",
|
||||
"common/servnotf.cpp",
|
||||
"common/servrbf.cpp",
|
||||
"common/servslkf.cpp",
|
||||
"common/sharedobject.cpp",
|
||||
"common/simpleformatter.cpp",
|
||||
"common/static_unicode_sets.cpp",
|
||||
"common/stringpiece.cpp",
|
||||
"common/stringtriebuilder.cpp",
|
||||
"common/uarrsort.cpp",
|
||||
"common/ubidi.cpp",
|
||||
"common/ubidi_props.cpp",
|
||||
"common/ubidiln.cpp",
|
||||
"common/ubiditransform.cpp",
|
||||
"common/ubidiwrt.cpp",
|
||||
"common/ubrk.cpp",
|
||||
"common/ucase.cpp",
|
||||
"common/ucasemap.cpp",
|
||||
"common/ucasemap_titlecase_brkiter.cpp",
|
||||
"common/ucat.cpp",
|
||||
"common/uchar.cpp",
|
||||
"common/ucharstrie.cpp",
|
||||
"common/ucharstriebuilder.cpp",
|
||||
"common/ucharstrieiterator.cpp",
|
||||
"common/uchriter.cpp",
|
||||
"common/ucln_cmn.cpp",
|
||||
"common/ucmndata.cpp",
|
||||
"common/ucnv.cpp",
|
||||
"common/ucnv2022.cpp",
|
||||
"common/ucnv_bld.cpp",
|
||||
"common/ucnv_cb.cpp",
|
||||
"common/ucnv_cnv.cpp",
|
||||
"common/ucnv_ct.cpp",
|
||||
"common/ucnv_err.cpp",
|
||||
"common/ucnv_ext.cpp",
|
||||
"common/ucnv_io.cpp",
|
||||
"common/ucnv_lmb.cpp",
|
||||
"common/ucnv_set.cpp",
|
||||
"common/ucnv_u16.cpp",
|
||||
"common/ucnv_u32.cpp",
|
||||
"common/ucnv_u7.cpp",
|
||||
"common/ucnv_u8.cpp",
|
||||
"common/ucnvbocu.cpp",
|
||||
"common/ucnvdisp.cpp",
|
||||
"common/ucnvhz.cpp",
|
||||
"common/ucnvisci.cpp",
|
||||
"common/ucnvlat1.cpp",
|
||||
"common/ucnvmbcs.cpp",
|
||||
"common/ucnvscsu.cpp",
|
||||
"common/ucnvsel.cpp",
|
||||
"common/ucol_swp.cpp",
|
||||
"common/ucptrie.cpp",
|
||||
"common/ucurr.cpp",
|
||||
"common/udata.cpp",
|
||||
"common/udatamem.cpp",
|
||||
"common/udataswp.cpp",
|
||||
"common/uenum.cpp",
|
||||
"common/uhash.cpp",
|
||||
"common/uhash_us.cpp",
|
||||
"common/uidna.cpp",
|
||||
"common/uinit.cpp",
|
||||
"common/uinvchar.cpp",
|
||||
"common/uiter.cpp",
|
||||
"common/ulist.cpp",
|
||||
"common/uloc.cpp",
|
||||
"common/uloc_keytype.cpp",
|
||||
"common/uloc_tag.cpp",
|
||||
"common/ulocale.cpp",
|
||||
"common/ulocbuilder.cpp",
|
||||
"common/umapfile.cpp",
|
||||
"common/umath.cpp",
|
||||
"common/umutablecptrie.cpp",
|
||||
"common/umutex.cpp",
|
||||
"common/unames.cpp",
|
||||
"common/unifiedcache.cpp",
|
||||
"common/unifilt.cpp",
|
||||
"common/unifunct.cpp",
|
||||
"common/uniset.cpp",
|
||||
"common/uniset_closure.cpp",
|
||||
"common/uniset_props.cpp",
|
||||
"common/unisetspan.cpp",
|
||||
"common/unistr.cpp",
|
||||
"common/unistr_case.cpp",
|
||||
"common/unistr_case_locale.cpp",
|
||||
"common/unistr_cnv.cpp",
|
||||
"common/unistr_props.cpp",
|
||||
"common/unistr_titlecase_brkiter.cpp",
|
||||
"common/unorm.cpp",
|
||||
"common/unormcmp.cpp",
|
||||
"common/uobject.cpp",
|
||||
"common/uprops.cpp",
|
||||
"common/ures_cnv.cpp",
|
||||
"common/uresbund.cpp",
|
||||
"common/uresdata.cpp",
|
||||
"common/usc_impl.cpp",
|
||||
"common/uscript.cpp",
|
||||
"common/uscript_props.cpp",
|
||||
"common/uset.cpp",
|
||||
"common/uset_props.cpp",
|
||||
"common/usetiter.cpp",
|
||||
# "common/ushape.cpp",
|
||||
"common/usprep.cpp",
|
||||
"common/ustack.cpp",
|
||||
"common/ustr_cnv.cpp",
|
||||
"common/ustr_titlecase_brkiter.cpp",
|
||||
"common/ustr_wcs.cpp",
|
||||
"common/ustrcase.cpp",
|
||||
"common/ustrcase_locale.cpp",
|
||||
"common/ustrenum.cpp",
|
||||
"common/ustrfmt.cpp",
|
||||
"common/ustring.cpp",
|
||||
"common/ustrtrns.cpp",
|
||||
"common/utext.cpp",
|
||||
"common/utf_impl.cpp",
|
||||
"common/util.cpp",
|
||||
"common/util_props.cpp",
|
||||
"common/utrace.cpp",
|
||||
"common/utrie.cpp",
|
||||
"common/utrie2.cpp",
|
||||
"common/utrie2_builder.cpp",
|
||||
"common/utrie_swap.cpp",
|
||||
"common/uts46.cpp",
|
||||
"common/utypes.cpp",
|
||||
"common/uvector.cpp",
|
||||
"common/uvectr32.cpp",
|
||||
"common/uvectr64.cpp",
|
||||
"common/wintz.cpp",
|
||||
"i18n/scriptset.cpp",
|
||||
"i18n/ucln_in.cpp",
|
||||
"i18n/uspoof.cpp",
|
||||
"i18n/uspoof_impl.cpp",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
if not env.editor_build:
|
||||
thirdparty_sources += ["icu_data/icudata_stub.cpp"]
|
||||
|
||||
env_icu.Prepend(CPPEXTPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
|
||||
env_icu.Append(
|
||||
CXXFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_COMMON_IMPLEMENTATION",
|
||||
"-DUCONFIG_NO_COLLATION",
|
||||
"-DUCONFIG_NO_CONVERSION",
|
||||
"-DUCONFIG_NO_FORMATTING",
|
||||
"-DUCONFIG_NO_SERVICE",
|
||||
"-DUCONFIG_NO_IDNA",
|
||||
"-DUCONFIG_NO_FILE_IO",
|
||||
"-DUCONFIG_NO_TRANSLITERATION",
|
||||
"-DUCONFIG_NO_REGULAR_EXPRESSIONS",
|
||||
"-DPKGDATA_MODE=static",
|
||||
"-DU_ENABLE_DYLOAD=0",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
]
|
||||
)
|
||||
env_text_server_adv.Append(
|
||||
CXXFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
]
|
||||
)
|
||||
if env.editor_build:
|
||||
env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"])
|
||||
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
|
||||
|
||||
lib = env_icu.add_library("icu_builtin", thirdparty_sources)
|
||||
thirdparty_obj += lib
|
||||
|
||||
if env.editor_build:
|
||||
icudata = env_icu.CommandNoCache(
|
||||
"#thirdparty/icu4c/icudata.gen.h",
|
||||
"#thirdparty/icu4c/icudt_godot.dat",
|
||||
env.Run(text_server_adv_builders.make_icu_data),
|
||||
)
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/icu4c/"])
|
||||
env_icu.Depends(lib, icudata)
|
||||
|
||||
# Needs to be appended to arrive after libscene in the linker call,
|
||||
# but we don't want it to arrive *after* system libs, so manual hack
|
||||
# LIBS contains first SCons Library objects ("SCons.Node.FS.File object")
|
||||
# and then plain strings for system library. We insert between the two.
|
||||
inserted = False
|
||||
for idx, linklib in enumerate(env["LIBS"]):
|
||||
if isinstance(linklib, (str, bytes)): # first system lib such as "X11", otherwise SCons lib object
|
||||
env["LIBS"].insert(idx, lib)
|
||||
inserted = True
|
||||
break
|
||||
if not inserted:
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
module_obj = []
|
||||
|
||||
if env["builtin_msdfgen"] and msdfgen_enabled:
|
||||
env_text_server_adv.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/msdfgen"])
|
||||
|
||||
if env["builtin_freetype"] and freetype_enabled:
|
||||
env_text_server_adv.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/freetype/include"])
|
||||
|
||||
if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
|
||||
env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/graphite/include"])
|
||||
|
||||
env_text_server_adv.add_source_files(module_obj, "*.cpp")
|
||||
env.modules_sources += module_obj
|
||||
|
||||
# Needed to force rebuilding the module files when the thirdparty library is updated.
|
||||
env.Depends(module_obj, thirdparty_obj)
|
25
modules/text_server_adv/config.py
Normal file
25
modules/text_server_adv/config.py
Normal file
@@ -0,0 +1,25 @@
|
||||
def can_build(env, platform):
|
||||
env.module_add_dependencies("text_server_adv", ["freetype", "msdfgen", "svg"], True)
|
||||
return True
|
||||
|
||||
|
||||
def get_opts(platform):
|
||||
from SCons.Variables import BoolVariable
|
||||
|
||||
return [
|
||||
BoolVariable("graphite", "Enable SIL Graphite smart fonts support", True),
|
||||
]
|
||||
|
||||
|
||||
def configure(env):
|
||||
pass
|
||||
|
||||
|
||||
def get_doc_classes():
|
||||
return [
|
||||
"TextServerAdvanced",
|
||||
]
|
||||
|
||||
|
||||
def get_doc_path():
|
||||
return "doc_classes"
|
11
modules/text_server_adv/doc_classes/TextServerAdvanced.xml
Normal file
11
modules/text_server_adv/doc_classes/TextServerAdvanced.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="TextServerAdvanced" inherits="TextServerExtension" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
An advanced text server with support for BiDi, complex text layout, and contextual OpenType features. Used in Godot by default.
|
||||
</brief_description>
|
||||
<description>
|
||||
An implementation of [TextServer] that uses HarfBuzz, ICU and SIL Graphite to support BiDi, complex text layouts and contextual OpenType features. This is Godot's default primary [TextServer] interface.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
</class>
|
767
modules/text_server_adv/gdextension_build/SConstruct
Normal file
767
modules/text_server_adv/gdextension_build/SConstruct
Normal file
@@ -0,0 +1,767 @@
|
||||
#!/usr/bin/env python
|
||||
# ruff: noqa: F821
|
||||
|
||||
import methods
|
||||
|
||||
# For the reference:
|
||||
# - CCFLAGS are compilation flags shared between C and C++
|
||||
# - CFLAGS are for C-specific compilation flags
|
||||
# - CXXFLAGS are for C++-specific compilation flags
|
||||
# - CPPFLAGS are for pre-processor flags
|
||||
# - CPPDEFINES are for pre-processor defines
|
||||
# - LINKFLAGS are for linking flags
|
||||
|
||||
env = SConscript("./godot-cpp/SConstruct")
|
||||
env.__class__.disable_warnings = methods.disable_warnings
|
||||
|
||||
opts = Variables([], ARGUMENTS)
|
||||
opts.Add(BoolVariable("brotli_enabled", "Use Brotli library", True))
|
||||
opts.Add(BoolVariable("freetype_enabled", "Use FreeType library", True))
|
||||
opts.Add(BoolVariable("msdfgen_enabled", "Use MSDFgen library (require FreeType)", True))
|
||||
opts.Add(BoolVariable("graphite_enabled", "Use Graphite library (require FreeType)", True))
|
||||
opts.Add(BoolVariable("thorvg_enabled", "Use ThorVG library (require FreeType)", True))
|
||||
opts.Add(BoolVariable("static_icu_data", "Use built-in ICU data", True))
|
||||
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
|
||||
|
||||
opts.Update(env)
|
||||
|
||||
if env["platform"] == "windows" and not env["use_mingw"]:
|
||||
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
|
||||
|
||||
# ThorVG
|
||||
if env["thorvg_enabled"] and env["freetype_enabled"]:
|
||||
env_tvg = env.Clone()
|
||||
env_tvg.disable_warnings()
|
||||
|
||||
thirdparty_tvg_dir = "../../../thirdparty/thorvg/"
|
||||
thirdparty_tvg_sources = [
|
||||
# common
|
||||
"src/common/tvgCompressor.cpp",
|
||||
"src/common/tvgLines.cpp",
|
||||
"src/common/tvgMath.cpp",
|
||||
"src/common/tvgStr.cpp",
|
||||
# SVG parser
|
||||
"src/loaders/svg/tvgSvgCssStyle.cpp",
|
||||
"src/loaders/svg/tvgSvgLoader.cpp",
|
||||
"src/loaders/svg/tvgSvgPath.cpp",
|
||||
"src/loaders/svg/tvgSvgSceneBuilder.cpp",
|
||||
"src/loaders/svg/tvgSvgUtil.cpp",
|
||||
"src/loaders/svg/tvgXmlParser.cpp",
|
||||
"src/loaders/raw/tvgRawLoader.cpp",
|
||||
# image loaders
|
||||
"src/loaders/external_png/tvgPngLoader.cpp",
|
||||
"src/loaders/jpg/tvgJpgd.cpp",
|
||||
"src/loaders/jpg/tvgJpgLoader.cpp",
|
||||
# renderer common
|
||||
"src/renderer/tvgAccessor.cpp",
|
||||
# "src/renderer/tvgAnimation.cpp",
|
||||
"src/renderer/tvgCanvas.cpp",
|
||||
"src/renderer/tvgFill.cpp",
|
||||
# "src/renderer/tvgGlCanvas.cpp",
|
||||
"src/renderer/tvgInitializer.cpp",
|
||||
"src/renderer/tvgLoader.cpp",
|
||||
"src/renderer/tvgPaint.cpp",
|
||||
"src/renderer/tvgPicture.cpp",
|
||||
"src/renderer/tvgRender.cpp",
|
||||
# "src/renderer/tvgSaver.cpp",
|
||||
"src/renderer/tvgScene.cpp",
|
||||
"src/renderer/tvgShape.cpp",
|
||||
"src/renderer/tvgSwCanvas.cpp",
|
||||
"src/renderer/tvgTaskScheduler.cpp",
|
||||
"src/renderer/tvgText.cpp",
|
||||
# "src/renderer/tvgWgCanvas.cpp",
|
||||
# renderer sw_engine
|
||||
"src/renderer/sw_engine/tvgSwFill.cpp",
|
||||
"src/renderer/sw_engine/tvgSwImage.cpp",
|
||||
"src/renderer/sw_engine/tvgSwMath.cpp",
|
||||
"src/renderer/sw_engine/tvgSwMemPool.cpp",
|
||||
"src/renderer/sw_engine/tvgSwRaster.cpp",
|
||||
"src/renderer/sw_engine/tvgSwRenderer.cpp",
|
||||
"src/renderer/sw_engine/tvgSwRle.cpp",
|
||||
"src/renderer/sw_engine/tvgSwShape.cpp",
|
||||
"src/renderer/sw_engine/tvgSwStroke.cpp",
|
||||
]
|
||||
thirdparty_tvg_sources = [thirdparty_tvg_dir + file for file in thirdparty_tvg_sources]
|
||||
|
||||
env_tvg.Append(
|
||||
CPPPATH=[
|
||||
"../../../thirdparty/thorvg/inc",
|
||||
"../../../thirdparty/thorvg/src/common",
|
||||
"../../../thirdparty/thorvg/src/renderer",
|
||||
"../../../thirdparty/thorvg/src/renderer/sw_engine",
|
||||
"../../../thirdparty/thorvg/src/loaders/svg",
|
||||
"../../../thirdparty/thorvg/src/loaders/raw",
|
||||
"../../../thirdparty/thorvg/src/loaders/external_png",
|
||||
"../../../thirdparty/thorvg/src/loaders/jpg",
|
||||
"../../../thirdparty/libpng",
|
||||
]
|
||||
)
|
||||
|
||||
# Enable ThorVG static object linking.
|
||||
env_tvg.Append(CPPDEFINES=["TVG_STATIC"])
|
||||
|
||||
env.Append(
|
||||
CPPPATH=[
|
||||
"../../../thirdparty/thorvg/inc",
|
||||
"../../../thirdparty/thorvg/src/common",
|
||||
"../../../thirdparty/thorvg/src/renderer",
|
||||
]
|
||||
)
|
||||
env.Append(CPPDEFINES=["MODULE_SVG_ENABLED"])
|
||||
|
||||
lib = env_tvg.Library(
|
||||
f"tvg_builtin{env['suffix']}{env['LIBSUFFIX']}",
|
||||
thirdparty_tvg_sources,
|
||||
)
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
# MSDFGEN
|
||||
if env["msdfgen_enabled"] and env["freetype_enabled"]:
|
||||
env_msdfgen = env.Clone()
|
||||
env_msdfgen.disable_warnings()
|
||||
|
||||
thirdparty_msdfgen_dir = "../../../thirdparty/msdfgen/"
|
||||
thirdparty_msdfgen_sources = [
|
||||
"core/Contour.cpp",
|
||||
"core/DistanceMapping.cpp",
|
||||
"core/EdgeHolder.cpp",
|
||||
"core/MSDFErrorCorrection.cpp",
|
||||
"core/Projection.cpp",
|
||||
"core/Scanline.cpp",
|
||||
"core/Shape.cpp",
|
||||
"core/contour-combiners.cpp",
|
||||
"core/edge-coloring.cpp",
|
||||
"core/edge-segments.cpp",
|
||||
"core/edge-selectors.cpp",
|
||||
"core/equation-solver.cpp",
|
||||
# "core/export-svg.cpp",
|
||||
"core/msdf-error-correction.cpp",
|
||||
"core/msdfgen.cpp",
|
||||
"core/rasterization.cpp",
|
||||
"core/render-sdf.cpp",
|
||||
# "core/save-bmp.cpp",
|
||||
# "core/save-fl32.cpp",
|
||||
# "core/save-rgba.cpp",
|
||||
# "core/save-tiff.cpp",
|
||||
"core/sdf-error-estimation.cpp",
|
||||
"core/shape-description.cpp",
|
||||
]
|
||||
thirdparty_msdfgen_sources = [thirdparty_msdfgen_dir + file for file in thirdparty_msdfgen_sources]
|
||||
|
||||
env_msdfgen.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
|
||||
env_msdfgen.Append(CPPPATH=["../../../thirdparty/freetype/include", "../../../thirdparty/msdfgen"])
|
||||
env.Append(CPPPATH=["../../../thirdparty/msdfgen"])
|
||||
env.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
|
||||
env.Append(CPPDEFINES=["MODULE_MSDFGEN_ENABLED"])
|
||||
|
||||
lib = env_msdfgen.Library(
|
||||
f"msdfgen_builtin{env['suffix']}{env['LIBSUFFIX']}",
|
||||
thirdparty_msdfgen_sources,
|
||||
)
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
# FreeType
|
||||
if env["freetype_enabled"]:
|
||||
env_freetype = env.Clone()
|
||||
env_freetype.disable_warnings()
|
||||
|
||||
thirdparty_freetype_dir = "../../../thirdparty/freetype/"
|
||||
thirdparty_freetype_sources = [
|
||||
"src/autofit/autofit.c",
|
||||
"src/base/ftbase.c",
|
||||
"src/base/ftbbox.c",
|
||||
"src/base/ftbdf.c",
|
||||
"src/base/ftbitmap.c",
|
||||
"src/base/ftcid.c",
|
||||
"src/base/ftdebug.c",
|
||||
"src/base/ftfstype.c",
|
||||
"src/base/ftgasp.c",
|
||||
"src/base/ftglyph.c",
|
||||
"src/base/ftgxval.c",
|
||||
"src/base/ftinit.c",
|
||||
"src/base/ftmm.c",
|
||||
"src/base/ftotval.c",
|
||||
"src/base/ftpatent.c",
|
||||
"src/base/ftpfr.c",
|
||||
"src/base/ftstroke.c",
|
||||
"src/base/ftsynth.c",
|
||||
"src/base/ftsystem.c",
|
||||
"src/base/fttype1.c",
|
||||
"src/base/ftwinfnt.c",
|
||||
"src/bdf/bdf.c",
|
||||
"src/bzip2/ftbzip2.c",
|
||||
"src/cache/ftcache.c",
|
||||
"src/cff/cff.c",
|
||||
"src/cid/type1cid.c",
|
||||
"src/gxvalid/gxvalid.c",
|
||||
"src/gzip/ftgzip.c",
|
||||
"src/lzw/ftlzw.c",
|
||||
"src/otvalid/otvalid.c",
|
||||
"src/pcf/pcf.c",
|
||||
"src/pfr/pfr.c",
|
||||
"src/psaux/psaux.c",
|
||||
"src/pshinter/pshinter.c",
|
||||
"src/psnames/psnames.c",
|
||||
"src/raster/raster.c",
|
||||
"src/sdf/sdf.c",
|
||||
"src/svg/svg.c",
|
||||
"src/smooth/smooth.c",
|
||||
"src/truetype/truetype.c",
|
||||
"src/type1/type1.c",
|
||||
"src/type42/type42.c",
|
||||
"src/winfonts/winfnt.c",
|
||||
"src/sfnt/sfnt.c",
|
||||
]
|
||||
thirdparty_freetype_sources = [thirdparty_freetype_dir + file for file in thirdparty_freetype_sources]
|
||||
|
||||
thirdparty_png_dir = "../../../thirdparty/libpng/"
|
||||
thirdparty_png_sources = [
|
||||
"png.c",
|
||||
"pngerror.c",
|
||||
"pngget.c",
|
||||
"pngmem.c",
|
||||
"pngpread.c",
|
||||
"pngread.c",
|
||||
"pngrio.c",
|
||||
"pngrtran.c",
|
||||
"pngrutil.c",
|
||||
"pngset.c",
|
||||
"pngtrans.c",
|
||||
"pngwio.c",
|
||||
"pngwrite.c",
|
||||
"pngwtran.c",
|
||||
"pngwutil.c",
|
||||
]
|
||||
thirdparty_freetype_sources += [thirdparty_png_dir + file for file in thirdparty_png_sources]
|
||||
|
||||
thirdparty_zlib_dir = "../../../thirdparty/zlib/"
|
||||
thirdparty_zlib_sources = [
|
||||
"adler32.c",
|
||||
"compress.c",
|
||||
"crc32.c",
|
||||
"deflate.c",
|
||||
"inffast.c",
|
||||
"inflate.c",
|
||||
"inftrees.c",
|
||||
"trees.c",
|
||||
"uncompr.c",
|
||||
"zutil.c",
|
||||
]
|
||||
thirdparty_freetype_sources += [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
|
||||
|
||||
if env["brotli_enabled"]:
|
||||
thirdparty_brotli_dir = "../../../thirdparty/brotli/"
|
||||
thirdparty_brotli_sources = [
|
||||
"common/constants.c",
|
||||
"common/context.c",
|
||||
"common/dictionary.c",
|
||||
"common/platform.c",
|
||||
"common/shared_dictionary.c",
|
||||
"common/transform.c",
|
||||
"dec/bit_reader.c",
|
||||
"dec/decode.c",
|
||||
"dec/huffman.c",
|
||||
"dec/state.c",
|
||||
]
|
||||
thirdparty_freetype_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
|
||||
env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
|
||||
env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
|
||||
env.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
|
||||
|
||||
env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir])
|
||||
env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"])
|
||||
|
||||
env_freetype.Append(
|
||||
CPPDEFINES=[
|
||||
"FT2_BUILD_LIBRARY",
|
||||
"FT_CONFIG_OPTION_USE_PNG",
|
||||
"FT_CONFIG_OPTION_SYSTEM_ZLIB",
|
||||
]
|
||||
)
|
||||
if env.dev_build:
|
||||
env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"])
|
||||
|
||||
env.Append(CPPDEFINES=["MODULE_FREETYPE_ENABLED"])
|
||||
|
||||
lib = env_freetype.Library(
|
||||
f"freetype_builtin{env['suffix']}{env['LIBSUFFIX']}",
|
||||
thirdparty_freetype_sources,
|
||||
)
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
# HarfBuzz
|
||||
env_harfbuzz = env.Clone()
|
||||
env_harfbuzz.disable_warnings()
|
||||
|
||||
thirdparty_harfbuzz_dir = "../../../thirdparty/harfbuzz/"
|
||||
thirdparty_harfbuzz_sources = [
|
||||
"src/hb-aat-layout.cc",
|
||||
"src/hb-aat-map.cc",
|
||||
"src/hb-blob.cc",
|
||||
"src/hb-buffer-serialize.cc",
|
||||
"src/hb-buffer-verify.cc",
|
||||
"src/hb-buffer.cc",
|
||||
# "src/hb-cairo-utils.cc",
|
||||
# "src/hb-cairo.cc",
|
||||
"src/hb-common.cc",
|
||||
# "src/hb-coretext-font.cc",
|
||||
# "src/hb-coretext-shape.cc",
|
||||
# "src/hb-directwrite.cc",
|
||||
"src/hb-draw.cc",
|
||||
"src/hb-face-builder.cc",
|
||||
"src/hb-face.cc",
|
||||
"src/hb-fallback-shape.cc",
|
||||
"src/hb-font.cc",
|
||||
# "src/hb-gdi.cc",
|
||||
# "src/hb-glib.cc",
|
||||
# "src/hb-gobject-structs.cc",
|
||||
"src/hb-icu.cc",
|
||||
"src/hb-map.cc",
|
||||
"src/hb-number.cc",
|
||||
"src/hb-ot-cff1-table.cc",
|
||||
"src/hb-ot-cff2-table.cc",
|
||||
"src/hb-ot-color.cc",
|
||||
"src/hb-ot-face.cc",
|
||||
"src/hb-ot-font.cc",
|
||||
"src/hb-ot-layout.cc",
|
||||
"src/hb-ot-map.cc",
|
||||
"src/hb-ot-math.cc",
|
||||
"src/hb-ot-meta.cc",
|
||||
"src/hb-ot-metrics.cc",
|
||||
"src/hb-ot-name.cc",
|
||||
"src/hb-ot-shaper-arabic.cc",
|
||||
"src/hb-ot-shaper-default.cc",
|
||||
"src/hb-ot-shaper-hangul.cc",
|
||||
"src/hb-ot-shaper-hebrew.cc",
|
||||
"src/hb-ot-shaper-indic-table.cc",
|
||||
"src/hb-ot-shaper-indic.cc",
|
||||
"src/hb-ot-shaper-khmer.cc",
|
||||
"src/hb-ot-shaper-myanmar.cc",
|
||||
"src/hb-ot-shaper-syllabic.cc",
|
||||
"src/hb-ot-shaper-thai.cc",
|
||||
"src/hb-ot-shaper-use.cc",
|
||||
"src/hb-ot-shaper-vowel-constraints.cc",
|
||||
"src/hb-ot-shape-fallback.cc",
|
||||
"src/hb-ot-shape-normalize.cc",
|
||||
"src/hb-ot-shape.cc",
|
||||
"src/hb-ot-tag.cc",
|
||||
"src/hb-ot-var.cc",
|
||||
"src/hb-outline.cc",
|
||||
"src/hb-paint-bounded.cc",
|
||||
"src/hb-paint-extents.cc",
|
||||
"src/hb-paint.cc",
|
||||
"src/hb-set.cc",
|
||||
"src/hb-shape-plan.cc",
|
||||
"src/hb-shape.cc",
|
||||
"src/hb-shaper.cc",
|
||||
"src/hb-static.cc",
|
||||
"src/hb-style.cc",
|
||||
"src/hb-subset-cff-common.cc",
|
||||
"src/hb-subset-cff1.cc",
|
||||
"src/hb-subset-cff2.cc",
|
||||
"src/hb-subset-input.cc",
|
||||
"src/hb-subset-instancer-iup.cc",
|
||||
"src/hb-subset-instancer-solver.cc",
|
||||
"src/hb-subset-plan.cc",
|
||||
"src/hb-subset-serialize.cc",
|
||||
"src/hb-subset.cc",
|
||||
"src/hb-ucd.cc",
|
||||
"src/hb-unicode.cc",
|
||||
# "src/hb-uniscribe.cc",
|
||||
"src/OT/Var/VARC/VARC.cc",
|
||||
]
|
||||
|
||||
if env["freetype_enabled"]:
|
||||
thirdparty_harfbuzz_sources += [
|
||||
"src/hb-ft.cc",
|
||||
"src/hb-graphite2.cc",
|
||||
]
|
||||
thirdparty_harfbuzz_sources = [thirdparty_harfbuzz_dir + file for file in thirdparty_harfbuzz_sources]
|
||||
|
||||
env_harfbuzz.Append(
|
||||
CPPPATH=[
|
||||
"../../../thirdparty/harfbuzz/src",
|
||||
"../../../thirdparty/icu4c/common/",
|
||||
"../../../thirdparty/icu4c/i18n/",
|
||||
]
|
||||
)
|
||||
|
||||
if env["freetype_enabled"]:
|
||||
env_harfbuzz.Append(
|
||||
CPPPATH=[
|
||||
"../../../thirdparty/freetype/include",
|
||||
"../../../thirdparty/graphite/include",
|
||||
]
|
||||
)
|
||||
|
||||
if env["platform"] == "android" or env["platform"] == "linuxbsd":
|
||||
env_harfbuzz.Append(CCFLAGS=["-DHAVE_PTHREAD"])
|
||||
|
||||
env_harfbuzz.Append(
|
||||
CCFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
"-DHAVE_ICU_BUILTIN",
|
||||
"-DHAVE_ICU",
|
||||
]
|
||||
)
|
||||
|
||||
if env["freetype_enabled"]:
|
||||
env_harfbuzz.Append(
|
||||
CCFLAGS=[
|
||||
"-DHAVE_FREETYPE",
|
||||
"-DHAVE_GRAPHITE2",
|
||||
"-DGRAPHITE2_STATIC",
|
||||
]
|
||||
)
|
||||
|
||||
env.Append(CPPPATH=["../../../thirdparty/harfbuzz/src"])
|
||||
|
||||
lib = env_harfbuzz.Library(
|
||||
f"harfbuzz_builtin{env['suffix']}{env['LIBSUFFIX']}",
|
||||
thirdparty_harfbuzz_sources,
|
||||
)
|
||||
env.Prepend(LIBS=[lib])
|
||||
|
||||
# Graphite
|
||||
if env["graphite_enabled"] and env["freetype_enabled"]:
|
||||
env_graphite = env.Clone()
|
||||
env_graphite.disable_warnings()
|
||||
|
||||
thirdparty_graphite_dir = "../../../thirdparty/graphite/"
|
||||
thirdparty_graphite_sources = [
|
||||
"src/gr_char_info.cpp",
|
||||
"src/gr_face.cpp",
|
||||
"src/gr_features.cpp",
|
||||
"src/gr_font.cpp",
|
||||
"src/gr_logging.cpp",
|
||||
"src/gr_segment.cpp",
|
||||
"src/gr_slot.cpp",
|
||||
"src/CmapCache.cpp",
|
||||
"src/Code.cpp",
|
||||
"src/Collider.cpp",
|
||||
"src/Decompressor.cpp",
|
||||
"src/Face.cpp",
|
||||
#'src/FileFace.cpp',
|
||||
"src/FeatureMap.cpp",
|
||||
"src/Font.cpp",
|
||||
"src/GlyphCache.cpp",
|
||||
"src/GlyphFace.cpp",
|
||||
"src/Intervals.cpp",
|
||||
"src/Justifier.cpp",
|
||||
"src/NameTable.cpp",
|
||||
"src/Pass.cpp",
|
||||
"src/Position.cpp",
|
||||
"src/Segment.cpp",
|
||||
"src/Silf.cpp",
|
||||
"src/Slot.cpp",
|
||||
"src/Sparse.cpp",
|
||||
"src/TtfUtil.cpp",
|
||||
"src/UtfCodec.cpp",
|
||||
"src/FileFace.cpp",
|
||||
"src/json.cpp",
|
||||
]
|
||||
if env["platform"] != "windows" or env["use_mingw"]:
|
||||
thirdparty_graphite_sources += ["src/direct_machine.cpp"]
|
||||
else:
|
||||
thirdparty_graphite_sources += ["src/call_machine.cpp"]
|
||||
|
||||
thirdparty_graphite_sources = [thirdparty_graphite_dir + file for file in thirdparty_graphite_sources]
|
||||
|
||||
env_graphite.Append(CPPPATH=["../../../thirdparty/graphite/src", "../../../thirdparty/graphite/include"])
|
||||
env_graphite.Append(
|
||||
CCFLAGS=[
|
||||
"-DGRAPHITE2_STATIC",
|
||||
"-DGRAPHITE2_NTRACING",
|
||||
"-DGRAPHITE2_NFILEFACE",
|
||||
]
|
||||
)
|
||||
|
||||
lib = env_graphite.Library(
|
||||
f"graphite_builtin{env['suffix']}{env['LIBSUFFIX']}",
|
||||
thirdparty_graphite_sources,
|
||||
)
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
# ICU
|
||||
env_icu = env.Clone()
|
||||
env_icu.disable_warnings()
|
||||
|
||||
thirdparty_icu_dir = "../../../thirdparty/icu4c/"
|
||||
thirdparty_icu_sources = [
|
||||
"common/appendable.cpp",
|
||||
"common/bmpset.cpp",
|
||||
"common/brkeng.cpp",
|
||||
"common/brkiter.cpp",
|
||||
"common/bytesinkutil.cpp",
|
||||
"common/bytestream.cpp",
|
||||
"common/bytestrie.cpp",
|
||||
"common/bytestriebuilder.cpp",
|
||||
"common/bytestrieiterator.cpp",
|
||||
"common/caniter.cpp",
|
||||
"common/characterproperties.cpp",
|
||||
"common/chariter.cpp",
|
||||
"common/charstr.cpp",
|
||||
"common/cmemory.cpp",
|
||||
"common/cstr.cpp",
|
||||
"common/cstring.cpp",
|
||||
"common/cwchar.cpp",
|
||||
"common/dictbe.cpp",
|
||||
"common/dictionarydata.cpp",
|
||||
"common/dtintrv.cpp",
|
||||
"common/edits.cpp",
|
||||
"common/emojiprops.cpp",
|
||||
"common/errorcode.cpp",
|
||||
"common/filteredbrk.cpp",
|
||||
"common/filterednormalizer2.cpp",
|
||||
"common/icudataver.cpp",
|
||||
"common/icuplug.cpp",
|
||||
"common/loadednormalizer2impl.cpp",
|
||||
"common/localebuilder.cpp",
|
||||
"common/localematcher.cpp",
|
||||
"common/localeprioritylist.cpp",
|
||||
"common/locavailable.cpp",
|
||||
"common/locbased.cpp",
|
||||
"common/locdispnames.cpp",
|
||||
"common/locdistance.cpp",
|
||||
"common/locdspnm.cpp",
|
||||
"common/locid.cpp",
|
||||
"common/loclikely.cpp",
|
||||
"common/loclikelysubtags.cpp",
|
||||
"common/locmap.cpp",
|
||||
"common/locresdata.cpp",
|
||||
"common/locutil.cpp",
|
||||
"common/lsr.cpp",
|
||||
"common/lstmbe.cpp",
|
||||
"common/messagepattern.cpp",
|
||||
"common/mlbe.cpp",
|
||||
"common/normalizer2.cpp",
|
||||
"common/normalizer2impl.cpp",
|
||||
"common/normlzr.cpp",
|
||||
"common/parsepos.cpp",
|
||||
"common/patternprops.cpp",
|
||||
"common/pluralmap.cpp",
|
||||
"common/propname.cpp",
|
||||
"common/propsvec.cpp",
|
||||
"common/punycode.cpp",
|
||||
"common/putil.cpp",
|
||||
"common/rbbi.cpp",
|
||||
"common/rbbi_cache.cpp",
|
||||
"common/rbbidata.cpp",
|
||||
"common/rbbinode.cpp",
|
||||
"common/rbbirb.cpp",
|
||||
"common/rbbiscan.cpp",
|
||||
"common/rbbisetb.cpp",
|
||||
"common/rbbistbl.cpp",
|
||||
"common/rbbitblb.cpp",
|
||||
"common/resbund.cpp",
|
||||
"common/resbund_cnv.cpp",
|
||||
"common/resource.cpp",
|
||||
"common/restrace.cpp",
|
||||
"common/ruleiter.cpp",
|
||||
"common/schriter.cpp",
|
||||
"common/serv.cpp",
|
||||
"common/servlk.cpp",
|
||||
"common/servlkf.cpp",
|
||||
"common/servls.cpp",
|
||||
"common/servnotf.cpp",
|
||||
"common/servrbf.cpp",
|
||||
"common/servslkf.cpp",
|
||||
"common/sharedobject.cpp",
|
||||
"common/simpleformatter.cpp",
|
||||
"common/static_unicode_sets.cpp",
|
||||
"common/stringpiece.cpp",
|
||||
"common/stringtriebuilder.cpp",
|
||||
"common/uarrsort.cpp",
|
||||
"common/ubidi.cpp",
|
||||
"common/ubidi_props.cpp",
|
||||
"common/ubidiln.cpp",
|
||||
"common/ubiditransform.cpp",
|
||||
"common/ubidiwrt.cpp",
|
||||
"common/ubrk.cpp",
|
||||
"common/ucase.cpp",
|
||||
"common/ucasemap.cpp",
|
||||
"common/ucasemap_titlecase_brkiter.cpp",
|
||||
"common/ucat.cpp",
|
||||
"common/uchar.cpp",
|
||||
"common/ucharstrie.cpp",
|
||||
"common/ucharstriebuilder.cpp",
|
||||
"common/ucharstrieiterator.cpp",
|
||||
"common/uchriter.cpp",
|
||||
"common/ucln_cmn.cpp",
|
||||
"common/ucmndata.cpp",
|
||||
"common/ucnv.cpp",
|
||||
"common/ucnv2022.cpp",
|
||||
"common/ucnv_bld.cpp",
|
||||
"common/ucnv_cb.cpp",
|
||||
"common/ucnv_cnv.cpp",
|
||||
"common/ucnv_ct.cpp",
|
||||
"common/ucnv_err.cpp",
|
||||
"common/ucnv_ext.cpp",
|
||||
"common/ucnv_io.cpp",
|
||||
"common/ucnv_lmb.cpp",
|
||||
"common/ucnv_set.cpp",
|
||||
"common/ucnv_u16.cpp",
|
||||
"common/ucnv_u32.cpp",
|
||||
"common/ucnv_u7.cpp",
|
||||
"common/ucnv_u8.cpp",
|
||||
"common/ucnvbocu.cpp",
|
||||
"common/ucnvdisp.cpp",
|
||||
"common/ucnvhz.cpp",
|
||||
"common/ucnvisci.cpp",
|
||||
"common/ucnvlat1.cpp",
|
||||
"common/ucnvmbcs.cpp",
|
||||
"common/ucnvscsu.cpp",
|
||||
"common/ucnvsel.cpp",
|
||||
"common/ucol_swp.cpp",
|
||||
"common/ucptrie.cpp",
|
||||
"common/ucurr.cpp",
|
||||
"common/udata.cpp",
|
||||
"common/udatamem.cpp",
|
||||
"common/udataswp.cpp",
|
||||
"common/uenum.cpp",
|
||||
"common/uhash.cpp",
|
||||
"common/uhash_us.cpp",
|
||||
"common/uidna.cpp",
|
||||
"common/uinit.cpp",
|
||||
"common/uinvchar.cpp",
|
||||
"common/uiter.cpp",
|
||||
"common/ulist.cpp",
|
||||
"common/uloc.cpp",
|
||||
"common/uloc_keytype.cpp",
|
||||
"common/uloc_tag.cpp",
|
||||
"common/ulocale.cpp",
|
||||
"common/ulocbuilder.cpp",
|
||||
"common/umapfile.cpp",
|
||||
"common/umath.cpp",
|
||||
"common/umutablecptrie.cpp",
|
||||
"common/umutex.cpp",
|
||||
"common/unames.cpp",
|
||||
"common/unifiedcache.cpp",
|
||||
"common/unifilt.cpp",
|
||||
"common/unifunct.cpp",
|
||||
"common/uniset.cpp",
|
||||
"common/uniset_closure.cpp",
|
||||
"common/uniset_props.cpp",
|
||||
"common/unisetspan.cpp",
|
||||
"common/unistr.cpp",
|
||||
"common/unistr_case.cpp",
|
||||
"common/unistr_case_locale.cpp",
|
||||
"common/unistr_cnv.cpp",
|
||||
"common/unistr_props.cpp",
|
||||
"common/unistr_titlecase_brkiter.cpp",
|
||||
"common/unorm.cpp",
|
||||
"common/unormcmp.cpp",
|
||||
"common/uobject.cpp",
|
||||
"common/uprops.cpp",
|
||||
"common/ures_cnv.cpp",
|
||||
"common/uresbund.cpp",
|
||||
"common/uresdata.cpp",
|
||||
"common/usc_impl.cpp",
|
||||
"common/uscript.cpp",
|
||||
"common/uscript_props.cpp",
|
||||
"common/uset.cpp",
|
||||
"common/uset_props.cpp",
|
||||
"common/usetiter.cpp",
|
||||
# "common/ushape.cpp",
|
||||
"common/usprep.cpp",
|
||||
"common/ustack.cpp",
|
||||
"common/ustr_cnv.cpp",
|
||||
"common/ustr_titlecase_brkiter.cpp",
|
||||
"common/ustr_wcs.cpp",
|
||||
"common/ustrcase.cpp",
|
||||
"common/ustrcase_locale.cpp",
|
||||
"common/ustrenum.cpp",
|
||||
"common/ustrfmt.cpp",
|
||||
"common/ustring.cpp",
|
||||
"common/ustrtrns.cpp",
|
||||
"common/utext.cpp",
|
||||
"common/utf_impl.cpp",
|
||||
"common/util.cpp",
|
||||
"common/util_props.cpp",
|
||||
"common/utrace.cpp",
|
||||
"common/utrie.cpp",
|
||||
"common/utrie2.cpp",
|
||||
"common/utrie2_builder.cpp",
|
||||
"common/utrie_swap.cpp",
|
||||
"common/uts46.cpp",
|
||||
"common/utypes.cpp",
|
||||
"common/uvector.cpp",
|
||||
"common/uvectr32.cpp",
|
||||
"common/uvectr64.cpp",
|
||||
"common/wintz.cpp",
|
||||
"i18n/scriptset.cpp",
|
||||
"i18n/ucln_in.cpp",
|
||||
"i18n/uspoof.cpp",
|
||||
"i18n/uspoof_impl.cpp",
|
||||
]
|
||||
thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources]
|
||||
|
||||
if env["static_icu_data"]:
|
||||
env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/icudt_godot.dat")
|
||||
env_icu.Command(
|
||||
"../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/icudt_godot.dat", methods.make_icu_data
|
||||
)
|
||||
env.Append(CXXFLAGS=["-DICU_STATIC_DATA"])
|
||||
env.Append(CPPPATH=["../../../thirdparty/icu4c/"])
|
||||
else:
|
||||
thirdparty_icu_sources += ["../icu_data/icudata_stub.cpp"]
|
||||
|
||||
env_icu.Append(CPPPATH=["../../../thirdparty/icu4c/common/", "../../../thirdparty/icu4c/i18n/"])
|
||||
env_icu.Append(
|
||||
CXXFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_COMMON_IMPLEMENTATION",
|
||||
"-DUCONFIG_NO_COLLATION",
|
||||
"-DUCONFIG_NO_CONVERSION",
|
||||
"-DUCONFIG_NO_FORMATTING",
|
||||
"-DUCONFIG_NO_SERVICE",
|
||||
"-DUCONFIG_NO_IDNA",
|
||||
"-DUCONFIG_NO_FILE_IO",
|
||||
"-DUCONFIG_NO_TRANSLITERATION",
|
||||
"-DPKGDATA_MODE=static",
|
||||
"-DU_ENABLE_DYLOAD=0",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
]
|
||||
)
|
||||
env.Append(
|
||||
CXXFLAGS=[
|
||||
"-DU_STATIC_IMPLEMENTATION",
|
||||
"-DU_HAVE_LIB_SUFFIX=1",
|
||||
"-DU_LIB_SUFFIX_C_NAME=_godot",
|
||||
]
|
||||
)
|
||||
env.Append(CPPPATH=["../../../thirdparty/icu4c/common/", "../../../thirdparty/icu4c/i18n/"])
|
||||
|
||||
if env["platform"] == "windows":
|
||||
env.Append(LIBS=["advapi32"])
|
||||
|
||||
lib = env_icu.Library(f"icu_builtin{env['suffix']}{env['LIBSUFFIX']}", thirdparty_icu_sources)
|
||||
env.Append(LIBS=[lib])
|
||||
|
||||
env.Append(CPPDEFINES=["GDEXTENSION"])
|
||||
env.Append(CPPPATH=["../"])
|
||||
sources = Glob("../*.cpp")
|
||||
|
||||
if env["platform"] == "macos":
|
||||
methods.write_macos_plist(
|
||||
f"./bin/libtextserver_advanced.macos.{env['target']}.framework",
|
||||
f"libtextserver_advanced.macos.{env['target']}",
|
||||
"org.godotengine.textserver_advanced",
|
||||
"ICU / HarfBuzz / Graphite Text Server",
|
||||
)
|
||||
library = env.SharedLibrary(
|
||||
f"./bin/libtextserver_advanced.macos.{env['target']}.framework/libtextserver_advanced.macos.{env['target']}",
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.SharedLibrary(
|
||||
f"./bin/libtextserver_advanced{env['suffix']}{env['SHLIBSUFFIX']}",
|
||||
source=sources,
|
||||
)
|
||||
|
||||
Default(library)
|
||||
|
||||
methods.prepare_timer()
|
84
modules/text_server_adv/gdextension_build/methods.py
Normal file
84
modules/text_server_adv/gdextension_build/methods.py
Normal file
@@ -0,0 +1,84 @@
|
||||
def disable_warnings(self):
|
||||
# 'self' is the environment
|
||||
if self["platform"] == "windows" and not self["use_mingw"]:
|
||||
# We have to remove existing warning level defines before appending /w,
|
||||
# otherwise we get: "warning D9025 : overriding '/W3' with '/w'"
|
||||
WARN_FLAGS = ["/Wall", "/W4", "/W3", "/W2", "/W1", "/W0"]
|
||||
self["CCFLAGS"] = [x for x in self["CCFLAGS"] if x not in WARN_FLAGS]
|
||||
self["CFLAGS"] = [x for x in self["CFLAGS"] if x not in WARN_FLAGS]
|
||||
self["CXXFLAGS"] = [x for x in self["CXXFLAGS"] if x not in WARN_FLAGS]
|
||||
self.AppendUnique(CCFLAGS=["/w"])
|
||||
else:
|
||||
self.AppendUnique(CCFLAGS=["-w"])
|
||||
|
||||
|
||||
def prepare_timer():
|
||||
import atexit
|
||||
import time
|
||||
|
||||
def print_elapsed_time(time_at_start: float):
|
||||
time_elapsed = time.time() - time_at_start
|
||||
time_formatted = time.strftime("%H:%M:%S", time.gmtime(time_elapsed))
|
||||
time_centiseconds = round((time_elapsed % 1) * 100)
|
||||
print(f"[Time elapsed: {time_formatted}.{time_centiseconds}]")
|
||||
|
||||
atexit.register(print_elapsed_time, time.time())
|
||||
|
||||
|
||||
def make_icu_data(target, source, env):
|
||||
dst = target[0].srcnode().abspath
|
||||
with open(dst, "w", encoding="utf-8", newline="\n") as g:
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("/* (C) 2016 and later: Unicode, Inc. and others. */\n")
|
||||
g.write("/* License & terms of use: https://www.unicode.org/copyright.html */\n")
|
||||
g.write("#ifndef _ICU_DATA_H\n")
|
||||
g.write("#define _ICU_DATA_H\n")
|
||||
g.write('#include "unicode/utypes.h"\n')
|
||||
g.write('#include "unicode/udata.h"\n')
|
||||
g.write('#include "unicode/uversion.h"\n')
|
||||
|
||||
with open(source[0].srcnode().abspath, "rb") as f:
|
||||
buf = f.read()
|
||||
|
||||
g.write('extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = ' + str(len(buf)) + ";\n")
|
||||
g.write('extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {\n')
|
||||
for i in range(len(buf)):
|
||||
g.write("\t" + str(buf[i]) + ",\n")
|
||||
|
||||
g.write("};\n")
|
||||
g.write("#endif")
|
||||
|
||||
|
||||
def write_macos_plist(target, binary_name, identifier, name):
|
||||
import os
|
||||
|
||||
os.makedirs(f"{target}/Resource/", exist_ok=True)
|
||||
with open(f"{target}/Resource/Info.plist", "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(f"""\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{binary_name}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>{identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>{name}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.14</string>
|
||||
</dict>
|
||||
</plist>
|
||||
""")
|
@@ -0,0 +1,25 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "textserver_advanced_init"
|
||||
compatibility_minimum = 4.1
|
||||
|
||||
[libraries]
|
||||
|
||||
linux.x86_64.debug = "bin/libtextserver_advanced.linux.template_debug.x86_64.so"
|
||||
linux.x86_64.release = "bin/libtextserver_advanced.linux.template_release.x86_64.so"
|
||||
linux.x86_32.debug = "bin/libtextserver_advanced.linux.template_debug.x86_32.so"
|
||||
linux.x86_32.release = "bin/libtextserver_advanced.linux.template_release.x86_32.so"
|
||||
linux.arm64.debug = "bin/libtextserver_advanced.linux.template_debug.arm64.so"
|
||||
linux.arm64.release = "bin/libtextserver_advanced.linux.template_release.arm64.so"
|
||||
linux.rv64.debug = "bin/libtextserver_advanced.linux.template_debug.rv64.so"
|
||||
linux.rv64.release = "bin/libtextserver_advanced.linux.template_release.rv64.so"
|
||||
|
||||
windows.x86_64.debug = "bin/libtextserver_advanced.windows.template_debug.x86_64.dll"
|
||||
windows.x86_64.release = "bin/libtextserver_advanced.windows.template_release.x86_64.dll"
|
||||
windows.x86_32.debug = "bin/libtextserver_advanced.windows.template_debug.x86_32.dll"
|
||||
windows.x86_32.release = "bin/libtextserver_advanced.windows.template_release.x86_32.dll"
|
||||
windows.arm64.debug = "bin/libtextserver_advanced.windows.template_debug.arm64.dll"
|
||||
windows.arm64.release = "bin/libtextserver_advanced.windows.template_release.arm64.dll"
|
||||
|
||||
macos.debug = "bin/libtextserver_advanced.macos.template_debug.framework"
|
||||
macos.release = "bin/libtextserver_advanced.macos.template_release.framework"
|
63
modules/text_server_adv/icu_data/icudata_stub.cpp
Normal file
63
modules/text_server_adv/icu_data/icudata_stub.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************/
|
||||
/* icudata_stub.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include <unicode/udata.h>
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/uversion.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t header_size;
|
||||
uint8_t magic_1, magic_2;
|
||||
UDataInfo info;
|
||||
char padding[8];
|
||||
uint32_t count, reserved;
|
||||
int fake_name_and_data[4];
|
||||
} ICU_data_header;
|
||||
|
||||
extern "C" U_EXPORT const ICU_data_header U_ICUDATA_ENTRY_POINT = {
|
||||
32,
|
||||
0xDA, 0x27,
|
||||
{ sizeof(UDataInfo),
|
||||
0,
|
||||
#if U_IS_BIG_ENDIAN
|
||||
1,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
U_CHARSET_FAMILY,
|
||||
sizeof(UChar),
|
||||
0,
|
||||
{ 0x54, 0x6F, 0x43, 0x50 },
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 } },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
0, 0,
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
77
modules/text_server_adv/register_types.cpp
Normal file
77
modules/text_server_adv/register_types.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/**************************************************************************/
|
||||
/* register_types.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "register_types.h"
|
||||
|
||||
#include "text_server_adv.h"
|
||||
|
||||
void initialize_text_server_adv_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
GDREGISTER_CLASS(TextServerAdvanced);
|
||||
TextServerManager *tsman = TextServerManager::get_singleton();
|
||||
if (tsman) {
|
||||
Ref<TextServerAdvanced> ts;
|
||||
ts.instantiate();
|
||||
tsman->add_interface(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void uninitialize_text_server_adv_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GDEXTENSION
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
extern "C" {
|
||||
|
||||
GDExtensionBool GDE_EXPORT textserver_advanced_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
|
||||
init_obj.register_initializer(&initialize_text_server_adv_module);
|
||||
init_obj.register_terminator(&uninitialize_text_server_adv_module);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SERVERS);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
|
||||
} // ! extern "C"
|
||||
|
||||
#endif // ! GDEXTENSION
|
41
modules/text_server_adv/register_types.h
Normal file
41
modules/text_server_adv/register_types.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* register_types.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GDEXTENSION
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
using namespace godot;
|
||||
#elif defined(GODOT_MODULE)
|
||||
#include "modules/register_module_types.h"
|
||||
#endif
|
||||
|
||||
void initialize_text_server_adv_module(ModuleInitializationLevel p_level);
|
||||
void uninitialize_text_server_adv_module(ModuleInitializationLevel p_level);
|
128
modules/text_server_adv/script_iterator.cpp
Normal file
128
modules/text_server_adv/script_iterator.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/**************************************************************************/
|
||||
/* script_iterator.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "script_iterator.h"
|
||||
|
||||
// This implementation is derived from ICU: icu4c/source/extra/scrptrun/scrptrun.cpp
|
||||
|
||||
bool ScriptIterator::same_script(int32_t p_script_one, int32_t p_script_two) {
|
||||
return p_script_one <= USCRIPT_INHERITED || p_script_two <= USCRIPT_INHERITED || p_script_one == p_script_two;
|
||||
}
|
||||
|
||||
ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length) {
|
||||
struct ParenStackEntry {
|
||||
int pair_index;
|
||||
UScriptCode script_code;
|
||||
};
|
||||
|
||||
if (p_start >= p_length) {
|
||||
p_start = p_length - 1;
|
||||
}
|
||||
|
||||
if (p_start < 0) {
|
||||
p_start = 0;
|
||||
}
|
||||
|
||||
int paren_size = PAREN_STACK_DEPTH;
|
||||
ParenStackEntry *paren_stack = static_cast<ParenStackEntry *>(memalloc(paren_size * sizeof(ParenStackEntry)));
|
||||
|
||||
int script_start;
|
||||
int script_end = p_start;
|
||||
UScriptCode script_code;
|
||||
int paren_sp = -1;
|
||||
int start_sp = paren_sp;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
const char32_t *str = p_string.ptr();
|
||||
|
||||
do {
|
||||
script_code = USCRIPT_COMMON;
|
||||
for (script_start = script_end; script_end < p_length; script_end++) {
|
||||
UChar32 ch = str[script_end];
|
||||
UScriptCode sc = uscript_getScript(ch, &err);
|
||||
if (U_FAILURE(err)) {
|
||||
memfree(paren_stack);
|
||||
ERR_FAIL_MSG(u_errorName(err));
|
||||
}
|
||||
if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) != U_BPT_NONE) {
|
||||
if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_OPEN) {
|
||||
// If it's an open character, push it onto the stack.
|
||||
paren_sp++;
|
||||
if (unlikely(paren_sp >= paren_size)) {
|
||||
// If the stack is full, allocate more space to handle deeply nested parentheses. This is unlikely to happen with any real text.
|
||||
paren_size += PAREN_STACK_DEPTH;
|
||||
paren_stack = static_cast<ParenStackEntry *>(memrealloc(paren_stack, paren_size * sizeof(ParenStackEntry)));
|
||||
}
|
||||
paren_stack[paren_sp].pair_index = ch;
|
||||
paren_stack[paren_sp].script_code = script_code;
|
||||
} else if (paren_sp >= 0) {
|
||||
// If it's a close character, find the matching open on the stack, and use that script code. Any non-matching open characters above it on the stack will be popped.
|
||||
UChar32 paired_ch = u_getBidiPairedBracket(ch);
|
||||
while (paren_sp >= 0 && paren_stack[paren_sp].pair_index != paired_ch) {
|
||||
paren_sp -= 1;
|
||||
}
|
||||
if (paren_sp < start_sp) {
|
||||
start_sp = paren_sp;
|
||||
}
|
||||
if (paren_sp >= 0) {
|
||||
sc = paren_stack[paren_sp].script_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (same_script(script_code, sc)) {
|
||||
if (script_code <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
|
||||
script_code = sc;
|
||||
// Now that we have a final script code, fix any open characters we pushed before we knew the script code.
|
||||
while (start_sp < paren_sp) {
|
||||
paren_stack[++start_sp].script_code = script_code;
|
||||
}
|
||||
}
|
||||
if ((u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_CLOSE) && paren_sp >= 0) {
|
||||
// If this character is a close paired character pop the matching open character from the stack.
|
||||
paren_sp -= 1;
|
||||
if (start_sp >= 0) {
|
||||
start_sp -= 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptRange rng;
|
||||
rng.script = hb_icu_script_to_script(script_code);
|
||||
rng.start = script_start;
|
||||
rng.end = script_end;
|
||||
|
||||
script_ranges.push_back(rng);
|
||||
} while (script_end < p_length);
|
||||
|
||||
memfree(paren_stack);
|
||||
}
|
75
modules/text_server_adv/script_iterator.h
Normal file
75
modules/text_server_adv/script_iterator.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* script_iterator.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GDEXTENSION
|
||||
|
||||
// Headers for building as GDExtension plug-in.
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#elif defined(GODOT_MODULE)
|
||||
|
||||
// Headers for building as built-in module.
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include <unicode/uchar.h>
|
||||
#include <unicode/uloc.h>
|
||||
#include <unicode/uscript.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/utypes.h>
|
||||
|
||||
#include <hb-icu.h>
|
||||
#include <hb.h>
|
||||
|
||||
class ScriptIterator {
|
||||
static const int PAREN_STACK_DEPTH = 128;
|
||||
|
||||
public:
|
||||
struct ScriptRange {
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
hb_script_t script = HB_SCRIPT_COMMON;
|
||||
};
|
||||
Vector<ScriptRange> script_ranges;
|
||||
|
||||
private:
|
||||
static bool same_script(int32_t p_script_one, int32_t p_script_two);
|
||||
|
||||
public:
|
||||
ScriptIterator(const String &p_string, int p_start, int p_length);
|
||||
};
|
8243
modules/text_server_adv/text_server_adv.cpp
Normal file
8243
modules/text_server_adv/text_server_adv.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1066
modules/text_server_adv/text_server_adv.h
Normal file
1066
modules/text_server_adv/text_server_adv.h
Normal file
File diff suppressed because it is too large
Load Diff
21
modules/text_server_adv/text_server_adv_builders.py
Normal file
21
modules/text_server_adv/text_server_adv_builders.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""Functions used to generate source files during build time"""
|
||||
|
||||
import methods
|
||||
|
||||
|
||||
def make_icu_data(target, source, env):
|
||||
buffer = methods.get_buffer(str(source[0]))
|
||||
with methods.generated_wrapper(str(target[0])) as file:
|
||||
file.write(f"""\
|
||||
/* (C) 2016 and later: Unicode, Inc. and others. */
|
||||
/* License & terms of use: https://www.unicode.org/copyright.html */
|
||||
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/udata.h>
|
||||
#include <unicode/uversion.h>
|
||||
|
||||
extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = {len(buffer)};
|
||||
extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {{
|
||||
{methods.format_buffer(buffer, 1)}
|
||||
}};
|
||||
""")
|
381
modules/text_server_adv/thorvg_svg_in_ot.cpp
Normal file
381
modules/text_server_adv/thorvg_svg_in_ot.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
/**************************************************************************/
|
||||
/* thorvg_svg_in_ot.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "thorvg_svg_in_ot.h"
|
||||
|
||||
#ifdef GDEXTENSION
|
||||
// Headers for building as GDExtension plug-in.
|
||||
|
||||
#include <godot_cpp/classes/xml_parser.hpp>
|
||||
#include <godot_cpp/core/mutex_lock.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#elif defined(GODOT_MODULE)
|
||||
// Headers for building as built-in module.
|
||||
|
||||
#include "core/error/error_macros.h"
|
||||
#include "core/io/xml_parser.h"
|
||||
#include "core/os/memory.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/typedefs.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // For svg, freetype.
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
|
||||
#include <freetype/otsvg.h>
|
||||
#include <ft2build.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state) {
|
||||
*p_state = memnew(TVG_State);
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
void tvg_svg_in_ot_free(FT_Pointer *p_state) {
|
||||
TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
|
||||
memdelete(state);
|
||||
}
|
||||
|
||||
static void construct_xml(Ref<XMLParser> &parser, double &r_embox_x, double &r_embox_y, String *p_xml, int64_t &r_tag_count) {
|
||||
if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
|
||||
*p_xml += vformat("<%s", parser->get_node_name());
|
||||
bool is_svg_tag = parser->get_node_name() == "svg";
|
||||
for (int i = 0; i < parser->get_attribute_count(); i++) {
|
||||
String aname = parser->get_attribute_name(i);
|
||||
String value = parser->get_attribute_value(i);
|
||||
if (is_svg_tag && aname == "viewBox") {
|
||||
PackedStringArray vb = value.split(" ");
|
||||
if (vb.size() == 4) {
|
||||
r_embox_x = vb[2].to_float();
|
||||
r_embox_y = vb[3].to_float();
|
||||
}
|
||||
} else if (is_svg_tag && aname == "width") {
|
||||
r_embox_x = value.to_float();
|
||||
} else if (is_svg_tag && aname == "height") {
|
||||
r_embox_y = value.to_float();
|
||||
} else {
|
||||
*p_xml += vformat(" %s=\"%s\"", aname, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser->is_empty()) {
|
||||
*p_xml += "/>";
|
||||
} else {
|
||||
*p_xml += ">";
|
||||
if (r_tag_count >= 0) {
|
||||
r_tag_count++;
|
||||
}
|
||||
}
|
||||
} else if (parser->get_node_type() == XMLParser::NODE_TEXT) {
|
||||
*p_xml += parser->get_node_data();
|
||||
} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) {
|
||||
*p_xml += vformat("</%s>", parser->get_node_name());
|
||||
if (r_tag_count > 0) {
|
||||
r_tag_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state) {
|
||||
TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
|
||||
if (!state) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
|
||||
}
|
||||
MutexLock lock(state->mutex);
|
||||
|
||||
FT_SVG_Document document = (FT_SVG_Document)p_slot->other;
|
||||
FT_Size_Metrics metrics = document->metrics;
|
||||
|
||||
GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
|
||||
if (!gl_state.ready) {
|
||||
Ref<XMLParser> parser;
|
||||
parser.instantiate();
|
||||
parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length);
|
||||
|
||||
String xml_body;
|
||||
|
||||
double embox_x = document->units_per_EM;
|
||||
double embox_y = document->units_per_EM;
|
||||
|
||||
TVG_DocumentCache &cache = state->document_map[document->svg_document];
|
||||
|
||||
if (!cache.xml_body.is_empty()) {
|
||||
// If we have a cached document, that means we have already parsed it.
|
||||
// All node cache should be available.
|
||||
|
||||
xml_body = cache.xml_body;
|
||||
embox_x = cache.embox_x;
|
||||
embox_y = cache.embox_y;
|
||||
|
||||
ERR_FAIL_COND_V(!cache.node_caches.has(p_slot->glyph_index), FT_Err_Invalid_SVG_Document);
|
||||
Vector<TVG_NodeCache> &ncs = cache.node_caches[p_slot->glyph_index];
|
||||
|
||||
uint64_t offset = 0;
|
||||
for (TVG_NodeCache &nc : ncs) {
|
||||
// Seek will call read() internally.
|
||||
if (parser->seek(nc.document_offset) == OK) {
|
||||
int64_t tag_count = 0;
|
||||
String xml_node;
|
||||
|
||||
// We only parse the glyph node.
|
||||
do {
|
||||
construct_xml(parser, embox_x, embox_y, &xml_node, tag_count);
|
||||
} while (tag_count != 0 && parser->read() == OK);
|
||||
|
||||
xml_body = xml_body.insert(nc.body_offset + offset, xml_node);
|
||||
offset += xml_node.length();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String xml_node;
|
||||
String xml_body_temp;
|
||||
|
||||
String *p_xml = &xml_body_temp;
|
||||
int64_t tag_count = -1;
|
||||
|
||||
bool is_in_defs = false;
|
||||
while (parser->read() == OK) {
|
||||
if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name().to_lower() == "defs") {
|
||||
is_in_defs = true;
|
||||
} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name().to_lower() == "defs") {
|
||||
is_in_defs = false;
|
||||
}
|
||||
if (!is_in_defs && parser->has_attribute("id")) {
|
||||
const String &gl_name = parser->get_named_attribute_value("id");
|
||||
if (gl_name.begins_with("glyph")) {
|
||||
#ifdef GDEXTENSION
|
||||
int dot_pos = gl_name.find(".");
|
||||
#else
|
||||
int dot_pos = gl_name.find_char('.');
|
||||
#endif // GDEXTENSION
|
||||
int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int();
|
||||
|
||||
TVG_NodeCache node_cache = TVG_NodeCache();
|
||||
node_cache.document_offset = parser->get_node_offset(),
|
||||
node_cache.body_offset = (uint64_t)cache.xml_body.length();
|
||||
cache.node_caches[gl_idx].push_back(node_cache);
|
||||
|
||||
if (p_slot->glyph_index != gl_idx) {
|
||||
parser->skip_section();
|
||||
continue;
|
||||
}
|
||||
tag_count = 0;
|
||||
xml_node = "";
|
||||
p_xml = &xml_node;
|
||||
}
|
||||
}
|
||||
|
||||
xml_body_temp = "";
|
||||
construct_xml(parser, embox_x, embox_y, p_xml, tag_count);
|
||||
|
||||
if (xml_body_temp.length() > 0) {
|
||||
xml_body += xml_body_temp;
|
||||
cache.xml_body += xml_body_temp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_count == 0) {
|
||||
p_xml = &xml_body_temp;
|
||||
tag_count = -1;
|
||||
xml_body += xml_node;
|
||||
}
|
||||
}
|
||||
|
||||
cache.embox_x = embox_x;
|
||||
cache.embox_y = embox_y;
|
||||
}
|
||||
|
||||
std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
|
||||
gl_state.xml_code = xml_body.utf8();
|
||||
|
||||
tvg::Result result = picture->load(gl_state.xml_code.get_data(), gl_state.xml_code.length(), "svg+xml", false);
|
||||
if (result != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph metrics).");
|
||||
}
|
||||
|
||||
float svg_width, svg_height;
|
||||
picture->size(&svg_width, &svg_height);
|
||||
double aspect_x = (svg_width > svg_height) ? svg_width / svg_height : 1.0;
|
||||
double aspect_y = (svg_width < svg_height) ? svg_height / svg_width : 1.0;
|
||||
|
||||
result = picture->size(embox_x * aspect_x, embox_y * aspect_y);
|
||||
if (result != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to resize SVG document.");
|
||||
}
|
||||
|
||||
double scale = double(embox_x * aspect_x) / double(svg_width);
|
||||
double yoff = double(document->metrics.ascender + document->metrics.descender) / double(document->metrics.ascender);
|
||||
|
||||
double x_svg_to_out = (double)metrics.x_ppem / embox_x / scale;
|
||||
double y_svg_to_out = (double)metrics.y_ppem / embox_y / scale;
|
||||
|
||||
gl_state.m.e11 = (double)document->transform.xx / (1 << 16);
|
||||
gl_state.m.e12 = -(double)document->transform.xy / (1 << 16);
|
||||
gl_state.m.e21 = -(double)document->transform.yx / (1 << 16);
|
||||
gl_state.m.e22 = (double)document->transform.yy / (1 << 16);
|
||||
gl_state.m.e13 = (double)document->delta.x / 64 * embox_x / metrics.x_ppem * scale;
|
||||
gl_state.m.e23 = -(double)document->delta.y / 64 * embox_y / metrics.y_ppem * scale;
|
||||
gl_state.m.e31 = 0;
|
||||
gl_state.m.e32 = 0;
|
||||
gl_state.m.e33 = 1;
|
||||
|
||||
result = picture->size(embox_x * aspect_x * x_svg_to_out, embox_y * aspect_y * y_svg_to_out);
|
||||
if (result != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to resize SVG document.");
|
||||
}
|
||||
|
||||
result = picture->transform(gl_state.m);
|
||||
if (result != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
|
||||
}
|
||||
|
||||
picture->size(&gl_state.w, &gl_state.h);
|
||||
|
||||
gl_state.x = (double(p_slot->metrics.horiAdvance) / 64.0 - gl_state.w) / 2.0;
|
||||
gl_state.y = -Math::ceil(gl_state.h * yoff);
|
||||
|
||||
gl_state.ready = true;
|
||||
}
|
||||
|
||||
p_slot->bitmap_left = (FT_Int)gl_state.x;
|
||||
p_slot->bitmap_top = (FT_Int)-gl_state.y;
|
||||
|
||||
double tmpd = Math::ceil(gl_state.h);
|
||||
p_slot->bitmap.rows = (unsigned int)tmpd;
|
||||
tmpd = Math::ceil(gl_state.w);
|
||||
p_slot->bitmap.width = (unsigned int)tmpd;
|
||||
p_slot->bitmap.pitch = (int)p_slot->bitmap.width * 4;
|
||||
|
||||
p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
|
||||
|
||||
float metrics_width = (float)gl_state.w;
|
||||
float metrics_height = (float)gl_state.h;
|
||||
|
||||
float horiBearingX = (float)gl_state.x;
|
||||
float horiBearingY = (float)-gl_state.y;
|
||||
|
||||
float vertBearingX = p_slot->metrics.horiBearingX / 64.0f - p_slot->metrics.horiAdvance / 64.0f / 2;
|
||||
float vertBearingY = (p_slot->metrics.vertAdvance / 64.0f - p_slot->metrics.height / 64.0f) / 2;
|
||||
|
||||
float tmpf = Math::round(metrics_width * 64);
|
||||
p_slot->metrics.width = (FT_Pos)tmpf;
|
||||
tmpf = Math::round(metrics_height * 64);
|
||||
p_slot->metrics.height = (FT_Pos)tmpf;
|
||||
|
||||
p_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
|
||||
p_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
|
||||
p_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
|
||||
p_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
|
||||
|
||||
if (p_slot->metrics.vertAdvance == 0) {
|
||||
p_slot->metrics.vertAdvance = (FT_Pos)(metrics_height * 1.2f * 64);
|
||||
}
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state) {
|
||||
TVG_State *state = *reinterpret_cast<TVG_State **>(p_state);
|
||||
if (!state) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG in OT state not initialized.");
|
||||
}
|
||||
MutexLock lock(state->mutex);
|
||||
|
||||
if (!state->glyph_map.has(p_slot->glyph_index)) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "SVG glyph not loaded.");
|
||||
}
|
||||
|
||||
GL_State &gl_state = state->glyph_map[p_slot->glyph_index];
|
||||
ERR_FAIL_COND_V_MSG(!gl_state.ready, FT_Err_Invalid_SVG_Document, "SVG glyph not ready.");
|
||||
|
||||
std::unique_ptr<tvg::Picture> picture = tvg::Picture::gen();
|
||||
tvg::Result res = picture->load(gl_state.xml_code.get_data(), gl_state.xml_code.length(), "svg+xml", false);
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to load SVG document (glyph rendering).");
|
||||
}
|
||||
res = picture->size(gl_state.w, gl_state.h);
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to resize SVG document.");
|
||||
}
|
||||
res = picture->transform(gl_state.m);
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_SVG_Document, "Failed to apply transform to SVG document.");
|
||||
}
|
||||
|
||||
std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen();
|
||||
res = sw_canvas->target((uint32_t *)p_slot->bitmap.buffer, (int)p_slot->bitmap.width, (int)p_slot->bitmap.width, (int)p_slot->bitmap.rows, tvg::SwCanvas::ARGB8888S);
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to create SVG canvas.");
|
||||
}
|
||||
res = sw_canvas->push(std::move(picture));
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to set SVG canvas source.");
|
||||
}
|
||||
res = sw_canvas->draw();
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to draw to SVG canvas.");
|
||||
}
|
||||
res = sw_canvas->sync();
|
||||
if (res != tvg::Result::Success) {
|
||||
ERR_FAIL_V_MSG(FT_Err_Invalid_Outline, "Failed to sync SVG canvas.");
|
||||
}
|
||||
|
||||
state->glyph_map.erase(p_slot->glyph_index);
|
||||
|
||||
p_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
|
||||
p_slot->bitmap.num_grays = 256;
|
||||
p_slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
SVG_RendererHooks tvg_svg_in_ot_hooks = {
|
||||
(SVG_Lib_Init_Func)tvg_svg_in_ot_init,
|
||||
(SVG_Lib_Free_Func)tvg_svg_in_ot_free,
|
||||
(SVG_Lib_Render_Func)tvg_svg_in_ot_render,
|
||||
(SVG_Lib_Preset_Slot_Func)tvg_svg_in_ot_preset_slot,
|
||||
};
|
||||
|
||||
SVG_RendererHooks *get_tvg_svg_in_ot_hooks() {
|
||||
return &tvg_svg_in_ot_hooks;
|
||||
}
|
||||
|
||||
#endif // MODULE_FREETYPE_ENABLED
|
||||
#endif // MODULE_SVG_ENABLED
|
96
modules/text_server_adv/thorvg_svg_in_ot.h
Normal file
96
modules/text_server_adv/thorvg_svg_in_ot.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************/
|
||||
/* thorvg_svg_in_ot.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef GDEXTENSION
|
||||
// Headers for building as GDExtension plug-in.
|
||||
|
||||
#include <godot_cpp/core/mutex_lock.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/templates/hash_map.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#elif defined(GODOT_MODULE)
|
||||
// Headers for building as built-in module.
|
||||
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/typedefs.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // For svg, freetype.
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
#ifdef MODULE_FREETYPE_ENABLED
|
||||
|
||||
#include <freetype/freetype.h>
|
||||
#include <freetype/otsvg.h>
|
||||
#include <ft2build.h>
|
||||
#include <thorvg.h>
|
||||
|
||||
struct GL_State {
|
||||
bool ready = false;
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float w = 0;
|
||||
float h = 0;
|
||||
CharString xml_code;
|
||||
tvg::Matrix m;
|
||||
};
|
||||
|
||||
struct TVG_NodeCache {
|
||||
uint64_t document_offset;
|
||||
uint64_t body_offset;
|
||||
};
|
||||
|
||||
struct TVG_DocumentCache {
|
||||
String xml_body;
|
||||
double embox_x;
|
||||
double embox_y;
|
||||
HashMap<int64_t, Vector<TVG_NodeCache>> node_caches;
|
||||
};
|
||||
|
||||
struct TVG_State {
|
||||
Mutex mutex;
|
||||
HashMap<uint32_t, GL_State> glyph_map;
|
||||
HashMap<FT_Byte *, TVG_DocumentCache> document_map;
|
||||
};
|
||||
|
||||
FT_Error tvg_svg_in_ot_init(FT_Pointer *p_state);
|
||||
void tvg_svg_in_ot_free(FT_Pointer *p_state);
|
||||
FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Pointer *p_state);
|
||||
FT_Error tvg_svg_in_ot_render(FT_GlyphSlot p_slot, FT_Pointer *p_state);
|
||||
|
||||
SVG_RendererHooks *get_tvg_svg_in_ot_hooks();
|
||||
|
||||
#endif // MODULE_FREETYPE_ENABLED
|
||||
#endif // MODULE_SVG_ENABLED
|
Reference in New Issue
Block a user