Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Allow specifying multiple fonts or font families for local font rendering #16253

Merged
merged 11 commits into from
Apr 24, 2020

Conversation

1ec5
Copy link
Contributor

@1ec5 1ec5 commented Mar 1, 2020

By default, on iOS and macOS, CJK characters are now set in the font specified by the text-font layout property. If the named font is not installed on the device or bundled with the application, the characters are set in one of the fallback fonts passed into the localFontFamily parameter of mbgl::Renderer::Renderer() and mbgl::MapSnapshotter::MapSnapshotter(). This parameter can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline. These names form a cascade list that Core Text can use as fallbacks.

CJK characters are now laid out according to the font, so fonts with nonsquare glyphs have the correct kerning. This also fixes an issue where the baseline for CJK characters was too low compared to non-CJK characters.

Here’s a map where Noto Sans CJK JP Black is specified as the local font:

master This PR
before black

This PR has been developed in tandem with mapbox/mapbox-gl-native-ios#189.

The big to do list:

  • Plumb through font name list
  • Create a font descriptor from a font family, display name, and PostScript name simultaneously
  • Update big to-do list at the top of local_glyph_rasterizer.mm
  • Investigate macOS test failure
  • Investigate iOS test failure
  • Plumb through a vector of strings instead of a line-delimited string
  • Create font descriptors from the font stack and derive the application-specified font descriptors from the font stack–derived font descriptors
  • Investigate glyph metrics improvements

/cc @mapbox/gl-native @mapbox/maps-ios

@1ec5 1ec5 added iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS ⚠️ DO NOT MERGE Work in progress, proof of concept, or on hold text rendering labels Mar 1, 2020
@1ec5 1ec5 self-assigned this Mar 1, 2020
@1ec5
Copy link
Contributor Author

1ec5 commented Mar 1, 2020

A relevant test is crashing on macOS on CI:

2: [----------] 4 tests from LocalGlyphRasterizer
2: [ RUN      ] LocalGlyphRasterizer.PingFang
2/3 Test #2: mbgl-test-runner .................***Exception: SegFault 83.35 sec
test 3

Locally, it doesn’t crash, but I do get a failure:

/path/to/mapbox-gl-native-ios/vendor/mapbox-gl-native/test/src/mbgl/test/util.cpp:49: Failure
Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.015213 vs 0.015
[  FAILED  ] LocalGlyphRasterizer.PingFang (803 ms)

(To build mbgl-test-runner as part of macOS.xcworkspace in mapbox-gl-native-ios, I had to modify that target’s OTHER_LDFLAGS build setting to remove test/ from the paths of libmbgl-test.a and libmbgl-vendor-googletest.a.)

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 1, 2020

LocalGlyphRasterizer.PingFang is somewhat misleading on macOS: the test sets the local font family to “PingFang”, but macOS systems come with no font family or font by that name. Instead, there are separate “PingFang HK”, “PingFang SC”, and “PingFang TC” font families.

LocalGlyphRasterizerTest test(std::string("PingFang"));

CTFontDescriptorCreateWithAttributes() returns Helvetica with the default font cascade list, which for most locales would have PingFangTC-Regular as the first CJK font. Because of the MGLRendererConfiguration validation code that this PR removes, it wasn’t possible for a developer to pass “PingFang” into LocalGlyphRasterizer anyways.

/ref #10712 #10522 (comment) #10675 (comment)

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 1, 2020

At least on my machine, the failure appears to be related to the specific weight that Core Text has chosen:

Expected Diff Actual
expected diff actual

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 1, 2020

I’m guessing the new choice of PingFangTC-Regular is correct, based on the expected Qt rendering. The old code seems to have chosen PingFangTC-Thin by default. The Regular weight more closely matches the weight of the Latin text too.

Expected (macOS) Actual (macOS) Expected (Qt)
expected actual-macos expected-qt

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 2, 2020

(To build mbgl-test-runner as part of macOS.xcworkspace in mapbox-gl-native-ios, I had to modify that target’s OTHER_LDFLAGS build setting to remove test/ from the paths of libmbgl-test.a and libmbgl-vendor-googletest.a.)

#16259

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 2, 2020

Here’s the crash trace from the CI-only crash in #16253 (comment):

