summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore1
-rw-r--r--autobuild.xml406
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake9
-rw-r--r--indra/cmake/FindICU4C.cmake33
-rw-r--r--indra/cmake/ICU4C.cmake22
-rw-r--r--indra/cmake/Variables.cmake8
-rw-r--r--indra/cmake/ViewerMiscLibs.cmake2
-rw-r--r--indra/llappearance/llwearabletype.h2
-rw-r--r--indra/llcharacter/llbvhloader.cpp2
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llapp.cpp6
-rw-r--r--indra/llcommon/llbase64.cpp4
-rw-r--r--indra/llcommon/llcoros.h2
-rw-r--r--indra/llcommon/lldefs.h62
-rw-r--r--indra/llcommon/lldependencies.cpp2
-rw-r--r--indra/llcommon/lldependencies.h4
-rw-r--r--indra/llcommon/llerror.cpp2
-rw-r--r--indra/llcommon/llerrorthread.cpp2
-rw-r--r--indra/llcommon/lleventdispatcher.cpp24
-rw-r--r--indra/llcommon/llinstancetracker.h4
-rw-r--r--indra/llcommon/llkeybind.cpp39
-rw-r--r--indra/llcommon/llkeybind.h4
-rw-r--r--indra/llcommon/llleap.cpp6
-rw-r--r--indra/llcommon/llmd5.cpp34
-rw-r--r--indra/llcommon/llmd5.h8
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp4
-rw-r--r--indra/llcommon/llmetricperformancetester.h4
-rw-r--r--indra/llcommon/llmortician.cpp4
-rw-r--r--indra/llcommon/llmortician.h4
-rw-r--r--indra/llcommon/llqueuedthread.cpp17
-rw-r--r--indra/llcommon/llqueuedthread.h10
-rw-r--r--indra/llcommon/llrun.cpp2
-rw-r--r--indra/llcommon/llrun.h2
-rw-r--r--indra/llcommon/llsd.cpp120
-rw-r--r--indra/llcommon/llsd.h32
-rw-r--r--indra/llcommon/llsdserialize.cpp88
-rw-r--r--indra/llcommon/llsdserialize.h22
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp10
-rw-r--r--indra/llcommon/llsingleton.h2
-rw-r--r--indra/llcommon/llstreamtools.cpp40
-rw-r--r--indra/llcommon/llstring.cpp36
-rw-r--r--indra/llcommon/llstring.h4
-rw-r--r--indra/llcommon/llsys.cpp14
-rw-r--r--indra/llcommon/llsys.h2
-rw-r--r--indra/llcommon/llsys_objc.h6
-rw-r--r--indra/llcommon/llsys_objc.mm4
-rw-r--r--indra/llcommon/llthreadsafequeue.h6
-rw-r--r--indra/llcommon/lltimer.cpp11
-rw-r--r--indra/llcommon/lltrace.cpp2
-rw-r--r--indra/llcommon/lltrace.h4
-rw-r--r--indra/llcommon/lltraceaccumulators.cpp4
-rw-r--r--indra/llcommon/lltracerecording.cpp69
-rw-r--r--indra/llcommon/lltracerecording.h100
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp2
-rw-r--r--indra/llcommon/lltracethreadrecorder.h2
-rw-r--r--indra/llcommon/llworkerthread.cpp4
-rw-r--r--indra/llcommon/llworkerthread.h2
-rw-r--r--indra/llcommon/stdtypes.h106
-rw-r--r--indra/llcommon/tests/lleventdispatcher_test.cpp2
-rw-r--r--indra/llcommon/tests/llsingleton_test.cpp6
-rw-r--r--indra/llcommon/threadsafeschedule.h2
-rw-r--r--indra/llcorehttp/bufferarray.cpp6
-rw-r--r--indra/llimage/llimageworker.cpp2
-rw-r--r--indra/llimage/llimageworker.h2
-rw-r--r--indra/llinventory/llfoldertype.cpp2
-rw-r--r--indra/llinventory/llinventorysettings.cpp2
-rw-r--r--indra/llinventory/llsettingssky.cpp119
-rw-r--r--indra/llinventory/llsettingswater.cpp36
-rw-r--r--indra/llmath/llvolume.cpp4
-rw-r--r--indra/llmessage/llcircuit.cpp2
-rw-r--r--indra/llmessage/llexperiencecache.h2
-rw-r--r--indra/llmessage/llproxy.h2
-rw-r--r--indra/llrender/CMakeLists.txt2
-rw-r--r--indra/llrender/llfontbitmapcache.cpp163
-rw-r--r--indra/llrender/llfontbitmapcache.h42
-rw-r--r--indra/llrender/llfontfreetype.cpp278
-rw-r--r--indra/llrender/llfontfreetype.h31
-rw-r--r--indra/llrender/llfontfreetypesvg.cpp205
-rw-r--r--indra/llrender/llfontfreetypesvg.h54
-rw-r--r--indra/llrender/llfontgl.cpp84
-rw-r--r--indra/llrender/llfontgl.h18
-rw-r--r--indra/llrender/llfontregistry.cpp165
-rw-r--r--indra/llrender/llfontregistry.h43
-rw-r--r--indra/llrender/llgl.cpp2
-rw-r--r--indra/llui/CMakeLists.txt4
-rw-r--r--indra/llui/llbutton.cpp3
-rw-r--r--indra/llui/llemojidictionary.cpp200
-rw-r--r--indra/llui/llemojidictionary.h73
-rw-r--r--indra/llui/llemojihelper.cpp166
-rw-r--r--indra/llui/llemojihelper.h64
-rw-r--r--indra/llui/llfloater.cpp31
-rw-r--r--indra/llui/llfloater.h4
-rw-r--r--indra/llui/llfolderviewitem.cpp6
-rw-r--r--indra/llui/llmenugl.cpp3
-rw-r--r--indra/llui/llnotifications.cpp2
-rw-r--r--indra/llui/llnotifications.h6
-rw-r--r--indra/llui/llspellcheck.h2
-rw-r--r--indra/llui/lltextbase.cpp93
-rw-r--r--indra/llui/lltextbase.h22
-rw-r--r--indra/llui/lltexteditor.cpp55
-rw-r--r--indra/llui/lltexteditor.h7
-rw-r--r--indra/llui/lluictrl.h2
-rw-r--r--indra/llui/llview.cpp6
-rw-r--r--indra/llui/llviewquery.h12
-rw-r--r--indra/llxml/llcontrol.cpp4
-rw-r--r--indra/newview/CMakeLists.txt10
-rw-r--r--indra/newview/fonts/DejaVu-license.txt99
-rw-r--r--indra/newview/fonts/DejaVuSans-Bold.ttfbin573136 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-BoldOblique.ttfbin524056 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-Oblique.ttfbin523804 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans.ttfbin622280 -> 0 bytes
-rw-r--r--indra/newview/fonts/DejaVuSansMono.ttfbin321524 -> 0 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_zh.nsibin10144 -> 10154 bytes
-rw-r--r--indra/newview/llagent.cpp2
-rw-r--r--indra/newview/llappviewer.cpp15
-rw-r--r--indra/newview/llautoreplace.h2
-rw-r--r--indra/newview/llchannelmanager.h2
-rw-r--r--indra/newview/llchathistory.cpp2
-rw-r--r--indra/newview/llchicletbar.h4
-rw-r--r--indra/newview/llconversationlog.h10
-rw-r--r--indra/newview/llexpandabletextbox.cpp2
-rw-r--r--indra/newview/llfeaturemanager.h2
-rw-r--r--indra/newview/llfloaterlandholdings.cpp32
-rw-r--r--indra/newview/llfloateruipreview.cpp8
-rw-r--r--indra/newview/llfriendcard.h2
-rw-r--r--indra/newview/llgesturemgr.h4
-rw-r--r--indra/newview/llhudrender.cpp2
-rw-r--r--indra/newview/llimagefiltersmanager.h2
-rw-r--r--indra/newview/llimview.h2
-rw-r--r--indra/newview/llmeshrepository.cpp2
-rw-r--r--indra/newview/llmodelpreview.cpp5
-rw-r--r--indra/newview/llmutelist.h2
-rwxr-xr-xindra/newview/llnavigationbar.h8
-rw-r--r--indra/newview/lloutfitobserver.h2
-rw-r--r--indra/newview/llpanelemojicomplete.cpp321
-rw-r--r--indra/newview/llpanelemojicomplete.h115
-rw-r--r--indra/newview/llpanelnearbymedia.cpp4
-rw-r--r--indra/newview/llpaneltopinfobar.h6
-rw-r--r--indra/newview/llpathfindingnavmesh.cpp2
-rw-r--r--indra/newview/llpathfindingpathtool.h18
-rw-r--r--indra/newview/llproductinforequest.h2
-rw-r--r--indra/newview/llrecentpeople.h2
-rw-r--r--indra/newview/llsceneview.cpp4
-rw-r--r--indra/newview/llselectmgr.cpp7
-rw-r--r--indra/newview/llsettingsvo.cpp32
-rw-r--r--indra/newview/llspeakers.h4
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp4
-rw-r--r--indra/newview/llsprite.cpp5
-rw-r--r--indra/newview/llstartup.cpp2
-rw-r--r--indra/newview/lltexturecache.cpp4
-rw-r--r--indra/newview/lltexturecache.h2
-rw-r--r--indra/newview/lltexturefetch.cpp8
-rw-r--r--indra/newview/lltexturefetch.h4
-rw-r--r--indra/newview/lltextureview.cpp4
-rw-r--r--indra/newview/lltoolbrush.h20
-rw-r--r--indra/newview/lltoolcomp.h72
-rw-r--r--indra/newview/lltooldraganddrop.h12
-rw-r--r--indra/newview/lltoolface.h10
-rw-r--r--indra/newview/lltoolfocus.h14
-rw-r--r--indra/newview/lltoolindividual.h8
-rw-r--r--indra/newview/lltoolobjpicker.h14
-rw-r--r--indra/newview/lltoolpie.h32
-rw-r--r--indra/newview/lltoolpipette.h8
-rw-r--r--indra/newview/lltoolselectland.h16
-rw-r--r--indra/newview/llversioninfo.h2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerhelp.h10
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermediafocus.h16
-rw-r--r--indra/newview/llviewermenu.cpp4
-rw-r--r--indra/newview/llviewermessage.cpp2
-rw-r--r--indra/newview/llviewerobjectlist.cpp3
-rw-r--r--indra/newview/llviewerparcelaskplay.h4
-rw-r--r--indra/newview/llviewerparcelmedia.h2
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.h2
-rw-r--r--indra/newview/llviewertexturelist.h6
-rw-r--r--indra/newview/llviewerwindow.cpp2
-rw-r--r--indra/newview/llvoicechannel.h22
-rw-r--r--indra/newview/llvoicevivox.h144
-rw-r--r--indra/newview/llvosurfacepatch.cpp7
-rw-r--r--indra/newview/llvovolume.cpp13
-rw-r--r--indra/newview/llwearableitemslist.h6
-rw-r--r--indra/newview/llwindebug.h4
-rwxr-xr-xindra/newview/llworldmapview.cpp3
-rw-r--r--indra/newview/skins/default/xui/en/emoji_characters.xml10955
-rw-r--r--indra/newview/skins/default/xui/en/floater_emoji_complete.xml28
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml2
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml26
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_editor.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/emoji_complete.xml10
-rwxr-xr-xindra/newview/viewer_manifest.py6
193 files changed, 14320 insertions, 1433 deletions
diff --git a/.gitignore b/.gitignore
index 80eca667df..ab5f43b352 100755
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@ indra/newview/dbghelp.dll
indra/newview/filters.xml
indra/newview/fmod.dll
indra/newview/fmod.log
+indra/newview/fonts
indra/newview/mozilla-theme
indra/newview/mozilla-universal-darwin.tgz
indra/newview/pilot.txt
diff --git a/autobuild.xml b/autobuild.xml
index d09d862f1b..c221fcdb19 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -118,9 +118,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>fedc8d63856f534b6098102e059dc548</string>
+ <string>cae490999f05151e3a048b00d64237bb</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87776/805857/boost-1.72-darwin64-563847.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109513/952781/boost-1.72-darwin64-577704.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -142,9 +142,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>6cc9fb4ca21365c4470a3e516544ba71</string>
+ <string>aa0f955996442b8d7097447de1f5a9fe</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87784/805850/boost-1.72-windows-563847.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109516/952793/boost-1.72-windows-577704.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -154,9 +154,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>0c526efc3f8825cd25cdf635e238fab3</string>
+ <string>d3738a7ea84e2569017ae0237526da36</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87783/805851/boost-1.72-windows64-563847.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109515/952797/boost-1.72-windows64-577704.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
@@ -236,9 +236,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>a880dfc15fcb330baf548a85324cd88a</string>
+ <string>df05eee28649996c78a47dd054de2a47</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104133/913090/colladadom-2.3.574693-darwin64-574693.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112764/977018/colladadom-2.3.579218-darwin64-579218.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -260,9 +260,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>7e84441d9c7cf019a7bdc7b818b16c27</string>
+ <string>6752b4f098a522bb22b6334cdfba7614</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104112/912957/colladadom-2.3.574693-windows-574693.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112771/977087/colladadom-2.3.579224-windows-579224.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -272,16 +272,16 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>2eaffbb8a93b03a732d3c47055a8efcb</string>
+ <string>81de6dc4a79b547a25d0040370c42fec</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/104135/913103/colladadom-2.3.574693-windows64-574693.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112770/977082/colladadom-2.3.579224-windows64-579224.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
- <string>2.3.574693</string>
+ <string>2.3.579218</string>
</map>
<key>cubemaptoequirectangular</key>
<map>
@@ -307,31 +307,29 @@
<key>name</key>
<string>darwin64</string>
</map>
- <key>windows</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>b5ea7097ae10037024b0c2b3df9812b5</string>
+ <string>ac54672e0b38f52726f5c99047c913e4</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89307/815434/cubemaptoequirectangular-1.1.0-windows-564841.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2</string>
</map>
- <key>name</key>
- <string>windows</string>
</map>
- <key>windows64</key>
+ <key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>ac54672e0b38f52726f5c99047c913e4</string>
+ <string>b5ea7097ae10037024b0c2b3df9812b5</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89307/815434/cubemaptoequirectangular-1.1.0-windows-564841.tar.bz2</string>
</map>
<key>name</key>
- <string>windows64</string>
+ <string>windows</string>
</map>
- <key>linux64</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
@@ -340,6 +338,8 @@
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2</string>
</map>
+ <key>name</key>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
@@ -708,9 +708,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>8865739d8e530199dacb3c3042c1bc01</string>
+ <string>9cbcd452efa877fb8550c8c9b092b465</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87777/805782/freetype-2.4.4.563848-darwin64-563848.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111566/967515/freetype-2.12.1.578664-darwin64-578664.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -732,9 +732,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>c0b3601e997553931cadc7d7ee94168b</string>
+ <string>f3d7b72d10c162c9a8aa2ac4443ac52f</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87779/805814/freetype-2.4.4.563848-windows-563848.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111571/967545/freetype-2.12.1.578664-windows-578664.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -744,16 +744,16 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>e98e1e088cdcd20442e05e9abecdadf9</string>
+ <string>96d3689043e939ae424060a8b498be1f</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87778/805815/freetype-2.4.4.563848-windows64-563848.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/111570/967535/freetype-2.12.1.578664-windows64-578664.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
- <string>2.4.4.563848</string>
+ <string>2.12.1.578664</string>
</map>
<key>glext</key>
<map>
@@ -870,9 +870,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>11d0794582e91a57f6524ad345f2399d</string>
+ <string>772d3ae9d4a1d3e36eadcfb4b81ca47f</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87791/805924/googlemock-1.7.0.563853-darwin64-563853.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109950/956085/googlemock-1.7.0.577943-darwin64-577943.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -894,9 +894,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>7d267050970ec6e28749178597bc8af0</string>
+ <string>61df276991917f710d27cb578d9df25b</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87793/805930/googlemock-1.7.0.563853-windows-563853.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109953/956105/googlemock-1.7.0.577943-windows-577943.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -906,16 +906,16 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>27638c692f0ec6121e54bf75f2d45e49</string>
+ <string>cc1307e11133755eac29ab04ef240092</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87792/805936/googlemock-1.7.0.563853-windows64-563853.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109952/956106/googlemock-1.7.0.577943-windows64-577943.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
- <string>1.7.0.563853</string>
+ <string>1.7.0.577943</string>
</map>
<key>gstreamer</key>
<map>
@@ -1039,6 +1039,62 @@
<key>version</key>
<string>2012.1-2</string>
</map>
+ <key>icu4c</key>
+ <map>
+ <key>canonical_repo</key>
+ <string>https://bitbucket.org/lindenlab/3p-icu4c</string>
+ <key>copyright</key>
+ <string>Copyright (c) 1995-2011 International Business Machines Corporation and others &lt;http://source.icu-project.org&gt;</string>
+ <key>description</key>
+ <string>ICU is a mature, widely used set of C/C++ and Java libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms and between C/C++ and Java software.</string>
+ <key>license</key>
+ <string>ICU, permissive non-copyleft free software license</string>
+ <key>license_file</key>
+ <string>LICENSES/icu.txt</string>
+ <key>name</key>
+ <string>icu4c</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7f147ae0410f705f846b981498898392</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/112850/977592/icu4c-4.8.1-darwin64-579264.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>08749d1f7f0a96b1951eecdae5dc11ba</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109679/954178/icu4c-4.8.1-windows-577789.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>98bca5c137e6d47c5b57827e156b1857</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109678/954182/icu4c-4.8.1-windows64-577789.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>4.8.1</string>
+ </map>
<key>jpegencoderbasic</key>
<map>
<key>copyright</key>
@@ -1063,31 +1119,29 @@
<key>name</key>
<string>darwin64</string>
</map>
- <key>windows</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>0a376676dbb43fdd0c81ffdfbc5e6f81</string>
+ <string>e70898903475d8ac2e81ff33278fc987</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89308/815432/jpegencoderbasic-1.0-windows-564842.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2</string>
</map>
- <key>name</key>
- <string>windows</string>
</map>
- <key>windows64</key>
+ <key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e70898903475d8ac2e81ff33278fc987</string>
+ <string>0a376676dbb43fdd0c81ffdfbc5e6f81</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89308/815432/jpegencoderbasic-1.0-windows-564842.tar.bz2</string>
</map>
<key>name</key>
- <string>windows64</string>
+ <string>windows</string>
</map>
- <key>linux64</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
@@ -1096,6 +1150,8 @@
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2</string>
</map>
+ <key>name</key>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
@@ -1948,6 +2004,74 @@
<key>version</key>
<string>3.0.2.569217</string>
</map>
+ <key>nanosvg</key>
+ <map>
+ <key>canonical_repo</key>
+ <string>https://bitbucket.org/lindenlab/3p-nanosvg</string>
+ <key>copyright</key>
+ <string>Copyright (c) 2013-14 Mikko Mononen</string>
+ <key>description</key>
+ <string>NanoSVG is a simple single-header-file SVG parser and rasterizer</string>
+ <key>license</key>
+ <string>Zlib</string>
+ <key>license_file</key>
+ <string>LICENSES/nanosvg.txt</string>
+ <key>name</key>
+ <string>nanosvg</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>bee6bf71cec184ab26c89c486fc5f427</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109526/952883/nanosvg-2022.09.27-darwin64-577709.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>linux</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>c5a2ae5ecc8ade5a85b674e4426d6403</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107186/935576/nanosvg-2022.09.27-linux-576467.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>b7d1baa8003f64bed4efc2c163ee7e26</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109529/952902/nanosvg-2022.09.27-windows-577709.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>b8b51ad6b65be5bbc1470ee939c6bfae</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109528/952895/nanosvg-2022.09.27-windows64-577709.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>2022.09.27</string>
+ </map>
<key>nghttp2</key>
<map>
<key>copyright</key>
@@ -2484,31 +2608,29 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>name</key>
<string>darwin64</string>
</map>
- <key>windows</key>
+ <key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>e1303fb9f2242a79aee5fd9f97726ace</string>
+ <string>46edf0f55417f8ef0d33a5c007bc3644</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89311/815452/threejs-0.132.2-windows-564843.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2</string>
</map>
- <key>name</key>
- <string>windows</string>
</map>
- <key>windows64</key>
+ <key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>46edf0f55417f8ef0d33a5c007bc3644</string>
+ <string>e1303fb9f2242a79aee5fd9f97726ace</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89311/815452/threejs-0.132.2-windows-564843.tar.bz2</string>
</map>
<key>name</key>
- <string>windows64</string>
+ <string>windows</string>
</map>
- <key>linux64</key>
+ <key>windows64</key>
<map>
<key>archive</key>
<map>
@@ -2517,6 +2639,8 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2</string>
</map>
+ <key>name</key>
+ <string>windows64</string>
</map>
</map>
<key>version</key>
@@ -2682,6 +2806,60 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>0.9.4</string>
</map>
+ <key>viewer-fonts</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright various</string>
+ <key>description</key>
+ <string>Viewer fonts</string>
+ <key>license</key>
+ <string>Various open source</string>
+ <key>license_file</key>
+ <string>LICENSES/fonts.txt</string>
+ <key>name</key>
+ <string>viewer-fonts</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>d47e0ed35dad11f0a5dc821758e2ae46</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109658/953998/viewer_fonts-1.577782-darwin64-577782.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7dc39bb7cd8133d251eaff9c9e16bdfd</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109660/954010/viewer_fonts-1.577782-windows-577782.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>86134368c16c7d685156403e15a7cbcd</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/109659/954009/viewer_fonts-1.577782-windows64-577782.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>1.577782</string>
+ </map>
<key>viewer-manager</key>
<map>
<key>copyright</key>
@@ -3021,18 +3199,25 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>name</key>
<string>common</string>
</map>
- <key>linux64</key>
+ <key>darwin64</key>
<map>
<key>build_directory</key>
- <string>build-linux-x86_64</string>
+ <string>build-darwin-x86_64</string>
<key>configurations</key>
<map>
- <key>Release</key>
+ <key>RelWithDebInfo</key>
<map>
<key>build</key>
<map>
<key>command</key>
- <string>ninja</string>
+ <string>xcodebuild</string>
+ <key>options</key>
+ <array>
+ <string>-configuration</string>
+ <string>RelWithDebInfo</string>
+ <string>-project</string>
+ <string>SecondLife.xcodeproj</string>
+ </array>
</map>
<key>configure</key>
<map>
@@ -3043,53 +3228,40 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>options</key>
<array>
<string>-G</string>
- <string>Ninja</string>
- <string>-DLL_TESTS=Off</string>
+ <string>Xcode</string>
</array>
</map>
<key>default</key>
<string>True</string>
<key>name</key>
- <string>Release</string>
+ <string>RelWithDebInfo</string>
</map>
- <key>ReleaseOS</key>
+ <key>RelWithDebInfoOS</key>
<map>
<key>build</key>
<map>
<key>command</key>
- <string>ninja</string>
+ <string>xcodebuild</string>
+ <key>options</key>
+ <array>
+ <string>-configuration</string>
+ <string>RelWithDebInfo</string>
+ <string>-project</string>
+ <string>SecondLife.xcodeproj</string>
+ </array>
</map>
<key>configure</key>
<map>
<key>options</key>
<array>
<string>-G</string>
- <string>Ninja</string>
- <string>-DLL_TESTS=Off</string>
+ <string>Xcode</string>
</array>
</map>
<key>name</key>
- <string>ReleaseOS</string>
- </map>
- <key>default</key>
- <map>
- <key>build</key>
- <map>
- </map>
- <key>name</key>
- <string>default</string>
+ <string>RelWithDebInfoOS</string>
</map>
- </map>
- <key>name</key>
- <string>linux64</string>
- </map>
- <key>darwin64</key>
- <map>
- <key>build_directory</key>
- <string>build-darwin-x86_64</string>
- <key>configurations</key>
- <map>
- <key>RelWithDebInfo</key>
+ <key>Release</key>
<map>
<key>build</key>
<map>
@@ -3098,7 +3270,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>options</key>
<array>
<string>-configuration</string>
- <string>RelWithDebInfo</string>
+ <string>Release</string>
<string>-project</string>
<string>SecondLife.xcodeproj</string>
</array>
@@ -3115,12 +3287,10 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<string>Xcode</string>
</array>
</map>
- <key>default</key>
- <string>True</string>
<key>name</key>
- <string>RelWithDebInfo</string>
+ <string>Release</string>
</map>
- <key>RelWithDebInfoOS</key>
+ <key>ReleaseOS</key>
<map>
<key>build</key>
<map>
@@ -3129,7 +3299,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>options</key>
<array>
<string>-configuration</string>
- <string>RelWithDebInfo</string>
+ <string>Release</string>
<string>-project</string>
<string>SecondLife.xcodeproj</string>
</array>
@@ -3143,21 +3313,24 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
</array>
</map>
<key>name</key>
- <string>RelWithDebInfoOS</string>
+ <string>ReleaseOS</string>
</map>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>linux64</key>
+ <map>
+ <key>build_directory</key>
+ <string>build-linux-x86_64</string>
+ <key>configurations</key>
+ <map>
<key>Release</key>
<map>
<key>build</key>
<map>
<key>command</key>
- <string>xcodebuild</string>
- <key>options</key>
- <array>
- <string>-configuration</string>
- <string>Release</string>
- <string>-project</string>
- <string>SecondLife.xcodeproj</string>
- </array>
+ <string>ninja</string>
</map>
<key>configure</key>
<map>
@@ -3168,9 +3341,12 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>options</key>
<array>
<string>-G</string>
- <string>Xcode</string>
+ <string>Ninja</string>
+ <string>-DLL_TESTS=Off</string>
</array>
</map>
+ <key>default</key>
+ <string>True</string>
<key>name</key>
<string>Release</string>
</map>
@@ -3179,29 +3355,31 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>build</key>
<map>
<key>command</key>
- <string>xcodebuild</string>
- <key>options</key>
- <array>
- <string>-configuration</string>
- <string>Release</string>
- <string>-project</string>
- <string>SecondLife.xcodeproj</string>
- </array>
+ <string>ninja</string>
</map>
<key>configure</key>
<map>
<key>options</key>
<array>
<string>-G</string>
- <string>Xcode</string>
+ <string>Ninja</string>
+ <string>-DLL_TESTS=Off</string>
</array>
</map>
<key>name</key>
<string>ReleaseOS</string>
</map>
+ <key>default</key>
+ <map>
+ <key>build</key>
+ <map>
+ </map>
+ <key>name</key>
+ <string>default</string>
+ </map>
</map>
<key>name</key>
- <string>darwin64</string>
+ <string>linux64</string>
</map>
<key>windows</key>
<map>
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 1ee2a621f2..a4da822538 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -63,6 +63,15 @@ if(WINDOWS)
uriparser.dll
)
+ # ICU4C (same filenames for 32 and 64 bit builds)
+ set(release_files ${release_files} icudt48.dll)
+ set(release_files ${release_files} icuin48.dll)
+ set(release_files ${release_files} icuio48.dll)
+ set(release_files ${release_files} icule48.dll)
+ set(release_files ${release_files} iculx48.dll)
+ set(release_files ${release_files} icutu48.dll)
+ set(release_files ${release_files} icuuc48.dll)
+
# OpenSSL
if(ADDRESS_SIZE EQUAL 64)
set(release_files ${release_files} libcrypto-1_1-x64.dll)
diff --git a/indra/cmake/FindICU4C.cmake b/indra/cmake/FindICU4C.cmake
new file mode 100644
index 0000000000..327d761a88
--- /dev/null
+++ b/indra/cmake/FindICU4C.cmake
@@ -0,0 +1,33 @@
+# -*- cmake -*-
+
+# - Find ICU4C
+# This module defines
+# ICU4C_INCLUDE_DIR, where to find headers
+# ICU4C_LIBRARY, the library needed to use ICU4C.
+# ICU4C_FOUND, If false, do not try to use ICU4C.
+
+find_path(ICU4C_INCLUDE_DIR uchar.h
+ PATH_SUFFIXES unicode
+ )
+
+set(ICU4C_NAMES ${ICU4C_NAMES} icuuc)
+find_library(ICU4C_LIBRARY
+ NAMES ${ICU4C_NAMES}
+ )
+
+if (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR)
+ set(ICU4C_FOUND "YES")
+else (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR)
+ set(ICU4C_FOUND "NO")
+endif (ICU4C_LIBRARY AND ICU4C_INCLUDE_DIR)
+
+if (ICU4C_FOUND)
+ message(STATUS "Found ICU4C: Library in '${ICU4C_LIBRARY}' and header in '${ICU4C_INCLUDE_DIR}' ")
+else (ICU4C_FOUND)
+ message(FATAL_ERROR " * * *\nCould not find ICU4C library! * * *")
+endif (ICU4C_FOUND)
+
+mark_as_advanced(
+ ICU4C_LIBRARY
+ ICU4C_INCLUDE_DIR
+ )
diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake
new file mode 100644
index 0000000000..b51087e0e7
--- /dev/null
+++ b/indra/cmake/ICU4C.cmake
@@ -0,0 +1,22 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+set(ICU4C_FIND_QUIETLY ON)
+set(ICU4C_FIND_REQUIRED ON)
+
+if (USESYSTEMLIBS)
+ include(FindICU4C)
+else (USESYSTEMLIBS)
+ use_prebuilt_binary(icu4c)
+ if (WINDOWS)
+ set(ICU4C_LIBRARY icuuc)
+ elseif(DARWIN)
+ set(ICU4C_LIBRARY icuuc)
+ #elseif(LINUX)
+ # set(ICU4C_LIBRARY ...)
+ else()
+ message(FATAL_ERROR "Invalid platform")
+ endif()
+ set(ICU4C_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/unicode)
+ use_prebuilt_binary(dictionaries)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 653db2069a..35f5a8216a 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -191,9 +191,15 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# development must be done after the build as we do in viewer_manifest.py for
# released builds
# https://stackoverflow.com/a/54296008
+ # With Xcode 14.1, apparently you must take drastic steps to prevent
+ # implicit signing.
+ set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED NO)
+ set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO)
# "-" represents "Sign to Run Locally" and empty string represents "Do Not Sign"
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
-
+ set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "")
+ set(CMAKE_XCODE_ATTRIBUTE_DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING YES)
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION NO)
set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
string(REPLACE "AMD64" "x86_64" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 00f8b77106..7eed456833 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -18,3 +18,5 @@ endif()
use_prebuilt_binary(slvoice)
+use_prebuilt_binary(nanosvg)
+use_prebuilt_binary(viewer-fonts)
diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h
index 793a33cc87..1fbe19ddd1 100644
--- a/indra/llappearance/llwearabletype.h
+++ b/indra/llappearance/llwearabletype.h
@@ -37,7 +37,7 @@ class LLWearableType : public LLParamSingleton<LLWearableType>
{
LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans);
~LLWearableType();
- void initSingleton();
+ void initSingleton() override;
public:
enum EType
{
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index c38614b0b4..07f9828bb4 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -1365,7 +1365,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
dp.packS32(joint->mNumRotKeys, "num_rot_keys");
LLQuaternion::Order order = bvhStringToOrder( joint->mOrder );
- S32 outcount = 0;
S32 frame = 0;
for ( ki = joint->mKeys.begin();
ki != joint->mKeys.end();
@@ -1433,7 +1432,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
dp.packU16(x, "rot_angle_x");
dp.packU16(y, "rot_angle_y");
dp.packU16(z, "rot_angle_z");
- outcount++;
frame++;
}
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 3d073b009c..620b2c636c 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -3,6 +3,7 @@
project(llcommon)
include(00-Common)
+include(ICU4C)
include(LLCommon)
include(bugsplat)
include(Linking)
@@ -264,6 +265,7 @@ add_library (llcommon ${llcommon_SOURCE_FILES})
target_link_libraries(
llcommon
+ ${ICU4C_LIBRARY}
ll::apr
ll::expat
ll::jsoncpp
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 3ff8d16bbb..d839b19c99 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -862,14 +862,14 @@ bool unix_post_minidump_callback(const char *dump_dir,
// heap allocations in a crash handler.
// path format: <dump_dir>/<minidump_id>.dmp
- int dirPathLength = strlen(dump_dir);
- int idLength = strlen(minidump_id);
+ auto dirPathLength = strlen(dump_dir);
+ auto idLength = strlen(minidump_id);
// The path must not be truncated.
llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
char * path = LLApp::instance()->getMiniDumpFilename();
- S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
+ auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
strncpy(path, dump_dir, remaining);
remaining -= dirPathLength;
path += dirPathLength;
diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp
index 4e82cf7f20..bb85fe32a3 100644
--- a/indra/llcommon/llbase64.cpp
+++ b/indra/llcommon/llbase64.cpp
@@ -42,7 +42,7 @@ std::string LLBase64::encode(const U8* input, size_t input_size)
&& input_size > 0)
{
// Yes, it returns int.
- int b64_buffer_length = apr_base64_encode_len(input_size);
+ int b64_buffer_length = apr_base64_encode_len(narrow(input_size));
char* b64_buffer = new char[b64_buffer_length];
// This is faster than apr_base64_encode() if you know
@@ -52,7 +52,7 @@ std::string LLBase64::encode(const U8* input, size_t input_size)
b64_buffer_length = apr_base64_encode_binary(
b64_buffer,
input,
- input_size);
+ narrow(input_size));
output.assign(b64_buffer);
delete[] b64_buffer;
}
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 966ce03296..fd878f20ad 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -92,7 +92,7 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
LLSINGLETON(LLCoros);
~LLCoros();
- void cleanupSingleton();
+ void cleanupSingleton() override;
public:
/// The viewer's use of the term "coroutine" became deeply embedded before
/// the industry term "fiber" emerged to distinguish userland threads from
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 5a4b8325f4..5c46f6a796 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -28,6 +28,7 @@
#define LL_LLDEFS_H
#include "stdtypes.h"
+#include <type_traits>
// Often used array indices
const U32 VX = 0;
@@ -168,80 +169,79 @@ const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luc
// llclampb(a) // clamps a to [0 .. 255]
//
-template <class LLDATATYPE>
-inline LLDATATYPE llmax(const LLDATATYPE& d1, const LLDATATYPE& d2)
+template <typename T1, typename T2>
+inline auto llmax(T1 d1, T2 d2)
{
return (d1 > d2) ? d1 : d2;
}
-template <class LLDATATYPE>
-inline LLDATATYPE llmax(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3)
+template <typename T1, typename T2, typename T3>
+inline auto llmax(T1 d1, T2 d2, T3 d3)
{
- LLDATATYPE r = llmax(d1,d2);
+ auto r = llmax(d1,d2);
return llmax(r, d3);
}
-template <class LLDATATYPE>
-inline LLDATATYPE llmax(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3, const LLDATATYPE& d4)
+template <typename T1, typename T2, typename T3, typename T4>
+inline auto llmax(T1 d1, T2 d2, T3 d3, T4 d4)
{
- LLDATATYPE r1 = llmax(d1,d2);
- LLDATATYPE r2 = llmax(d3,d4);
+ auto r1 = llmax(d1,d2);
+ auto r2 = llmax(d3,d4);
return llmax(r1, r2);
}
-template <class LLDATATYPE>
-inline LLDATATYPE llmin(const LLDATATYPE& d1, const LLDATATYPE& d2)
+template <typename T1, typename T2>
+inline auto llmin(T1 d1, T2 d2)
{
return (d1 < d2) ? d1 : d2;
}
-template <class LLDATATYPE>
-inline LLDATATYPE llmin(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3)
+template <typename T1, typename T2, typename T3>
+inline auto llmin(T1 d1, T2 d2, T3 d3)
{
- LLDATATYPE r = llmin(d1,d2);
+ auto r = llmin(d1,d2);
return (r < d3 ? r : d3);
}
-template <class LLDATATYPE>
-inline LLDATATYPE llmin(const LLDATATYPE& d1, const LLDATATYPE& d2, const LLDATATYPE& d3, const LLDATATYPE& d4)
+template <typename T1, typename T2, typename T3, typename T4>
+inline auto llmin(T1 d1, T2 d2, T3 d3, T4 d4)
{
- LLDATATYPE r1 = llmin(d1,d2);
- LLDATATYPE r2 = llmin(d3,d4);
+ auto r1 = llmin(d1,d2);
+ auto r2 = llmin(d3,d4);
return llmin(r1, r2);
}
-template <class LLDATATYPE>
-inline LLDATATYPE llclamp(const LLDATATYPE& a, const LLDATATYPE& minval, const LLDATATYPE& maxval)
+template <typename A, typename MIN, typename MAX>
+inline A llclamp(A a, MIN minval, MAX maxval)
{
- if ( a < minval )
+ A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) };
+ if ( a < aminval )
{
- return minval;
+ return aminval;
}
- else if ( a > maxval )
+ else if ( a > amaxval )
{
- return maxval;
+ return amaxval;
}
return a;
}
template <class LLDATATYPE>
-inline LLDATATYPE llclampf(const LLDATATYPE& a)
+inline LLDATATYPE llclampf(LLDATATYPE a)
{
- return llmin(llmax(a, (LLDATATYPE)0), (LLDATATYPE)1);
+ return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
template <class LLDATATYPE>
-inline LLDATATYPE llclampb(const LLDATATYPE& a)
+inline LLDATATYPE llclampb(LLDATATYPE a)
{
- return llmin(llmax(a, (LLDATATYPE)0), (LLDATATYPE)255);
+ return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
template <class LLDATATYPE>
inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs)
{
- LLDATATYPE tmp = lhs;
- lhs = rhs;
- rhs = tmp;
+ std::swap(lhs, rhs);
}
#endif // LL_LLDEFS_H
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
index 0d5757effd..db546c5c3b 100644
--- a/indra/llcommon/lldependencies.cpp
+++ b/indra/llcommon/lldependencies.cpp
@@ -42,7 +42,7 @@
// other Linden headers
#include "llexception.h"
-LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
+LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(size_t vertices, const EdgeList& edges) const
{
// Construct a Boost Graph Library graph according to the constraints
// we've collected. It seems as though we ought to be able to capture
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index db2bbab8b0..950af4a4ad 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -126,7 +126,7 @@ public:
protected:
typedef std::vector< std::pair<std::size_t, std::size_t> > EdgeList;
typedef std::vector<std::size_t> VertexList;
- VertexList topo_sort(int vertices, const EdgeList& edges) const;
+ VertexList topo_sort(size_t vertices, const EdgeList& edges) const;
/**
* refpair is specifically intended to capture a pair of references. This
@@ -539,7 +539,7 @@ public:
for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end();
nmi != nmend; ++nmi)
{
- int thisnode = vmap[nmi->first];
+ auto thisnode = vmap[nmi->first];
// after dependencies: build edges from the named node to this one
for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(),
aend = nmi->second.after.end();
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 56fb7c21ca..f9eda3cd4e 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1514,7 +1514,7 @@ namespace LLError
const size_t BUF_SIZE = 64;
char time_str[BUF_SIZE]; /* Flawfinder: ignore */
- int chars = strftime(time_str, BUF_SIZE,
+ auto chars = strftime(time_str, BUF_SIZE,
"%Y-%m-%dT%H:%M:%SZ",
gmtime(&now));
diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp
index f6bc68b5c1..4f8f0a88ad 100644
--- a/indra/llcommon/llerrorthread.cpp
+++ b/indra/llcommon/llerrorthread.cpp
@@ -108,11 +108,9 @@ void LLErrorThread::run()
// application state as APP_STATUS_ERROR.
LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL;
- S32 counter = 0;
while (! (LLApp::isError() || LLApp::isStopped()))
{
ms_sleep(10);
- counter++;
}
if (LLApp::isError())
{
diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
index 5b6d4efbe9..cd0ab6bc29 100644
--- a/indra/llcommon/lleventdispatcher.cpp
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -178,7 +178,7 @@ private:
// store it as a map from name string to position index. Of course that's
// easy to generate from the incoming names array, but why do it more than
// once?
- typedef std::map<LLSD::String, LLSD::Integer> IndexMap;
+ typedef std::map<LLSD::String, size_t> IndexMap;
IndexMap _indexes;
// Generated array of default values, aligned with the array of param names.
LLSD _defaults;
@@ -197,9 +197,9 @@ LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
{
LL_ERRS("LLSDArgsMapper") << function << " names must be an array, not " << names << LL_ENDL;
}
- LLSD::Integer nparams(_names.size());
+ auto nparams(_names.size());
// From _names generate _indexes.
- for (LLSD::Integer ni = 0, nend = _names.size(); ni < nend; ++ni)
+ for (size_t ni = 0, nend = _names.size(); ni < nend; ++ni)
{
_indexes[_names[ni]] = ni;
}
@@ -214,7 +214,7 @@ LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
if (defaults.isUndefined() || defaults.isArray())
{
- LLSD::Integer ndefaults = defaults.size();
+ auto ndefaults = defaults.size();
// defaults is a (possibly empty) array. Right-align it with names.
if (ndefaults > nparams)
{
@@ -224,10 +224,10 @@ LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
// Offset by which we slide defaults array right to right-align with
// _names array
- LLSD::Integer offset = nparams - ndefaults;
+ auto offset = nparams - ndefaults;
// Fill rightmost _defaults entries from defaults, and mark them as
// filled
- for (LLSD::Integer i = 0, iend = ndefaults; i < iend; ++i)
+ for (size_t i = 0, iend = ndefaults; i < iend; ++i)
{
_defaults[i + offset] = defaults[i];
_has_dft[i + offset] = 1;
@@ -247,7 +247,7 @@ LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
continue;
}
- LLSD::Integer pos = ixit->second;
+ auto pos = ixit->second;
// Store default value at that position in the _defaults array.
_defaults[pos] = mi->second;
// Don't forget to record the fact that we've filled this
@@ -301,7 +301,7 @@ LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
{
// Fill args from array. If there are too many args in passed array,
// ignore the rest.
- LLSD::Integer size(argsmap.size());
+ auto size(argsmap.size());
if (size > args.size())
{
// We don't just use std::min() because we want to sneak in this
@@ -338,7 +338,7 @@ LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
<< mi->first << "=" << mi->second << LL_ENDL;
continue;
}
- LLSD::Integer pos = ixit->second;
+ auto pos = ixit->second;
// Store the value at that position in the args array.
args[pos] = mi->second;
// Don't forget to record the fact that we've filled this
@@ -349,7 +349,7 @@ LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
// Fill any remaining holes from _defaults.
LLSD unfilled(LLSD::emptyArray());
- for (LLSD::Integer i = 0, iend = args.size(); i < iend; ++i)
+ for (size_t i = 0, iend = args.size(); i < iend; ++i)
{
if (! filled[i])
{
@@ -503,9 +503,9 @@ struct LLEventDispatcher::MapParamsDispatchEntry: public LLEventDispatcher::Para
if (defaults.isArray() || defaults.isUndefined())
{
// Right-align the params and defaults arrays.
- LLSD::Integer offset = params.size() - defaults.size();
+ auto offset = params.size() - defaults.size();
// Now the name of every defaults[i] is at params[i + offset].
- for (LLSD::Integer i(0), iend(defaults.size()); i < iend; ++i)
+ for (size_t i(0), iend(defaults.size()); i < iend; ++i)
{
// Erase this optional param from mRequired.
mRequired.erase(params[i + offset].asString());
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 02535a59e7..34f2a5985a 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -99,7 +99,7 @@ public:
return mSelf;
}
- static S32 instanceCount()
+ static size_t instanceCount()
{
return LockStatic()->mMap.size();
}
@@ -363,7 +363,7 @@ public:
return mSelf;
}
- static S32 instanceCount()
+ static size_t instanceCount()
{
return LockStatic()->mSet.size();
}
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index 38696c2258..12e57ae94b 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -30,6 +30,7 @@
#include "llsd.h"
#include "llsdutil.h"
+#include <algorithm>
LLKeyData::LLKeyData()
:
@@ -180,10 +181,10 @@ LLKeyBind::LLKeyBind(const LLSD &key_bind)
bool LLKeyBind::operator==(const LLKeyBind& rhs)
{
- U32 size = mData.size();
+ auto size = mData.size();
if (size != rhs.mData.size()) return false;
- for (U32 i = 0; i < size; i++)
+ for (size_t i = 0; i < size; i++)
{
if (mData[i] != rhs.mData[i]) return false;
}
@@ -193,7 +194,7 @@ bool LLKeyBind::operator==(const LLKeyBind& rhs)
bool LLKeyBind::operator!=(const LLKeyBind& rhs)
{
- U32 size = mData.size();
+ auto size = mData.size();
if (size != rhs.mData.size()) return true;
for (U32 i = 0; i < size; i++)
@@ -213,19 +214,23 @@ bool LLKeyBind::isEmpty() const
return true;
}
-LLSD LLKeyBind::asLLSD() const
+LLKeyBind::data_vector_t::const_iterator LLKeyBind::endNonEmpty() const
{
- S32 last = mData.size() - 1;
- while (mData[last].empty())
- {
- last--;
- }
+ // search backwards for last non-empty entry, then turn back into forwards
+ // iterator (.base() call)
+ return std::find_if_not(mData.rbegin(), mData.rend(),
+ [](const auto& kdata){ return kdata.empty(); }).base();
+}
+LLSD LLKeyBind::asLLSD() const
+{
LLSD data;
- for (S32 i = 0; i <= last; ++i)
+ auto end{ endNonEmpty() };
+ for (auto it = mData.begin(); it < end; ++it)
{
- // append even if empty to not affect visual representation
- data.append(mData[i].asLLSD());
+ // append intermediate entries even if empty to not affect visual
+ // representation
+ data.append(it->asLLSD());
}
return data;
}
@@ -380,16 +385,10 @@ void LLKeyBind::resetKeyData(S32 index)
void LLKeyBind::trimEmpty()
{
- S32 last = mData.size() - 1;
- while (last >= 0 && mData[last].empty())
- {
- mData.erase(mData.begin() + last);
- last--;
- }
+ mData.erase(endNonEmpty(), mData.end());
}
-U32 LLKeyBind::getDataCount()
+size_t LLKeyBind::getDataCount()
{
return mData.size();
}
-
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index c6b4bd970f..488f509411 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -95,11 +95,13 @@ public:
void clear() { mData.clear(); }
// if there any empty LLKeyData in the end of the array, remove them
void trimEmpty();
- U32 getDataCount();
+ size_t getDataCount();
private:
typedef std::vector<LLKeyData> data_vector_t;
data_vector_t mData;
+
+ data_vector_t::const_iterator endNonEmpty() const;
};
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 2704f8b6de..c87c0758fe 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -231,7 +231,8 @@ public:
}
|*==========================================================================*/
- LL_DEBUGS("EventHost") << "Sending: " << buffer.tellp() << ':';
+ LL_DEBUGS("EventHost") << "Sending: "
+ << static_cast<U64>(buffer.tellp()) << ':';
std::string::size_type truncate(80);
if (buffer.tellp() <= truncate)
{
@@ -244,7 +245,8 @@ public:
LL_CONT << LL_ENDL;
LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
- childin.get_ostream() << buffer.tellp() << ':' << buffer.str() << std::flush;
+ childin.get_ostream() << static_cast<U64>(buffer.tellp())
+ << ':' << buffer.str() << std::flush;
return false;
}
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index f942a976b7..9b2a2bab60 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -96,10 +96,10 @@ LLMD5::LLMD5()
// operation, processing another message block, and updating the
// context.
-void LLMD5::update (const uint1 *input, const uint4 input_length) {
+void LLMD5::update (const uint1 *input, const size_t input_length) {
- uint4 input_index, buffer_index;
- uint4 buffer_space; // how much space is left in buffer
+ size_t input_index, buffer_index;
+ size_t buffer_space; // how much space is left in buffer
if (finalized){ // so we can't update!
std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
@@ -107,14 +107,10 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
}
// Compute number of bytes mod 64
- buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
+ buffer_index = size_t((count >> 3) & 0x3F);
// Update number of bits
- if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
- count[1]++;
-
- count[1] += ((uint4)input_length >> 29);
-
+ count += input_length << 3;
buffer_space = 64 - buffer_index; // how much space is left in buffer
@@ -192,7 +188,7 @@ void LLMD5::update(const std::string& s)
void LLMD5::finalize (){
unsigned char bits[8]; /* Flawfinder: ignore */
- unsigned int index, padLen;
+ size_t index, padLen;
static uint1 PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -204,11 +200,12 @@ void LLMD5::finalize (){
return;
}
- // Save number of bits
- encode (bits, count, 8);
+ // Save number of bits.
+ // Treat count, a uint64_t, as uint4[2].
+ encode (bits, reinterpret_cast<uint4*>(&count), 8);
// Pad out to 56 mod 64.
- index = (uint4) ((count[0] >> 3) & 0x3f);
+ index = size_t((count >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
update (PADDING, padLen);
@@ -340,8 +337,7 @@ void LLMD5::init(){
finalized=0; // we just started!
// Nothing counted, so count=0
- count[0] = 0;
- count[1] = 0;
+ count = 0;
// Load magic initialization constants.
state[0] = 0x67452301;
@@ -508,9 +504,9 @@ void LLMD5::transform (const U8 block[64]){
// Encodes input (UINT4) into output (unsigned char). Assumes len is
// a multiple of 4.
-void LLMD5::encode (uint1 *output, const uint4 *input, const uint4 len) {
+void LLMD5::encode (uint1 *output, const uint4 *input, const size_t len) {
- unsigned int i, j;
+ size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (uint1) (input[i] & 0xff);
@@ -525,9 +521,9 @@ void LLMD5::encode (uint1 *output, const uint4 *input, const uint4 len) {
// Decodes input (unsigned char) into output (UINT4). Assumes len is
// a multiple of 4.
-void LLMD5::decode (uint4 *output, const uint1 *input, const uint4 len){
+void LLMD5::decode (uint4 *output, const uint1 *input, const size_t len){
- unsigned int i, j;
+ size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h
index 1526e6ac3c..8530dc0389 100644
--- a/indra/llcommon/llmd5.h
+++ b/indra/llcommon/llmd5.h
@@ -86,7 +86,7 @@ class LL_COMMON_API LLMD5 {
public:
// methods for controlled operation:
LLMD5 (); // simple initializer
- void update (const uint1 *input, const uint4 input_length);
+ void update (const uint1 *input, const size_t input_length);
void update (std::istream& stream);
void update (FILE *file);
void update (const std::string& str);
@@ -110,7 +110,7 @@ private:
// next, the private data:
uint4 state[4];
- uint4 count[2]; // number of *bits*, mod 2^64
+ uint64_t count; // number of *bits*, mod 2^64
uint1 buffer[64]; // input buffer
uint1 digest[16];
uint1 finalized;
@@ -120,8 +120,8 @@ private:
void transform (const uint1 *buffer); // does the real update work. Note
// that length is implied to be 64.
- static void encode (uint1 *dest, const uint4 *src, const uint4 length);
- static void decode (uint4 *dest, const uint1 *src, const uint4 length);
+ static void encode (uint1 *dest, const uint4 *src, const size_t length);
+ static void decode (uint4 *dest, const uint1 *src, const size_t length);
};
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 100eb57555..864ecf650b 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -111,8 +111,8 @@ LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& i
{
ret[label]["Name"] = iter->second["Name"] ;
- S32 num_of_metrics = tester->getNumberOfMetrics() ;
- for(S32 index = 0 ; index < num_of_metrics ; index++)
+ auto num_of_metrics = tester->getNumberOfMetrics() ;
+ for(size_t index = 0 ; index < num_of_metrics ; index++)
{
ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
}
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
index 2e99ed979d..6561a78f03 100644
--- a/indra/llcommon/llmetricperformancetester.h
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -67,12 +67,12 @@ public:
/**
* @return Returns the number of the test metrics in this tester instance.
*/
- S32 getNumberOfMetrics() const { return mMetricStrings.size() ;}
+ auto getNumberOfMetrics() const { return mMetricStrings.size() ;}
/**
* @return Returns the metric name at index
* @param[in] index - Index on the list of metrics managed by this tester instance.
*/
- std::string getMetricName(S32 index) const { return mMetricStrings[index] ;}
+ std::string getMetricName(size_t index) const { return mMetricStrings[index] ;}
protected:
/**
diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp
index 93c7d520f2..b6ad40c2af 100644
--- a/indra/llcommon/llmortician.cpp
+++ b/indra/llcommon/llmortician.cpp
@@ -37,9 +37,9 @@ LLMortician::~LLMortician()
sGraveyard.remove(this);
}
-U32 LLMortician::logClass(std::stringstream &str)
+size_t LLMortician::logClass(std::stringstream &str)
{
- U32 size = sGraveyard.size();
+ auto size = sGraveyard.size();
str << "Mortician graveyard count: " << size;
str << " Zealous: " << (sDestroyImmediate ? "True" : "False");
if (size == 0)
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index 41cb49fab1..f92c5a11db 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -34,8 +34,8 @@ class LL_COMMON_API LLMortician
{
public:
LLMortician() { mIsDead = FALSE; }
- static U32 graveyardCount() { return sGraveyard.size(); };
- static U32 logClass(std::stringstream &str);
+ static auto graveyardCount() { return sGraveyard.size(); };
+ static size_t logClass(std::stringstream &str);
static void updateClass();
virtual ~LLMortician();
void die();
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 8cef4293cd..b06fee0ec2 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -110,7 +110,7 @@ void LLQueuedThread::shutdown()
// MAIN THREAD
// virtual
-S32 LLQueuedThread::update(F32 max_time_ms)
+size_t LLQueuedThread::update(F32 max_time_ms)
{
if (!mStarted)
{
@@ -123,11 +123,11 @@ S32 LLQueuedThread::update(F32 max_time_ms)
return updateQueue(max_time_ms);
}
-S32 LLQueuedThread::updateQueue(F32 max_time_ms)
+size_t LLQueuedThread::updateQueue(F32 max_time_ms)
{
F64 max_time = (F64)max_time_ms * .001;
LLTimer timer;
- S32 pending = 1;
+ size_t pending = 1;
// Frame Update
if (mThreaded)
@@ -164,9 +164,9 @@ void LLQueuedThread::incQueue()
//virtual
// May be called from any thread
-S32 LLQueuedThread::getPending()
+size_t LLQueuedThread::getPending()
{
- S32 res;
+ size_t res;
lockData();
res = mRequestQueue.size();
unlockData();
@@ -399,7 +399,7 @@ bool LLQueuedThread::check()
//============================================================================
// Runs on its OWN thread
-S32 LLQueuedThread::processNextRequest()
+size_t LLQueuedThread::processNextRequest()
{
QueuedRequest *req;
// Get next request from pool
@@ -473,8 +473,7 @@ S32 LLQueuedThread::processNextRequest()
LLTrace::get_thread_recorder()->pushToParent();
}
- S32 pending = getPending();
- return pending;
+ return getPending();
}
// virtual
@@ -511,7 +510,7 @@ void LLQueuedThread::run()
threadedUpdate();
- int pending_work = processNextRequest();
+ auto pending_work = processNextRequest();
if (pending_work == 0)
{
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 5d3f873646..90fce3dc5d 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -167,19 +167,19 @@ private:
protected:
handle_t generateHandle();
bool addRequest(QueuedRequest* req);
- S32 processNextRequest(void);
+ size_t processNextRequest(void);
void incQueue();
public:
bool waitForResult(handle_t handle, bool auto_complete = true);
- virtual S32 update(F32 max_time_ms);
- S32 updateQueue(F32 max_time_ms);
-
+ virtual size_t update(F32 max_time_ms);
+ size_t updateQueue(F32 max_time_ms);
+
void waitOnPending();
void printQueueStats();
- virtual S32 getPending();
+ virtual size_t getPending();
bool getThreaded() { return mThreaded ? true : false; }
// Request accessors
diff --git a/indra/llcommon/llrun.cpp b/indra/llcommon/llrun.cpp
index f5d3f302fa..a3b3fccf4b 100644
--- a/indra/llcommon/llrun.cpp
+++ b/indra/llcommon/llrun.cpp
@@ -47,7 +47,7 @@ LLRunner::~LLRunner()
mRunEvery.clear();
}
-S32 LLRunner::run()
+size_t LLRunner::run()
{
// We collect all of the runnables which should be run. Since the
// runnables are allowed to adjust the run list, we need to copy
diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h
index a117405366..d610f86234 100644
--- a/indra/llcommon/llrun.h
+++ b/indra/llcommon/llrun.h
@@ -85,7 +85,7 @@ public:
*
* @return Returns the number of runnables run.
*/
- S32 run();
+ size_t run();
/**
* @brief Add a runnable to the run list.
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 807b3d13f8..590915e9d2 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -36,6 +36,18 @@
#include "llsdserialize.h"
#include "stringize.h"
+#include <limits>
+
+// Defend against a caller forcibly passing a negative number into an unsigned
+// size_t index param
+inline
+bool was_negative(size_t i)
+{
+ return (i > std::numeric_limits<int>::max());
+}
+#define NEGATIVE_EXIT(i) if (was_negative(i)) return
+#define NEGATIVE_RETURN(i, result) NEGATIVE_EXIT(i) (result)
+
#ifndef LL_RELEASE_FOR_DOWNLOAD
#define NAME_UNNAMED_NAMESPACE
#endif
@@ -136,10 +148,10 @@ public:
virtual void erase(const String&) { }
virtual const LLSD& ref(const String&) const{ return undef(); }
- virtual int size() const { return 0; }
- virtual LLSD get(Integer) const { return LLSD(); }
- virtual void erase(Integer) { }
- virtual const LLSD& ref(Integer) const { return undef(); }
+ virtual size_t size() const { return 0; }
+ virtual LLSD get(size_t) const { return LLSD(); }
+ virtual void erase(size_t) { }
+ virtual const LLSD& ref(size_t) const { return undef(); }
virtual LLSD::map_const_iterator beginMap() const { return endMap(); }
virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); }
@@ -272,7 +284,7 @@ namespace
virtual LLSD::UUID asUUID() const { return LLUUID(mValue); }
virtual LLSD::Date asDate() const { return LLDate(mValue); }
virtual LLSD::URI asURI() const { return LLURI(mValue); }
- virtual int size() const { return mValue.size(); }
+ virtual size_t size() const { return mValue.size(); }
virtual const LLSD::String& asStringRef() const { return mValue; }
};
@@ -377,9 +389,9 @@ namespace
virtual bool has(const LLSD::String&) const;
- using LLSD::Impl::get; // Unhiding get(LLSD::Integer)
- using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
- using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
+ using LLSD::Impl::get; // Unhiding get(size_t)
+ using LLSD::Impl::erase; // Unhiding erase(size_t)
+ using LLSD::Impl::ref; // Unhiding ref(size_t)
virtual LLSD get(const LLSD::String&) const;
virtual LLSD getKeys() const;
void insert(const LLSD::String& k, const LLSD& v);
@@ -387,7 +399,7 @@ namespace
LLSD& ref(const LLSD::String&);
virtual const LLSD& ref(const LLSD::String&) const;
- virtual int size() const { return mData.size(); }
+ virtual size_t size() const { return mData.size(); }
LLSD::map_iterator beginMap() { return mData.begin(); }
LLSD::map_iterator endMap() { return mData.end(); }
@@ -518,14 +530,14 @@ namespace
using LLSD::Impl::get; // Unhiding get(LLSD::String)
using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
- virtual int size() const;
- virtual LLSD get(LLSD::Integer) const;
- void set(LLSD::Integer, const LLSD&);
- void insert(LLSD::Integer, const LLSD&);
+ virtual size_t size() const;
+ virtual LLSD get(size_t) const;
+ void set(size_t, const LLSD&);
+ void insert(size_t, const LLSD&);
LLSD& append(const LLSD&);
- virtual void erase(LLSD::Integer);
- LLSD& ref(LLSD::Integer);
- virtual const LLSD& ref(LLSD::Integer) const;
+ virtual void erase(size_t);
+ LLSD& ref(size_t);
+ virtual const LLSD& ref(size_t) const;
LLSD::array_iterator beginArray() { return mData.begin(); }
LLSD::array_iterator endArray() { return mData.end(); }
@@ -550,85 +562,82 @@ namespace
return *this;
}
}
-
- int ImplArray::size() const { return mData.size(); }
-
- LLSD ImplArray::get(LLSD::Integer i) const
+
+ size_t ImplArray::size() const { return mData.size(); }
+
+ LLSD ImplArray::get(size_t i) const
{
- if (i < 0) { return LLSD(); }
+ NEGATIVE_RETURN(i, LLSD());
DataVector::size_type index = i;
-
+
return (index < mData.size()) ? mData[index] : LLSD();
}
-
- void ImplArray::set(LLSD::Integer i, const LLSD& v)
+
+ void ImplArray::set(size_t i, const LLSD& v)
{
- if (i < 0) { return; }
+ NEGATIVE_EXIT(i);
DataVector::size_type index = i;
-
+
if (index >= mData.size())
{
mData.resize(index + 1);
}
-
+
mData[index] = v;
}
-
- void ImplArray::insert(LLSD::Integer i, const LLSD& v)
+
+ void ImplArray::insert(size_t i, const LLSD& v)
{
- if (i < 0)
- {
- return;
- }
+ NEGATIVE_EXIT(i);
DataVector::size_type index = i;
-
+
if (index >= mData.size()) // tbd - sanity check limit for index ?
{
mData.resize(index + 1);
}
-
+
mData.insert(mData.begin() + index, v);
}
-
+
LLSD& ImplArray::append(const LLSD& v)
{
mData.push_back(v);
return mData.back();
}
-
- void ImplArray::erase(LLSD::Integer i)
+
+ void ImplArray::erase(size_t i)
{
- if (i < 0) { return; }
+ NEGATIVE_EXIT(i);
DataVector::size_type index = i;
-
+
if (index < mData.size())
{
mData.erase(mData.begin() + index);
}
}
-
- LLSD& ImplArray::ref(LLSD::Integer i)
+
+ LLSD& ImplArray::ref(size_t i)
{
- DataVector::size_type index = i >= 0 ? i : 0;
-
+ DataVector::size_type index = was_negative(i)? 0 : i;
+
if (index >= mData.size())
{
- mData.resize(i + 1);
+ mData.resize(index + 1);
}
-
+
return mData[index];
}
- const LLSD& ImplArray::ref(LLSD::Integer i) const
+ const LLSD& ImplArray::ref(size_t i) const
{
- if (i < 0) { return undef(); }
+ NEGATIVE_RETURN(i, undef());
DataVector::size_type index = i;
-
+
if (index >= mData.size())
{
return undef();
}
-
+
return mData[index];
}
@@ -841,9 +850,6 @@ LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-// Convenience Constructors
-LLSD::LLSD(F32 v) : impl(0) { ALLOC_LLSD_OBJECT; assign((Real)v); }
-
// Scalar Assignment
void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
void LLSD::assign(Integer v) { safe(impl).assign(impl, v); }
@@ -912,7 +918,7 @@ LLSD LLSD::emptyArray()
return v;
}
-int LLSD::size() const { return safe(impl).size(); }
+size_t LLSD::size() const { return safe(impl).size(); }
LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
@@ -926,12 +932,12 @@ LLSD& LLSD::with(Integer i, const LLSD& v)
LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
-LLSD& LLSD::operator[](Integer i)
+LLSD& LLSD::operator[](size_t i)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return makeArray(impl).ref(i);
}
-const LLSD& LLSD::operator[](Integer i) const
+const LLSD& LLSD::operator[](size_t i) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return safe(impl).ref(i);
@@ -956,7 +962,7 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
out << LLSDNotationStreamer(llsd);
out_string = out.str();
}
- int len = out_string.length();
+ auto len = out_string.length();
sStorage = new char[len + 1];
memcpy(sStorage, out_string.c_str(), len);
sStorage[len] = '\0';
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 3daaef44fc..cdb9a7ed8a 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -192,7 +192,17 @@ public:
/** @name Convenience Constructors */
//@{
- LLSD(F32); // F32 -> Real
+ // support construction from size_t et al.
+ template <typename VALUE,
+ typename std::enable_if<std::is_integral<VALUE>::value &&
+ ! std::is_same<VALUE, Boolean>::value,
+ bool>::type = true>
+ LLSD(VALUE v): LLSD(Integer(narrow(v))) {}
+ // support construction from F32 et al.
+ template <typename VALUE,
+ typename std::enable_if<std::is_floating_point<VALUE>::value,
+ bool>::type = true>
+ LLSD(VALUE v): LLSD(Real(narrow(v))) {}
//@}
/** @name Scalar Assignment */
@@ -275,7 +285,7 @@ public:
//@{
LLSD(const char*);
void assign(const char*);
- LLSD& operator=(const char* v) { assign(v); return *this; }
+ LLSD& operator=(const char* v) { assign(v); return *this; }
//@}
/** @name Map Values */
@@ -313,14 +323,24 @@ public:
LLSD& append(const LLSD&);
void erase(Integer);
LLSD& with(Integer, const LLSD&);
-
- const LLSD& operator[](Integer) const;
- LLSD& operator[](Integer);
+
+ // accept size_t so we can index relative to size()
+ const LLSD& operator[](size_t) const;
+ LLSD& operator[](size_t);
+ // template overloads to support int literals, U32 et al.
+ template <typename IDX,
+ typename std::enable_if<std::is_convertible<IDX, size_t>::value,
+ bool>::type = true>
+ const LLSD& operator[](IDX i) const { return (*this)[size_t(i)]; }
+ template <typename IDX,
+ typename std::enable_if<std::is_convertible<IDX, size_t>::value,
+ bool>::type = true>
+ LLSD& operator[](IDX i) { return (*this)[size_t(i)]; }
//@}
/** @name Iterators */
//@{
- int size() const;
+ size_t size() const;
typedef std::map<String, LLSD>::iterator map_iterator;
typedef std::map<String, LLSD>::const_iterator map_const_iterator;
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index a510b73096..f66c4ff843 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -53,7 +53,7 @@
#include "lluri.h"
// File constants
-static const int MAX_HDR_LEN = 20;
+static const size_t MAX_HDR_LEN = 20;
static const S32 UNZIP_LLSD_MAX_DEPTH = 96;
static const char LEGACY_NON_HEADER[] = "<llsd>";
const std::string LLSD_BINARY_HEADER("LLSD/Binary");
@@ -102,7 +102,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
}
// static
-bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
+bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
{
LLPointer<LLSDParser> p = NULL;
char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
@@ -255,7 +255,7 @@ F64 ll_ntohd(F64 netdouble)
* @return Returns number of bytes read off of the stream. Returns
* PARSE_FAILURE (-1) on failure.
*/
-int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
+llssize deserialize_string(std::istream& istr, std::string& value, llssize max_bytes);
/**
* @brief Parse a delimited string.
@@ -266,7 +266,7 @@ int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
* @return Returns number of bytes read off of the stream. Returns
* PARSE_FAILURE (-1) on failure.
*/
-int deserialize_string_delim(std::istream& istr, std::string& value, char d);
+llssize deserialize_string_delim(std::istream& istr, std::string& value, char d);
/**
* @brief Read a raw string off the stream.
@@ -280,10 +280,10 @@ int deserialize_string_delim(std::istream& istr, std::string& value, char d);
* @return Returns number of bytes read off of the stream. Returns
* PARSE_FAILURE (-1) on failure.
*/
-int deserialize_string_raw(
+llssize deserialize_string_raw(
std::istream& istr,
std::string& value,
- S32 max_bytes);
+ llssize max_bytes);
/**
* @brief helper method for dealing with the different notation boolean format.
@@ -295,7 +295,7 @@ int deserialize_string_raw(
* @return Returns number of bytes read off of the stream. Returns
* PARSE_FAILURE (-1) on failure.
*/
-int deserialize_boolean(
+llssize deserialize_boolean(
std::istream& istr,
LLSD& data,
const std::string& compare,
@@ -332,7 +332,7 @@ LLSDParser::LLSDParser()
LLSDParser::~LLSDParser()
{ }
-S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth)
+S32 LLSDParser::parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth)
{
mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
mMaxBytesLeft = max_bytes;
@@ -362,7 +362,7 @@ std::istream& LLSDParser::get(
char delim) const
{
istr.get(s, n, delim);
- if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
return istr;
}
@@ -372,7 +372,7 @@ std::istream& LLSDParser::get(
char delim) const
{
istr.get(sb, delim);
- if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
return istr;
}
@@ -396,11 +396,11 @@ std::istream& LLSDParser::read(
std::streamsize n) const
{
istr.read(s, n);
- if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
return istr;
}
-void LLSDParser::account(S32 bytes) const
+void LLSDParser::account(llssize bytes) const
{
if(mCheckLimits) mMaxBytesLeft -= bytes;
}
@@ -505,7 +505,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
c = istr.peek();
if(isalpha(c))
{
- int cnt = deserialize_boolean(
+ auto cnt = deserialize_boolean(
istr,
data,
NOTATION_FALSE_SERIAL,
@@ -535,7 +535,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
c = istr.peek();
if(isalpha(c))
{
- int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
+ auto cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
if(PARSE_FAILURE == cnt) parse_count = cnt;
else account(cnt);
}
@@ -611,7 +611,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
c = get(istr); // pop the 'l'
c = get(istr); // pop the delimiter
std::string str;
- int cnt = deserialize_string_delim(istr, str, c);
+ auto cnt = deserialize_string_delim(istr, str, c);
if(PARSE_FAILURE == cnt)
{
parse_count = PARSE_FAILURE;
@@ -634,7 +634,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
c = get(istr); // pop the 'd'
c = get(istr); // pop the delimiter
std::string str;
- int cnt = deserialize_string_delim(istr, str, c);
+ auto cnt = deserialize_string_delim(istr, str, c);
if(PARSE_FAILURE == cnt)
{
parse_count = PARSE_FAILURE;
@@ -666,7 +666,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c
default:
parse_count = PARSE_FAILURE;
- LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+ LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
<< ")" << LL_ENDL;
break;
}
@@ -697,7 +697,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) c
{
putback(istr, c);
found_name = true;
- int count = deserialize_string(istr, name, mMaxBytesLeft);
+ auto count = deserialize_string(istr, name, mMaxBytesLeft);
if(PARSE_FAILURE == count) return PARSE_FAILURE;
account(count);
}
@@ -779,7 +779,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_dept
bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
{
std::string value;
- int count = deserialize_string(istr, value, mMaxBytesLeft);
+ auto count = deserialize_string(istr, value, mMaxBytesLeft);
if(PARSE_FAILURE == count) return false;
account(count);
data = value;
@@ -806,13 +806,13 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
{
// We probably have a valid raw binary stream. determine
// the size, and read it.
- S32 len = strtol(buf + 2, NULL, 0);
+ auto len = strtol(buf + 2, NULL, 0);
if(mCheckLimits && (len > mMaxBytesLeft)) return false;
std::vector<U8> value;
if(len)
{
value.resize(len);
- account((int)fullread(istr, (char *)&value[0], len));
+ account(fullread(istr, (char *)&value[0], len));
}
c = get(istr); // strip off the trailing double-quote
data = value;
@@ -1009,7 +1009,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
case '"':
{
std::string value;
- int cnt = deserialize_string_delim(istr, value, c);
+ auto cnt = deserialize_string_delim(istr, value, c);
if(PARSE_FAILURE == cnt)
{
parse_count = PARSE_FAILURE;
@@ -1096,7 +1096,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
if(size > 0)
{
value.resize(size);
- account((int)fullread(istr, (char*)&value[0], size));
+ account(fullread(istr, (char*)&value[0], size));
}
data = value;
}
@@ -1110,7 +1110,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
default:
parse_count = PARSE_FAILURE;
- LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+ LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
<< ")" << LL_ENDL;
break;
}
@@ -1144,7 +1144,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) con
case '\'':
case '"':
{
- int cnt = deserialize_string_delim(istr, name, c);
+ auto cnt = deserialize_string_delim(istr, name, c);
if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
account(cnt);
break;
@@ -1228,7 +1228,7 @@ bool LLSDBinaryParser::parseString(
if(size)
{
buf.resize(size);
- account((int)fullread(istr, &buf[0], size));
+ account(fullread(istr, &buf[0], size));
value.assign(buf.begin(), buf.end());
}
return true;
@@ -1432,7 +1432,7 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr,
ostr << std::uppercase;
auto oldfill(ostr.fill('0'));
auto oldwidth(ostr.width());
- for (int i = 0; i < buffer.size(); i++)
+ for (size_t i = 0; i < buffer.size(); i++)
{
// have to restate setw() before every conversion
ostr << std::setw(2) << (int) buffer[i];
@@ -1595,7 +1595,7 @@ void LLSDBinaryFormatter::formatString(
/**
* local functions
*/
-int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
+llssize deserialize_string(std::istream& istr, std::string& value, llssize max_bytes)
{
int c = istr.get();
if(istr.fail())
@@ -1605,7 +1605,7 @@ int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
return LLSDParser::PARSE_FAILURE;
}
- int rv = LLSDParser::PARSE_FAILURE;
+ llssize rv = LLSDParser::PARSE_FAILURE;
switch(c)
{
case '\'':
@@ -1625,7 +1625,7 @@ int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
return rv + 1; // account for the character grabbed at the top.
}
-int deserialize_string_delim(
+llssize deserialize_string_delim(
std::istream& istr,
std::string& value,
char delim)
@@ -1635,7 +1635,7 @@ int deserialize_string_delim(
bool found_hex = false;
bool found_digit = false;
U8 byte = 0;
- int count = 0;
+ llssize count = 0;
while (true)
{
@@ -1650,7 +1650,7 @@ int deserialize_string_delim(
}
char next_char = (char)next_byte; // Now that we know it's not EOF
-
+
if(found_escape)
{
// next character(s) is a special sequence.
@@ -1728,16 +1728,16 @@ int deserialize_string_delim(
return count;
}
-int deserialize_string_raw(
+llssize deserialize_string_raw(
std::istream& istr,
std::string& value,
- S32 max_bytes)
+ llssize max_bytes)
{
- int count = 0;
+ llssize count = 0;
const S32 BUF_LEN = 20;
char buf[BUF_LEN]; /* Flawfinder: ignore */
istr.get(buf, BUF_LEN - 1, ')');
- count += (int)istr.gcount();
+ count += istr.gcount();
int c = istr.get();
c = istr.get();
count += 2;
@@ -1746,13 +1746,13 @@ int deserialize_string_raw(
// We probably have a valid raw string. determine
// the size, and read it.
// *FIX: This is memory inefficient.
- S32 len = strtol(buf + 1, NULL, 0);
+ auto len = strtol(buf + 1, NULL, 0);
if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
std::vector<char> buf;
if(len)
{
buf.resize(len);
- count += (int)fullread(istr, (char *)&buf[0], len);
+ count += fullread(istr, (char *)&buf[0], len);
value.assign(buf.begin(), buf.end());
}
c = istr.get();
@@ -2041,7 +2041,7 @@ void serialize_string(const std::string& value, std::ostream& str)
}
}
-int deserialize_boolean(
+llssize deserialize_boolean(
std::istream& istr,
LLSD& data,
const std::string& compare,
@@ -2058,7 +2058,7 @@ int deserialize_boolean(
// * set data to LLSD::null
// * return LLSDParser::PARSE_FAILURE (-1)
//
- int bytes_read = 0;
+ llssize bytes_read = 0;
std::string::size_type ii = 0;
char c = istr.peek();
while((++ii < compare.size())
@@ -2113,7 +2113,7 @@ std::string zip_llsd(LLSD& data)
U8 out[CHUNK];
- strm.avail_in = source.size();
+ strm.avail_in = narrow(source.size());
strm.next_in = (U8*) source.data();
U8* output = NULL;
@@ -2193,7 +2193,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
{
U8* result = NULL;
- U32 cur_size = 0;
+ llssize cur_size = 0;
z_stream strm;
constexpr U32 CHUNK = 1024 * 512;
@@ -2287,7 +2287,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
//This unzip function will only work with a gzip header and trailer - while the contents
//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
//and trailers are different for the formats.
-U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
+U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size )
{
if (size == 0)
{
@@ -2388,7 +2388,7 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
return result;
}
-char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
+char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size)
{
const char* deprecated_header = "<? LLSD/Binary ?>";
constexpr size_t deprecated_header_size = 17;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index d33d2b6f34..5ddf0ff552 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -77,7 +77,7 @@ public:
* @return Returns the number of LLSD objects parsed into
* data. Returns PARSE_FAILURE (-1) on parse failure.
*/
- S32 parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth = -1);
+ S32 parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth = -1);
/** Like parse(), but uses a different call (istream.getline()) to read by lines
* This API is better suited for XML, where the parse cannot tell
@@ -194,7 +194,7 @@ protected:
* Conceptually const since it only modifies mutable members.
* @param bytes The number of bytes read.
*/
- void account(S32 bytes) const;
+ void account(llssize bytes) const;
protected:
/**
@@ -205,7 +205,7 @@ protected:
/**
* @brief The maximum number of bytes left to be parsed.
*/
- mutable S32 mMaxBytesLeft;
+ mutable llssize mMaxBytesLeft;
/**
* @brief Use line-based reading to get text
@@ -336,7 +336,7 @@ private:
class Impl;
Impl& impl;
- void parsePart(const char* buf, int len);
+ void parsePart(const char* buf, llssize len);
friend class LLSDSerialize;
};
@@ -756,7 +756,7 @@ public:
* @param max_bytes the maximum number of bytes to parse
* @return Returns true if the stream appears to contain valid data
*/
- static bool deserialize(LLSD& sd, std::istream& str, S32 max_bytes);
+ static bool deserialize(LLSD& sd, std::istream& str, llssize max_bytes);
/*
* Notation Methods
@@ -778,12 +778,12 @@ public:
LLSDFormatter::EFormatterOptions(LLSDFormatter::OPTIONS_PRETTY |
LLSDFormatter::OPTIONS_PRETTY_BINARY));
}
- static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes)
+ static S32 fromNotation(LLSD& sd, std::istream& str, llssize max_bytes)
{
LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
return p->parse(str, sd, max_bytes);
}
- static LLSD fromNotation(std::istream& str, S32 max_bytes)
+ static LLSD fromNotation(std::istream& str, llssize max_bytes)
{
LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
LLSD sd;
@@ -834,12 +834,12 @@ public:
LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter;
return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
}
- static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes, S32 max_depth = -1)
+ static S32 fromBinary(LLSD& sd, std::istream& str, llssize max_bytes, S32 max_depth = -1)
{
LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
return p->parse(str, sd, max_bytes, max_depth);
}
- static LLSD fromBinary(std::istream& str, S32 max_bytes, S32 max_depth = -1)
+ static LLSD fromBinary(std::istream& str, llssize max_bytes, S32 max_depth = -1)
{
LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
LLSD sd;
@@ -870,8 +870,8 @@ public:
LL_COMMON_API std::string zip_llsd(LLSD& data);
-LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);
+LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size);
// returns a pointer to the array or past the array if the deprecated header exists
-LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);
+LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size = nullptr);
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 0da824d694..ac128c9f86 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -196,12 +196,12 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr,
// *FIX: memory inefficient.
// *TODO: convert to use LLBase64
ostr << pre << "<binary encoding=\"base64\">";
- int b64_buffer_length = apr_base64_encode_len(buffer.size());
+ int b64_buffer_length = apr_base64_encode_len(narrow(buffer.size()));
char* b64_buffer = new char[b64_buffer_length];
b64_buffer_length = apr_base64_encode_binary(
b64_buffer,
&buffer[0],
- buffer.size());
+ narrow(buffer.size()));
ostr.write(b64_buffer, b64_buffer_length - 1);
delete[] b64_buffer;
ostr << "</binary>" << post;
@@ -260,7 +260,7 @@ public:
S32 parse(std::istream& input, LLSD& data);
S32 parseLines(std::istream& input, LLSD& data);
- void parsePart(const char *buf, int len);
+ void parsePart(const char *buf, llssize len);
void reset();
@@ -542,7 +542,7 @@ LLSDXMLParser::Impl::findAttribute(const XML_Char* name, const XML_Char** pairs)
return NULL;
}
-void LLSDXMLParser::Impl::parsePart(const char* buf, int len)
+void LLSDXMLParser::Impl::parsePart(const char* buf, llssize len)
{
if ( buf != NULL
&& len > 0 )
@@ -915,7 +915,7 @@ LLSDXMLParser::~LLSDXMLParser()
delete &impl;
}
-void LLSDXMLParser::parsePart(const char *buf, int len)
+void LLSDXMLParser::parsePart(const char *buf, llssize len)
{
impl.parsePart(buf, len);
}
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 51ef514cf7..cbe5ab6406 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -802,7 +802,7 @@ public:
private: \
/* implement LLSingleton pure virtual method whose sole purpose */ \
/* is to remind people to use this macro */ \
- virtual void you_must_use_LLSINGLETON_macro() {} \
+ virtual void you_must_use_LLSINGLETON_macro() override {} \
friend class LLSingleton<DERIVED_CLASS>; \
DERIVED_CLASS(__VA_ARGS__)
diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp
index d7a6f47932..1ff15fcf89 100644
--- a/indra/llcommon/llstreamtools.cpp
+++ b/indra/llcommon/llstreamtools.cpp
@@ -118,7 +118,7 @@ bool skip_to_next_word(std::istream& input_stream)
bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
{
- int key_length = strlen(keyword); /*Flawfinder: ignore*/
+ auto key_length = strlen(keyword); /*Flawfinder: ignore*/
if (0 == key_length)
{
return false;
@@ -315,7 +315,7 @@ bool unget_line(const std::string& line, std::istream& input_stream)
// returns true if removed last char
bool remove_last_char(char c, std::string& line)
{
- int line_size = line.size();
+ auto line_size = line.size();
if (line_size > 1
&& c == line[line_size - 1])
{
@@ -330,9 +330,8 @@ bool remove_last_char(char c, std::string& line)
// "\\n" ---> '\n' (backslash n becomes carriage return)
void unescape_string(std::string& line)
{
- int line_size = line.size();
- int index = 0;
- while (index < line_size - 1)
+ auto line_size = line.size();
+ for (size_t index = 0; line_size >= 1 && index < line_size - 1; ++index)
{
if ('\\' == line[index])
{
@@ -347,7 +346,6 @@ void unescape_string(std::string& line)
line_size--;
}
}
- index++;
}
}
@@ -356,9 +354,8 @@ void unescape_string(std::string& line)
// '\n' ---> "\\n" (carriage return becomes backslash n)
void escape_string(std::string& line)
{
- int line_size = line.size();
- int index = 0;
- while (index < line_size)
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; ++index)
{
if ('\\' == line[index])
{
@@ -372,31 +369,27 @@ void escape_string(std::string& line)
line_size++;
index++;
}
- index++;
}
}
// removes '\n' characters
void replace_newlines_with_whitespace(std::string& line)
{
- int line_size = line.size();
- int index = 0;
- while (index < line_size)
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; ++index)
{
if ('\n' == line[index])
{
line.replace(index, 1, " ");
}
- index++;
}
}
// erases any double-quote characters in 'line'
void remove_double_quotes(std::string& line)
{
- int index = 0;
- int line_size = line.size();
- while (index < line_size)
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; )
{
if ('"' == line[index])
{
@@ -424,22 +417,21 @@ void get_keyword_and_value(std::string& keyword,
const std::string& line)
{
// skip initial whitespace
- int line_size = line.size();
- int line_index = 0;
+ auto line_size = line.size();
+ size_t line_index = 0;
char c;
- while (line_index < line_size)
+ for ( ; line_index < line_size; ++line_index)
{
c = line[line_index];
if (!LLStringOps::isSpace(c))
{
break;
}
- line_index++;
}
// get the keyword
keyword.clear();
- while (line_index < line_size)
+ for ( ; line_index < line_size; ++line_index)
{
c = line[line_index];
if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c)
@@ -447,7 +439,6 @@ void get_keyword_and_value(std::string& keyword,
break;
}
keyword += c;
- line_index++;
}
// get the value
@@ -465,7 +456,7 @@ void get_keyword_and_value(std::string& keyword,
line_index++;
}
- while (line_index < line_size)
+ for ( ; line_index < line_size; ++line_index)
{
c = line[line_index];
if ('\r' == c || '\n' == c)
@@ -473,7 +464,6 @@ void get_keyword_and_value(std::string& keyword,
break;
}
value += c;
- line_index++;
}
}
}
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 7f501f2e77..cda1791e45 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -30,6 +30,7 @@
#include "llerror.h"
#include "llfasttimer.h"
#include "llsd.h"
+#include <unicode/uchar.h>
#include <vector>
#if LL_WINDOWS
@@ -141,7 +142,7 @@ std::string rawstr_to_utf8(const std::string& raw)
return wstring_to_utf8str(wstr);
}
-S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
+std::ptrdiff_t wchar_to_utf8chars(llwchar in_char, char* outchars)
{
U32 cur_char = (U32)in_char;
char* base = outchars;
@@ -192,7 +193,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
return outchars - base;
}
-S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
+auto utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
{
const U16* base = inchars;
U16 cur_char = *inchars++;
@@ -310,7 +311,7 @@ S32 wstring_utf16_length(const LLWString &wstr, const S32 woffset, const S32 wle
// and whose equivalent utf-16 string does not exceeds the given utf16_length.
S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, const S32 woffset, const S32 utf16_length, BOOL *unaligned)
{
- const S32 end = wstr.length();
+ const auto end = wstr.length();
BOOL u = FALSE;
S32 n = woffset + utf16_length;
S32 i = woffset;
@@ -426,7 +427,7 @@ LLWString utf8str_to_wstring(const char* utf8str, size_t len)
}
// Check that this character doesn't go past the end of the string
- S32 end = (len < (i + cont_bytes)) ? len : (i + cont_bytes);
+ auto end = (len < (i + cont_bytes)) ? len : (i + cont_bytes);
do
{
++i;
@@ -471,7 +472,7 @@ std::string wstring_to_utf8str(const llwchar* utf32str, size_t len)
while (i < len)
{
char tchars[8]; /* Flawfinder: ignore */
- S32 n = wchar_to_utf8chars(utf32str[i], tchars);
+ auto n = wchar_to_utf8chars(utf32str[i], tchars);
tchars[n] = 0;
out += tchars;
i++;
@@ -833,6 +834,31 @@ std::string LLStringOps::sDayFormat;
std::string LLStringOps::sAM;
std::string LLStringOps::sPM;
+// static
+bool LLStringOps::isEmoji(llwchar wch)
+{
+ switch (ublock_getCode(wch))
+ {
+ case UBLOCK_MISCELLANEOUS_SYMBOLS:
+ case UBLOCK_DINGBATS:
+ case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS:
+ case UBLOCK_EMOTICONS:
+ case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS:
+#if U_ICU_VERSION_MAJOR_NUM > 56
+ // Boost uses ICU so we can't update it independently
+ case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS:
+#endif // U_ICU_VERSION_MAJOR_NUM > 56
+ return true;
+ default:
+#if U_ICU_VERSION_MAJOR_NUM > 56
+ return false;
+#else
+ // See https://en.wikipedia.org/wiki/Supplemental_Symbols_and_Pictographs
+ return wch >= 0x1F900 && wch <= 0x1F9FF;
+#endif // U_ICU_VERSION_MAJOR_NUM > 56
+ }
+}
+
S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
{
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index d94f549480..9afbea9afe 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -189,6 +189,8 @@ public:
static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
+ static bool isEmoji(llwchar wch);
+
static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
static S32 collate(const llwchar* a, const llwchar* b);
@@ -664,7 +666,7 @@ ll_convert_forms(ll_convert_alias, LLWString, std::string, utf8str_to_
// Same function, better name. JC
inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
-LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
+LL_COMMON_API std::ptrdiff_t wchar_to_utf8chars(llwchar inchar, char* outchars);
ll_convert_forms(ll_convert_alias, std::string, LLWString, wstring_to_utf8str);
ll_convert_forms(ll_convert_u16_alias, std::string, llutf16string, utf16str_to_utf8str);
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index a8b5c7b3a8..91cb65b815 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -273,7 +273,7 @@ LLOSInfo::LLOSInfo() :
{
const char * DARWIN_PRODUCT_NAME = "Mac OS X";
- S32 major_version, minor_version, bugfix_version = 0;
+ int64_t major_version, minor_version, bugfix_version = 0;
if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))
{
@@ -454,14 +454,14 @@ LLOSInfo::LLOSInfo() :
#ifndef LL_WINDOWS
// static
-S32 LLOSInfo::getMaxOpenFiles()
+long LLOSInfo::getMaxOpenFiles()
{
- const S32 OPEN_MAX_GUESS = 256;
+ const long OPEN_MAX_GUESS = 256;
#ifdef OPEN_MAX
- static S32 open_max = OPEN_MAX;
+ static long open_max = OPEN_MAX;
#else
- static S32 open_max = 0;
+ static long open_max = 0;
#endif
if (0 == open_max)
@@ -909,7 +909,7 @@ void LLMemoryInfo::stream(std::ostream& s) const
// Now stream stats
BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap))
{
- s << pfx << std::setw(key_width+1) << (pair.first + ':') << ' ';
+ s << pfx << std::setw(narrow(key_width+1)) << (pair.first + ':') << ' ';
LLSD value(pair.second);
if (value.isInteger())
s << std::setw(12) << value.asInteger();
@@ -1280,7 +1280,7 @@ public:
<< " seconds ";
}
- S32 precision = LL_CONT.precision();
+ auto precision = LL_CONT.precision();
LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
<< LLMemoryInfo();
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 5ffbf5a732..70a03810c5 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -59,7 +59,7 @@ public:
S32 mBuild;
#ifndef LL_WINDOWS
- static S32 getMaxOpenFiles();
+ static long getMaxOpenFiles();
#endif
static bool is64Bit();
diff --git a/indra/llcommon/llsys_objc.h b/indra/llcommon/llsys_objc.h
index 35599a574b..b48ff97bdb 100644
--- a/indra/llcommon/llsys_objc.h
+++ b/indra/llcommon/llsys_objc.h
@@ -27,7 +27,11 @@
#ifndef LL_LLSYS_OBJC_H
#define LL_LLSYS_OBJC_H
-bool LLGetDarwinOSInfo(int &major, int &minor, int &patch);
+#include <cstdint>
+
+// C++ land doesn't define NSInteger, and we don't want to introduce that for
+// this one case, so use int64_t instead (which is equivalent).
+bool LLGetDarwinOSInfo(int64_t &major, int64_t &minor, int64_t &patch);
#endif // LL_LLSYS_OBJC_H
diff --git a/indra/llcommon/llsys_objc.mm b/indra/llcommon/llsys_objc.mm
index cdb1e320d5..3fd85fb1c9 100644
--- a/indra/llcommon/llsys_objc.mm
+++ b/indra/llcommon/llsys_objc.mm
@@ -27,12 +27,12 @@
#import "llsys_objc.h"
#import <AppKit/AppKit.h>
-static int intAtStringIndex(NSArray *array, int index)
+static auto intAtStringIndex(NSArray *array, int index)
{
return [(NSString *)[array objectAtIndex:index] integerValue];
}
-bool LLGetDarwinOSInfo(int &major, int &minor, int &patch)
+bool LLGetDarwinOSInfo(int64_t &major, int64_t &minor, int64_t &patch)
{
if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8)
{
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 68d79cdd12..f396a71e6f 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -82,7 +82,7 @@ public:
// Limiting the number of pending items prevents unbounded growth of the
// underlying queue.
- LLThreadSafeQueue(U32 capacity = 1024);
+ LLThreadSafeQueue(size_t capacity = 1024);
virtual ~LLThreadSafeQueue() {}
// Add an element to the queue (will block if the queue has reached
@@ -179,7 +179,7 @@ public:
protected:
typedef QueueT queue_type;
QueueT mStorage;
- U32 mCapacity;
+ size_t mCapacity;
bool mClosed;
boost::fibers::timed_mutex mLock;
@@ -262,7 +262,7 @@ namespace LL
* LLThreadSafeQueue implementation
*****************************************************************************/
template<typename ElementT, typename QueueT>
-LLThreadSafeQueue<ElementT, QueueT>::LLThreadSafeQueue(U32 capacity) :
+LLThreadSafeQueue<ElementT, QueueT>::LLThreadSafeQueue(size_t capacity) :
mCapacity(capacity),
mClosed(false)
{
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index aaa6df325c..58bedacf43 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -121,9 +121,14 @@ U32 micro_sleep(U64 us, U32 max_yields)
U64 start = get_clock_count();
// This is kernel dependent. Currently, our kernel generates software clock
// interrupts at 250 Hz (every 4,000 microseconds).
- const U64 KERNEL_SLEEP_INTERVAL_US = 4000;
-
- S32 num_sleep_intervals = (us - (KERNEL_SLEEP_INTERVAL_US >> 1)) / KERNEL_SLEEP_INTERVAL_US;
+ const S64 KERNEL_SLEEP_INTERVAL_US = 4000;
+
+ // Use signed arithmetic to discover whether a sleep is even necessary. If
+ // either 'us' or KERNEL_SLEEP_INTERVAL_US is unsigned, the compiler
+ // promotes the difference to unsigned. If 'us' is less than half
+ // KERNEL_SLEEP_INTERVAL_US, the unsigned difference will be hugely
+ // positive, resulting in a crazy long wait.
+ auto num_sleep_intervals = (S64(us) - (KERNEL_SLEEP_INTERVAL_US >> 1)) / KERNEL_SLEEP_INTERVAL_US;
if (num_sleep_intervals > 0)
{
U64 sleep_time = (num_sleep_intervals * KERNEL_SLEEP_INTERVAL_US) - (KERNEL_SLEEP_INTERVAL_US >> 1);
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index acdda5fe1e..ff671a8370 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -65,7 +65,7 @@ void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent )
llassert_always(parent != mBlock);
llassert_always(parent != NULL);
- TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(parent->getIndex());
+ TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(narrow(parent->getIndex()));
if (!parent_tree_node) return;
if (mParent)
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index fcd8753f75..580cf0a5fd 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -340,7 +340,7 @@ inline void claim_alloc(MemStatHandle& measurement, const T& value)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
- S32 size = MeasureMem<T>::measureFootprint(value);
+ auto size = MeasureMem<T>::measureFootprint(value);
if(size == 0) return;
MemAccumulator& accumulator = measurement.getCurrentAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
@@ -353,7 +353,7 @@ inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
- S32 size = MeasureMem<T>::measureFootprint(value);
+ auto size = MeasureMem<T>::measureFootprint(value);
if(size == 0) return;
MemAccumulator& accumulator = measurement.getCurrentAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index fe447d5319..6bd886ae98 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -96,9 +96,9 @@ void AccumulatorBufferGroup::makeCurrent()
ThreadRecorder* thread_recorder = get_thread_recorder();
AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
// update stacktimer parent pointers
- for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
+ for (size_t i = 0, end_i = mStackTimers.size(); i < end_i; i++)
{
- TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
+ TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(narrow(i));
if (tree_node)
{
timer_accumulator_buffer[i].mParent = tree_node->mParent;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 8cbb0db135..dd148dd08a 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -606,7 +606,8 @@ void PeriodicRecording::nextPeriod()
mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
old_recording.splitTo(getCurRecording());
- mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
+ mNumRecordedPeriods = mRecordingPeriods.empty()? 0 :
+ llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
}
void PeriodicRecording::appendRecording(Recording& recording)
@@ -625,21 +626,21 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
getCurRecording().update();
other.getCurRecording().update();
- const S32 other_recording_slots = other.mRecordingPeriods.size();
- const S32 other_num_recordings = other.getNumRecordedPeriods();
- const S32 other_current_recording_index = other.mCurPeriod;
- const S32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
+ const auto other_recording_slots = other.mRecordingPeriods.size();
+ const auto other_num_recordings = other.getNumRecordedPeriods();
+ const auto other_current_recording_index = other.mCurPeriod;
+ const auto other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
// append first recording into our current slot
getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
// from now on, add new recordings for everything after the first
- S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+ auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
if (mAutoResize)
{
// push back recordings for everything in the middle
- S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+ auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
while (other_index != other_current_recording_index)
{
mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
@@ -652,8 +653,8 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
}
- mCurPeriod = mRecordingPeriods.size() - 1;
- mNumRecordedPeriods = mRecordingPeriods.size() - 1;
+ mCurPeriod = mRecordingPeriods.empty()? 0 : mRecordingPeriods.size() - 1;
+ mNumRecordedPeriods = mCurPeriod;
}
else
{
@@ -682,7 +683,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
llassert(num_to_copy >= 1);
// advance to last recording period copied, and make that our current period
mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
- mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
+ mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
}
// end with fresh period, otherwise next appendPeriodicRecording() will merge the first
@@ -695,10 +696,10 @@ F64Seconds PeriodicRecording::getDuration() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
F64Seconds duration;
- S32 num_periods = mRecordingPeriods.size();
- for (S32 i = 1; i <= num_periods; i++)
+ auto num_periods = mRecordingPeriods.size();
+ for (size_t i = 1; i <= num_periods; i++)
{
- S32 index = (mCurPeriod + num_periods - i) % num_periods;
+ auto index = (mCurPeriod + num_periods - i) % num_periods;
duration += mRecordingPeriods[index].getDuration();
}
return duration;
@@ -734,16 +735,16 @@ const Recording& PeriodicRecording::getCurRecording() const
return mRecordingPeriods[mCurPeriod];
}
-Recording& PeriodicRecording::getPrevRecording( S32 offset )
+Recording& PeriodicRecording::getPrevRecording( size_t offset )
{
- S32 num_periods = mRecordingPeriods.size();
+ auto num_periods = mRecordingPeriods.size();
offset = llclamp(offset, 0, num_periods - 1);
return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
}
-const Recording& PeriodicRecording::getPrevRecording( S32 offset ) const
+const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
{
- S32 num_periods = mRecordingPeriods.size();
+ auto num_periods = mRecordingPeriods.size();
offset = llclamp(offset, 0, num_periods - 1);
return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
}
@@ -790,7 +791,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
getCurRecording().splitTo(other.getCurRecording());
}
-F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -812,7 +813,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32
: NaN;
}
-F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -835,7 +836,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32
}
// calculates means using aggregates per period
-F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -858,7 +859,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S3
: NaN;
}
-F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -883,7 +884,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
: NaN;
}
-F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -905,7 +906,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S3
: NaN;
}
-F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -928,7 +929,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32
}
-F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -951,7 +952,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S
: NaN;
}
-F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -977,7 +978,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat,
return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
-F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1003,7 +1004,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
}
-F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1018,12 +1019,12 @@ F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& st
return min_val;
}
-F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1038,12 +1039,12 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& sta
return max_val;
}
-F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1059,12 +1060,12 @@ F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& s
return mean / F64(num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1089,7 +1090,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAc
: NaN);
}
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods)
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodStandardDeviation(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 556b7470cf..8b56721f42 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -334,7 +334,7 @@ namespace LLTrace
~PeriodicRecording();
void nextPeriod();
- S32 getNumRecordedPeriods()
+ auto getNumRecordedPeriods()
{
// current period counts if not active
return mNumRecordedPeriods + (isStarted() ? 0 : 1);
@@ -348,24 +348,24 @@ namespace LLTrace
const Recording& getLastRecording() const;
Recording& getCurRecording();
const Recording& getCurRecording() const;
- Recording& getPrevRecording(S32 offset);
- const Recording& getPrevRecording(S32 offset) const;
+ Recording& getPrevRecording(size_t offset);
+ const Recording& getPrevRecording(size_t offset) const;
Recording snapshotCurRecording() const;
template <typename T>
- S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ auto getSampleCount(const StatType<T>& stat, size_t num_periods = S32_MAX)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
- S32 num_samples = 0;
- for (S32 i = 1; i <= num_periods; i++)
+ size_t num_samples = 0;
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
num_samples += recording.getSampleCount(stat);
}
return num_samples;
- }
+ }
//
// PERIODIC MIN
@@ -373,7 +373,7 @@ namespace LLTrace
// catch all for stats that have a defined sum
template <typename T>
- typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -396,33 +396,33 @@ namespace LLTrace
}
template<typename T>
- T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMin(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- T getPeriodMin(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMin(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- T getPeriodMin(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
- F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
- F64Kilobytes getPeriodMin(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = S32_MAX);
template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -437,7 +437,7 @@ namespace LLTrace
}
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
@@ -449,7 +449,7 @@ namespace LLTrace
// catch all for stats that have a defined sum
template <typename T>
- typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -472,33 +472,33 @@ namespace LLTrace
}
template<typename T>
- T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- T getPeriodMax(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMax(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- T getPeriodMax(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
- F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
- F64Kilobytes getPeriodMax(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = S32_MAX);
template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -513,7 +513,7 @@ namespace LLTrace
}
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
@@ -525,7 +525,7 @@ namespace LLTrace
// catch all for stats that have a defined sum
template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -546,32 +546,32 @@ namespace LLTrace
}
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMean(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMean(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
- F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
- F64Kilobytes getPeriodMean(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = S32_MAX);
template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -593,16 +593,16 @@ namespace LLTrace
}
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
- F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -622,7 +622,7 @@ namespace LLTrace
}
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
@@ -632,25 +632,25 @@ namespace LLTrace
// PERIODIC STANDARD DEVIATION
//
- F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
- F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
- F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
- F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = S32_MAX);
private:
// implementation for LLStopWatchControlsMixin
@@ -662,8 +662,8 @@ namespace LLTrace
private:
std::vector<Recording> mRecordingPeriods;
const bool mAutoResize;
- S32 mCurPeriod;
- S32 mNumRecordedPeriods;
+ size_t mCurPeriod;
+ size_t mNumRecordedPeriods;
};
PeriodicRecording& get_frame_recording();
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 26db15eaa0..4028a5ce97 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -125,7 +125,7 @@ ThreadRecorder::~ThreadRecorder()
#endif
}
-TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
+TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( size_t index )
{
#if LL_TRACE_ENABLED
if (0 <= index && index < mNumTimeBlockTreeNodes)
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 8fd1e5ef58..8ee6729ac6 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -57,7 +57,7 @@ namespace LLTrace
void pullFromChildren();
void pushToParent();
- TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
+ TimeBlockTreeNode* getTimeBlockTreeNode(size_t index);
protected:
void init();
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 4b91b2caca..97838e296e 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -81,9 +81,9 @@ void LLWorkerThread::clearDeleteList()
}
// virtual
-S32 LLWorkerThread::update(F32 max_time_ms)
+size_t LLWorkerThread::update(F32 max_time_ms)
{
- S32 res = LLQueuedThread::update(max_time_ms);
+ auto res = LLQueuedThread::update(max_time_ms);
// Delete scheduled workers
std::vector<LLWorkerClass*> delete_list;
std::vector<LLWorkerClass*> abort_list;
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 0387e75c65..e3004d7242 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -88,7 +88,7 @@ public:
LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
~LLWorkerThread();
- /*virtual*/ S32 update(F32 max_time_ms);
+ /*virtual*/ size_t update(F32 max_time_ms);
handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index b07805b628..da8512169c 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -26,16 +26,23 @@
#ifndef LL_STDTYPES_H
#define LL_STDTYPES_H
+#include <cassert>
#include <cfloat>
#include <climits>
+#include <limits>
+#include <type_traits>
-typedef signed char S8;
+typedef signed char S8;
typedef unsigned char U8;
typedef signed short S16;
typedef unsigned short U16;
-typedef signed int S32;
+typedef signed int S32;
typedef unsigned int U32;
+// to express an index that might go negative
+// (ssize_t is provided by SOME compilers, don't collide)
+typedef typename std::make_signed<size_t>::type llssize;
+
#if LL_WINDOWS
// https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type
// https://docs.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp
@@ -45,7 +52,7 @@ typedef unsigned int U32;
// The version of clang available with VS 2019 also defines wchar_t as __wchar_t
// which is also 16 bits.
// In any case, llwchar should be a UTF-32 type.
-typedef U32 llwchar;
+typedef U32 llwchar;
#else
typedef wchar_t llwchar;
// What we'd actually want is a simple module-scope 'if constexpr' to test
@@ -76,7 +83,7 @@ typedef double F64;
typedef S32 BOOL;
typedef U8 KEY;
typedef U32 MASK;
-typedef U32 TPACKETID;
+typedef U32 TPACKETID;
// Use #define instead of consts to avoid conversion headaches
#define S8_MAX (SCHAR_MAX)
@@ -118,4 +125,95 @@ typedef U8 LLPCode;
typedef int intptr_t;
#endif
+/*****************************************************************************
+* Narrowing
+*****************************************************************************/
+/**
+ * narrow() is used to cast a wider type to a narrower type with validation.
+ *
+ * In many cases we take the size() of a container and try to pass it to an
+ * S32 or a U32 parameter. We used to be able to assume that the size of
+ * anything we could fit into memory could be expressed as a 32-bit int. With
+ * 64-bit viewers, though, size_t as returned by size() and length() and so
+ * forth is 64 bits, and the compiler is unhappy about stuffing such values
+ * into 32-bit types.
+ *
+ * It works to force the compiler to truncate, e.g. static_cast<S32>(len) or
+ * S32(len) or (S32)len, but we can do better.
+ *
+ * For:
+ * @code
+ * std::vector<Object> container;
+ * void somefunc(S32 size);
+ * @endcode
+ * call:
+ * @code
+ * somefunc(narrow(container.size()));
+ * @endcode
+ *
+ * narrow() truncates but, in RelWithDebInfo builds, it validates (using
+ * assert()) that the passed value can validly be expressed by the destination
+ * type.
+ */
+// narrow_holder is a struct that accepts the passed value as its original
+// type and provides templated conversion functions to other types. Once we're
+// building with compilers that support Class Template Argument Deduction, we
+// can rename this class template 'narrow' and eliminate the narrow() factory
+// function below.
+template <typename FROM>
+class narrow_holder
+{
+private:
+ FROM mValue;
+
+public:
+ narrow_holder(FROM value): mValue(value) {}
+
+ /*---------------------- Narrowing unsigned to signed ----------------------*/
+ template <typename TO,
+ typename std::enable_if<std::is_unsigned<FROM>::value &&
+ std::is_signed<TO>::value,
+ bool>::type = true>
+ inline
+ operator TO() const
+ {
+ // The reason we skip the
+ // assert(value >= std::numeric_limits<TO>::lowest());
+ // like the overload below is that to perform the above comparison,
+ // the compiler promotes the signed lowest() to the unsigned FROM
+ // type, making it hugely positive -- so a reasonable 'value' will
+ // always fail the assert().
+ assert(mValue <= std::numeric_limits<TO>::max());
+ return static_cast<TO>(mValue);
+ }
+
+ /*----------------------- Narrowing all other cases ------------------------*/
+ template <typename TO,
+ typename std::enable_if<! (std::is_unsigned<FROM>::value &&
+ std::is_signed<TO>::value),
+ bool>::type = true>
+ inline
+ operator TO() const
+ {
+ // two different assert()s so we can tell which condition failed
+ assert(mValue <= std::numeric_limits<TO>::max());
+ // Funny, with floating point types min() is "positive epsilon" rather
+ // than "largest negative" -- that's lowest().
+ assert(mValue >= std::numeric_limits<TO>::lowest());
+ // Do we really expect to use this with floating point types?
+ // If so, does it matter if a very small value truncates to zero?
+ //assert(fabs(mValue) >= std::numeric_limits<TO>::min());
+ return static_cast<TO>(mValue);
+ }
+};
+
+/// narrow() factory function returns a narrow_holder<FROM>(), which can be
+/// implicitly converted to the target type.
+template <typename FROM>
+inline
+narrow_holder<FROM> narrow(FROM value)
+{
+ return { value };
+}
+
#endif
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index 9da1ecfd67..966dc2c5aa 100644
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -335,7 +335,7 @@ namespace tut
// Full, partial defaults arrays for params for freena(), freenb()
LLSD dft_array_full, dft_array_partial;
// Start index of partial defaults arrays
- const LLSD::Integer partial_offset;
+ const size_t partial_offset;
// Full, partial defaults maps for params for freena(), freenb()
LLSD dft_map_full, dft_map_partial;
// Most of the above are indexed by "a" or "b". Useful to have an
diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
index 15ffe68e67..6f8aaaa0cb 100644
--- a/indra/llcommon/tests/llsingleton_test.cpp
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -47,8 +47,8 @@ public: \
DEP_INIT /* dependency in initSingleton */ \
} sDepFlag; \
\
- void initSingleton(); \
- void cleanupSingleton(); \
+ void initSingleton() override; \
+ void cleanupSingleton() override; \
}; \
\
CLS::dep_flag CLS::sDepFlag = DEP_NONE
@@ -300,7 +300,7 @@ namespace tut
{
LLSINGLETON_EMPTY_CTOR(CircularPInit);
public:
- virtual void initSingleton()
+ virtual void initSingleton() override
{
// never mind indirection, just go straight for the circularity
CircularPInit *pt = getInstance();
diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h
index 0c3a541196..92bc7da940 100644
--- a/indra/llcommon/threadsafeschedule.h
+++ b/indra/llcommon/threadsafeschedule.h
@@ -82,7 +82,7 @@ namespace LL
using TimePoint = ThreadSafeSchedulePrivate::TimePoint;
using Clock = TimePoint::clock;
- ThreadSafeSchedule(U32 capacity=1024):
+ ThreadSafeSchedule(size_t capacity=1024):
super(capacity)
{}
diff --git a/indra/llcorehttp/bufferarray.cpp b/indra/llcorehttp/bufferarray.cpp
index e0b2876a00..8d2e7c6a63 100644
--- a/indra/llcorehttp/bufferarray.cpp
+++ b/indra/llcorehttp/bufferarray.cpp
@@ -196,7 +196,7 @@ size_t BufferArray::read(size_t pos, void * dst, size_t len)
return 0;
size_t result(0), offset(0);
- const int block_limit(mBlocks.size());
+ const auto block_limit(mBlocks.size());
int block_start(findBlock(pos, &offset));
if (block_start < 0)
return 0;
@@ -228,7 +228,7 @@ size_t BufferArray::write(size_t pos, const void * src, size_t len)
return 0;
size_t result(0), offset(0);
- const int block_limit(mBlocks.size());
+ const auto block_limit(mBlocks.size());
int block_start(findBlock(pos, &offset));
if (block_start >= 0)
@@ -288,7 +288,7 @@ int BufferArray::findBlock(size_t pos, size_t * ret_offset)
if (pos >= mLen)
return -1; // Doesn't exist
- const int block_limit(mBlocks.size());
+ const int block_limit(narrow(mBlocks.size()));
for (int i(0); i < block_limit; ++i)
{
if (pos < mBlocks[i]->mUsed)
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 0dbb744bcf..ff4336d2de 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -46,7 +46,7 @@ LLImageDecodeThread::~LLImageDecodeThread()
// MAIN THREAD
// virtual
-S32 LLImageDecodeThread::update(F32 max_time_ms)
+size_t LLImageDecodeThread::update(F32 max_time_ms)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLMutexLock lock(mCreationMutex);
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index 1bfb0ddfd3..54814c24c5 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -78,7 +78,7 @@ public:
handle_t decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux,
Responder* responder);
- S32 update(F32 max_time_ms);
+ size_t update(F32 max_time_ms);
// Used by unit tests to check the consistency of the thread instance
S32 tut_size();
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 675da65af2..818a8b5cc3 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -60,7 +60,7 @@ class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
{
LLSINGLETON(LLFolderDictionary);
protected:
- virtual LLFolderType::EType notFound() const
+ virtual LLFolderType::EType notFound() const override
{
return LLFolderType::FT_NONE;
}
diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp
index 81485b3a97..bc604097da 100644
--- a/indra/llinventory/llinventorysettings.cpp
+++ b/indra/llinventory/llinventorysettings.cpp
@@ -62,7 +62,7 @@ class LLSettingsDictionary : public LLSingleton<LLSettingsDictionary>,
{
LLSINGLETON(LLSettingsDictionary);
- void initSingleton();
+ void initSingleton() override;
};
LLSettingsDictionary::LLSettingsDictionary()
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 83a92f08d0..a129f0a6f0 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -152,24 +152,24 @@ LLSettingsSky::validation_list_t legacyHazeValidationList()
{
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray,
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(3.0f, 3.0f, 3.0f, "*"))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray,
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(3.0f, 3.0f, 3.0f, "*"))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray,
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(3.0f, 3.0f, 3.0f, "*"))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 5.0f))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 5.0f))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0001f, 2.0f))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(1000.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0001f, 1000.0f))));
}
return legacyHazeValidation;
}
@@ -180,19 +180,19 @@ LLSettingsSky::validation_list_t rayleighValidationList()
if (rayleighValidation.empty())
{
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
}
return rayleighValidation;
}
@@ -203,19 +203,19 @@ LLSettingsSky::validation_list_t absorptionValidationList()
if (absorptionValidation.empty())
{
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
}
return absorptionValidation;
}
@@ -226,22 +226,22 @@ LLSettingsSky::validation_list_t mieValidationList()
if (mieValidation.empty())
{
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
}
return mieValidation;
}
@@ -546,89 +546,86 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
static validation_list_t validation;
if (validation.empty())
- { // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the
- // copy constructor for LLSDArray. Directly binding the LLSDArray as
- // a parameter without first wrapping it in a pure LLSD object will result
- // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
+ {
validation.push_back(Validator(SETTING_BLOOM_TEXTUREID, true, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_RAINBOW_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_HALO_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(1.0f, 1.0f, 1.0f, "*"))));
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(1.0f)(1.0f)(3.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(1.0f, 1.0f, 3.0f, "*"))));
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(1.0f, 1.0f, 1.0f, "*"))));
validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.001f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.001f, 3.0f))));
validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(-50.0f)(-50.0f)),
- LLSD(LLSDArray(50.0f)(50.0f)))));
+ llsd::array(-50.0f, -50.0f),
+ llsd::array(50.0f, 50.0f))));
validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_CLOUD_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(2000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 2000.0f))));
validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 20.0f))));
validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.2f)("*")(-10.0f)("*")),
- LLSD(LLSDArray(40.0f)("*")(10.0f)("*")))));
+ llsd::array(0.2f, "*", -10.0f, "*"),
+ llsd::array(40.0f, "*", 10.0f, "*"))));
validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(10000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 10000.0f))));
validation.push_back(Validator(SETTING_MOON_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
validation.push_back(Validator(SETTING_MOON_SCALE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.25f, 20.0f)), LLSD::Real(1.0)));
validation.push_back(Validator(SETTING_MOON_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(500.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 500.0f))));
validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
- LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+ llsd::array(0.0f, 0.0f, 0.0f, "*"),
+ llsd::array(3.0f, 3.0f, 3.0f, "*"))));
validation.push_back(Validator(SETTING_SUN_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
validation.push_back(Validator(SETTING_SUN_SCALE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.25f, 20.0f)), LLSD::Real(1.0)));
validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f))));
validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f))));
validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f))));
validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(0.1f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 0.1f))));
validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(5.0f)(1000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(5.0f, 1000.0f))));
validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
@@ -719,7 +716,7 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position)
dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
dfltsetting[SETTING_CLOUD_SCALE] = LLSD::Real(0.4199);
- dfltsetting[SETTING_CLOUD_SCROLL_RATE] = LLSDArray(0.0f)(0.0f);
+ dfltsetting[SETTING_CLOUD_SCROLL_RATE] = llsd::array(0.0f, 0.0f);
dfltsetting[SETTING_CLOUD_SHADOW] = LLSD::Real(0.2699);
dfltsetting[SETTING_CLOUD_VARIANCE] = LLSD::Real(0.0);
diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp
index 90f99e8198..f19beb5be5 100644
--- a/indra/llinventory/llsettingswater.cpp
+++ b/indra/llinventory/llsettingswater.cpp
@@ -222,42 +222,38 @@ LLSettingsWater::validation_list_t LLSettingsWater::validationList()
static validation_list_t validation;
if (validation.empty())
- { // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the
- // copy constructor for LLSDArray. Directly binding the LLSDArray as
- // a parameter without first wrapping it in a pure LLSD object will result
- // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
-
+ {
validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-0.5f)(0.5f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(-0.5f, 0.5f))));
validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)),
- LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f)))));
+ llsd::array(0.0f, 0.0f, 0.0f, 1.0f),
+ llsd::array(1.0f, 1.0f, 1.0f, 1.0f))));
validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-10.0f)(10.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(-10.0f, 10.0f))));
validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 20.0f))));
validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f))));
validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(0.0f)(0.0f)(0.0f)),
- LLSD(LLSDArray(10.0f)(10.0f)(10.0f)))));
+ llsd::array(0.0f, 0.0f, 0.0f),
+ llsd::array(10.0f, 10.0f, 10.0f))));
validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 3.0f))));
validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 3.0f))));
validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(-20.0f)(-20.0f)),
- LLSD(LLSDArray(20.0f)(20.0f)))));
+ llsd::array(-20.0f, -20.0f),
+ llsd::array(20.0f, 20.0f))));
validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray,
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
- LLSD(LLSDArray(-20.0f)(-20.0f)),
- LLSD(LLSDArray(20.0f)(20.0f)))));
+ llsd::array(-20.0f, -20.0f),
+ llsd::array(20.0f, 20.0f))));
}
return validation;
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 281f1bd87a..1879ff2a05 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2416,7 +2416,7 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
mVolumeFaces.resize(face_count);
- for (U32 i = 0; i < face_count; ++i)
+ for (size_t i = 0; i < face_count; ++i)
{
LLVolumeFace& face = mVolumeFaces[i];
@@ -5482,14 +5482,12 @@ bool LLVolumeFace::cacheOptimize()
new_indices.push_back(tri->mVertex[2]->mIdx);
tri->complete();
- U32 breaks = 0;
for (U32 i = 1; i < mNumIndices/3; ++i)
{
cache.updateScores();
tri = cache.mBestTriangle;
if (!tri)
{
- breaks++;
for (U32 j = 0; j < triangle_data.size(); ++j)
{
if (triangle_data[j].mActive)
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 8baa2e328b..a9a292958f 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -271,7 +271,6 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
{
- S32 resent_packets = 0;
LLReliablePacket *packetp;
@@ -375,7 +374,6 @@ S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
// Don't remove it yet, it still gets to try to resend at least once.
++iter;
}
- resent_packets++;
}
else
{
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index 1c97133723..8be4c64dfc 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -106,7 +106,7 @@ public:
private:
virtual ~LLExperienceCache();
- virtual void initSingleton();
+ virtual void initSingleton() override;
typedef boost::function<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLCore::HttpRequest::ptr_t, std::string)> permissionInvoker_fn;
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index 25f6977e14..8a64cdbfaa 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -226,7 +226,7 @@ class LLProxy: public LLSingleton<LLProxy>
LLSINGLETON(LLProxy);
LOG_CLASS(LLProxy);
- /*virtual*/ void initSingleton();
+ /*virtual*/ void initSingleton() override;
public:
// Static check for enabled status for UDP packets. Call from main thread only.
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index c5cf1100d5..2bc09accb2 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -14,6 +14,7 @@ set(llrender_SOURCE_FILES
llcubemap.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
+ llfontfreetypesvg.cpp
llfontgl.cpp
llfontregistry.cpp
llgl.cpp
@@ -41,6 +42,7 @@ set(llrender_HEADER_FILES
llcubemap.h
llfontgl.h
llfontfreetype.h
+ llfontfreetypesvg.h
llfontbitmapcache.h
llfontregistry.h
llgl.h
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index c71e24c83a..42b0045cf3 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -30,14 +30,7 @@
#include "llfontbitmapcache.h"
LLFontBitmapCache::LLFontBitmapCache()
-: mNumComponents(0),
- mBitmapWidth(0),
- mBitmapHeight(0),
- mBitmapNum(-1),
- mMaxCharWidth(0),
- mMaxCharHeight(0),
- mCurrentOffsetX(1),
- mCurrentOffsetY(1)
+
{
}
@@ -45,121 +38,149 @@ LLFontBitmapCache::~LLFontBitmapCache()
{
}
-void LLFontBitmapCache::init(S32 num_components,
- S32 max_char_width,
+void LLFontBitmapCache::init(S32 max_char_width,
S32 max_char_height)
{
reset();
- mNumComponents = num_components;
mMaxCharWidth = max_char_width;
mMaxCharHeight = max_char_height;
+
+ S32 image_width = mMaxCharWidth * 20;
+ S32 pow_iw = 2;
+ while (pow_iw < image_width)
+ {
+ pow_iw <<= 1;
+ }
+ image_width = pow_iw;
+ image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
+
+ mBitmapWidth = image_width;
+ mBitmapHeight = image_width;
}
-LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
+LLImageRaw *LLFontBitmapCache::getImageRaw(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- if (bitmap_num >= mImageRawVec.size())
- return NULL;
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageRawVec[bitmap_idx].size())
+ return nullptr;
- return mImageRawVec[bitmap_num];
+ return mImageRawVec[bitmap_idx][bitmap_num];
}
-LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const
+LLImageGL *LLFontBitmapCache::getImageGL(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- if (bitmap_num >= mImageGLVec.size())
- return NULL;
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageGLVec[bitmap_idx].size())
+ return nullptr;
- return mImageGLVec[bitmap_num];
+ return mImageGLVec[bitmap_idx][bitmap_num];
}
-BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32 &pos_x, S32 &pos_y, S32& bitmap_num)
+BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyphType bitmap_type, U32& bitmap_num)
{
- if ((mBitmapNum<0) || (mCurrentOffsetX + width + 1) > mBitmapWidth)
+ if (bitmap_type >= EFontGlyphType::Count)
+ {
+ return FALSE;
+ }
+
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth)
{
- if ((mBitmapNum<0) || (mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight)
+ if ((mImageRawVec[bitmap_idx].empty()) || (mCurrentOffsetY[bitmap_idx] + 2*mMaxCharHeight + 2) > mBitmapHeight)
{
// We're out of space in the current image, or no image
// has been allocated yet. Make a new one.
-
- mImageRawVec.push_back(new LLImageRaw);
- mBitmapNum = mImageRawVec.size()-1;
- LLImageRaw *image_raw = getImageRaw(mBitmapNum);
-
- // Make corresponding GL image.
- mImageGLVec.push_back(new LLImageGL(FALSE));
- LLImageGL *image_gl = getImageGL(mBitmapNum);
-
- S32 image_width = mMaxCharWidth * 20;
- S32 pow_iw = 2;
- while (pow_iw < image_width)
+
+ S32 image_width = mMaxCharWidth * 20;
+ S32 pow_iw = 2;
+ while (pow_iw < image_width)
+ {
+ pow_iw *= 2;
+ }
+ image_width = pow_iw;
+ image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
+ S32 image_height = image_width;
+
+ mBitmapWidth = image_width;
+ mBitmapHeight = image_height;
+
+ S32 num_components = getNumComponents(bitmap_type);
+ mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
+ bitmap_num = mImageRawVec[bitmap_idx].size() - 1;
+
+ LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
+ if (EFontGlyphType::Grayscale == bitmap_type)
{
- pow_iw *= 2;
+ image_raw->clear(255, 0);
}
- image_width = pow_iw;
- image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
- S32 image_height = image_width;
-
- image_raw->resize(image_width, image_height, mNumComponents);
-
- mBitmapWidth = image_width;
- mBitmapHeight = image_height;
- switch (mNumComponents)
- {
- case 1:
- image_raw->clear();
- break;
- case 2:
- image_raw->clear(255, 0);
- break;
- }
+ // Make corresponding GL image.
+ mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
+ LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
// Start at beginning of the new image.
- mCurrentOffsetX = 1;
- mCurrentOffsetY = 1;
+ mCurrentOffsetX[bitmap_idx] = 1;
+ mCurrentOffsetY[bitmap_idx] = 1;
- // Attach corresponding GL texture.
- image_gl->createGLTexture(0, image_raw);
+ // Attach corresponding GL texture. (*TODO: is this needed?)
gGL.getTexUnit(0)->bind(image_gl);
image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE);
}
else
{
// Move to next row in current image.
- mCurrentOffsetX = 1;
- mCurrentOffsetY += mMaxCharHeight + 1;
+ mCurrentOffsetX[bitmap_idx] = 1;
+ mCurrentOffsetY[bitmap_idx] += mMaxCharHeight + 1;
}
}
- pos_x = mCurrentOffsetX;
- pos_y = mCurrentOffsetY;
- bitmap_num = mBitmapNum;
+ pos_x = mCurrentOffsetX[bitmap_idx];
+ pos_y = mCurrentOffsetY[bitmap_idx];
+ bitmap_num = getNumBitmaps(bitmap_type) - 1;
- mCurrentOffsetX += width + 1;
+ mCurrentOffsetX[bitmap_idx] += width + 1;
return TRUE;
}
void LLFontBitmapCache::destroyGL()
{
- for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec.begin();
- it != mImageGLVec.end(); ++it)
+ for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
- (*it)->destroyGLTexture();
+ for (LLImageGL* image_gl : mImageGLVec[idx])
+ {
+ image_gl->destroyGLTexture();
+ }
}
}
void LLFontBitmapCache::reset()
{
- mImageRawVec.clear();
-
- mImageGLVec.clear();
+ for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
+ {
+ mImageRawVec[idx].clear();
+ mImageGLVec[idx].clear();
+ mCurrentOffsetX[idx] = 1;
+ mCurrentOffsetY[idx] = 1;
+ }
mBitmapWidth = 0;
mBitmapHeight = 0;
- mBitmapNum = -1;
- mCurrentOffsetX = 1;
- mCurrentOffsetY = 1;
}
+//static
+U32 LLFontBitmapCache::getNumComponents(EFontGlyphType bitmap_type)
+{
+ switch (bitmap_type)
+ {
+ case EFontGlyphType::Grayscale:
+ return 2;
+ case EFontGlyphType::Color:
+ return 4;
+ default:
+ llassert(false);
+ return 2;
+ }
+}
diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h
index 7de3a6b56f..c63281ab70 100644
--- a/indra/llrender/llfontbitmapcache.h
+++ b/indra/llrender/llfontbitmapcache.h
@@ -30,6 +30,14 @@
#include <vector>
#include "lltrace.h"
+enum class EFontGlyphType : U32
+{
+ Grayscale = 0,
+ Color,
+ Count,
+ Unspecified,
+};
+
// Maintain a collection of bitmaps containing rendered glyphs.
// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.
class LLFontBitmapCache
@@ -39,35 +47,35 @@ public:
~LLFontBitmapCache();
// Need to call this once, before caching any glyphs.
- void init(S32 num_components,
- S32 max_char_width,
+ void init(S32 max_char_width,
S32 max_char_height);
void reset();
- BOOL nextOpenPos(S32 width, S32 &posX, S32 &posY, S32 &bitmapNum);
+ BOOL nextOpenPos(S32 width, S32& posX, S32& posY, EFontGlyphType bitmapType, U32& bitmapNum);
void destroyGL();
- LLImageRaw *getImageRaw(U32 bitmapNum = 0) const;
- LLImageGL *getImageGL(U32 bitmapNum = 0) const;
-
+ LLImageRaw* getImageRaw(EFontGlyphType bitmapType, U32 bitmapNum) const;
+ LLImageGL* getImageGL(EFontGlyphType bitmapType, U32 bitmapNum) const;
+
S32 getMaxCharWidth() const { return mMaxCharWidth; }
- S32 getNumComponents() const { return mNumComponents; }
+ U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? mImageRawVec[static_cast<U32>(bitmapType)].size() : 0; }
S32 getBitmapWidth() const { return mBitmapWidth; }
S32 getBitmapHeight() const { return mBitmapHeight; }
+protected:
+ static U32 getNumComponents(EFontGlyphType bitmap_type);
+
private:
- S32 mNumComponents;
- S32 mBitmapWidth;
- S32 mBitmapHeight;
- S32 mBitmapNum;
- S32 mMaxCharWidth;
- S32 mMaxCharHeight;
- S32 mCurrentOffsetX;
- S32 mCurrentOffsetY;
- std::vector<LLPointer<LLImageRaw> > mImageRawVec;
- std::vector<LLPointer<LLImageGL> > mImageGLVec;
+ S32 mBitmapWidth = 0;
+ S32 mBitmapHeight = 0;
+ S32 mCurrentOffsetX[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
+ S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
+ S32 mMaxCharWidth = 0;
+ S32 mMaxCharHeight = 0;
+ std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
+ std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
};
#endif //LL_LLFONTBITMAPCACHE_H
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index e964d1586f..e4010579b3 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -34,14 +34,17 @@
#ifdef LL_WINDOWS
#include <freetype2\freetype\ftsystem.h>
#endif
+#include "llfontfreetypesvg.h"
// For some reason, this won't work if it's not wrapped in the ifdef
#ifdef FT_FREETYPE_H
#include FT_FREETYPE_H
#endif
+#include "lldir.h"
#include "llerror.h"
#include "llimage.h"
+#include "llimagepng.h"
//#include "llimagej2c.h"
#include "llmath.h" // Linden math
#include "llstring.h"
@@ -49,6 +52,8 @@
#include "llfontbitmapcache.h"
#include "llgl.h"
+#define ENABLE_OT_SVG_SUPPORT
+
FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
LLFontManager *gFontManagerp = NULL;
@@ -81,6 +86,16 @@ LLFontManager::LLFontManager()
LL_ERRS() << "Freetype initialization failure!" << LL_ENDL;
FT_Done_FreeType(gFTLibrary);
}
+
+#ifdef ENABLE_OT_SVG_SUPPORT
+ SVG_RendererHooks hooks = {
+ LLFontFreeTypeSvgRenderer::OnInit,
+ LLFontFreeTypeSvgRenderer::OnFree,
+ LLFontFreeTypeSvgRenderer::OnRender,
+ LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot,
+ };
+ FT_Property_Set(gFTLibrary, "ot-svg", "svg-hooks", &hooks);
+#endif
}
LLFontManager::~LLFontManager()
@@ -89,8 +104,9 @@ LLFontManager::~LLFontManager()
}
-LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
+LLFontGlyphInfo::LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type)
: mGlyphIndex(index),
+ mGlyphType(glyph_type),
mWidth(0), // In pixels
mHeight(0), // In pixels
mXAdvance(0.f), // In pixels
@@ -99,10 +115,25 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
mYBitmapOffset(0), // Offset to the origin in the bitmap
mXBearing(0), // Distance from baseline to left in pixels
mYBearing(0), // Distance from baseline to top in pixels
- mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph
+ mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
{
}
+LLFontGlyphInfo::LLFontGlyphInfo(const LLFontGlyphInfo& fgi)
+ : mGlyphIndex(fgi.mGlyphIndex)
+ , mGlyphType(fgi.mGlyphType)
+ , mWidth(fgi.mWidth)
+ , mHeight(fgi.mHeight)
+ , mXAdvance(fgi.mXAdvance)
+ , mYAdvance(fgi.mYAdvance)
+ , mXBitmapOffset(fgi.mXBitmapOffset)
+ , mYBitmapOffset(fgi.mYBitmapOffset)
+ , mXBearing(fgi.mXBearing)
+ , mYBearing(fgi.mYBearing)
+{
+ mBitmapEntry = fgi.mBitmapEntry;
+}
+
LLFontFreetype::LLFontFreetype()
: mFontBitmapCachep(new LLFontBitmapCache),
mAscender(0.f),
@@ -156,7 +187,7 @@ void ft_close_cb(FT_Stream stream) {
}
#endif
-BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
+BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)
{
// Don't leak face objects. This is also needed to deal with
// changed font file names.
@@ -220,7 +251,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
S32 max_char_width = ll_round(0.5f + (x_max - x_min));
S32 max_char_height = ll_round(0.5f + (y_max - y_min));
- mFontBitmapCachep->init(components, max_char_width, max_char_height);
+ mFontBitmapCachep->init(max_char_width, max_char_height);
if (!mFTFace->charmap)
{
@@ -231,7 +262,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (!mIsFallback)
{
// Add the default glyph
- addGlyphFromFont(this, 0, 0);
+ addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
}
mName = filename;
@@ -323,14 +354,11 @@ void LLFontFreetype::clearFontStreams()
}
#endif
-void LLFontFreetype::setFallbackFonts(const font_vector_t &font)
-{
- mFallbackFonts = font;
-}
-
-const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const
+void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor)
{
- return mFallbackFonts;
+ // Insert functor fallbacks before generic fallbacks
+ mFallbackFonts.insert((functor) ? std::find_if(mFallbackFonts.begin(), mFallbackFonts.end(), [](const fallback_font_t& fe) { return !fe.second; }) : mFallbackFonts.end(),
+ std::make_pair(fallback_font, functor));
}
F32 LLFontFreetype::getLineHeight() const
@@ -354,7 +382,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
return 0.0;
// Return existing info only if it is current
- LLFontGlyphInfo* gi = getGlyphInfo(wch);
+ LLFontGlyphInfo* gi = getGlyphInfo(wch, EFontGlyphType::Unspecified);
if (gi)
{
return gi->mXAdvance;
@@ -386,10 +414,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return 0.0;
//llassert(!mIsFallback);
- LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
+ LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
// Kern this puppy.
- LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
+ LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
@@ -420,60 +448,91 @@ BOOL LLFontFreetype::hasGlyph(llwchar wch) const
return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
}
-LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
+LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type) const
{
if (mFTFace == NULL)
return FALSE;
llassert(!mIsFallback);
+ llassert(glyph_type < EFontGlyphType::Count);
//LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL;
FT_UInt glyph_index;
+ // Fallback fonts with a functor have precedence over everything else
+ fallback_font_vector_t::const_iterator it_fallback = mFallbackFonts.cbegin();
+ for (; it_fallback != mFallbackFonts.cend() && it_fallback->second; ++it_fallback)
+ {
+ if (it_fallback->second(wch))
+ {
+ glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
+ if (glyph_index)
+ {
+ return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
+ }
+ }
+ }
+
// Initialize char to glyph map
glyph_index = FT_Get_Char_Index(mFTFace, wch);
if (glyph_index == 0)
{
//LL_INFOS() << "Trying to add glyph from fallback font!" << LL_ENDL;
- font_vector_t::const_iterator iter;
- for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++)
+ for (; it_fallback != mFallbackFonts.cend(); ++it_fallback)
{
- glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
+ glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
if (glyph_index)
{
- return addGlyphFromFont(*iter, wch, glyph_index);
+ return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
}
}
}
- char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
- if (iter == mCharGlyphInfoMap.end())
+ std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
+ char_glyph_info_map_t::iterator iter =
+ std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; });
+ if (iter == range_it.second)
{
- return addGlyphFromFont(this, wch, glyph_index);
+ return addGlyphFromFont(this, wch, glyph_index, glyph_type);
}
return NULL;
}
-LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
+LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const
{
LL_PROFILE_ZONE_SCOPED;
if (mFTFace == NULL)
return NULL;
llassert(!mIsFallback);
- fontp->renderGlyph(glyph_index);
+ fontp->renderGlyph(requested_glyph_type, glyph_index);
+
+ EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified;
+ switch (fontp->mFTFace->glyph->bitmap.pixel_mode)
+ {
+ case FT_PIXEL_MODE_MONO:
+ case FT_PIXEL_MODE_GRAY:
+ bitmap_glyph_type = EFontGlyphType::Grayscale;
+ break;
+ case FT_PIXEL_MODE_BGRA:
+ bitmap_glyph_type = EFontGlyphType::Color;
+ break;
+ default:
+ llassert_always(true);
+ break;
+ }
S32 width = fontp->mFTFace->glyph->bitmap.width;
S32 height = fontp->mFTFace->glyph->bitmap.rows;
S32 pos_x, pos_y;
- S32 bitmap_num;
- mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num);
+ U32 bitmap_num;
+ mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_glyph_type, bitmap_num);
mAddGlyphCount++;
- LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index);
+ LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index, requested_glyph_type);
gi->mXBitmapOffset = pos_x;
gi->mYBitmapOffset = pos_y;
- gi->mBitmapNum = bitmap_num;
+ gi->mBitmapEntry = std::make_pair(bitmap_glyph_type, bitmap_num);
gi->mWidth = width;
gi->mHeight = height;
gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
@@ -484,8 +543,12 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
insertGlyphInfo(wch, gi);
- llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
- || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
+ if (requested_glyph_type != bitmap_glyph_type)
+ {
+ LLFontGlyphInfo* gi_temp = new LLFontGlyphInfo(*gi);
+ gi_temp->mGlyphType = bitmap_glyph_type;
+ insertGlyphInfo(wch, gi_temp);
+ }
if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
|| fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
@@ -520,78 +583,86 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
buffer_row_stride = width;
}
- switch (mFontBitmapCachep->getNumComponents())
- {
- case 1:
- mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x,
- pos_y,
- width,
- height,
- buffer_data,
- buffer_row_stride,
- TRUE);
- break;
- case 2:
- setSubImageLuminanceAlpha(pos_x,
- pos_y,
- bitmap_num,
- width,
- height,
- buffer_data,
- buffer_row_stride);
- break;
- default:
- break;
- }
+ setSubImageLuminanceAlpha(pos_x,
+ pos_y,
+ bitmap_num,
+ width,
+ height,
+ buffer_data,
+ buffer_row_stride);
if (tmp_graydata)
delete[] tmp_graydata;
+ }
+ else if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
+ {
+ setSubImageBGRA(pos_x,
+ pos_y,
+ bitmap_num,
+ fontp->mFTFace->glyph->bitmap.width,
+ fontp->mFTFace->glyph->bitmap.rows,
+ fontp->mFTFace->glyph->bitmap.buffer,
+ llabs(fontp->mFTFace->glyph->bitmap.pitch));
} else {
- // we don't know how to handle this pixel format from FreeType;
- // omit it from the font-image.
+ llassert(false);
}
- LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
- LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
+ LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
return gi;
}
-LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
+LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const
{
- char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
- if (iter != mCharGlyphInfoMap.end())
+ std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
+
+ char_glyph_info_map_t::iterator iter = (EFontGlyphType::Unspecified != glyph_type)
+ ? std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; })
+ : range_it.first;
+ if (iter != range_it.second)
{
return iter->second;
}
else
{
// this glyph doesn't yet exist, so render it and return the result
- return addGlyph(wch);
+ return addGlyph(wch, (EFontGlyphType::Unspecified != glyph_type) ? glyph_type : EFontGlyphType::Grayscale);
}
}
void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
{
- char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
- if (iter != mCharGlyphInfoMap.end())
+ llassert(gi->mGlyphType < EFontGlyphType::Count);
+ std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
+
+ char_glyph_info_map_t::iterator iter =
+ std::find_if(range_it.first, range_it.second, [&gi](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == gi->mGlyphType; });
+ if (iter != range_it.second)
{
delete iter->second;
iter->second = gi;
}
else
{
- mCharGlyphInfoMap[wch] = gi;
+ mCharGlyphInfoMap.insert(std::make_pair(wch, gi));
}
}
-void LLFontFreetype::renderGlyph(U32 glyph_index) const
+void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const
{
if (mFTFace == NULL)
return;
- llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT) );
+ FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
+ if (EFontGlyphType::Color == bitmap_type)
+ {
+ // We may not actually get a color render so our caller should always examine mFTFace->glyph->bitmap.pixel_mode
+ load_flags |= FT_LOAD_COLOR;
+ }
+
+ llassert_always(! FT_Load_Glyph(mFTFace, glyph_index, load_flags) );
llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) );
@@ -601,7 +672,7 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
resetBitmapCache();
- loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
+ loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);
if (!mIsFallback)
{
// This is the head of the list - need to rebuild ourself and all fallbacks.
@@ -611,11 +682,9 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
}
else
{
- for(font_vector_t::iterator it = mFallbackFonts.begin();
- it != mFallbackFonts.end();
- ++it)
+ for (fallback_font_vector_t::iterator it = mFallbackFonts.begin(); it != mFallbackFonts.end(); ++it)
{
- (*it)->reset(vert_dpi, horz_dpi);
+ it->first->reset(vert_dpi, horz_dpi);
}
}
}
@@ -637,7 +706,7 @@ void LLFontFreetype::resetBitmapCache()
if(!mIsFallback)
{
// Add the empty glyph
- addGlyphFromFont(this, 0, 0);
+ addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
}
}
@@ -651,6 +720,34 @@ const std::string &LLFontFreetype::getName() const
return mName;
}
+static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_name)
+{
+ LLPointer<LLImagePNG> tmpImage = new LLImagePNG();
+ if ( (tmpImage->encode(image_raw, 0.0f)) && (tmpImage->save(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name))) )
+ {
+ LL_INFOS("Font") << "Successfully saved " << file_name << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Font") << "Failed to save " << file_name << LL_ENDL;
+ }
+}
+
+void LLFontFreetype::dumpFontBitmaps() const
+{
+ // Dump all the regular bitmaps (if any)
+ for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++)
+ {
+ dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
+ }
+
+ // Dump all the color bitmaps (if any)
+ for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Color); idx < cnt; idx++)
+ {
+ dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, idx), llformat("%s_%d_%d_%d_clr.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
+ }
+}
+
const LLFontBitmapCache* LLFontFreetype::getFontBitmapCache() const
{
return mFontBitmapCachep;
@@ -666,17 +763,46 @@ U8 LLFontFreetype::getStyle() const
return mStyle;
}
+bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const
+{
+ LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num);
+ llassert(!mIsFallback);
+ llassert(image_raw && (image_raw->getComponents() == 4));
+
+ // NOTE: inspired by LLImageRaw::setSubImage()
+ U32* image_data = (U32*)image_raw->getData();
+ if (!image_data)
+ {
+ return false;
+ }
+
+ for (U32 idxRow = 0; idxRow < height; idxRow++)
+ {
+ const U32 nSrcRow = height - 1 - idxRow;
+ const U32 nSrcOffset = nSrcRow * width * image_raw->getComponents();
+ const U32 nDstOffset = (y + idxRow) * image_raw->getWidth() + x;
+
+ for (U32 idxCol = 0; idxCol < width; idxCol++)
+ {
+ U32 nTemp = nSrcOffset + idxCol * 4;
+ image_data[nDstOffset + idxCol] = data[nTemp + 3] << 24 | data[nTemp] << 16 | data[nTemp + 1] << 8 | data[nTemp + 2];
+ }
+ }
+
+ return true;
+}
+
void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
{
- LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num);
llassert(!mIsFallback);
llassert(image_raw && (image_raw->getComponents() == 2));
-
U8 *target = image_raw->getData();
+ llassert(target);
- if (!data)
+ if (!data || !target)
{
return;
}
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index f61f169987..b036d337ba 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -56,9 +56,11 @@ private:
struct LLFontGlyphInfo
{
- LLFontGlyphInfo(U32 index);
+ LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type);
+ LLFontGlyphInfo(const LLFontGlyphInfo& fgi);
U32 mGlyphIndex;
+ EFontGlyphType mGlyphType;
// Metrics
S32 mWidth; // In pixels
@@ -71,7 +73,7 @@ struct LLFontGlyphInfo
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
S32 mYBearing; // Distance from baseline to top in pixels
- S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph
+ std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
};
extern LLFontManager *gFontManagerp;
@@ -84,7 +86,7 @@ public:
// is_fallback should be true for fallback fonts that aren't used
// to render directly (Unicode backup, primarily)
- BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n = 0);
+ BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);
S32 getNumFaces(const std::string& filename);
@@ -93,10 +95,8 @@ public:
void clearFontStreams();
#endif
- typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t;
-
- void setFallbackFonts(const font_vector_t &font);
- const font_vector_t &getFallbackFonts() const;
+ typedef std::function<bool(llwchar)> char_functor_t;
+ void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr);
// Global font metrics - in units of pixels
F32 getLineHeight() const;
@@ -135,7 +135,7 @@ public:
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
- LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
+ LLFontGlyphInfo* getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const;
void reset(F32 vert_dpi, F32 horz_dpi);
@@ -143,6 +143,7 @@ public:
const std::string& getName() const;
+ void dumpFontBitmaps() const;
const LLFontBitmapCache* getFontBitmapCache() const;
void setStyle(U8 style);
@@ -151,10 +152,11 @@ public:
private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
+ bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
- LLFontGlyphInfo* addGlyph(llwchar wch) const; // Add a new character to the font if necessary
- LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
- void renderGlyph(U32 glyph_index) const;
+ LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
+ LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
+ void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
std::string mName;
@@ -174,9 +176,12 @@ private:
#endif
BOOL mIsFallback;
- font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
+ typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
+ typedef std::vector<fallback_font_t> fallback_font_vector_t;
+ fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
- typedef boost::unordered_map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
+ // *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
+ typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLFontBitmapCache* mFontBitmapCachep;
diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp
new file mode 100644
index 0000000000..19d327a4c9
--- /dev/null
+++ b/indra/llrender/llfontfreetypesvg.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file llfontfreetypesvg.cpp
+ * @brief Freetype font library SVG glyph rendering
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llfontfreetypesvg.h"
+
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4702)
+#endif
+
+#define NANOSVG_IMPLEMENTATION
+#include <nanosvg/nanosvg.h>
+#define NANOSVGRAST_IMPLEMENTATION
+#include <nanosvg/nanosvgrast.h>
+
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+
+struct LLSvgRenderData
+{
+ FT_UInt GlyphIndex = 0;
+ FT_Error Error = FT_Err_Ok; // FreeType currently (@2.12.1) ignores the error value returned by the preset glyph slot callback so we return it at render time
+ // (See https://github.com/freetype/freetype/blob/5faa1df8b93ebecf0f8fd5fe8fda7b9082eddced/src/base/ftobjs.c#L1170)
+ NSVGimage* pNSvgImage = nullptr;
+ float Scale = 0.f;
+};
+
+// static
+FT_Error LLFontFreeTypeSvgRenderer::OnInit(FT_Pointer* state)
+{
+ // The SVG driver hook state is shared across all callback invocations; since our state is lightweight
+ // we store it in the glyph instead.
+ *state = nullptr;
+
+ return FT_Err_Ok;
+}
+
+// static
+void LLFontFreeTypeSvgRenderer::OnFree(FT_Pointer* state)
+{
+}
+
+// static
+void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp)
+{
+ FT_GlyphSlot glyph_slot = static_cast<FT_GlyphSlot>(objectp);
+
+ LLSvgRenderData* pData = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ glyph_slot->generic.data = nullptr;
+ glyph_slot->generic.finalizer = nullptr;
+ delete(pData);
+}
+
+//static
+FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*)
+{
+ FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other);
+
+ llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex);
+ if (!glyph_slot->generic.data)
+ {
+ glyph_slot->generic.data = new LLSvgRenderData();
+ glyph_slot->generic.finalizer = LLFontFreeTypeSvgRenderer::OnDataFinalizer;
+ }
+ LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ if (!cache)
+ {
+ datap->GlyphIndex = glyph_slot->glyph_index;
+ datap->Error = FT_Err_Ok;
+ }
+
+ // NOTE: nsvgParse modifies the input string so we need a temporary copy
+ llassert(!datap->pNSvgImage || cache);
+ if (!datap->pNSvgImage)
+ {
+ char* document_buffer = new char[document->svg_document_length + 1];
+ memcpy(document_buffer, document->svg_document, document->svg_document_length);
+ document_buffer[document->svg_document_length] = '\0';
+
+ datap->pNSvgImage = nsvgParse(document_buffer, "px", 0.);
+
+ delete[] document_buffer;
+ }
+
+ if (!datap->pNSvgImage)
+ {
+ datap->Error = FT_Err_Invalid_SVG_Document;
+ return FT_Err_Invalid_SVG_Document;
+ }
+
+ // We don't (currently) support transformations so test for an identity rotation matrix + zero translation
+ if (document->transform.xx != 1 << 16 || document->transform.yx != 0 ||
+ document->transform.xy != 0 || document->transform.yy != 1 << 16 ||
+ document->delta.x > 0 || document->delta.y > 0)
+ {
+ datap->Error = FT_Err_Unimplemented_Feature;
+ return FT_Err_Unimplemented_Feature;
+ }
+
+ float svg_width = datap->pNSvgImage->width;
+ float svg_height = datap->pNSvgImage->height;
+ if (svg_width == 0.f || svg_height == 0.f)
+ {
+ svg_width = document->units_per_EM;
+ svg_height = document->units_per_EM;
+ }
+
+ float svg_x_scale = (float)document->metrics.x_ppem / floorf(svg_width);
+ float svg_y_scale = (float)document->metrics.y_ppem / floorf(svg_height);
+ float svg_scale = llmin(svg_x_scale, svg_y_scale);
+ datap->Scale = svg_scale;
+
+ glyph_slot->bitmap.width = floorf(svg_width) * svg_scale;
+ glyph_slot->bitmap.rows = floorf(svg_height) * svg_scale;
+ glyph_slot->bitmap_left = (document->metrics.x_ppem - glyph_slot->bitmap.width) / 2;
+ glyph_slot->bitmap_top = glyph_slot->face->size->metrics.ascender / 64.f;
+ glyph_slot->bitmap.pitch = glyph_slot->bitmap.width * 4;
+ glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ /* Copied as-is from fcft (MIT license) */
+
+ // Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
+ float horiBearingX = 0.;
+ float horiBearingY = -glyph_slot->bitmap_top;
+
+ // XXX parentheses correct?
+ float vertBearingX = glyph_slot->metrics.horiBearingX / 64.0f - glyph_slot->metrics.horiAdvance / 64.0f / 2;
+ float vertBearingY = (glyph_slot->metrics.vertAdvance / 64.0f - glyph_slot->metrics.height / 64.0f) / 2;
+
+ // Do conversion in two steps to avoid 'bad function cast' warning
+ glyph_slot->metrics.width = glyph_slot->bitmap.width * 64;
+ glyph_slot->metrics.height = glyph_slot->bitmap.rows * 64;
+ glyph_slot->metrics.horiBearingX = horiBearingX * 64;
+ glyph_slot->metrics.horiBearingY = horiBearingY * 64;
+ glyph_slot->metrics.vertBearingX = vertBearingX * 64;
+ glyph_slot->metrics.vertBearingY = vertBearingY * 64;
+ if (glyph_slot->metrics.vertAdvance == 0)
+ {
+ glyph_slot->metrics.vertAdvance = glyph_slot->bitmap.rows * 1.2f * 64;
+ }
+
+ return FT_Err_Ok;
+}
+
+// static
+FT_Error LLFontFreeTypeSvgRenderer::OnRender(FT_GlyphSlot glyph_slot, FT_Pointer*)
+{
+ LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ llassert(FT_Err_Ok == datap->Error);
+ if (FT_Err_Ok != datap->Error)
+ {
+ return datap->Error;
+ }
+
+ // Render to glyph bitmap
+ NSVGrasterizer* nsvgRasterizer = nsvgCreateRasterizer();
+ nsvgRasterize(nsvgRasterizer, datap->pNSvgImage, 0, 0, datap->Scale, glyph_slot->bitmap.buffer, glyph_slot->bitmap.width, glyph_slot->bitmap.rows, glyph_slot->bitmap.pitch);
+ nsvgDeleteRasterizer(nsvgRasterizer);
+ nsvgDelete(datap->pNSvgImage);
+ datap->pNSvgImage = nullptr;
+
+ // Convert from RGBA to BGRA
+ U32* pixel_buffer = (U32*)glyph_slot->bitmap.buffer; U8* byte_buffer = glyph_slot->bitmap.buffer;
+ for (size_t y = 0, h = glyph_slot->bitmap.rows; y < h; y++)
+ {
+ for (size_t x = 0, w = glyph_slot->bitmap.pitch / 4; x < w; x++)
+ {
+ size_t pixel_idx = y * w + x;
+ size_t byte_idx = pixel_idx * 4;
+ U8 alpha = byte_buffer[byte_idx + 3];
+ // Store as ARGB (*TODO - do we still have to care about endianness?)
+ pixel_buffer[y * w + x] = alpha << 24 | (byte_buffer[byte_idx] * alpha / 0xFF) << 16 | (byte_buffer[byte_idx + 1] * alpha / 0xFF) << 8 | (byte_buffer[byte_idx + 2] * alpha / 0xFF);
+ }
+ }
+
+ glyph_slot->format = FT_GLYPH_FORMAT_BITMAP;
+ glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ return FT_Err_Ok;
+}
diff --git a/indra/llrender/llfontfreetypesvg.h b/indra/llrender/llfontfreetypesvg.h
new file mode 100644
index 0000000000..b5f541991a
--- /dev/null
+++ b/indra/llrender/llfontfreetypesvg.h
@@ -0,0 +1,54 @@
+/**
+ * @file llfontfreetypesvg.h
+ * @brief Freetype font library SVG glyph rendering
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include <ft2build.h>
+#include FT_TYPES_H
+#include FT_MODULE_H
+#include FT_OTSVG_H
+
+ // See https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html
+class LLFontFreeTypeSvgRenderer
+{
+public:
+ // Called when the very first OT-SVG glyph is rendered (across the entire lifetime of our FT_Library object)
+ static FT_Error OnInit(FT_Pointer* state);
+
+ // Called when the ot-svg module is being freed (but only called if the init hook was called previously)
+ static void OnFree(FT_Pointer* state);
+
+ // Called to preset the glyph slot, twice per glyph:
+ // - when FT_Load_Glyph needs to preset the glyph slot (with cache == false)
+ // - right before the svg module calls the render callback hook. (with cache == true)
+ static FT_Error OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer* state);
+
+ // Called to render an OT-SVG glyph (right after the preset hook OnPresetGlypthSlot was called with cache set to TRUE)
+ static FT_Error OnRender(FT_GlyphSlot glyph_slot, FT_Pointer* state);
+
+ // Called to deallocate our per glyph slot data
+ static void OnDataFinalizer(void* objectp);
+};
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 1bf061bc8d..001b7fd7b8 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -89,14 +89,14 @@ void LLFontGL::destroyGL()
mFontFreetype->destroyGL();
}
-BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
+BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n)
{
if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
{
mFontFreetype = new LLFontFreetype;
}
- return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback, face_n);
+ return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n);
}
S32 LLFontGL::getNumFaces(const std::string& filename)
@@ -110,14 +110,14 @@ S32 LLFontGL::getNumFaces(const std::string& filename)
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
- ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
+ ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
LLRectf rect_float(rect.mLeft, rect.mTop, rect.mRight, rect.mBottom);
- return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses);
+ return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color);
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
- ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
+ ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
F32 x = rect.mLeft;
F32 y = 0.f;
@@ -138,12 +138,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec
y = rect.mBottom;
break;
}
- return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses);
+ return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses, use_color);
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
- ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
+ ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
@@ -278,7 +278,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
LLColor4U text_color(color);
- S32 bitmap_num = -1;
+ std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
S32 glyph_count = 0;
for (i = begin_offset; i < begin_offset + length; i++)
{
@@ -288,7 +288,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
next_glyph = NULL;
if(!fgi)
{
- fgi = mFontFreetype->getGlyphInfo(wch);
+ fgi = mFontFreetype->getGlyphInfo(wch, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
}
if (!fgi)
{
@@ -296,8 +296,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
break;
}
// Per-glyph bitmap texture.
- S32 next_bitmap_num = fgi->mBitmapNum;
- if (next_bitmap_num != bitmap_num)
+ std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
+ if (next_bitmap_entry != bitmap_entry)
{
// Actually draw the queued glyphs before switching their texture;
// otherwise the queued glyphs will be taken from wrong textures.
@@ -311,8 +311,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
glyph_count = 0;
}
- bitmap_num = next_bitmap_num;
- LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num);
+ bitmap_entry = next_bitmap_entry;
+ LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
gGL.getTexUnit(0)->bind(font_image);
}
@@ -345,7 +345,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
glyph_count = 0;
}
- drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength);
+ drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, (bitmap_entry.first == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@@ -355,7 +355,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(next_char);
+ next_glyph = mFontFreetype->getGlyphInfo(next_char, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
@@ -409,7 +409,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
shadow,
S32_MAX, max_pixels,
right_x,
- FALSE);
+ FALSE,
+ use_color);
gGL.popUIMatrix();
}
@@ -423,19 +424,19 @@ S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, cons
return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
-S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
+S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
- return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
+ return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
{
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
{
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE, FALSE);
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels
@@ -512,7 +513,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
next_glyph = NULL;
if(!fgi)
{
- fgi = mFontFreetype->getGlyphInfo(wch);
+ fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
}
F32 advance = mFontFreetype->getXAdvance(fgi);
@@ -532,7 +533,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
&& (next_char < LAST_CHARACTER))
{
// Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(next_char);
+ next_glyph = mFontFreetype->getGlyphInfo(next_char, EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@@ -550,7 +551,7 @@ void LLFontGL::generateASCIIglyphs()
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI
for (U32 i = 32; (i < 127); i++)
{
- mFontFreetype->getGlyphInfo(i);
+ mFontFreetype->getGlyphInfo(i, EFontGlyphType::Grayscale);
}
}
@@ -624,7 +625,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
next_glyph = NULL;
if(!fgi)
{
- fgi = mFontFreetype->getGlyphInfo(wch);
+ fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
if (NULL == fgi)
{
@@ -649,7 +650,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if (((i+1) < max_chars) && wchars[i+1])
{
// Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1], EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
@@ -696,7 +697,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
- const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
// last character uses character width, since the whole character needs to be visible
// other characters just use advance
@@ -771,7 +772,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
next_glyph = NULL;
if(!glyph)
{
- glyph = mFontFreetype->getGlyphInfo(wch);
+ glyph = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
}
F32 char_width = mFontFreetype->getXAdvance(glyph);
@@ -801,7 +802,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
&& (wchars[(pos + 1)]))
{
// Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1], EFontGlyphType::Unspecified);
cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
}
@@ -841,6 +842,26 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
LLFontGL::loadDefaultFonts();
}
+void LLFontGL::dumpTextures()
+{
+ if (mFontFreetype.notNull())
+ {
+ mFontFreetype->dumpFontBitmaps();
+ }
+}
+
+// static
+void LLFontGL::dumpFonts()
+{
+ sFontRegistry->dump();
+}
+
+// static
+void LLFontGL::dumpFontTextures()
+{
+ sFontRegistry->dumpTextures();
+}
+
// Force standard fonts to get generated up front.
// This is primarily for error detection purposes.
// Don't do this during initClass because it can be slow and we want to get
@@ -1003,6 +1024,13 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
return gl_vfont_align;
}
+ //static
+LLFontGL* LLFontGL::getFontEmoji()
+{
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Large", 0));
+ return fontp;;
+}
+
//static
LLFontGL* LLFontGL::getFontMonospace()
{
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 3b58a37d33..915c2439a3 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -87,7 +87,7 @@ public:
void destroyGL();
- BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback, S32 face_n = 0);
+ BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
S32 getNumFaces(const std::string& filename);
@@ -98,7 +98,8 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
- BOOL use_ellipses = FALSE) const;
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset,
const LLRectf& rect,
@@ -107,7 +108,8 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
- BOOL use_ellipses = FALSE) const;
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset,
F32 x, F32 y,
@@ -116,12 +118,13 @@ public:
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x=NULL,
- BOOL use_ellipses = FALSE) const;
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
// renderUTF8 does a conversion, so is slower!
- S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const;
+ S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
@@ -165,6 +168,10 @@ public:
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
+ void dumpTextures();
+ static void dumpFonts();
+ static void dumpFontTextures();
+
// Load sans-serif, sans-serif-small, etc.
// Slow, requires multiple seconds to load fonts.
static bool loadDefaultFonts();
@@ -187,6 +194,7 @@ public:
static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }
+ static LLFontGL* getFontEmoji();
static LLFontGL* getFontMonospace();
static LLFontGL* getFontSansSerifSmall();
static LLFontGL* getFontSansSerif();
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 9750bd4fa1..d2c7e466e6 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -47,6 +47,10 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/";
+LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({
+ { "is_emoji", LLStringOps::isEmoji }
+});
+
LLFontDescriptor::LLFontDescriptor():
mStyle(0)
{
@@ -55,22 +59,22 @@ LLFontDescriptor::LLFontDescriptor():
LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style,
- const string_vec_t& file_names):
+ const font_file_info_vec_t& font_files):
mName(name),
mSize(size),
mStyle(style),
- mFileNames(file_names)
+ mFontFiles(font_files)
{
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style,
- const string_vec_t& file_names,
- const string_vec_t& ft_collection_listections) :
- LLFontDescriptor(name, size, style, file_names)
+ const font_file_info_vec_t& font_list,
+ const font_file_info_vec_t& font_collection_files) :
+ LLFontDescriptor(name, size, style, font_list)
{
- mFontCollectionsList = ft_collection_listections;
+ mFontCollectionFiles = font_collection_files;
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
@@ -82,7 +86,6 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name,
{
}
-
bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const
{
if (mName < b.mName)
@@ -175,7 +178,19 @@ LLFontDescriptor LLFontDescriptor::normalize() const
if (removeSubString(new_name,"Italic"))
new_style |= LLFontGL::ITALIC;
- return LLFontDescriptor(new_name,new_size,new_style,getFileNames(),getFontCollectionsList());
+ return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
+}
+
+void LLFontDescriptor::addFontFile(const std::string& file_name, const std::string& char_functor)
+{
+ char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
+ mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
+}
+
+void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, const std::string& char_functor)
+{
+ char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
+ mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
}
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
@@ -273,17 +288,24 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
if (child->hasName("file"))
{
std::string font_file_name = child->getTextContents();
- desc.getFileNames().push_back(font_file_name);
-
+ std::string char_functor;
+
+ if (child->hasAttribute("functor"))
+ {
+ child->getAttributeString("functor", char_functor);
+ }
+
if (child->hasAttribute("load_collection"))
{
BOOL col = FALSE;
child->getAttributeBOOL("load_collection", col);
if (col)
{
- desc.getFontCollectionsList().push_back(font_file_name);
+ desc.addFontCollectionFile(font_file_name, char_functor);
}
}
+
+ desc.addFontFile(font_file_name, char_functor);
}
else if (child->hasName("os"))
{
@@ -326,19 +348,19 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
// A little roundabout because the map key is const,
// so we have to fetch it, make a new map key, and
// replace the old entry.
- string_vec_t match_file_names = match_desc->getFileNames();
- match_file_names.insert(match_file_names.begin(),
- desc.getFileNames().begin(),
- desc.getFileNames().end());
+ font_file_info_vec_t font_files = match_desc->getFontFiles();
+ font_files.insert(font_files.begin(),
+ desc.getFontFiles().begin(),
+ desc.getFontFiles().end());
- string_vec_t collections_list = match_desc->getFontCollectionsList();
- collections_list.insert(collections_list.begin(),
- desc.getFontCollectionsList().begin(),
- desc.getFontCollectionsList().end());
+ font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
+ font_collection_files.insert(font_collection_files.begin(),
+ desc.getFontCollectionFiles().begin(),
+ desc.getFontCollectionFiles().end());
LLFontDescriptor new_desc = *match_desc;
- new_desc.getFileNames() = match_file_names;
- new_desc.getFontCollectionsList() = collections_list;
+ new_desc.setFontFiles(font_files);
+ new_desc.setFontCollectionFiles(font_collection_files);
registry->mFontMap.erase(*match_desc);
registry->mFontMap[new_desc] = NULL;
}
@@ -423,82 +445,80 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
// Build list of font names to look for.
// Files specified for this font come first, followed by those from the default descriptor.
- string_vec_t file_names = match_desc->getFileNames();
- string_vec_t ft_collection_list = match_desc->getFontCollectionsList();
- string_vec_t default_file_names;
+ font_file_info_vec_t font_files = match_desc->getFontFiles();
+ font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
LLFontDescriptor default_desc("default",s_template_string,0);
const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
if (match_default_desc)
{
- file_names.insert(file_names.end(),
- match_default_desc->getFileNames().begin(),
- match_default_desc->getFileNames().end());
- ft_collection_list.insert(ft_collection_list.end(),
- match_default_desc->getFontCollectionsList().begin(),
- match_default_desc->getFontCollectionsList().end());
+ font_files.insert(font_files.end(),
+ match_default_desc->getFontFiles().begin(),
+ match_default_desc->getFontFiles().end());
+ font_collection_files.insert(font_collection_files.end(),
+ match_default_desc->getFontCollectionFiles().begin(),
+ match_default_desc->getFontCollectionFiles().end());
}
// Add ultimate fallback list - generated dynamically on linux,
// null elsewhere.
- file_names.insert(file_names.end(),
- getUltimateFallbackList().begin(),
- getUltimateFallbackList().end());
+ std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
+ [](const std::string& file_name) { return LLFontFileInfo(file_name); });
// Load fonts based on names.
- if (file_names.empty())
+ if (font_files.empty())
{
LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL;
return NULL;
}
- LLFontFreetype::font_vector_t fontlist;
LLFontGL *result = NULL;
- // Snarf all fonts we can into fontlist. First will get pulled
- // off the list and become the "head" font, set to non-fallback.
+ // The first font will get pulled will be the "head" font, set to non-fallback.
// Rest will consitute the fallback list.
BOOL is_first_found = TRUE;
- std::string local_path = LLFontGL::getFontPathLocal();
- std::string sys_path = LLFontGL::getFontPathSystem();
-
+ string_vec_t font_search_paths;
+ font_search_paths.push_back(LLFontGL::getFontPathLocal());
+ font_search_paths.push_back(LLFontGL::getFontPathSystem());
+#if LL_DARWIN
+ font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY);
+ font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL);
+ font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL);
+#endif
+
// The fontname string may contain multiple font file names separated by semicolons.
// Break it apart and try loading each one, in order.
- for(string_vec_t::iterator file_name_it = file_names.begin();
- file_name_it != file_names.end();
- ++file_name_it)
+ for(font_file_info_vec_t::iterator font_file_it = font_files.begin();
+ font_file_it != font_files.end();
+ ++font_file_it)
{
LLFontGL *fontp = NULL;
- string_vec_t font_paths;
- font_paths.push_back(local_path + *file_name_it);
- font_paths.push_back(sys_path + *file_name_it);
-#if LL_DARWIN
- font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it);
- font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL + *file_name_it);
- font_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL + *file_name_it);
-#endif
-
- bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end());
+
+ bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(),
+ [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end());
+
// *HACK: Fallback fonts don't render, so we can use that to suppress
// creation of OpenGL textures for test apps. JC
BOOL is_fallback = !is_first_found || !mCreateGLTextures;
F32 extra_scale = (is_fallback)?fallback_scale:1.0;
F32 point_size_scale = extra_scale * point_size;
bool is_font_loaded = false;
- for(string_vec_t::iterator font_paths_it = font_paths.begin();
- font_paths_it != font_paths.end();
- ++font_paths_it)
+ for(string_vec_t::iterator font_search_path_it = font_search_paths.begin();
+ font_search_path_it != font_search_paths.end();
+ ++font_search_path_it)
{
+ const std::string font_path = *font_search_path_it + font_file_it->FileName;
+
fontp = new LLFontGL;
- S32 num_faces = is_ft_collection ? fontp->getNumFaces(*font_paths_it) : 1;
+ S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1;
for (S32 i = 0; i < num_faces; i++)
{
if (fontp == NULL)
{
fontp = new LLFontGL;
}
- if (fontp->loadFace(*font_paths_it, point_size_scale,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback, i))
+ if (fontp->loadFace(font_path, point_size_scale,
+ LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))
{
is_font_loaded = true;
if (is_first_found)
@@ -508,7 +528,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
}
else
{
- fontlist.push_back(fontp->mFontFreetype);
+ result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor);
+
delete fontp;
fontp = NULL;
}
@@ -523,17 +544,12 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
}
if(!is_font_loaded)
{
- LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL;
+ LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL;
delete fontp;
fontp = NULL;
}
}
- if (result && !fontlist.empty())
- {
- result->mFontFreetype->setFallbackFonts(fontlist);
- }
-
if (result)
{
result->mFontDescriptor = desc;
@@ -720,11 +736,22 @@ void LLFontRegistry::dump()
<< " size=[" << desc.getSize() << "]"
<< " fileNames="
<< LL_ENDL;
- for (string_vec_t::const_iterator file_it=desc.getFileNames().begin();
- file_it != desc.getFileNames().end();
+ for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin();
+ file_it != desc.getFontFiles().end();
++file_it)
{
- LL_INFOS() << " file: " << *file_it <<LL_ENDL;
+ LL_INFOS() << " file: " << file_it->FileName << LL_ENDL;
+ }
+ }
+}
+
+void LLFontRegistry::dumpTextures()
+{
+ for (const auto& fontEntry : mFontMap)
+ {
+ if (fontEntry.second)
+ {
+ fontEntry.second->dumpTextures();
}
}
}
diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h
index e30c81c630..b0ef72c5de 100644
--- a/indra/llrender/llfontregistry.h
+++ b/indra/llrender/llfontregistry.h
@@ -34,13 +34,32 @@ class LLFontGL;
typedef std::vector<std::string> string_vec_t;
+struct LLFontFileInfo
+{
+ LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr)
+ : FileName(file_name)
+ , CharFunctor(char_functor)
+ {
+ }
+
+ LLFontFileInfo(const LLFontFileInfo& ffi)
+ : FileName(ffi.FileName)
+ , CharFunctor(ffi.CharFunctor)
+ {
+ }
+
+ std::string FileName;
+ std::function<bool(llwchar)> CharFunctor;
+};
+typedef std::vector<LLFontFileInfo> font_file_info_vec_t;
+
class LLFontDescriptor
{
public:
LLFontDescriptor();
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
- LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names);
- LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names, const string_vec_t& font_collections);
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list);
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list, const font_file_info_vec_t& font_collection_list);
LLFontDescriptor normalize() const;
bool operator<(const LLFontDescriptor& b) const;
@@ -51,19 +70,26 @@ public:
void setName(const std::string& name) { mName = name; }
const std::string& getSize() const { return mSize; }
void setSize(const std::string& size) { mSize = size; }
- const std::vector<std::string>& getFileNames() const { return mFileNames; }
- std::vector<std::string>& getFileNames() { return mFileNames; }
- const std::vector<std::string>& getFontCollectionsList() const { return mFontCollectionsList; }
- std::vector<std::string>& getFontCollectionsList() { return mFontCollectionsList; }
+
+ void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
+ void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
+ void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
+ void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
+
const U8 getStyle() const { return mStyle; }
void setStyle(U8 style) { mStyle = style; }
private:
std::string mName;
std::string mSize;
- string_vec_t mFileNames;
- string_vec_t mFontCollectionsList;
+ font_file_info_vec_t mFontFiles;
+ font_file_info_vec_t mFontCollectionFiles;
U8 mStyle;
+
+ typedef std::map<std::string, std::function<bool(llwchar)>> char_functor_map_t;
+ static char_functor_map_t mCharFunctors;
};
class LLFontRegistry
@@ -94,6 +120,7 @@ public:
bool nameToSize(const std::string& size_name, F32& size);
void dump();
+ void dumpTextures();
const string_vec_t& getUltimateFallbackList() const;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 193cfa64b8..88402730c9 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -2330,8 +2330,6 @@ void LLGLSyncFence::wait()
{
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
{ //track the number of times we've waited here
- static S32 waits = 0;
- waits++;
}
}
#endif
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 9108c6143c..a0314cb5f2 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -29,6 +29,8 @@ set(llui_SOURCE_FILES
lldockcontrol.cpp
lldraghandle.cpp
lleditmenuhandler.cpp
+ llemojidictionary.cpp
+ llemojihelper.cpp
llf32uictrl.cpp
llfiltereditor.cpp
llflashtimer.cpp
@@ -139,6 +141,8 @@ set(llui_HEADER_FILES
lldockablefloater.h
lldockcontrol.h
lleditmenuhandler.h
+ llemojidictionary.h
+ llemojihelper.h
llf32uictrl.h
llfiltereditor.h
llflashtimer.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 8028f397f3..3354cb2db3 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -942,11 +942,8 @@ void LLButton::draw()
break;
}
- S32 y_offset = 2 + (getRect().getHeight() - 20)/2;
-
if (pressed && mDisplayPressedState)
{
- y_offset--;
x++;
}
diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp
new file mode 100644
index 0000000000..b70a9b2e7a
--- /dev/null
+++ b/indra/llui/llemojidictionary.cpp
@@ -0,0 +1,200 @@
+/**
+* @file llemojidictionary.cpp
+* @brief Implementation of LLEmojiDictionary
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+
+#include "lldir.h"
+#include "llemojidictionary.h"
+#include "llsdserialize.h"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/range/adaptor/filtered.hpp>
+#include <boost/range/algorithm/transform.hpp>
+
+// ============================================================================
+// Constants
+//
+
+constexpr char SKINNED_EMOJI_FILENAME[] = "emoji_characters.xml";
+
+// ============================================================================
+// Helper functions
+//
+
+template<class T>
+std::list<T> llsd_array_to_list(const LLSD& sd, std::function<void(T&)> mutator = {});
+
+template<>
+std::list<std::string> llsd_array_to_list(const LLSD& sd, std::function<void(std::string&)> mutator)
+{
+ std::list<std::string> result;
+ for (LLSD::array_const_iterator it = sd.beginArray(), end = sd.endArray(); it != end; ++it)
+ {
+ const LLSD& entry = *it;
+ if (!entry.isString())
+ continue;
+
+ result.push_back(entry.asStringRef());
+ if (mutator)
+ {
+ mutator(result.back());
+ }
+ }
+ return result;
+}
+
+LLEmojiDescriptor::LLEmojiDescriptor(const LLSD& descriptor_sd)
+{
+ Name = descriptor_sd["Name"].asStringRef();
+
+ const LLWString emoji_string = utf8str_to_wstring(descriptor_sd["Character"].asString());
+ Character = (1 == emoji_string.size()) ? emoji_string[0] : L'\0'; // We don't currently support character composition
+
+ auto toLower = [](std::string& str) { LLStringUtil::toLower(str); };
+ ShortCodes = llsd_array_to_list<std::string>(descriptor_sd["ShortCodes"], toLower);
+ Categories = llsd_array_to_list<std::string>(descriptor_sd["Categories"], toLower);
+
+ if (Name.empty())
+ {
+ Name = ShortCodes.front();
+ }
+}
+
+bool LLEmojiDescriptor::isValid() const
+{
+ return
+ Character &&
+ !ShortCodes.empty() &&
+ !Categories.empty();
+}
+
+struct emoji_filter_base
+{
+ emoji_filter_base(const std::string& needle)
+ {
+ // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category
+ mNeedle = (boost::starts_with(needle, ":")) ? needle.substr(1) : needle;
+ LLStringUtil::toLower(mNeedle);
+ }
+
+protected:
+ std::string mNeedle;
+};
+
+struct emoji_filter_shortcode_or_category_contains : public emoji_filter_base
+{
+ emoji_filter_shortcode_or_category_contains(const std::string& needle) : emoji_filter_base(needle) {}
+
+ bool operator()(const LLEmojiDescriptor& descr) const
+ {
+ for (const auto& short_code : descr.ShortCodes)
+ {
+ if (boost::icontains(short_code, mNeedle))
+ return true;
+ }
+
+ for (const auto& category : descr.Categories)
+ {
+ if (boost::icontains(category, mNeedle))
+ return true;
+ }
+
+ return false;
+ }
+};
+
+// ============================================================================
+// LLEmojiDictionary class
+//
+
+LLEmojiDictionary::LLEmojiDictionary()
+{
+}
+
+// static
+void LLEmojiDictionary::initClass()
+{
+ LLEmojiDictionary* pThis = &LLEmojiDictionary::initParamSingleton();
+
+ LLSD data;
+
+ const std::string filename = gDirUtilp->findSkinnedFilenames(LLDir::XUI, SKINNED_EMOJI_FILENAME, LLDir::CURRENT_SKIN).front();
+ llifstream file(filename.c_str());
+ if (file.is_open())
+ {
+ LL_DEBUGS() << "Loading emoji characters file at " << filename << LL_ENDL;
+ LLSDSerialize::fromXML(data, file);
+ }
+
+ if (data.isUndefined())
+ {
+ LL_WARNS() << "Emoji file characters missing or ill-formed" << LL_ENDL;
+ return;
+ }
+
+ for (LLSD::array_const_iterator descriptor_it = data.beginArray(), descriptor_end = data.endArray(); descriptor_it != descriptor_end; ++descriptor_it)
+ {
+ LLEmojiDescriptor descriptor(*descriptor_it);
+ if (!descriptor.isValid())
+ {
+ LL_WARNS() << "Skipping invalid emoji descriptor " << descriptor.Character << LL_ENDL;
+ continue;
+ }
+ pThis->addEmoji(std::move(descriptor));
+ }
+}
+
+LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const
+{
+ LLWString result;
+ boost::transform(mEmojis | boost::adaptors::filtered(emoji_filter_shortcode_or_category_contains(needle)),
+ std::back_inserter(result), [](const auto& descr) { return descr.Character; });
+ return result;
+}
+
+const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const
+{
+ const auto it = mShortCode2Descr.find(short_code);
+ return (mShortCode2Descr.end() != it) ? it->second : nullptr;
+}
+
+std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) const
+{
+ const auto it = mEmoji2Descr.find(ch);
+ return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null;
+}
+
+void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr)
+{
+ mEmojis.push_back(descr);
+ mEmoji2Descr.insert(std::make_pair(descr.Character, &mEmojis.back()));
+ for (const std::string& shortCode : descr.ShortCodes)
+ {
+ mShortCode2Descr.insert(std::make_pair(shortCode, &mEmojis.back()));
+ }
+}
+
+// ============================================================================
diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h
new file mode 100644
index 0000000000..46a61f1cd7
--- /dev/null
+++ b/indra/llui/llemojidictionary.h
@@ -0,0 +1,73 @@
+/**
+* @file llemojidictionary.h
+* @brief Header file for LLEmojiDictionary
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#pragma once
+
+#include "lldictionary.h"
+#include "llinitdestroyclass.h"
+#include "llsingleton.h"
+
+// ============================================================================
+// LLEmojiDescriptor class
+//
+
+struct LLEmojiDescriptor
+{
+ LLEmojiDescriptor(const LLSD& descriptor_sd);
+
+ bool isValid() const;
+
+ std::string Name;
+ llwchar Character;
+ std::list<std::string> ShortCodes;
+ std::list<std::string> Categories;
+};
+
+// ============================================================================
+// LLEmojiDictionary class
+//
+
+class LLEmojiDictionary : public LLParamSingleton<LLEmojiDictionary>, public LLInitClass<LLEmojiDictionary>
+{
+ LLSINGLETON(LLEmojiDictionary);
+ ~LLEmojiDictionary() override {};
+
+public:
+ static void initClass();
+ LLWString findMatchingEmojis(const std::string& needle) const;
+ const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
+ std::string getNameFromEmoji(llwchar ch) const;
+
+private:
+ void addEmoji(LLEmojiDescriptor&& descr);
+
+private:
+ std::list<LLEmojiDescriptor> mEmojis;
+ std::map<llwchar, const LLEmojiDescriptor*> mEmoji2Descr;
+ std::map<std::string, const LLEmojiDescriptor*> mShortCode2Descr;
+};
+
+// ============================================================================
diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp
new file mode 100644
index 0000000000..1e4c19a183
--- /dev/null
+++ b/indra/llui/llemojihelper.cpp
@@ -0,0 +1,166 @@
+/**
+* @file llemojihelper.h
+* @brief Header file for LLEmojiHelper
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+
+#include "llemojidictionary.h"
+#include "llemojihelper.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "lluictrl.h"
+
+// ============================================================================
+// Constants
+//
+
+constexpr char DEFAULT_EMOJI_HELPER_FLOATER[] = "emoji_complete";
+constexpr S32 HELPER_FLOATER_OFFSET_X = 20;
+constexpr S32 HELPER_FLOATER_OFFSET_Y = 0;
+
+// ============================================================================
+// LLEmojiHelper
+//
+
+std::string LLEmojiHelper::getToolTip(llwchar ch) const
+{
+ return LLEmojiDictionary::instance().getNameFromEmoji(ch);
+}
+
+bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const
+{
+ return mHostHandle.get() == ctrl_p;
+}
+
+// static
+bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos)
+{
+ // If the cursor is currently on a colon start the check one character further back
+ S32 shortCodePos = (cursorPos == 0 || L':' != wtext[cursorPos - 1]) ? cursorPos : cursorPos - 1;
+
+ auto isPartOfShortcode = [](llwchar ch) {
+ switch (ch)
+ {
+ case L'-':
+ case L'_':
+ case L'+':
+ return true;
+ default:
+ return LLStringOps::isAlnum(ch);
+ }
+ };
+ while (shortCodePos > 1 && isPartOfShortcode(wtext[shortCodePos - 1]))
+ {
+ shortCodePos--;
+ }
+
+ bool isShortCode = (L':' == wtext[shortCodePos - 1]) && (cursorPos - shortCodePos >= 2);
+ if (pShortCodePos)
+ *pShortCodePos = (isShortCode) ? shortCodePos - 1 : -1;
+ return isShortCode;
+}
+
+void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> cb)
+{
+ // Commit immediately if the user already typed a full shortcode
+ if (const auto* emojiDescrp = LLEmojiDictionary::instance().getDescriptorFromShortCode(short_code))
+ {
+ cb(LLWString(1, emojiDescrp->Character));
+ hideHelper();
+ return;
+ }
+
+ if (mHelperHandle.isDead())
+ {
+ LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER);
+ mHelperHandle = pHelperFloater->getHandle();
+ mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())); }, std::placeholders::_2));
+ }
+ setHostCtrl(hostctrl_p);
+ mEmojiCommitCb = cb;
+
+ S32 floater_x, floater_y;
+ if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView))
+ {
+ LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL;
+ return;
+ }
+
+ LLFloater* pHelperFloater = mHelperHandle.get();
+ LLRect rct = pHelperFloater->getRect();
+ rct.setLeftTopAndSize(floater_x - HELPER_FLOATER_OFFSET_X, floater_y - HELPER_FLOATER_OFFSET_Y + rct.getHeight(), rct.getWidth(), rct.getHeight());
+ pHelperFloater->setRect(rct);
+ pHelperFloater->openFloater(LLSD().with("hint", short_code));
+}
+
+void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p)
+{
+ if (ctrl_p && !isActive(ctrl_p))
+ {
+ return;
+ }
+
+ setHostCtrl(nullptr);
+}
+
+bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask)
+{
+ if (mHelperHandle.isDead() || !isActive(ctrl_p))
+ {
+ return false;
+ }
+
+ return mHelperHandle.get()->handleKey(key, mask, true);
+}
+
+void LLEmojiHelper::onCommitEmoji(const LLWString& wstr)
+{
+ if (!mHostHandle.isDead() && mEmojiCommitCb)
+ {
+ mEmojiCommitCb(wstr);
+ }
+}
+
+void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p)
+{
+ const LLUICtrl* pCurHostCtrl = mHostHandle.get();
+ if (pCurHostCtrl != hostctrl_p)
+ {
+ mHostCtrlFocusLostConn.disconnect();
+ mHostHandle.markDead();
+ mEmojiCommitCb = {};
+
+ if (!mHelperHandle.isDead())
+ {
+ mHelperHandle.get()->closeFloater();
+ }
+
+ if (hostctrl_p)
+ {
+ mHostHandle = hostctrl_p->getHandle();
+ mHostCtrlFocusLostConn = hostctrl_p->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); }));
+ }
+ }
+}
diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h
new file mode 100644
index 0000000000..63f5c640c9
--- /dev/null
+++ b/indra/llui/llemojihelper.h
@@ -0,0 +1,64 @@
+/**
+* @file llemojihelper.h
+* @brief Header file for LLEmojiHelper
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#pragma once
+
+#include "llhandle.h"
+#include "llsingleton.h"
+
+#include <boost/signals2.hpp>
+
+class LLFloater;
+class LLUICtrl;
+
+class LLEmojiHelper : public LLSingleton<LLEmojiHelper>
+{
+ LLSINGLETON(LLEmojiHelper) {}
+ ~LLEmojiHelper() override {}
+
+public:
+ // General
+ std::string getToolTip(llwchar ch) const;
+ bool isActive(const LLUICtrl* ctrl_p) const;
+ static bool isCursorInEmojiCode(const LLWString& wtext, S32 cursor_pos, S32* short_code_pos_p = nullptr);
+ void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function<void(LLWString)> commit_cb);
+ void hideHelper(const LLUICtrl* ctrl_p = nullptr);
+
+ // Eventing
+ bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask);
+ void onCommitEmoji(const LLWString& wstr);
+
+protected:
+ LLUICtrl* getHostCtrl() const { return mHostHandle.get(); }
+ void setHostCtrl(LLUICtrl* hostctrl_p);
+
+private:
+ LLHandle<LLUICtrl> mHostHandle;
+ LLHandle<LLFloater> mHelperHandle;
+ boost::signals2::connection mHostCtrlFocusLostConn;
+ boost::signals2::connection mHelperCommitConn;
+ std::function<void(LLWString)> mEmojiCommitCb;
+};
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 2303cd24b7..346e89a101 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2488,7 +2488,7 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore
if (mFrontChild == child)
{
- if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
+ if (give_focus && child->canFocusStealFrontmost() && !gFocusMgr.childHasKeyboardFocus(child))
{
child->setFocus(TRUE);
}
@@ -3041,7 +3041,34 @@ void LLFloaterView::syncFloaterTabOrder()
LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
if (gFocusMgr.childHasKeyboardFocus(floaterp))
{
- bringToFront(floaterp, FALSE);
+ if (mFrontChild != floaterp)
+ {
+ // Grab a list of the top floaters that want to stay on top of the focused floater
+ std::list<LLFloater*> listTop;
+ if (mFrontChild && !mFrontChild->canFocusStealFrontmost())
+ {
+ for (LLView* childp : *getChildList())
+ {
+ LLFloater* child_floaterp = static_cast<LLFloater*>(childp);
+ if (child_floaterp->canFocusStealFrontmost())
+ break;
+ listTop.push_back(child_floaterp);
+ }
+ }
+
+ bringToFront(floaterp, FALSE);
+
+ // Restore top floaters
+ if (!listTop.empty())
+ {
+ for (LLView* childp : listTop)
+ {
+ sendChildToFront(childp);
+ }
+ mFrontChild = listTop.back();
+ }
+ }
+
break;
}
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 668cd208a9..282f7a80ac 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -313,6 +313,9 @@ public:
/*virtual*/ void setVisible(BOOL visible); // do not override
/*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override
+ bool canFocusStealFrontmost() const { return mFocusStealsFrontmost; }
+ void setFocusStealsFrontmost(bool wants_frontmost) { mFocusStealsFrontmost = wants_frontmost; }
+
void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
@@ -481,6 +484,7 @@ private:
BOOL mCanTearOff;
BOOL mCanMinimize;
BOOL mCanClose;
+ bool mFocusStealsFrontmost = true; // FALSE if we don't want the currently focused floater to cover this floater without user interaction
BOOL mDragOnLeft;
BOOL mResizable;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index eba93beed9..d5988dadbc 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -874,7 +874,7 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y
//
font->renderUTF8(mLabel, 0, x, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, TRUE);
+ S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/TRUE, /*use_color*/FALSE);
}
void LLFolderViewItem::draw()
@@ -953,7 +953,7 @@ void LLFolderViewItem::draw()
{
font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, S32_MAX, &right_x, FALSE );
+ S32_MAX, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE );
}
//--------------------------------------------------------------------------------//
@@ -966,7 +966,7 @@ void LLFolderViewItem::draw()
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- filter_string_length, S32_MAX, &right_x, FALSE );
+ filter_string_length, S32_MAX, &right_x, /*use_ellipses*/FALSE, /*use_color*/FALSE );
}
//Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 5cb840fd61..d29781cf33 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -487,9 +487,6 @@ void LLMenuItemGL::draw( void )
// let disabled items be highlighted, just don't draw them as such
if( getEnabled() && getHighlight() && !mBriefItem)
{
- int debug_count = 0;
- if (dynamic_cast<LLMenuItemCallGL*>(this))
- debug_count++;
gGL.color4fv( mHighlightBackground.get().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 7c381161c9..d736aa6634 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -337,7 +337,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&
element["name"] = name;
element["text"] = name;
element["value"] = value;
- element["index"] = mFormData.size();
+ element["index"] = LLSD::Integer(mFormData.size());
element["enabled"] = enabled;
mFormData.append(element);
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 921398a693..4d9a33f1d7 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -913,7 +913,7 @@ public:
/* virtual */ LLNotificationPtr add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
- LLNotificationFunctorRegistry::ResponseFunctor functor);
+ LLNotificationFunctorRegistry::ResponseFunctor functor) override;
LLNotificationPtr add(const LLNotification::Params& p);
void add(const LLNotificationPtr pNotif);
@@ -964,8 +964,8 @@ public:
bool isVisibleByRules(LLNotificationPtr pNotification);
private:
- /*virtual*/ void initSingleton();
- /*virtual*/ void cleanupSingleton();
+ /*virtual*/ void initSingleton() override;
+ /*virtual*/ void cleanupSingleton() override;
void loadPersistentNotifications();
diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h
index 3da5e30955..14f9b44fe4 100644
--- a/indra/llui/llspellcheck.h
+++ b/indra/llui/llspellcheck.h
@@ -47,7 +47,7 @@ public:
protected:
void addToDictFile(const std::string& dict_path, const std::string& word);
void initHunspell(const std::string& dict_language);
- void initSingleton();
+ void initSingleton() override;
public:
typedef std::list<std::string> dict_list_t;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 82a3c01c6d..0066e09cfc 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -29,6 +29,7 @@
#include "lltextbase.h"
+#include "llemojihelper.h"
#include "lllocalcliprect.h"
#include "llmenugl.h"
#include "llscrollcontainer.h"
@@ -161,10 +162,12 @@ LLTextBase::Params::Params()
line_spacing("line_spacing"),
max_text_length("max_length", 255),
font_shadow("font_shadow"),
+ text_valign("text_valign"),
wrap("wrap"),
trusted_content("trusted_content", true),
always_show_icons("always_show_icons", false),
use_ellipses("use_ellipses", false),
+ use_color("use_color", false),
parse_urls("parse_urls", false),
force_urls_external("force_urls_external", false),
parse_highlights("parse_highlights", false)
@@ -208,6 +211,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mVPad(p.v_pad),
mHAlign(p.font_halign),
mVAlign(p.font_valign),
+ mTextVAlign(p.text_valign.isProvided() ? p.text_valign.getValue() : p.font_valign.getValue()),
mLineSpacingMult(p.line_spacing.multiple),
mLineSpacingPixels(p.line_spacing.pixels),
mClip(p.clip),
@@ -222,6 +226,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mPlainText ( p.plain_text ),
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
+ mUseColor(p.use_color),
mParseHTML(p.parse_urls),
mForceUrlsExternal(p.force_urls_external),
mParseHighlights(p.parse_highlights),
@@ -582,7 +587,7 @@ void LLTextBase::drawCursor()
fontp = segmentp->getStyle()->getFont();
fontp->render(text, mCursorPos, cursor_rect,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
- LLFontGL::LEFT, mVAlign,
+ LLFontGL::LEFT, mTextVAlign,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
1);
@@ -896,6 +901,25 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
}
+ // Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us)
+ {
+ LLStyleSP emoji_style;
+ for (S32 text_kitty = 0, text_len = wstr.size(); text_kitty < text_len; text_kitty++)
+ {
+ if (LLStringOps::isEmoji(wstr[text_kitty]))
+ {
+ if (!emoji_style)
+ {
+ emoji_style = new LLStyle(getStyleParams());
+ emoji_style->setFont(LLFontGL::getFontEmoji());
+ }
+
+ S32 new_seg_start = pos + text_kitty;
+ insertSegment(new LLEmojiTextSegment(emoji_style, new_seg_start, new_seg_start + 1, *this));
+ }
+ }
+ }
+
getViewModel()->getEditableDisplay().insert(pos, wstr);
if ( truncate() )
@@ -1979,21 +2003,8 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaini
LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
{
-
static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
- S32 text_len = 0;
- if (!useLabel())
- {
- text_len = getLength();
- }
- else
- {
- text_len = mLabel.getWString().length();
- }
-
- if (index > text_len) { return mSegments.end(); }
-
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@@ -2007,18 +2018,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i
{
static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
- S32 text_len = 0;
- if (!useLabel())
- {
- text_len = getLength();
- }
- else
- {
- text_len = mLabel.getWString().length();
- }
-
- if (index > text_len) { return mSegments.end(); }
-
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
@@ -3312,12 +3311,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
color,
- LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length,
&right_x,
- mEditor.getUseEllipses());
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
}
rect.mLeft = right_x;
@@ -3331,12 +3331,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
mStyle->getSelectedColor().get(),
- LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
length,
&right_x,
- mEditor.getUseEllipses());
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
}
rect.mLeft = right_x;
if( selection_end < seg_end )
@@ -3348,12 +3349,13 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
color,
- LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::LEFT, mEditor.mTextVAlign,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length,
&right_x,
- mEditor.getUseEllipses());
+ mEditor.getUseEllipses(),
+ mEditor.getUseColor());
}
return right_x;
}
@@ -3585,6 +3587,33 @@ const S32 LLLabelTextSegment::getLength() const
}
//
+// LLEmojiTextSegment
+//
+LLEmojiTextSegment::LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor)
+ : LLNormalTextSegment(style, start, end, editor)
+{
+}
+
+LLEmojiTextSegment::LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
+ : LLNormalTextSegment(color, start, end, editor, is_visible)
+{
+}
+
+BOOL LLEmojiTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ if (mTooltip.empty())
+ {
+ LLWString emoji = getWText().substr(getStart(), getEnd() - getStart());
+ if (!emoji.empty())
+ {
+ mTooltip = LLEmojiHelper::instance().getToolTip(emoji[0]);
+ }
+ }
+
+ return LLNormalTextSegment::handleToolTip(x, y, mask);
+}
+
+//
// LLOnHoverChangeableTextSegment
//
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index e3cf56a5ee..9b3691e404 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -178,6 +178,18 @@ protected:
/*virtual*/ const S32 getLength() const;
};
+// Text segment that represents a single emoji character that has a different style (=font size) than the rest of
+// the document it belongs to
+class LLEmojiTextSegment : public LLNormalTextSegment
+{
+public:
+ LLEmojiTextSegment(LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor);
+ LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
+
+ bool canEdit() const override { return false; }
+ BOOL handleToolTip(S32 x, S32 y, MASK mask) override;
+};
+
// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)
class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
{
@@ -316,6 +328,7 @@ public:
plain_text,
wrap,
use_ellipses,
+ use_color,
parse_urls,
force_urls_external,
parse_highlights,
@@ -335,6 +348,8 @@ public:
Optional<LLFontGL::ShadowType> font_shadow;
+ Optional<LLFontGL::VAlign> text_valign;
+
Params();
};
@@ -394,6 +409,7 @@ public:
// used by LLTextSegment layout code
bool getWordWrap() { return mWordWrap; }
bool getUseEllipses() { return mUseEllipses; }
+ bool getUseColor() { return mUseColor; }
bool truncate(); // returns true of truncation occurred
bool isContentTrusted() {return mTrustedContent;}
@@ -687,8 +703,9 @@ protected:
// configuration
S32 mHPad; // padding on left of text
S32 mVPad; // padding above text
- LLFontGL::HAlign mHAlign;
- LLFontGL::VAlign mVAlign;
+ LLFontGL::HAlign mHAlign; // horizontal alignment of the document in its entirety
+ LLFontGL::VAlign mVAlign; // vertical alignment of the document in its entirety
+ LLFontGL::VAlign mTextVAlign; // vertical alignment of a text segment within a single line of text
F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding)
S32 mLineSpacingPixels; // padding between lines
bool mBorderVisible;
@@ -697,6 +714,7 @@ protected:
bool mParseHighlights; // highlight user-defined keywords
bool mWordWrap;
bool mUseEllipses;
+ bool mUseColor;
bool mTrackEnd; // if true, keeps scroll position at end of document during resize
bool mReadOnly;
bool mBGVisible; // render background?
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3d2a426913..a85ac2a5a3 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -43,6 +43,7 @@
#include "llmath.h"
#include "llclipboard.h"
+#include "llemojihelper.h"
#include "llscrollbar.h"
#include "llstl.h"
#include "llstring.h"
@@ -238,6 +239,7 @@ LLTextEditor::Params::Params()
default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
show_context_menu("show_context_menu"),
+ show_emoji_helper("show_emoji_helper"),
enable_tooltip_paste("enable_tooltip_paste")
{
addSynonym(prevalidate_callback, "text_type");
@@ -258,6 +260,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mTabsToNextField(p.ignore_tab),
mPrevalidateFunc(p.prevalidate_callback()),
mShowContextMenu(p.show_context_menu),
+ mShowEmojiHelper(p.show_emoji_helper),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(FALSE),
mKeepSelectionOnReturn(false)
@@ -505,6 +508,15 @@ void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out,
}
}
+void LLTextEditor::setShowEmojiHelper(bool show) {
+ if (!mShowEmojiHelper)
+ {
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+
+ mShowEmojiHelper = show;
+}
+
BOOL LLTextEditor::selectionContainsLineBreaks()
{
if (hasSelection())
@@ -668,6 +680,21 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
endSelection();
}
+void LLTextEditor::handleEmojiCommit(const LLWString& wstr)
+{
+ LLWString wtext(getWText()); S32 shortCodePos;
+ if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
+ {
+ remove(shortCodePos, mCursorPos - shortCodePos, true);
+
+ auto styleParams = LLStyle::Params();
+ styleParams.font = LLFontGL::getFontEmoji();
+ insert(shortCodePos, wstr, false, new LLEmojiTextSegment(new LLStyle(styleParams), shortCodePos, shortCodePos + wstr.size(), *this));
+
+ setCursorPos(shortCodePos + 1);
+ }
+}
+
BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -934,6 +961,12 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
S32 LLTextEditor::execute( TextCmd* cmd )
{
+ if (!mReadOnly && mShowEmojiHelper)
+ {
+ // Any change to our contents should always hide the helper
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+
S32 delta = 0;
if( cmd->execute(this, &delta) )
{
@@ -1128,6 +1161,17 @@ void LLTextEditor::addChar(llwchar wc)
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
+ if (!mReadOnly && mShowEmojiHelper)
+ {
+ LLWString wtext(getWText()); S32 shortCodePos;
+ if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos))
+ {
+ const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos - 1);
+ const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos - shortCodePos);
+ LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode), std::bind(&LLTextEditor::handleEmojiCommit, this, std::placeholders::_1));
+ }
+ }
+
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
// autoreplace the text, if necessary
@@ -1778,6 +1822,11 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
}
else
{
+ if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
+ {
+ return TRUE;
+ }
+
if (mEnableTooltipPaste &&
LLToolTipMgr::instance().toolTipVisible() &&
KEY_TAB == key)
@@ -1819,6 +1868,12 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
{
resetCursorBlink();
needsScroll();
+
+ if (mShowEmojiHelper)
+ {
+ // Dismiss the helper whenever we handled a key that it didn't
+ LLEmojiHelper::instance().hideHelper(this);
+ }
}
return handled;
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index f3939248c2..dabd0460c6 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -60,6 +60,7 @@ public:
ignore_tab,
commit_on_focus_lost,
show_context_menu,
+ show_emoji_helper,
enable_tooltip_paste,
auto_indent;
@@ -91,6 +92,8 @@ public:
static S32 spacesPerTab();
+ void handleEmojiCommit(const LLWString& wstr);
+
// mousehandler overrides
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -202,6 +205,9 @@ public:
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
+ void setShowEmojiHelper(bool show);
+ bool getShowEmojiHelper() const { return mShowEmojiHelper; }
+
void setPassDelete(BOOL b) { mPassDelete = b; }
protected:
@@ -318,6 +324,7 @@ private:
BOOL mAllowEmbeddedItems;
bool mShowContextMenu;
+ bool mShowEmojiHelper;
bool mEnableTooltipPaste;
bool mPassDelete;
bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 67dd24341c..d71dc8d859 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -263,7 +263,7 @@ public:
class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
{
LLSINGLETON_EMPTY_CTOR(LLTextInputFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override
{
return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->acceptsTextInput(), TRUE);
}
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 9ba71913d0..2b7f05dcda 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1324,7 +1324,7 @@ void LLView::drawDebugRect()
debug_rect.getWidth(), debug_rect.getHeight());
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, S32_MAX, NULL, FALSE);
+ S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
}
LLUI::popMatrix();
@@ -1953,7 +1953,7 @@ private:
class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>
{
LLSINGLETON_EMPTY_CTOR(SortByTabOrder);
- /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const
+ /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const override
{
children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup()));
}
@@ -1977,7 +1977,7 @@ const LLViewQuery & LLView::getTabOrderQuery()
class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton<LLFocusRootsFilter>
{
LLSINGLETON_EMPTY_CTOR(LLFocusRootsFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override
{
return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot());
}
diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h
index 21bb1be26f..4bc9c4a08e 100644
--- a/indra/llui/llviewquery.h
+++ b/indra/llui/llviewquery.h
@@ -55,37 +55,37 @@ public:
class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter>
{
LLSINGLETON_EMPTY_CTOR(LLLeavesFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter>
{
LLSINGLETON_EMPTY_CTOR(LLRootsFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
{
LLSINGLETON_EMPTY_CTOR(LLVisibleFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
{
LLSINGLETON_EMPTY_CTOR(LLEnabledFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
{
LLSINGLETON_EMPTY_CTOR(LLTabStopFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter>
{
LLSINGLETON_EMPTY_CTOR(LLCtrlFilter);
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const override;
};
template <class T>
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index ead8634df4..ab5bca5d2a 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -774,7 +774,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
return 0;
}
- U32 item = 0;
U32 validitems = 0;
S32 version;
@@ -807,9 +806,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
continue;
}
- // Got an item. Load it up.
- item++;
-
// If not declared, assume it's a string
if (!declared)
{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 361718a13e..b63100fc2b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -18,6 +18,7 @@ include(DragDrop)
include(EXPAT)
include(FMODSTUDIO)
include(Hunspell)
+include(ICU4C)
include(JPEGEncoderBasic)
include(JsonCpp)
include(LLAppearance)
@@ -408,6 +409,7 @@ set(viewer_SOURCE_FILES
llpaneleditsky.cpp
llpaneleditwater.cpp
llpaneleditwearable.cpp
+ llpanelemojicomplete.cpp
llpanelenvironment.cpp
llpanelexperiencelisteditor.cpp
llpanelexperiencelog.cpp
@@ -1039,6 +1041,7 @@ set(viewer_HEADER_FILES
llpaneleditsky.h
llpaneleditwater.h
llpaneleditwearable.h
+ llpanelemojicomplete.h
llpanelenvironment.h
llpanelexperiencelisteditor.h
llpanelexperiencelog.h
@@ -1894,6 +1897,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLPHYSICSEXTENSIONS_LIBRARIES}
ll::bugsplat
ll::tracy
+ ${ICU4C_LIBRARY}
)
if( TARGET ll::intel_memops )
@@ -1907,6 +1911,12 @@ endif()
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
"Path to artwork files.")
+message("Copying fonts")
+file(GLOB FONT_FILE_GLOB_LIST
+ "${AUTOBUILD_INSTALL_DIR}/fonts/*"
+)
+file(COPY ${FONT_FILE_GLOB_LIST} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/fonts")
+
if (LINUX)
set(product SecondLife-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION})
diff --git a/indra/newview/fonts/DejaVu-license.txt b/indra/newview/fonts/DejaVu-license.txt
deleted file mode 100644
index 254e2cc42a..0000000000
--- a/indra/newview/fonts/DejaVu-license.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
-Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
-
-Bitstream Vera Fonts Copyright
-------------------------------
-
-Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
-a trademark of Bitstream, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of the fonts accompanying this license ("Fonts") and associated
-documentation files (the "Font Software"), to reproduce and distribute the
-Font Software, including without limitation the rights to use, copy, merge,
-publish, distribute, and/or sell copies of the Font Software, and to permit
-persons to whom the Font Software is furnished to do so, subject to the
-following conditions:
-
-The above copyright and trademark notices and this permission notice shall
-be included in all copies of one or more of the Font Software typefaces.
-
-The Font Software may be modified, altered, or added to, and in particular
-the designs of glyphs or characters in the Fonts may be modified and
-additional glyphs or characters may be added to the Fonts, only if the fonts
-are renamed to names not containing either the words "Bitstream" or the word
-"Vera".
-
-This License becomes null and void to the extent applicable to Fonts or Font
-Software that has been modified and is distributed under the "Bitstream
-Vera" names.
-
-The Font Software may be sold as part of a larger software package but no
-copy of one or more of the Font Software typefaces may be sold by itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
-TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
-FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
-ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
-FONT SOFTWARE.
-
-Except as contained in this notice, the names of Gnome, the Gnome
-Foundation, and Bitstream Inc., shall not be used in advertising or
-otherwise to promote the sale, use or other dealings in this Font Software
-without prior written authorization from the Gnome Foundation or Bitstream
-Inc., respectively. For further information, contact: fonts at gnome dot
-org.
-
-Arev Fonts Copyright
-------------------------------
-
-Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the fonts accompanying this license ("Fonts") and
-associated documentation files (the "Font Software"), to reproduce
-and distribute the modifications to the Bitstream Vera Font Software,
-including without limitation the rights to use, copy, merge, publish,
-distribute, and/or sell copies of the Font Software, and to permit
-persons to whom the Font Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright and trademark notices and this permission notice
-shall be included in all copies of one or more of the Font Software
-typefaces.
-
-The Font Software may be modified, altered, or added to, and in
-particular the designs of glyphs or characters in the Fonts may be
-modified and additional glyphs or characters may be added to the
-Fonts, only if the fonts are renamed to names not containing either
-the words "Tavmjong Bah" or the word "Arev".
-
-This License becomes null and void to the extent applicable to Fonts
-or Font Software that has been modified and is distributed under the
-"Tavmjong Bah Arev" names.
-
-The Font Software may be sold as part of a larger software package but
-no copy of one or more of the Font Software typefaces may be sold by
-itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
-TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
-
-Except as contained in this notice, the name of Tavmjong Bah shall not
-be used in advertising or otherwise to promote the sale, use or other
-dealings in this Font Software without prior written authorization
-from Tavmjong Bah. For further information, contact: tavmjong @ free
-. fr.
-
-$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
diff --git a/indra/newview/fonts/DejaVuSans-Bold.ttf b/indra/newview/fonts/DejaVuSans-Bold.ttf
deleted file mode 100644
index ec1a2ebaf2..0000000000
--- a/indra/newview/fonts/DejaVuSans-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
deleted file mode 100644
index 1a5576460d..0000000000
--- a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf
deleted file mode 100644
index becc549927..0000000000
--- a/indra/newview/fonts/DejaVuSans-Oblique.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf
deleted file mode 100644
index c1b19d8705..0000000000
--- a/indra/newview/fonts/DejaVuSans.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf
deleted file mode 100644
index 6bc854ddae..0000000000
--- a/indra/newview/fonts/DejaVuSansMono.ttf
+++ /dev/null
Binary files differ
diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi
index 7922d9df52..0985663041 100755
--- a/indra/newview/installers/windows/lang_zh.nsi
+++ b/indra/newview/installers/windows/lang_zh.nsi
Binary files differ
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 9018a5f168..f158d312ff 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3707,7 +3707,6 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
// take controls
msg->getU32("Data", "Controls", controls, block_index );
msg->getBOOL("Data", "PassToAgent", passon, block_index );
- U32 total_count = 0;
for (i = 0; i < TOTAL_CONTROLS; i++)
{
if (controls & ( 1 << i))
@@ -3720,7 +3719,6 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
{
gAgent.mControlsTakenCount[i]++;
}
- total_count++;
}
}
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9e06fc3ac0..8a0e304d66 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3195,15 +3195,16 @@ LLSD LLAppViewer::getViewerInfo() const
// LLFloaterAbout.
LLSD info;
auto& versionInfo(LLVersionInfo::instance());
- info["VIEWER_VERSION"] = LLSDArray(versionInfo.getMajor())(versionInfo.getMinor())(versionInfo.getPatch())(versionInfo.getBuild());
+ info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(),
+ versionInfo.getPatch(), versionInfo.getBuild());
info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
info["CHANNEL"] = versionInfo.getChannel();
- info["ADDRESS_SIZE"] = ADDRESS_SIZE;
- std::string build_config = versionInfo.getBuildConfig();
- if (build_config != "Release")
- {
- info["BUILD_CONFIG"] = build_config;
- }
+ info["ADDRESS_SIZE"] = ADDRESS_SIZE;
+ std::string build_config = versionInfo.getBuildConfig();
+ if (build_config != "Release")
+ {
+ info["BUILD_CONFIG"] = build_config;
+ }
// return a URL to the release notes for this viewer, such as:
// https://releasenotes.secondlife.com/viewer/2.1.0.123456.html
diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h
index 23cc313646..a1eebf9dcb 100644
--- a/indra/newview/llautoreplace.h
+++ b/indra/newview/llautoreplace.h
@@ -203,7 +203,7 @@ public:
void setSettings(const LLAutoReplaceSettings& settings);
private:
- /*virtual*/ void initSingleton();
+ /*virtual*/ void initSingleton() override;
LLAutoReplaceSettings mSettings; ///< configuration information
diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h
index 8abe350196..22ae595d66 100644
--- a/indra/newview/llchannelmanager.h
+++ b/indra/newview/llchannelmanager.h
@@ -46,7 +46,7 @@ class LLChannelManager : public LLSingleton<LLChannelManager>
LLSINGLETON(LLChannelManager);
virtual ~LLChannelManager();
- void cleanupSingleton();
+ void cleanupSingleton() override;
public:
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 9a608fba8e..f4fa449ca2 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -1096,6 +1096,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
editor_params.enabled = false; // read only
editor_params.show_context_menu = "true";
editor_params.trusted_content = false;
+ editor_params.text_valign = LLFontGL::VAlign::VCENTER;
+ editor_params.use_color = true;
mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
mEditor->setIsFriendCallback(LLAvatarActions::isFriend);
mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h
index 6c521dc1d5..c295b99962 100644
--- a/indra/newview/llchicletbar.h
+++ b/indra/newview/llchicletbar.h
@@ -43,11 +43,11 @@ class LLChicletBar
public:
- BOOL postBuild();
+ BOOL postBuild() override;
LLChicletPanel* getChicletPanel() { return mChicletPanel; }
- /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent) override;
/**
diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h
index 820a5db491..54aeedcf9a 100644
--- a/indra/newview/llconversationlog.h
+++ b/indra/newview/llconversationlog.h
@@ -125,11 +125,11 @@ public:
void removeObserver(LLConversationLogObserver* observer);
// LLIMSessionObserver triggers
- virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg);
- virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; // Stub
- virtual void sessionRemoved(const LLUUID& session_id){} // Stub
- virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}; // Stub
- virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}; // Stub
+ virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) override;
+ virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub
+ virtual void sessionRemoved(const LLUUID& session_id) override{} // Stub
+ virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override{}; // Stub
+ virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override{}; // Stub
void notifyObservers();
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 3395777aab..2d332f75f5 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -88,7 +88,7 @@ public:
mStyle->getShadowType(),
end - start, draw_rect.getWidth(),
&right_x,
- mEditor.getUseEllipses());
+ mEditor.getUseEllipses(), mEditor.getUseColor());
return right_x;
}
/*virtual*/ bool canEdit() const { return false; }
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 42a226cd18..d9269224af 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -101,7 +101,7 @@ class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManag
~LLFeatureManager() {cleanupFeatureTables();}
// initialize this by loading feature table and gpu table
- void initSingleton();
+ void initSingleton() override;
public:
diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp
index 8633fe4e5e..a3222d622f 100644
--- a/indra/newview/llfloaterlandholdings.cpp
+++ b/indra/newview/llfloaterlandholdings.cpp
@@ -39,6 +39,7 @@
#include "llfloaterworldmap.h"
#include "llproductinforequest.h"
#include "llscrolllistctrl.h"
+#include "llsdutil.h"
#include "llstatusbar.h"
#include "lltextbox.h"
#include "llscrolllistctrl.h"
@@ -79,24 +80,25 @@ BOOL LLFloaterLandHoldings::postBuild()
for(S32 i = 0; i < count; ++i)
{
LLUUID id(gAgent.mGroups.at(i).mID);
-
- LLSD element;
- element["id"] = id;
- element["columns"][0]["column"] = "group";
- element["columns"][0]["value"] = gAgent.mGroups.at(i).mName;
- element["columns"][0]["font"] = "SANSSERIF";
-
LLUIString areastr = getString("area_string");
areastr.setArg("[AREA]", llformat("%d", gAgent.mGroups.at(i).mContribution));
- element["columns"][1]["column"] = "area";
- element["columns"][1]["value"] = areastr;
- element["columns"][1]["font"] = "SANSSERIF";
- grant_list->addElement(element);
+ grant_list->addElement(
+ llsd::map(
+ "id", id,
+ "columns", llsd::array(
+ llsd::map(
+ "column", "group",
+ "value", gAgent.mGroups.at(i).mName,
+ "font", "SANSSERIF"),
+ llsd::map(
+ "column", "area",
+ "value", areastr,
+ "font", "SANSSERIF"))));
}
-
+
center();
-
+
return TRUE;
}
@@ -108,8 +110,8 @@ LLFloaterLandHoldings::~LLFloaterLandHoldings()
void LLFloaterLandHoldings::onOpen(const LLSD& key)
{
- LLScrollListCtrl *list = getChild<LLScrollListCtrl>("parcel list");
- list->clearRows();
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("parcel list");
+ list->clearRows();
// query_id null is known to be us
const LLUUID& query_id = LLUUID::null;
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index e67c79a3a0..9d16faf0b5 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -1601,7 +1601,7 @@ void LLOverlapPanel::draw()
LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5
LLView::sDrawPreviewHighlights = FALSE;
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color,
- LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
else
{
@@ -1619,7 +1619,7 @@ void LLOverlapPanel::draw()
std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)");
S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10;
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color,
- LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
// widen panel enough to fit this text
LLRect rect = getRect();
setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop));
@@ -1685,7 +1685,7 @@ void LLOverlapPanel::draw()
// draw currently-selected element at top of overlappers
LLUI::translate(0,-mSpacing);
LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color,
- LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight()); // skip spacing distance + height
LLView::sPreviewClickedElement->draw();
@@ -1700,7 +1700,7 @@ void LLOverlapPanel::draw()
// draw name
LLUI::translate(0,-mSpacing);
LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color,
- LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
// draw element
LLUI::translate(0,-mSpacing-viewp->getRect().getHeight()); // skip spacing distance + height
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index f5679d7d85..ef0dda7949 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -55,7 +55,7 @@ public:
};
// LLFriendObserver implementation
- void changed(U32 mask)
+ void changed(U32 mask) override
{
onFriendListUpdate(mask);
}
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index 7c8e8279c2..7bb60f00e2 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -135,7 +135,7 @@ public:
void notifyObservers();
// Overriding so we can update active gesture names and notify observers
- void changed(U32 mask);
+ void changed(U32 mask) override;
BOOL matchPrefix(const std::string& in_str, std::string* out_str);
@@ -150,7 +150,7 @@ protected:
void runStep(LLMultiGesture* gesture, LLGestureStep* step);
// LLInventoryCompletionObserver trigger
- void done();
+ void done() override;
// Used by loadGesture
static void onLoadComplete(const LLUUID& asset_uuid,
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index dff310ecf9..c1f17c9d33 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -138,7 +138,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
F32 right_x;
- font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
+ font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x, /*use_ellipses*/false, /*use_color*/true);
LLUI::popMatrix();
gGL.popMatrix();
diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
index d06212d85a..05d1806da4 100644
--- a/indra/newview/llimagefiltersmanager.h
+++ b/indra/newview/llimagefiltersmanager.h
@@ -45,7 +45,7 @@ private:
void loadAllFilters();
void loadFiltersFromDir(const std::string& dir);
- /*virtual*/ void initSingleton();
+ /*virtual*/ void initSingleton() override;
// List of filters : first is the user friendly localized name, second is the xml file name
std::map<std::string,std::string> mFiltersList;
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 946eb02f26..bace97d37a 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -537,7 +537,7 @@ public:
static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent);
private:
- void initSingleton();
+ void initSingleton() override;
void onVoiceChannelChangedInt(const LLUUID &session_id);
void onVoiceChannelStateChangedInt(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction, bool ended_by_agent);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index f937754368..18420a2356 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1865,7 +1865,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
U32 header_size = 0;
if (data_size > 0)
{
- U32 dsize = data_size;
+ llssize dsize = data_size;
char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size);
data_size = dsize;
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index e1a5b22490..495153981b 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -2685,9 +2685,6 @@ void LLModelPreview::clearBuffers()
void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
{
- U32 mesh_count = 0;
-
-
LLModelLoader::model_list* model = NULL;
if (lod < 0 || lod > 4)
@@ -2818,8 +2815,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
vb->flush();
mVertexBuffer[lod][mdl].push_back(vb);
-
- ++mesh_count;
}
}
}
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 2c45014321..bf3eecfe77 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -73,7 +73,7 @@ class LLMuteList : public LLSingleton<LLMuteList>
{
LLSINGLETON(LLMuteList);
~LLMuteList();
- /*virtual*/ void cleanupSingleton();
+ /*virtual*/ void cleanupSingleton() override;
public:
// reasons for auto-unmuting a resident
enum EAutoReason
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 11c671294a..4649f5bcb0 100755
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -92,10 +92,10 @@ class LLNavigationBar
public:
- /*virtual*/ void draw();
- /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ void draw() override;
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ BOOL postBuild() override;
+ /*virtual*/ void setVisible(BOOL visible) override;
void handleLoginComplete();
void clearHistoryCache();
diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h
index 77041db68d..77bb3543aa 100644
--- a/indra/newview/lloutfitobserver.h
+++ b/indra/newview/lloutfitobserver.h
@@ -41,7 +41,7 @@ class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitO
public:
- virtual void changed(U32 mask);
+ virtual void changed(U32 mask) override;
void notifyOutfitLockChanged() { mOutfitLockChanged(); }
diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp
new file mode 100644
index 0000000000..8b89e3aa14
--- /dev/null
+++ b/indra/newview/llpanelemojicomplete.cpp
@@ -0,0 +1,321 @@
+/**
+* @file llpanelemojicomplete.h
+* @brief Header file for LLPanelEmojiComplete
+*
+* $LicenseInfo:firstyear=2012&license=lgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llemojidictionary.h"
+#include "llemojihelper.h"
+#include "llpanelemojicomplete.h"
+#include "lluictrlfactory.h"
+
+constexpr U32 MIN_MOUSE_MOVE_DELTA = 4;
+
+// ============================================================================
+// LLPanelEmojiComplete
+//
+
+static LLDefaultChildRegistry::Register<LLPanelEmojiComplete> r("emoji_complete");
+
+LLPanelEmojiComplete::Params::Params()
+ : autosize("autosize")
+ , max_emoji("max_emoji")
+ , padding("padding")
+ , selected_image("selected_image")
+{
+}
+
+LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p)
+ : LLUICtrl(p)
+ , mAutoSize(p.autosize)
+ , mMaxVisible(p.max_emoji)
+ , mPadding(p.padding)
+ , mSelectedImage(p.selected_image)
+{
+ setFont(p.font);
+}
+
+LLPanelEmojiComplete::~LLPanelEmojiComplete()
+{
+}
+
+void LLPanelEmojiComplete::draw()
+{
+ if (!mEmojis.empty())
+ {
+ const S32 centerY = mRenderRect.getCenterY();
+ const size_t firstVisibleIdx = mScrollPos, lastVisibleIdx = llmin(mScrollPos + mVisibleEmojis, mEmojis.size()) - 1;
+
+ if (mCurSelected >= firstVisibleIdx && mCurSelected <= lastVisibleIdx)
+ {
+ const S32 emoji_left = mRenderRect.mLeft + (mCurSelected - firstVisibleIdx) * mEmojiWidth;
+ const S32 emoji_height = mFont->getLineHeight() + mPadding;
+ mSelectedImage->draw(emoji_left, centerY - emoji_height / 2, mEmojiWidth, emoji_height);
+ }
+
+ U32 left = mRenderRect.mLeft + mPadding;
+ for (U32 curIdx = firstVisibleIdx; curIdx <= lastVisibleIdx; curIdx++)
+ {
+ mFont->render(
+ mEmojis, curIdx,
+ left, centerY,
+ LLColor4::white, LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT,
+ 1, S32_MAX, nullptr, false, true);
+ left += mEmojiWidth;
+ }
+ }
+}
+
+BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask)
+{
+ LLVector2 curHover(x, y);
+ if ((mLastHover - curHover).lengthSquared() > MIN_MOUSE_MOVE_DELTA)
+ {
+ mCurSelected = posToIndex(x, y);
+ mLastHover = curHover;
+ }
+
+ return TRUE;
+}
+
+BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ bool handled = false;
+ if (MASK_NONE == mask)
+ {
+ switch (key)
+ {
+ case KEY_LEFT:
+ case KEY_UP:
+ selectPrevious();
+ handled = true;
+ break;
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ selectNext();
+ handled = true;
+ break;
+ case KEY_RETURN:
+ if (!mEmojis.empty())
+ {
+ onCommit();
+ handled = true;
+ }
+ break;
+ }
+ }
+
+ if (handled)
+ {
+ return TRUE;
+ }
+ return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+BOOL LLPanelEmojiComplete::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ mCurSelected = posToIndex(x, y);
+ mLastHover = LLVector2(x, y);
+
+ return TRUE;
+}
+
+BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ mCurSelected = posToIndex(x, y);
+ onCommit();
+
+ return TRUE;
+}
+
+void LLPanelEmojiComplete::onCommit()
+{
+ if (npos != mCurSelected)
+ {
+ LLWString wstr;
+ wstr.push_back(mEmojis.at(mCurSelected));
+ setValue(wstring_to_utf8str(wstr));
+ LLUICtrl::onCommit();
+ }
+}
+
+void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLUICtrl::reshape(width, height, called_from_parent);
+ updateConstraints();
+}
+
+void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
+{
+ llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0;
+
+ mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint);
+ size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos;
+ mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0;
+
+ if (mAutoSize)
+ {
+ mVisibleEmojis = std::min(mEmojis.size(), mMaxVisible);
+ reshape(mVisibleEmojis * mEmojiWidth, getRect().getHeight(), false);
+ }
+ else
+ {
+ updateConstraints();
+ }
+
+ mScrollPos = llmin(mScrollPos, mEmojis.size());
+}
+
+size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const
+{
+ if (mRenderRect.pointInRect(x, y))
+ {
+ return mScrollPos + llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1);
+ }
+ return npos;
+}
+
+void LLPanelEmojiComplete::select(size_t emoji_idx)
+{
+ mCurSelected = llclamp<size_t>(emoji_idx, 0, mEmojis.size());
+ updateScrollPos();
+}
+
+void LLPanelEmojiComplete::selectNext()
+{
+ select(mCurSelected + 1 < mEmojis.size() ? mCurSelected + 1 : 0);
+}
+
+void LLPanelEmojiComplete::selectPrevious()
+{
+ select(mCurSelected - 1 >= 0 ? mCurSelected - 1 : mEmojis.size() - 1);
+}
+
+void LLPanelEmojiComplete::setFont(const LLFontGL* fontp)
+{
+ mFont = fontp;
+ updateConstraints();
+}
+
+void LLPanelEmojiComplete::updateConstraints()
+{
+ const S32 ctrlWidth = getLocalRect().getWidth();
+
+ mEmojiWidth = mFont->getWidthF32(u8"\U0001F431") + mPadding * 2;
+ mVisibleEmojis = ctrlWidth / mEmojiWidth;
+ mRenderRect = getLocalRect().stretch((ctrlWidth - mVisibleEmojis * mEmojiWidth) / -2, 0);
+
+ updateScrollPos();
+}
+
+void LLPanelEmojiComplete::updateScrollPos()
+{
+ const size_t cntEmoji = mEmojis.size();
+ if (0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected)
+ {
+ mScrollPos = 0;
+ }
+ else if (cntEmoji - 1 == mCurSelected)
+ {
+ mScrollPos = mCurSelected - mVisibleEmojis + 1;
+ }
+ else
+ {
+ mScrollPos = mCurSelected - ((float)mCurSelected / (cntEmoji - 2) * (mVisibleEmojis - 2));
+ }
+}
+
+// ============================================================================
+// LLFloaterEmojiComplete
+//
+
+LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey)
+ : LLFloater(sdKey)
+{
+ // This floater should hover on top of our dependent (with the dependent having the focus)
+ setFocusStealsFrontmost(false);
+ setAutoFocus(false);
+ setBackgroundVisible(false);
+ setIsChrome(true);
+}
+
+BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ bool handled = false;
+ if (MASK_NONE == mask)
+ {
+ switch (key)
+ {
+ case KEY_ESCAPE:
+ LLEmojiHelper::instance().hideHelper();
+ handled = true;
+ break;
+ }
+
+ }
+
+ if (handled)
+ return TRUE;
+ return LLFloater::handleKey(key, mask, called_from_parent);
+}
+
+void LLFloaterEmojiComplete::onOpen(const LLSD& key)
+{
+ mEmojiCtrl->setEmojiHint(key["hint"].asString());
+ if (0 == mEmojiCtrl->getEmojiCount())
+ {
+ LLEmojiHelper::instance().hideHelper();
+ }
+}
+
+BOOL LLFloaterEmojiComplete::postBuild()
+{
+ mEmojiCtrl = findChild<LLPanelEmojiComplete>("emoji_complete_ctrl");
+ mEmojiCtrl->setCommitCallback(
+ std::bind([&](const LLSD& sdValue)
+ {
+ setValue(sdValue);
+ onCommit();
+ }, std::placeholders::_2));
+ mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth();
+
+ return LLFloater::postBuild();
+}
+
+void LLFloaterEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ if (!called_from_parent)
+ {
+ LLRect rctFloater = getRect(), rctCtrl = mEmojiCtrl->getRect();
+ rctFloater.mRight = rctFloater.mLeft + rctCtrl.getWidth() + mEmojiCtrlHorz;
+ setRect(rctFloater);
+
+ return;
+ }
+
+ LLFloater::reshape(width, height, called_from_parent);
+}
+
+// ============================================================================
diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h
new file mode 100644
index 0000000000..aa0f806525
--- /dev/null
+++ b/indra/newview/llpanelemojicomplete.h
@@ -0,0 +1,115 @@
+/**
+* @file llpanelemojicomplete.h
+* @brief Header file for LLPanelEmojiComplete
+*
+* $LicenseInfo:firstyear=2014&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2014, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#pragma once
+
+#include "llfloater.h"
+#include "lluictrl.h"
+
+// ============================================================================
+// LLPanelEmojiComplete
+//
+
+class LLPanelEmojiComplete : public LLUICtrl
+{
+ friend class LLUICtrlFactory;
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> autosize;
+ Optional<S32> max_emoji,
+ padding;
+
+ Optional<LLUIImage*> selected_image;
+
+ Params();
+ };
+
+protected:
+ LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&);
+public:
+ virtual ~LLPanelEmojiComplete();
+
+ void draw() override;
+ BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
+ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ void onCommit() override;
+ void reshape(S32 width, S32 height, BOOL called_from_parent) override;
+
+public:
+ size_t getEmojiCount() const { return mEmojis.size(); }
+ void setEmojiHint(const std::string& hint);
+protected:
+ size_t posToIndex(S32 x, S32 y) const;
+ void select(size_t emoji_idx);
+ void selectNext();
+ void selectPrevious();
+ void setFont(const LLFontGL* fontp);
+ void updateConstraints();
+ void updateScrollPos();
+
+protected:
+ static constexpr auto npos = std::numeric_limits<size_t>::max();
+
+ bool mAutoSize = false;
+ const LLFontGL* mFont;
+ U16 mEmojiWidth = 0;
+ size_t mMaxVisible = 0;
+ S32 mPadding = 8;
+ LLRect mRenderRect;
+ LLUIImagePtr mSelectedImage;
+
+ LLWString mEmojis;
+ size_t mVisibleEmojis = 0;
+ size_t mFirstVisible = 0;
+ size_t mScrollPos = 0;
+ size_t mCurSelected = 0;
+ LLVector2 mLastHover;
+};
+
+// ============================================================================
+// LLFloaterEmojiComplete
+//
+
+class LLFloaterEmojiComplete : public LLFloater
+{
+public:
+ LLFloaterEmojiComplete(const LLSD& sdKey);
+
+public:
+ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
+ void onOpen(const LLSD& key) override;
+ BOOL postBuild() override;
+ void reshape(S32 width, S32 height, BOOL called_from_parent) override;
+
+protected:
+ LLPanelEmojiComplete* mEmojiCtrl = nullptr;
+ S32 mEmojiCtrlHorz = 0;
+};
+
+// ============================================================================
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index 02911313ed..c1eae27636 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -619,7 +619,6 @@ void LLPanelNearByMedia::refreshList()
LLViewerMedia::impl_list impls = media_inst->getPriorityList();
LLViewerMedia::impl_list::iterator priority_iter;
- U32 enabled_count = 0;
U32 disabled_count = 0;
// iterate over the impl list, creating rows as necessary.
@@ -662,10 +661,7 @@ void LLPanelNearByMedia::refreshList()
{
disabled_count++;
}
- else {
- enabled_count++;
}
- }
}
mDisableAllCtrl->setEnabled((gSavedSettings.getBOOL("AudioStreamingMusic") ||
gSavedSettings.getBOOL("AudioStreamingMedia")) &&
diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h
index 78dd997029..b6c263e331 100644
--- a/indra/newview/llpaneltopinfobar.h
+++ b/indra/newview/llpaneltopinfobar.h
@@ -46,8 +46,8 @@ class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>,
public:
typedef boost::signals2::signal<void ()> resize_signal_t;
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void draw();
+ /*virtual*/ BOOL postBuild() override;
+ /*virtual*/ void draw() override;
/**
* Updates location and parcel icons on login complete
@@ -83,7 +83,7 @@ private:
*/
void initParcelIcons();
- BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
/**
* Handles clicks on the parcel icons.
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp
index 0287c07f96..c297cac771 100644
--- a/indra/newview/llpathfindingnavmesh.cpp
+++ b/indra/newview/llpathfindingnavmesh.cpp
@@ -143,7 +143,7 @@ void LLPathfindingNavMesh::handleNavMeshResult(const LLSD &pContent, U32 pNavMes
unsigned int binSize = value.size();
std::string newStr(reinterpret_cast<const char *>(&value[0]), binSize);
std::istringstream streamdecomp( newStr );
- unsigned int decompBinSize = 0;
+ size_t decompBinSize = 0;
bool valid = false;
U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ;
if ( !valid )
diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h
index 88cb3a15f8..f98624e30d 100644
--- a/indra/newview/llpathfindingpathtool.h
+++ b/indra/newview/llpathfindingpathtool.h
@@ -66,17 +66,17 @@ public:
typedef boost::signals2::signal<void (void)> path_event_signal_t;
typedef boost::signals2::connection path_event_slot_t;
- virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseDown(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleMouseUp(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleRightMouseDown(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleRightMouseUp(S32 pX, S32 pY, MASK pMask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
- virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask);
+ virtual BOOL handleHover(S32 pX, S32 pY, MASK pMask) override;
- virtual BOOL handleKey(KEY pKey, MASK pMask);
+ virtual BOOL handleKey(KEY pKey, MASK pMask) override;
EPathStatus getPathStatus() const;
diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h
index d1036374e8..0b94c39d11 100644
--- a/indra/newview/llproductinforequest.h
+++ b/indra/newview/llproductinforequest.h
@@ -46,7 +46,7 @@ public:
std::string getDescriptionForSku(const std::string& sku);
private:
- /* virtual */ void initSingleton();
+ /* virtual */ void initSingleton() override;
void getLandDescriptionsCoro(std::string url);
LLSD mSkuDescriptions;
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index 1b322f2c0a..0c04222a9f 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -106,7 +106,7 @@ public:
/**
* LLSimpleListener interface.
*/
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) override;
void updateAvatarsArrivalTime(uuid_vec_t& uuids);
F32 getArrivalTimeByID(const LLUUID& id);
diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp
index 5e339a52bf..2f55d4cdaf 100644
--- a/indra/newview/llsceneview.cpp
+++ b/indra/newview/llsceneview.cpp
@@ -99,9 +99,6 @@ void LLSceneView::draw()
std::vector<F32> physics_cost[2];
F32 total_physics[] = { 0.f, 0.f };
-
- U32 object_count = 0;
-
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
@@ -116,7 +113,6 @@ void LLSceneView::draw()
U32 idx = object->isAttachment() ? 1 : 0;
LLVolume* volume = object->getVolume();
- object_count++;
F32 radius = object->getScale().magVec();
size[idx].push_back(radius);
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 86f7d2bf25..eea00da43e 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -5273,9 +5273,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
LLSelectNode* linkset_root = NULL;
LLViewerRegion* last_region;
LLViewerRegion* current_region;
-
- S32 objects_sent = 0;
- S32 packets_sent = 0;
S32 objects_in_this_packet = 0;
bool link_operation = message_name == "ObjectLink";
@@ -5407,7 +5404,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
(*pack_body)(node, user_data);
// do any related logging
(*log_func)(node, user_data);
- ++objects_sent;
++objects_in_this_packet;
// and on to the next object
@@ -5425,7 +5421,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
{
// otherwise send current message and start new one
gMessageSystem->sendReliable( last_region->getHost());
- packets_sent++;
objects_in_this_packet = 0;
gMessageSystem->newMessage(message_name.c_str());
@@ -5442,7 +5437,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
{
// add root instance into new message
(*pack_body)(linkset_root, user_data);
- ++objects_sent;
++objects_in_this_packet;
}
}
@@ -5456,7 +5450,6 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
if (gMessageSystem->getCurrentSendTotal() > 0)
{
gMessageSystem->sendReliable( current_region->getHost());
- packets_sent++;
}
else
{
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 707b602fc6..b1eed81476 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -568,11 +568,11 @@ void LLSettingsVOSky::convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings)
legacy[SETTING_BLUE_DENSITY] = ensure_array_4(legacyhaze[SETTING_BLUE_DENSITY], 1.0);
legacy[SETTING_BLUE_HORIZON] = ensure_array_4(legacyhaze[SETTING_BLUE_HORIZON], 1.0);
- legacy[SETTING_DENSITY_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
- legacy[SETTING_DISTANCE_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_DENSITY_MULTIPLIER] = llsd::array(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal(), 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_DISTANCE_MULTIPLIER] = llsd::array(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal(), 0.0f, 0.0f, 1.0f);
- legacy[SETTING_HAZE_DENSITY] = LLSDArray(legacyhaze[SETTING_HAZE_DENSITY])(0.0f)(0.0f)(1.0f);
- legacy[SETTING_HAZE_HORIZON] = LLSDArray(legacyhaze[SETTING_HAZE_HORIZON])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_HAZE_DENSITY] = llsd::array(legacyhaze[SETTING_HAZE_DENSITY], 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_HAZE_HORIZON] = llsd::array(legacyhaze[SETTING_HAZE_HORIZON], 0.0f, 0.0f, 1.0f);
}
}
@@ -586,15 +586,15 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA
legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0);
legacy[SETTING_CLOUD_POS_DENSITY1] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY1], 1.0);
legacy[SETTING_CLOUD_POS_DENSITY2] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY2], 1.0);
- legacy[SETTING_CLOUD_SCALE] = LLSDArray(settings[SETTING_CLOUD_SCALE])(LLSD::Real(0.0))(LLSD::Real(0.0))(LLSD::Real(1.0));
+ legacy[SETTING_CLOUD_SCALE] = llsd::array(settings[SETTING_CLOUD_SCALE], LLSD::Real(0.0), LLSD::Real(0.0), LLSD::Real(1.0));
legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE];
- legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = LLSDArray(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())))
- (LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));
- legacy[SETTING_CLOUD_SHADOW] = LLSDArray(settings[SETTING_CLOUD_SHADOW].asReal())(0.0f)(0.0f)(1.0f);
- legacy[SETTING_GAMMA] = LLSDArray(settings[SETTING_GAMMA])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = llsd::array(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())),
+ LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));
+ legacy[SETTING_CLOUD_SHADOW] = llsd::array(settings[SETTING_CLOUD_SHADOW].asReal(), 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_GAMMA] = llsd::array(settings[SETTING_GAMMA], 0.0f, 0.0f, 1.0f);
legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0);
legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f);
- legacy[SETTING_MAX_Y] = LLSDArray(settings[SETTING_MAX_Y])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_MAX_Y] = llsd::array(settings[SETTING_MAX_Y], 0.0f, 0.0f, 1.0f);
legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS].asReal() / 250.0f; // convert from 0-500 -> 0-2 ala pre-FS-compat changes
legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f);
@@ -1062,7 +1062,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n
newsettings[SETTING_NAME] = name;
- LLSD watertrack = LLSDArray(
+ LLSD watertrack = llsd::array(
LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
(SETTING_KEYNAME, "water:Default"));
@@ -1077,7 +1077,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n
skytrack.append(entry);
}
- newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
+ newsettings[SETTING_TRACKS] = llsd::array(watertrack, skytrack);
LLSD frames(LLSD::emptyMap());
@@ -1165,7 +1165,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regio
watersettings[SETTING_NAME] = watername;
frames[watername] = watersettings;
- LLSD watertrack = LLSDArray(
+ LLSD watertrack = llsd::array(
LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
(SETTING_KEYNAME, watername));
@@ -1179,7 +1179,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regio
LLSD newsettings = LLSDMap
( SETTING_NAME, "Region (legacy)" )
- ( SETTING_TRACKS, LLSDArray(watertrack)(skytrack))
+ ( SETTING_TRACKS, llsd::array(watertrack, skytrack))
( SETTING_FRAMES, frames )
( SETTING_TYPE, "daycycle" );
@@ -1360,7 +1360,7 @@ LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
skys[name.str()] = std::static_pointer_cast<LLSettingsSky>((*it).second);
F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first;
- llsdcycle.append( LLSDArray(LLSD::Real(frame))(name.str()) );
+ llsdcycle.append( llsd::array(LLSD::Real(frame), name.str()) );
}
LLSD llsdskylist(LLSD::emptyMap());
@@ -1373,7 +1373,7 @@ LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
llsdskylist[(*its).first] = llsdsky;
}
- return LLSDArray(LLSD::emptyMap())(llsdcycle)(llsdskylist)(llsdwater);
+ return llsd::array(LLSD::emptyMap(), llsdcycle, llsdskylist, llsdwater);
}
LLSettingsSkyPtr_t LLSettingsVODay::getDefaultSky() const
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index ed795b5155..22c9481687 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -338,7 +338,7 @@ class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeak
LOG_CLASS(LLActiveSpeakerMgr);
protected:
- virtual void updateSpeakerList();
+ virtual void updateSpeakerList() override;
};
class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
@@ -347,7 +347,7 @@ class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeaker
~LLLocalSpeakerMgr ();
LOG_CLASS(LLLocalSpeakerMgr);
protected:
- virtual void updateSpeakerList();
+ virtual void updateSpeakerList() override;
};
#endif // LL_LLSPEAKERS_H
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index 0111d8869c..c4c9673be3 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -53,7 +53,7 @@ class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, L
LOG_CLASS(SpeakingIndicatorManager);
protected:
- void cleanupSingleton();
+ void cleanupSingleton() override;
public:
@@ -88,7 +88,7 @@ public:
* So, method does not calculate difference between these list it only switches off already
* switched on indicators and switches on indicators of voice channel participants
*/
- void onParticipantsChanged();
+ void onParticipantsChanged() override;
private:
typedef std::set<LLUUID> speaker_ids_t;
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index c3eb70f850..fd41cdf0d7 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -79,7 +79,6 @@ void LLSprite::updateFace(LLFace &face)
// First, figure out how many vertices/indices we need.
U32 num_vertices, num_indices;
- U32 vertex_count = 0;
// Get the total number of vertices and indices
if (mFollow)
@@ -203,25 +202,21 @@ void LLSprite::updateFace(LLFace &face)
*verticesp = mC;
tex_coordsp++;
verticesp++;
- vertex_count++;
*tex_coordsp = LLVector2(0.f, 1.f);
*verticesp = mB;
tex_coordsp++;
verticesp++;
- vertex_count++;
*tex_coordsp = LLVector2(1.f, 1.f);
*verticesp = mA;
tex_coordsp++;
verticesp++;
- vertex_count++;
*tex_coordsp = LLVector2(1.f, 0.0f);
*verticesp = mD;
tex_coordsp++;
verticesp++;
- vertex_count++;
// Generate indices, since they're easy.
// Just a series of quads.
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6883ead5ee..8fc94ed782 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -3244,7 +3244,7 @@ LLSD transform_cert_args(LLPointer<LLCertificate> cert)
// are actually arrays, and we want to format them as comma separated
// strings, so special case those.
LLSDSerialize::toXML(cert_info[iter->first], std::cout);
- if((iter->first== std::string(CERT_KEY_USAGE)) |
+ if((iter->first== std::string(CERT_KEY_USAGE)) ||
(iter->first == std::string(CERT_EXTENDED_KEY_USAGE)))
{
value = "";
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index af89b4b53b..5c6f7254f2 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -859,12 +859,12 @@ LLTextureCache::~LLTextureCache()
//////////////////////////////////////////////////////////////////////////////
//virtual
-S32 LLTextureCache::update(F32 max_time_ms)
+size_t LLTextureCache::update(F32 max_time_ms)
{
static LLFrameTimer timer ;
static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds.
- S32 res;
+ size_t res;
res = LLWorkerThread::update(max_time_ms);
mListMutex.lock();
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index e1c752b58e..b6ace467c7 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -113,7 +113,7 @@ public:
LLTextureCache(bool threaded);
~LLTextureCache();
- /*virtual*/ S32 update(F32 max_time_ms);
+ /*virtual*/ size_t update(F32 max_time_ms);
void purgeCache(ELLPath location, bool remove_dir = true);
void setReadOnly(BOOL read_only) ;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index a7dcb1a9bb..6f6ca2be9b 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2879,9 +2879,9 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
// Threads: T*
//virtual
-S32 LLTextureFetch::getPending()
+size_t LLTextureFetch::getPending()
{
- S32 res;
+ size_t res;
lockData(); // +Ct
{
LLMutexLock lock(&mQueueMutex); // +Mfq
@@ -2956,7 +2956,7 @@ void LLTextureFetch::commonUpdate()
// Threads: Tmain
//virtual
-S32 LLTextureFetch::update(F32 max_time_ms)
+size_t LLTextureFetch::update(F32 max_time_ms)
{
static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0);
@@ -2970,7 +2970,7 @@ S32 LLTextureFetch::update(F32 max_time_ms)
mNetworkQueueMutex.unlock(); // -Mfnq
}
- S32 res = LLWorkerThread::update(max_time_ms);
+ size_t res = LLWorkerThread::update(max_time_ms);
if (!mThreaded)
{
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index d087db275b..611a7d6419 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -65,7 +65,7 @@ public:
class TFRequest;
// Threads: Tmain
- /*virtual*/ S32 update(F32 max_time_ms);
+ /*virtual*/ size_t update(F32 max_time_ms);
// called in the main thread after the TextureCacheThread shuts down.
// Threads: Tmain
@@ -131,7 +131,7 @@ public:
U32 getTotalNumHTTPRequests();
// Threads: T*
- S32 getPending();
+ size_t getPending();
// Threads: T*
void lockQueue() { mQueueMutex.lock(); }
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index cf9211767e..f0033692c0 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -613,7 +613,7 @@ void LLGLTexMemBar::draw()
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX,
- &x_right, FALSE);
+ &x_right, /*use_ellipses*/FALSE, /*use_color*/FALSE);
F32Kilobits bandwidth(LLAppViewer::getTextureFetch()->getTextureBandwidth());
F32Kilobits max_bandwidth(gSavedSettings.getF32("ThrottleBandwidthKBPS"));
@@ -845,8 +845,6 @@ void LLTextureView::draw()
if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
{
- static S32 debug_count = 0;
- ++debug_count; // for breakpoints
}
F32 pri;
diff --git a/indra/newview/lltoolbrush.h b/indra/newview/lltoolbrush.h
index c108d83256..6545ee3611 100644
--- a/indra/newview/lltoolbrush.h
+++ b/indra/newview/lltoolbrush.h
@@ -49,27 +49,27 @@ class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingle
public:
// x,y in window coords, 0,0 = left,bot
- virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual void handleSelect();
- virtual void handleDeselect();
+ virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override;
+ virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override;
+ virtual BOOL handleHover( S32 x, S32 y, MASK mask ) override;
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
// isAlwaysRendered() - return true if this is a tool that should
// always be rendered regardless of selection.
- virtual BOOL isAlwaysRendered() { return TRUE; }
+ virtual BOOL isAlwaysRendered() override { return TRUE; }
// Draw the area that will be affected.
- virtual void render();
+ virtual void render() override;
// on Idle is where the land modification actually occurs
static void onIdle(void* brush_tool);
- void onMouseCaptureLost();
+ void onMouseCaptureLost() override;
void modifyLandInSelectionGlobal();
- virtual void undo();
- virtual BOOL canUndo() const { return TRUE; }
+ virtual void undo() override;
+ virtual BOOL canUndo() const override { return TRUE; }
protected:
void brush( void );
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index 86506f725e..f539a045b7 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -108,11 +108,11 @@ class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompI
public:
// Overridden from LLToolComposite
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleKey(KEY key, MASK mask);
- virtual void onMouseCaptureLost();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleKey(KEY key, MASK mask) override;
+ virtual void onMouseCaptureLost() override;
void keyUp(KEY key, MASK mask);
static void pickCallback(const LLPickInfo& pick_info);
@@ -133,13 +133,13 @@ class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCom
public:
// Overridden from LLToolComposite
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); // Returns to the default tool
- virtual void render();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; // Returns to the default tool
+ virtual void render() override;
- virtual LLTool* getOverrideTool(MASK mask);
+ virtual LLTool* getOverrideTool(MASK mask) override;
static void pickCallback(const LLPickInfo& pick_info);
};
@@ -154,13 +154,13 @@ class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompSca
public:
// Overridden from LLToolComposite
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); // Returns to the default tool
- virtual void render();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; // Returns to the default tool
+ virtual void render() override;
- virtual LLTool* getOverrideTool(MASK mask);
+ virtual LLTool* getOverrideTool(MASK mask) override;
static void pickCallback(const LLPickInfo& pick_info);
};
@@ -176,13 +176,13 @@ class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRo
public:
// Overridden from LLToolComposite
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual void render();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual void render() override;
- virtual LLTool* getOverrideTool(MASK mask);
+ virtual LLTool* getOverrideTool(MASK mask) override;
static void pickCallback(const LLPickInfo& pick_info);
@@ -199,9 +199,9 @@ class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCr
public:
// Overridden from LLToolComposite
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
static void pickCallback(const LLPickInfo& pick_info);
protected:
@@ -224,16 +224,16 @@ class LLToolCompGun : public LLToolComposite, public LLSingleton<LLToolCompGun>
public:
// Overridden from LLToolComposite
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- virtual void onMouseCaptureLost();
- virtual void handleSelect();
- virtual void handleDeselect();
- virtual LLTool* getOverrideTool(MASK mask) { return NULL; }
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override;
+ virtual void onMouseCaptureLost() override;
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
+ virtual LLTool* getOverrideTool(MASK mask) override { return NULL; }
protected:
LLToolGun* mGun;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 4537d73332..8ec027cb0e 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -48,12 +48,12 @@ public:
typedef boost::signals2::signal<void ()> enddrag_signal_t;
// overridden from LLTool
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleKey(KEY key, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
- virtual void onMouseCaptureLost();
- virtual void handleDeselect();
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleKey(KEY key, MASK mask) override;
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override;
+ virtual void onMouseCaptureLost() override;
+ virtual void handleDeselect() override;
void setDragStart( S32 x, S32 y ); // In screen space
BOOL isOverThreshold( S32 x, S32 y ); // In screen space
diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h
index e4b8ae12b8..7c8ff20480 100644
--- a/indra/newview/lltoolface.h
+++ b/indra/newview/lltoolface.h
@@ -39,11 +39,11 @@ class LLToolFace
virtual ~LLToolFace();
public:
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual void handleSelect();
- virtual void handleDeselect();
- virtual void render(); // draw face highlights
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
+ virtual void render() override; // draw face highlights
static void pickCallback(const LLPickInfo& pick_info);
};
diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h
index ef71f9230a..54d9827ae6 100644
--- a/indra/newview/lltoolfocus.h
+++ b/indra/newview/lltoolfocus.h
@@ -38,16 +38,16 @@ class LLToolCamera
virtual ~LLToolCamera();
public:
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
- virtual void onMouseCaptureLost();
+ virtual void onMouseCaptureLost() override;
- virtual void handleSelect();
- virtual void handleDeselect();
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
- virtual LLTool* getOverrideTool(MASK mask) { return NULL; }
+ virtual LLTool* getOverrideTool(MASK mask) override { return NULL; }
void setClickPickPending() { mClickPickPending = true; }
static void pickCallback(const LLPickInfo& pick_info);
diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h
index e7c2060fba..89dd9d9796 100644
--- a/indra/newview/lltoolindividual.h
+++ b/indra/newview/lltoolindividual.h
@@ -43,11 +43,9 @@ class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual>
virtual ~LLToolIndividual();
public:
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- virtual void handleSelect();
- //virtual void handleDeselect();
- //virtual void render();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ virtual void handleSelect() override;
static void pickCallback(const LLPickInfo& pick_info);
diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h
index 5ad9b67e21..a55cd223de 100644
--- a/indra/newview/lltoolobjpicker.h
+++ b/indra/newview/lltoolobjpicker.h
@@ -38,16 +38,16 @@ class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>
LLSINGLETON(LLToolObjPicker);
public:
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
- virtual void handleSelect();
- virtual void handleDeselect();
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
- virtual void onMouseCaptureLost();
+ virtual void onMouseCaptureLost() override;
- virtual void setExitCallback(void (*callback)(void *), void *callback_data);
+ void setExitCallback(void (*callback)(void *), void *callback_data);
LLUUID getObjectID() const { return mHitObjectID; }
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 8f6100e4b4..dca0d12cf6 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -42,26 +42,26 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
public:
// Virtual functions inherited from LLMouseHandler
- virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down) override;
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
BOOL handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
- virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override;
+ virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks) override;
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override;
- virtual void render();
+ virtual void render() override;
- virtual void stopEditing();
+ virtual void stopEditing() override;
- virtual void onMouseCaptureLost();
- virtual void handleSelect();
- virtual void handleDeselect();
- virtual LLTool* getOverrideTool(MASK mask);
+ virtual void onMouseCaptureLost() override;
+ virtual void handleSelect() override;
+ virtual void handleDeselect() override;
+ virtual LLTool* getOverrideTool(MASK mask) override;
LLPickInfo& getPick() { return mPick; }
U8 getClickAction() { return mClickAction; }
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 7575d8ad18..2636811c66 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -47,10 +47,10 @@ class LLToolPipette
virtual ~LLToolPipette();
public:
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) override;
// Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h
index b5ba72f16d..88bc4e2e3d 100644
--- a/indra/newview/lltoolselectland.h
+++ b/indra/newview/lltoolselectland.h
@@ -39,15 +39,15 @@ class LLToolSelectLand
virtual ~LLToolSelectLand();
public:
- /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ void render(); // draw the select rectangle
- /*virtual*/ BOOL isAlwaysRendered() { return TRUE; }
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ void render() override; // draw the select rectangle
+ /*virtual*/ BOOL isAlwaysRendered() override { return TRUE; }
- /*virtual*/ void handleSelect();
- /*virtual*/ void handleDeselect();
+ /*virtual*/ void handleSelect() override;
+ /*virtual*/ void handleDeselect() override;
protected:
BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y);
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
index 02ff0c094a..37382243f6 100644
--- a/indra/newview/llversioninfo.h
+++ b/indra/newview/llversioninfo.h
@@ -47,7 +47,7 @@ class LLStoreListener;
class LLVersionInfo: public LLSingleton<LLVersionInfo>
{
LLSINGLETON(LLVersionInfo);
- void initSingleton();
+ void initSingleton() override;
public:
~LLVersionInfo();
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index c0398372b4..1c1aa9ea47 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -158,6 +158,7 @@
#include "llfloaterimnearbychat.h"
#include "llpanelblockedlist.h"
#include "llpanelprofileclassifieds.h"
+#include "llpanelemojicomplete.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
@@ -336,6 +337,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);
LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
+ LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", &LLFloaterReg::build<LLFloaterEmojiComplete>);
LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h
index da50e07a43..bbd20bc07e 100644
--- a/indra/newview/llviewerhelp.h
+++ b/indra/newview/llviewerhelp.h
@@ -43,21 +43,21 @@ class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>
public:
/// display the specified help topic in the help viewer
- /*virtual*/ void showTopic(const std::string &topic);
+ /*virtual*/ void showTopic(const std::string &topic) override;
- std::string getURL(const std::string& topic);
+ std::string getURL(const std::string& topic) override;
// return topic derived from viewer UI focus, else default topic
std::string getTopicFromFocus();
/// return default (fallback) topic name suitable for showTopic()
- /*virtual*/ std::string defaultTopic();
+ /*virtual*/ std::string defaultTopic() override;
// return topic to use before the user logs in
- /*virtual*/ std::string preLoginTopic();
+ /*virtual*/ std::string preLoginTopic() override;
// return topic to use for the top-level help, invoked by F1
- /*virtual*/ std::string f1HelpTopic();
+ /*virtual*/ std::string f1HelpTopic() override;
};
#endif // header guard
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index f1f42afd81..ad7c4bcefa 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -74,7 +74,7 @@ class LLViewerMedia: public LLSingleton<LLViewerMedia>
{
LLSINGLETON(LLViewerMedia);
~LLViewerMedia();
- void initSingleton();
+ void initSingleton() override;
LOG_CLASS(LLViewerMedia);
public:
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index effd08a559..2310e4dbfc 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -54,10 +54,10 @@ public:
void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
void clearHover();
- /*virtual*/ bool getFocus();
- /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
- /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ bool getFocus();
+ /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override;
+ /*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) override;
+ /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) override;
BOOL handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
@@ -92,12 +92,12 @@ public:
LLUUID getControlsMediaID();
// The MoaP object wants keyup and keydown events. Overridden to return true.
- virtual bool wantsKeyUpKeyDown() const;
- virtual bool wantsReturnKey() const;
+ virtual bool wantsKeyUpKeyDown() const override;
+ virtual bool wantsReturnKey() const override;
protected:
- /*virtual*/ void onFocusReceived();
- /*virtual*/ void onFocusLost();
+ /*virtual*/ void onFocusReceived() override;
+ /*virtual*/ void onFocusLost() override;
private:
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a0223a5dbb..af3eaea9be 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -9566,6 +9566,10 @@ void initialize_menus()
//Develop (clear cache immediately)
commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
+ // Develop (Fonts debugging)
+ commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts));
+ commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures));
+
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index c1a9b6be80..84495bf78f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -6292,7 +6292,7 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
// More than OFFER_RECIPIENT_LIMIT targets will overload the message
// producing an llerror.
LLSD args;
- args["OFFERS"] = notification["payload"]["ids"].size();
+ args["OFFERS"] = LLSD::Integer(notification["payload"]["ids"].size());
args["LIMIT"] = static_cast<int>(OFFER_RECIPIENT_LIMIT);
LLNotificationsUtil::add("TooManyTeleportOffers", args);
return false;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index efc4ded79e..9666533db8 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -773,7 +773,6 @@ void LLViewerObjectList::dirtyAllObjectInventory()
void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
{
S32 i;
- S32 num_objects = 0;
LLViewerObject *objectp;
S32 num_updates, max_value;
@@ -830,8 +829,6 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
objectp = mObjects[i];
if (!objectp->isDead())
{
- num_objects++;
-
// Update distance & gpw
objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
objectp->updateTextures(); // Update the image levels of textures for this object.
diff --git a/indra/newview/llviewerparcelaskplay.h b/indra/newview/llviewerparcelaskplay.h
index dc711917d2..56faddae66 100644
--- a/indra/newview/llviewerparcelaskplay.h
+++ b/indra/newview/llviewerparcelaskplay.h
@@ -34,8 +34,8 @@ class LLViewerParcelAskPlay : public LLSingleton<LLViewerParcelAskPlay>
{
LLSINGLETON(LLViewerParcelAskPlay);
~LLViewerParcelAskPlay();
- void initSingleton();
- void cleanupSingleton();
+ void initSingleton() override;
+ void cleanupSingleton() override;
public:
// functor expects functor(region_id, parcel_id, url, play/stop)
typedef boost::function<void(const LLUUID&, const S32&, const std::string&, const bool&)> ask_callback;
diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h
index 779a65bdf8..790b2b71fc 100644
--- a/indra/newview/llviewerparcelmedia.h
+++ b/indra/newview/llviewerparcelmedia.h
@@ -74,7 +74,7 @@ public:
void sendMediaNavigateMessage(const std::string& url);
// inherited from LLViewerMediaObserver
- virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+ virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override;
private:
void processParcelMediaCommandMessage(LLMessageSystem *msg);
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index d71fd4c075..e83085dee0 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -35,7 +35,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer, public LLSingleton<LLViewerPar
{
LLSINGLETON(LLViewerParcelMediaAutoPlay);
public:
- virtual BOOL tick();
+ virtual BOOL tick() override;
static void playStarted();
private:
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 0018e78d45..f159682b67 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -242,9 +242,9 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm
LLSINGLETON_EMPTY_CTOR(LLUIImageList);
public:
// LLImageProviderInterface
- /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority);
- /*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority);
- void cleanUp();
+ /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) override;
+ /*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) override;
+ void cleanUp() override;
bool initFromFile();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ddc11ac0bd..a6a62ffacf 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1008,7 +1008,7 @@ public:
const Line& line = *iter;
LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
LLFontGL::LEFT, LLFontGL::TOP,
- LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, /*use_ellipses*/FALSE, /*use_color*/FALSE);
}
}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 309c3eebdd..e68bfbe1ff 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -170,12 +170,12 @@ class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoice
LLSINGLETON(LLVoiceChannelProximal);
public:
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ BOOL isActive();
- /*virtual*/ void activate();
- /*virtual*/ void deactivate();
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal) override;
+ /*virtual*/ void handleStatusChange(EStatusType status) override;
+ /*virtual*/ void handleError(EStatusType status) override;
+ /*virtual*/ BOOL isActive() override;
+ /*virtual*/ void activate() override;
+ /*virtual*/ void deactivate() override;
};
@@ -184,15 +184,15 @@ class LLVoiceChannelP2P : public LLVoiceChannelGroup
public:
LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ void activate();
- /*virtual*/ void getChannelInfo();
+ /*virtual*/ void handleStatusChange(EStatusType status) override;
+ /*virtual*/ void handleError(EStatusType status) override;
+ /*virtual*/ void activate() override;
+ /*virtual*/ void getChannelInfo() override;
void setSessionHandle(const std::string& handle, const std::string &inURI);
protected:
- virtual void setState(EState state);
+ virtual void setState(EState state) override;
private:
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 0a785401c1..3df5cd33ac 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -64,26 +64,26 @@ public:
/// @name LLVoiceModuleInterface virtual implementations
/// @see LLVoiceModuleInterface
//@{
- virtual void init(LLPumpIO *pump); // Call this once at application startup (creates connector)
- virtual void terminate(); // Call this to clean up during shutdown
+ virtual void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
+ virtual void terminate() override; // Call this to clean up during shutdown
- virtual const LLVoiceVersionInfo& getVersion();
+ virtual const LLVoiceVersionInfo& getVersion() override;
- virtual void updateSettings(); // call after loading settings and whenever they change
+ virtual void updateSettings() override; // call after loading settings and whenever they change
// Returns true if vivox has successfully logged in and is not in error state
- virtual bool isVoiceWorking() const;
+ virtual bool isVoiceWorking() const override;
/////////////////////
/// @name Tuning
//@{
- virtual void tuningStart();
- virtual void tuningStop();
- virtual bool inTuningMode();
+ virtual void tuningStart() override;
+ virtual void tuningStop() override;
+ virtual bool inTuningMode() override;
- virtual void tuningSetMicVolume(float volume);
- virtual void tuningSetSpeakerVolume(float volume);
- virtual float tuningGetEnergy(void);
+ virtual void tuningSetMicVolume(float volume) override;
+ virtual void tuningSetSpeakerVolume(float volume) override;
+ virtual float tuningGetEnergy(void) override;
//@}
/////////////////////
@@ -91,40 +91,40 @@ public:
//@{
// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
// i.e. when the daemon is running and connected, and the device lists are populated.
- virtual bool deviceSettingsAvailable();
- virtual bool deviceSettingsUpdated(); //return if the list has been updated and never fetched, only to be called from the voicepanel.
+ virtual bool deviceSettingsAvailable() override;
+ virtual bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
// Requery the vivox daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
- virtual void refreshDeviceLists(bool clearCurrentList = true);
+ virtual void refreshDeviceLists(bool clearCurrentList = true) override;
- virtual void setCaptureDevice(const std::string& name);
- virtual void setRenderDevice(const std::string& name);
+ virtual void setCaptureDevice(const std::string& name) override;
+ virtual void setRenderDevice(const std::string& name) override;
- virtual LLVoiceDeviceList& getCaptureDevices();
- virtual LLVoiceDeviceList& getRenderDevices();
+ virtual LLVoiceDeviceList& getCaptureDevices() override;
+ virtual LLVoiceDeviceList& getRenderDevices() override;
//@}
- virtual void getParticipantList(std::set<LLUUID> &participants);
- virtual bool isParticipant(const LLUUID& speaker_id);
+ virtual void getParticipantList(std::set<LLUUID> &participants) override;
+ virtual bool isParticipant(const LLUUID& speaker_id) override;
// Send a text message to the specified user, initiating the session if necessary.
// virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};
// close any existing text IM session with the specified user
- virtual void endUserIMSession(const LLUUID &uuid);
+ virtual void endUserIMSession(const LLUUID &uuid) override;
// Returns true if calling back the session URI after the session has closed is possible.
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
- virtual BOOL isSessionCallBackPossible(const LLUUID &session_id);
+ virtual BOOL isSessionCallBackPossible(const LLUUID &session_id) override;
// Returns true if the session can accepte text IM's.
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
- virtual BOOL isSessionTextIMPossible(const LLUUID &session_id);
+ virtual BOOL isSessionTextIMPossible(const LLUUID &session_id) override;
////////////////////////////
@@ -132,21 +132,21 @@ public:
//@{
// returns true iff the user is currently in a proximal (local spatial) channel.
// Note that gestures should only fire if this returns true.
- virtual bool inProximalChannel();
+ virtual bool inProximalChannel() override;
virtual void setNonSpatialChannel(const std::string &uri,
- const std::string &credentials);
+ const std::string &credentials) override;
virtual bool setSpatialChannel(const std::string &uri,
- const std::string &credentials);
+ const std::string &credentials) override;
- virtual void leaveNonSpatialChannel();
+ virtual void leaveNonSpatialChannel() override;
- virtual void leaveChannel(void);
+ virtual void leaveChannel(void) override;
// Returns the URI of the current channel, or an empty string if not currently in a channel.
// NOTE that it will return an empty string if it's in the process of joining a channel.
- virtual std::string getCurrentChannel();
+ virtual std::string getCurrentChannel() override;
//@}
@@ -154,59 +154,59 @@ public:
/// @name invitations
//@{
// start a voice channel with the specified user
- virtual void callUser(const LLUUID &uuid);
- virtual bool isValidChannel(std::string &channelHandle);
- virtual bool answerInvite(std::string &channelHandle);
- virtual void declineInvite(std::string &channelHandle);
+ virtual void callUser(const LLUUID &uuid) override;
+ virtual bool isValidChannel(std::string &channelHandle) override;
+ virtual bool answerInvite(std::string &channelHandle) override;
+ virtual void declineInvite(std::string &channelHandle) override;
//@}
/////////////////////////
/// @name Volume/gain
//@{
- virtual void setVoiceVolume(F32 volume);
- virtual void setMicGain(F32 volume);
+ virtual void setVoiceVolume(F32 volume) override;
+ virtual void setMicGain(F32 volume) override;
//@}
/////////////////////////
/// @name enable disable voice and features
//@{
- virtual bool voiceEnabled();
- virtual void setVoiceEnabled(bool enabled);
- virtual BOOL lipSyncEnabled();
- virtual void setLipSyncEnabled(BOOL enabled);
- virtual void setMuteMic(bool muted); // Set the mute state of the local mic.
+ virtual bool voiceEnabled() override;
+ virtual void setVoiceEnabled(bool enabled) override;
+ virtual BOOL lipSyncEnabled() override;
+ virtual void setLipSyncEnabled(BOOL enabled) override;
+ virtual void setMuteMic(bool muted) override; // Set the mute state of the local mic.
//@}
//////////////////////////
/// @name nearby speaker accessors
//@{
- virtual BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar
- virtual std::string getDisplayName(const LLUUID& id);
- virtual BOOL isParticipantAvatar(const LLUUID &id);
- virtual BOOL getIsSpeaking(const LLUUID& id);
- virtual BOOL getIsModeratorMuted(const LLUUID& id);
- virtual F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
- virtual BOOL getOnMuteList(const LLUUID& id);
- virtual F32 getUserVolume(const LLUUID& id);
- virtual void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
+ virtual BOOL getVoiceEnabled(const LLUUID& id) override; // true if we've received data for this avatar
+ virtual std::string getDisplayName(const LLUUID& id) override;
+ virtual BOOL isParticipantAvatar(const LLUUID &id) override;
+ virtual BOOL getIsSpeaking(const LLUUID& id) override;
+ virtual BOOL getIsModeratorMuted(const LLUUID& id) override;
+ virtual F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
+ virtual BOOL getOnMuteList(const LLUUID& id) override;
+ virtual F32 getUserVolume(const LLUUID& id) override;
+ virtual void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
//@}
// authorize the user
virtual void userAuthorized(const std::string& user_id,
- const LLUUID &agentID);
+ const LLUUID &agentID) override;
//////////////////////////////
/// @name Status notification
//@{
- virtual void addObserver(LLVoiceClientStatusObserver* observer);
- virtual void removeObserver(LLVoiceClientStatusObserver* observer);
- virtual void addObserver(LLFriendObserver* observer);
- virtual void removeObserver(LLFriendObserver* observer);
- virtual void addObserver(LLVoiceClientParticipantObserver* observer);
- virtual void removeObserver(LLVoiceClientParticipantObserver* observer);
+ virtual void addObserver(LLVoiceClientStatusObserver* observer) override;
+ virtual void removeObserver(LLVoiceClientStatusObserver* observer) override;
+ virtual void addObserver(LLFriendObserver* observer) override;
+ virtual void removeObserver(LLFriendObserver* observer) override;
+ virtual void addObserver(LLVoiceClientParticipantObserver* observer) override;
+ virtual void removeObserver(LLVoiceClientParticipantObserver* observer) override;
//@}
- virtual std::string sipURIFromID(const LLUUID &id);
+ virtual std::string sipURIFromID(const LLUUID &id) override;
//@}
/// @name LLVoiceEffectInterface virtual implementations
@@ -216,32 +216,32 @@ public:
//////////////////////////
/// @name Accessors
//@{
- virtual bool setVoiceEffect(const LLUUID& id);
- virtual const LLUUID getVoiceEffect();
- virtual LLSD getVoiceEffectProperties(const LLUUID& id);
+ virtual bool setVoiceEffect(const LLUUID& id) override;
+ virtual const LLUUID getVoiceEffect() override;
+ virtual LLSD getVoiceEffectProperties(const LLUUID& id) override;
- virtual void refreshVoiceEffectLists(bool clear_lists);
- virtual const voice_effect_list_t& getVoiceEffectList() const;
- virtual const voice_effect_list_t& getVoiceEffectTemplateList() const;
+ virtual void refreshVoiceEffectLists(bool clear_lists) override;
+ virtual const voice_effect_list_t& getVoiceEffectList() const override;
+ virtual const voice_effect_list_t& getVoiceEffectTemplateList() const override;
//@}
//////////////////////////////
/// @name Status notification
//@{
- virtual void addObserver(LLVoiceEffectObserver* observer);
- virtual void removeObserver(LLVoiceEffectObserver* observer);
+ virtual void addObserver(LLVoiceEffectObserver* observer) override;
+ virtual void removeObserver(LLVoiceEffectObserver* observer) override;
//@}
//////////////////////////////
/// @name Effect preview buffer
//@{
- virtual void enablePreviewBuffer(bool enable);
- virtual void recordPreviewBuffer();
- virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null);
- virtual void stopPreviewBuffer();
+ virtual void enablePreviewBuffer(bool enable) override;
+ virtual void recordPreviewBuffer() override;
+ virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override;
+ virtual void stopPreviewBuffer() override;
- virtual bool isPreviewRecording();
- virtual bool isPreviewPlaying();
+ virtual bool isPreviewRecording() override;
+ virtual bool isPreviewPlaying() override;
//@}
//@}
@@ -752,7 +752,7 @@ private:
std::string getAudioSessionURI();
std::string getAudioSessionHandle();
- void setHidden(bool hidden); //virtual
+ void setHidden(bool hidden) override; //virtual
void sendPositionAndVolumeUpdate(void);
void sendCaptureAndRenderDevices();
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index b0af565867..5cb7e7478b 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -408,7 +408,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
LLStrider<U16> &indicesp,
U32 &index_offset)
{
- S32 vertex_count = 0;
S32 i, x, y;
S32 num_vertices;
@@ -443,7 +442,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
// North patch
@@ -456,7 +454,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
@@ -493,7 +490,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
// Iterate through the north patch's points
@@ -507,7 +503,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
@@ -551,7 +546,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
// Iterate through the north patch's points
@@ -565,7 +559,6 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
normalsp++;
texCoords0p++;
texCoords1p++;
- vertex_count++;
}
for (i = 0; i < length; i++)
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 2e7ccc8334..d1f2ada4f1 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -6287,7 +6287,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
LLSpatialGroup::buffer_map_t buffer_map;
LLViewerTexture* last_tex = NULL;
- S32 buffer_index = 0;
S32 texture_index_channels = 1;
@@ -6301,11 +6300,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
}
- if (distance_sort)
- {
- buffer_index = -1;
- }
-
static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
texture_index_channels = llmin(texture_index_channels, (S32) max_texture_index);
@@ -6328,14 +6322,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
tex = NULL;
}
- if (last_tex == tex)
- {
- buffer_index++;
- }
- else
+ if (last_tex != tex)
{
last_tex = tex;
- buffer_index = 0;
}
bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic();
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index f7774a7086..0dbe50d5e4 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -428,7 +428,7 @@ public:
{
LLSINGLETON(ContextMenu);
public:
- /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
+ /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) override;
void show(LLView* spawning_view, LLWearableType::EType w_type, S32 x, S32 y);
@@ -441,7 +441,7 @@ public:
MASK_UNKNOWN = 0x10,
};
- /* virtual */ LLContextMenu* createMenu();
+ /* virtual */ LLContextMenu* createMenu() override;
void updateItemsVisibility(LLContextMenu* menu);
void updateItemsLabels(LLContextMenu* menu);
static void setMenuItemVisible(LLContextMenu* menu, const std::string& name, bool val);
@@ -472,7 +472,7 @@ public:
virtual ~LLWearableItemsList();
- /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item);
+ /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item) override;
void updateList(const LLUUID& category_id);
diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h
index 524adba652..31dbfb8ffd 100644
--- a/indra/newview/llwindebug.h
+++ b/indra/newview/llwindebug.h
@@ -40,9 +40,9 @@ class LLWinDebug:
{
LLSINGLETON_EMPTY_CTOR(LLWinDebug);
public:
- void initSingleton();
+ void initSingleton() override;
static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL);
- void cleanupSingleton();
+ void cleanupSingleton() override;
private:
static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename);
};
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 6e994b4e68..67632cdbf7 100755
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -551,7 +551,8 @@ void LLWorldMapView::draw()
S32_MAX, //max_chars
mMapScale, //max_pixels
NULL,
- TRUE); //use ellipses
+ /*use_ellipses*/TRUE,
+ /*use_color*/FALSE);
}
}
}
diff --git a/indra/newview/skins/default/xui/en/emoji_characters.xml b/indra/newview/skins/default/xui/en/emoji_characters.xml
new file mode 100644
index 0000000000..55aefe6745
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/emoji_characters.xml
@@ -0,0 +1,10955 @@
+<?xml version="1.0" ?>
+<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd">
+ <array>
+ <map>
+ <key>Character</key>
+ <string>😀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:grinning:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smile:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:laughing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rofl:</string>
+ <string>:satisfied:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:slightly_smiling_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:wink:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:innocent:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smiley:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:grin:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sweat_smile:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:joy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:upside_down_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blush:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Smiling</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smiling_face_with_three_hearts:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:star_struck:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kissing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kissing_closed_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smiling_face_with_tear:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heart_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kissing_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>☺️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:relaxed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kissing_smiling_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Affection</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:yum:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:stuck_out_tongue_winking_eye:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:stuck_out_tongue_closed_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:stuck_out_tongue:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zany_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:money_mouth_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Tongue</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hugs:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hand</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shushing_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hand</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hand_over_mouth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hand</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:thinking:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hand</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zipper_mouth_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:neutral_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:no_mouth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smirk:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:roll_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😮‍💨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:face_exhaling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raised_eyebrow:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:expressionless:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😶‍🌫️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:face_in_clouds:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:unamused:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:grimacing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lying_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Neutral Skeptical</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:relieved:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Sleepy</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sleepy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Sleepy</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sleeping:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Sleepy</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pensive:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Sleepy</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:drooling_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Sleepy</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mask:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:face_with_head_bandage:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:vomiting_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hot_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woozy_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😵‍💫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:face_with_spiral_eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:face_with_thermometer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:nauseated_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sneezing_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cold_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dizzy_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:exploding_head:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Unwell</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cowboy_hat_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hat</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:disguised_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hat</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:partying_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Hat</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sunglasses:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Glasses</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:monocle_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Glasses</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:nerd_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Glasses</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:confused:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:slightly_frowning_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:open_mouth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:astonished:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pleading_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:anguished:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cold_sweat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cry:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:scream:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:persevere:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sweat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tired_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:worried:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>☹️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frowning_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hushed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:flushed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frowning:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fearful:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:disappointed_relieved:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sob:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:confounded:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:disappointed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:weary:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:yawning_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Concerned</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:triumph:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:angry:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smiling_imp:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:skull:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pout:</string>
+ <string>:rage:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cursing_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👿</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:imp:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>☠️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:skull_and_crossbones:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Negative</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hankey:</string>
+ <string>:poop:</string>
+ <string>:shit:</string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:japanese_ogre:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ghost:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:space_invader:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:clown_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:japanese_goblin:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:alien:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:robot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Face Costume</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smiley_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:joy_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smirk_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:scream_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pouting_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:smile_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heart_eyes_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kissing_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>😿</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:crying_cat_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Cat Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:see_no_evil:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Monkey Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:speak_no_evil:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Monkey Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hear_no_evil:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Smiley</string>
+ <string>Monkey Face</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kiss:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cupid:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sparkling_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heartbeat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:two_hearts:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>❣️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heavy_heart_exclamation:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>❤️‍🔥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heart_on_fire:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>❤️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:yellow_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blue_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:brown_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:white_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:anger:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dizzy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dash:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bomb:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👁️‍🗨️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:eye_speech_bubble:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🗯️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:right_anger_bubble:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zzz:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:love_letter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:gift_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heartpulse:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:revolving_hearts:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:heart_decoration:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:broken_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>❤️‍🩹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mending_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:orange_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:green_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:purple_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🖤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:black_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:100:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:boom:</string>
+ <string>:collision:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sweat_drops:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕳️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hole:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:speech_balloon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🗨️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:left_speech_bubble:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:thought_balloon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Emotion</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:wave:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Open</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🖐️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raised_hand_with_fingers_splayed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Open</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🖖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:vulcan_salute:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Open</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raised_back_of_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Open</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>✋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hand:</string>
+ <string>:raised_hand:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Open</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ok_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pinching_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:crossed_fingers:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:metal:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pinched_fingers:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>✌️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:v:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:love_you_gesture:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:call_me_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Partial</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:point_left:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:point_up_2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:point_down:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:point_right:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🖕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fu:</string>
+ <string>:middle_finger:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>☝️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:point_up:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Single Finger</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:+1:</string>
+ <string>:thumbsup:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>✊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fist:</string>
+ <string>:fist_raised:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fist_left:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:-1:</string>
+ <string>:thumbsdown:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:facepunch:</string>
+ <string>:fist_oncoming:</string>
+ <string>:punch:</string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fist_right:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Fingers Closed</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:clap:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:open_hands:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:handshake:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raised_hands:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:palms_up_together:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pray:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hands</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>✍️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:writing_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Prop</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:selfie:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Prop</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:nail_care:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Hand Prop</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:muscle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦿</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mechanical_leg:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:foot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ear_with_hearing_aid:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:brain:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lungs:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bone:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👁️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:eye:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lips:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mechanical_arm:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:leg:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ear:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:nose:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:anatomical_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tooth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:eyes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tongue:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Body</string>
+ <string>Body Parts</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:baby:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:adult:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧔‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_beard:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:red_haired_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:white_haired_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_red_hair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_curly_hair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_white_hair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_bald:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👱‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blond_haired_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:older_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:child:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blond_haired_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bearded_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧔‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_beard:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:curly_haired_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bald_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:red_haired_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:curly_haired_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:white_haired_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bald_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👱‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blond_haired_woman:</string>
+ <string>:blonde_woman:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:older_adult:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:older_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frowning_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙍‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frowning_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙎‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pouting_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:no_good:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙅‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ng_woman:</string>
+ <string>:no_good_woman:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙆‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ok_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:information_desk_person:</string>
+ <string>:tipping_hand_person:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💁‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sassy_woman:</string>
+ <string>:tipping_hand_woman:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙋‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raising_hand_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:deaf_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧏‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:deaf_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙇‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bowing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:facepalm:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤦‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_facepalming:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤷‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_shrugging:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙍‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frowning_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pouting_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙎‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pouting_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙅‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ng_man:</string>
+ <string>:no_good_man:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ok_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙆‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ok_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💁‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sassy_man:</string>
+ <string>:tipping_hand_man:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raising_hand:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙋‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raising_hand_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧏‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:deaf_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bow:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🙇‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bowing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤦‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_facepalming:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shrug:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤷‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_shrugging:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Gesture</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍⚕️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:health_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍⚕️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_health_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🎓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_student:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🏫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:teacher:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🏫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_teacher:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍⚖️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_judge:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🌾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:farmer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🌾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_farmer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🍳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_cook:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🔧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mechanic:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🔧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_mechanic:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🏭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_factory_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍💼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:office_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍💼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_office_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🔬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_scientist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍💻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:technologist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍💻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_technologist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🎤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_singer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🎨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:artist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🎨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_artist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍✈️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_pilot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🚀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:astronaut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🚀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_astronaut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🚒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_firefighter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cop:</string>
+ <string>:police_officer:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👮‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:policewoman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕵️‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:male_detective:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:guard:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💂‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:guardswoman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:construction_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👷‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:construction_worker_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:princess:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👳‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_with_turban:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_with_gua_pi_mao:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_in_tuxedo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤵‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_in_tuxedo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👰‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_with_veil:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pregnant_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🍼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_feeding_baby:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🍼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_feeding_baby:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍⚕️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_health_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🎓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:student:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🎓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_student:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🏫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_teacher:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍⚖️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:judge:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍⚖️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_judge:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🌾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_farmer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🍳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cook:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🍳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_cook:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🔧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_mechanic:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🏭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:factory_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🏭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_factory_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍💼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_office_worker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🔬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:scientist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🔬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_scientist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍💻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_technologist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🎤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:singer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🎤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_singer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🎨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_artist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍✈️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pilot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍✈️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_pilot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🚀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_astronaut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🚒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:firefighter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🚒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_firefighter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👮‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:policeman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕵️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:detective:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕵️‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:female_detective:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💂‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:guardsman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ninja:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👷‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:construction_worker_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:prince:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_with_turban:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👳‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_with_turban:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_with_headscarf:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤵‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_in_tuxedo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_with_veil:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👰‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bride_with_veil:</string>
+ <string>:woman_with_veil:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:breast_feeding:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🍼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_feeding_baby:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Role</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:angel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mrs_claus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:superhero:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦸‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:superhero_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦹‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:supervillain_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mage:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧙‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mage_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧚‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fairy_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:vampire:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧛‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:vampire_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧜‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:merman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:elf:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧝‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:elf_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧞‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:genie_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zombie:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧟‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zombie_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🎅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:santa:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🎄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mx_claus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦸‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:superhero_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:supervillain:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦹‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:supervillain_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧙‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mage_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fairy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧚‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fairy_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧛‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:vampire_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:merperson:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧜‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mermaid:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧝‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:elf_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:genie:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧞‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:genie_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧟‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zombie_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Fantasy</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:massage:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💆‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:massage_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💇‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:haircut_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:walking:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚶‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:walking_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧍‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:standing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kneeling_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧎‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kneeling_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_with_probing_cane:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_in_motorized_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_in_motorized_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_in_manual_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:runner:</string>
+ <string>:running:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏃‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:running_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_dancing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dancers:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👯‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dancing_women:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧖‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sauna_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:climbing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧗‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:climbing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💆‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:massage_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:haircut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💇‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:haircut_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚶‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:walking_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:standing_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧍‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:standing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧎‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kneeling_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_with_probing_cane:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_with_probing_cane:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍🦼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_in_motorized_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🦽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_in_manual_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍🦽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_in_manual_wheelchair:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏃‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:running_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dancer:</string>
+ <string>:woman_dancing:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕴️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:business_suit_levitating:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👯‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dancing_men:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sauna_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧖‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sauna_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧗‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:climbing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Activity</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:person_fencing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>⛷️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:skier:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏌️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:golfing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏌️‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:golfing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏄‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:surfing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rowboat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚣‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rowing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏊‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:swimming_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>⛹️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bouncing_ball_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>⛹️‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:basketball_woman:</string>
+ <string>:bouncing_ball_woman:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏋️‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:weight_lifting_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bicyclist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚴‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:biking_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚵‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mountain_biking_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cartwheeling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤸‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_cartwheeling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤼‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:men_wrestling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:water_polo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤽‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_playing_water_polo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤾‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_playing_handball:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:juggling_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤹‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_juggling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:horse_racing:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:snowboarder:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏌️‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:golfing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:surfer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏄‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:surfing_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚣‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rowing_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:swimmer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏊‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:swimming_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>⛹️‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:basketball_man:</string>
+ <string>:bouncing_ball_man:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏋️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:weight_lifting:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏋️‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:weight_lifting_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚴‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:biking_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mountain_bicyclist:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🚵‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mountain_biking_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤸‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_cartwheeling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:wrestling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤼‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:women_wrestling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤽‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_playing_water_polo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:handball_person:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤾‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:woman_playing_handball:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🤹‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:man_juggling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Sport</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lotus_position:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Resting</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧘‍♀️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lotus_position_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Resting</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🛌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sleeping_bed:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Resting</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧘‍♂️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lotus_position_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Resting</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🛀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bath:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Resting</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧑‍🤝‍🧑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:people_holding_hands:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couple:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couplekiss:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍❤️‍💋‍👨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couplekiss_man_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couple_with_heart:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍❤️‍👨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couple_with_heart_man_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👩‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_woman_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👩‍👦‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_woman_boy_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👨‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_man_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👨‍👧‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_man_girl_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👨‍👧‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_man_girl_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👩‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_woman_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👩‍👦‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_woman_boy_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👧‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_girl_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👦‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_boy_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👧‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_girl_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:two_women_holding_hands:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:two_men_holding_hands:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍❤️‍💋‍👨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couplekiss_man_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍❤️‍💋‍👩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couplekiss_woman_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍❤️‍👨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couple_with_heart_woman_man:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍❤️‍👩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:couple_with_heart_woman_woman:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👩‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_woman_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👩‍👧‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_woman_girl_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👩‍👧‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_woman_girl_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👨‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_man_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👨‍👦‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_man_boy_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👩‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_woman_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👩‍👧‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_woman_girl_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👩‍👧‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_woman_girl_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👦‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_boy_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👨‍👧‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_man_girl_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_boy:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👩‍👧‍👧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:family_woman_girl_girl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person</string>
+ <string>Family</string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🗣️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:speaking_head:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Symbol</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:busts_in_silhouette:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Symbol</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:footprints:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Symbol</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>👤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bust_in_silhouette:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Symbol</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:people_hugging:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Person Symbol</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:monkey_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:gorilla:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:guide_dog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:poodle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fox_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐈‍⬛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:black_cat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tiger:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:leopard:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:racehorse:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:zebra:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bison:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ox:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cow2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pig2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pig_nose:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sheep:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dromedary_camel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:llama:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:elephant:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rhinoceros:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mouse:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rabbit:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐿️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:chipmunk:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hedgehog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bear:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:koala:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sloth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:skunk:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:badger:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:monkey:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:orangutan:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dog2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐕‍🦺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:service_dog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:wolf:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:raccoon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cat2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lion:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tiger2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:horse:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:unicorn:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:deer:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cow:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:water_buffalo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pig:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:boar:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ram:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:goat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:camel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:giraffe:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mammoth:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hippopotamus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mouse2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hamster:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rabbit2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:beaver:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐻‍❄️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:polar_bear:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:panda_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:otter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kangaroo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:feet:</string>
+ <string>:paw_prints:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Mammal</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:turkey:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rooster:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:baby_chick:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bird:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕊️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dove:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:duck:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:owl:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪶</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:feather:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:peacock:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:chicken:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hatching_chick:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hatched_chick:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐧</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:penguin:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:eagle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:swan:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dodo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:flamingo:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:parrot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bird</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:frog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Amphibian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:crocodile:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lizard:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dragon_face:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sauropod:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:turtle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:snake:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dragon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:t-rex:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Reptile</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:whale:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dolphin:</string>
+ <string>:flipper:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fish:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blowfish:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:octopus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:whale2:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:seal:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tropical_fish:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shark:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shell:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Marine</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:snail:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bug:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bee:</string>
+ <string>:honeybee:</string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lady_beetle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cockroach:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕸️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:spider_web:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mosquito:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:worm:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:butterfly:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🐜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ant:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:beetle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cricket:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🕷️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:spider:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:scorpion:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fly:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🦠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:microbe:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Animal Bug</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bouquet:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>💮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:white_flower:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌹</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rose:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌺</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hibiscus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌼</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blossom:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌸</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cherry_blossom:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🏵️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rosette:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:wilted_flower:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌻</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sunflower:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌷</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tulip:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Flower</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:seedling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:evergreen_tree:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:palm_tree:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌾</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ear_of_rice:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>☘️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shamrock:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍁</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:maple_leaf:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍃</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:leaves:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🪴</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:potted_plant:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:deciduous_tree:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌵</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cactus:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌿</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:herb:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:four_leaf_clover:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fallen_leaf:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Plant Other</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:grapes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍉</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:watermelon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍋</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:lemon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍍</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pineapple:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍎</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:apple:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pear:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cherries:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:blueberries:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tomato:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:coconut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:melon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍊</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mandarin:</string>
+ <string>:orange:</string>
+ <string>:tangerine:</string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍌</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:banana:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mango:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍏</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:green_apple:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:peach:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:strawberry:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:kiwi_fruit:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:olive:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Fruit</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:avocado:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:potato:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌽</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:corn:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫑</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bell_pepper:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥬</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:leafy_green:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:garlic:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍄</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:mushroom:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌰</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:chestnut:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:eggplant:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:carrot:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌶️</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hot_pepper:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥒</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cucumber:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥦</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:broccoli:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧅</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:onion:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:peanuts:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Vegetable</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bread:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:baguette_bread:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥨</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pretzel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥞</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pancakes:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧀</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cheese:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:poultry_leg:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bacon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fries:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌭</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hotdog:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:taco:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:tamale:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧆</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:falafel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍳</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fried_egg:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍲</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:stew:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bowl_with_spoon:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍿</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:popcorn:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧂</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:salt:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥐</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:croissant:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫓</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:flatbread:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bagel:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧇</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:waffle:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍖</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:meat_on_bone:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥩</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:cut_of_meat:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍔</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:hamburger:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:pizza:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥪</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sandwich:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🌯</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:burrito:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:stuffed_flatbread:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:egg:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:shallow_pan_of_food:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🫕</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fondue:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥗</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:green_salad:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🧈</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:butter:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥫</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:canned_food:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Prepared</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍱</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:bento:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍙</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rice_ball:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍛</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:curry:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍝</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:spaghetti:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍢</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:oden:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍤</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fried_shrimp:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥮</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:moon_cake:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥟</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dumpling:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:takeout_box:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍘</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rice_cracker:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍚</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:rice:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍜</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:ramen:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sweet_potato:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍣</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:sushi:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍥</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fish_cake:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🍡</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:dango:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ <map>
+ <key>Character</key>
+ <string>🥠</string>
+ <key>ShortCodes</key>
+ <array>
+ <string>:fortune_cookie:</string>
+ <string></string>
+ <string></string>
+ </array>
+ <key>Categories</key>
+ <array>
+ <string>Food Asian</string>
+ <string></string>
+ </array>
+ </map>
+ </array>
+</llsd>
diff --git a/indra/newview/skins/default/xui/en/floater_emoji_complete.xml b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml
new file mode 100644
index 0000000000..e9ea8f4de7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_close="false"
+ can_dock="false"
+ can_drag_on_left="false"
+ can_minimize="false"
+ can_resize="false"
+ can_tear_off="false"
+ header_height="0"
+ layout="topleft"
+ legacy_header_height="0"
+ height="40"
+ single_instance="true"
+ width="240"
+ >
+ <emoji_complete
+ autosize="true"
+ height="30"
+ follows="top|left"
+ layout="topleft"
+ left="5"
+ max_emoji="7"
+ name="emoji_complete_ctrl"
+ top="5"
+ width="230"
+ >
+ </emoji_complete>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index dcbdfa8794..ac5467c036 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -73,6 +73,8 @@
spellcheck="true"
tab_group="1"
top="46"
+ use_color="true"
+ show_emoji_helper="true"
width="392"
word_wrap="true">
Loading...
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index d88c267a95..40045625fd 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -3,6 +3,7 @@
<font name="default" comment="default font files (global fallbacks)">
<file>DejaVuSans.ttf</file>
+ <file functor="is_emoji">TwemojiSVG.ttf</file>
<os name="Windows">
<file>meiryo.TTC</file>
<file>MSGOTHIC.TTC</file>
@@ -69,6 +70,11 @@
<file>DejaVuSans-BoldOblique.ttf</file>
</font>
+ <font name="Emoji"
+ comment="Name of emoji font">
+ <file>TwemojiSVG.ttf</file>
+ </font>
+
<font name="Monospace"
comment="Name of monospace font">
<file>DejaVuSansMono.ttf</file>
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 96fac1c6e8..40399b33ef 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -161,6 +161,32 @@
<menu_item_separator />
<menu
create_jump_keys="true"
+ label="Fonts"
+ name="Fonts"
+ tear_off="true">
+ <menu_item_call
+ label="Show Font Test"
+ name="Show Font Test">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="font_test" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Dump Fonts"
+ name="Dump Fonts">
+ <menu_item_call.on_click
+ function="Develop.Fonts.Dump" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Font Textures"
+ name="Dump Font Textures">
+ <menu_item_call.on_click
+ function="Develop.Fonts.DumpTextures" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
label="UI Tests"
name="UI Tests"
tear_off="true">
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 58584345a9..66b70512a6 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3484,6 +3484,18 @@ function="World.EnvPreset"
parameter="https://cryptic-ridge-1632.herokuapp.com/"/>
</menu_item_call>
<menu_item_call
+ label="Dump Fonts"
+ name="Dump Fonts">
+ <menu_item_call.on_click
+ function="Develop.Fonts.Dump" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Font Textures"
+ name="Dump Font Textures">
+ <menu_item_call.on_click
+ function="Develop.Fonts.DumpTextures" />
+ </menu_item_call>
+ <menu_item_call
label="Dump SelectMgr"
name="Dump SelectMgr">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml
index f9facb593a..c550f634e5 100644
--- a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<chat_editor
name="chat_editor"
- show_context_menu="true"/>
+ show_context_menu="true"
+ show_emoji_helper="true"
+ use_color="true"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml
new file mode 100644
index 0000000000..370f1d174e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<emoji_complete
+ autosize="false"
+ font="EmojiHuge"
+ hover_image="ListItem_Over"
+ max_emoji="7"
+ padding="8"
+ selected_image="ListItem_Select"
+ >
+</emoji_complete>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 89481add29..de050d7c62 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -141,7 +141,7 @@ class ViewerManifest(LLManifest):
self.path("*.tga")
# Include our fonts
- with self.prefix(src_dst="fonts"):
+ with self.prefix(src="../packages/fonts",src_dst="fonts"):
self.path("*.ttf")
self.path("*.txt")
@@ -517,6 +517,10 @@ class WindowsManifest(ViewerManifest):
self.path("OpenAL32.dll")
self.path("alut.dll")
+ # For ICU4C
+ self.path("icudt48.dll")
+ self.path("icuuc48.dll")
+
# For textures
self.path("openjp2.dll")