diff options
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 <http://source.icu-project.org></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 Binary files differdeleted file mode 100644 index ec1a2ebaf2..0000000000 --- a/indra/newview/fonts/DejaVuSans-Bold.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf Binary files differdeleted file mode 100644 index 1a5576460d..0000000000 --- a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf Binary files differdeleted file mode 100644 index becc549927..0000000000 --- a/indra/newview/fonts/DejaVuSans-Oblique.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf Binary files differdeleted file mode 100644 index c1b19d8705..0000000000 --- a/indra/newview/fonts/DejaVuSans.ttf +++ /dev/null diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf Binary files differdeleted file mode 100644 index 6bc854ddae..0000000000 --- a/indra/newview/fonts/DejaVuSansMono.ttf +++ /dev/null diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi Binary files differindex 7922d9df52..0985663041 100755 --- a/indra/newview/installers/windows/lang_zh.nsi +++ b/indra/newview/installers/windows/lang_zh.nsi 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 ®io 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 ®io 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") |