TFontCascade::CreateFallback(__CTFont const*, __CFString const*, CTEmojiPolicy) const + 1194
Process:               mbgl-test-runner [6161]
Path:                  /Users/USER/*/mbgl-test-runner
Identifier:            mbgl-test-runner
Version:               0
Code Type:             X86-64 (Native)
Parent Process:        bash [6012]
Responsible:           mbgl-test-runner [6161]
User ID:               501

Date/Time:             2020-03-02 14:59:27.622 -0800
OS Version:            Mac OS X 10.14.4 (18E226)
Report Version:        12
Anonymous UUID:        5C810297-F9C2-6887-2447-9DD30FE08FE0


Time Awake Since Boot: 4000 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [6161]

VM Regions Near 0:
--> 
    __TEXT                 000000010f7ab000-000000011019e000 [  9.9M] r-x/r-x SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.CoreText            	0x00007fff44b45d82 TFontCascade::CreateFallback(__CTFont const*, __CFString const*, CTEmojiPolicy) const + 1194
1   com.apple.CoreText            	0x00007fff44b44f7a TGlyphEncoder::AppendUnmappedCharRun(unsigned int, TCFRef<CTRun*>&, __CTFont const*, CFRange&, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const&, TGlyphEncoder::ClusterMatching, bool) + 460
2   com.apple.CoreText            	0x00007fff44b3b418 TGlyphEncoder::RunUnicodeEncoderRecursively(unsigned int, TCFRef<CTRun*>&&, __CTFont const*, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const*, TGlyphEncoder::ClusterMatching, bool) + 1306
3   com.apple.CoreText            	0x00007fff44b3ae84 TGlyphEncoder::RunUnicodeEncoder(TCFRef<CTRun*>&&, __CTFont const*, CFRange, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const*) + 116
4   com.apple.CoreText            	0x00007fff44b3723a TGlyphEncoder::EncodeChars(CFRange, TAttributes const&, TGlyphEncoder::Fallbacks) + 1676
5   com.apple.CoreText            	0x00007fff44b366e2 TTypesetterAttrString::Initialize(__CFAttributedString const*) + 236
6   com.apple.CoreText            	0x00007fff44b36435 TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*, __CFDictionary const*) + 163
7   com.apple.CoreText            	0x00007fff44b36286 CTLineCreateWithAttributedString + 60
8   mbgl-test-runner              	0x000000010ff99980 mbgl::drawGlyphBitmap(char16_t, __CTFont const*, mbgl::Size) + 304
9   mbgl-test-runner              	0x000000010ff99bf6 mbgl::LocalGlyphRasterizer::rasterizeGlyph(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char16_t) + 134
10  mbgl-test-runner              	0x000000010fec5b26 mbgl::GlyphManager::getGlyphs(mbgl::GlyphRequestor&, std::__1::map<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> >, std::__1::less<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::allocator<std::__1::pair<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> > > > >, mbgl::FileSource&) + 438
11  mbgl-test-runner              	0x000000010ff02c68 mbgl::GeometryTile::getGlyphs(std::__1::map<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> >, std::__1::less<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::allocator<std::__1::pair<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> > > > >) + 120
12  mbgl-test-runner              	0x000000010ff36aef mbgl::MessageImpl<mbgl::GeometryTile, void (mbgl::GeometryTile::*)(std::__1::map<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> >, std::__1::less<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::allocator<std::__1::pair<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> > > > >), std::__1::tuple<std::__1::map<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> >, std::__1::less<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >, std::__1::allocator<std::__1::pair<std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const, std::__1::set<char16_t, std::__1::less<char16_t>, std::__1::allocator<char16_t> > > > > > >::operator()() + 111
13  mbgl-test-runner              	0x000000010fc2e044 mbgl::Mailbox::receive() + 356
14  mbgl-test-runner              	0x000000010fc2f069 std::__1::__function::__func<mbgl::Mailbox::makeClosure(std::__1::weak_ptr<mbgl::Mailbox>)::$_0, std::__1::allocator<mbgl::Mailbox::makeClosure(std::__1::weak_ptr<mbgl::Mailbox>)::$_0>, void ()>::operator()() + 57
15  mbgl-test-runner              	0x000000010f9b22a2 mbgl::WorkTaskImpl<std::__1::function<void ()>, std::__1::tuple<> >::operator()() + 50
16  mbgl-test-runner              	0x000000010ff9b102 mbgl::util::RunLoop::process() + 450
17  com.apple.CoreFoundation      	0x00007fff42f0031b __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
18  com.apple.CoreFoundation      	0x00007fff42f002c1 __CFRunLoopDoSource0 + 108
19  com.apple.CoreFoundation      	0x00007fff42ee41bb __CFRunLoopDoSources0 + 195
20  com.apple.CoreFoundation      	0x00007fff42ee3783 __CFRunLoopRun + 1196
21  com.apple.CoreFoundation      	0x00007fff42ee3085 CFRunLoopRunSpecific + 459
22  mbgl-test-runner              	0x000000010ff9cb7b mbgl::HeadlessFrontend::render(mbgl::Map&) + 187
23  mbgl-test-runner              	0x000000010fae0877 (anonymous namespace)::LocalGlyphRasterizerTest::checkRendering(char const*, double, double) + 183
24  mbgl-test-runner              	0x000000010fae03fa LocalGlyphRasterizer_PingFang_Test::TestBody() + 458
25  mbgl-test-runner              	0x00000001100064f8 void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) + 72
26  mbgl-test-runner              	0x000000011000644d testing::Test::Run() + 253
27  mbgl-test-runner              	0x0000000110007680 testing::TestInfo::Run() + 272
28  mbgl-test-runner              	0x0000000110008147 testing::TestCase::Run() + 263
29  mbgl-test-runner              	0x0000000110011037 testing::internal::UnitTestImpl::RunAllTests() + 1191
30  mbgl-test-runner              	0x00000001100109e8 bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) + 72
31  mbgl-test-runner              	0x000000011001095c testing::UnitTest::Run() + 172
32  mbgl-test-runner              	0x000000010f8d184e mbgl::runTests(int, char**) + 62
33  libdyld.dylib                 	0x00007fff6f4143d5 start + 1

Thread 1:
0   libsystem_kernel.dylib        	0x00007fff6f55061a __select + 10
1   mbgl-test-runner              	0x000000010fc136f4 httplib::Server::listen_internal() + 212
2   mbgl-test-runner              	0x000000010fc08490 mbgl::test::runServer(std::__1::unique_ptr<httplib::Server, std::__1::default_delete<httplib::Server> >&) + 1680
3   mbgl-test-runner              	0x000000010fc2cefc void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(std::__1::unique_ptr<httplib::Server, std::__1::default_delete<httplib::Server> >&), std::__1::reference_wrapper<std::__1::unique_ptr<httplib::Server, std::__1::default_delete<httplib::Server> > > > >(void*) + 44
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 2:
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010fc2cb21 httplib::ThreadPool::worker::operator()() + 145
4   mbgl-test-runner              	0x000000010fc2ca1d void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, httplib::ThreadPool::worker> >(void*) + 45
5   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 3:
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010fc2cb21 httplib::ThreadPool::worker::operator()() + 145
4   mbgl-test-runner              	0x000000010fc2ca1d void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, httplib::ThreadPool::worker> >(void*) + 45
5   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 4:
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010fc2cb21 httplib::ThreadPool::worker::operator()() + 145
4   mbgl-test-runner              	0x000000010fc2ca1d void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, httplib::ThreadPool::worker> >(void*) + 45
5   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 5:
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010fc2cb21 httplib::ThreadPool::worker::operator()() + 145
4   mbgl-test-runner              	0x000000010fc2ca1d void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, httplib::ThreadPool::worker> >(void*) + 45
5   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
6   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
7   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 6:
0   libsystem_pthread.dylib       	0x00007fff6f6013f0 start_wqthread + 0

Thread 7:
0   libsystem_pthread.dylib       	0x00007fff6f6013f0 start_wqthread + 0

Thread 8:: com.mapbox.mbgl.Worker 1
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010ff59c9b void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, mbgl::ThreadedSchedulerBase::makeSchedulerThread(unsigned long)::$_0> >(void*) + 555
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 9:: com.mapbox.mbgl.Worker 2
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010ff59c9b void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, mbgl::ThreadedSchedulerBase::makeSchedulerThread(unsigned long)::$_0> >(void*) + 555
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 10:: com.mapbox.mbgl.Worker 3
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010ff59c9b void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, mbgl::ThreadedSchedulerBase::makeSchedulerThread(unsigned long)::$_0> >(void*) + 555
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 11:: com.mapbox.mbgl.Worker 4
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010ff59c9b void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, mbgl::ThreadedSchedulerBase::makeSchedulerThread(unsigned long)::$_0> >(void*) + 555
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 12:: com.mapbox.mbgl.Worker 1
0   libsystem_kernel.dylib        	0x00007fff6f54c86a __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff6f60556e _pthread_cond_wait + 722
2   libc++.1.dylib                	0x00007fff6c42ca0a std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
3   mbgl-test-runner              	0x000000010ff59c9b void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, mbgl::ThreadedSchedulerBase::makeSchedulerThread(unsigned long)::$_0> >(void*) + 555
4   libsystem_pthread.dylib       	0x00007fff6f6022eb _pthread_body + 126
5   libsystem_pthread.dylib       	0x00007fff6f605249 _pthread_start + 66
6   libsystem_pthread.dylib       	0x00007fff6f60140d thread_start + 13

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x00007f86ffe0ad90  rcx: 0x0000000100001280  rdx: 0x00007fff6dc055f8
  rdi: 0x0000000000000000  rsi: 0x0000000000000307  rbp: 0x00007ffee044fbb0  rsp: 0x00007ffee044faf0
   r8: 0x0000000000000004   r9: 0x00007f86ffd83750  r10: 0x00007f86ffd00000  r11: 0x0000000000000009
  r12: 0x00007ffee044fc28  r13: 0x0000000000000001  r14: 0x00007f86ffe0ad60  r15: 0x0000000000000001
  rip: 0x00007fff44b45d82  rfl: 0x0000000000010206  cr2: 0x0000000000000000
  
Logical CPU:     0
Error Code:      0x00000004
Trap Number:     14


Binary Images:
       0x10f7ab000 -        0x11019dfff +mbgl-test-runner (0) <FDEBDB8E-524A-3667-8CF9-ADB87E138D08> /Users/USER/*/mbgl-test-runner
       0x11dc9b000 -        0x11dd056ef  dyld (655.1.1) <F217F7F8-A795-3109-B77F-B1E2277F3E3B> /usr/lib/dyld
    0x7fff3f12b000 -     0x7fff3f12bfff  com.apple.Accelerate (1.11 - Accelerate 1.11) <B2A0C739-1D41-3452-9D00-8C01ADA5DD99> /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
    0x7fff3f143000 -     0x7fff3fa37fcb  com.apple.vImage (8.1 - ???) <1CD3BAF5-C53F-3931-B28E-B28FD2C5AFFF> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
    0x7fff3fa38000 -     0x7fff3fbdefeb  libBLAS.dylib (1243.200.4) <EDCBFA9D-93E3-39AD-913F-25D269394249> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
    0x7fff3fbdf000 -     0x7fff3fc23ff7  libBNNS.dylib (38.250.1) <9E7966E8-B82A-396E-8F9A-7EF242DF8CC4> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib
    0x7fff3fc24000 -     0x7fff3ffdcff3  libLAPACK.dylib (1243.200.4) <2CD8E9C6-E489-38E1-8A08-42CBE87FAC77> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
    0x7fff3ffdd000 -     0x7fff3fff2ffb  libLinearAlgebra.dylib (1243.200.4) <7B1B0EB3-179A-3FA5-992E-F5D006219874> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib
    0x7fff3fff3000 -     0x7fff3fff8ff3  libQuadrature.dylib (3.200.2) <354D7970-0570-32E0-ABAE-222DAAF1F7A9> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib
    0x7fff3fff9000 -     0x7fff40075ff3  libSparse.dylib (79.200.5) <DCC01AE4-FC16-3C7B-9010-999411448164> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib
    0x7fff40076000 -     0x7fff40088ffb  libSparseBLAS.dylib (1243.200.4) <D20610A4-C7F3-3ABD-AADF-F6BA8E993A55> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib
    0x7fff40089000 -     0x7fff40229fef  libvDSP.dylib (671.250.4) <CA46FD92-D0CB-39B5-BD26-BEB3897D3154> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
    0x7fff4022a000 -     0x7fff4039efdf  libvMisc.dylib (671.250.4) <AC290632-C0DA-3FB4-992C-DC44B905D78B> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
    0x7fff4039f000 -     0x7fff4039ffff  com.apple.Accelerate.vecLib (3.11 - vecLib 3.11) <A83C1419-E651-3924-8A6D-FF7321C8AB90> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
    0x7fff40541000 -     0x7fff412f6fff  com.apple.AppKit (6.9 - 1671.40.119) <0A857684-99C7-30A9-8E23-D3015C6B24A3> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
    0x7fff41348000 -     0x7fff41348fff  com.apple.ApplicationServices (50.1 - 50.1) <E57E6BAC-3CA7-3EFB-9A6B-ACF662E07FAC> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
    0x7fff41349000 -     0x7fff413b4fff  com.apple.ApplicationServices.ATS (377 - 453.11.2.2) <5B30E86D-B3AB-3346-A19F-F2CABF342465> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
    0x7fff4144d000 -     0x7fff41564fff  libFontParser.dylib (228.6.2.3) <BBB2EECE-7C24-3D43-A902-EB473A70EDED> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib
    0x7fff41565000 -     0x7fff415a7fff  libFontRegistry.dylib (228.12.2.3) <DEA7AE34-2FA6-336E-BF00-00CA2BDC7584> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib
    0x7fff41698000 -     0x7fff4169cff3  com.apple.ColorSyncLegacy (4.13.0 - 1) <6EDD928D-BC75-385E-AB04-3CB63EAEBF96> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy
    0x7fff41737000 -     0x7fff41789ff7  com.apple.HIServices (1.22 - 627.15) <1B4C3D08-1DBA-365B-9362-C6708D8844AA> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
    0x7fff4178a000 -     0x7fff41799fff  com.apple.LangAnalysis (1.7.0 - 1.7.0) <76B698A9-18B9-3089-9570-4FC3F754D56D> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
    0x7fff4179a000 -     0x7fff417e3ff7  com.apple.print.framework.PrintCore (14.2 - 503.8) <885645E0-D760-35EC-B506-7FC2763390DF> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
    0x7fff417e4000 -     0x7fff4181dff7  com.apple.QD (3.12 - 407.2) <A414332F-72EC-393B-B2BC-7285268A19BD> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
    0x7fff4181e000 -     0x7fff4182afff  com.apple.speech.synthesis.framework (8.1.2 - 8.1.2) <1F910DC7-410A-391B-A03D-17605E50B688> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
    0x7fff4182b000 -     0x7fff41aa2ff7  com.apple.audio.toolbox.AudioToolbox (1.14 - 1.14) <1C76AD80-1106-312E-B2C0-126A8D62F192> /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
    0x7fff41aa4000 -     0x7fff41aa4fff  com.apple.audio.units.AudioUnit (1.14 - 1.14) <6AFA15D5-1886-3EBF-ADC9-90421375DB30> /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit
    0x7fff41dfc000 -     0x7fff4219dfff  com.apple.CFNetwork (978.0.7 - 978.0.7) <EFB91439-6953-3CD4-8A14-3E7DC90DDF7E> /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
    0x7fff421b7000 -     0x7fff424adfff  com.apple.HIToolbox (2.1.1 - 918.4) <CBD6613A-C5A5-3CF3-866A-B8A8C6FD64B5> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
    0x7fff424b8000 -     0x7fff4254dff3  com.apple.ink.framework (10.9 - 225) <091165EE-D540-3978-9B0C-2FAB5CB185A8> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
    0x7fff4258b000 -     0x7fff42591ff7  com.apple.speech.recognition.framework (6.0.3 - 6.0.3) <E38A62C5-31EE-3BE7-83E5-CF126ECF4F51> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
    0x7fff426c1000 -     0x7fff4278dff7  com.apple.ColorSync (4.13.0 - 3340.7) <3ABFA780-F46A-3F0A-8504-005ADDA0662E> /System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync
    0x7fff42919000 -     0x7fff4299ffff  com.apple.audio.CoreAudio (4.3.0 - 4.3.0) <7D8A5C9A-3F58-38C2-A1DC-20765150C742> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
    0x7fff42a03000 -     0x7fff42a2dffb  com.apple.CoreBluetooth (1.0 - 1) <D0C72748-F75A-3C27-9620-C7973C4D365D> /System/Library/Frameworks/CoreBluetooth.framework/Versions/A/CoreBluetooth
    0x7fff42a2e000 -     0x7fff42dc0ff7  com.apple.CoreData (120 - 866.5) <3B9084AB-04EA-3294-9A9D-99929795C5CB> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
    0x7fff42dc1000 -     0x7fff42ea8ff7  com.apple.CoreDisplay (101.3 - 108.11) <373AC375-0178-3721-8FFB-248D96E6AB05> /System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay
    0x7fff42ea9000 -     0x7fff432edff7  com.apple.CoreFoundation (6.9 - 1570.16) <CB6EB0AE-6E30-3DB1-8EA4-1F5CBAF90161> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
    0x7fff432ef000 -     0x7fff4399bff7  com.apple.CoreGraphics (2.0 - 1251.12) <BB033674-310A-39FF-85D3-4FE17875CE65> /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
    0x7fff4399d000 -     0x7fff43cbdfff  com.apple.CoreImage (14.2.0 - 720.0.130) <D09743D4-3B21-367D-8C4A-3DB0F1C1E36D> /System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage
    0x7fff43cbe000 -     0x7fff43d36fff  com.apple.corelocation (2245.12.30) <6C27F2BF-3050-36EC-A628-152A313E5312> /System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation
    0x7fff44118000 -     0x7fff44118fff  com.apple.CoreServices (944.3 - 944.3) <364A9C3B-6841-3E34-A02A-8227FB5C9030> /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
    0x7fff44119000 -     0x7fff44195ff7  com.apple.AE (773 - 773) <3E32B3FF-0A2E-39F6-BBE0-F2E9607AB83A> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
    0x7fff44196000 -     0x7fff4446dfff  com.apple.CoreServices.CarbonCore (1178.32 - 1178.32) <B5B61DE0-93F8-3A9F-8AA6-ACAAD04B3547> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
    0x7fff4446e000 -     0x7fff444b6ff7  com.apple.DictionaryServices (1.2 - 284.16.3) <3EE59BD1-FCDD-3DE2-A7D6-6C503564E1AC> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
    0x7fff444b7000 -     0x7fff444bfffb  com.apple.CoreServices.FSEvents (1239.200.12 - 1239.200.12) <727151AB-D38F-39B8-B7B3-F0039DBD45D0> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents
    0x7fff444c0000 -     0x7fff44672fff  com.apple.LaunchServices (944.3 - 944.3) <7BB5AEC5-A509-3188-9884-619E0DF8EED6> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
    0x7fff44673000 -     0x7fff44711ff7  com.apple.Metadata (10.7.0 - 1191.56) <8DD9AC75-7D3E-3607-BEA0-556E98C30765> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
    0x7fff44712000 -     0x7fff4475cff7  com.apple.CoreServices.OSServices (944.3 - 944.3) <B631283D-9B71-3BF0-B0E7-65F8D444179F> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
    0x7fff4475d000 -     0x7fff447c4ff7  com.apple.SearchKit (1.4.0 - 1.4.0) <FB1A5F99-FB2F-3533-9658-EB0C82BA2705> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
    0x7fff447c5000 -     0x7fff447e6ff3  com.apple.coreservices.SharedFileList (71.28 - 71.28) <B8B5D959-4236-369D-847D-E696A8293420> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList
    0x7fff44af1000 -     0x7fff44c53ff3  com.apple.CoreText (352.0 - 584.26.2.7) <C7E919A8-5840-39C9-A9E7-0E686F486109> /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
    0x7fff44c54000 -     0x7fff44c91ff3  com.apple.CoreVideo (1.8 - 0.0) <0376A7EC-8C71-3F26-9599-4CA7AB7924EA> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
    0x7fff44c92000 -     0x7fff44d20ffb  com.apple.framework.CoreWLAN (13.0 - 1370.8) <68770CCD-9C7F-31AB-8BBB-0DE4577D5F61> /System/Library/Frameworks/CoreWLAN.framework/Versions/A/CoreWLAN
    0x7fff44f77000 -     0x7fff44f7cffb  com.apple.DiskArbitration (2.7 - 2.7) <F30DF62A-0BE9-371D-8D86-96554FF45811> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
    0x7fff4513b000 -     0x7fff454e8ff3  com.apple.Foundation (6.9 - 1570.16) <84055403-9921-3EFC-B593-8F0600EBEE80> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
    0x7fff45557000 -     0x7fff45586ffb  com.apple.GSS (4.0 - 2.0) <F5E9FADD-D2DF-3A27-A08B-C74C9F7DB98D> /System/Library/Frameworks/GSS.framework/Versions/A/GSS
    0x7fff45686000 -     0x7fff4578eff7  com.apple.Bluetooth (6.0.11 - 6.0.11f4) <D695F37C-27CE-3231-8136-49124F367418> /System/Library/Frameworks/IOBluetooth.framework/Versions/A/IOBluetooth
    0x7fff457f0000 -     0x7fff4587ffff  com.apple.framework.IOKit (2.0.2 - 1483.250.15) <1170EC49-1912-3657-9C71-991653959191> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
    0x7fff45881000 -     0x7fff45890ff3  com.apple.IOSurface (255.4.2 - 255.4.2) <9025E034-7D75-36E3-B71B-96E91FAE109B> /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
    0x7fff458e4000 -     0x7fff45a72fff  com.apple.ImageIO.framework (3.3.0 - 1824.6) <DF69B73A-BD00-3A57-994C-844F2F3567F6> /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
    0x7fff45a73000 -     0x7fff45a77ffb  libGIF.dylib (1824.6) <5EE06C74-D45E-3DBB-B64E-0C1FD1720827> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
    0x7fff45a78000 -     0x7fff45b55ff7  libJP2.dylib (1824.6) <6B1466B6-F25B-3EEE-A39F-3FEDFFC7785B> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
    0x7fff45b56000 -     0x7fff45b7bfff  libJPEG.dylib (1824.6) <3E7E462F-6008-395A-B542-023F16C0D7F6> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
    0x7fff45e3f000 -     0x7fff45e65ff7  libPng.dylib (1824.6) <933948D2-7611-3BD6-A0B3-A5B3025E1183> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
    0x7fff45e66000 -     0x7fff45e68ffb  libRadiance.dylib (1824.6) <C9D2B3A0-992B-3601-A817-9621592B74A2> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib
    0x7fff45e69000 -     0x7fff45eb6ffb  libTIFF.dylib (1824.6) <8C656C6F-F277-3032-9E9B-E80F0F8D7342> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
    0x7fff4702c000 -     0x7fff47045fff  com.apple.Kerberos (3.0 - 1) <39F3F99E-036E-3406-80D9-8A845D820D4D> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
    0x7fff47a59000 -     0x7fff47ae8ff7  com.apple.Metal (161.7.1 - 161.7.1) <18BEB663-0D31-3255-9710-50BC5C3D2A0F> /System/Library/Frameworks/Metal.framework/Versions/A/Metal
    0x7fff47b04000 -     0x7fff47b23ff7  com.apple.MetalPerformanceShaders.MPSCore (1.0 - 1) <BE0FF8B9-2DBA-3276-A293-C8B0F62BFFC4> /System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSCore.framework/Versions/A/MPSCore
    0x7fff47b24000 -     0x7fff47ba0fe7  com.apple.MetalPerformanceShaders.MPSImage (1.0 - 1) <7E94924C-1648-3AE2-A32E-FC0AFCA433C6> /System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSImage.framework/Versions/A/MPSImage
    0x7fff47ba1000 -     0x7fff47bc8fff  com.apple.MetalPerformanceShaders.MPSMatrix (1.0 - 1) <E878F04A-43F8-3AA4-B9D8-0401F5F98653> /System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix
    0x7fff47bc9000 -     0x7fff47cf4ff7  com.apple.MetalPerformanceShaders.MPSNeuralNetwork (1.0 - 1) <4866922C-9732-3FCE-9419-402E5DD22639> /System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork
    0x7fff47cf5000 -     0x7fff47d0ffff  com.apple.MetalPerformanceShaders.MPSRayIntersector (1.0 - 1) <80CB3AF2-4401-3B3C-8941-7DEB648DD001> /System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector
    0x7fff47d10000 -     0x7fff47d11ff7  com.apple.MetalPerformanceShaders.MetalPerformanceShaders (1.0 - 1) <A589BBEA-93C6-325C-A695-6E7371B8477C> /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders
    0x7fff48b08000 -     0x7fff48b14ff7  com.apple.NetFS (6.0 - 4.0) <7278E8E5-1583-3964-91DA-FB2127DFD63A> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS
    0x7fff4b5a9000 -     0x7fff4b5b1fe3  libcldcpuengine.dylib (2.11) <49B139D2-D0D6-3333-9603-DF158D61544C> /System/Library/Frameworks/OpenCL.framework/Versions/A/Libraries/libcldcpuengine.dylib
    0x7fff4b5b2000 -     0x7fff4b609ff7  com.apple.opencl (2.15.3 - 2.15.3) <F558A6A7-3B33-320E-83C0-CF16220A150F> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL
    0x7fff4b60a000 -     0x7fff4b625ff7  com.apple.CFOpenDirectory (10.14 - 207.200.4) <386A02AB-0BFA-3847-A56A-2E0EEC5E5D33> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
    0x7fff4b626000 -     0x7fff4b631ffb  com.apple.OpenDirectory (10.14 - 207.200.4) <0BD19D17-7F00-3D56-8734-2EE52992B118> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
    0x7fff4bf81000 -     0x7fff4bf83fff  libCVMSPluginSupport.dylib (17.5.4) <36EB7FAE-4E66-36BF-9B39-623B19486B3B> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib
    0x7fff4bf84000 -     0x7fff4bf89ff3  libCoreFSCache.dylib (166.2) <1AD45004-2625-3351-8087-77878B95348F> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib
    0x7fff4bf8a000 -     0x7fff4bf8efff  libCoreVMClient.dylib (166.2) <E7FBDAEF-BC56-3662-8D59-71FF88D95F8C> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib
    0x7fff4bf8f000 -     0x7fff4bf97ff7  libGFXShared.dylib (17.5.4) <E3B4FD28-FF4B-3174-AEB3-9EA12EF88100> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib
    0x7fff4bf98000 -     0x7fff4bfa3fff  libGL.dylib (17.5.4) <F6D39828-B5D0-3F8D-8DE0-3683A17042E2> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
    0x7fff4bfa4000 -     0x7fff4bfdefe7  libGLImage.dylib (17.5.4) <7EE3273C-41C2-387F-A4B7-793EFAA67769> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
    0x7fff4bfdf000 -     0x7fff4c151ff7  libGLProgrammability.dylib (17.5.4) <A7E6B75B-8FF8-3389-AD69-38DB11B7C3F4> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLProgrammability.dylib
    0x7fff4c152000 -     0x7fff4c190fff  libGLU.dylib (17.5.4) <B56C2FEC-CB14-3B61-ADEB-FD4A92931F16> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
    0x7fff4cb2d000 -     0x7fff4cb3cffb  com.apple.opengl (17.5.4 - 17.5.4) <34FA5E8C-0FAF-3708-836B-E8ACB67EF4F4> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
    0x7fff4cb3d000 -     0x7fff4ccd2ff7  GLEngine (17.5.4) <F008AD68-59DF-337B-BE0D-4117BFFCC3E8> /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine
    0x7fff4ccd3000 -     0x7fff4ccfcff3  GLRendererFloat (17.5.4) <6E85E322-0E3D-3687-BE1D-B8D74971D5B9> /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLRendererFloat.bundle/GLRendererFloat
    0x7fff4d93d000 -     0x7fff4db92fff  com.apple.QuartzCore (1.11 - 697.24.4.2) <BB1034F0-B791-3AF1-B166-6532B2AB54FE> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
    0x7fff4e3c6000 -     0x7fff4e6c4ff7  com.apple.security (7.0 - 58286.251.4) <2084C515-AD64-3A48-BE3E-811CAA5A0E41> /System/Library/Frameworks/Security.framework/Versions/A/Security
    0x7fff4e6c5000 -     0x7fff4e751fff  com.apple.securityfoundation (6.0 - 55185.251.1) <4A36D3BA-02B5-3C52-8B49-08EC290E1924> /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
    0x7fff4e783000 -     0x7fff4e787ff3  com.apple.xpc.ServiceManagement (1.0 - 1) <139D85D7-C356-36FA-B8F4-696FD37FD1EA> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
    0x7fff4eb1f000 -     0x7fff4eb8cfff  com.apple.SystemConfiguration (1.17 - 1.17) <90F4626B-F9F6-377C-AA62-B8C23E857244> /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
    0x7fff51fa1000 -     0x7fff52046fe7  com.apple.APFS (1.0 - 1) <BA5A03A1-09AF-3859-AA38-BD24C4225E23> /System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS
    0x7fff52a46000 -     0x7fff52a47ff7  com.apple.AggregateDictionary (1.0 - 1) <49B5FD7F-A50C-3D67-BFAB-1C25E60F685A> /System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary
    0x7fff53041000 -     0x7fff5306dff7  com.apple.framework.Apple80211 (13.0 - 1376.3) <9D32EF36-80E0-35DA-9270-2865C91F1020> /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Apple80211
    0x7fff53345000 -     0x7fff53354fc7  com.apple.AppleFSCompression (96.200.3 - 1.0) <5D6A617C-999A-3D51-8350-109D55E9428A> /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression
    0x7fff5344e000 -     0x7fff53459fff  com.apple.AppleIDAuthSupport (1.0 - 1) <91975ABC-B2EB-3630-A81E-69A1B95E4D19> /System/Library/PrivateFrameworks/AppleIDAuthSupport.framework/Versions/A/AppleIDAuthSupport
    0x7fff5349a000 -     0x7fff534e3ff3  com.apple.AppleJPEG (1.0 - 1) <EED8C42F-AF5B-355F-BC86-66A6458513C7> /System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG
    0x7fff53737000 -     0x7fff53759fff  com.apple.applesauce (1.0 - ???) <48562D0B-1A1D-3D62-8BC2-61C55D0DCECE> /System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce
    0x7fff538b8000 -     0x7fff538ccffb  com.apple.AssertionServices (1.0 - 1) <F64A3177-294E-320C-A0E1-25C4322B98E9> /System/Library/PrivateFrameworks/AssertionServices.framework/Versions/A/AssertionServices
    0x7fff53c97000 -     0x7fff53f34ff7  com.apple.AuthKit (1.0 - 1) <5BC0D7C7-A46A-3B1A-BDC9-7E9150B5A876> /System/Library/PrivateFrameworks/AuthKit.framework/Versions/A/AuthKit
    0x7fff540f6000 -     0x7fff540fefff  com.apple.coreservices.BackgroundTaskManagement (1.0 - 57.1) <7F48D9BD-17A8-3A76-8828-EC49245735EE> /System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement
    0x7fff540ff000 -     0x7fff54194fff  com.apple.backup.framework (1.10.4 - ???) <8247B1BE-DF97-31DC-BCC2-1A15797352D3> /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup
    0x7fff54195000 -     0x7fff54202fff  com.apple.BaseBoard (360.27 - 360.27) <215A242E-BD57-3A4B-BCA4-FCC9D674CE7B> /System/Library/PrivateFrameworks/BaseBoard.framework/Versions/A/BaseBoard
    0x7fff55e67000 -     0x7fff55e70ffb  com.apple.CommonAuth (4.0 - 2.0) <55CEF8E6-A659-3D68-BEE0-1236F36E494C> /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth
    0x7fff56b46000 -     0x7fff56b57ff7  com.apple.CoreEmoji (1.0 - 69.19.9) <90ACD3F0-1542-3094-A1F6-FF2F508A8561> /System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji
    0x7fff57100000 -     0x7fff57166ff7  com.apple.CoreNLP (1.0 - 130.15.22) <5191A681-5DF3-359A-B401-C29109EA420A> /System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP
    0x7fff57413000 -     0x7fff5741bff7  com.apple.CorePhoneNumbers (1.0 - 1) <01CAC5E2-B6B1-3444-8939-595A9301399C> /System/Library/PrivateFrameworks/CorePhoneNumbers.framework/Versions/A/CorePhoneNumbers
    0x7fff57597000 -     0x7fff575c8ff3  com.apple.CoreServicesInternal (358 - 358) <7DD35528-033B-3B59-AAF2-5BFAF449D915> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/Versions/A/CoreServicesInternal
    0x7fff5798e000 -     0x7fff57a12fff  com.apple.CoreSymbolication (10.2 - 64490.25.1) <CBA82F08-26CC-3FB4-9539-B0B55B35C5E1> /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication
    0x7fff57aa1000 -     0x7fff57bccff7  com.apple.coreui (2.1 - 499.10) <50A90628-5400-3EBC-A1FE-87D68BC59377> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
    0x7fff57bcd000 -     0x7fff57d69ffb  com.apple.CoreUtils (5.7.6 - 576.49) <60FF6102-EEBB-302E-8DE4-6DCBB689ACC8> /System/Library/PrivateFrameworks/CoreUtils.framework/Versions/A/CoreUtils
    0x7fff57dbd000 -     0x7fff57e20ff7  com.apple.framework.CoreWiFi (13.0 - 1370.8) <F8634D22-1AD4-36B0-848C-BA60CC88BDAE> /System/Library/PrivateFrameworks/CoreWiFi.framework/Versions/A/CoreWiFi
    0x7fff57e21000 -     0x7fff57e32ff7  com.apple.CrashReporterSupport (10.13 - 938.25) <AB842AE0-8594-3530-ABB7-30E583F82FC5> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport
    0x7fff57ec1000 -     0x7fff57ed0fff  com.apple.framework.DFRFoundation (1.0 - 211.1) <201CCA68-44E4-3E09-8604-7D8833AC803B> /System/Library/PrivateFrameworks/DFRFoundation.framework/Versions/A/DFRFoundation
    0x7fff57ed1000 -     0x7fff57ed5fff  com.apple.DSExternalDisplay (3.1 - 380) <6AC4F805-7AAF-31D3-B614-C78B61907EE3> /System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay
    0x7fff57f56000 -     0x7fff57fcbff3  com.apple.datadetectorscore (7.0 - 590.24) <2A591F27-0FEE-3CE1-B6C3-7A3B56C9D18D> /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore
    0x7fff58017000 -     0x7fff58054ff7  com.apple.DebugSymbols (190 - 190) <F2269F7B-5FCC-3187-8F13-A15F2C9D21E5> /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols
    0x7fff58055000 -     0x7fff58190fff  com.apple.desktopservices (1.13.1 - ???) <420CC09F-7C18-3644-A024-DA8997FECA02> /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
    0x7fff590cb000 -     0x7fff594e6fff  com.apple.vision.FaceCore (3.3.4 - 3.3.4) <D642D5E1-C7C5-3EBF-9D0A-397BDE2A5723> /System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore
    0x7fff5e43b000 -     0x7fff5e440fff  com.apple.GPUWrangler (3.30.14 - 3.30.14) <5D15F5B8-9D7B-356D-A224-A86CF809BFBF> /System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler
    0x7fff5e80a000 -     0x7fff5f203fff  com.apple.GeoServices (1.0 - 1364.24.8.24.47) <7A0FB79F-E311-3805-A8E2-C5E0176736DA> /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/GeoServices
    0x7fff5f245000 -     0x7fff5f254fff  com.apple.GraphVisualizer (1.0 - 5) <C261C18C-C66F-39BA-A640-727434ADBEB7> /System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer
    0x7fff5f3a1000 -     0x7fff5f415ffb  com.apple.Heimdal (4.0 - 2.0) <05B753FE-8F65-3764-8E18-F31902064BA1> /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal
    0x7fff606ff000 -     0x7fff60706ffb  com.apple.IOAccelerator (404.8 - 404.8) <FB11472D-74D7-31D4-8DF6-9A668BB08D4F> /System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator
    0x7fff6070a000 -     0x7fff60722fff  com.apple.IOPresentment (1.0 - 42.6) <B3365E07-6FC3-3AAA-884D-D6EE7ACDAE16> /System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment
    0x7fff60aca000 -     0x7fff60af7ff7  com.apple.IconServices (379 - 379) <189807AC-4BB1-3C37-B6EC-D4F0B645902D> /System/Library/PrivateFrameworks/IconServices.framework/Versions/A/IconServices
    0x7fff60d89000 -     0x7fff60d9bff3  com.apple.security.KeychainCircle.KeychainCircle (1.0 - 1) <731EEEC5-1613-3725-B33C-B38BBD55FA96> /System/Library/PrivateFrameworks/KeychainCircle.framework/Versions/A/KeychainCircle
    0x7fff60db6000 -     0x7fff60e91ff7  com.apple.LanguageModeling (1.0 - 159.15.15) <229A8E92-CCB6-3BC7-BCD3-B2309FA744B3> /System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling
    0x7fff60e92000 -     0x7fff60eceff7  com.apple.Lexicon-framework (1.0 - 33.15.10) <30D3EEF3-31E5-3DE8-8158-40627C358AF6> /System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon
    0x7fff60ed5000 -     0x7fff60edafff  com.apple.LinguisticData (1.0 - 238.24.1) <E155D8DF-8AC1-34B2-B143-BBD3408C8D19> /System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData
    0x7fff61bc9000 -     0x7fff61bf1ff7  com.apple.spotlight.metadata.utilities (1.0 - 1191.56) <550876F2-D905-3D65-8FA6-3366D857437B> /System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities
    0x7fff61bf2000 -     0x7fff61c7cfff  com.apple.gpusw.MetalTools (1.0 - 1) <09394594-A80D-3D8B-99E8-E71693909FA1> /System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools
    0x7fff61e4a000 -     0x7fff61e64fff  com.apple.MobileKeyBag (2.0 - 1.0) <A38DB402-7EB2-3D81-A9FA-4C95748FFC2D> /System/Library/PrivateFrameworks/MobileKeyBag.framework/Versions/A/MobileKeyBag
    0x7fff61eec000 -     0x7fff61f16ffb  com.apple.MultitouchSupport.framework (2440.7 - 2440.7) <FAE48832-BB56-35C9-B433-F0D03EF50FCD> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport
    0x7fff62152000 -     0x7fff6215cfff  com.apple.NetAuth (6.2 - 6.2) <216DF366-7A3E-39E7-896C-7CDFD2A9BD3D> /System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth
    0x7fff629bd000 -     0x7fff62a0eff3  com.apple.OTSVG (1.0 - ???) <AF7D1285-08EE-3EEB-B8B7-6C358768473D> /System/Library/PrivateFrameworks/OTSVG.framework/Versions/A/OTSVG
    0x7fff63ac2000 -     0x7fff63ad1ff7  com.apple.PerformanceAnalysis (1.218.2 - 218.2) <DAF9D379-F0E9-3929-829E-7B2FAFC7DC64> /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis
    0x7fff65961000 -     0x7fff6597fff7  com.apple.ProtocolBuffer (1 - 263) <DBBA73C9-E9AE-3CF5-88A4-7E4262BDE34E> /System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer
    0x7fff65b17000 -     0x7fff65b67fff  com.apple.ROCKit (27.6 - 27.6) <A8116AFC-F78F-32BF-A66C-ED3B5E9FF1D9> /System/Library/PrivateFrameworks/ROCKit.framework/Versions/A/ROCKit
    0x7fff65cb0000 -     0x7fff65cd2fff  com.apple.RemoteViewServices (2.0 - 128) <E22D4E74-7B87-31ED-86D2-D63258D1B792> /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices
    0x7fff674d1000 -     0x7fff675ebfff  com.apple.Sharing (1288.25 - 1288.25) <E4C2CE6D-757D-322F-AA8D-52A0993E02D6> /System/Library/PrivateFrameworks/Sharing.framework/Versions/A/Sharing
    0x7fff68393000 -     0x7fff6863cfff  com.apple.SkyLight (1.600.0 - 340.9) <A962D996-6561-3993-B470-EFD6EE4BFA9C> /System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight
    0x7fff68dde000 -     0x7fff68deafff  com.apple.SpeechRecognitionCore (5.0.21 - 5.0.21) <08222836-F14B-3B9D-BCB9-3167505438E4> /System/Library/PrivateFrameworks/SpeechRecognitionCore.framework/Versions/A/SpeechRecognitionCore
    0x7fff6953b000 -     0x7fff695c6fc7  com.apple.Symbolication (10.2 - 64490.38.1) <15A1DF22-3EE2-359A-8F94-B27F89F35ECE> /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication
    0x7fff69aad000 -     0x7fff69ab9ffb  com.apple.TCC (1.0 - 1) <95D4B7DF-78F3-3948-AA63-6425AF2C00CD> /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
    0x7fff69d1f000 -     0x7fff69de7ff3  com.apple.TextureIO (3.8.4 - 3.8.1) <29383676-6133-3EB4-8CAC-5A6F25FE2F4D> /System/Library/PrivateFrameworks/TextureIO.framework/Versions/A/TextureIO
    0x7fff69e9d000 -     0x7fff69e9efff  com.apple.TrustEvaluationAgent (2.0 - 31.200.1) <DDE0F972-B214-324D-BDA5-749E81CB642F> /System/Library/PrivateFrameworks/TrustEvaluationAgent.framework/Versions/A/TrustEvaluationAgent
    0x7fff69ea4000 -     0x7fff6a05aff7  com.apple.UIFoundation (1.0 - 551) <5359E30D-AF76-3013-8B50-0A93DB97BB8F> /System/Library/PrivateFrameworks/UIFoundation.framework/Versions/A/UIFoundation
    0x7fff6b586000 -     0x7fff6b589fff  com.apple.dt.XCTTargetBootstrap (1.0 - 14490.46.2) <7763C799-CE25-302D-96D7-2A4DD9BEEE9A> /System/Library/PrivateFrameworks/XCTTargetBootstrap.framework/Versions/A/XCTTargetBootstrap
    0x7fff6b98a000 -     0x7fff6b98cffb  com.apple.loginsupport (1.0 - 1) <F9C63D6B-5191-3D95-B5C7-B998FA148AA6> /System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport
    0x7fff6bc53000 -     0x7fff6bc87fff  libCRFSuite.dylib (41.15.4) <43D02A64-2A7B-3825-8097-A6747AF914EE> /usr/lib/libCRFSuite.dylib
    0x7fff6bc8a000 -     0x7fff6bc94ff7  libChineseTokenizer.dylib (28.15.3) <BE41A678-907E-3031-B2BA-ECDB81282499> /usr/lib/libChineseTokenizer.dylib
    0x7fff6bd22000 -     0x7fff6bd23ffb  libDiagnosticMessagesClient.dylib (107) <B5675E8C-2F34-3E0A-B7E8-6F2373589038> /usr/lib/libDiagnosticMessagesClient.dylib
    0x7fff6bd5a000 -     0x7fff6bfb1ffb  libFosl_dynamic.dylib (18.3.2) <C46C13F6-2799-39A0-BB32-126C2259194A> /usr/lib/libFosl_dynamic.dylib
    0x7fff6c002000 -     0x7fff6c020fff  libMobileGestalt.dylib (645.250.13) <6B4E26AD-D712-360B-904C-877C24D89393> /usr/lib/libMobileGestalt.dylib
    0x7fff6c021000 -     0x7fff6c021fff  libOpenScriptingUtil.dylib (179.1) <5C6CFA80-CBCD-35EB-A69C-72C3B2E8FF50> /usr/lib/libOpenScriptingUtil.dylib
    0x7fff6c161000 -     0x7fff6c162ffb  libSystem.B.dylib (1252.250.1) <72841192-B0C9-36A0-8E55-ED651EADEF08> /usr/lib/libSystem.B.dylib
    0x7fff6c1de000 -     0x7fff6c1dffff  libThaiTokenizer.dylib (2.15.1) <3D80A800-D49A-305E-9DF0-E6FB11D4FD65> /usr/lib/libThaiTokenizer.dylib
    0x7fff6c1f1000 -     0x7fff6c207ffb  libapple_nghttp2.dylib (1.24.1) <96F6DF29-D31C-3097-9C3E-63B1D62D756C> /usr/lib/libapple_nghttp2.dylib
    0x7fff6c208000 -     0x7fff6c231ffb  libarchive.2.dylib (54.250.1) <D6370CDB-920D-37A3-A9C0-6C1FC95F2F99> /usr/lib/libarchive.2.dylib
    0x7fff6c232000 -     0x7fff6c331fef  libate.dylib (1.13.8) <E9801F27-69B1-3829-A67F-A6C1D563A647> /usr/lib/libate.dylib
    0x7fff6c335000 -     0x7fff6c335ff3  libauto.dylib (187) <4E260A46-13BB-3A8F-A037-D89748837B2A> /usr/lib/libauto.dylib
    0x7fff6c405000 -     0x7fff6c415ffb  libbsm.0.dylib (39.200.18) <CF0C09D6-FCED-3B48-A617-768A0B5B9DEB> /usr/lib/libbsm.0.dylib
    0x7fff6c416000 -     0x7fff6c423fff  libbz2.1.0.dylib (38.200.3) <62019AC3-20C9-3DDC-9C83-189C1F258073> /usr/lib/libbz2.1.0.dylib
    0x7fff6c424000 -     0x7fff6c477ff7  libc++.1.dylib (400.9.4) <446DAE5E-4E97-3E4B-B2A3-AC0A74C0E453> /usr/lib/libc++.1.dylib
    0x7fff6c478000 -     0x7fff6c48dff7  libc++abi.dylib (400.17) <A2D1FDAD-E10F-3E53-958F-CB6BC8485767> /usr/lib/libc++abi.dylib
    0x7fff6c48e000 -     0x7fff6c48eff3  libcharset.1.dylib (51.200.6) <0D3A5F4C-8800-33E3-AFE5-307E8BEE462C> /usr/lib/libcharset.1.dylib
    0x7fff6c48f000 -     0x7fff6c49fffb  libcmph.dylib (6.15.1) <740A788E-FD92-36F3-B678-E7D510B1E2A1> /usr/lib/libcmph.dylib
    0x7fff6c4a0000 -     0x7fff6c4b8ffb  libcompression.dylib (52.250.2) <2AD18016-88F4-3A10-B235-50B44C3A70A8> /usr/lib/libcompression.dylib
    0x7fff6c72d000 -     0x7fff6c743fff  libcoretls.dylib (155.220.1) <FF7EA01E-9A26-36F9-A6FF-9665B501B536> /usr/lib/libcoretls.dylib
    0x7fff6c744000 -     0x7fff6c745ff3  libcoretls_cfhelpers.dylib (155.220.1) <51572EB9-D154-348B-9934-3CA9444FAE5E> /usr/lib/libcoretls_cfhelpers.dylib
    0x7fff6c8e3000 -     0x7fff6ca72ffb  libcrypto.35.dylib (22.250.1) <3C591DDE-3002-3E2D-9CB0-9F588053E703> /usr/lib/libcrypto.35.dylib
    0x7fff6cdb7000 -     0x7fff6ce0dff7  libcups.2.dylib (462.10) <83EF6851-07F6-35B4-AA80-690EF026C706> /usr/lib/libcups.2.dylib
    0x7fff6cf41000 -     0x7fff6cf41fff  libenergytrace.dylib (17.200.1) <F0A35E72-B772-359B-81AC-0C94B8A621CA> /usr/lib/libenergytrace.dylib
    0x7fff6cf73000 -     0x7fff6cf78ff7  libgermantok.dylib (17.15.2) <A78E0BF5-0038-35C7-A8E7-05AEDF86D6D5> /usr/lib/libgermantok.dylib
    0x7fff6cf79000 -     0x7fff6cf7eff7  libheimdal-asn1.dylib (520.250.1) <DE1C4650-FDFE-3A31-98AD-597B57C947E5> /usr/lib/libheimdal-asn1.dylib
    0x7fff6cfa9000 -     0x7fff6d099fff  libiconv.2.dylib (51.200.6) <E767B418-3531-3BB0-B58D-9ECB203407B7> /usr/lib/libiconv.2.dylib
    0x7fff6d09a000 -     0x7fff6d2faff3  libicucore.A.dylib (62123.0.1) <3936C798-1978-3C6C-9050-3BBD57CDA53E> /usr/lib/libicucore.A.dylib
    0x7fff6d347000 -     0x7fff6d348fff  liblangid.dylib (128.15.1) <1ED2EB78-3891-3DBA-8CB7-BA1A100CFC8F> /usr/lib/liblangid.dylib
    0x7fff6d349000 -     0x7fff6d361ff3  liblzma.5.dylib (10.200.3) <E6CA9433-904B-3804-82FF-B328E2047368> /usr/lib/liblzma.5.dylib
    0x7fff6d379000 -     0x7fff6d41dff7  libmecab.1.0.0.dylib (779.24.1) <0C57BF6E-A713-3AE8-8AD3-80F65D4CCC15> /usr/lib/libmecab.1.0.0.dylib
    0x7fff6d41e000 -     0x7fff6d622fff  libmecabra.dylib (779.24.1) <A658B79D-4071-3EC1-9344-ADA438E43FB4> /usr/lib/libmecabra.dylib
    0x7fff6d7fa000 -     0x7fff6db4bff7  libnetwork.dylib (1229.250.15) <D8F52B1D-1AD9-3D33-8D59-2D631A3CBFEC> /usr/lib/libnetwork.dylib
    0x7fff6dbdb000 -     0x7fff6e363fd7  libobjc.A.dylib (756.2) <E344D532-344C-3D2A-9DA7-B2684DDFB43A> /usr/lib/libobjc.A.dylib
    0x7fff6e375000 -     0x7fff6e379ffb  libpam.2.dylib (22.200.1) <3AEB13DB-8DE2-3FD9-97D5-D9DB206E0693> /usr/lib/libpam.2.dylib
    0x7fff6e37c000 -     0x7fff6e3b1fff  libpcap.A.dylib (79.250.1) <FA490ABF-6C15-336A-818F-0C14A8C090DB> /usr/lib/libpcap.A.dylib
    0x7fff6e4ca000 -     0x7fff6e4e2ffb  libresolv.9.dylib (65.200.2) <DB6CA331-BB44-306D-8528-023EADE54BF7> /usr/lib/libresolv.9.dylib
    0x7fff6e535000 -     0x7fff6e706ffb  libsqlite3.dylib (274.22) <4DB422B2-DFBD-3C46-ABA9-50CC2D4490FD> /usr/lib/libsqlite3.dylib
    0x7fff6e986000 -     0x7fff6e989ff7  libutil.dylib (51.200.4) <336F9184-A739-3770-ACFA-4659DFEEACC4> /usr/lib/libutil.dylib
    0x7fff6e98a000 -     0x7fff6e997fff  libxar.1.dylib (417.1) <D7AC80EE-D974-33E6-ACA7-87B398ACEDD7> /usr/lib/libxar.1.dylib
    0x7fff6e99c000 -     0x7fff6ea7eff3  libxml2.2.dylib (32.8) <064C2F49-C054-38F9-A6B2-032C4AC9738B> /usr/lib/libxml2.2.dylib
    0x7fff6ea7f000 -     0x7fff6eaa7ff3  libxslt.1.dylib (16.1) <FB93A727-731D-313F-AF6B-4518FE830FFB> /usr/lib/libxslt.1.dylib
    0x7fff6eaa8000 -     0x7fff6eabaff7  libz.1.dylib (70.200.4) <FDF169F3-F992-3E8E-B3F7-D4134FEBAE41> /usr/lib/libz.1.dylib
    0x7fff6f297000 -     0x7fff6f29bff3  libcache.dylib (81) <9A8C27B0-49C9-337F-8BE2-37171ED2D8EE> /usr/lib/system/libcache.dylib
    0x7fff6f29c000 -     0x7fff6f2a6ff3  libcommonCrypto.dylib (60118.250.2) <17C4F395-9FF0-331F-8167-5E85AA3588E9> /usr/lib/system/libcommonCrypto.dylib
    0x7fff6f2a7000 -     0x7fff6f2aeff7  libcompiler_rt.dylib (63.4) <8CB2B2B6-2C55-3733-9842-0E037AE3F46A> /usr/lib/system/libcompiler_rt.dylib
    0x7fff6f2af000 -     0x7fff6f2b8ff7  libcopyfile.dylib (146.250.1) <24905E41-9E2F-3DD1-A255-5A17F9FCDAD7> /usr/lib/system/libcopyfile.dylib
    0x7fff6f2b9000 -     0x7fff6f33dfc7  libcorecrypto.dylib (602.250.23) <3A6CBD41-AFFE-3E06-B1EC-3E95BC79BAC5> /usr/lib/system/libcorecrypto.dylib
    0x7fff6f3c4000 -     0x7fff6f3fdff7  libdispatch.dylib (1008.250.7) <50235FCE-B399-3319-90DC-88F530D4FC5C> /usr/lib/system/libdispatch.dylib
    0x7fff6f3fe000 -     0x7fff6f42aff7  libdyld.dylib (655.1.1) <54C6B494-4A3D-3EEC-B083-636A76AAD649> /usr/lib/system/libdyld.dylib
    0x7fff6f42b000 -     0x7fff6f42bffb  libkeymgr.dylib (30) <BEA04E04-FCF1-3A70-810F-08D0FF54CA36> /usr/lib/system/libkeymgr.dylib
    0x7fff6f42c000 -     0x7fff6f438ff3  libkxld.dylib (4903.251.3) <649F5829-6AA8-32EE-9A33-B1244378C319> /usr/lib/system/libkxld.dylib
    0x7fff6f439000 -     0x7fff6f439ff7  liblaunch.dylib (1336.251.2) <30E6424E-4640-3DBA-9B64-D5F725263C6E> /usr/lib/system/liblaunch.dylib
    0x7fff6f43a000 -     0x7fff6f43ffff  libmacho.dylib (927.0.2) <D8515A20-ED7B-3B13-9ADA-4BD7E19E38C4> /usr/lib/system/libmacho.dylib
    0x7fff6f440000 -     0x7fff6f442ffb  libquarantine.dylib (86.220.1) <8A9BF971-DB7D-311A-B131-6C5025E82F8F> /usr/lib/system/libquarantine.dylib
    0x7fff6f443000 -     0x7fff6f444ff7  libremovefile.dylib (45.200.2) <950036B7-B91E-3B5D-853C-8C551E5B6A32> /usr/lib/system/libremovefile.dylib
    0x7fff6f445000 -     0x7fff6f45cff3  libsystem_asl.dylib (356.200.4) <16F632AD-FADA-3DE9-85E8-EBC7D619A1DA> /usr/lib/system/libsystem_asl.dylib
    0x7fff6f45d000 -     0x7fff6f45dff7  libsystem_blocks.dylib (73) <0CD6861B-EC5F-3345-9C24-B21EEB85E44F> /usr/lib/system/libsystem_blocks.dylib
    0x7fff6f45e000 -     0x7fff6f4e5fff  libsystem_c.dylib (1272.250.1) <F3AA9047-EEDD-3D80-8CC1-023FB312EC8B> /usr/lib/system/libsystem_c.dylib
    0x7fff6f4e6000 -     0x7fff6f4e9ffb  libsystem_configuration.dylib (963.250.1) <02C7A973-014A-31D7-B7D2-247D384CB0D2> /usr/lib/system/libsystem_configuration.dylib
    0x7fff6f4ea000 -     0x7fff6f4edff7  libsystem_coreservices.dylib (66) <4CF1C89B-FA6C-3DF3-B1F8-79F549849534> /usr/lib/system/libsystem_coreservices.dylib
    0x7fff6f4ee000 -     0x7fff6f4f4fff  libsystem_darwin.dylib (1272.250.1) <6983A268-20F4-3F98-A3F5-D63848933B02> /usr/lib/system/libsystem_darwin.dylib
    0x7fff6f4f5000 -     0x7fff6f4fbff7  libsystem_dnssd.dylib (878.250.4) <9FC5724C-DD03-3E14-A6E1-2DD009D79E0A> /usr/lib/system/libsystem_dnssd.dylib
    0x7fff6f4fc000 -     0x7fff6f547ffb  libsystem_info.dylib (517.200.9) <F617D3CF-5A4A-36D0-8CBB-4A7C7CDB67AF> /usr/lib/system/libsystem_info.dylib
    0x7fff6f548000 -     0x7fff6f570ff7  libsystem_kernel.dylib (4903.251.3) <84EF0290-6CB5-36E5-A273-692A7E437B36> /usr/lib/system/libsystem_kernel.dylib
    0x7fff6f571000 -     0x7fff6f5bcff7  libsystem_m.dylib (3158.200.7) <33105665-CCC3-36D5-82C9-9B21730CB3DF> /usr/lib/system/libsystem_m.dylib
    0x7fff6f5bd000 -     0x7fff6f5e1fff  libsystem_malloc.dylib (166.251.2) <90DA09E3-1276-3FCF-8F5F-C9AA61AB9B6D> /usr/lib/system/libsystem_malloc.dylib
    0x7fff6f5e2000 -     0x7fff6f5ecff7  libsystem_networkextension.dylib (767.250.2) <4575D797-B793-3D18-9E93-8696CF0B133B> /usr/lib/system/libsystem_networkextension.dylib
    0x7fff6f5ed000 -     0x7fff6f5f4fff  libsystem_notify.dylib (172.200.21) <679E9132-1A46-326E-9A11-D3FF9C86041C> /usr/lib/system/libsystem_notify.dylib
    0x7fff6f5f5000 -     0x7fff6f5fefef  libsystem_platform.dylib (177.250.1) <3CC59141-5365-3848-94C3-D65E6FCA1E74> /usr/lib/system/libsystem_platform.dylib
    0x7fff6f5ff000 -     0x7fff6f609ff7  libsystem_pthread.dylib (330.250.2) <4344198A-A1A3-3C52-97B4-F168D56E9789> /usr/lib/system/libsystem_pthread.dylib
    0x7fff6f60a000 -     0x7fff6f60dff7  libsystem_sandbox.dylib (851.250.12) <66E91015-F62A-3365-BB81-AA88707E8F12> /usr/lib/system/libsystem_sandbox.dylib
    0x7fff6f60e000 -     0x7fff6f610ff3  libsystem_secinit.dylib (30.220.1) <F054DCB0-68CE-35E7-8B8C-D648C42124EC> /usr/lib/system/libsystem_secinit.dylib
    0x7fff6f611000 -     0x7fff6f618ff3  libsystem_symptoms.dylib (820.257.1) <C8517F35-E9DA-3649-B07D-2B38349C6730> /usr/lib/system/libsystem_symptoms.dylib
    0x7fff6f619000 -     0x7fff6f62efff  libsystem_trace.dylib (906.250.5) <AE77ACC7-488F-3AE1-BB0C-1ACFC7E1CE77> /usr/lib/system/libsystem_trace.dylib
    0x7fff6f630000 -     0x7fff6f635ffb  libunwind.dylib (35.4) <8F0BC197-B97C-3DDC-92B0-6A7D3CB72FD8> /usr/lib/system/libunwind.dylib
    0x7fff6f636000 -     0x7fff6f665ff7  libxpc.dylib (1336.251.2) <49138829-09C8-355C-B558-97E070B84EC5> /usr/lib/system/libxpc.dylib

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 1437
    thread_create: 0
    thread_set_state: 0

