Merge tag 'v5.15.16-lts' into tqtc/lts-5.15-opensource
Qt 5.15.16-lts release Change-Id: I0b81d82eee67dff8d225bf5da2fe65ff08b02c82
This commit is contained in:
commit
8ad94db938
@ -6,4 +6,4 @@ DEFINES += QT_NO_JAVA_STYLE_ITERATORS
|
||||
QT_SOURCE_TREE = $$PWD
|
||||
QT_BUILD_TREE = $$shadowed($$PWD)
|
||||
|
||||
MODULE_VERSION = 5.15.15
|
||||
MODULE_VERSION = 5.15.16
|
||||
|
@ -233,15 +233,8 @@ android: CONFIG += qt_android_deps no_linker_version_script
|
||||
|
||||
current = Qt_$$QT_MAJOR_VERSION
|
||||
verscript_content += "$$current { *; };"
|
||||
isEmpty(QT_NAMESPACE): tag_symbol = qt_version_tag
|
||||
else: tag_symbol = qt_version_tag_$$QT_NAMESPACE
|
||||
|
||||
for(i, 0..$$QT_MINOR_VERSION) {
|
||||
previous = $$current
|
||||
current = Qt_$${QT_MAJOR_VERSION}.$$i
|
||||
equals(i, $$QT_MINOR_VERSION): verscript_content += "$$current { $$tag_symbol; } $$previous;"
|
||||
else: verscript_content += "$$current {} $$previous;"
|
||||
}
|
||||
!isEmpty(MODULE_VERSCRIPT_CONTENT_EXT): verscript_content += $$MODULE_VERSCRIPT_CONTENT_EXT
|
||||
|
||||
# Add a post-processing step to replace the @FILE:filename@
|
||||
verscript_in = $${verscript}.in
|
||||
|
@ -288,9 +288,12 @@ isEmpty($${target_prefix}.INCDIRS) {
|
||||
}
|
||||
}
|
||||
}
|
||||
isEmpty(QMAKE_DEFAULT_LIBDIRS)|isEmpty(QMAKE_DEFAULT_INCDIRS): \
|
||||
isEmpty(QMAKE_DEFAULT_INCDIRS): \
|
||||
!integrity: \
|
||||
error("failed to parse default search paths from compiler output")
|
||||
error("failed to parse default include paths from compiler output")
|
||||
isEmpty(QMAKE_DEFAULT_LIBDIRS): \
|
||||
!integrity:!darwin: \
|
||||
error("failed to parse default library paths from compiler output")
|
||||
QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
|
||||
} else: ghs {
|
||||
cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp
|
||||
@ -412,7 +415,7 @@ isEmpty($${target_prefix}.INCDIRS) {
|
||||
QMAKE_DEFAULT_INCDIRS = $$split(INCLUDE, $$QMAKE_DIRLIST_SEP)
|
||||
}
|
||||
|
||||
unix:if(!cross_compile|host_build) {
|
||||
unix:!darwin:if(!cross_compile|host_build) {
|
||||
isEmpty(QMAKE_DEFAULT_INCDIRS): QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include
|
||||
isEmpty(QMAKE_DEFAULT_LIBDIRS): QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib
|
||||
}
|
||||
|
8
src/3rdparty/freetype/README
vendored
8
src/3rdparty/freetype/README
vendored
@ -1,4 +1,4 @@
|
||||
FreeType 2.13.1
|
||||
FreeType 2.13.2
|
||||
===============
|
||||
|
||||
Homepage: https://www.freetype.org
|
||||
@ -32,9 +32,9 @@ sites. Go to
|
||||
|
||||
and download one of the following files.
|
||||
|
||||
freetype-doc-2.13.1.tar.xz
|
||||
freetype-doc-2.13.1.tar.gz
|
||||
ftdoc2131.zip
|
||||
freetype-doc-2.13.2.tar.xz
|
||||
freetype-doc-2.13.2.tar.gz
|
||||
ftdoc2132.zip
|
||||
|
||||
To view the documentation online, go to
|
||||
|
||||
|
14
src/3rdparty/freetype/docs/CHANGES
vendored
14
src/3rdparty/freetype/docs/CHANGES
vendored
@ -1,3 +1,17 @@
|
||||
CHANGES BETWEEN 2.13.1 and 2.13.2 (2023-Aug-25)
|
||||
|
||||
I. MISCELLANEOUS
|
||||
|
||||
- Better support for CFF2 variation fonts.
|
||||
|
||||
- TrueType interpreter version 38 (also known as 'Infinality') has
|
||||
been removed.
|
||||
|
||||
- Improved OpenVMS support.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
CHANGES BETWEEN 2.13.0 and 2.13.1 (2023-Jun-24)
|
||||
|
||||
I. MISCELLANEOUS
|
||||
|
190
src/3rdparty/freetype/include/dlg/dlg.h
vendored
190
src/3rdparty/freetype/include/dlg/dlg.h
vendored
@ -85,6 +85,13 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This macro is used when an assertion fails. It gets the source expression
|
||||
// and can return an alternative (that must stay alive).
|
||||
// Mainly useful to execute something on failed assertion.
|
||||
#ifndef DLG_FAILED_ASSERTION_TEXT
|
||||
#define DLG_FAILED_ASSERTION_TEXT(x) x
|
||||
#endif
|
||||
|
||||
// - utility -
|
||||
// two methods needed since cplusplus does not support compound literals
|
||||
// and c does not support uniform initialization/initializer lists
|
||||
@ -131,83 +138,12 @@ struct dlg_origin {
|
||||
// Type of the output handler, see dlg_set_handler.
|
||||
typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, void* data);
|
||||
|
||||
#ifdef DLG_DISABLE
|
||||
#ifndef DLG_DISABLE
|
||||
// Tagged/Untagged logging with variable level
|
||||
// Tags must always be in the format `("tag1", "tag2")` (including brackets)
|
||||
#define dlg_log(level, ...)
|
||||
#define dlg_logt(level, tags, ...)
|
||||
|
||||
// Dynamic level assert macros in various versions for additional arguments
|
||||
#define dlg_assertl(level, expr) // assert without tags/message
|
||||
#define dlg_assertlt(level, tags, expr) // assert with tags
|
||||
#define dlg_assertlm(level, expr, ...) // assert with message
|
||||
#define dlg_assertltm(level, tags, expr, ...) // assert with tags & message
|
||||
|
||||
// Sets the handler that is responsible for formatting and outputting log calls.
|
||||
// This function is not thread safe and the handler is set globally.
|
||||
// The handler itself must not change dlg tags or call a dlg macro (if it
|
||||
// does so, the provided string or tags array in 'origin' might get invalid).
|
||||
// The handler can also be used for various other things such as dealing
|
||||
// with failed assertions or filtering calls based on the passed tags.
|
||||
// The default handler is dlg_default_output (see its doc for more info).
|
||||
// If using c++ make sure the registered handler cannot throw e.g. by
|
||||
// wrapping everything into a try-catch blog.
|
||||
inline void dlg_set_handler(dlg_handler handler, void* data) {
|
||||
(void) handler;
|
||||
(void) data;
|
||||
}
|
||||
|
||||
// Returns the currently active dlg handler and sets `data` to
|
||||
// its user data pointer. `data` must not be NULL.
|
||||
// Useful to create handler chains.
|
||||
// This function is not threadsafe, i.e. retrieving the handler while
|
||||
// changing it from another thread is unsafe.
|
||||
// See `dlg_set_handler`.
|
||||
inline dlg_handler dlg_get_handler(void** data) {
|
||||
*data = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The default output handler.
|
||||
// Only use this to reset the output handler, prefer to use
|
||||
// dlg_generic_output (from output.h) which this function simply calls.
|
||||
// It also flushes the stream used and correctly outputs even from multiple threads.
|
||||
inline void dlg_default_output(const struct dlg_origin* o, const char* str, void* data) {
|
||||
(void) o;
|
||||
(void) str;
|
||||
(void) data;
|
||||
}
|
||||
|
||||
// Adds the given tag associated with the given function to the thread specific list.
|
||||
// If func is not NULL the tag will only applied to calls from the same function.
|
||||
// Remove the tag again calling dlg_remove_tag (with exactly the same pointers!).
|
||||
// Does not check if the tag is already present.
|
||||
inline void dlg_add_tag(const char* tag, const char* func) {
|
||||
(void) tag;
|
||||
(void) func;
|
||||
}
|
||||
|
||||
// Removes a tag added with dlg_add_tag (has no effect for tags no present).
|
||||
// The pointers must be exactly the same pointers that were supplied to dlg_add_tag,
|
||||
// this function will not check using strcmp. When the same tag/func combination
|
||||
// is added multiple times, this function remove exactly one candidate, it is
|
||||
// undefined which. Returns whether a tag was found (and removed).
|
||||
inline bool dlg_remove_tag(const char* tag, const char* func) {
|
||||
(void) tag;
|
||||
(void) func;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the thread-specific buffer and its size for dlg.
|
||||
// The buffer should only be used by formatting functions.
|
||||
// The buffer can be reallocated and the size changed, just make sure
|
||||
// to update both values correctly.
|
||||
inline char** dlg_thread_buffer(size_t** size) {
|
||||
(void) size;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else // DLG_DISABLE
|
||||
// Example usages:
|
||||
// dlg_log(dlg_level_warning, "test 1")
|
||||
// dlg_logt(("tag1, "tag2"), dlg_level_debug, "test %d", 2)
|
||||
#define dlg_log(level, ...) if(level >= DLG_LOG_LEVEL) \
|
||||
dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \
|
||||
DLG_FMT_FUNC(__VA_ARGS__), NULL)
|
||||
@ -215,23 +151,31 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string,
|
||||
dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, \
|
||||
DLG_FMT_FUNC(__VA_ARGS__), NULL)
|
||||
|
||||
// Dynamic level assert macros in various versions for additional arguments
|
||||
// Example usages:
|
||||
// dlg_assertl(dlg_level_warning, data != nullptr);
|
||||
// dlg_assertlt(("tag1, "tag2"), dlg_level_trace, data != nullptr);
|
||||
// dlg_asserttlm(("tag1), dlg_level_warning, data != nullptr, "Data must not be null");
|
||||
// dlg_assertlm(dlg_level_error, data != nullptr, "Data must not be null");
|
||||
#define dlg_assertl(level, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
|
||||
dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, #expr)
|
||||
dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, \
|
||||
DLG_FAILED_ASSERTION_TEXT(#expr))
|
||||
#define dlg_assertlt(level, tags, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
|
||||
dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, #expr)
|
||||
dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, \
|
||||
DLG_FAILED_ASSERTION_TEXT(#expr))
|
||||
#define dlg_assertlm(level, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
|
||||
dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \
|
||||
DLG_FMT_FUNC(__VA_ARGS__), #expr)
|
||||
DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
|
||||
#define dlg_assertltm(level, tags, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
|
||||
dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, \
|
||||
__func__, DLG_FMT_FUNC(__VA_ARGS__), #expr)
|
||||
__func__, DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
|
||||
|
||||
DLG_API void dlg_set_handler(dlg_handler handler, void* data);
|
||||
DLG_API dlg_handler dlg_get_handler(void** data);
|
||||
DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*);
|
||||
DLG_API void dlg_add_tag(const char* tag, const char* func);
|
||||
DLG_API bool dlg_remove_tag(const char* tag, const char* func);
|
||||
DLG_API char** dlg_thread_buffer(size_t** size);
|
||||
#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) {\
|
||||
if(level >= DLG_ASSERT_LEVEL) \
|
||||
dlg__do_log(level, tags, DLG_FILE, __LINE__, __func__, msg, \
|
||||
DLG_FAILED_ASSERTION_TEXT(#expr)); \
|
||||
code; \
|
||||
} (void) NULL
|
||||
|
||||
// - Private interface: not part of the abi/api but needed in macros -
|
||||
// Formats the given format string and arguments as printf would, uses the thread buffer.
|
||||
@ -239,8 +183,66 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string,
|
||||
DLG_API void dlg__do_log(enum dlg_level lvl, const char* const*, const char*, int,
|
||||
const char*, const char*, const char*);
|
||||
DLG_API const char* dlg__strip_root_path(const char* file, const char* base);
|
||||
|
||||
#else // DLG_DISABLE
|
||||
|
||||
#define dlg_log(level, ...)
|
||||
#define dlg_logt(level, tags, ...)
|
||||
|
||||
#define dlg_assertl(level, expr) // assert without tags/message
|
||||
#define dlg_assertlt(level, tags, expr) // assert with tags
|
||||
#define dlg_assertlm(level, expr, ...) // assert with message
|
||||
#define dlg_assertltm(level, tags, expr, ...) // assert with tags & message
|
||||
|
||||
#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) { code; } (void) NULL
|
||||
#endif // DLG_DISABLE
|
||||
|
||||
// The API below is independent from DLG_DISABLE
|
||||
|
||||
// Sets the handler that is responsible for formatting and outputting log calls.
|
||||
// This function is not thread safe and the handler is set globally.
|
||||
// The handler itself must not change dlg tags or call a dlg macro (if it
|
||||
// does so, the provided string or tags array in 'origin' might get invalid).
|
||||
// The handler can also be used for various other things such as dealing
|
||||
// with failed assertions or filtering calls based on the passed tags.
|
||||
// The default handler is dlg_default_output (see its doc for more info).
|
||||
// If using c++ make sure the registered handler cannot throw e.g. by
|
||||
// wrapping everything into a try-catch blog.
|
||||
DLG_API void dlg_set_handler(dlg_handler handler, void* data);
|
||||
|
||||
// The default output handler.
|
||||
// Only use this to reset the output handler, prefer to use
|
||||
// dlg_generic_output (from output.h) which this function simply calls.
|
||||
// It also flushes the stream used and correctly outputs even from multiple threads.
|
||||
DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*);
|
||||
|
||||
// Returns the currently active dlg handler and sets `data` to
|
||||
// its user data pointer. `data` must not be NULL.
|
||||
// Useful to create handler chains.
|
||||
// This function is not threadsafe, i.e. retrieving the handler while
|
||||
// changing it from another thread is unsafe.
|
||||
// See `dlg_set_handler`.
|
||||
DLG_API dlg_handler dlg_get_handler(void** data);
|
||||
|
||||
// Adds the given tag associated with the given function to the thread specific list.
|
||||
// If func is not NULL the tag will only applied to calls from the same function.
|
||||
// Remove the tag again calling dlg_remove_tag (with exactly the same pointers!).
|
||||
// Does not check if the tag is already present.
|
||||
DLG_API void dlg_add_tag(const char* tag, const char* func);
|
||||
|
||||
// Removes a tag added with dlg_add_tag (has no effect for tags no present).
|
||||
// The pointers must be exactly the same pointers that were supplied to dlg_add_tag,
|
||||
// this function will not check using strcmp. When the same tag/func combination
|
||||
// is added multiple times, this function remove exactly one candidate, it is
|
||||
// undefined which. Returns whether a tag was found (and removed).
|
||||
DLG_API bool dlg_remove_tag(const char* tag, const char* func);
|
||||
|
||||
// Returns the thread-specific buffer and its size for dlg.
|
||||
// The buffer should only be used by formatting functions.
|
||||
// The buffer can be reallocated and the size changed, just make sure
|
||||
// to update both values correctly.
|
||||
DLG_API char** dlg_thread_buffer(size_t** size);
|
||||
|
||||
// Untagged leveled logging
|
||||
#define dlg_trace(...) dlg_log(dlg_level_trace, __VA_ARGS__)
|
||||
#define dlg_debug(...) dlg_log(dlg_level_debug, __VA_ARGS__)
|
||||
@ -263,6 +265,24 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string,
|
||||
#define dlg_assertm(expr, ...) dlg_assertlm(DLG_DEFAULT_ASSERT, expr, __VA_ARGS__)
|
||||
#define dlg_asserttm(tags, expr, ...) dlg_assertltm(DLG_DEFAULT_ASSERT, tags, expr, __VA_ARGS__)
|
||||
|
||||
// If (expr) does not evaluate to true, always executes 'code' (no matter what
|
||||
// DLG_ASSERT_LEVEL is or if dlg is disabled or not).
|
||||
// When dlg is enabled and the level is greater or equal to DLG_ASSERT_LEVEL,
|
||||
// logs the failed assertion.
|
||||
// Example usages:
|
||||
// dlg_assertl_or(dlg_level_warn, data != nullptr, return);
|
||||
// dlg_assertlm_or(dlg_level_fatal, data != nullptr, return, "Data must not be null");
|
||||
// dlg_assert_or(data != nullptr, logError(); return false);
|
||||
#define dlg_assertltm_or(level, tags, expr, code, ...) dlg__assert_or(level, \
|
||||
DLG_CREATE_TAGS tags, expr, code, DLG_FMT_FUNC(__VA_ARGS__))
|
||||
#define dlg_assertlm_or(level, expr, code, ...) dlg__assert_or(level, \
|
||||
DLG_CREATE_TAGS(NULL), expr, code, DLG_FMT_FUNC(__VA_ARGS__))
|
||||
#define dlg_assertl_or(level, expr, code) dlg__assert_or(level, \
|
||||
DLG_CREATE_TAGS(NULL), expr, code, NULL)
|
||||
|
||||
#define dlg_assert_or(expr, code) dlg_assertl_or(DLG_DEFAULT_ASSERT, expr, code)
|
||||
#define dlg_assertm_or(expr, code, ...) dlg_assertlm_or(DLG_DEFAULT_ASSERT, expr, code, __VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -5222,7 +5222,7 @@ FT_BEGIN_HEADER
|
||||
*/
|
||||
#define FREETYPE_MAJOR 2
|
||||
#define FREETYPE_MINOR 13
|
||||
#define FREETYPE_PATCH 1
|
||||
#define FREETYPE_PATCH 2
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -332,9 +332,9 @@ FT_BEGIN_HEADER
|
||||
* Based on geometric considerations we use the following inequality to
|
||||
* identify a degenerate matrix.
|
||||
*
|
||||
* 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
|
||||
* 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
|
||||
*
|
||||
* Value 50 is heuristic.
|
||||
* Value 32 is heuristic.
|
||||
*/
|
||||
FT_BASE( FT_Bool )
|
||||
FT_Matrix_Check( const FT_Matrix* matrix );
|
||||
|
@ -1394,14 +1394,6 @@ FT_BEGIN_HEADER
|
||||
* vert_metrics_offset ::
|
||||
* The file offset of the 'vmtx' table.
|
||||
*
|
||||
* sph_found_func_flags ::
|
||||
* Flags identifying special bytecode functions (used by the v38
|
||||
* implementation of the bytecode interpreter).
|
||||
*
|
||||
* sph_compatibility_mode ::
|
||||
* This flag is set if we are in ClearType backward compatibility mode
|
||||
* (used by the v38 implementation of the bytecode interpreter).
|
||||
*
|
||||
* ebdt_start ::
|
||||
* The file offset of the sbit data table (CBDT, bdat, etc.).
|
||||
*
|
||||
@ -1597,13 +1589,6 @@ FT_BEGIN_HEADER
|
||||
FT_ULong horz_metrics_offset;
|
||||
FT_ULong vert_metrics_offset;
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
/* since 2.4.12 */
|
||||
FT_ULong sph_found_func_flags; /* special functions found */
|
||||
/* for this face */
|
||||
FT_Bool sph_compatibility_mode;
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
|
||||
/* since 2.7 */
|
||||
FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */
|
||||
|
3
src/3rdparty/freetype/qt_attribution.json
vendored
3
src/3rdparty/freetype/qt_attribution.json
vendored
@ -7,8 +7,7 @@
|
||||
|
||||
"Description": "FreeType is a freely available software library to render fonts.",
|
||||
"Homepage": "http://www.freetype.org",
|
||||
"Version": "2.13.0",
|
||||
|
||||
"Version": "2.13.2",
|
||||
"License": "Freetype Project License or GNU General Public License v2.0 only",
|
||||
"LicenseId": "FTL OR GPL-2.0",
|
||||
"LicenseFile": "LICENSE.txt",
|
||||
|
6
src/3rdparty/freetype/src/autofit/afcjk.c
vendored
6
src/3rdparty/freetype/src/autofit/afcjk.c
vendored
@ -1634,7 +1634,7 @@
|
||||
|
||||
stem_edge->pos = base_edge->pos + fitted_width;
|
||||
|
||||
FT_TRACE5(( " CJKLINK: edge %ld @%d (opos=%.2f) linked to %.2f,"
|
||||
FT_TRACE5(( " CJKLINK: edge %td @%d (opos=%.2f) linked to %.2f,"
|
||||
" dist was %.2f, now %.2f\n",
|
||||
stem_edge - hints->axis[dim].edges, stem_edge->fpos,
|
||||
(double)stem_edge->opos / 64,
|
||||
@ -1858,7 +1858,7 @@
|
||||
continue;
|
||||
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
FT_TRACE5(( " CJKBLUE: edge %ld @%d (opos=%.2f) snapped to %.2f,"
|
||||
FT_TRACE5(( " CJKBLUE: edge %td @%d (opos=%.2f) snapped to %.2f,"
|
||||
" was %.2f\n",
|
||||
edge1 - edges, edge1->fpos, (double)edge1->opos / 64,
|
||||
(double)blue->fit / 64, (double)edge1->pos / 64 ));
|
||||
@ -1922,7 +1922,7 @@
|
||||
/* this should not happen, but it's better to be safe */
|
||||
if ( edge2->blue_edge )
|
||||
{
|
||||
FT_TRACE5(( "ASSERTION FAILED for edge %ld\n", edge2-edges ));
|
||||
FT_TRACE5(( "ASSERTION FAILED for edge %td\n", edge2 - edges ));
|
||||
|
||||
af_cjk_align_linked_edge( hints, dim, edge2, edge );
|
||||
edge->flags |= AF_EDGE_DONE;
|
||||
|
38
src/3rdparty/freetype/src/autofit/aflatin.c
vendored
38
src/3rdparty/freetype/src/autofit/aflatin.c
vendored
@ -1022,7 +1022,7 @@
|
||||
{
|
||||
*a = *b;
|
||||
FT_TRACE5(( "blue zone overlap:"
|
||||
" adjusting %s %ld to %ld\n",
|
||||
" adjusting %s %td to %ld\n",
|
||||
a_is_top ? "overshoot" : "reference",
|
||||
blue_sorted[i] - axis->blues,
|
||||
*a ));
|
||||
@ -2960,7 +2960,7 @@
|
||||
|
||||
stem_edge->pos = base_edge->pos + fitted_width;
|
||||
|
||||
FT_TRACE5(( " LINK: edge %ld (opos=%.2f) linked to %.2f,"
|
||||
FT_TRACE5(( " LINK: edge %td (opos=%.2f) linked to %.2f,"
|
||||
" dist was %.2f, now %.2f\n",
|
||||
stem_edge - hints->axis[dim].edges,
|
||||
(double)stem_edge->opos / 64, (double)stem_edge->pos / 64,
|
||||
@ -3085,13 +3085,13 @@
|
||||
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
if ( !anchor )
|
||||
FT_TRACE5(( " BLUE_ANCHOR: edge %ld (opos=%.2f) snapped to %.2f,"
|
||||
" was %.2f (anchor=edge %ld)\n",
|
||||
FT_TRACE5(( " BLUE_ANCHOR: edge %td (opos=%.2f) snapped to %.2f,"
|
||||
" was %.2f (anchor=edge %td)\n",
|
||||
edge1 - edges,
|
||||
(double)edge1->opos / 64, (double)blue->fit / 64,
|
||||
(double)edge1->pos / 64, edge - edges ));
|
||||
else
|
||||
FT_TRACE5(( " BLUE: edge %ld (opos=%.2f) snapped to %.2f,"
|
||||
FT_TRACE5(( " BLUE: edge %td (opos=%.2f) snapped to %.2f,"
|
||||
" was %.2f\n",
|
||||
edge1 - edges,
|
||||
(double)edge1->opos / 64, (double)blue->fit / 64,
|
||||
@ -3141,7 +3141,7 @@
|
||||
/* this should not happen, but it's better to be safe */
|
||||
if ( edge2->blue_edge )
|
||||
{
|
||||
FT_TRACE5(( " ASSERTION FAILED for edge %ld\n", edge2 - edges ));
|
||||
FT_TRACE5(( " ASSERTION FAILED for edge %td\n", edge2 - edges ));
|
||||
|
||||
af_latin_align_linked_edge( hints, dim, edge2, edge );
|
||||
edge->flags |= AF_EDGE_DONE;
|
||||
@ -3209,7 +3209,7 @@
|
||||
anchor = edge;
|
||||
edge->flags |= AF_EDGE_DONE;
|
||||
|
||||
FT_TRACE5(( " ANCHOR: edge %ld (opos=%.2f) and %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " ANCHOR: edge %td (opos=%.2f) and %td (opos=%.2f)"
|
||||
" snapped to %.2f and %.2f\n",
|
||||
edge - edges, (double)edge->opos / 64,
|
||||
edge2 - edges, (double)edge2->opos / 64,
|
||||
@ -3238,7 +3238,7 @@
|
||||
|
||||
if ( edge2->flags & AF_EDGE_DONE )
|
||||
{
|
||||
FT_TRACE5(( " ADJUST: edge %ld (pos=%.2f) moved to %.2f\n",
|
||||
FT_TRACE5(( " ADJUST: edge %td (pos=%.2f) moved to %.2f\n",
|
||||
edge - edges, (double)edge->pos / 64,
|
||||
(double)( edge2->pos - cur_len ) / 64 ));
|
||||
|
||||
@ -3279,7 +3279,7 @@
|
||||
edge->pos = cur_pos1 - cur_len / 2;
|
||||
edge2->pos = cur_pos1 + cur_len / 2;
|
||||
|
||||
FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)"
|
||||
" snapped to %.2f and %.2f\n",
|
||||
edge - edges, (double)edge->opos / 64,
|
||||
edge2 - edges, (double)edge2->opos / 64,
|
||||
@ -3310,7 +3310,7 @@
|
||||
edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
|
||||
edge2->pos = edge->pos + cur_len;
|
||||
|
||||
FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)"
|
||||
" snapped to %.2f and %.2f\n",
|
||||
edge - edges, (double)edge->opos / 64,
|
||||
edge2 - edges, (double)edge2->opos / 64,
|
||||
@ -3333,7 +3333,7 @@
|
||||
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
|
||||
{
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
|
||||
FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
|
||||
edge - edges,
|
||||
(double)edge->pos / 64,
|
||||
(double)edge[-1].pos / 64 ));
|
||||
@ -3435,7 +3435,7 @@
|
||||
if ( delta < 64 + 16 )
|
||||
{
|
||||
af_latin_align_serif_edge( hints, edge->serif, edge );
|
||||
FT_TRACE5(( " SERIF: edge %ld (opos=%.2f) serif to %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " SERIF: edge %td (opos=%.2f) serif to %td (opos=%.2f)"
|
||||
" aligned to %.2f\n",
|
||||
edge - edges, (double)edge->opos / 64,
|
||||
edge->serif - edges, (double)edge->serif->opos / 64,
|
||||
@ -3445,9 +3445,9 @@
|
||||
{
|
||||
edge->pos = FT_PIX_ROUND( edge->opos );
|
||||
anchor = edge;
|
||||
FT_TRACE5(( " SERIF_ANCHOR: edge %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " SERIF_ANCHOR: edge %td (opos=%.2f)"
|
||||
" snapped to %.2f\n",
|
||||
edge-edges,
|
||||
edge - edges,
|
||||
(double)edge->opos / 64, (double)edge->pos / 64 ));
|
||||
}
|
||||
else
|
||||
@ -3474,8 +3474,8 @@
|
||||
after->pos - before->pos,
|
||||
after->opos - before->opos );
|
||||
|
||||
FT_TRACE5(( " SERIF_LINK1: edge %ld (opos=%.2f) snapped to %.2f"
|
||||
" from %ld (opos=%.2f)\n",
|
||||
FT_TRACE5(( " SERIF_LINK1: edge %td (opos=%.2f) snapped to %.2f"
|
||||
" from %td (opos=%.2f)\n",
|
||||
edge - edges, (double)edge->opos / 64,
|
||||
(double)edge->pos / 64,
|
||||
before - edges, (double)before->opos / 64 ));
|
||||
@ -3484,7 +3484,7 @@
|
||||
{
|
||||
edge->pos = anchor->pos +
|
||||
( ( edge->opos - anchor->opos + 16 ) & ~31 );
|
||||
FT_TRACE5(( " SERIF_LINK2: edge %ld (opos=%.2f)"
|
||||
FT_TRACE5(( " SERIF_LINK2: edge %td (opos=%.2f)"
|
||||
" snapped to %.2f\n",
|
||||
edge - edges,
|
||||
(double)edge->opos / 64, (double)edge->pos / 64 ));
|
||||
@ -3505,7 +3505,7 @@
|
||||
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
|
||||
{
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
|
||||
FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
|
||||
edge - edges,
|
||||
(double)edge->pos / 64,
|
||||
(double)edge[-1].pos / 64 ));
|
||||
@ -3526,7 +3526,7 @@
|
||||
if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
|
||||
{
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n",
|
||||
FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n",
|
||||
edge - edges,
|
||||
(double)edge->pos / 64,
|
||||
(double)edge[1].pos / 64 ));
|
||||
|
84
src/3rdparty/freetype/src/base/ftcalc.c
vendored
84
src/3rdparty/freetype/src/base/ftcalc.c
vendored
@ -749,65 +749,43 @@
|
||||
FT_BASE_DEF( FT_Bool )
|
||||
FT_Matrix_Check( const FT_Matrix* matrix )
|
||||
{
|
||||
FT_Matrix m;
|
||||
FT_Fixed val[4];
|
||||
FT_Fixed nonzero_minval, maxval;
|
||||
FT_Fixed temp1, temp2;
|
||||
FT_UInt i;
|
||||
FT_Fixed xx, xy, yx, yy;
|
||||
FT_Fixed val;
|
||||
FT_Int shift;
|
||||
FT_ULong temp1, temp2;
|
||||
|
||||
|
||||
if ( !matrix )
|
||||
return 0;
|
||||
|
||||
val[0] = FT_ABS( matrix->xx );
|
||||
val[1] = FT_ABS( matrix->xy );
|
||||
val[2] = FT_ABS( matrix->yx );
|
||||
val[3] = FT_ABS( matrix->yy );
|
||||
xx = matrix->xx;
|
||||
xy = matrix->xy;
|
||||
yx = matrix->yx;
|
||||
yy = matrix->yy;
|
||||
val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy );
|
||||
|
||||
/*
|
||||
* To avoid overflow, we ensure that each value is not larger than
|
||||
*
|
||||
* int(sqrt(2^31 / 4)) = 23170 ;
|
||||
*
|
||||
* we also check that no value becomes zero if we have to scale.
|
||||
*/
|
||||
|
||||
maxval = 0;
|
||||
nonzero_minval = FT_LONG_MAX;
|
||||
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( val[i] > maxval )
|
||||
maxval = val[i];
|
||||
if ( val[i] && val[i] < nonzero_minval )
|
||||
nonzero_minval = val[i];
|
||||
}
|
||||
|
||||
/* we only handle 32bit values */
|
||||
if ( maxval > 0x7FFFFFFFL )
|
||||
/* we only handle non-zero 32-bit values */
|
||||
if ( !val || val > 0x7FFFFFFFL )
|
||||
return 0;
|
||||
|
||||
if ( maxval > 23170 )
|
||||
/* Scale matrix to avoid the temp1 overflow, which is */
|
||||
/* more stringent than avoiding the temp2 overflow. */
|
||||
|
||||
shift = FT_MSB( val ) - 12;
|
||||
|
||||
if ( shift > 0 )
|
||||
{
|
||||
FT_Fixed scale = FT_DivFix( maxval, 23170 );
|
||||
|
||||
|
||||
if ( !FT_DivFix( nonzero_minval, scale ) )
|
||||
return 0; /* value range too large */
|
||||
|
||||
m.xx = FT_DivFix( matrix->xx, scale );
|
||||
m.xy = FT_DivFix( matrix->xy, scale );
|
||||
m.yx = FT_DivFix( matrix->yx, scale );
|
||||
m.yy = FT_DivFix( matrix->yy, scale );
|
||||
xx >>= shift;
|
||||
xy >>= shift;
|
||||
yx >>= shift;
|
||||
yy >>= shift;
|
||||
}
|
||||
else
|
||||
m = *matrix;
|
||||
|
||||
temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
|
||||
temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;
|
||||
temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx );
|
||||
temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) +
|
||||
(FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy );
|
||||
|
||||
if ( temp1 == 0 ||
|
||||
temp2 / temp1 > 50 )
|
||||
if ( temp1 <= temp2 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -1092,9 +1070,6 @@
|
||||
{
|
||||
FT_UInt i;
|
||||
FT_Int64 temp;
|
||||
#ifndef FT_INT64
|
||||
FT_Int64 halfUnit;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FT_INT64
|
||||
@ -1139,13 +1114,10 @@
|
||||
FT_Add64( &temp, &multResult, &temp );
|
||||
}
|
||||
|
||||
/* Round value. */
|
||||
halfUnit.hi = 0;
|
||||
halfUnit.lo = 0x8000;
|
||||
FT_Add64( &temp, &halfUnit, &temp );
|
||||
/* Shift and round value. */
|
||||
return (FT_Int32)( ( ( temp.hi << 16 ) | ( temp.lo >> 16 ) )
|
||||
+ ( 1 & ( temp.lo >> 15 ) ) );
|
||||
|
||||
return (FT_Int32)( ( (FT_Int32)( temp.hi & 0xFFFF ) << 16 ) |
|
||||
( temp.lo >> 16 ) );
|
||||
|
||||
#endif /* !FT_INT64 */
|
||||
|
||||
|
3
src/3rdparty/freetype/src/base/ftobjs.c
vendored
3
src/3rdparty/freetype/src/base/ftobjs.c
vendored
@ -1747,7 +1747,8 @@
|
||||
FT_Memory memory = library->memory;
|
||||
|
||||
|
||||
args.flags = 0;
|
||||
args.driver = NULL;
|
||||
args.flags = 0;
|
||||
|
||||
if ( driver_name )
|
||||
{
|
||||
|
8
src/3rdparty/freetype/src/base/ftstream.c
vendored
8
src/3rdparty/freetype/src/base/ftstream.c
vendored
@ -141,7 +141,9 @@
|
||||
if ( read_bytes > count )
|
||||
read_bytes = count;
|
||||
|
||||
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
|
||||
/* Allow "reading" zero bytes without UB even if buffer is NULL */
|
||||
if ( count )
|
||||
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
|
||||
}
|
||||
|
||||
stream->pos = pos + read_bytes;
|
||||
@ -178,7 +180,9 @@
|
||||
if ( read_bytes > count )
|
||||
read_bytes = count;
|
||||
|
||||
FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
|
||||
/* Allow "reading" zero bytes without UB even if buffer is NULL */
|
||||
if ( count )
|
||||
FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
|
||||
}
|
||||
|
||||
stream->pos += read_bytes;
|
||||
|
4
src/3rdparty/freetype/src/base/ftver.rc
vendored
4
src/3rdparty/freetype/src/base/ftver.rc
vendored
@ -18,8 +18,8 @@
|
||||
|
||||
#include<windows.h>
|
||||
|
||||
#define FT_VERSION 2,13,1,0
|
||||
#define FT_VERSION_STR "2.13.1"
|
||||
#define FT_VERSION 2,13,2,0
|
||||
#define FT_VERSION_STR "2.13.2"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION FT_VERSION
|
||||
|
9
src/3rdparty/freetype/src/cff/cffload.c
vendored
9
src/3rdparty/freetype/src/cff/cffload.c
vendored
@ -1361,14 +1361,15 @@
|
||||
for ( i = 0; i < numBlends; i++ )
|
||||
{
|
||||
const FT_Int32* weight = &blend->BV[1];
|
||||
FT_UInt32 sum;
|
||||
FT_Fixed sum;
|
||||
|
||||
|
||||
/* convert inputs to 16.16 fixed-point */
|
||||
sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000;
|
||||
/* convert inputs to 16.16 fixed point */
|
||||
sum = cff_parse_fixed( parser, &parser->stack[i + base] );
|
||||
|
||||
for ( j = 1; j < blend->lenBV; j++ )
|
||||
sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++;
|
||||
sum += FT_MulFix( cff_parse_fixed( parser, &parser->stack[delta++] ),
|
||||
*weight++ );
|
||||
|
||||
/* point parser stack to new value on blend_stack */
|
||||
parser->stack[i + base] = subFont->blend_top;
|
||||
|
22
src/3rdparty/freetype/src/cff/cffparse.c
vendored
22
src/3rdparty/freetype/src/cff/cffparse.c
vendored
@ -499,6 +499,24 @@
|
||||
{
|
||||
if ( **d == 30 )
|
||||
return cff_parse_real( *d, parser->limit, scaling, NULL );
|
||||
else if ( **d == 255 )
|
||||
{
|
||||
FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
|
||||
( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
|
||||
( (FT_UInt32)*( d[0] + 3 ) << 8 ) |
|
||||
(FT_UInt32)*( d[0] + 4 ) ) );
|
||||
|
||||
if ( scaling )
|
||||
{
|
||||
if ( FT_ABS( val ) > power_ten_limits[scaling] )
|
||||
{
|
||||
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
||||
return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
|
||||
}
|
||||
val *= power_tens[scaling];
|
||||
}
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Long val = cff_parse_integer( *d, parser->limit );
|
||||
@ -506,7 +524,7 @@
|
||||
|
||||
if ( scaling )
|
||||
{
|
||||
if ( FT_ABS( val ) > power_ten_limits[scaling] )
|
||||
if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] )
|
||||
{
|
||||
val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
|
||||
goto Overflow;
|
||||
@ -536,7 +554,7 @@
|
||||
|
||||
|
||||
/* read a floating point number, either integer or real */
|
||||
static FT_Fixed
|
||||
FT_LOCAL_DEF( FT_Fixed )
|
||||
cff_parse_fixed( CFF_Parser parser,
|
||||
FT_Byte** d )
|
||||
{
|
||||
|
4
src/3rdparty/freetype/src/cff/cffparse.h
vendored
4
src/3rdparty/freetype/src/cff/cffparse.h
vendored
@ -76,6 +76,10 @@ FT_BEGIN_HEADER
|
||||
cff_parse_num( CFF_Parser parser,
|
||||
FT_Byte** d );
|
||||
|
||||
FT_LOCAL( FT_Fixed )
|
||||
cff_parse_fixed( CFF_Parser parser,
|
||||
FT_Byte** d );
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
cff_parser_init( CFF_Parser parser,
|
||||
FT_UInt code,
|
||||
|
644
src/3rdparty/freetype/src/gzip/infback.c
vendored
644
src/3rdparty/freetype/src/gzip/infback.c
vendored
@ -1,644 +0,0 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(
|
||||
z_streamp strm,
|
||||
int windowBits,
|
||||
unsigned char FAR *window,
|
||||
const char *version,
|
||||
int stream_size)
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = (uInt)windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->wnext = 0;
|
||||
state->whave = 0;
|
||||
state->sane = 1;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(
|
||||
struct inflate_state FAR *state)
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(
|
||||
z_streamp strm,
|
||||
in_func in,
|
||||
void FAR *in_desc,
|
||||
out_func out,
|
||||
void FAR *out_desc)
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code here; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
else {
|
||||
if (here.val == 16) {
|
||||
NEEDBITS(here.bits + 2);
|
||||
DROPBITS(here.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (here.val == 17) {
|
||||
NEEDBITS(here.bits + 3);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(here.bits + 7);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* check for end-of-block code (better have one) */
|
||||
if (state->lens[256] == 0) {
|
||||
strm->msg = (char *)"invalid code -- missing end-of-block";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* build code tables -- note: do not change the lenbits or distbits
|
||||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
/* fallthrough */
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.op && (here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
state->length = (unsigned)here.val;
|
||||
|
||||
/* process literal */
|
||||
if (here.op == 0) {
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (here.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)here.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly */
|
||||
ret = Z_STREAM_END;
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default:
|
||||
/* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Write leftover output and return unused input */
|
||||
inf_leave:
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left) &&
|
||||
ret == Z_STREAM_END)
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(
|
||||
z_streamp strm)
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
33
src/3rdparty/freetype/src/gzip/rules.mk
vendored
33
src/3rdparty/freetype/src/gzip/rules.mk
vendored
@ -36,24 +36,23 @@ endif
|
||||
#
|
||||
# All source and header files get loaded by `ftgzip.c' only if SYSTEM_ZLIB
|
||||
# is not defined (regardless whether we have a `single' or a `multi' build).
|
||||
# However, it doesn't harm if we add everything as a dependency
|
||||
# unconditionally.
|
||||
#
|
||||
GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \
|
||||
$(GZIP_DIR)/crc32.c \
|
||||
$(GZIP_DIR)/crc32.h \
|
||||
$(GZIP_DIR)/ftzconf.h \
|
||||
$(GZIP_DIR)/inffast.c \
|
||||
$(GZIP_DIR)/inffast.h \
|
||||
$(GZIP_DIR)/inffixed.h \
|
||||
$(GZIP_DIR)/inflate.c \
|
||||
$(GZIP_DIR)/inflate.h \
|
||||
$(GZIP_DIR)/inftrees.c \
|
||||
$(GZIP_DIR)/inftrees.h \
|
||||
$(GZIP_DIR)/zlib.h \
|
||||
$(GZIP_DIR)/zutil.c \
|
||||
$(GZIP_DIR)/zutil.h
|
||||
|
||||
ifeq ($(SYSTEM_ZLIB),)
|
||||
GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \
|
||||
$(GZIP_DIR)/crc32.c \
|
||||
$(GZIP_DIR)/crc32.h \
|
||||
$(GZIP_DIR)/ftzconf.h \
|
||||
$(GZIP_DIR)/inffast.c \
|
||||
$(GZIP_DIR)/inffast.h \
|
||||
$(GZIP_DIR)/inffixed.h \
|
||||
$(GZIP_DIR)/inflate.c \
|
||||
$(GZIP_DIR)/inflate.h \
|
||||
$(GZIP_DIR)/inftrees.c \
|
||||
$(GZIP_DIR)/inftrees.h \
|
||||
$(GZIP_DIR)/zlib.h \
|
||||
$(GZIP_DIR)/zutil.c \
|
||||
$(GZIP_DIR)/zutil.h
|
||||
endif
|
||||
|
||||
# gzip driver object(s)
|
||||
#
|
||||
|
6
src/3rdparty/freetype/src/psaux/cffdecode.c
vendored
6
src/3rdparty/freetype/src/psaux/cffdecode.c
vendored
@ -2153,7 +2153,7 @@
|
||||
decoder->locals_bias );
|
||||
|
||||
|
||||
FT_TRACE4(( " callsubr (idx %d, entering level %ld)\n",
|
||||
FT_TRACE4(( " callsubr (idx %d, entering level %td)\n",
|
||||
idx,
|
||||
zone - decoder->zones + 1 ));
|
||||
|
||||
@ -2197,7 +2197,7 @@
|
||||
decoder->globals_bias );
|
||||
|
||||
|
||||
FT_TRACE4(( " callgsubr (idx %d, entering level %ld)\n",
|
||||
FT_TRACE4(( " callgsubr (idx %d, entering level %td)\n",
|
||||
idx,
|
||||
zone - decoder->zones + 1 ));
|
||||
|
||||
@ -2236,7 +2236,7 @@
|
||||
break;
|
||||
|
||||
case cff_op_return:
|
||||
FT_TRACE4(( " return (leaving level %ld)\n",
|
||||
FT_TRACE4(( " return (leaving level %td)\n",
|
||||
decoder->zone - decoder->zones ));
|
||||
|
||||
if ( decoder->zone <= decoder->zones )
|
||||
|
2
src/3rdparty/freetype/src/psaux/pshints.c
vendored
2
src/3rdparty/freetype/src/psaux/pshints.c
vendored
@ -310,7 +310,7 @@
|
||||
CF2_Hint hint = &hintmap->edge[i];
|
||||
|
||||
|
||||
FT_TRACE6(( " %3ld %7.2f %7.2f %5d %s%s%s%s\n",
|
||||
FT_TRACE6(( " %3zu %7.2f %7.2f %5d %s%s%s%s\n",
|
||||
hint->index,
|
||||
hint->csCoord / 65536.0,
|
||||
hint->dsCoord / ( hint->scale * 1.0 ),
|
||||
|
4
src/3rdparty/freetype/src/psaux/t1decode.c
vendored
4
src/3rdparty/freetype/src/psaux/t1decode.c
vendored
@ -520,7 +520,7 @@
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
if ( bol )
|
||||
{
|
||||
FT_TRACE5(( " (%ld)", decoder->top - decoder->stack ));
|
||||
FT_TRACE5(( " (%td)", decoder->top - decoder->stack ));
|
||||
bol = FALSE;
|
||||
}
|
||||
#endif
|
||||
@ -1165,7 +1165,7 @@
|
||||
if ( top - decoder->stack != num_args )
|
||||
FT_TRACE0(( "t1_decoder_parse_charstrings:"
|
||||
" too much operands on the stack"
|
||||
" (seen %ld, expected %d)\n",
|
||||
" (seen %td, expected %d)\n",
|
||||
top - decoder->stack, num_args ));
|
||||
break;
|
||||
}
|
||||
|
18
src/3rdparty/freetype/src/sfnt/sfwoff2.c
vendored
18
src/3rdparty/freetype/src/sfnt/sfwoff2.c
vendored
@ -36,6 +36,8 @@
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT sfwoff2
|
||||
|
||||
/* An arbitrary, heuristic size limit (67MByte) for expanded WOFF2 data. */
|
||||
#define MAX_SFNT_SIZE ( 1 << 26 )
|
||||
|
||||
#define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) )
|
||||
|
||||
@ -2180,9 +2182,8 @@
|
||||
else
|
||||
sfnt_size = woff2.totalSfntSize;
|
||||
|
||||
/* Value 1<<26 = 67108864 is heuristic. */
|
||||
if (sfnt_size >= (1 << 26))
|
||||
sfnt_size = 1 << 26;
|
||||
if ( sfnt_size >= MAX_SFNT_SIZE )
|
||||
sfnt_size = MAX_SFNT_SIZE;
|
||||
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
if ( sfnt_size != woff2.totalSfntSize )
|
||||
@ -2257,10 +2258,15 @@
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( woff2.uncompressed_size > sfnt_size )
|
||||
/* We must not blindly trust `uncompressed_size` since its */
|
||||
/* value might be corrupted. If it is too large, reject the */
|
||||
/* font. In other words, we don't accept a WOFF2 font that */
|
||||
/* expands to something larger than MAX_SFNT_SIZE. If ever */
|
||||
/* necessary, this limit can be easily adjusted. */
|
||||
if ( woff2.uncompressed_size > MAX_SFNT_SIZE )
|
||||
{
|
||||
FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
FT_ERROR(( "Uncompressed font too large.\n" ));
|
||||
error = FT_THROW( Array_Too_Large );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
4
src/3rdparty/freetype/src/sfnt/ttcolr.c
vendored
4
src/3rdparty/freetype/src/sfnt/ttcolr.c
vendored
@ -229,7 +229,7 @@
|
||||
|
||||
base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
|
||||
|
||||
if ( base_glyphs_offset_v1 + 4 >= table_size )
|
||||
if ( base_glyphs_offset_v1 >= table_size - 4 )
|
||||
goto InvalidTable;
|
||||
|
||||
p1 = (FT_Byte*)( table + base_glyphs_offset_v1 );
|
||||
@ -249,7 +249,7 @@
|
||||
|
||||
if ( layer_offset_v1 )
|
||||
{
|
||||
if ( layer_offset_v1 + 4 >= table_size )
|
||||
if ( layer_offset_v1 >= table_size - 4 )
|
||||
goto InvalidTable;
|
||||
|
||||
p1 = (FT_Byte*)( table + layer_offset_v1 );
|
||||
|
11
src/3rdparty/freetype/src/smooth/ftgrays.c
vendored
11
src/3rdparty/freetype/src/smooth/ftgrays.c
vendored
@ -1006,10 +1006,11 @@ typedef ptrdiff_t FT_PtrDist;
|
||||
*
|
||||
* For other cases, using binary splits is actually slightly faster.
|
||||
*/
|
||||
#if defined( __SSE2__ ) || \
|
||||
( defined( __x86_64__ ) && !defined( __VMS ) ) || \
|
||||
defined( _M_AMD64 ) || \
|
||||
( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 )
|
||||
#if ( defined( __SSE2__ ) || \
|
||||
defined( __x86_64__ ) || \
|
||||
defined( _M_AMD64 ) || \
|
||||
( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
|
||||
!defined( __VMS )
|
||||
# define FT_SSE2 1
|
||||
#else
|
||||
# define FT_SSE2 0
|
||||
@ -1933,7 +1934,7 @@ typedef ptrdiff_t FT_PtrDist;
|
||||
if ( continued )
|
||||
FT_Trace_Enable();
|
||||
|
||||
FT_TRACE7(( "band [%d..%d]: %ld cell%s remaining/\n",
|
||||
FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
|
||||
ras.min_ey,
|
||||
ras.max_ey,
|
||||
ras.cell_null - ras.cell_free,
|
||||
|
3
src/3rdparty/freetype/src/truetype/rules.mk
vendored
3
src/3rdparty/freetype/src/truetype/rules.mk
vendored
@ -33,8 +33,7 @@ TT_DRV_SRC := $(TT_DIR)/ttdriver.c \
|
||||
$(TT_DIR)/ttgxvar.c \
|
||||
$(TT_DIR)/ttinterp.c \
|
||||
$(TT_DIR)/ttobjs.c \
|
||||
$(TT_DIR)/ttpload.c \
|
||||
$(TT_DIR)/ttsubpix.c
|
||||
$(TT_DIR)/ttpload.c
|
||||
|
||||
# TrueType driver headers
|
||||
#
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "ttinterp.c"
|
||||
#include "ttobjs.c" /* object manager */
|
||||
#include "ttpload.c" /* tables loader */
|
||||
#include "ttsubpix.c"
|
||||
|
||||
|
||||
/* END */
|
||||
|
@ -100,11 +100,6 @@
|
||||
break;
|
||||
|
||||
case TT_INTERPRETER_VERSION_38:
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TT_INTERPRETER_VERSION_40:
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
driver->interpreter_version = TT_INTERPRETER_VERSION_40;
|
||||
|
295
src/3rdparty/freetype/src/truetype/ttgload.c
vendored
295
src/3rdparty/freetype/src/truetype/ttgload.c
vendored
@ -35,7 +35,6 @@
|
||||
#endif
|
||||
|
||||
#include "tterrors.h"
|
||||
#include "ttsubpix.h"
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
@ -152,9 +151,6 @@
|
||||
FT_UInt glyph_index )
|
||||
{
|
||||
TT_Face face = loader->face;
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
|
||||
#endif
|
||||
|
||||
FT_Error error;
|
||||
FT_Stream stream = loader->stream;
|
||||
@ -183,20 +179,6 @@
|
||||
loader->top_bearing = top_bearing;
|
||||
loader->vadvance = advance_height;
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
||||
loader->exec )
|
||||
{
|
||||
loader->exec->sph_tweak_flags = 0;
|
||||
|
||||
/* This may not be the right place for this, but it works... */
|
||||
/* Note that we have to unconditionally load the tweaks since */
|
||||
/* it is possible that glyphs individually switch ClearType's */
|
||||
/* backward compatibility mode on and off. */
|
||||
sph_set_tweaks( loader, glyph_index );
|
||||
}
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||
/* With the incremental interface, these values are set by */
|
||||
/* a call to `tt_get_metrics_incremental'. */
|
||||
@ -798,8 +780,7 @@
|
||||
TT_Hint_Glyph( TT_Loader loader,
|
||||
FT_Bool is_composite )
|
||||
{
|
||||
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
|
||||
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
TT_Face face = loader->face;
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
|
||||
#endif
|
||||
@ -820,7 +801,7 @@
|
||||
FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
|
||||
|
||||
/* Reset graphics state. */
|
||||
loader->exec->GS = loader->size->GS;
|
||||
exec->GS = loader->size->GS;
|
||||
|
||||
/* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
|
||||
/* completely refer to the (already) hinted subglyphs. */
|
||||
@ -860,7 +841,7 @@
|
||||
exec->is_composite = is_composite;
|
||||
exec->pts = *zone;
|
||||
|
||||
error = TT_Run_Context( loader->exec );
|
||||
error = TT_Run_Context( exec );
|
||||
if ( error && exec->pedantic_hinting )
|
||||
return error;
|
||||
|
||||
@ -871,32 +852,20 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
/* Save possibly modified glyph phantom points unless in v40 backward */
|
||||
/* compatibility mode, where no movement on the x axis means no reason */
|
||||
/* to change bearings or advance widths. */
|
||||
if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
||||
exec->backward_compatibility ) )
|
||||
{
|
||||
#endif
|
||||
loader->pp1 = zone->cur[zone->n_points - 4];
|
||||
loader->pp2 = zone->cur[zone->n_points - 3];
|
||||
loader->pp3 = zone->cur[zone->n_points - 2];
|
||||
loader->pp4 = zone->cur[zone->n_points - 1];
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
}
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
||||
exec->backward_compatibility )
|
||||
return FT_Err_Ok;
|
||||
#endif
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
|
||||
{
|
||||
if ( exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
|
||||
FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
|
||||
|
||||
else if ( exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
|
||||
FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
|
||||
}
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
loader->pp1 = zone->cur[zone->n_points - 4];
|
||||
loader->pp2 = zone->cur[zone->n_points - 3];
|
||||
loader->pp3 = zone->cur[zone->n_points - 2];
|
||||
loader->pp4 = zone->cur[zone->n_points - 1];
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
@ -960,16 +929,6 @@
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
TT_Face face = loader->face;
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
|
||||
|
||||
FT_String* family = face->root.family_name;
|
||||
FT_UInt ppem = loader->size->metrics->x_ppem;
|
||||
FT_String* style = face->root.style_name;
|
||||
FT_UInt x_scale_factor = 1000;
|
||||
#endif
|
||||
|
||||
FT_Vector* vec = outline->points;
|
||||
FT_Vector* limit = outline->points + n_points;
|
||||
|
||||
@ -979,52 +938,6 @@
|
||||
FT_Bool do_scale = FALSE;
|
||||
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
|
||||
{
|
||||
/* scale, but only if enabled and only if TT hinting is being used */
|
||||
if ( IS_HINTED( loader->load_flags ) )
|
||||
x_scale_factor = sph_test_tweak_x_scaling( face,
|
||||
family,
|
||||
ppem,
|
||||
style,
|
||||
loader->glyph_index );
|
||||
/* scale the glyph */
|
||||
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
|
||||
x_scale_factor != 1000 )
|
||||
{
|
||||
x_scale = FT_MulDiv( loader->size->metrics->x_scale,
|
||||
(FT_Long)x_scale_factor, 1000 );
|
||||
y_scale = loader->size->metrics->y_scale;
|
||||
|
||||
/* compensate for any scaling by de/emboldening; */
|
||||
/* the amount was determined via experimentation */
|
||||
if ( x_scale_factor != 1000 && ppem > 11 )
|
||||
{
|
||||
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
||||
FT_Vector* orig_points = outline->points;
|
||||
|
||||
|
||||
if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
|
||||
outline->points = unrounded;
|
||||
#endif
|
||||
FT_Outline_EmboldenXY( outline,
|
||||
FT_MulFix( 1280 * ppem,
|
||||
1000 - x_scale_factor ),
|
||||
0 );
|
||||
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
||||
if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
|
||||
outline->points = orig_points;
|
||||
#endif
|
||||
}
|
||||
do_scale = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
{
|
||||
/* scale the glyph */
|
||||
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
|
||||
@ -1451,45 +1364,31 @@
|
||||
static void
|
||||
tt_loader_set_pp( TT_Loader loader )
|
||||
{
|
||||
FT_Bool subpixel_hinting = 0;
|
||||
FT_Bool grayscale = 0;
|
||||
FT_Bool use_aw_2 = 0;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
|
||||
{
|
||||
subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
|
||||
: 0;
|
||||
grayscale = loader->exec ? loader->exec->grayscale
|
||||
: 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
|
||||
{
|
||||
subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
|
||||
: 0;
|
||||
grayscale = loader->exec ? loader->exec->grayscale_cleartype
|
||||
: 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
use_aw_2 = FT_BOOL( subpixel_hinting && grayscale );
|
||||
|
||||
loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
|
||||
loader->pp1.y = 0;
|
||||
loader->pp2.x = loader->pp1.x + loader->advance;
|
||||
loader->pp2.y = 0;
|
||||
|
||||
loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
|
||||
loader->pp3.x = 0;
|
||||
loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
|
||||
loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
|
||||
loader->pp4.x = 0;
|
||||
loader->pp4.y = loader->pp3.y - loader->vadvance;
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
{
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
|
||||
|
||||
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
||||
loader->exec &&
|
||||
loader->exec->subpixel_hinting_lean &&
|
||||
loader->exec->grayscale_cleartype )
|
||||
{
|
||||
loader->pp3.x = loader->advance / 2;
|
||||
loader->pp4.x = loader->advance / 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -2277,8 +2176,7 @@
|
||||
#ifdef TT_USE_BYTECODE_INTERPRETER
|
||||
FT_Error error;
|
||||
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
|
||||
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
|
||||
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
|
||||
#endif
|
||||
#endif
|
||||
@ -2298,20 +2196,6 @@
|
||||
FT_Bool grayscale_cleartype;
|
||||
#endif
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
FT_Bool subpixel_hinting = FALSE;
|
||||
|
||||
#if 0
|
||||
/* not used yet */
|
||||
FT_Bool compatible_widths;
|
||||
FT_Bool symmetrical_smoothing;
|
||||
FT_Bool bgr;
|
||||
FT_Bool vertical_lcd;
|
||||
FT_Bool subpixel_positioned;
|
||||
FT_Bool gray_cleartype;
|
||||
#endif
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
FT_Bool reexecute = FALSE;
|
||||
|
||||
|
||||
@ -2331,6 +2215,9 @@
|
||||
if ( !exec )
|
||||
return FT_THROW( Could_Not_Find_Context );
|
||||
|
||||
grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
FT_RENDER_MODE_MONO );
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
|
||||
{
|
||||
@ -2347,6 +2234,7 @@
|
||||
FT_BOOL( subpixel_hinting_lean &&
|
||||
( load_flags &
|
||||
FT_LOAD_TARGET_LCD_V ) );
|
||||
grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2356,111 +2244,11 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
|
||||
{
|
||||
subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
FT_RENDER_MODE_MONO ) &&
|
||||
SPH_OPTION_SET_SUBPIXEL );
|
||||
|
||||
if ( subpixel_hinting )
|
||||
grayscale = FALSE;
|
||||
else if ( SPH_OPTION_SET_GRAYSCALE )
|
||||
{
|
||||
grayscale = TRUE;
|
||||
subpixel_hinting = FALSE;
|
||||
}
|
||||
else
|
||||
grayscale = FALSE;
|
||||
|
||||
if ( FT_IS_TRICKY( glyph->face ) )
|
||||
subpixel_hinting = FALSE;
|
||||
|
||||
exec->ignore_x_mode = subpixel_hinting || grayscale;
|
||||
exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
|
||||
if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
|
||||
exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
|
||||
|
||||
#if 1
|
||||
exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
|
||||
exec->symmetrical_smoothing = TRUE;
|
||||
exec->bgr = FALSE;
|
||||
exec->vertical_lcd = FALSE;
|
||||
exec->subpixel_positioned = TRUE;
|
||||
exec->gray_cleartype = FALSE;
|
||||
#else /* 0 */
|
||||
exec->compatible_widths =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_COMPATIBLE_WIDTHS );
|
||||
exec->symmetrical_smoothing =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_SYMMETRICAL_SMOOTHING );
|
||||
exec->bgr =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_BGR );
|
||||
exec->vertical_lcd =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_VERTICAL_LCD );
|
||||
exec->subpixel_positioned =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_SUBPIXEL_POSITIONED );
|
||||
exec->gray_cleartype =
|
||||
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
TT_LOAD_GRAY_CLEARTYPE );
|
||||
#endif /* 0 */
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
|
||||
grayscale = FT_BOOL( !subpixel_hinting_lean &&
|
||||
FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
FT_RENDER_MODE_MONO );
|
||||
else
|
||||
#endif
|
||||
grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
|
||||
FT_RENDER_MODE_MONO );
|
||||
|
||||
error = TT_Load_Context( exec, face, size );
|
||||
if ( error )
|
||||
return error;
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
|
||||
{
|
||||
/* a change from mono to subpixel rendering (and vice versa) */
|
||||
/* requires a re-execution of the CVT program */
|
||||
if ( subpixel_hinting != exec->subpixel_hinting )
|
||||
{
|
||||
FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
|
||||
" re-executing `prep' table\n" ));
|
||||
|
||||
exec->subpixel_hinting = subpixel_hinting;
|
||||
reexecute = TRUE;
|
||||
}
|
||||
|
||||
/* a change from mono to grayscale rendering (and vice versa) */
|
||||
/* requires a re-execution of the CVT program */
|
||||
if ( grayscale != exec->grayscale )
|
||||
{
|
||||
FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
|
||||
" re-executing `prep' table\n" ));
|
||||
|
||||
exec->grayscale = grayscale;
|
||||
reexecute = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
{
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
|
||||
{
|
||||
@ -2518,14 +2306,6 @@
|
||||
if ( exec->GS.instruct_control & 2 )
|
||||
exec->GS = tt_default_graphics_state;
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
/* check whether we have a font hinted for ClearType -- */
|
||||
/* note that this flag can also be modified in a glyph's bytecode */
|
||||
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
||||
exec->GS.instruct_control & 4 )
|
||||
exec->ignore_x_mode = FALSE;
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
/*
|
||||
* Toggle backward compatibility according to what font wants, except
|
||||
@ -2561,13 +2341,6 @@
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
!( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
||||
exec->backward_compatibility ) &&
|
||||
#endif
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
!( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
||||
!SPH_OPTION_BITMAP_WIDTHS &&
|
||||
FT_LOAD_TARGET_MODE( loader->load_flags ) !=
|
||||
FT_RENDER_MODE_MONO &&
|
||||
exec->compatible_widths ) &&
|
||||
#endif
|
||||
!face->postscript.isFixedPitch )
|
||||
{
|
||||
|
8
src/3rdparty/freetype/src/truetype/ttgxvar.c
vendored
8
src/3rdparty/freetype/src/truetype/ttgxvar.c
vendored
@ -621,10 +621,10 @@
|
||||
{
|
||||
GX_ItemVarData varData = &itemStore->varData[i];
|
||||
|
||||
FT_UInt item_count;
|
||||
FT_UInt word_delta_count;
|
||||
FT_UInt region_idx_count;
|
||||
FT_UInt per_region_size;
|
||||
FT_UInt item_count;
|
||||
FT_UShort word_delta_count;
|
||||
FT_UInt region_idx_count;
|
||||
FT_UInt per_region_size;
|
||||
|
||||
|
||||
if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) )
|
||||
|
838
src/3rdparty/freetype/src/truetype/ttinterp.c
vendored
838
src/3rdparty/freetype/src/truetype/ttinterp.c
vendored
File diff suppressed because it is too large
Load Diff
74
src/3rdparty/freetype/src/truetype/ttinterp.h
vendored
74
src/3rdparty/freetype/src/truetype/ttinterp.h
vendored
@ -98,48 +98,6 @@ FT_BEGIN_HEADER
|
||||
} TT_CallRec, *TT_CallStack;
|
||||
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* These structures define rules used to tweak subpixel hinting for
|
||||
* various fonts. "", 0, "", NULL value indicates to match any value.
|
||||
*/
|
||||
|
||||
#define SPH_MAX_NAME_SIZE 32
|
||||
#define SPH_MAX_CLASS_MEMBERS 100
|
||||
|
||||
typedef struct SPH_TweakRule_
|
||||
{
|
||||
const char family[SPH_MAX_NAME_SIZE];
|
||||
const FT_UInt ppem;
|
||||
const char style[SPH_MAX_NAME_SIZE];
|
||||
const FT_ULong glyph;
|
||||
|
||||
} SPH_TweakRule;
|
||||
|
||||
|
||||
typedef struct SPH_ScaleRule_
|
||||
{
|
||||
const char family[SPH_MAX_NAME_SIZE];
|
||||
const FT_UInt ppem;
|
||||
const char style[SPH_MAX_NAME_SIZE];
|
||||
const FT_ULong glyph;
|
||||
const FT_ULong scale;
|
||||
|
||||
} SPH_ScaleRule;
|
||||
|
||||
|
||||
typedef struct SPH_Font_Class_
|
||||
{
|
||||
const char name[SPH_MAX_NAME_SIZE];
|
||||
const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE];
|
||||
|
||||
} SPH_Font_Class;
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* The main structure for the interpreter which collects all necessary
|
||||
@ -399,38 +357,6 @@ FT_BEGIN_HEADER
|
||||
FT_Bool grayscale_cleartype;
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
TT_Round_Func func_round_sphn; /* subpixel rounding function */
|
||||
|
||||
FT_Bool subpixel_hinting; /* Using subpixel hinting? */
|
||||
FT_Bool ignore_x_mode; /* Standard rendering mode for */
|
||||
/* subpixel hinting. On if gray */
|
||||
/* or subpixel hinting is on. */
|
||||
|
||||
/* The following 6 aren't fully implemented but here for MS rasterizer */
|
||||
/* compatibility. */
|
||||
FT_Bool compatible_widths; /* compatible widths? */
|
||||
FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */
|
||||
FT_Bool bgr; /* bgr instead of rgb? */
|
||||
FT_Bool vertical_lcd; /* long side of LCD subpixel */
|
||||
/* rectangles is horizontal */
|
||||
FT_Bool subpixel_positioned; /* subpixel positioned */
|
||||
/* (DirectWrite ClearType)? */
|
||||
FT_Bool gray_cleartype; /* ClearType hinting but */
|
||||
/* grayscale rendering */
|
||||
|
||||
FT_Int rasterizer_version; /* MS rasterizer version */
|
||||
|
||||
FT_Bool iup_called; /* IUP called for glyph? */
|
||||
|
||||
FT_ULong sph_tweak_flags; /* flags to control */
|
||||
/* hint tweaks */
|
||||
|
||||
FT_ULong sph_in_func_flags; /* flags to indicate if in */
|
||||
/* special functions */
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
/* We maintain two counters (in addition to the instruction counter) */
|
||||
/* that act as loop detectors for LOOPCALL and jump opcodes with */
|
||||
/* negative arguments. */
|
||||
|
3
src/3rdparty/freetype/src/truetype/ttobjs.c
vendored
3
src/3rdparty/freetype/src/truetype/ttobjs.c
vendored
@ -1481,9 +1481,6 @@
|
||||
TT_Driver driver = (TT_Driver)ttdriver;
|
||||
|
||||
driver->interpreter_version = TT_INTERPRETER_VERSION_35;
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
|
||||
#endif
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
||||
driver->interpreter_version = TT_INTERPRETER_VERSION_40;
|
||||
#endif
|
||||
|
2
src/3rdparty/freetype/src/truetype/ttobjs.h
vendored
2
src/3rdparty/freetype/src/truetype/ttobjs.h
vendored
@ -162,8 +162,6 @@ FT_BEGIN_HEADER
|
||||
FT_Long end; /* where does it end? */
|
||||
FT_UInt opc; /* function #, or instruction code */
|
||||
FT_Bool active; /* is it active? */
|
||||
FT_Bool inline_delta; /* is function that defines inline delta? */
|
||||
FT_ULong sph_fdef_flags; /* flags to identify special functions */
|
||||
|
||||
} TT_DefRecord, *TT_DefArray;
|
||||
|
||||
|
1013
src/3rdparty/freetype/src/truetype/ttsubpix.c
vendored
1013
src/3rdparty/freetype/src/truetype/ttsubpix.c
vendored
File diff suppressed because it is too large
Load Diff
110
src/3rdparty/freetype/src/truetype/ttsubpix.h
vendored
110
src/3rdparty/freetype/src/truetype/ttsubpix.h
vendored
@ -1,110 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* ttsubpix.h
|
||||
*
|
||||
* TrueType Subpixel Hinting.
|
||||
*
|
||||
* Copyright (C) 2010-2023 by
|
||||
* David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
*
|
||||
* This file is part of the FreeType project, and may only be used,
|
||||
* modified, and distributed under the terms of the FreeType project
|
||||
* license, LICENSE.TXT. By continuing to use, modify, or distribute
|
||||
* this file you indicate that you have read the license and
|
||||
* understand and accept it fully.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TTSUBPIX_H_
|
||||
#define TTSUBPIX_H_
|
||||
|
||||
#include "ttobjs.h"
|
||||
#include "ttinterp.h"
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* ID flags to identify special functions at FDEF and runtime.
|
||||
*
|
||||
*/
|
||||
#define SPH_FDEF_INLINE_DELTA_1 0x0000001
|
||||
#define SPH_FDEF_INLINE_DELTA_2 0x0000002
|
||||
#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
|
||||
#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008
|
||||
#define SPH_FDEF_TTFAUTOHINT_1 0x0000010
|
||||
#define SPH_FDEF_SPACING_1 0x0000020
|
||||
#define SPH_FDEF_SPACING_2 0x0000040
|
||||
#define SPH_FDEF_TYPEMAN_STROKES 0x0000080
|
||||
#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Tweak flags that are set for each glyph by the below rules.
|
||||
*
|
||||
*/
|
||||
#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL
|
||||
#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL
|
||||
#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL
|
||||
#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL
|
||||
#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL
|
||||
#define SPH_TWEAK_DO_SHPIX 0x0000020UL
|
||||
#define SPH_TWEAK_EMBOLDEN 0x0000040UL
|
||||
#define SPH_TWEAK_MIAP_HACK 0x0000080UL
|
||||
#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL
|
||||
#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL
|
||||
#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL
|
||||
#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL
|
||||
#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL
|
||||
#define SPH_TWEAK_RASTERIZER_35 0x0002000UL
|
||||
#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL
|
||||
#define SPH_TWEAK_SKIP_IUP 0x0008000UL
|
||||
#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL
|
||||
#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL
|
||||
#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL
|
||||
#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL
|
||||
|
||||
|
||||
FT_LOCAL( FT_Bool )
|
||||
sph_test_tweak( TT_Face face,
|
||||
const FT_String* family,
|
||||
FT_UInt ppem,
|
||||
const FT_String* style,
|
||||
FT_UInt glyph_index,
|
||||
const SPH_TweakRule* rule,
|
||||
FT_UInt num_rules );
|
||||
|
||||
FT_LOCAL( FT_UInt )
|
||||
sph_test_tweak_x_scaling( TT_Face face,
|
||||
const FT_String* family,
|
||||
FT_UInt ppem,
|
||||
const FT_String* style,
|
||||
FT_UInt glyph_index );
|
||||
|
||||
FT_LOCAL( void )
|
||||
sph_set_tweaks( TT_Loader loader,
|
||||
FT_UInt glyph_index );
|
||||
|
||||
|
||||
/* These macros are defined absent a method for setting them */
|
||||
#define SPH_OPTION_BITMAP_WIDTHS FALSE
|
||||
#define SPH_OPTION_SET_SUBPIXEL TRUE
|
||||
#define SPH_OPTION_SET_GRAYSCALE FALSE
|
||||
#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE
|
||||
#define SPH_OPTION_SET_RASTERIZER_VERSION 38
|
||||
|
||||
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* TTSUBPIX_H_ */
|
||||
|
||||
|
||||
/* END */
|
4
src/3rdparty/freetype/src/type1/t1load.c
vendored
4
src/3rdparty/freetype/src/type1/t1load.c
vendored
@ -1773,7 +1773,7 @@
|
||||
*/
|
||||
|
||||
FT_TRACE0(( "parse_subrs: adjusting number of subroutines"
|
||||
" (from %d to %ld)\n",
|
||||
" (from %d to %zu)\n",
|
||||
num_subrs,
|
||||
( parser->root.limit - parser->root.cursor ) >> 3 ));
|
||||
num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3;
|
||||
@ -1948,7 +1948,7 @@
|
||||
if ( num_glyphs > ( limit - cur ) >> 3 )
|
||||
{
|
||||
FT_TRACE0(( "parse_charstrings: adjusting number of glyphs"
|
||||
" (from %d to %ld)\n",
|
||||
" (from %d to %zu)\n",
|
||||
num_glyphs, ( limit - cur ) >> 3 ));
|
||||
num_glyphs = ( limit - cur ) >> 3;
|
||||
}
|
||||
|
2
src/3rdparty/freetype/src/type42/t42parse.c
vendored
2
src/3rdparty/freetype/src/type42/t42parse.c
vendored
@ -872,7 +872,7 @@
|
||||
if ( loader->num_glyphs > ( limit - parser->root.cursor ) >> 2 )
|
||||
{
|
||||
FT_TRACE0(( "t42_parse_charstrings: adjusting number of glyphs"
|
||||
" (from %d to %ld)\n",
|
||||
" (from %d to %zu)\n",
|
||||
loader->num_glyphs,
|
||||
( limit - parser->root.cursor ) >> 2 ));
|
||||
loader->num_glyphs = ( limit - parser->root.cursor ) >> 2;
|
||||
|
19
src/3rdparty/harfbuzz-ng/AUTHORS
vendored
19
src/3rdparty/harfbuzz-ng/AUTHORS
vendored
@ -1,9 +1,14 @@
|
||||
Behdad Esfahbod
|
||||
Simon Hausmann
|
||||
Martin Hosken
|
||||
Jonathan Kew
|
||||
Lars Knoll
|
||||
Werner Lemberg
|
||||
Roozbeh Pournader
|
||||
Owen Taylor
|
||||
David Corbett
|
||||
David Turner
|
||||
Ebrahim Byagowi
|
||||
Garret Rieger
|
||||
Jonathan Kew
|
||||
Khaled Hosny
|
||||
Lars Knoll
|
||||
Martin Hosken
|
||||
Owen Taylor
|
||||
Roderick Sheeter
|
||||
Roozbeh Pournader
|
||||
Simon Hausmann
|
||||
Werner Lemberg
|
||||
|
20
src/3rdparty/harfbuzz-ng/COPYING
vendored
20
src/3rdparty/harfbuzz-ng/COPYING
vendored
@ -2,17 +2,23 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
||||
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010,2011,2012 Google, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2010-2022 Google, Inc.
|
||||
Copyright © 2015-2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012,2015 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2009 Martin Hosken and SIL International
|
||||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2006 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
|
||||
For full copyright notices consult the individual files in the package.
|
||||
|
||||
|
1808
src/3rdparty/harfbuzz-ng/NEWS
vendored
1808
src/3rdparty/harfbuzz-ng/NEWS
vendored
File diff suppressed because it is too large
Load Diff
15
src/3rdparty/harfbuzz-ng/README
vendored
15
src/3rdparty/harfbuzz-ng/README
vendored
@ -1,15 +0,0 @@
|
||||
[](https://travis-ci.org/harfbuzz/harfbuzz)
|
||||
[](https://ci.appveyor.com/project/harfbuzz/harfbuzz)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz)
|
||||
[](https://coveralls.io/r/harfbuzz/harfbuzz)
|
||||
[ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
|
||||
|
||||
This is HarfBuzz, a text shaping library.
|
||||
|
||||
For bug reports, mailing list, and other information please visit:
|
||||
|
||||
http://harfbuzz.org/
|
||||
|
||||
For license information, see the file COPYING.
|
||||
|
||||
Documentation: https://harfbuzz.github.io
|
102
src/3rdparty/harfbuzz-ng/README.md
vendored
Normal file
102
src/3rdparty/harfbuzz-ng/README.md
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
[](https://github.com/harfbuzz/harfbuzz/workflows/linux-ci/badge.svg)
|
||||
[](https://circleci.com/gh/harfbuzz/harfbuzz/tree/main)
|
||||
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
|
||||
[](https://scan.coverity.com/projects/harfbuzz)
|
||||
[](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade)
|
||||
[](https://codecov.io/gh/harfbuzz/harfbuzz)
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
|
||||
|
||||
|
||||
# HarfBuzz
|
||||
|
||||
HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also
|
||||
[Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome,
|
||||
ChromeOS, Firefox, GNOME, GTK+, KDE, Qt, LibreOffice, OpenJDK, XeTeX,
|
||||
PlayStation, Microsoft Edge, Photoshop, Illustrator, InDesign,
|
||||
and other places.
|
||||
|
||||
For bug reports, mailing list, and other information please visit:
|
||||
|
||||
http://harfbuzz.org/
|
||||
|
||||
For license information, see [COPYING](COPYING).
|
||||
|
||||
## Documentation
|
||||
|
||||
For user manual as well as API documentation, check: https://harfbuzz.github.io
|
||||
|
||||
## Download
|
||||
|
||||
For tarball releases of HarfBuzz, look [here][3]. At the same place you
|
||||
will also find Win32/Win64 binary bundles that include `libharfbuzz` DLL,
|
||||
`hb-view.exe`, `hb-shape.exe`, and all dependencies.
|
||||
|
||||
The canonical source tree is available on [github][4].
|
||||
|
||||
The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
|
||||
headers are more likely to go through minor modifications, but again, we do our
|
||||
best to never change API in an incompatible way. We will never break the ABI.
|
||||
|
||||
If you are not sure whether Pango or HarfBuzz is right for you, read [Pango vs
|
||||
HarfBuzz][5].
|
||||
|
||||
## Development
|
||||
|
||||
For build information, see [BUILD.md](BUILD.md).
|
||||
|
||||
For custom configurations, see [CONFIG.md](CONFIG.md).
|
||||
|
||||
For testing and profiling, see [TESTING.md](TESTING.md).
|
||||
|
||||
To get a better idea of where HarfBuzz stands in the text rendering stack you
|
||||
may want to read [State of Text Rendering][6], though, that document is many
|
||||
years old. Here are a few presentation slides about HarfBuzz at the
|
||||
Internationalization and Unicode Conference over the years:
|
||||
|
||||
* November 2014, [Unicode, OpenType, and HarfBuzz: Closing the Circle][7],
|
||||
* October 2012, [HarfBuzz, The Free and Open Text Shaping Engine][8],
|
||||
* October 2009, [HarfBuzz: the Free and Open Shaping Engine][9].
|
||||
|
||||
Both development and user support discussion around HarfBuzz happens on the
|
||||
[github][4].
|
||||
|
||||
To report bugs or submit patches please use [github][4] issues and
|
||||
pull-requests.
|
||||
|
||||
For a comparison of old vs new HarfBuzz memory consumption see [this][10].
|
||||
|
||||
<!--See past and upcoming [HarfBuzz Hackfests](https://freedesktop.org/wiki/Software/HarfBuzz/Hackfests/)!-->
|
||||
|
||||
## Name
|
||||
|
||||
HarfBuzz (حرفباز) is my Persian translation of “[OpenType][1]”,
|
||||
transliterated using the Latin script. It sports a second meaning, but that
|
||||
ain’t translatable.
|
||||
|
||||
> Background: Originally there was this font format called TrueType. People and
|
||||
> companies started calling their type engines all things ending in Type:
|
||||
> FreeType, CoolType, ClearType, etc. And then came OpenType, which is the
|
||||
> successor of TrueType. So, for my OpenType implementation, I decided to stick
|
||||
> with the concept but use the Persian translation. Which is fitting given that
|
||||
> Persian is written in the Arabic script, and OpenType is an extension of
|
||||
> TrueType that adds support for complex script rendering, and HarfBuzz is an
|
||||
> implementation of OpenType complex text shaping.
|
||||
|
||||
<details>
|
||||
<summary>Packaging status of HarfBuzz</summary>
|
||||
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
|
||||
</details>
|
||||
|
||||
[1]: https://docs.microsoft.com/en-us/typography/opentype/spec/
|
||||
[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
|
||||
[3]: https://github.com/harfbuzz/harfbuzz/releases
|
||||
[4]: https://github.com/harfbuzz/harfbuzz
|
||||
[5]: http://mces.blogspot.com/2009/11/pango-vs-harfbuzz.html
|
||||
[6]: http://behdad.org/text/
|
||||
[7]: https://goo.gl/FSIQuC
|
||||
[8]: https://goo.gl/2wSRu
|
||||
[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf
|
||||
[10]: https://goo.gl/woyty
|
2
src/3rdparty/harfbuzz-ng/THANKS
vendored
2
src/3rdparty/harfbuzz-ng/THANKS
vendored
@ -1,6 +1,6 @@
|
||||
Bradley Grainger
|
||||
Khaled Hosny
|
||||
Kenichi Ishibashi
|
||||
Ivan Kuckir <https://photopea.com/>
|
||||
Ryan Lortie
|
||||
Jeff Muizelaar
|
||||
suzuki toshiya
|
||||
|
13
src/3rdparty/harfbuzz-ng/config.h
vendored
13
src/3rdparty/harfbuzz-ng/config.h
vendored
@ -22,6 +22,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QHARFBUZZ_CONFIG_H
|
||||
#define QHARFBUZZ_CONFIG_H
|
||||
|
||||
#include <QtCore/qatomic.h>
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
@ -37,11 +40,19 @@ inline QAtomicPointer<T> *makeAtomicPointer(T * const &ptr)
|
||||
return reinterpret_cast<QAtomicPointer<T> *>(const_cast<T **>(&ptr));
|
||||
}
|
||||
|
||||
static inline void _hb_memory_barrier ()
|
||||
{
|
||||
QAtomicInt a;
|
||||
a.ref(); // Ordered memory semantics, so imposes a memory barrier at this point
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
typedef int hb_atomic_int_impl_t;
|
||||
#define HB_ATOMIC_INT_IMPL_INIT(V) (V)
|
||||
#define hb_atomic_int_impl_add(AI, V) reinterpret_cast<QAtomicInt &>(AI).fetchAndAddOrdered(V)
|
||||
#define hb_atomic_int_impl_add(AI, V) reinterpret_cast<QAtomicInt *>(AI)->fetchAndAddOrdered(V)
|
||||
|
||||
#define hb_atomic_ptr_impl_get(P) makeAtomicPointer(*(P))->loadAcquire()
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) makeAtomicPointer(*(P))->testAndSetOrdered((O), (N))
|
||||
|
||||
#endif // QHARFBUZZ_CONFIG_H
|
||||
|
172
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
172
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
@ -14,11 +14,11 @@ SHAPERS += opentype # HB's main shaper; enabling it should be enough most
|
||||
# native shaper on Apple platforms; could be used alone to handle both OT and AAT fonts
|
||||
darwin: SHAPERS += coretext
|
||||
|
||||
# fallback shaper: not really useful with opentype or coretext shaper
|
||||
#SHAPERS += fallback
|
||||
# fallback shaper: not really useful with opentype or coretext shaper but needed for linking
|
||||
SHAPERS += fallback
|
||||
|
||||
DEFINES += HAVE_CONFIG_H
|
||||
DEFINES += HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
|
||||
DEFINES += HB_NO_UNICODE_FUNCS
|
||||
DEFINES += HB_NDEBUG
|
||||
DEFINES += HB_EXTERN=
|
||||
|
||||
@ -26,6 +26,7 @@ DEFINES += HB_EXTERN=
|
||||
DEFINES += HAVE_ATEXIT
|
||||
unix: DEFINES += HAVE_PTHREAD HAVE_SCHED_H HAVE_SCHED_YIELD
|
||||
win32: DEFINES += HB_NO_WIN1256
|
||||
msvc:winrt: QMAKE_CXXFLAGS += /bigobj # prevent error C1128
|
||||
|
||||
#Workaround https://code.google.com/p/android/issues/detail?id=194631
|
||||
android: DEFINES += _POSIX_C_SOURCE=200112L
|
||||
@ -35,35 +36,46 @@ INCLUDEPATH += $$QT.core.includes
|
||||
DEFINES += QT_NO_VERSION_TAGGING
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/hb-dummy.cc \
|
||||
$$PWD/src/hb-aat-layout.cc \
|
||||
$$PWD/src/hb-aat-map.cc \
|
||||
$$PWD/src/hb-blob.cc \
|
||||
$$PWD/src/hb-buffer.cc \
|
||||
$$PWD/src/hb-buffer-serialize.cc \
|
||||
$$PWD/src/hb-common.cc \
|
||||
$$PWD/src/hb-draw.cc \
|
||||
$$PWD/src/hb-face.cc \
|
||||
$$PWD/src/hb-face-builder.cc \
|
||||
$$PWD/src/hb-font.cc \
|
||||
$$PWD/src/hb-map.cc \
|
||||
$$PWD/src/hb-number.cc \
|
||||
$$PWD/src/hb-ot-tag.cc \
|
||||
$$PWD/src/hb-outline.cc \
|
||||
$$PWD/src/hb-paint.cc \
|
||||
$$PWD/src/hb-paint-extents.cc \
|
||||
$$PWD/src/hb-set.cc \
|
||||
$$PWD/src/hb-shape.cc \
|
||||
$$PWD/src/hb-shape-plan.cc \
|
||||
$$PWD/src/hb-shaper.cc \
|
||||
$$PWD/src/hb-style.cc \
|
||||
$$PWD/src/hb-subset.cc \
|
||||
$$PWD/src/hb-subset-cff-common.cc \
|
||||
$$PWD/src/hb-subset-cff1.cc \
|
||||
$$PWD/src/hb-subset-cff2.cc \
|
||||
$$PWD/src/hb-subset-input.cc \
|
||||
$$PWD/src/hb-subset-instancer-solver.cc \
|
||||
$$PWD/src/hb-subset-plan.cc \
|
||||
$$PWD/src/hb-subset-repacker.cc \
|
||||
$$PWD/src/hb-unicode.cc \
|
||||
$$PWD/src/hb-warning.cc
|
||||
$$PWD/src/hb-buffer-verify.cc
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/hb-atomic-private.hh \
|
||||
$$PWD/src/hb-buffer-private.hh \
|
||||
$$PWD/src/hb-buffer-deserialize-json.hh \
|
||||
$$PWD/src/hb-buffer-deserialize-text.hh \
|
||||
$$PWD/src/hb-cache-private.hh \
|
||||
$$PWD/src/hb-buffer-deserialize-text-glyphs.hh \
|
||||
$$PWD/src/hb-buffer-deserialize-text-unicode.hh \
|
||||
$$PWD/src/hb-debug.hh \
|
||||
$$PWD/src/hb-dsalgs.hh \
|
||||
$$PWD/src/hb-face-private.hh \
|
||||
$$PWD/src/hb-font-private.hh \
|
||||
$$PWD/src/hb-mutex-private.hh \
|
||||
$$PWD/src/hb-object-private.hh \
|
||||
$$PWD/src/hb-open-file-private.hh \
|
||||
$$PWD/src/hb-open-type-private.hh \
|
||||
$$PWD/src/hb-ot-cbdt-table.hh \
|
||||
$$PWD/src/hb-face.hh \
|
||||
$$PWD/src/hb-mutex.hh \
|
||||
$$PWD/src/hb-ot-cmap-table.hh \
|
||||
$$PWD/src/hb-ot-glyf-table.hh \
|
||||
$$PWD/src/hb-ot-head-table.hh \
|
||||
@ -73,83 +85,120 @@ HEADERS += \
|
||||
$$PWD/src/hb-ot-name-table.hh \
|
||||
$$PWD/src/hb-ot-os2-table.hh \
|
||||
$$PWD/src/hb-ot-post-table.hh \
|
||||
$$PWD/src/hb-private.hh \
|
||||
$$PWD/src/hb-set-digest-private.hh \
|
||||
$$PWD/src/hb-set-private.hh \
|
||||
$$PWD/src/hb-shape-plan-private.hh \
|
||||
$$PWD/src/hb-shaper-impl-private.hh \
|
||||
$$PWD/src/hb-set.hh \
|
||||
$$PWD/src/hb-set-digest.hh \
|
||||
$$PWD/src/hb-shape-plan.hh \
|
||||
$$PWD/src/hb-shaper.hh \
|
||||
$$PWD/src/hb-shaper-impl.hh \
|
||||
$$PWD/src/hb-shaper-list.hh \
|
||||
$$PWD/src/hb-shaper-private.hh \
|
||||
$$PWD/src/hb-string-array.hh \
|
||||
$$PWD/src/hb-unicode-private.hh \
|
||||
$$PWD/src/hb-utf-private.hh
|
||||
$$PWD/src/hb-subset-plan-member-list.hh \
|
||||
$$PWD/src/hb-subset-repacker.h \
|
||||
$$PWD/src/hb-unicode.hh
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/hb.h \
|
||||
$$PWD/src/hb-algs.hh \
|
||||
$$PWD/src/hb-atomic.hh \
|
||||
$$PWD/src/hb-blob.h \
|
||||
$$PWD/src/hb-buffer.h \
|
||||
$$PWD/src/hb-buffer.hh \
|
||||
$$PWD/src/hb-cache.hh \
|
||||
$$PWD/src/hb-common.h \
|
||||
$$PWD/src/hb-deprecated.h \
|
||||
$$PWD/src/hb-draw.h \
|
||||
$$PWD/src/hb-draw.hh \
|
||||
$$PWD/src/hb-face.h \
|
||||
$$PWD/src/hb-font.h \
|
||||
$$PWD/src/hb-font.hh \
|
||||
$$PWD/src/hb-ft-colr.hh \
|
||||
$$PWD/src/hb-limits.hh \
|
||||
$$PWD/src/hb-map.h \
|
||||
$$PWD/src/hb-map.hh \
|
||||
$$PWD/src/hb-object.hh \
|
||||
$$PWD/src/hb-open-file.hh \
|
||||
$$PWD/src/hb-open-type.hh \
|
||||
$$PWD/src/hb-ot-cff1-std-str.hh \
|
||||
$$PWD/src/hb-outline.hh \
|
||||
$$PWD/src/hb-paint.h \
|
||||
$$PWD/src/hb-paint.hh \
|
||||
$$PWD/src/hb-paint-extents.hh \
|
||||
$$PWD/src/hb-priority-queue.hh \
|
||||
$$PWD/src/hb-repacker.hh \
|
||||
$$PWD/src/hb-set.h \
|
||||
$$PWD/src/hb-shape.h \
|
||||
$$PWD/src/hb-shape-plan.h \
|
||||
$$PWD/src/hb-style.h \
|
||||
$$PWD/src/hb-unicode.h \
|
||||
$$PWD/src/hb-utf.hh \
|
||||
$$PWD/src/hb-version.h
|
||||
|
||||
contains(SHAPERS, opentype) {
|
||||
DEFINES += HAVE_OT
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/hb-ot-cff1-table.cc \
|
||||
$$PWD/src/hb-ot-cff2-table.cc \
|
||||
$$PWD/src/hb-ot-color.cc \
|
||||
$$PWD/src/hb-ot-face.cc \
|
||||
$$PWD/src/hb-ot-font.cc \
|
||||
$$PWD/src/hb-ot-layout.cc \
|
||||
$$PWD/src/hb-ot-map.cc \
|
||||
$$PWD/src/hb-ot-math.cc \
|
||||
$$PWD/src/hb-ot-meta.cc \
|
||||
$$PWD/src/hb-ot-metrics.cc \
|
||||
$$PWD/src/hb-ot-name.cc \
|
||||
$$PWD/src/hb-ot-shape.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-arabic.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-default.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-hangul.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-hebrew.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-indic.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-indic-table.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-myanmar.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-thai.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-tibetan.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-use.cc \
|
||||
$$PWD/src/hb-ot-shape-complex-use-table.cc \
|
||||
$$PWD/src/hb-ot-shaper-arabic.cc \
|
||||
$$PWD/src/hb-ot-shaper-default.cc \
|
||||
$$PWD/src/hb-ot-shaper-hangul.cc \
|
||||
$$PWD/src/hb-ot-shaper-hebrew.cc \
|
||||
$$PWD/src/hb-ot-shaper-indic.cc \
|
||||
$$PWD/src/hb-ot-shaper-thai.cc \
|
||||
$$PWD/src/hb-ot-shape-fallback.cc \
|
||||
$$PWD/src/hb-ot-shape-normalize.cc \
|
||||
$$PWD/src/hb-ot-var.cc
|
||||
$$PWD/src/hb-ot-shaper-indic-table.cc \
|
||||
$$PWD/src/hb-ot-shaper-khmer.cc \
|
||||
$$PWD/src/hb-ot-shaper-myanmar.cc \
|
||||
$$PWD/src/hb-ot-shaper-syllabic.cc \
|
||||
$$PWD/src/hb-ot-shaper-use.cc \
|
||||
$$PWD/src/hb-ot-shaper-vowel-constraints.cc \
|
||||
$$PWD/src/hb-ot-var.cc
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/hb-ot-kern-table.hh \
|
||||
$$PWD/src/hb-ot-layout-common-private.hh \
|
||||
$$PWD/src/hb-ot-layout-gdef-table.hh \
|
||||
$$PWD/src/hb-ot-layout-gpos-table.hh \
|
||||
$$PWD/src/hb-ot-layout-gsubgpos-private.hh \
|
||||
$$PWD/src/hb-ot-layout-gsub-table.hh \
|
||||
$$PWD/src/hb-ot-layout-jstf-table.hh \
|
||||
$$PWD/src/hb-ot-layout-math-table.hh \
|
||||
$$PWD/src/hb-ot-layout-private.hh \
|
||||
$$PWD/src/hb-ot-map-private.hh \
|
||||
$$PWD/src/hb-ot-layout.hh \
|
||||
$$PWD/src/hb-ot-map.hh \
|
||||
$$PWD/src/hb-ot-math-table.hh \
|
||||
$$PWD/src/hb-ot-post-macroman.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-arabic-fallback.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-arabic-private.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-arabic-table.hh \
|
||||
# $$PWD/src/hb-ot-shape-complex-arabic-win1256.hh \ # disabled with HB_NO_WIN1256
|
||||
$$PWD/src/hb-ot-shape-complex-indic-machine.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-indic-private.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-myanmar-machine.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-private.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-use-machine.hh \
|
||||
$$PWD/src/hb-ot-shape-complex-use-private.hh \
|
||||
$$PWD/src/hb-ot-shape-fallback-private.hh \
|
||||
$$PWD/src/hb-ot-shape-normalize-private.hh \
|
||||
$$PWD/src/hb-ot-shape-private.hh \
|
||||
$$PWD/src/hb-ot-post-table-v2subset.hh \
|
||||
$$PWD/src/hb-ot-shaper-arabic-joining-list.hh \
|
||||
$$PWD/src/hb-ot-shaper-arabic-pua.hh \
|
||||
$$PWD/src/hb-ot-shaper-indic-machine.hh \
|
||||
$$PWD/src/hb-ot-shaper-arabic-fallback.hh \
|
||||
$$PWD/src/hb-ot-shaper-arabic.hh \
|
||||
$$PWD/src/hb-ot-shaper-arabic-table.hh \
|
||||
# $$PWD/src/hb-ot-shaper-arabic-win1256.hh \ # disabled with HB_NO_WIN1256
|
||||
$$PWD/src/hb-ot-shaper.hh \
|
||||
$$PWD/src/hb-ot-shape-fallback.hh \
|
||||
$$PWD/src/hb-ot-shape-normalize.hh \
|
||||
$$PWD/src/hb-ot-shaper-indic.hh \
|
||||
$$PWD/src/hb-ot-shaper-khmer-machine.hh \
|
||||
$$PWD/src/hb-ot-shaper-myanmar-machine.hh \
|
||||
$$PWD/src/hb-ot-shaper-syllabic.hh \
|
||||
$$PWD/src/hb-ot-shaper-use-machine.hh \
|
||||
$$PWD/src/hb-ot-shaper-use-table.hh \
|
||||
$$PWD/src/hb-ot-shaper-vowel-constraints.hh \
|
||||
$$PWD/src/hb-subset-accelerator.hh \
|
||||
$$PWD/src/hb-ot-var-common.hh \
|
||||
$$PWD/src/hb-ot-var-avar-table.hh \
|
||||
$$PWD/src/hb-ot-var-cvar-table.hh \
|
||||
$$PWD/src/hb-ot-var-fvar-table.hh \
|
||||
$$PWD/src/hb-ot-var-gvar-table.hh \
|
||||
$$PWD/src/hb-ot-var-hvar-table.hh \
|
||||
$$PWD/src/hb-ot-var-mvar-table.hh
|
||||
|
||||
@ -159,8 +208,17 @@ contains(SHAPERS, opentype) {
|
||||
$$PWD/src/hb-ot-layout.h \
|
||||
$$PWD/src/hb-ot-math.h \
|
||||
$$PWD/src/hb-ot-shape.h \
|
||||
$$PWD/src/hb-ot-tag.h \
|
||||
$$PWD/src/hb-ot-var.h
|
||||
$$PWD/src/hb-ot-shape.hh \
|
||||
$$PWD/src/hb-ot-var.h \
|
||||
$$PWD/src/OT/Color/CBDT/CBDT.hh \
|
||||
$$PWD/src/OT/Color/COLR/COLR.hh \
|
||||
$$PWD/src/OT/Color/COLR/colrv1-closure.hh \
|
||||
$$PWD/src/OT/Color/CPAL/CPAL.hh \
|
||||
$$PWD/src/OT/Color/sbix/sbix.hh \
|
||||
$$PWD/src/OT/Color/svg/svg.hh \
|
||||
$$PWD/src/OT/Layout/GDEF/GDEF.hh \
|
||||
$$PWD/src/OT/name/name.hh
|
||||
|
||||
}
|
||||
|
||||
MODULE_EXT_HEADERS = $$HEADERS
|
||||
@ -169,7 +227,7 @@ contains(SHAPERS, coretext) {
|
||||
DEFINES += HAVE_CORETEXT
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/hb-coretext.mm
|
||||
$$PWD/src/hb-coretext.cc
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/hb-coretext.h
|
||||
|
8
src/3rdparty/harfbuzz-ng/hb-dummy.cc
vendored
Normal file
8
src/3rdparty/harfbuzz-ng/hb-dummy.cc
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// Work-around for issue with qmake: Since hb-common.cc has #include "hb-static.cc" in it,
|
||||
// qmake will assume it is included and ignore it in the SOURCES list. But the #include
|
||||
// is protected inside an #ifdef and will not be used, so hb-static.cc ends up not being
|
||||
// linked at all and we get missing symbols. We work around this by including both in
|
||||
// the same compilation unit.
|
||||
|
||||
#include "src/hb-common.cc"
|
||||
#include "src/hb-static.cc"
|
92
src/3rdparty/harfbuzz-ng/import_from_tarball.sh
vendored
Normal file
92
src/3rdparty/harfbuzz-ng/import_from_tarball.sh
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
#! /bin/sh
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
## Copyright (C) 2021 The Qt Company Ltd.
|
||||
## Contact: https://www.qt.io/licensing/
|
||||
##
|
||||
## This file is the build configuration utility of the Qt Toolkit.
|
||||
##
|
||||
## $QT_BEGIN_LICENSE:LGPL$
|
||||
## Commercial License Usage
|
||||
## Licensees holding valid commercial Qt licenses may use this file in
|
||||
## accordance with the commercial license agreement provided with the
|
||||
## Software or, alternatively, in accordance with the terms contained in
|
||||
## a written agreement between you and The Qt Company. For licensing terms
|
||||
## and conditions see https://www.qt.io/terms-conditions. For further
|
||||
## information use the contact form at https://www.qt.io/contact-us.
|
||||
##
|
||||
## GNU Lesser General Public License Usage
|
||||
## Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
## General Public License version 3 as published by the Free Software
|
||||
## Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
## packaging of this file. Please review the following information to
|
||||
## ensure the GNU Lesser General Public License version 3 requirements
|
||||
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
##
|
||||
## GNU General Public License Usage
|
||||
## Alternatively, this file may be used under the terms of the GNU
|
||||
## General Public License version 2.0 or (at your option) the GNU General
|
||||
## Public license version 3 or any later version approved by the KDE Free
|
||||
## Qt Foundation. The licenses are as published by the Free Software
|
||||
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
## included in the packaging of this file. Please review the following
|
||||
## information to ensure the GNU General Public License requirements will
|
||||
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
## https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
##
|
||||
## $QT_END_LICENSE$
|
||||
##
|
||||
#############################################################################
|
||||
|
||||
# This is a small script to copy the required files from a harfbuzz tarball
|
||||
# into 3rdparty/harfbuzz-ng/ . Documentation, tests, demos etc. are not imported.
|
||||
# Steps:
|
||||
# 1. rm $QTDIR/src/3rdparty/harfbuzz-ng/src/*
|
||||
# 2. source import_from_tarball.sh harfbuzz_tarball_dir/ $QTDIR/src/3rdparty/harfbuzz-ng/
|
||||
# 3. Check that CMakeLists contains everything
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Usage: $0 harfbuzz_tarball_dir/ \$QTDIR/src/3rdparty/harfbuzz-ng/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HB_DIR=$1
|
||||
TARGET_DIR=$2
|
||||
|
||||
if [ ! -d "$HB_DIR" -o ! -r "$HB_DIR" -o ! -d "$TARGET_DIR" -o ! -w "$TARGET_DIR" ]; then
|
||||
echo "Either the harfbuzz source dir or the target dir do not exist,"
|
||||
echo "are not directories or have the wrong permissions."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# with 1 argument, copies HB_DIR/$1 to TARGET_DIR/$1
|
||||
# with 2 arguments, copies HB_DIR/$1 to TARGET_DIR/$2
|
||||
copy_file_or_dir() {
|
||||
if [ $# -lt 1 -o $# -gt 2 ]; then
|
||||
echo "Wrong number of arguments to copy_file_or_dir"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
SOURCE_FILE=$1
|
||||
if [ -n "$2" ]; then
|
||||
DEST_FILE=$2
|
||||
else
|
||||
DEST_FILE=$1
|
||||
fi
|
||||
|
||||
mkdir -p "$TARGET_DIR/$(dirname "$SOURCE_FILE")"
|
||||
cp -R "$HB_DIR/$SOURCE_FILE" "$TARGET_DIR/$DEST_FILE"
|
||||
}
|
||||
|
||||
FILES=(AUTHORS
|
||||
COPYING
|
||||
README.md
|
||||
THANKS
|
||||
)
|
||||
|
||||
for i in ${FILES[*]}; do
|
||||
copy_file_or_dir "$i"
|
||||
done
|
||||
|
||||
cp -R $HB_DIR/src $TARGET_DIR
|
33
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
33
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
@ -3,24 +3,29 @@
|
||||
"Name": "HarfBuzz-NG",
|
||||
"QDocModule": "qtgui",
|
||||
"QtUsage": "Optionally used in Qt GUI. Configure with -system-harfbuzz to force the use of the system library, or -qt-harfbuzz to link statically to the library that is bundled with your Qt version.",
|
||||
"SecurityCritical": true,
|
||||
|
||||
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
||||
"Homepage": "http://harfbuzz.org",
|
||||
"Version": "1.7.4",
|
||||
|
||||
"Version": "8.2.2",
|
||||
"License": "MIT License",
|
||||
"LicenseId": "MIT",
|
||||
"LicenseFile": "COPYING",
|
||||
"Copyright": "Copyright © 2010,2011,2012 Google, Inc.
|
||||
Copyright © 2012 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2009 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2006 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc.
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
"
|
||||
"Copyright": "Copyright © 2010-2022 Google, Inc.
|
||||
Copyright © 2015-2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012,2015 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov"
|
||||
}
|
||||
|
1025
src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
vendored
Normal file
1025
src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2488
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
vendored
Normal file
2488
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
107
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/colrv1-closure.hh
vendored
Normal file
107
src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/colrv1-closure.hh
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_COLR_COLRV1_CLOSURE_HH
|
||||
#define OT_COLOR_COLR_COLRV1_CLOSURE_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "COLR.hh"
|
||||
|
||||
/*
|
||||
* COLR -- Color
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/colr
|
||||
*/
|
||||
namespace OT {
|
||||
|
||||
HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
c->add_layer_indices (firstLayerIndex, numLayers);
|
||||
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
|
||||
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
|
||||
{
|
||||
const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i];
|
||||
paint.dispatch (c);
|
||||
}
|
||||
}
|
||||
|
||||
HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
c->add_glyph (gid);
|
||||
(this+paint).dispatch (c);
|
||||
}
|
||||
|
||||
HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
const COLR *colr_table = c->get_colr_table ();
|
||||
const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid);
|
||||
if (!baseglyph_paintrecord) return;
|
||||
c->add_glyph (gid);
|
||||
|
||||
const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList ();
|
||||
(&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c);
|
||||
}
|
||||
|
||||
template <template<typename> class Var>
|
||||
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+src).dispatch (c); }
|
||||
|
||||
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
(this+src).dispatch (c);
|
||||
(this+backdrop).dispatch (c);
|
||||
}
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* OT_COLOR_COLR_COLRV1_CLOSURE_HH */
|
350
src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh
vendored
Normal file
350
src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh
vendored
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright © 2016 Google, Inc.
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Sascha Brawer
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_CPAL_CPAL_HH
|
||||
#define OT_COLOR_CPAL_CPAL_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-ot-color.h"
|
||||
#include "../../../hb-ot-name.h"
|
||||
|
||||
|
||||
/*
|
||||
* CPAL -- Color Palette
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
|
||||
*/
|
||||
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct CPALV1Tail
|
||||
{
|
||||
friend struct CPAL;
|
||||
|
||||
private:
|
||||
hb_ot_color_palette_flags_t get_palette_flags (const void *base,
|
||||
unsigned int palette_index,
|
||||
unsigned int palette_count) const
|
||||
{
|
||||
if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
|
||||
return (hb_ot_color_palette_flags_t) (uint32_t)
|
||||
(base+paletteFlagsZ).as_array (palette_count)[palette_index];
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_palette_name_id (const void *base,
|
||||
unsigned int palette_index,
|
||||
unsigned int palette_count) const
|
||||
{
|
||||
if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
|
||||
return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_color_name_id (const void *base,
|
||||
unsigned int color_index,
|
||||
unsigned int color_count) const
|
||||
{
|
||||
if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
|
||||
return (base+colorLabelsZ).as_array (color_count)[color_index];
|
||||
}
|
||||
|
||||
public:
|
||||
void collect_name_ids (const void *base,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (paletteLabelsZ)
|
||||
{
|
||||
+ (base+paletteLabelsZ).as_array (palette_count)
|
||||
| hb_sink (nameids_to_retain)
|
||||
;
|
||||
}
|
||||
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
nameids_to_retain->add (colorLabels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const void *base,
|
||||
const hb_map_t *color_index_map) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->allocate_size<CPALV1Tail> (static_size);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->paletteFlagsZ = 0;
|
||||
if (paletteFlagsZ)
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
out->paletteLabelsZ = 0;
|
||||
if (paletteLabelsZ)
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
c->push ();
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
if (!c->copy<NameID> (colorLabels[i]))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
c->add_link (out->colorLabelsZ, c->pop_pack ());
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const void *base,
|
||||
unsigned int palette_count,
|
||||
unsigned int color_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
(!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
|
||||
(!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
|
||||
(!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count)));
|
||||
}
|
||||
|
||||
protected:
|
||||
// TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
|
||||
// here. Currently they are needed since UnsizedArrayOf doesn't define null_size
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT32>>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
* is provided. */
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
paletteLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the palette labels array. Set to 0 if no
|
||||
* array is provided. */
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
colorLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the color labels array. Set to 0
|
||||
* if no array is provided. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
typedef HBUINT32 BGRAColor;
|
||||
|
||||
struct CPAL
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
|
||||
|
||||
bool has_data () const { return numPalettes; }
|
||||
|
||||
unsigned int get_size () const
|
||||
{ return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
|
||||
|
||||
unsigned int get_palette_count () const { return numPalettes; }
|
||||
unsigned int get_color_count () const { return numColors; }
|
||||
|
||||
hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
|
||||
{ return v1 ().get_palette_flags (this, palette_index, numPalettes); }
|
||||
|
||||
hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
|
||||
{ return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
|
||||
|
||||
hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
|
||||
{ return v1 ().get_color_name_id (this, color_index, numColors); }
|
||||
|
||||
unsigned int get_palette_colors (unsigned int palette_index,
|
||||
unsigned int start_offset,
|
||||
unsigned int *color_count, /* IN/OUT. May be NULL. */
|
||||
hb_color_t *colors /* OUT. May be NULL. */) const
|
||||
{
|
||||
if (unlikely (palette_index >= numPalettes))
|
||||
{
|
||||
if (color_count) *color_count = 0;
|
||||
return 0;
|
||||
}
|
||||
unsigned int start_index = colorRecordIndicesZ[palette_index];
|
||||
hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
|
||||
hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
|
||||
numColors);
|
||||
if (color_count)
|
||||
{
|
||||
+ palette_colors.sub_array (start_offset, color_count)
|
||||
| hb_sink (hb_array (colors, *color_count))
|
||||
;
|
||||
}
|
||||
return numColors;
|
||||
}
|
||||
|
||||
void collect_name_ids (const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (version == 1)
|
||||
v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
|
||||
}
|
||||
|
||||
private:
|
||||
const CPALV1Tail& v1 () const
|
||||
{
|
||||
if (version == 0) return Null (CPALV1Tail);
|
||||
return StructAfter<CPALV1Tail> (*this);
|
||||
}
|
||||
|
||||
public:
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_array_t<const HBUINT16> &color_record_indices,
|
||||
const hb_array_t<const BGRAColor> &color_records,
|
||||
const hb_vector_t<unsigned>& first_color_index_for_layer,
|
||||
const hb_map_t& first_color_to_layer_index,
|
||||
const hb_set_t &retained_color_indices) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
// TODO(grieger): limit total final size.
|
||||
|
||||
for (const auto idx : color_record_indices)
|
||||
{
|
||||
hb_codepoint_t layer_index = first_color_to_layer_index[idx];
|
||||
|
||||
HBUINT16 new_idx;
|
||||
new_idx = layer_index * retained_color_indices.get_population ();
|
||||
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
|
||||
}
|
||||
|
||||
c->push ();
|
||||
for (unsigned first_color_index : first_color_index_for_layer)
|
||||
{
|
||||
for (hb_codepoint_t color_index : retained_color_indices)
|
||||
{
|
||||
if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c->add_link (colorRecordsZ, c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (!numPalettes) return_trace (false);
|
||||
|
||||
const hb_map_t *color_index_map = &c->plan->colr_palettes;
|
||||
if (color_index_map->is_empty ()) return_trace (false);
|
||||
|
||||
hb_set_t retained_color_indices;
|
||||
for (const auto _ : color_index_map->keys ())
|
||||
{
|
||||
if (_ == 0xFFFF) continue;
|
||||
retained_color_indices.add (_);
|
||||
}
|
||||
if (retained_color_indices.is_empty ()) return_trace (false);
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
|
||||
out->version = version;
|
||||
out->numColors = retained_color_indices.get_population ();
|
||||
out->numPalettes = numPalettes;
|
||||
|
||||
hb_vector_t<unsigned> first_color_index_for_layer;
|
||||
hb_map_t first_color_to_layer_index;
|
||||
|
||||
const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
|
||||
for (const auto first_color_record_idx : colorRecordIndices)
|
||||
{
|
||||
if (first_color_to_layer_index.has (first_color_record_idx)) continue;
|
||||
|
||||
first_color_index_for_layer.push (first_color_record_idx);
|
||||
first_color_to_layer_index.set (first_color_record_idx,
|
||||
first_color_index_for_layer.length - 1);
|
||||
}
|
||||
|
||||
out->numColorRecords = first_color_index_for_layer.length
|
||||
* retained_color_indices.get_population ();
|
||||
|
||||
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
|
||||
if (!out->serialize (c->serializer,
|
||||
colorRecordIndices,
|
||||
color_records,
|
||||
first_color_index_for_layer,
|
||||
first_color_to_layer_index,
|
||||
retained_color_indices))
|
||||
return_trace (false);
|
||||
|
||||
if (version == 1)
|
||||
return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
(this+colorRecordsZ).sanitize (c, numColorRecords) &&
|
||||
colorRecordIndicesZ.sanitize (c, numPalettes) &&
|
||||
(version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number */
|
||||
/* Version 0 */
|
||||
HBUINT16 numColors; /* Number of colors in each palette. */
|
||||
HBUINT16 numPalettes; /* Number of palettes in the table. */
|
||||
HBUINT16 numColorRecords; /* Total number of color records, combined for
|
||||
* all palettes. */
|
||||
NNOffset32To<UnsizedArrayOf<BGRAColor>>
|
||||
colorRecordsZ; /* Offset from the beginning of CPAL table to
|
||||
* the first ColorRecord. */
|
||||
UnsizedArrayOf<HBUINT16>
|
||||
colorRecordIndicesZ; /* Index of each palette’s first color record in
|
||||
* the combined color record array. */
|
||||
/*CPALV1Tail v1;*/
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* OT_COLOR_CPAL_CPAL_HH */
|
447
src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
vendored
Normal file
447
src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh
vendored
Normal file
@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Calder Kitagawa
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_SBIX_SBIX_HH
|
||||
#define OT_COLOR_SBIX_SBIX_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
|
||||
/*
|
||||
* sbix -- Standard Bitmap Graphics
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
|
||||
*/
|
||||
#define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct SBIXGlyph
|
||||
{
|
||||
SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
|
||||
if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
|
||||
|
||||
new_glyph->xOffset = xOffset;
|
||||
new_glyph->yOffset = yOffset;
|
||||
new_glyph->graphicType = graphicType;
|
||||
data.copy (c, data_length);
|
||||
return_trace (new_glyph);
|
||||
}
|
||||
|
||||
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
|
||||
* edge of the graphic to the glyph’s origin.
|
||||
* That is, the x-coordinate of the point on the
|
||||
* baseline at the left edge of the glyph. */
|
||||
HBINT16 yOffset; /* The vertical (y-axis) offset from the bottom
|
||||
* edge of the graphic to the glyph’s origin.
|
||||
* That is, the y-coordinate of the point on the
|
||||
* baseline at the left edge of the glyph. */
|
||||
Tag graphicType; /* Indicates the format of the embedded graphic
|
||||
* data: one of 'jpg ', 'png ' or 'tiff', or the
|
||||
* special format 'dupe'. */
|
||||
UnsizedArrayOf<HBUINT8>
|
||||
data; /* The actual embedded graphic data. The total
|
||||
* length is inferred from sequential entries in
|
||||
* the glyphDataOffsets array and the fixed size
|
||||
* (8 bytes) of the preceding fields. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, data);
|
||||
};
|
||||
|
||||
struct SBIXStrike
|
||||
{
|
||||
static unsigned int get_size (unsigned num_glyphs)
|
||||
{ return min_size + num_glyphs * HBUINT32::static_size; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
|
||||
}
|
||||
|
||||
hb_blob_t *get_glyph_blob (unsigned int glyph_id,
|
||||
hb_blob_t *sbix_blob,
|
||||
hb_tag_t file_type,
|
||||
int *x_offset,
|
||||
int *y_offset,
|
||||
unsigned int num_glyphs,
|
||||
unsigned int *strike_ppem) const
|
||||
{
|
||||
if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
|
||||
|
||||
unsigned int retry_count = 8;
|
||||
unsigned int sbix_len = sbix_blob->length;
|
||||
unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
|
||||
assert (strike_offset < sbix_len);
|
||||
|
||||
retry:
|
||||
if (unlikely (glyph_id >= num_glyphs ||
|
||||
imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
|
||||
imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
|
||||
(unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
|
||||
unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
|
||||
|
||||
const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
|
||||
|
||||
if (glyph->graphicType == HB_TAG ('d','u','p','e'))
|
||||
{
|
||||
if (glyph_length >= 2)
|
||||
{
|
||||
glyph_id = *((HBUINT16 *) &glyph->data);
|
||||
if (retry_count--)
|
||||
goto retry;
|
||||
}
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
if (unlikely (file_type != glyph->graphicType))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
if (strike_ppem) *strike_ppem = ppem;
|
||||
if (x_offset) *x_offset = glyph->xOffset;
|
||||
if (y_offset) *y_offset = glyph->yOffset;
|
||||
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c, unsigned int available_len) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
|
||||
|
||||
auto* out = c->serializer->start_embed<SBIXStrike> ();
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
|
||||
out->ppem = ppem;
|
||||
out->resolution = resolution;
|
||||
HBUINT32 head;
|
||||
head = get_size (num_output_glyphs + 1);
|
||||
|
||||
bool has_glyphs = false;
|
||||
for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
|
||||
unlikely (imageOffsetsZ[old_gid].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
|
||||
imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
|
||||
(unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
|
||||
{
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
continue;
|
||||
}
|
||||
has_glyphs = true;
|
||||
unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
|
||||
unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
|
||||
if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
|
||||
return_trace (false);
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
head += delta;
|
||||
}
|
||||
if (has_glyphs)
|
||||
out->imageOffsetsZ[num_output_glyphs] = head;
|
||||
else
|
||||
c->serializer->revert (snap);
|
||||
return_trace (has_glyphs);
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
|
||||
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
|
||||
* strike was designed. (E.g., 96 PPI, 192 PPI.) */
|
||||
protected:
|
||||
UnsizedArrayOf<Offset32To<SBIXGlyph>>
|
||||
imageOffsetsZ; /* Offset from the beginning of the strike data header
|
||||
* to bitmap data for an individual glyph ID. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, imageOffsetsZ);
|
||||
};
|
||||
|
||||
struct sbix
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
|
||||
|
||||
bool has_data () const { return version; }
|
||||
|
||||
const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<sbix> (face);
|
||||
num_glyphs = face->get_num_glyphs ();
|
||||
}
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
||||
bool has_data () const { return table->has_data (); }
|
||||
|
||||
bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
bool scale = true) const
|
||||
{
|
||||
/* We only support PNG right now, and following function checks type. */
|
||||
return get_png_extents (font, glyph, extents, scale);
|
||||
}
|
||||
|
||||
hb_blob_t *reference_png (hb_font_t *font,
|
||||
hb_codepoint_t glyph_id,
|
||||
int *x_offset,
|
||||
int *y_offset,
|
||||
unsigned int *available_ppem) const
|
||||
{
|
||||
return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
|
||||
HB_TAG ('p','n','g',' '),
|
||||
x_offset, y_offset,
|
||||
num_glyphs, available_ppem);
|
||||
}
|
||||
|
||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
unsigned int strike_ppem = 0;
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyph_extents_t pixel_extents;
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return false;
|
||||
|
||||
if (!hb_font_get_glyph_extents (font, glyph, &extents))
|
||||
return false;
|
||||
|
||||
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
|
||||
return false;
|
||||
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
pixel_extents.width, -pixel_extents.height,
|
||||
HB_PAINT_IMAGE_FORMAT_PNG,
|
||||
font->slant_xy,
|
||||
&extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const SBIXStrike &choose_strike (hb_font_t *font) const
|
||||
{
|
||||
unsigned count = table->strikes.len;
|
||||
if (unlikely (!count))
|
||||
return Null (SBIXStrike);
|
||||
|
||||
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
|
||||
if (!requested_ppem)
|
||||
requested_ppem = 1<<30; /* Choose largest strike. */
|
||||
/* TODO Add DPI sensitivity as well? */
|
||||
unsigned int best_i = 0;
|
||||
unsigned int best_ppem = table->get_strike (0).ppem;
|
||||
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
{
|
||||
unsigned int ppem = (table->get_strike (i)).ppem;
|
||||
if ((requested_ppem <= ppem && ppem < best_ppem) ||
|
||||
(requested_ppem > best_ppem && ppem > best_ppem))
|
||||
{
|
||||
best_i = i;
|
||||
best_ppem = ppem;
|
||||
}
|
||||
}
|
||||
|
||||
return table->get_strike (best_i);
|
||||
}
|
||||
|
||||
struct PNGHeader
|
||||
{
|
||||
HBUINT8 signature[8];
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
HBUINT32 length;
|
||||
Tag type;
|
||||
} header;
|
||||
HBUINT32 width;
|
||||
HBUINT32 height;
|
||||
HBUINT8 bitDepth;
|
||||
HBUINT8 colorType;
|
||||
HBUINT8 compressionMethod;
|
||||
HBUINT8 filterMethod;
|
||||
HBUINT8 interlaceMethod;
|
||||
} IHDR;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (29);
|
||||
};
|
||||
|
||||
bool get_png_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
bool scale = true) const
|
||||
{
|
||||
/* Following code is safe to call even without data.
|
||||
* But faster to short-circuit. */
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
unsigned int strike_ppem = 0;
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
|
||||
const PNGHeader &png = *blob->as<PNGHeader>();
|
||||
|
||||
if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
extents->x_bearing = x_offset;
|
||||
extents->y_bearing = png.IHDR.height + y_offset;
|
||||
extents->width = png.IHDR.width;
|
||||
extents->height = -1 * png.IHDR.height;
|
||||
|
||||
/* Convert to font units. */
|
||||
if (strike_ppem && scale)
|
||||
{
|
||||
float scale = font->face->get_upem () / (float) strike_ppem;
|
||||
extents->x_bearing = roundf (extents->x_bearing * scale);
|
||||
extents->y_bearing = roundf (extents->y_bearing * scale);
|
||||
extents->width = roundf (extents->width * scale);
|
||||
extents->height = roundf (extents->height * scale);
|
||||
}
|
||||
|
||||
if (scale)
|
||||
font->scale_glyph_extents (extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return strike_ppem;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<sbix> table;
|
||||
|
||||
unsigned int num_glyphs;
|
||||
};
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
version >= 1 &&
|
||||
strikes.sanitize (c, this)));
|
||||
}
|
||||
|
||||
bool
|
||||
add_strike (hb_subset_context_t *c, unsigned i) const
|
||||
{
|
||||
if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
|
||||
return false;
|
||||
|
||||
return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
|
||||
}
|
||||
|
||||
bool serialize_strike_offsets (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
|
||||
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
|
||||
for (int i = strikes.len - 1; i >= 0; --i)
|
||||
{
|
||||
auto* o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
*o = 0;
|
||||
auto snap = c->serializer->snapshot ();
|
||||
c->serializer->push ();
|
||||
bool ret = add_strike (c, i);
|
||||
if (!ret)
|
||||
{
|
||||
c->serializer->pop_discard ();
|
||||
out->pop ();
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
else
|
||||
{
|
||||
objidxs.push (c->serializer->pop_pack ());
|
||||
new_strikes.push (o);
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < new_strikes.length; ++i)
|
||||
c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t* c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
|
||||
|
||||
return_trace (serialize_strike_offsets (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number — set to 1 */
|
||||
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
|
||||
* Bits 2 to 15: reserved (set to 0). */
|
||||
Array32OfOffset32To<SBIXStrike>
|
||||
strikes; /* Offsets from the beginning of the 'sbix'
|
||||
* table to data for each individual bitmap strike. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, strikes);
|
||||
};
|
||||
|
||||
struct sbix_accelerator_t : sbix::accelerator_t {
|
||||
sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
#endif /* OT_COLOR_SBIX_SBIX_HH */
|
151
src/3rdparty/harfbuzz-ng/src/OT/Color/svg/svg.hh
vendored
Normal file
151
src/3rdparty/harfbuzz-ng/src/OT/Color/svg/svg.hh
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_SVG_SVG_HH
|
||||
#define OT_COLOR_SVG_SVG_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-blob.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
|
||||
/*
|
||||
* SVG -- SVG (Scalable Vector Graphics)
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/svg
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_SVG HB_TAG('S','V','G',' ')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct SVGDocumentIndexEntry
|
||||
{
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
|
||||
|
||||
hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
|
||||
{
|
||||
return hb_blob_create_sub_blob (svg_blob,
|
||||
index_offset + (unsigned int) svgDoc,
|
||||
svgDocLength);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
svgDoc.sanitize (c, base, svgDocLength));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 startGlyphID; /* The first glyph ID in the range described by
|
||||
* this index entry. */
|
||||
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
|
||||
* this index entry. Must be >= startGlyphID. */
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT8>>
|
||||
svgDoc; /* Offset from the beginning of the SVG Document Index
|
||||
* to an SVG document. Must be non-zero. */
|
||||
HBUINT32 svgDocLength; /* Length of the SVG document.
|
||||
* Must be non-zero. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
struct SVG
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
|
||||
|
||||
bool has_data () const { return svgDocEntries; }
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{ table = hb_sanitize_context_t ().reference_table<SVG> (face); }
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
||||
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
|
||||
table->svgDocEntries);
|
||||
}
|
||||
|
||||
bool has_data () const { return table->has_data (); }
|
||||
|
||||
bool paint_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
hb_blob_t *blob = reference_blob_for_glyph (glyph);
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return false;
|
||||
|
||||
funcs->image (data,
|
||||
blob,
|
||||
0, 0,
|
||||
HB_PAINT_IMAGE_FORMAT_SVG,
|
||||
font->slant_xy,
|
||||
nullptr);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<SVG> table;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (sizeof (hb_blob_ptr_t<SVG>));
|
||||
};
|
||||
|
||||
const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
|
||||
{ return (this+svgDocEntries).bsearch (glyph_id); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
(this+svgDocEntries).sanitize_shallow (c)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version (starting at 0). */
|
||||
Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
|
||||
svgDocEntries; /* Offset (relative to the start of the SVG table) to the
|
||||
* SVG Documents Index. Must be non-zero. */
|
||||
/* Array of SVG Document Index Entries. */
|
||||
HBUINT32 reserved; /* Set to 0. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
struct SVG_accelerator_t : SVG::accelerator_t {
|
||||
SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* OT_COLOR_SVG_SVG_HH */
|
351
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
vendored
Normal file
351
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh
vendored
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGE_HH
|
||||
|
||||
#include "../types.hh"
|
||||
#include "CoverageFormat1.hh"
|
||||
#include "CoverageFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void Coverage_serialize (hb_serialize_context_t *c,
|
||||
Iterator it);
|
||||
|
||||
struct Coverage
|
||||
{
|
||||
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
CoverageFormat1_3<SmallTypes> format1;
|
||||
CoverageFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
CoverageFormat1_3<MediumTypes>format3;
|
||||
CoverageFormat2_4<MediumTypes>format4;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
HB_ALWAYS_INLINE
|
||||
#endif
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
case 4: return_trace (u.format4.sanitize (c));
|
||||
#endif
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Has interface. */
|
||||
unsigned operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.get_coverage (glyph_id);
|
||||
case 2: return u.format2.get_coverage (glyph_id);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_coverage (glyph_id);
|
||||
case 4: return u.format4.get_coverage (glyph_id);
|
||||
#endif
|
||||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.get_population ();
|
||||
case 2: return u.format2.get_population ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_population ();
|
||||
case 4: return u.format4.get_population ();
|
||||
#endif
|
||||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned count = hb_len (glyphs);
|
||||
unsigned num_ranges = 0;
|
||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||
hb_codepoint_t max = 0;
|
||||
bool unsorted = false;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last != (hb_codepoint_t) -2 && g < last)
|
||||
unsorted = true;
|
||||
if (last + 1 != g)
|
||||
num_ranges++;
|
||||
last = g;
|
||||
if (g > max) max = g;
|
||||
}
|
||||
u.format = !unsorted && count <= num_ranges * 3 ? 1 : 2;
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (max > 0xFFFFu)
|
||||
u.format += 2;
|
||||
if (unlikely (max > 0xFFFFFFu))
|
||||
#else
|
||||
if (unlikely (max > 0xFFFFu))
|
||||
#endif
|
||||
{
|
||||
c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs));
|
||||
case 2: return_trace (u.format2.serialize (c, glyphs));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (u.format3.serialize (c, glyphs));
|
||||
case 4: return_trace (u.format4.serialize (c, glyphs));
|
||||
#endif
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto it =
|
||||
+ iter ()
|
||||
| hb_take (c->plan->source->get_num_glyphs ())
|
||||
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
|
||||
| hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; })
|
||||
;
|
||||
|
||||
// Cache the iterator result as it will be iterated multiple times
|
||||
// by the serialize code below.
|
||||
hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
|
||||
Coverage_serialize (c->serializer, glyphs.iter ());
|
||||
return_trace (bool (glyphs));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.intersects (glyphs);
|
||||
case 2: return u.format2.intersects (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersects (glyphs);
|
||||
case 4: return u.format4.intersects (glyphs);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.intersects_coverage (glyphs, index);
|
||||
case 2: return u.format2.intersects_coverage (glyphs, index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersects_coverage (glyphs, index);
|
||||
case 4: return u.format4.intersects_coverage (glyphs, index);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.collect_coverage (glyphs);
|
||||
case 2: return u.format2.collect_coverage (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.collect_coverage (glyphs);
|
||||
case 4: return u.format4.collect_coverage (glyphs);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
||||
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
|
||||
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
|
||||
#endif
|
||||
default:return ;
|
||||
}
|
||||
}
|
||||
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const Coverage &c_ = Null (Coverage))
|
||||
{
|
||||
hb_memset (this, 0, sizeof (*this));
|
||||
format = c_.u.format;
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.init (c_.u.format1); return;
|
||||
case 2: u.format2.init (c_.u.format2); return;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: u.format3.init (c_.u.format3); return;
|
||||
case 4: u.format4.init (c_.u.format4); return;
|
||||
#endif
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
bool __more__ () const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1.__more__ ();
|
||||
case 2: return u.format2.__more__ ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.__more__ ();
|
||||
case 4: return u.format4.__more__ ();
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
void __next__ ()
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.__next__ (); break;
|
||||
case 2: u.format2.__next__ (); break;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: u.format3.__next__ (); break;
|
||||
case 4: u.format4.__next__ (); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
__item_t__ __item__ () const { return get_glyph (); }
|
||||
|
||||
hb_codepoint_t get_glyph () const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1.get_glyph ();
|
||||
case 2: return u.format2.get_glyph ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_glyph ();
|
||||
case 4: return u.format4.get_glyph ();
|
||||
#endif
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
bool operator != (const iter_t& o) const
|
||||
{
|
||||
if (unlikely (format != o.format)) return true;
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1 != o.u.format1;
|
||||
case 2: return u.format2 != o.u.format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3 != o.u.format3;
|
||||
case 4: return u.format4 != o.u.format4;
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
iter_t __end__ () const
|
||||
{
|
||||
iter_t it = {};
|
||||
it.format = format;
|
||||
switch (format)
|
||||
{
|
||||
case 1: it.u.format1 = u.format1.__end__ (); break;
|
||||
case 2: it.u.format2 = u.format2.__end__ (); break;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: it.u.format3 = u.format3.__end__ (); break;
|
||||
case 4: it.u.format4 = u.format4.__end__ (); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int format;
|
||||
union {
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1_3<MediumTypes>::iter_t format3;
|
||||
#endif
|
||||
CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1_3<SmallTypes>::iter_t format1;
|
||||
} u;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void
|
||||
Coverage_serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{ c->start_embed<Coverage> ()->serialize (c, it); }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH
|
133
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
vendored
Normal file
133
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
#define NOT_COVERED ((unsigned int) -1)
|
||||
|
||||
template <typename Types>
|
||||
struct CoverageFormat1_3
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
protected:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
|
||||
SortedArray16Of<typename Types::HBGlyphID>
|
||||
glyphArray; /* Array of GlyphIDs--in numerical order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, glyphArray);
|
||||
|
||||
private:
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (glyphArray.sanitize (c));
|
||||
}
|
||||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
unsigned int i;
|
||||
glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
return glyphArray.len;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (glyphArray.serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2)
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& g : glyphArray.as_array ())
|
||||
if (glyphs->has (g))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{ return glyphs->has (glyphArray[index]); }
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
unsigned count = glyphArray.len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
if (glyphs.has (glyphArray[i]))
|
||||
intersect_glyphs << glyphArray[i];
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_sorted_array (glyphArray.as_array ()); }
|
||||
|
||||
public:
|
||||
/* Older compilers need this to be public. */
|
||||
struct iter_t
|
||||
{
|
||||
void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
|
||||
bool __more__ () const { return i < c->glyphArray.len; }
|
||||
void __next__ () { i++; }
|
||||
hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return i != o.i; }
|
||||
iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
|
||||
|
||||
private:
|
||||
const struct CoverageFormat1_3 *c;
|
||||
unsigned int i;
|
||||
};
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
239
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
vendored
Normal file
239
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
||||
|
||||
#include "RangeRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template <typename Types>
|
||||
struct CoverageFormat2_4
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
protected:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 2 */
|
||||
SortedArray16Of<RangeRecord<Types>>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
* Start GlyphID. rangeCount entries
|
||||
* long */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, rangeRecord);
|
||||
|
||||
private:
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (rangeRecord.sanitize (c));
|
||||
}
|
||||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
|
||||
return likely (range.first <= range.last)
|
||||
? (unsigned int) range.value + (glyph_id - range.first)
|
||||
: NOT_COVERED;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
typename Types::large_int ret = 0;
|
||||
for (const auto &r : rangeRecord)
|
||||
ret += r.get_population ();
|
||||
return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned num_ranges = 0;
|
||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last + 1 != g)
|
||||
num_ranges++;
|
||||
last = g;
|
||||
}
|
||||
|
||||
if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
|
||||
if (!num_ranges) return_trace (true);
|
||||
|
||||
unsigned count = 0;
|
||||
unsigned range = (unsigned) -1;
|
||||
last = (hb_codepoint_t) -2;
|
||||
unsigned unsorted = false;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last + 1 != g)
|
||||
{
|
||||
if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g))
|
||||
unsorted = true;
|
||||
|
||||
range++;
|
||||
rangeRecord.arrayZ[range].first = g;
|
||||
rangeRecord.arrayZ[range].value = count;
|
||||
}
|
||||
rangeRecord.arrayZ[range].last = g;
|
||||
last = g;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (unlikely (unsorted))
|
||||
rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2)
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return hb_any (+ hb_iter (rangeRecord)
|
||||
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
auto *range = rangeRecord.as_array ().bsearch (index);
|
||||
if (range)
|
||||
return range->intersects (*glyphs);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
/* Break out of loop for overlapping, broken, tables,
|
||||
* to avoid fuzzer timouts. */
|
||||
hb_codepoint_t last = 0;
|
||||
for (const auto& range : rangeRecord)
|
||||
{
|
||||
if (unlikely (range.first < last))
|
||||
break;
|
||||
last = range.last;
|
||||
for (hb_codepoint_t g = range.first - 1;
|
||||
glyphs.next (&g) && g <= last;)
|
||||
intersect_glyphs << g;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
for (const auto& range: rangeRecord)
|
||||
if (unlikely (!range.collect_coverage (glyphs)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
/* Older compilers need this to be public. */
|
||||
struct iter_t
|
||||
{
|
||||
void init (const CoverageFormat2_4 &c_)
|
||||
{
|
||||
c = &c_;
|
||||
coverage = 0;
|
||||
i = 0;
|
||||
j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
|
||||
if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
|
||||
{
|
||||
/* Broken table. Skip. */
|
||||
i = c->rangeRecord.len;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
bool __more__ () const { return i < c->rangeRecord.len; }
|
||||
void __next__ ()
|
||||
{
|
||||
if (j >= c->rangeRecord[i].last)
|
||||
{
|
||||
i++;
|
||||
if (__more__ ())
|
||||
{
|
||||
unsigned int old = coverage;
|
||||
j = c->rangeRecord.arrayZ[i].first;
|
||||
coverage = c->rangeRecord.arrayZ[i].value;
|
||||
if (unlikely (coverage != old + 1))
|
||||
{
|
||||
/* Broken table. Skip. Important to avoid DoS.
|
||||
* Also, our callers depend on coverage being
|
||||
* consecutive and monotonically increasing,
|
||||
* ie. iota(). */
|
||||
i = c->rangeRecord.len;
|
||||
j = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
j = 0;
|
||||
return;
|
||||
}
|
||||
coverage++;
|
||||
j++;
|
||||
}
|
||||
hb_codepoint_t get_glyph () const { return j; }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return i != o.i || j != o.j; }
|
||||
iter_t __end__ () const
|
||||
{
|
||||
iter_t it;
|
||||
it.init (*c);
|
||||
it.i = c->rangeRecord.len;
|
||||
it.j = 0;
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
const struct CoverageFormat2_4 *c;
|
||||
unsigned int i, coverage;
|
||||
hb_codepoint_t j;
|
||||
};
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
97
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh
vendored
Normal file
97
src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
|
||||
#define OT_LAYOUT_COMMON_RANGERECORD_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template <typename Types>
|
||||
struct RangeRecord
|
||||
{
|
||||
typename Types::HBGlyphID first; /* First GlyphID in the range */
|
||||
typename Types::HBGlyphID last; /* Last GlyphID in the range */
|
||||
HBUINT16 value; /* Value */
|
||||
|
||||
DEFINE_SIZE_STATIC (2 + 2 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < first ? -1 : g <= last ? 0 : +1; }
|
||||
|
||||
HB_INTERNAL static int cmp_range (const void *pa, const void *pb) {
|
||||
const RangeRecord *a = (const RangeRecord *) pa;
|
||||
const RangeRecord *b = (const RangeRecord *) pb;
|
||||
if (a->first < b->first) return -1;
|
||||
if (a->first > b->first) return +1;
|
||||
if (a->last < b->last) return -1;
|
||||
if (a->last > b->last) return +1;
|
||||
if (a->value < b->value) return -1;
|
||||
if (a->value > b->value) return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
if (unlikely (last < first)) return 0;
|
||||
return (last - first + 1);
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t &glyphs) const
|
||||
{ return glyphs.intersects (first, last); }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_range (first, last); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(garretrieger): This was previously implemented using
|
||||
// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
|
||||
// but that only works when there is only a single namespace level.
|
||||
// The macro should probably be fixed so it can work in this situation.
|
||||
extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
|
||||
template <typename Spec>
|
||||
struct Null<OT::Layout::Common::RangeRecord<Spec>> {
|
||||
static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
|
||||
return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
|
1022
src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
vendored
Normal file
1022
src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
83
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Anchor.hh
vendored
Normal file
83
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Anchor.hh
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHOR_HH
|
||||
|
||||
#include "AnchorFormat1.hh"
|
||||
#include "AnchorFormat2.hh"
|
||||
#include "AnchorFormat3.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct Anchor
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
AnchorFormat1 format1;
|
||||
AnchorFormat2 format2;
|
||||
AnchorFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.sanitize (c)) return_trace (false);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
|
||||
float *x, float *y) const
|
||||
{
|
||||
*x = *y = 0;
|
||||
switch (u.format) {
|
||||
case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
|
||||
case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
|
||||
case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
case 2:
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
// AnchorFormat 2 just containins extra hinting information, so
|
||||
// if hints are being dropped convert to format 1.
|
||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
}
|
||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
|
||||
case 3: return_trace (u.format3.subset (c));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: case 2:
|
||||
return;
|
||||
case 3:
|
||||
u.format3.collect_variation_indices (c);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHOR_HH
|
46
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh
vendored
Normal file
46
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat1.hh
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat1
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
}
|
||||
|
||||
AnchorFormat1* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
AnchorFormat1* out = c->embed<AnchorFormat1> (this);
|
||||
if (!out) return_trace (out);
|
||||
out->format = 1;
|
||||
return_trace (out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
58
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh
vendored
Normal file
58
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat2.hh
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat2
|
||||
{
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
HBUINT16 anchorPoint; /* Index to glyph contour point */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
|
||||
#ifdef HB_NO_HINTING
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
unsigned int x_ppem = font->x_ppem;
|
||||
unsigned int y_ppem = font->y_ppem;
|
||||
hb_position_t cx = 0, cy = 0;
|
||||
bool ret;
|
||||
|
||||
ret = (x_ppem || y_ppem) &&
|
||||
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
|
||||
*x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
|
||||
*y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
|
||||
}
|
||||
|
||||
AnchorFormat2* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (c->embed<AnchorFormat2> (this));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
114
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
vendored
Normal file
114
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat3
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 3 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
Offset16To<Device>
|
||||
xDeviceTable; /* Offset to Device table for X
|
||||
* coordinate-- from beginning of
|
||||
* Anchor table (may be NULL) */
|
||||
Offset16To<Device>
|
||||
yDeviceTable; /* Offset to Device table for Y
|
||||
* coordinate-- from beginning of
|
||||
* Anchor table (may be NULL) */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this))) return_trace (false);
|
||||
|
||||
return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
|
||||
if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
|
||||
*x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
|
||||
if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
|
||||
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->embed (format))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
|
||||
|
||||
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
if (x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
{
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
|
||||
x_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
if (y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
{
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (y_varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
|
||||
y_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* in case that all axes are pinned or no variations after instantiation,
|
||||
* both var_idxes will be mapped to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */
|
||||
if (x_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX &&
|
||||
y_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
||||
if (!c->serializer->embed (yDeviceTable)) return_trace (false);
|
||||
|
||||
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
(this+xDeviceTable).collect_variation_indices (c);
|
||||
(this+yDeviceTable).collect_variation_indices (c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
85
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
vendored
Normal file
85
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorMatrix
|
||||
{
|
||||
HBUINT16 rows; /* Number of rows */
|
||||
UnsizedArrayOf<Offset16To<Anchor>>
|
||||
matrixZ; /* Matrix of offsets to Anchor tables--
|
||||
* from beginning of AnchorMatrix table */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, matrixZ);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!c->check_struct (this)) return_trace (false);
|
||||
if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
|
||||
unsigned int count = rows * cols;
|
||||
if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
const Anchor& get_anchor (hb_ot_apply_context_t *c,
|
||||
unsigned int row, unsigned int col,
|
||||
unsigned int cols, bool *found) const
|
||||
{
|
||||
*found = false;
|
||||
if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
|
||||
auto &offset = matrixZ[row * cols + col];
|
||||
if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
|
||||
*found = !offset.is_null ();
|
||||
return this+offset;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
Iterator index_iter) const
|
||||
{
|
||||
for (unsigned i : index_iter)
|
||||
(this+matrixZ[i]).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
unsigned num_rows,
|
||||
Iterator index_iter) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
|
||||
if (!index_iter) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
out->rows = num_rows;
|
||||
bool ret = false;
|
||||
for (const unsigned i : index_iter)
|
||||
{
|
||||
auto *offset = c->serializer->embed (matrixZ[i]);
|
||||
if (!offset) return_trace (false);
|
||||
ret |= offset->serialize_subset (c, matrixZ[i], this);
|
||||
}
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
|
14
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh
vendored
Normal file
14
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ChainContextPos.hh
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ChainContextPos : ChainContext {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */
|
33
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh
vendored
Normal file
33
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/Common.hh
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef OT_LAYOUT_GPOS_COMMON_HH
|
||||
#define OT_LAYOUT_GPOS_COMMON_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
enum attach_type_t {
|
||||
ATTACH_TYPE_NONE = 0X00,
|
||||
|
||||
/* Each attachment should be either a mark or a cursive; can't be both. */
|
||||
ATTACH_TYPE_MARK = 0X01,
|
||||
ATTACH_TYPE_CURSIVE = 0X02,
|
||||
};
|
||||
|
||||
/* buffer **position** var allocations */
|
||||
#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
|
||||
#define attach_type() var.u8[2] /* attachment type */
|
||||
/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
|
||||
|
||||
template<typename Iterator, typename SrcLookup>
|
||||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
bool all_axes_pinned);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_COMMON_HH
|
14
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh
vendored
Normal file
14
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ContextPos.hh
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ContextPos : Context {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */
|
35
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
vendored
Normal file
35
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePos.hh
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
|
||||
|
||||
#include "CursivePosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct CursivePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
CursivePosFormat1 format1;
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */
|
309
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
vendored
Normal file
309
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
|
||||
|
||||
#include "Anchor.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct EntryExitRecord
|
||||
{
|
||||
friend struct CursivePosFormat1;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
(src_base+entryAnchor).collect_variation_indices (c);
|
||||
(src_base+exitAnchor).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
ret |= out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
|
||||
ret |= out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
protected:
|
||||
Offset16To<Anchor>
|
||||
entryAnchor; /* Offset to EntryAnchor table--from
|
||||
* beginning of CursivePos
|
||||
* subtable--may be NULL */
|
||||
Offset16To<Anchor>
|
||||
exitAnchor; /* Offset to ExitAnchor table--from
|
||||
* beginning of CursivePos
|
||||
* subtable--may be NULL */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
static void
|
||||
reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
|
||||
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
|
||||
if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
|
||||
return;
|
||||
|
||||
pos[i].attach_chain() = 0;
|
||||
|
||||
unsigned int j = (int) i + chain;
|
||||
|
||||
/* Stop if we see new parent in the chain. */
|
||||
if (j == new_parent)
|
||||
return;
|
||||
|
||||
reverse_cursive_minor_offset (pos, j, direction, new_parent);
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
pos[j].y_offset = -pos[i].y_offset;
|
||||
else
|
||||
pos[j].x_offset = -pos[i].x_offset;
|
||||
|
||||
pos[j].attach_chain() = -chain;
|
||||
pos[j].attach_type() = type;
|
||||
}
|
||||
|
||||
|
||||
struct CursivePosFormat1
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
Array16Of<EntryExitRecord>
|
||||
entryExitRecord; /* Array of EntryExit records--in
|
||||
* Coverage Index order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, entryExitRecord);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!coverage.sanitize (c, this)))
|
||||
return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (entryExitRecord.sanitize_shallow (c));
|
||||
else
|
||||
return_trace (entryExitRecord.sanitize (c, this));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, entryExitRecord)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
|
||||
if (!this_record.entryAnchor ||
|
||||
unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_from;
|
||||
if (unlikely (!skippy_iter.prev (&unsafe_from)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
|
||||
if (!prev_record.exitAnchor ||
|
||||
unlikely (!prev_record.exitAnchor.sanitize (&c->sanitizer, this)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int i = skippy_iter.idx;
|
||||
unsigned int j = buffer->idx;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attaching glyph at %u to glyph at %u",
|
||||
i, j);
|
||||
}
|
||||
|
||||
buffer->unsafe_to_break (i, j + 1);
|
||||
float entry_x, entry_y, exit_x, exit_y;
|
||||
(this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
|
||||
(this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
|
||||
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
|
||||
hb_position_t d;
|
||||
/* Main-direction adjustment */
|
||||
switch (c->direction) {
|
||||
case HB_DIRECTION_LTR:
|
||||
pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
|
||||
|
||||
d = roundf (entry_x) + pos[j].x_offset;
|
||||
pos[j].x_advance -= d;
|
||||
pos[j].x_offset -= d;
|
||||
break;
|
||||
case HB_DIRECTION_RTL:
|
||||
d = roundf (exit_x) + pos[i].x_offset;
|
||||
pos[i].x_advance -= d;
|
||||
pos[i].x_offset -= d;
|
||||
|
||||
pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_TTB:
|
||||
pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
|
||||
|
||||
d = roundf (entry_y) + pos[j].y_offset;
|
||||
pos[j].y_advance -= d;
|
||||
pos[j].y_offset -= d;
|
||||
break;
|
||||
case HB_DIRECTION_BTT:
|
||||
d = roundf (exit_y) + pos[i].y_offset;
|
||||
pos[i].y_advance -= d;
|
||||
pos[i].y_offset -= d;
|
||||
|
||||
pos[j].y_advance = roundf (entry_y);
|
||||
break;
|
||||
case HB_DIRECTION_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cross-direction adjustment */
|
||||
|
||||
/* We attach child to parent (think graph theory and rooted trees whereas
|
||||
* the root stays on baseline and each node aligns itself against its
|
||||
* parent.
|
||||
*
|
||||
* Optimize things for the case of RightToLeft, as that's most common in
|
||||
* Arabic. */
|
||||
unsigned int child = i;
|
||||
unsigned int parent = j;
|
||||
hb_position_t x_offset = roundf (entry_x - exit_x);
|
||||
hb_position_t y_offset = roundf (entry_y - exit_y);
|
||||
if (!(c->lookup_props & LookupFlag::RightToLeft))
|
||||
{
|
||||
unsigned int k = child;
|
||||
child = parent;
|
||||
parent = k;
|
||||
x_offset = -x_offset;
|
||||
y_offset = -y_offset;
|
||||
}
|
||||
|
||||
/* If child was already connected to someone else, walk through its old
|
||||
* chain and reverse the link direction, such that the whole tree of its
|
||||
* previous connection now attaches to new parent. Watch out for case
|
||||
* where new parent is on the path from old chain...
|
||||
*/
|
||||
reverse_cursive_minor_offset (pos, child, c->direction, parent);
|
||||
|
||||
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
|
||||
pos[child].attach_chain() = (int) parent - (int) child;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
|
||||
pos[child].y_offset = y_offset;
|
||||
else
|
||||
pos[child].x_offset = x_offset;
|
||||
|
||||
/* If parent was attached to child, separate them.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/2469
|
||||
*/
|
||||
if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
|
||||
{
|
||||
pos[parent].attach_chain() = 0;
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
|
||||
pos[parent].y_offset = 0;
|
||||
else
|
||||
pos[parent].x_offset = 0;
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attached glyph at %u to glyph at %u",
|
||||
i, j);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_subset_context_t *c,
|
||||
Iterator it,
|
||||
const void *src_base)
|
||||
{
|
||||
if (unlikely (!c->serializer->extend_min ((*this)))) return;
|
||||
this->format = 1;
|
||||
this->entryExitRecord.len = it.len ();
|
||||
|
||||
for (const EntryExitRecord& entry_record : + it
|
||||
| hb_map (hb_second))
|
||||
entry_record.subset (c, src_base);
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c->serializer, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, entryExitRecord)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
|
||||
{ return hb_pair (glyph_map[p.first], p.second);})
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
out->serialize (c, it, this);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */
|
17
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh
vendored
Normal file
17
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ExtensionPos.hh
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
|
||||
#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ExtensionPos : Extension<ExtensionPos>
|
||||
{
|
||||
typedef struct PosLookupSubTable SubTable;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */
|
171
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh
vendored
Normal file
171
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
#ifndef OT_LAYOUT_GPOS_GPOS_HH
|
||||
#define OT_LAYOUT_GPOS_GPOS_HH
|
||||
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
#include "Common.hh"
|
||||
#include "PosLookup.hh"
|
||||
|
||||
namespace OT {
|
||||
|
||||
using Layout::GPOS_impl::PosLookup;
|
||||
|
||||
namespace Layout {
|
||||
|
||||
static void
|
||||
propagate_attachment_offsets (hb_glyph_position_t *pos,
|
||||
unsigned int len,
|
||||
unsigned int i,
|
||||
hb_direction_t direction,
|
||||
unsigned nesting_level = HB_MAX_NESTING_LEVEL);
|
||||
|
||||
/*
|
||||
* GPOS -- Glyph Positioning
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
|
||||
*/
|
||||
|
||||
struct GPOS : GSUBGPOS
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
|
||||
|
||||
using Lookup = PosLookup;
|
||||
|
||||
const PosLookup& get_lookup (unsigned int i) const
|
||||
{ return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
|
||||
|
||||
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
|
||||
static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
|
||||
static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<PosLookup> (&l);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (GSUBGPOS::sanitize<PosLookup> (c));
|
||||
}
|
||||
|
||||
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
|
||||
{
|
||||
if (!c->gpos_lookups->has (i)) continue;
|
||||
const PosLookup &l = get_lookup (i);
|
||||
l.dispatch (c);
|
||||
}
|
||||
}
|
||||
|
||||
void closure_lookups (hb_face_t *face,
|
||||
const hb_set_t *glyphs,
|
||||
hb_set_t *lookup_indexes /* IN/OUT */) const
|
||||
{ GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
|
||||
|
||||
typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
propagate_attachment_offsets (hb_glyph_position_t *pos,
|
||||
unsigned int len,
|
||||
unsigned int i,
|
||||
hb_direction_t direction,
|
||||
unsigned nesting_level)
|
||||
{
|
||||
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
|
||||
* offset of glyph they are attached to. */
|
||||
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
|
||||
if (likely (!chain))
|
||||
return;
|
||||
|
||||
pos[i].attach_chain() = 0;
|
||||
|
||||
unsigned int j = (int) i + chain;
|
||||
|
||||
if (unlikely (j >= len))
|
||||
return;
|
||||
|
||||
if (unlikely (!nesting_level))
|
||||
return;
|
||||
|
||||
propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
|
||||
|
||||
assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
|
||||
|
||||
if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
|
||||
{
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
pos[i].y_offset += pos[j].y_offset;
|
||||
else
|
||||
pos[i].x_offset += pos[j].x_offset;
|
||||
}
|
||||
else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
|
||||
{
|
||||
pos[i].x_offset += pos[j].x_offset;
|
||||
pos[i].y_offset += pos[j].y_offset;
|
||||
|
||||
assert (j < i);
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = j; k < i; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = j + 1; k < i + 1; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
|
||||
{
|
||||
//_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||
|
||||
unsigned int len;
|
||||
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
|
||||
hb_direction_t direction = buffer->props.direction;
|
||||
|
||||
/* Handle attachments */
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
|
||||
if (unlikely (font->slant))
|
||||
{
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (unlikely (pos[i].y_offset))
|
||||
pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
|
||||
GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_GPOS_HH */
|
57
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh
vendored
Normal file
57
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH
|
||||
#define OT_LAYOUT_GPOS_LIGATUREARRAY_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
typedef AnchorMatrix LigatureAttach; /* component-major--
|
||||
* in order of writing direction--,
|
||||
* mark-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
|
||||
struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
||||
{
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
Iterator coverage,
|
||||
unsigned class_count,
|
||||
const hb_map_t *klass_mapping) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
for (const auto _ : + hb_zip (coverage, *this)
|
||||
| hb_filter (glyphset, hb_first))
|
||||
{
|
||||
auto *matrix = out->serialize_append (c->serializer);
|
||||
if (unlikely (!matrix)) return_trace (false);
|
||||
|
||||
const LigatureAttach& src = (this + _.second);
|
||||
auto indexes =
|
||||
+ hb_range (src.rows * class_count)
|
||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||
;
|
||||
ret |= matrix->serialize_subset (c,
|
||||
_.second,
|
||||
this,
|
||||
src.rows,
|
||||
indexes);
|
||||
}
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_HH */
|
128
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
vendored
Normal file
128
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
|
||||
#define OT_LAYOUT_GPOS_MARKARRAY_HH
|
||||
|
||||
#include "AnchorMatrix.hh"
|
||||
#include "MarkRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (Array16Of<MarkRecord>::sanitize (c, this));
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c,
|
||||
unsigned int mark_index, unsigned int glyph_index,
|
||||
const AnchorMatrix &anchors, unsigned int class_count,
|
||||
unsigned int glyph_pos) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
|
||||
unsigned int mark_class = record.klass;
|
||||
|
||||
const Anchor& mark_anchor = this + record.markAnchor;
|
||||
bool found;
|
||||
const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found);
|
||||
/* If this subtable doesn't have an anchor for this base and this class,
|
||||
* return false such that the subsequent subtables have a chance at it. */
|
||||
if (unlikely (!found)) return_trace (false);
|
||||
|
||||
float mark_x, mark_y, base_x, base_y;
|
||||
|
||||
buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
|
||||
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
|
||||
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attaching mark glyph at %u to glyph at %u",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
hb_glyph_position_t &o = buffer->cur_pos();
|
||||
o.x_offset = roundf (base_x - mark_x);
|
||||
o.y_offset = roundf (base_y - mark_y);
|
||||
o.attach_type() = ATTACH_TYPE_MARK;
|
||||
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attached mark glyph at %u to glyph at %u",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
Iterator coverage,
|
||||
const hb_map_t *klass_mapping) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
|
||||
auto* out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (coverage, this->iter ())
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
bool ret = false;
|
||||
unsigned new_length = 0;
|
||||
for (const auto& mark_record : mark_iter) {
|
||||
ret |= mark_record.subset (c, this, klass_mapping);
|
||||
new_length++;
|
||||
}
|
||||
|
||||
if (unlikely (!c->serializer->check_assign (out->len, new_length,
|
||||
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
HB_INTERNAL inline
|
||||
void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
|
||||
const MarkArray &mark_array,
|
||||
const hb_set_t &glyphset,
|
||||
hb_map_t* klass_mapping /* INOUT */)
|
||||
{
|
||||
hb_set_t orig_classes;
|
||||
|
||||
+ hb_zip (mark_coverage, mark_array)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (&MarkRecord::get_class)
|
||||
| hb_sink (orig_classes)
|
||||
;
|
||||
|
||||
unsigned idx = 0;
|
||||
for (auto klass : orig_classes.iter ())
|
||||
{
|
||||
if (klass_mapping->has (klass)) continue;
|
||||
klass_mapping->set (klass, idx);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
|
41
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
vendored
Normal file
41
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePos.hh
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKBASEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKBASEPOS_HH
|
||||
|
||||
#include "MarkBasePosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkBasePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKBASEPOS_HH */
|
243
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
vendored
Normal file
243
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
|
||||
|
||||
#include "MarkArray.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef AnchorMatrix BaseArray; /* base-major--
|
||||
* in order of BaseCoverage Index--,
|
||||
* mark-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
template <typename Types>
|
||||
struct MarkBasePosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to MarkCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
baseCoverage; /* Offset to BaseCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
HBUINT16 classCount; /* Number of classes defined for marks */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
typename Types::template OffsetTo<BaseArray>
|
||||
baseArray; /* Offset to BaseArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
markCoverage.sanitize (c, this) &&
|
||||
baseCoverage.sanitize (c, this) &&
|
||||
markArray.sanitize (c, this) &&
|
||||
baseArray.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+baseCoverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned basecount = (this+baseArray).rows;
|
||||
auto base_iter =
|
||||
+ hb_zip (this+baseCoverage, hb_range (basecount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
for (const unsigned row : base_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (base_indexes)
|
||||
;
|
||||
}
|
||||
(this+baseArray).collect_variation_indices (c, base_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||
|
||||
static inline bool accept (hb_buffer_t *buffer, unsigned idx)
|
||||
{
|
||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||
* Reject others...
|
||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||
return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
|
||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
|
||||
(idx == 0 ||
|
||||
_hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
|
||||
!_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
|
||||
);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph.
|
||||
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/4124
|
||||
if (!accept (buffer, j - 1) &&
|
||||
NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
|
||||
match = skippy_iter.SKIP;
|
||||
}
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
|
||||
|
||||
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
if (base_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ mark_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||
(this+markCoverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
unsigned basecount = (this+baseArray).rows;
|
||||
auto base_iter =
|
||||
+ hb_zip (this+baseCoverage, hb_range (basecount))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
+ base_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
for (const unsigned row : + base_iter
|
||||
| hb_map (hb_second))
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (base_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
return_trace (out->baseArray.serialize_subset (c, baseArray, this,
|
||||
base_iter.len (),
|
||||
base_indexes.iter ()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH */
|
41
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
vendored
Normal file
41
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPos.hh
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKLIGPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKLIGPOS_HH
|
||||
|
||||
#include "MarkLigPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkLigPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKLIGPOS_HH */
|
224
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
vendored
Normal file
224
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
|
||||
|
||||
#include "LigatureArray.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct MarkLigPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to Mark Coverage table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
ligatureCoverage; /* Offset to Ligature Coverage
|
||||
* table--from beginning of MarkLigPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
typename Types::template OffsetTo<LigatureArray>
|
||||
ligatureArray; /* Offset to LigatureArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
markCoverage.sanitize (c, this) &&
|
||||
ligatureCoverage.sanitize (c, this) &&
|
||||
markArray.sanitize (c, this) &&
|
||||
ligatureArray.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+ligatureCoverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned ligcount = (this+ligatureArray).len;
|
||||
auto lig_iter =
|
||||
+ hb_zip (this+ligatureCoverage, hb_range (ligcount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
const LigatureArray& lig_array = this+ligatureArray;
|
||||
for (const unsigned i : lig_iter)
|
||||
{
|
||||
hb_sorted_vector_t<unsigned> lig_indexes;
|
||||
unsigned row_count = lig_array[i].rows;
|
||||
for (unsigned row : + hb_range (row_count))
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (lig_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
|
||||
|
||||
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
if (lig_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
const LigatureArray& lig_array = this+ligatureArray;
|
||||
const LigatureAttach& lig_attach = lig_array[lig_index];
|
||||
|
||||
/* Find component to attach to */
|
||||
unsigned int comp_count = lig_attach.rows;
|
||||
if (unlikely (!comp_count))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
/* We must now check whether the ligature ID of the current mark glyph
|
||||
* is identical to the ligature ID of the found ligature. If yes, we
|
||||
* can directly use the component index. If not, we attach the mark
|
||||
* glyph to the last component of the ligature. */
|
||||
unsigned int comp_index;
|
||||
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[idx]);
|
||||
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
||||
comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
|
||||
else
|
||||
comp_index = comp_count - 1;
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
auto new_mark_coverage =
|
||||
+ mark_iter
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
;
|
||||
|
||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||
(this+markCoverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
auto new_ligature_coverage =
|
||||
+ hb_iter (this + ligatureCoverage)
|
||||
| hb_take ((this + ligatureArray).len)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
| hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; })
|
||||
;
|
||||
|
||||
if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
||||
hb_iter (this+ligatureCoverage),
|
||||
classCount, &klass_mapping));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH */
|
42
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
vendored
Normal file
42
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPos.hh
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKMARKPOS_HH
|
||||
|
||||
#include "MarkMarkPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkMarkPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */
|
230
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
vendored
Normal file
230
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
|
||||
|
||||
#include "MarkMarkPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef AnchorMatrix Mark2Array; /* mark2-major--
|
||||
* in order of Mark2Coverage Index--,
|
||||
* mark1-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
template <typename Types>
|
||||
struct MarkMarkPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark1Coverage; /* Offset to Combining Mark1 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark2Coverage; /* Offset to Combining Mark2 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
mark1Array; /* Offset to Mark1Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
typename Types::template OffsetTo<Mark2Array>
|
||||
mark2Array; /* Offset to Mark2Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
mark1Coverage.sanitize (c, this) &&
|
||||
mark2Coverage.sanitize (c, this) &&
|
||||
mark1Array.sanitize (c, this) &&
|
||||
mark2Array.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+mark1Coverage).intersects (glyphs) &&
|
||||
(this+mark2Coverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+mark1Coverage, this+mark1Array)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned mark2_count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2_count))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
for (const unsigned row : mark2_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (mark2_indexes)
|
||||
;
|
||||
}
|
||||
(this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+mark1Coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark1_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
|
||||
unsigned unsafe_from;
|
||||
if (unlikely (!skippy_iter.prev (&unsafe_from)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int j = skippy_iter.idx;
|
||||
|
||||
unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||
unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
|
||||
unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
|
||||
|
||||
if (likely (id1 == id2))
|
||||
{
|
||||
if (id1 == 0) /* Marks belonging to the same base. */
|
||||
goto good;
|
||||
else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
|
||||
goto good;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If ligature ids don't match, it may be the case that one of the marks
|
||||
* itself is a ligature. In which case match. */
|
||||
if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
|
||||
goto good;
|
||||
}
|
||||
|
||||
/* Didn't match. */
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
|
||||
good:
|
||||
unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
|
||||
if (mark2_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark1_iter =
|
||||
+ hb_zip (this+mark1Coverage, this+mark1Array)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ mark1_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
|
||||
(this+mark1Coverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
unsigned mark2count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2count))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
+ mark2_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
for (const unsigned row : + mark2_iter
|
||||
| hb_map (hb_second))
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (mark2_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
|
||||
mark2_iter.len (),
|
||||
mark2_indexes.iter ()));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */
|
51
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh
vendored
Normal file
51
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKRECORD_HH
|
||||
#define OT_LAYOUT_GPOS_MARKRECORD_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkRecord
|
||||
{
|
||||
friend struct MarkArray;
|
||||
|
||||
public:
|
||||
HBUINT16 klass; /* Class defined for this mark */
|
||||
Offset16To<Anchor>
|
||||
markAnchor; /* Offset to Anchor table--from
|
||||
* beginning of MarkArray table */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
|
||||
unsigned get_class () const { return (unsigned) klass; }
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const void *src_base,
|
||||
const hb_map_t *klass_mapping) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->klass = klass_mapping->get (klass);
|
||||
return_trace (out->markAnchor.serialize_subset (c, markAnchor, src_base));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
(src_base+markAnchor).collect_variation_indices (c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKRECORD_HH */
|
46
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
vendored
Normal file
46
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPos.hh
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOS_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOS_HH
|
||||
|
||||
#include "PairPosFormat1.hh"
|
||||
#include "PairPosFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PairPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
PairPosFormat1_3<SmallTypes> format1;
|
||||
PairPosFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
PairPosFormat1_3<MediumTypes> format3;
|
||||
PairPosFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOS_HH
|
217
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
vendored
Normal file
217
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
||||
|
||||
#include "PairSet.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairPosFormat1_3
|
||||
{
|
||||
using PairSet = GPOS_impl::PairSet<Types>;
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat[2]; /* [0] Defines the types of data in
|
||||
* ValueRecord1--for the first glyph
|
||||
* in the pair--may be zero (0) */
|
||||
/* [1] Defines the types of data in
|
||||
* ValueRecord2--for the second glyph
|
||||
* in the pair--may be zero (0) */
|
||||
Array16Of<typename Types::template OffsetTo<PairSet>>
|
||||
pairSet; /* Array of PairSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (!c->check_struct (this)) return_trace (false);
|
||||
|
||||
unsigned int len1 = valueFormat[0].get_len ();
|
||||
unsigned int len2 = valueFormat[1].get_len ();
|
||||
typename PairSet::sanitize_closure_t closure =
|
||||
{
|
||||
valueFormat,
|
||||
len1,
|
||||
PairSet::get_size (len1, len2)
|
||||
};
|
||||
|
||||
return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
auto &cov = this+coverage;
|
||||
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
||||
{
|
||||
for (hb_codepoint_t g : glyphs->iter())
|
||||
{
|
||||
unsigned i = cov.get_coverage (g);
|
||||
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
+ hb_zip (cov, pairSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
|
||||
{ return (this+_).intersects (glyphs, valueFormat); })
|
||||
| hb_any
|
||||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
+ it
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
unsigned int count = pairSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
(this+pairSet[i]).collect_glyphs (c, valueFormat);
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_to;
|
||||
if (unlikely (!skippy_iter.next (&unsafe_to)))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
out->valueFormat[0] = valueFormat[0];
|
||||
out->valueFormat[1] = valueFormat[1];
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
|
||||
out->valueFormat[0] = newFormats.first;
|
||||
out->valueFormat[1] = newFormats.second;
|
||||
}
|
||||
|
||||
if (c->plan->all_axes_pinned)
|
||||
{
|
||||
out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags ();
|
||||
out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags ();
|
||||
}
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
|
||||
{
|
||||
auto snap = c->serializer->snapshot ();
|
||||
auto *o = out->pairSet.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return false;
|
||||
bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
|
||||
if (!ret)
|
||||
{
|
||||
out->pairSet.pop ();
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
||||
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
|
||||
{
|
||||
unsigned record_size = PairSet::get_size (valueFormat);
|
||||
|
||||
unsigned format1 = 0;
|
||||
unsigned format2 = 0;
|
||||
for (const auto & _ :
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
)
|
||||
{
|
||||
const PairSet& set = (this + _);
|
||||
const PairValueRecord *record = &set.firstPairValueRecord;
|
||||
|
||||
unsigned count = set.len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (record->intersects (glyphset))
|
||||
{
|
||||
format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
|
||||
format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
|
||||
}
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat[0] && format2 == valueFormat[1])
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
359
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
vendored
Normal file
359
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
||||
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct PairPosFormat2_4
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat1; /* ValueRecord definition--for the
|
||||
* first glyph of the pair--may be zero
|
||||
* (0) */
|
||||
ValueFormat valueFormat2; /* ValueRecord definition--for the
|
||||
* second glyph of the pair--may be
|
||||
* zero (0) */
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef1; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the first glyph of the pair */
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef2; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the second glyph of the pair */
|
||||
HBUINT16 class1Count; /* Number of classes in ClassDef1
|
||||
* table--includes Class0 */
|
||||
HBUINT16 class2Count; /* Number of classes in ClassDef2
|
||||
* table--includes Class0 */
|
||||
ValueRecord values; /* Matrix of value pairs:
|
||||
* class1-major, class2-minor,
|
||||
* Each entry has value1 and value2 */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!(c->check_struct (this)
|
||||
&& coverage.sanitize (c, this)
|
||||
&& classDef1.sanitize (c, this)
|
||||
&& classDef2.sanitize (c, this))) return_trace (false);
|
||||
|
||||
unsigned int len1 = valueFormat1.get_len ();
|
||||
unsigned int len2 = valueFormat2.get_len ();
|
||||
unsigned int stride = HBUINT16::static_size * (len1 + len2);
|
||||
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
|
||||
return_trace (c->check_range ((const void *) values,
|
||||
count,
|
||||
stride) &&
|
||||
(c->lazy_some_gpos ||
|
||||
(valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
|
||||
valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride))));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+coverage).intersects (glyphs) &&
|
||||
(this+classDef2).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!intersects (c->glyph_set)) return;
|
||||
if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
|
||||
|
||||
hb_set_t klass1_glyphs, klass2_glyphs;
|
||||
if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
|
||||
if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
|
||||
|
||||
hb_set_t class1_set, class2_set;
|
||||
for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
|
||||
{
|
||||
if (!klass1_glyphs.has (cp)) class1_set.add (0);
|
||||
else
|
||||
{
|
||||
unsigned klass1 = (this+classDef1).get (cp);
|
||||
class1_set.add (klass1);
|
||||
}
|
||||
}
|
||||
|
||||
class2_set.add (0);
|
||||
for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
|
||||
{
|
||||
unsigned klass2 = (this+classDef2).get (cp);
|
||||
class2_set.add (klass2);
|
||||
}
|
||||
|
||||
if (class1_set.is_empty ()
|
||||
|| class2_set.is_empty ()
|
||||
|| (class2_set.get_population() == 1 && class2_set.has(0)))
|
||||
return;
|
||||
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
|
||||
for (const unsigned class1_idx : class1_set.iter ())
|
||||
{
|
||||
for (const unsigned class2_idx : class2_set.iter ())
|
||||
{
|
||||
unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||
if (valueFormat1.has_device ())
|
||||
valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
|
||||
|
||||
if (valueFormat2.has_device ())
|
||||
valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_to;
|
||||
if (unlikely (!skippy_iter.next (&unsafe_to)))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
|
||||
if (!klass2)
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
|
||||
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int len1 = valueFormat1.get_len ();
|
||||
unsigned int len2 = valueFormat2.get_len ();
|
||||
unsigned int record_len = len1 + len2;
|
||||
|
||||
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
|
||||
|
||||
bool applied_first = false, applied_second = false;
|
||||
|
||||
|
||||
/* Isolate simple kerning and apply it half to each side.
|
||||
* Results in better cursor positioning / underline drawing.
|
||||
*
|
||||
* Disabled, because causes issues... :-(
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3408
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
|
||||
*/
|
||||
#ifndef HB_SPLIT_KERN
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
if (!len2)
|
||||
{
|
||||
const hb_direction_t dir = buffer->props.direction;
|
||||
const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
|
||||
const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
|
||||
unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
|
||||
if (backward)
|
||||
mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
|
||||
/* Add Devices. */
|
||||
mask |= mask << 4;
|
||||
|
||||
if (valueFormat1 & ~mask)
|
||||
goto bail;
|
||||
|
||||
/* Is simple kern. Apply value on an empty position slot,
|
||||
* then split it between sides. */
|
||||
|
||||
hb_glyph_position_t pos{};
|
||||
if (valueFormat1.apply_value (c, this, v, pos))
|
||||
{
|
||||
hb_position_t *src = &pos.x_advance;
|
||||
hb_position_t *dst1 = &buffer->cur_pos().x_advance;
|
||||
hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
|
||||
unsigned i = horizontal ? 0 : 1;
|
||||
|
||||
hb_position_t kern = src[i];
|
||||
hb_position_t kern1 = kern >> 1;
|
||||
hb_position_t kern2 = kern - kern1;
|
||||
|
||||
if (!backward)
|
||||
{
|
||||
dst1[i] += kern1;
|
||||
dst2[i] += kern2;
|
||||
dst2[i + 2] += kern2;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst1[i] += kern1;
|
||||
dst1[i + 2] += src[i + 2] - kern2;
|
||||
dst2[i] += kern2;
|
||||
}
|
||||
|
||||
applied_first = applied_second = kern != 0;
|
||||
goto success;
|
||||
}
|
||||
goto boring;
|
||||
}
|
||||
}
|
||||
bail:
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
applied_first = len1 && valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
||||
applied_second = len2 && valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
||||
|
||||
if (applied_first || applied_second)
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
success:
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
else
|
||||
boring:
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
|
||||
if (len2)
|
||||
{
|
||||
skippy_iter.idx++;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
}
|
||||
|
||||
buffer->idx = skippy_iter.idx;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass1_map;
|
||||
out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
|
||||
out->class1Count = klass1_map.get_population ();
|
||||
|
||||
hb_map_t klass2_map;
|
||||
out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
|
||||
out->class2Count = klass2_map.get_population ();
|
||||
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
|
||||
hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
newFormats = compute_effective_value_formats (klass1_map, klass2_map);
|
||||
|
||||
out->valueFormat1 = newFormats.first;
|
||||
out->valueFormat2 = newFormats.second;
|
||||
|
||||
if (c->plan->all_axes_pinned)
|
||||
{
|
||||
out->valueFormat1 = out->valueFormat1.drop_device_table_flags ();
|
||||
out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
|
||||
}
|
||||
|
||||
unsigned total_len = len1 + len2;
|
||||
hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
|
||||
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
||||
{
|
||||
for (unsigned class2_idx : class2_idxs)
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len;
|
||||
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
|
||||
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
|
||||
}
|
||||
}
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (glyphset)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
;
|
||||
|
||||
out->coverage.serialize_serialize (c->serializer, it);
|
||||
return_trace (out->class1Count && out->class2Count && bool (it));
|
||||
}
|
||||
|
||||
|
||||
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
|
||||
const hb_map_t& klass2_map) const
|
||||
{
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
unsigned record_size = len1 + len2;
|
||||
|
||||
unsigned format1 = 0;
|
||||
unsigned format2 = 0;
|
||||
|
||||
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
||||
{
|
||||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
|
||||
format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
|
||||
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat1 && format2 == valueFormat2)
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
208
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
vendored
Normal file
208
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRSET_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRSET_HH
|
||||
|
||||
#include "PairValueRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairSet
|
||||
{
|
||||
template <typename Types2>
|
||||
friend struct PairPosFormat1_3;
|
||||
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 len; /* Number of PairValueRecords */
|
||||
PairValueRecord firstPairValueRecord;
|
||||
/* Array of PairValueRecords--ordered
|
||||
* by GlyphID of the second glyph */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
|
||||
static unsigned get_size (unsigned len1, unsigned len2)
|
||||
{
|
||||
return Types::HBGlyphID::static_size + Value::static_size * (len1 + len2);
|
||||
}
|
||||
static unsigned get_size (const ValueFormat valueFormats[2])
|
||||
{
|
||||
unsigned len1 = valueFormats[0].get_len ();
|
||||
unsigned len2 = valueFormats[1].get_len ();
|
||||
return get_size (len1, len2);
|
||||
}
|
||||
|
||||
struct sanitize_closure_t
|
||||
{
|
||||
const ValueFormat *valueFormats;
|
||||
unsigned int len1; /* valueFormats[0].get_len() */
|
||||
unsigned int stride; /* bytes */
|
||||
};
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!(c->check_struct (this)
|
||||
&& c->check_range (&firstPairValueRecord,
|
||||
len,
|
||||
closure->stride))) return_trace (false);
|
||||
|
||||
unsigned int count = len;
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
return_trace (c->lazy_some_gpos ||
|
||||
(closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
|
||||
closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphs->has (record->secondGlyph))
|
||||
return true;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
c->input->add_array (&record->secondGlyph, len, record_size);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (c->glyph_set->has (record->secondGlyph))
|
||||
{ record->collect_variation_indices (c, valueFormats, this); }
|
||||
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
unsigned int pos) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int len1 = valueFormats[0].get_len ();
|
||||
unsigned int len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = get_size (len1, len2);
|
||||
|
||||
const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
|
||||
&firstPairValueRecord,
|
||||
len,
|
||||
record_size);
|
||||
if (record)
|
||||
{
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
||||
bool applied_second = len2 && valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
||||
|
||||
if (applied_first || applied_second)
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
|
||||
if (len2)
|
||||
{
|
||||
pos++;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
}
|
||||
|
||||
buffer->idx = pos;
|
||||
return_trace (true);
|
||||
}
|
||||
buffer->unsafe_to_concat (buffer->idx, pos + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const ValueFormat valueFormats[2],
|
||||
const ValueFormat newFormats[2]) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->len = 0;
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned len1 = valueFormats[0].get_len ();
|
||||
unsigned len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = get_size (len1, len2);
|
||||
|
||||
typename PairValueRecord::context_t context =
|
||||
{
|
||||
this,
|
||||
valueFormats,
|
||||
newFormats,
|
||||
len1,
|
||||
&glyph_map,
|
||||
&c->plan->layout_variation_idx_delta_map
|
||||
};
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len, num = 0;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphset.has (record->secondGlyph)
|
||||
&& record->subset (c, &context)) num++;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
out->len = num;
|
||||
if (!num) c->serializer->revert (snap);
|
||||
return_trace (num);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRSET_HH
|
99
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
vendored
Normal file
99
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairValueRecord
|
||||
{
|
||||
template <typename Types2>
|
||||
friend struct PairSet;
|
||||
|
||||
protected:
|
||||
typename Types::HBGlyphID
|
||||
secondGlyph; /* GlyphID of second glyph in the
|
||||
* pair--first glyph is listed in the
|
||||
* Coverage table */
|
||||
ValueRecord values; /* Positioning data for the first glyph
|
||||
* followed by for second glyph */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (Types::HBGlyphID::static_size, values);
|
||||
|
||||
int cmp (hb_codepoint_t k) const
|
||||
{ return secondGlyph.cmp (k); }
|
||||
|
||||
struct context_t
|
||||
{
|
||||
const void *base;
|
||||
const ValueFormat *valueFormats;
|
||||
const ValueFormat *newFormats;
|
||||
unsigned len1; /* valueFormats[0].get_len() */
|
||||
const hb_map_t *glyph_map;
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
|
||||
};
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
context_t *closure) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *s = c->serializer;
|
||||
auto *out = s->start_embed (*this);
|
||||
if (unlikely (!s->extend_min (out))) return_trace (false);
|
||||
|
||||
out->secondGlyph = (*closure->glyph_map)[secondGlyph];
|
||||
|
||||
closure->valueFormats[0].copy_values (s,
|
||||
closure->newFormats[0],
|
||||
closure->base, &values[0],
|
||||
closure->layout_variation_idx_delta_map);
|
||||
closure->valueFormats[1].copy_values (s,
|
||||
closure->newFormats[1],
|
||||
closure->base,
|
||||
&values[closure->len1],
|
||||
closure->layout_variation_idx_delta_map);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
const void *base) const
|
||||
{
|
||||
unsigned record1_len = valueFormats[0].get_len ();
|
||||
unsigned record2_len = valueFormats[1].get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
|
||||
|
||||
if (valueFormats[0].has_device ())
|
||||
valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
|
||||
|
||||
if (valueFormats[1].has_device ())
|
||||
valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t& glyphset) const
|
||||
{
|
||||
return glyphset.has(secondGlyph);
|
||||
}
|
||||
|
||||
const Value* get_values_1 () const
|
||||
{
|
||||
return &values[0];
|
||||
}
|
||||
|
||||
const Value* get_values_2 (ValueFormat format1) const
|
||||
{
|
||||
return &values[format1.get_len ()];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
79
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh
vendored
Normal file
79
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookup.hh
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef OT_LAYOUT_GPOS_POSLOOKUP_HH
|
||||
#define OT_LAYOUT_GPOS_POSLOOKUP_HH
|
||||
|
||||
#include "PosLookupSubTable.hh"
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PosLookup : Lookup
|
||||
{
|
||||
using SubTable = PosLookupSubTable;
|
||||
|
||||
const SubTable& get_subtable (unsigned int i) const
|
||||
{ return Lookup::get_subtable<SubTable> (i); }
|
||||
|
||||
bool is_reverse () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ return dispatch (c); }
|
||||
|
||||
hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
|
||||
{
|
||||
if (c->is_lookup_visited (this_index))
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
|
||||
c->set_lookup_visited (this_index);
|
||||
if (!intersects (c->glyphs))
|
||||
{
|
||||
c->set_lookup_inactive (this_index);
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
}
|
||||
|
||||
hb_closure_lookups_context_t::return_t ret = dispatch (c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
hb_collect_coverage_context_t<set_t> c (glyphs);
|
||||
dispatch (&c);
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{ return Lookup::subset<SubTable> (c); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return Lookup::sanitize<SubTable> (c); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_POSLOOKUP_HH */
|
79
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh
vendored
Normal file
79
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PosLookupSubTable.hh
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
|
||||
#define OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
|
||||
|
||||
#include "SinglePos.hh"
|
||||
#include "PairPos.hh"
|
||||
#include "CursivePos.hh"
|
||||
#include "MarkBasePos.hh"
|
||||
#include "MarkLigPos.hh"
|
||||
#include "MarkMarkPos.hh"
|
||||
#include "ContextPos.hh"
|
||||
#include "ChainContextPos.hh"
|
||||
#include "ExtensionPos.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PosLookupSubTable
|
||||
{
|
||||
friend struct ::OT::Lookup;
|
||||
friend struct PosLookup;
|
||||
|
||||
enum Type {
|
||||
Single = 1,
|
||||
Pair = 2,
|
||||
Cursive = 3,
|
||||
MarkBase = 4,
|
||||
MarkLig = 5,
|
||||
MarkMark = 6,
|
||||
Context = 7,
|
||||
ChainContext = 8,
|
||||
Extension = 9
|
||||
};
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
|
||||
{
|
||||
TRACE_DISPATCH (this, lookup_type);
|
||||
switch (lookup_type) {
|
||||
case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c, lookup_type);
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
SinglePos single;
|
||||
PairPos pair;
|
||||
CursivePos cursive;
|
||||
MarkBasePos markBase;
|
||||
MarkLigPos markLig;
|
||||
MarkMarkPos markMark;
|
||||
ContextPos context;
|
||||
ChainContextPos chainContext;
|
||||
ExtensionPos extension;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (0);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HB_OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH */
|
100
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
vendored
Normal file
100
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePos.hh
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOS_HH
|
||||
|
||||
#include "SinglePosFormat1.hh"
|
||||
#include "SinglePosFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
SinglePosFormat1 format1;
|
||||
SinglePosFormat2 format2;
|
||||
} u;
|
||||
|
||||
public:
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned get_format (Iterator glyph_val_iter_pairs)
|
||||
{
|
||||
hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
|
||||
|
||||
for (const auto iter : glyph_val_iter_pairs)
|
||||
for (const auto _ : hb_zip (iter.second, first_val_iter))
|
||||
if (_.first != _.second)
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup* src,
|
||||
Iterator glyph_val_iter_pairs,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
bool all_axes_pinned)
|
||||
{
|
||||
if (unlikely (!c->extend_min (u.format))) return;
|
||||
unsigned format = 2;
|
||||
ValueFormat new_format = src->get_value_format ();
|
||||
|
||||
if (all_axes_pinned)
|
||||
new_format = new_format.drop_device_table_flags ();
|
||||
|
||||
if (glyph_val_iter_pairs)
|
||||
format = get_format (glyph_val_iter_pairs);
|
||||
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
case 1: u.format1.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
case 2: u.format2.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Iterator, typename SrcLookup>
|
||||
static void
|
||||
SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
bool all_axes_pinned)
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOS_HH */
|
165
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
vendored
Normal file
165
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
|
||||
|
||||
#include "Common.hh"
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePosFormat1
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat; /* Defines the types of data in the
|
||||
* ValueRecord */
|
||||
ValueRecord values; /* Defines positioning
|
||||
* value(s)--applied to all glyphs in
|
||||
* the Coverage table */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
/* The coverage table may use a range to represent a set
|
||||
* of glyphs, which means a small number of bytes can
|
||||
* generate a large glyph set. Manually modify the
|
||||
* sanitizer max ops to take this into account.
|
||||
*
|
||||
* Note: This check *must* be right after coverage sanitize. */
|
||||
c->check_ops ((this + coverage).get_population () >> 1) &&
|
||||
valueFormat.sanitize_value (c, this, values));
|
||||
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (*c->glyph_set, intersection);
|
||||
if (!intersection) return;
|
||||
|
||||
valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
ValueFormat get_value_format () const { return valueFormat; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this, values, buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_blob_t *table_blob,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
|
||||
|
||||
valueFormat.apply_value (&c, this, values, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
ValueFormat newFormat,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||
{
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
if (unlikely (!c->check_assign (valueFormat,
|
||||
newFormat,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
|
||||
for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
|
||||
{
|
||||
src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map);
|
||||
// Only serialize the first entry in the iterator, the rest are assumed to
|
||||
// be the same.
|
||||
break;
|
||||
}
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (glyphset, intersection);
|
||||
|
||||
auto it =
|
||||
+ hb_iter (intersection)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
| hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */
|
177
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
vendored
Normal file
177
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
|
||||
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePosFormat2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat; /* Defines the types of data in the
|
||||
* ValueRecord */
|
||||
HBUINT16 valueCount; /* Number of ValueRecords */
|
||||
ValueRecord values; /* Array of ValueRecords--positioning
|
||||
* values applied to glyphs */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
valueFormat.sanitize_values (c, this, values, valueCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
|
||||
|
||||
for (unsigned i : + it
|
||||
| hb_map (hb_second))
|
||||
valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
|
||||
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
ValueFormat get_value_format () const { return valueFormat; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (unlikely (index >= valueCount)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_blob_t *table_blob,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
if (unlikely (index >= valueCount)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
|
||||
|
||||
valueFormat.apply_value (&c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
ValueFormat newFormat,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||
{
|
||||
auto out = c->extend_min (this);
|
||||
if (unlikely (!out)) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
|
||||
|
||||
+ it
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (hb_array_t<const Value> _)
|
||||
{ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); })
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
auto values_array = values.as_array (valueCount * sub_length);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
|
||||
{
|
||||
return hb_pair (glyph_map[_.first],
|
||||
values_array.sub_array (_.second * sub_length,
|
||||
sub_length));
|
||||
})
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */
|
412
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
vendored
Normal file
412
src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
#ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
||||
#define OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
||||
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef HBUINT16 Value;
|
||||
|
||||
typedef UnsizedArrayOf<Value> ValueRecord;
|
||||
|
||||
struct ValueFormat : HBUINT16
|
||||
{
|
||||
enum Flags {
|
||||
xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
|
||||
yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
|
||||
xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
|
||||
yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
|
||||
xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
|
||||
yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
|
||||
xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
|
||||
yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
|
||||
ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
|
||||
reserved = 0xF000u, /* For future use */
|
||||
|
||||
devices = 0x00F0u /* Mask for having any Device table */
|
||||
};
|
||||
|
||||
/* All fields are options. Only those available advance the value pointer. */
|
||||
#if 0
|
||||
HBINT16 xPlacement; /* Horizontal adjustment for
|
||||
* placement--in design units */
|
||||
HBINT16 yPlacement; /* Vertical adjustment for
|
||||
* placement--in design units */
|
||||
HBINT16 xAdvance; /* Horizontal adjustment for
|
||||
* advance--in design units (only used
|
||||
* for horizontal writing) */
|
||||
HBINT16 yAdvance; /* Vertical adjustment for advance--in
|
||||
* design units (only used for vertical
|
||||
* writing) */
|
||||
Offset16To<Device> xPlaDevice; /* Offset to Device table for
|
||||
* horizontal placement--measured from
|
||||
* beginning of PosTable (may be NULL) */
|
||||
Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
|
||||
* placement--measured from beginning
|
||||
* of PosTable (may be NULL) */
|
||||
Offset16To<Device> xAdvDevice; /* Offset to Device table for
|
||||
* horizontal advance--measured from
|
||||
* beginning of PosTable (may be NULL) */
|
||||
Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
|
||||
* advance--measured from beginning of
|
||||
* PosTable (may be NULL) */
|
||||
#endif
|
||||
|
||||
IntType& operator = (uint16_t i) { v = i; return *this; }
|
||||
|
||||
unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
|
||||
unsigned int get_size () const { return get_len () * Value::static_size; }
|
||||
|
||||
hb_vector_t<unsigned> get_device_table_indices () const {
|
||||
unsigned i = 0;
|
||||
hb_vector_t<unsigned> result;
|
||||
unsigned format = *this;
|
||||
|
||||
if (format & xPlacement) i++;
|
||||
if (format & yPlacement) i++;
|
||||
if (format & xAdvance) i++;
|
||||
if (format & yAdvance) i++;
|
||||
|
||||
if (format & xPlaDevice) result.push (i++);
|
||||
if (format & yPlaDevice) result.push (i++);
|
||||
if (format & xAdvDevice) result.push (i++);
|
||||
if (format & yAdvDevice) result.push (i++);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool apply_value (hb_ot_apply_context_t *c,
|
||||
const void *base,
|
||||
const Value *values,
|
||||
hb_glyph_position_t &glyph_pos) const
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int format = *this;
|
||||
if (!format) return ret;
|
||||
|
||||
hb_font_t *font = c->font;
|
||||
bool horizontal =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
HB_DIRECTION_IS_HORIZONTAL (c->direction)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
;
|
||||
|
||||
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
|
||||
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
|
||||
if (format & xAdvance) {
|
||||
if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
|
||||
values++;
|
||||
}
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (format & yAdvance) {
|
||||
if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
|
||||
values++;
|
||||
}
|
||||
|
||||
if (!has_device ()) return ret;
|
||||
|
||||
bool use_x_device = font->x_ppem || font->num_coords;
|
||||
bool use_y_device = font->y_ppem || font->num_coords;
|
||||
|
||||
if (!use_x_device && !use_y_device) return ret;
|
||||
|
||||
const VariationStore &store = c->var_store;
|
||||
auto *cache = c->var_store_cache;
|
||||
|
||||
/* pixel -> fractional pixel */
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & yPlaDevice)
|
||||
{
|
||||
if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & xAdvDevice)
|
||||
{
|
||||
if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & yAdvDevice)
|
||||
{
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int get_effective_format (const Value *values) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
|
||||
if (format & flag) should_drop (*values++, (Flags) flag, &format);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned int get_effective_format (Iterator it) const {
|
||||
unsigned int new_format = 0;
|
||||
|
||||
for (const hb_array_t<const Value>& values : it)
|
||||
new_format = new_format | get_effective_format (&values);
|
||||
|
||||
return new_format;
|
||||
}
|
||||
|
||||
void copy_values (hb_serialize_context_t *c,
|
||||
unsigned int new_format,
|
||||
const void *base,
|
||||
const Value *values,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
if (!format) return;
|
||||
|
||||
HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
|
||||
if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
|
||||
if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++);
|
||||
if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
|
||||
if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
|
||||
|
||||
if (!has_device ())
|
||||
return;
|
||||
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
|
||||
}
|
||||
|
||||
if (format & yPlaDevice)
|
||||
{
|
||||
add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice);
|
||||
}
|
||||
|
||||
if (format & xAdvDevice)
|
||||
{
|
||||
add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice);
|
||||
}
|
||||
|
||||
if (format & yAdvDevice)
|
||||
{
|
||||
add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice);
|
||||
}
|
||||
}
|
||||
|
||||
HBINT16* copy_value (hb_serialize_context_t *c,
|
||||
unsigned int new_format,
|
||||
Flags flag,
|
||||
Value value) const
|
||||
{
|
||||
// Filter by new format.
|
||||
if (!(new_format & flag)) return nullptr;
|
||||
return reinterpret_cast<HBINT16 *> (c->copy (value));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *base,
|
||||
const hb_array_t<const Value>& values) const
|
||||
{
|
||||
unsigned format = *this;
|
||||
unsigned i = 0;
|
||||
if (format & xPlacement) i++;
|
||||
if (format & yPlacement) i++;
|
||||
if (format & xAdvance) i++;
|
||||
if (format & yAdvance) i++;
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::xAdvDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yAdvDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned drop_device_table_flags () const
|
||||
{
|
||||
unsigned format = *this;
|
||||
for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
|
||||
format = format & ~flag;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
|
||||
if (format & xPlacement) values++;
|
||||
if (format & yPlacement) values++;
|
||||
if (format & xAdvance) values++;
|
||||
if (format & yAdvance) values++;
|
||||
|
||||
if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline Offset16To<Device>& get_device (Value* value)
|
||||
{
|
||||
return *static_cast<Offset16To<Device> *> (value);
|
||||
}
|
||||
static inline const Offset16To<Device>& get_device (const Value* value)
|
||||
{
|
||||
return *static_cast<const Offset16To<Device> *> (value);
|
||||
}
|
||||
static inline const Device& get_device (const Value* value,
|
||||
bool *worked,
|
||||
const void *base,
|
||||
hb_sanitize_context_t &c)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
auto &offset = *static_cast<const Offset16To<Device> *> (value);
|
||||
|
||||
if (unlikely (!offset.sanitize (&c, base)))
|
||||
return Null(Device);
|
||||
|
||||
return base + offset;
|
||||
}
|
||||
|
||||
void add_delta_to_value (HBINT16 *value,
|
||||
const void *base,
|
||||
const Value *src_value,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
{
|
||||
if (!value) return;
|
||||
unsigned varidx = (base + get_device (src_value)).get_variation_index ();
|
||||
hb_pair_t<unsigned, int> *varidx_delta;
|
||||
if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return;
|
||||
|
||||
*value += hb_second (*varidx_delta);
|
||||
}
|
||||
|
||||
bool copy_device (hb_serialize_context_t *c, const void *base,
|
||||
const Value *src_value,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned int new_format, Flags flag) const
|
||||
{
|
||||
// Filter by new format.
|
||||
if (!(new_format & flag)) return true;
|
||||
|
||||
Value *dst_value = c->copy (*src_value);
|
||||
|
||||
if (!dst_value) return false;
|
||||
if (*dst_value == 0) return true;
|
||||
|
||||
*dst_value = 0;
|
||||
c->push ();
|
||||
if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map))
|
||||
{
|
||||
c->add_link (*dst_value, c->pop_pack ());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->pop_discard ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
return *reinterpret_cast<const HBINT16 *> (value);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool has_device () const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
return (format & devices) != 0;
|
||||
}
|
||||
|
||||
bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (unlikely (!c->check_range (values, get_size ()))) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
return_trace (!has_device () || sanitize_value_devices (c, base, values));
|
||||
}
|
||||
|
||||
bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
unsigned size = get_size ();
|
||||
|
||||
if (!c->check_range (values, count, size)) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
|
||||
}
|
||||
|
||||
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */
|
||||
bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (!has_device ()) return_trace (true);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
if (!sanitize_value_devices (c, base, values))
|
||||
return_trace (false);
|
||||
values = &StructAtOffset<const Value> (values, stride);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void should_drop (Value value, Flags flag, unsigned int* format) const
|
||||
{
|
||||
if (value) return;
|
||||
*format = *format & ~flag;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
126
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
vendored
Normal file
126
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSet.hh
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESET_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESET_HH
|
||||
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct AlternateSet
|
||||
{
|
||||
protected:
|
||||
Array16Of<typename Types::HBGlyphID>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, alternates);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (alternates.sanitize (c));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return hb_any (alternates, glyphs); }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{ c->output->add_array (alternates.arrayZ, alternates.len); }
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ c->output->add_array (alternates.arrayZ, alternates.len); }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int count = alternates.len;
|
||||
|
||||
if (unlikely (!count)) return_trace (false);
|
||||
|
||||
hb_mask_t glyph_mask = c->buffer->cur().mask;
|
||||
hb_mask_t lookup_mask = c->lookup_mask;
|
||||
|
||||
/* Note: This breaks badly if two features enabled this lookup together. */
|
||||
unsigned int shift = hb_ctz (lookup_mask);
|
||||
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
|
||||
|
||||
/* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
|
||||
if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
|
||||
{
|
||||
/* Maybe we can do better than unsafe-to-break all; but since we are
|
||||
* changing random state, it would be hard to track that. Good 'nough. */
|
||||
c->buffer->unsafe_to_break (0, c->buffer->len);
|
||||
alt_index = c->random_number () % count + 1;
|
||||
}
|
||||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (alternate substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (alternates[alt_index - 1]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (alternate substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned
|
||||
get_alternates (unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{
|
||||
if (alternates.len && alternate_count)
|
||||
{
|
||||
+ alternates.as_array ().sub_array (start_offset, alternate_count)
|
||||
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
|
||||
;
|
||||
}
|
||||
return alternates.len;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator alts)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (alternates.serialize (c, alts));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (alternates)
|
||||
| hb_filter (glyphset)
|
||||
| hb_map (glyph_map)
|
||||
;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
return_trace (out->serialize (c->serializer, it) &&
|
||||
out->alternates);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESET_HH */
|
62
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
vendored
Normal file
62
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubst.hh
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESUBST_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESUBST_HH
|
||||
|
||||
#include "AlternateSubstFormat1.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct AlternateSubst
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
|
||||
* iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format))) return_trace (false);
|
||||
unsigned int format = 1;
|
||||
u.format = format;
|
||||
switch (u.format) {
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO subset() should choose format. */
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESUBST_HH */
|
128
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
vendored
Normal file
128
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
|
||||
|
||||
#include "AlternateSet.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct AlternateSubstFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
|
||||
alternateSet; /* Array of AlternateSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
|
||||
;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||
|
||||
unsigned
|
||||
get_glyph_alternates (hb_codepoint_t gid,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{ return (this+alternateSet[(this+coverage).get_coverage (gid)])
|
||||
.get_alternates (start_offset, alternate_count, alternate_glyphs); }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
return_trace ((this+alternateSet[index]).apply (c));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
unsigned int alternate_len = alternate_len_list[i];
|
||||
if (unlikely (!alternateSet[i]
|
||||
.serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
|
||||
return_trace (false);
|
||||
alternate_glyphs_list += alternate_len;
|
||||
}
|
||||
return_trace (coverage.serialize_serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH */
|
18
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
vendored
Normal file
18
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ChainContextSubst.hh
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
|
||||
#define OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
|
||||
|
||||
// TODO(garretrieger): move to new layout.
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct ChainContextSubst : ChainContext {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH */
|
19
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
vendored
Normal file
19
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef OT_LAYOUT_GSUB_COMMON_HH
|
||||
#define OT_LAYOUT_GSUB_COMMON_HH
|
||||
|
||||
#include "../../../hb-serialize.hh"
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template<typename Iterator>
|
||||
static void SingleSubst_serialize (hb_serialize_context_t *c,
|
||||
Iterator it);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_COMMON_HH */
|
18
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
vendored
Normal file
18
src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ContextSubst.hh
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef OT_LAYOUT_GSUB_CONTEXTSUBST_HH
|
||||
#define OT_LAYOUT_GSUB_CONTEXTSUBST_HH
|
||||
|
||||
// TODO(garretrieger): move to new layout.
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct ContextSubst : Context {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_CONTEXTSUBST_HH */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user