VM Region Summary:
ReadOnly portion of Libraries: Total=398.9M resident=0K(0%) swapped_out_or_unallocated=398.9M(100%)
Writable regions: Total=62.0M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=62.0M(100%)
 
                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Activity Tracing                   256K        1 
Dispatch continuations            8192K        1 
Kernel Alloc Once                    8K        1 
MALLOC                            38.5M       12 
MALLOC guard page                   16K        4 
MALLOC_LARGE (reserved)           1024K        1         reserved VM address space (unallocated)
STACK GUARD                       56.0M       13 
Stack                             14.1M       13 
VM_ALLOCATE                         48K        3 
__DATA                            25.9M      230 
__FONT_DATA                          4K        1 
__GLSLBUILTINS                    5176K        1 
__LINKEDIT                       225.4M        3 
__TEXT                           173.6M      231 
__UNICODE                          564K        1 
mapped file                       30.8M        5 
shared memory                      628K        8 
===========                     =======  ======= 
TOTAL                            579.8M      529 
TOTAL, minus reserved VM space   578.8M      529 

To grab that crash trace, SSH into the build bot and:

cd project/build/
./mbgl-test-runner --gtest_filter=LocalGlyphRasterizer.*
cat ~/Library/Logs/DiagnosticReports/mbgl-test-runner_2020-03-02-145929_Distillers-Mac-4.crash

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 2, 2020

The PingFang font families are installed on the build machine at /System/Library/Fonts/PingFang.ttc, and no font is disabled:

$ plutil -p ~/Library/Preferences/com.apple.FontRegistry.user.plist
{
  "LastUpdated" => 2020-03-02 21:51:57 +0000
  "Version" => "18E226"
}

I seem to have no problem running this equivalent Swift code in interactive mode, so I wonder if there’s a memory management problem that only surfaces on the build machine for some reason.

import Foundation
import CoreText

let attributes = [
    kCTFontSizeAttribute: 24,
    kCTFontFamilyNameAttribute: "PingFang",
] as [CFString : Any]
let desc = CTFontDescriptorCreateWithAttributes(attributes as CFDictionary)
let font = CTFontCreateWithFontDescriptor(desc, 0, nil)

let attrs = [kCTFontAttributeName: font]
let attrStr = CFAttributedStringCreate(kCFAllocatorDefault, "\u{8EAB}\u{4EC0}\u{6230}\u{30A2}\u{3042}1" as CFString, attrs as CFDictionary)
print(CTLineCreateWithAttributedString(attrStr!))
<CTLine: 0x10013bbe0>{run count = 2, string range = (0, 6), width = 133.348, A/D/L = 25.4401/8.16002/0, glyph count = 6, runs = (

<CTRun: 0x10013de40>{string range = (0, 5), string = "\u8EAB\u4EC0\u6230\u30A2\u3042", attributes = <CFBasicHash 0x10013ca70 [0x7fff9aba98f0]>{type = mutable dict, count = 1,
entries =>
	2 : <CFString 0x7fff9af613a0 [0x7fff9aba98f0]>{contents = "NSFont"} = <CTFont: 0x10013db70>{name = PingFangSC-Regular, size = 24.000000, matrix = 0x0, descriptor = <CTFontDescriptor: 0x100130650>{attributes = <CFBasicHash 0x1001305e0 [0x7fff9aba98f0]>{type = mutable dict, count = 1,
entries =>
	2 : <CFString 0x7fff9af70580 [0x7fff9aba98f0]>{contents = "NSFontNameAttribute"} = <CFString 0x100217680 [0x7fff9aba98f0]>{contents = "PingFangSC-Regular"}
}
>}}
}
}


<CTRun: 0x10013df90>{string range = (5, 1), string = "1", attributes = <CFBasicHash 0x10020f3b0 [0x7fff9aba98f0]>{type = mutable dict, count = 1,
entries =>
	2 : <CFString 0x7fff9af613a0 [0x7fff9aba98f0]>{contents = "NSFont"} = <CTFont: 0x10020d040>{name = Helvetica, size = 24.000000, matrix = 0x0, descriptor = <CTFontDescriptor: 0x10020cbd0>{attributes = <CFBasicHash 0x10020be20 [0x7fff9aba98f0]>{type = mutable dict, count = 2,
entries =>
	0 : <CFString 0x7fff9af70820 [0x7fff9aba98f0]>{contents = "NSFontSizeAttribute"} = <CFNumber 0xd7b353bde9963a39 [0x7fff9aba98f0]>{value = +12.00000000000000000000, type = kCFNumberFloat64Type}
	2 : <CFString 0x7fff9af70580 [0x7fff9aba98f0]>{contents = "NSFontNameAttribute"} = <CFString 0x7fff9af60ac0 [0x7fff9aba98f0]>{contents = "Helvetica"}
}
>}}
}
}

)
}

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 3, 2020

The iOS failure is similar to the macOS failure (not the crash) in #16253 (comment):

<testcase name="PingFang" status="run" time="0.056" classname="LocalGlyphRasterizer">
<failure message="/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.015213 vs 0.015" type="">
/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.015213 vs 0.015
</failure>
</testcase>

The test was passing on iOS before 305df25, so the previous fixture was correct for iOS.

@1ec5
Copy link
Contributor Author

1ec5 commented Mar 5, 2020

I’m unable to reproduce the LocalGlyphRasterizer.PingFang test failure locally in the following environments:

  • iPhone 8 simulator, iOS 13.3
  • iPhone 11 simulator, iOS 13.3

The test passes with the modified test fixture, unlike on CI:

[ RUN      ] LocalGlyphRasterizer.PingFang
2020-03-04 18:22:35.230959-0800 UnitTestsApp[17902:8721939] [INFO] {}[General]: GPU Identifier: Apple Software Renderer
[       OK ] LocalGlyphRasterizer.PingFang (488 ms)

@1ec5

This comment has been minimized.

@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch from 09c809f to 3d1ad67 Compare March 18, 2020 06:32
@1ec5
Copy link
Contributor Author

1ec5 commented Mar 20, 2020

e8384c2 gets glyph metrics from the font. It’s a mixture of parts of coretext-hack (#7862 (comment)) and the code removed in 155804b, but using the correct Core Text APIs so there aren’t any gaps in glyph metrics.

Some rendering tests currently fail with these changes. For the most part, I think the new rendering is superior in terms of making the baseline more consistent with mixed CJK/Latin text and improving kerning of Hangul. (The Hangul fonts that ship with Apple platforms don’t have perfectly square glyphs.) However, vertical text isn’t centered correctly. The metrics need to be reinterpreted for vertical text, which will require changes to the platform-agnostic interface. As well, Latin followed by CJK has too little kerning, probably because of an inaccurate advance metric coming from non-locally rasterized glyphs.

Expected Diff Actual
expected diff actual

I think these changes might help to address some of the suboptimal placement reported in mapbox/mapbox-gl-js#9134.

@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch 2 times, most recently from 22ab715 to 603e650 Compare March 30, 2020 16:02
Copy link
Contributor Author

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For those following along, this PR currently implements the elegant approach described in mapbox/mapbox-gl-native-ios#105 (comment), not the more comprehensive but more convoluted approach in mapbox/mapbox-gl-native-ios#105 (comment). Either way, the new LocalGlyphRasterizer implementation is sufficiently generic that we’re two steps away from extending LocalGlyphRasterizer support to all scripts, not just monospaced CJK.

However, including the font stack in the font cascade list could have performance implementations, so we may need to introduce optimizations like font descriptor caching. If polishing the font stack–aware implementation drags on, we can split out 93809da into a separate PR and first land a non–font stack–aware implementation.

{
fallbackFontNames = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"MGLIdeographicFontFamilyName"];
if (fontFamily_) {
fallbackFontNames = [fallbackFontNames ?: @[] arrayByAddingObjectsFromArray:[@(fontFamily_->c_str()) componentsSeparatedByString:@"\n"]];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The primary thing I’m looking for feedback on is what to do about this single-string argument to the LocalGlyphRasterizer constructor. My understanding is that other platforms like Android need to select and validate a single font at the SDK level, whereas iOS/macOS has outgrown that approach and needs to maintain a whole list of fonts that can only be validated by the system on the fly.

Should we change the signature of this constructor across all platforms to allow for a std::vector of font names? Alternatively, would it be OK for the iOS/macOS implementation to ignore the single-string name or treat it as just one more fallback (as currently implemented in this PR)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the idea of using std::vector here. Though could we land this PR as is and address that later?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps – it just feels wrong to smuggle a newline-delimited list through a single-string API to split it apart on the other end.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The primary thing I’m looking for feedback on is what to do about this single-string argument to the LocalGlyphRasterizer constructor.

Should we change the signature of this constructor across all platforms to allow for a std::vector of font names? Alternatively, would it be OK for the iOS/macOS implementation to ignore the single-string name or treat it as just one more fallback (as currently implemented in this PR)?

@alexshalamov I think you're the most familiar with this part of the code. Is there any reason GL Native can't accept a whole list of fonts here?

If we agree to make this change at the core level, I also think that it would be better in a separate PR.

cc @tmpsantos @tobrun @knov @zugaldia

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had been trying to minimize changes to the cross-platform interface, but this constructor is only called from platform-specific code, so the cross-platform code in mbgl doesn’t particularly care about the signature. If folks are OK with a little additional churn, it would be great to change this method to take a std::optional<std::vector<std::string>>, with nullptr disabling local glyph rasterization and an empty vector using the system’s default fallback.

}

private:
optional<std::string> fontFamily;
CTFontRef fontHandle;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR no longer memoizes the resolved font. The font cascade list starts with the font stack from the style, which means the font descriptor can potentially differ for every invocation of LocalGlyphRasterizer::rasterizeGlyph(). If performance turns out to be an issue, this class could build up a cache mapping FontStacks to CTFontDescriptorRefs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, let's check the performance after this PR.

@@ -96,14 +122,30 @@ CTFontRef getFont() {
{}

bool LocalGlyphRasterizer::canRasterizeGlyph(const FontStack&, GlyphID glyphID) {
return util::i18n::allowsFixedWidthGlyphGeneration(glyphID) && impl->getFont();
return util::i18n::allowsFixedWidthGlyphGeneration(glyphID) && impl->isEnabled();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff is a bit hard to follow. Before, glyphs within the limited CJK ranges would be rasterized locally unless no local font family was specified (disabling the feature). In the case where getFont() failed to create a CTFontRef, it would throw an exception, not return false. Moreover, that case would never occur, because CTFontCreateWithFontDescriptor() always returns a best-match font (Helvetica as a last resort fallback).

The new code makes the disabled case more explicit.


// Start drawing a little bit below the top of the bitmap
CGContextSetTextPosition(*context, 0.0, 5.0);
CGContextSetTextPosition(*context, 0.0, descent);
CTLineDraw(*line, *context);
Copy link
Contributor Author

@1ec5 1ec5 Apr 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new code is pretty robust, even doing away with the hard-coded left, top, and advance metrics that were in the old code. But it falls short of the coretext-hack branch (#7862 (comment)) in that individual characters are still being rasterized in isolation. If we were to enable local glyph rasterizing for all scripts today, that would cause some combining characters to be rendered with unsightly spacing dotted circles (◌) underneath.

coretext-hack didn’t have these artifacts. I think it’s because CTFontDrawGlyphs() already knows the glyphs will be reassembled into a line, whereas CTLineDraw() assumes the glyphs have already been reassembled. I think replacing CTLineDraw() with CTFontDrawGlyphs() would do the trick. Ideally, though, making GlyphManager::generateLocalSDF() operate on an entire string, not individual glyphs, would not only address the dotted circle problem but also weaken our incorrect reliance on a one-to-one mapping between characters and glyphs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using CTFontDrawGlyphs() resulted in the same rendered output, including the dotted circles. It’s definitely because we’re rendering one character at a time.

The coretext-hack branch’s approach does require rendering one glyph at a time using CTFontDrawGlyphs(), but getGlyphDependencies() calculates those glyph IDs based on an entire run of text ahead of time. In fact, that branch redefines GlyphID to pair the numeric glyph ID with a font name, since a given codepoint can be represented by a different glyph depending on the font.

Essentially, we need this code that currently conflates codepoints with glyphs to ask a platform-specific implementation to perform shaping and map these codepoints to actual glyph IDs, and the font name is important for preventing collisions between different glyphs in different fonts that happen to have the same ID:

GlyphIDs& dependencies =
layoutParameters.glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack];
char16_t codePoint = ft.formattedText->getCharCodeAt(j);
dependencies.insert(codePoint);

I can’t think of a less invasive way to solve the combining character issue, because shaping happens so far from glyph rendering in mbgl’s current architecture. The font name could be optional for platforms that don’t perform shaping, but the diff will still be large. Clearly, that refactoring will need to take place in a separate PR.

@1ec5 1ec5 requested a review from julianrex April 14, 2020 15:13
Copy link
Contributor

@julianrex julianrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good (though it's been a while since I played with CoreText)!
A few questions - mostly about when things get cleaned up.

{
fallbackFontNames = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"MGLIdeographicFontFamilyName"];
if (fontFamily_) {
fallbackFontNames = [fallbackFontNames ?: @[] arrayByAddingObjectsFromArray:[@(fontFamily_->c_str()) componentsSeparatedByString:@"\n"]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the idea of using std::vector here. Though could we land this PR as is and address that later?

platform/darwin/src/local_glyph_rasterizer.mm Outdated Show resolved Hide resolved
platform/darwin/src/local_glyph_rasterizer.mm Outdated Show resolved Hide resolved
}

private:
optional<std::string> fontFamily;
CTFontRef fontHandle;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, let's check the performance after this PR.

platform/darwin/src/local_glyph_rasterizer.mm Show resolved Hide resolved
@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch from 603e650 to 12d530a Compare April 14, 2020 23:11
@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch 2 times, most recently from 20c5fb3 to 1281b9f Compare April 20, 2020 16:41
@1ec5
Copy link
Contributor Author

1ec5 commented Apr 23, 2020

Finally figured out the macOS crash. The gory details are in #16253 (comment). 5ed0d85 fixes the crash by changing how the font descriptor’s cascade list is built. Previously, the main font descriptor was created by copying the first font descriptor in what would become the main font descriptor’s cascade list, effectively making the same font appear twice in the cascade list. Now each font appears only as many times as it appears in the font stack or MGLIdeographicFontFamilyName.

I don’t know for sure why it only occurs on the build machine. I can’t reproduce the issue on MacBook Pros running either macOS 10.13.6 or 10.15.4, but the build machine happens to be running macOS 10.14.4.

@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch from 5ed0d85 to b905aef Compare April 23, 2020 04:16
@1ec5
Copy link
Contributor Author

1ec5 commented Apr 23, 2020

After passing for a while, LocalGlyphRasterizer.PingFang has started failing again on iOS as seen previously in #16253 (comment):

<testcase name="PingFang" status="run" result="completed" time="0.03" timestamp="2020-04-23T01:09:11" classname="LocalGlyphRasterizer">
<failure message="/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.0156403 vs 0.015" type="">
/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.0156403 vs 0.015
</failure>
</testcase>

@chloekraw
Copy link
Contributor

After passing for a while, LocalGlyphRasterizer.PingFang has started failing again on iOS

😢

Does this test win some kind of award for flakiness?

@alexshalamov
Copy link
Contributor

alexshalamov commented Apr 23, 2020

Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.0156403 vs 0.015

@1ec5 I checked failures for ios unit runners, and the diff is quite small. If you think rendering result is good enough, let's bump threshold to reasonable value that would satisfy ios / macos tests. What do you think?

Actual Diff Expected
actual diff expected

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 23, 2020

Looking at those differences, I think iOS is choosing PingFangTC-Thin instead of PingFangTC-Regular, but I can’t reproduce the issue in the simulator, maybe because it’s using a macOS build of Core Text under the hood or something. (I’ve been unable to run the tests on a device due to #16259 (comment).)

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 23, 2020

So far we’ve been able to verify on a few devices:

Device OS LocalGlyphRasterizer.PingFang
iPhone 8 iOS 13.4
iPhone 11 iOS 13.3
iPhone XR iOS 13.3

To run on the device:

  1. Apply this patch to your clone of mapbox-gl-native using patch -p1 < pingfang.patch:
    diff --git a/test/ios/ios_test_runner.cpp b/test/ios/ios_test_runner.cpp
    index c99d8c3f30..c1d89ade75 100644
    --- a/test/ios/ios_test_runner.cpp
    +++ b/test/ios/ios_test_runner.cpp
    @@ -11,7 +11,7 @@
     
     EXPORT
     bool TestRunner::startTest(const std::string& basePath) {
    -    std::vector<std::string> arguments = {"mbgl-test-runner", "--gtest_output=xml:" + basePath + "/test/results.xml"};
    +    std::vector<std::string> arguments = {"mbgl-test-runner", "--gtest_filter=LocalGlyphRasterizer.*", "--gtest_output=xml:" + basePath + "/test/results.xml"};
         std::vector<char*> argv;
         for (const auto& arg : arguments) {
             argv.push_back(const_cast<char*>(arg.data()));
    
  2. Run the following commands:
    cd test/
    cmake ../ -G Xcode -DBUILD_SHARED_LIBS=OFF -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DMBGL_IOS_UNIT_TEST=ON -DCMAKE_OSX_ARCHITECTURES=arm64 -DMBGL_WITH_IOS_CCACHE=ON
    open Mapbox\ GL\ Native.xcodeproj
    (substituting your device’s architecture in CMAKE_OSX_ARCHITECTURES)
  3. Delete the FRAMEWORK_SEARCH_PATHS build setting from the UnitTestsAppTests target.
  4. Test the UnitTestsApp scheme.

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 24, 2020

307fba5 relaxes the criteria for matching a font, which should fix the failures we’ve been seeing on iOS.

The following screenshots are from an iPhone 8 running iOS 13.4 and iosapp with the MGLIdeographicFontFamilyName Info.plist key set to either a font family name or a font display name. The screenshots show that mbgl is capable of displaying any font face either explicitly or implicitly through the font family name:

PingFang TC PingFang TC Ultralight PingFang TC Semibold
PingFang TC PingFang TC Ultralight PingFang TC Semibold

mbgl is also capable of displaying downloadable fonts. Hiragino Sans W7 doesn’t come preinstalled on iOS, but it comes from Pages as a downloadable font:

Hiragino Sans Hiragino Sans W3 Hiragino Sans W7
Hiragino Sans Hiragino Sans W3 Hiragino Sans W7

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 24, 2020

That change makes the difference grow even more in the failing test on CI:

<failure message="/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.0160217 vs 0.015" type="">
/Users/distiller/project/test/src/mbgl/test/util.cpp:49 Expected: (pixels / (expected.size.width * expected.size.height)) <= (imageThreshold), actual: 0.0160217 vs 0.015
</failure>

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 24, 2020

In mapbox/mapbox-gl-native-ios#189 (comment), I’ve added a snapshot test in Objective-C powered by MGLMapSnapshotter as an alternative to the C++ test in mbgl that’s much easier to test on a device. To run it:

  1. Run make iproj, which should automatically open ios.xcworkspace.
  2. Set a Test Failure breakpoint.
  3. Switch to the dynamic target, then run the -[MGLMapSnapshotterTests testLocalGlyphRendering] test either using the Test navigator or by going to MGLMapSnapshotterTests.mm and clicking the 🔹 in the line gutter.

As it happens, this snapshot test fails, tripping this assertion, even in an iPhone 8 / iOS 13.4 simulator:

Expected Actual
expected actual

To inspect the results:

  1. When the Test Failure breakpoint gets hit, Quick Look the expectedImage and actualImage variables in the Variables view of the Debug area by selecting those rows and striking the spacebar.
  2. You can then click Open in Preview to compare the images in your favorite image comparison tool (or by flipping back and forth).

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 24, 2020

In the end, I could find no Core Text object model differences between iOS and macOS, yet each glyph run was being rendered more faintly on iOS than on macOS. What we’re seeing here seems to reproduce some of the observations in this Medium post. Like UITextView, we’re relying on an NSAttributedString to draw itself.

For now, I’ve increased the tolerance on the test to 0.0161, as suggested in #16253 (comment), and also disabled the snapshot test on iOS. Although it’s unfortunate that iOS renders the same text differently than other platforms, including macOS, it can still render a noticeable distinction between various font weights, as seen in #16253 (comment).

1ec5 and others added 11 commits April 24, 2020 10:29
PingFangTC-Regular is better than PingFangTC-Thin. There is no font by the name “PingFang”.
…al font rendering

mbgl::Renderer and mbgl::MapSnapshotter can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline.
Take font family names from user defaults before falling back to font family names in Info.plist.
Prefer local fonts that match the names specified in the font stack (from the text-font layout property), except for the last resort fonts that mbgl hard-codes. Fall back to the list of fallback CJK fonts in user defaults, then the fonts passed in through the platform-agnostic interface (that come from Info.plist). Explicitly use the first font descriptor in the cascade list instead of the system default of Helvetica.

Since the font stack can vary from one rasterization operation to the next, avoid caching the resolved font for now. Removed null checks that are unrealistic given the Core Text API contract.
A font descriptor should not be a fallback for itself.
Get glyph metrics from the font in the process of drawing each glyph into a bitmap context. These metrics result in more accurate kerning and better aligned baselines than the previous hard-coded values.

Align iOS/macOS local glyph rasterization test fixture to Qt.
Co-authored-by: Alexander Shalamov <alexander.shalamov@mapbox.com>
@1ec5 1ec5 force-pushed the 1ec5-local-font-names-105 branch from ddd39fb to 3d3b021 Compare April 24, 2020 17:59
@1ec5 1ec5 merged commit 0ccc9f2 into master Apr 24, 2020
@1ec5 1ec5 deleted the 1ec5-local-font-names-105 branch April 24, 2020 20:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
GL JS parity For feature parity with Mapbox GL JS iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS MapKit parity For feature parity with MapKit on iOS or macOS text rendering
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants