From 4e2b2f662ad3f7b2e09f9451227bbf7018d91708 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 20 Oct 2019 23:45:52 +0200 Subject: Update freetype to 2.10.1 and move viewer fonts to their own package --- indra/cmake/ViewerMiscLibs.cmake | 1 + indra/newview/CMakeLists.txt | 6 ++ indra/newview/fonts/DejaVu-license.txt | 99 ------------------------- indra/newview/fonts/DejaVuSans-Bold.ttf | Bin 573136 -> 0 bytes indra/newview/fonts/DejaVuSans-BoldOblique.ttf | Bin 524056 -> 0 bytes indra/newview/fonts/DejaVuSans-Oblique.ttf | Bin 523804 -> 0 bytes indra/newview/fonts/DejaVuSans.ttf | Bin 622280 -> 0 bytes indra/newview/fonts/DejaVuSansMono.ttf | Bin 321524 -> 0 bytes indra/newview/viewer_manifest.py | 2 +- 9 files changed, 8 insertions(+), 100 deletions(-) delete mode 100644 indra/newview/fonts/DejaVu-license.txt delete mode 100644 indra/newview/fonts/DejaVuSans-Bold.ttf delete mode 100644 indra/newview/fonts/DejaVuSans-BoldOblique.ttf delete mode 100644 indra/newview/fonts/DejaVuSans-Oblique.ttf delete mode 100644 indra/newview/fonts/DejaVuSans.ttf delete mode 100644 indra/newview/fonts/DejaVuSansMono.ttf (limited to 'indra') diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index fc5bdedb5a..f213de100c 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -10,3 +10,4 @@ if (NOT USESYSTEMLIBS) use_prebuilt_binary(slvoice) endif(NOT USESYSTEMLIBS) +use_prebuilt_binary(fonts) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b8789da66b..b83d3afadd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1470,6 +1470,12 @@ if (WINDOWS) set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp) endif(USE_PRECOMPILED_HEADERS) + 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") + # Replace the icons with the appropriate ones for the channel # ('test' is the default) set(ICON_PATH "test") diff --git a/indra/newview/fonts/DejaVu-license.txt b/indra/newview/fonts/DejaVu-license.txt deleted file mode 100644 index 254e2cc42a..0000000000 --- a/indra/newview/fonts/DejaVu-license.txt +++ /dev/null @@ -1,99 +0,0 @@ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. -Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) - -Bitstream Vera Fonts Copyright ------------------------------- - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is -a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license ("Fonts") and associated -documentation files (the "Font Software"), to reproduce and distribute the -Font Software, including without limitation the rights to use, copy, merge, -publish, distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to the -following conditions: - -The above copyright and trademark notices and this permission notice shall -be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional glyphs or characters may be added to the Fonts, only if the fonts -are renamed to names not containing either the words "Bitstream" or the word -"Vera". - -This License becomes null and void to the extent applicable to Fonts or Font -Software that has been modified and is distributed under the "Bitstream -Vera" names. - -The Font Software may be sold as part of a larger software package but no -copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING -ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE -FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome -Foundation, and Bitstream Inc., shall not be used in advertising or -otherwise to promote the sale, use or other dealings in this Font Software -without prior written authorization from the Gnome Foundation or Bitstream -Inc., respectively. For further information, contact: fonts at gnome dot -org. - -Arev Fonts Copyright ------------------------------- - -Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the fonts accompanying this license ("Fonts") and -associated documentation files (the "Font Software"), to reproduce -and distribute the modifications to the Bitstream Vera Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to -the following conditions: - -The above copyright and trademark notices and this permission notice -shall be included in all copies of one or more of the Font Software -typefaces. - -The Font Software may be modified, altered, or added to, and in -particular the designs of glyphs or characters in the Fonts may be -modified and additional glyphs or characters may be added to the -Fonts, only if the fonts are renamed to names not containing either -the words "Tavmjong Bah" or the word "Arev". - -This License becomes null and void to the extent applicable to Fonts -or Font Software that has been modified and is distributed under the -"Tavmjong Bah Arev" names. - -The Font Software may be sold as part of a larger software package but -no copy of one or more of the Font Software typefaces may be sold by -itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL -TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the name of Tavmjong Bah shall not -be used in advertising or otherwise to promote the sale, use or other -dealings in this Font Software without prior written authorization -from Tavmjong Bah. For further information, contact: tavmjong @ free -. fr. - -$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/indra/newview/fonts/DejaVuSans-Bold.ttf b/indra/newview/fonts/DejaVuSans-Bold.ttf deleted file mode 100644 index ec1a2ebaf2..0000000000 Binary files a/indra/newview/fonts/DejaVuSans-Bold.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf deleted file mode 100644 index 1a5576460d..0000000000 Binary files a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf deleted file mode 100644 index becc549927..0000000000 Binary files a/indra/newview/fonts/DejaVuSans-Oblique.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf deleted file mode 100644 index c1b19d8705..0000000000 Binary files a/indra/newview/fonts/DejaVuSans.ttf and /dev/null differ diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf deleted file mode 100644 index 6bc854ddae..0000000000 Binary files a/indra/newview/fonts/DejaVuSansMono.ttf and /dev/null differ diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index fcb97ded8f..d5526bf5fd 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -137,7 +137,7 @@ class ViewerManifest(LLManifest): self.path("*.tga") # Include our fonts - with self.prefix(src_dst="fonts"): + with self.prefix(src="../packages/fonts"): self.path("*.ttf") self.path("*.txt") -- cgit v1.2.3 From 05566ce7a7e1895a5b3ab2f9df2587dac63429e1 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 27 Oct 2019 16:41:38 +0200 Subject: Font debugging aid to dump descriptors + individual textures --- indra/llrender/llfontbitmapcache.h | 1 + indra/llrender/llfontfreetype.cpp | 33 ++++++++++++++++++++++ indra/llrender/llfontfreetype.h | 1 + indra/llrender/llfontgl.cpp | 20 +++++++++++++ indra/llrender/llfontgl.h | 4 +++ indra/llrender/llfontregistry.cpp | 11 ++++++++ indra/llrender/llfontregistry.h | 1 + indra/newview/llviewermenu.cpp | 4 +++ indra/newview/skins/default/xui/en/menu_login.xml | 26 +++++++++++++++++ indra/newview/skins/default/xui/en/menu_viewer.xml | 12 ++++++++ 10 files changed, 113 insertions(+) (limited to 'indra') diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 75df3a94a7..7e0e905756 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -53,6 +53,7 @@ public: LLImageGL *getImageGL(U32 bitmapNum = 0) const; S32 getMaxCharWidth() const { return mMaxCharWidth; } + S32 getNumBitmaps() const { return mImageRawVec.size(); } S32 getNumComponents() const { return mNumComponents; } S32 getBitmapWidth() const { return mBitmapWidth; } S32 getBitmapHeight() const { return mBitmapHeight; } diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index c41730ebaa..78bc6ac433 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -40,8 +40,10 @@ #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" @@ -657,6 +659,37 @@ const std::string &LLFontFreetype::getName() const return mName; } +static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_name) +{ + LLPointer 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 + for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(); idx < cnt; idx++) + { + dumpFontBitmap(mFontBitmapCachep->getImageRaw(idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx)); + } + +// // Dump all the color bitmaps (if any) +// if (mFontColorBitmapCachep) +// { +// for (int idxBitmap = 0, cntBitmap = mFontColorBitmapCachep->getNumBitmaps(); idxBitmap < cntBitmap; idxBitmap++) +// { +// dumpFontBitmap(mFontColorBitmapCachep->getImageRaw(idxBitmap), llformat("%s_%d_%d_clr_%d.png", mFTFace->family_name, (int)mPointSize, mStyle, idxBitmap)); +// } +// } +} + const LLFontBitmapCache* LLFontFreetype::getFontBitmapCache() const { return mFontBitmapCachep; diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 1afe84e770..a25cc18fcf 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -143,6 +143,7 @@ public: const std::string& getName() const; + void dumpFontBitmaps() const; const LLFontBitmapCache* getFontBitmapCache() const; void setStyle(U8 style); diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 86a4c35e6d..990a3e8281 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -831,6 +831,26 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st } } +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 diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 10891faed9..b1a433f97d 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -163,6 +163,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(); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index dbe71e2882..5ab2ab046e 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -721,6 +721,17 @@ void LLFontRegistry::dump() } } +void LLFontRegistry::dumpTextures() +{ + for (const auto& fontEntry : mFontMap) + { + if (fontEntry.second) + { + fontEntry.second->dumpTextures(); + } + } +} + const string_vec_t& LLFontRegistry::getUltimateFallbackList() const { return mUltimateFallbackList; diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index e30c81c630..b1259ef4e7 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -94,6 +94,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/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 52b2c631fa..f99cbedcbe 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9121,6 +9121,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/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 07b3cc3bd8..93795be474 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -166,6 +166,32 @@ parameter="ui_preview" /> + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 9cfdb278de30e4a22d5d38fd08305fd40a905d80 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Mon, 28 Oct 2019 23:40:41 +0200 Subject: Support for COLR/CPAL fonts --- indra/llrender/llfontbitmapcache.cpp | 175 +++++++++++++++++++---------------- indra/llrender/llfontbitmapcache.h | 34 ++++--- indra/llrender/llfontfreetype.cpp | 148 ++++++++++++++++++----------- indra/llrender/llfontfreetype.h | 8 +- indra/llrender/llfontgl.cpp | 16 ++-- indra/llrender/llfontgl.h | 2 +- indra/llrender/llfontregistry.cpp | 2 +- 7 files changed, 222 insertions(+), 163 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index f128636ab2..754adb14cb 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -30,152 +30,165 @@ #include "llfontbitmapcache.h" LLFontBitmapCache::LLFontBitmapCache() -: LLTrace::MemTrackable("LLFontBitmapCache"), - mNumComponents(0), - mBitmapWidth(0), - mBitmapHeight(0), - mBitmapNum(-1), - mMaxCharWidth(0), - mMaxCharHeight(0), - mCurrentOffsetX(1), - mCurrentOffsetY(1) + : LLTrace::MemTrackable("LLFontBitmapCache") + , mBitmapWidth(0) + , mBitmapHeight(0) + , mMaxCharWidth(0) + , mMaxCharHeight(0) { + // *TODO: simplify with initializer after VS2017 + for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) + { + mCurrentOffsetX[idx] = 1; + mCurrentOffsetY[idx] = 1; + } } 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(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(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) { - if ((mBitmapNum<0) || (mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight) + return FALSE; + } + + const U32 bitmap_idx = static_cast(bitmap_type); + if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth) + { + 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); + S32 num_components = getNumComponents(bitmap_type); + mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components)); + bitmap_num = mImageRawVec[bitmap_idx].size() - 1; - // 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) + 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); - - claimMem(image_raw); - claimMem(image_gl); } 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 >::iterator it = mImageGLVec.begin(); - it != mImageGLVec.end(); ++it) + for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - (*it)->destroyGLTexture(); + for (std::vector >::iterator it = mImageGLVec[idx].begin(); it != mImageGLVec[idx].end(); ++it) + { + (*it)->destroyGLTexture(); + } } } void LLFontBitmapCache::reset() { - for (std::vector >::iterator it = mImageRawVec.begin(), end_it = mImageRawVec.end(); - it != end_it; - ++it) + for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - disclaimMem(**it); + for (std::vector >::iterator it = mImageRawVec[idx].begin(), end_it = mImageRawVec[idx].end(); it != end_it; ++it) + { + disclaimMem(**it); + } + mImageRawVec[idx].clear(); } - mImageRawVec.clear(); - for (std::vector >::iterator it = mImageGLVec.begin(), end_it = mImageGLVec.end(); - it != end_it; - ++it) + for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - disclaimMem(**it); + for (std::vector >::iterator it = mImageGLVec[idx].begin(), end_it = mImageGLVec[idx].end(); it != end_it; ++it) + { + disclaimMem(**it); + } + mImageGLVec[idx].clear(); + mCurrentOffsetX[idx] = 1; + mCurrentOffsetY[idx] = 1; } - mImageGLVec.clear(); 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 7e0e905756..f68af0d2b6 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -30,6 +30,13 @@ #include #include "lltrace.h" +enum class EFontGlyphType : U32 +{ + Grayscale = 0, + Color, + Count +}; + // Maintain a collection of bitmaps containing rendered glyphs. // Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL. class LLFontBitmapCache : public LLTrace::MemTrackable @@ -39,36 +46,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 getNumBitmaps() const { return mImageRawVec.size(); } - S32 getNumComponents() const { return mNumComponents; } + U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? mImageRawVec[static_cast(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 mCurrentOffsetX[static_cast(EFontGlyphType::Count)]; + S32 mCurrentOffsetY[static_cast(EFontGlyphType::Count)]; S32 mMaxCharWidth; S32 mMaxCharHeight; - S32 mCurrentOffsetX; - S32 mCurrentOffsetY; - std::vector > mImageRawVec; - std::vector > mImageGLVec; + std::vector> mImageRawVec[static_cast(EFontGlyphType::Count)]; + std::vector> mImageGLVec[static_cast(EFontGlyphType::Count)]; }; #endif //LL_LLFONTBITMAPCACHE_H diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 78bc6ac433..57154feeec 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -101,6 +101,7 @@ 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 + mBitmapType(EFontGlyphType::Grayscale), mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph { } @@ -159,7 +160,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 use_color, bool is_fallback, S32 face_n) { // Don't leak face objects. This is also needed to deal with // changed font file names. @@ -223,7 +224,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); claimMem(mFontBitmapCachep); @@ -236,7 +237,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; @@ -447,7 +448,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(*iter, wch, glyph_index); + return addGlyphFromFont(*iter, wch, glyph_index, EFontGlyphType::Color); } } } @@ -455,29 +456,43 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); if (iter == mCharGlyphInfoMap.end()) { - return addGlyphFromFont(this, wch, glyph_index); + return addGlyphFromFont(this, wch, glyph_index, EFontGlyphType::Color); } 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 bitmap_type) const { if (mFTFace == NULL) return NULL; llassert(!mIsFallback); - fontp->renderGlyph(glyph_index); + fontp->renderGlyph(bitmap_type, glyph_index); + switch (fontp->mFTFace->glyph->bitmap.pixel_mode) + { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: + bitmap_type = EFontGlyphType::Grayscale; + break; + case FT_PIXEL_MODE_BGRA: + bitmap_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_type, bitmap_num); mAddGlyphCount++; LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); gi->mXBitmapOffset = pos_x; gi->mYBitmapOffset = pos_y; + gi->mBitmapType = bitmap_type; gi->mBitmapNum = bitmap_num; gi->mWidth = width; gi->mHeight = height; @@ -489,9 +504,6 @@ 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 (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { @@ -525,39 +537,32 @@ 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_type, bitmap_num); + LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_type, bitmap_num); image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); return gi; @@ -592,12 +597,19 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const } } -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) ); @@ -607,7 +619,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, true, mIsFallback, 0); if (!mIsFallback) { // This is the head of the list - need to rebuild ourself and all fallbacks. @@ -645,7 +657,7 @@ void LLFontFreetype::resetBitmapCache() if(!mIsFallback) { // Add the empty glyph - addGlyphFromFont(this, 0, 0); + addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale); } } @@ -674,20 +686,17 @@ static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_ void LLFontFreetype::dumpFontBitmaps() const { - // Dump all the regular bitmaps - for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(); idx < cnt; idx++) + // Dump all the regular bitmaps (if any) + for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++) { - dumpFontBitmap(mFontBitmapCachep->getImageRaw(idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, 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) -// if (mFontColorBitmapCachep) -// { -// for (int idxBitmap = 0, cntBitmap = mFontColorBitmapCachep->getNumBitmaps(); idxBitmap < cntBitmap; idxBitmap++) -// { -// dumpFontBitmap(mFontColorBitmapCachep->getImageRaw(idxBitmap), llformat("%s_%d_%d_clr_%d.png", mFTFace->family_name, (int)mPointSize, mStyle, idxBitmap)); -// } -// } + // 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 @@ -705,9 +714,38 @@ 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)); diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index a25cc18fcf..7b7b3faaf0 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -71,6 +71,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 + EFontGlyphType mBitmapType; // Specifies the bitmap type in the bitmap cache S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph }; @@ -84,7 +85,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 use_color, bool is_fallback, S32 face_n); S32 getNumFaces(const std::string& filename); @@ -152,10 +153,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* 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; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 990a3e8281..6fee34d3eb 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 use_color, bool is_fallback, S32 face_n) { if(mFontFreetype == reinterpret_cast(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, use_color, is_fallback, face_n); } S32 LLFontGL::getNumFaces(const std::string& filename) @@ -280,7 +280,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 bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; for (i = begin_offset; i < begin_offset + length; i++) { @@ -298,8 +298,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 next_bitmap_entry = std::make_pair(fgi->mBitmapType, fgi->mBitmapNum); + 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. @@ -313,8 +313,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(fgi->mBitmapType, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); } @@ -347,7 +347,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, (fgi->mBitmapType == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index b1a433f97d..5028ccc770 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 use_color, bool is_fallback, S32 face_n); S32 getNumFaces(const std::string& filename); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 5ab2ab046e..426b10b016 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -495,7 +495,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) fontp = new LLFontGL; } if (fontp->loadFace(*font_paths_it, point_size_scale, - LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback, i)) + LLFontGL::sVertDPI, LLFontGL::sHorizDPI, true, is_fallback, i)) { is_font_loaded = true; if (is_first_found) -- cgit v1.2.3 From 418308bc7ce4e9924d6280f784222ba45172eea4 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 6 Nov 2019 12:34:26 +0100 Subject: Characters can have more than one representation in LLFontFreetype * By default all viewer text will use B/W glyphs * Added temporary use_color attribute to LLTextBase for testing --- indra/llrender/llfontbitmapcache.h | 3 +- indra/llrender/llfontfreetype.cpp | 90 ++++++++++++++++++++++++----------- indra/llrender/llfontfreetype.h | 14 +++--- indra/llrender/llfontgl.cpp | 45 +++++++++--------- indra/llrender/llfontgl.h | 11 +++-- indra/llui/llfolderviewitem.cpp | 6 +-- indra/llui/lltextbase.cpp | 11 +++-- indra/llui/lltextbase.h | 3 ++ indra/llui/llview.cpp | 2 +- indra/newview/llexpandabletextbox.cpp | 2 +- indra/newview/llfloateruipreview.cpp | 8 ++-- indra/newview/lltextureview.cpp | 2 +- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/llworldmapview.cpp | 3 +- 14 files changed, 126 insertions(+), 76 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index f68af0d2b6..5d0094fd69 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -34,7 +34,8 @@ enum class EFontGlyphType : U32 { Grayscale = 0, Color, - Count + Count, + Unspecified, }; // Maintain a collection of bitmaps containing rendered glyphs. diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 57154feeec..7d66965e57 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -91,8 +91,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 @@ -101,11 +102,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 - mBitmapType(EFontGlyphType::Grayscale), - 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() : LLTrace::MemTrackable("LLFontFreetype"), mFontBitmapCachep(new LLFontBitmapCache), @@ -361,7 +376,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; @@ -393,10 +408,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; @@ -427,12 +442,13 @@ 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; @@ -448,34 +464,38 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(*iter, wch, glyph_index, EFontGlyphType::Color); + return addGlyphFromFont(*iter, wch, glyph_index, glyph_type); } } } - char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); - if (iter == mCharGlyphInfoMap.end()) + std::pair 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, EFontGlyphType::Color); + return addGlyphFromFont(this, wch, glyph_index, glyph_type); } return NULL; } -LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const +LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const { if (mFTFace == NULL) return NULL; llassert(!mIsFallback); - fontp->renderGlyph(bitmap_type, 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_type = EFontGlyphType::Grayscale; + bitmap_glyph_type = EFontGlyphType::Grayscale; break; case FT_PIXEL_MODE_BGRA: - bitmap_type = EFontGlyphType::Color; + bitmap_glyph_type = EFontGlyphType::Color; break; default: llassert_always(true); @@ -486,14 +506,13 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l S32 pos_x, pos_y; U32 bitmap_num; - mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_type, 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->mBitmapType = bitmap_type; - 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; @@ -504,6 +523,13 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l insertGlyphInfo(wch, gi); + 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) { @@ -561,31 +587,39 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l llassert(false); } - LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_type, bitmap_num); - LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_type, 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 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 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; @@ -593,7 +627,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const else { claimMem(gi); - mCharGlyphInfoMap[wch] = gi; + mCharGlyphInfoMap.insert(std::make_pair(wch, gi)); } } diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 7b7b3faaf0..8c2d2bc491 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,8 +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 - EFontGlyphType mBitmapType; // Specifies the bitmap type in the bitmap cache - S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph + std::pair mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph }; extern LLFontManager *gFontManagerp; @@ -136,7 +137,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); @@ -155,7 +156,7 @@ private: 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* 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; @@ -179,7 +180,8 @@ private: BOOL mIsFallback; font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) - typedef boost::unordered_map 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 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/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 6fee34d3eb..78017ecb3d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -112,14 +112,14 @@ S32 LLFontGL::getNumFaces(const std::string& filename) static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts"); 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; @@ -140,12 +140,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_RECORD_BLOCK_TIME(FTM_RENDER_FONTS); @@ -290,7 +290,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) { @@ -298,7 +298,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons break; } // Per-glyph bitmap texture. - std::pair next_bitmap_entry = std::make_pair(fgi->mBitmapType, fgi->mBitmapNum); + std::pair next_bitmap_entry = fgi->mBitmapEntry; if (next_bitmap_entry != bitmap_entry) { // Actually draw the queued glyphs before switching their texture; @@ -314,7 +314,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons } bitmap_entry = next_bitmap_entry; - LLImageGL* font_image = font_bitmap_cache->getImageGL(fgi->mBitmapType, bitmap_entry.second); + LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); } @@ -347,7 +347,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, (fgi->mBitmapType == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, 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; @@ -357,7 +357,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); } @@ -411,7 +411,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(); } @@ -425,19 +426,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 @@ -514,7 +515,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); @@ -534,7 +535,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. @@ -616,7 +617,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) { @@ -641,7 +642,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); } @@ -688,7 +689,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 @@ -763,7 +764,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); @@ -793,7 +794,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); } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 5028ccc770..68bf5db668 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -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; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0510e472c5..0c1c3c40ec 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -826,7 +826,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() @@ -905,7 +905,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 ); } //--------------------------------------------------------------------------------// @@ -917,7 +917,7 @@ void LLFolderViewItem::draw() F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), 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/lltextbase.cpp b/indra/llui/lltextbase.cpp index a23741b6dd..64b3a0ddcc 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -163,6 +163,7 @@ LLTextBase::Params::Params() wrap("wrap"), trusted_content("trusted_content", true), 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) @@ -217,6 +218,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), @@ -3198,7 +3200,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele mStyle->getShadowType(), length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } rect.mLeft = right_x; @@ -3217,7 +3220,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele LLFontGL::NO_SHADOW, length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } rect.mLeft = right_x; if( selection_end < seg_end ) @@ -3234,7 +3238,8 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele mStyle->getShadowType(), length, &right_x, - mEditor.getUseEllipses()); + mEditor.getUseEllipses(), + mEditor.getUseColor()); } return right_x; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 9831c35858..6f1e178e36 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -314,6 +314,7 @@ public: plain_text, wrap, use_ellipses, + use_color, parse_urls, force_urls_external, parse_highlights, @@ -389,6 +390,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;} @@ -681,6 +683,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/llview.cpp b/indra/llui/llview.cpp index 89ad8138d8..40537e6c4a 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1282,7 +1282,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(); diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index d657f04457..a03b84daa5 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/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index db5a192287..211371571d 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/lltextureview.cpp b/indra/newview/lltextureview.cpp index 0d2edc0268..9ec6b99416 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -612,7 +612,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")); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c3cf07e9c7..e4d445b95c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -867,7 +867,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); } mLineList.clear(); } diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 86249badaa..ff1f95526e 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -469,7 +469,8 @@ void LLWorldMapView::draw() S32_MAX, //max_chars sMapScale, //max_pixels NULL, - TRUE); //use ellipses + /*use_ellipses*/TRUE, + /*use_color*/FALSE); } } } -- cgit v1.2.3 From 5a6ddb2ea666e895890d3cb690cce5101cf12652 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 17:15:21 +0100 Subject: Fallback fonts can have first crack at adding an unknown character + set Twemoji as the viewer's fallback for all emoji blocks --- indra/cmake/CMakeLists.txt | 2 + indra/cmake/FindICU4C.cmake | 33 ++++++ indra/cmake/ICU4C.cmake | 22 ++++ indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/llstring.cpp | 26 +++++ indra/llcommon/llstring.h | 2 + indra/llrender/llfontfreetype.cpp | 42 +++++--- indra/llrender/llfontfreetype.h | 12 +-- indra/llrender/llfontgl.cpp | 4 +- indra/llrender/llfontgl.h | 2 +- indra/llrender/llfontregistry.cpp | 150 +++++++++++++++------------ indra/llrender/llfontregistry.h | 42 ++++++-- indra/newview/CMakeLists.txt | 2 + indra/newview/skins/default/xui/en/fonts.xml | 1 + indra/win_crash_logger/CMakeLists.txt | 2 + 15 files changed, 243 insertions(+), 101 deletions(-) create mode 100644 indra/cmake/FindICU4C.cmake create mode 100644 indra/cmake/ICU4C.cmake (limited to 'indra') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 84e1c5d6fd..d64c38b1b3 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -32,6 +32,7 @@ set(cmake_SOURCE_FILES FindGLH.cmake FindGoogleBreakpad.cmake FindHUNSPELL.cmake + FindICU4C.cmake FindJsonCpp.cmake FindNDOF.cmake FindOpenJPEG.cmake @@ -49,6 +50,7 @@ set(cmake_SOURCE_FILES GoogleMock.cmake Havok.cmake Hunspell.cmake + ICU4C.cmake JPEG.cmake JsonCpp.cmake LLAddBuildTest.cmake 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..007a9b6937 --- /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 ...) + #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/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af41b9e460..ba87d93fec 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -4,6 +4,7 @@ project(llcommon) include(00-Common) +include(ICU4C) include(LLCommon) include(Linking) include(Boost) @@ -288,6 +289,7 @@ target_link_libraries( ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} + ${ICU4C_LIBRARY} ${JSONCPP_LIBRARIES} ${ZLIB_LIBRARIES} ${WINDOWS_LIBRARIES} diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 0174c411b4..b272728200 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 #include #if LL_WINDOWS @@ -888,6 +889,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 b619a9e48c..d31d0cafc7 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -193,6 +193,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); diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 7d66965e57..25740a5f87 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -175,7 +175,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, bool use_color, 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. @@ -345,14 +345,11 @@ void LLFontFreetype::clearFontStreams() } #endif -void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +void LLFontFreetype::addFallbackFont(const LLPointer& fallback_font, const char_functor_t& functor) { - mFallbackFonts = font; -} - -const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const -{ - 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 @@ -453,18 +450,31 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type 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, glyph_type); + return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type); } } } @@ -653,7 +663,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) co void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) { resetBitmapCache(); - loadFace(mName, mPointSize, vert_dpi ,horz_dpi, true, mIsFallback, 0); + 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. @@ -663,11 +673,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); } } } diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 8c2d2bc491..8afc5e3ed5 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -86,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, bool use_color, bool is_fallback, S32 face_n); + 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); @@ -95,10 +95,8 @@ public: void clearFontStreams(); #endif - typedef std::vector > font_vector_t; - - void setFallbackFonts(const font_vector_t &font); - const font_vector_t &getFallbackFonts() const; + typedef std::function char_functor_t; + void addFallbackFont(const LLPointer& fallback_font, const char_functor_t& functor = nullptr); // Global font metrics - in units of pixels F32 getLineHeight() const; @@ -178,7 +176,9 @@ private: #endif BOOL mIsFallback; - font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + typedef std::pair, char_functor_t> fallback_font_t; + typedef std::vector fallback_font_vector_t; + fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) // *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique) typedef boost::unordered_multimap char_glyph_info_map_t; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 78017ecb3d..4770f79395 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, const F32 vert_dpi, const F32 horz_dpi, bool use_color, 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(NULL)) { mFontFreetype = new LLFontFreetype; } - return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, use_color, 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) diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 68bf5db668..a60feb87cb 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, bool use_color, bool is_fallback, S32 face_n); + 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); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 426b10b016..ac2b695a3e 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -46,6 +46,10 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node); const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/"; +LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({ + { "is_emoji", LLStringOps::isEmoji } +}); + LLFontDescriptor::LLFontDescriptor(): mStyle(0) { @@ -54,22 +58,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, @@ -81,7 +85,6 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name, { } - bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const { if (mName < b.mName) @@ -174,7 +177,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) @@ -272,17 +287,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")) { @@ -325,19 +347,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; } @@ -422,80 +444,78 @@ 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); +#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); -#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, true, 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) @@ -505,7 +525,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; } @@ -520,17 +541,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; @@ -712,11 +728,11 @@ 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 <FileName << LL_ENDL; } } } diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index b1259ef4e7..b0ef72c5de 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -34,13 +34,32 @@ class LLFontGL; typedef std::vector string_vec_t; +struct LLFontFileInfo +{ + LLFontFileInfo(const std::string& file_name, const std::function& char_functor = nullptr) + : FileName(file_name) + , CharFunctor(char_functor) + { + } + + LLFontFileInfo(const LLFontFileInfo& ffi) + : FileName(ffi.FileName) + , CharFunctor(ffi.CharFunctor) + { + } + + std::string FileName; + std::function CharFunctor; +}; +typedef std::vector 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& getFileNames() const { return mFileNames; } - std::vector& getFileNames() { return mFileNames; } - const std::vector& getFontCollectionsList() const { return mFontCollectionsList; } - std::vector& 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> char_functor_map_t; + static char_functor_map_t mCharFunctors; }; class LLFontRegistry diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b83d3afadd..f03dcb4066 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -21,6 +21,7 @@ include(EXPAT) include(FMODEX) include(GLOD) include(Hunspell) +include(ICU4C) include(JsonCpp) include(LLAppearance) include(LLAudio) @@ -2003,6 +2004,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${NDOF_LIBRARY} ${NVAPI_LIBRARY} ${HUNSPELL_LIBRARY} + ${ICU4C_LIBRARY} ${viewer_LIBRARIES} ${BOOST_PROGRAM_OPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 2d5263b78f..6df666a700 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -3,6 +3,7 @@ DejaVuSans.ttf + Twemoji.ttf meiryo.TTC MSGOTHIC.TTC diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt index 4fba26ab2f..d1de20a6a0 100644 --- a/indra/win_crash_logger/CMakeLists.txt +++ b/indra/win_crash_logger/CMakeLists.txt @@ -3,6 +3,7 @@ project(win_crash_logger) include(00-Common) +include(ICU4C) include(LLCommon) include(LLCoreHttp) include(LLCrashLogger) @@ -74,6 +75,7 @@ add_executable(windows-crash-logger WIN32 ${win_crash_logger_SOURCE_FILES}) target_link_libraries(windows-crash-logger ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} + ${ICU4C_LIBRARY} ${LLCRASHLOGGER_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLVFS_LIBRARIES} -- cgit v1.2.3 From b44ade68e6eea656dc0e31738f9603caffe4d659 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 20:33:53 +0100 Subject: FIXED Calling LLTextBase::insertStringNoUndo() with more than one segment results in overlapping segment ranges Text is only inserted into the view model *after* the segments are added so if seg1_pos_start is the current EOF: -> 1st segment: getSegIterContaining(seg1_pos_start) returns the last segment and insertSegment() ends up properly adjusting its start/end position -> 2nd segment: getSegIterContaining(seg2_pos_start) returns mSegments.end() since its position is beyond the available and insertSegment() leaves the last 2 segments with overlapping ranges After the fix: -> if index runs past the end of all segments then mSegments.end() is returned (no change) -> if index is a position past the length of text but claimed by a segment then that segment is returned (change) -> if index specifies a position in the middle of the document unclaimed by any segment then the first segment after that position is returned (no change) (this does break the assertion that segment->mStart <= index <= segment->mEnd?) --- indra/llui/lltextbase.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 64b3a0ddcc..ecceb289f0 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1889,8 +1889,6 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) 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(); } @@ -1914,8 +1912,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i 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(); } -- cgit v1.2.3 From d58b530e805e2b3c943b1ff446ac84a10c500b32 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Thu, 7 Nov 2019 20:48:20 +0100 Subject: Add text_valign to LLTextBase to specify the vertical alignment within a single document line The existing font_valign property is used as to position the entire document so it's impossible to top align a text editor with each line's text centered within that line's extents --- indra/llui/lltextbase.cpp | 10 ++++++---- indra/llui/lltextbase.h | 7 +++++-- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index ecceb289f0..cc44f46706 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -160,6 +160,7 @@ 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), use_ellipses("use_ellipses", false), @@ -205,6 +206,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 : p.font_valign), mLineSpacingMult(p.line_spacing.multiple), mLineSpacingPixels(p.line_spacing.pixels), mClip(p.clip), @@ -515,7 +517,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); @@ -3191,7 +3193,7 @@ 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, @@ -3211,7 +3213,7 @@ 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, @@ -3229,7 +3231,7 @@ 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, diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 6f1e178e36..99c243a346 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -333,6 +333,8 @@ public: Optional font_shadow; + Optional text_valign; + Params(); }; @@ -673,8 +675,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; -- cgit v1.2.3 From bab70f6f152952ce755188d29bea1cfd8821a4be Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Mon, 29 Aug 2022 00:00:31 +0200 Subject: Review + resolve minor issues --- indra/llrender/llfontbitmapcache.cpp | 29 +++++++++++------------------ indra/llrender/llfontbitmapcache.h | 12 ++++++------ indra/llrender/llfontregistry.cpp | 4 ++-- indra/llui/lltextbase.cpp | 2 +- indra/newview/viewer_manifest.py | 2 +- 5 files changed, 21 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index 754adb14cb..2d65ec47c6 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -31,17 +31,7 @@ LLFontBitmapCache::LLFontBitmapCache() : LLTrace::MemTrackable("LLFontBitmapCache") - , mBitmapWidth(0) - , mBitmapHeight(0) - , mMaxCharWidth(0) - , mMaxCharHeight(0) { - // *TODO: simplify with initializer after VS2017 - for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) - { - mCurrentOffsetX[idx] = 1; - mCurrentOffsetY[idx] = 1; - } } LLFontBitmapCache::~LLFontBitmapCache() @@ -123,6 +113,9 @@ BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp // Attach corresponding GL texture. (*TODO: is this needed?) gGL.getTexUnit(0)->bind(image_gl); image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE); + + claimMem(image_raw); + claimMem(image_gl); } else { @@ -145,29 +138,29 @@ void LLFontBitmapCache::destroyGL() { for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - for (std::vector >::iterator it = mImageGLVec[idx].begin(); it != mImageGLVec[idx].end(); ++it) + for (LLImageGL* image_gl : mImageGLVec[idx]) { - (*it)->destroyGLTexture(); + image_gl->destroyGLTexture(); } } } void LLFontBitmapCache::reset() { - for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) + for (U32 kitty = 0, cnt = static_cast(EFontGlyphType::Count); kitty < cnt; kitty++) { - for (std::vector >::iterator it = mImageRawVec[idx].begin(), end_it = mImageRawVec[idx].end(); it != end_it; ++it) + for (LLImageRaw* image_raw : mImageRawVec[kitty]) { - disclaimMem(**it); + disclaimMem(image_raw); } - mImageRawVec[idx].clear(); + mImageRawVec[kitty].clear(); } for (U32 idx = 0, cnt = static_cast(EFontGlyphType::Count); idx < cnt; idx++) { - for (std::vector >::iterator it = mImageGLVec[idx].begin(), end_it = mImageGLVec[idx].end(); it != end_it; ++it) + for (LLImageGL* image_gl : mImageGLVec[idx]) { - disclaimMem(**it); + disclaimMem(image_gl); } mImageGLVec[idx].clear(); mCurrentOffsetX[idx] = 1; diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 5d0094fd69..6b339e9afd 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -68,12 +68,12 @@ protected: static U32 getNumComponents(EFontGlyphType bitmap_type); private: - S32 mBitmapWidth; - S32 mBitmapHeight; - S32 mCurrentOffsetX[static_cast(EFontGlyphType::Count)]; - S32 mCurrentOffsetY[static_cast(EFontGlyphType::Count)]; - S32 mMaxCharWidth; - S32 mMaxCharHeight; + S32 mBitmapWidth = 0; + S32 mBitmapHeight = 0; + S32 mCurrentOffsetX[static_cast(EFontGlyphType::Count)] = { 1 }; + S32 mCurrentOffsetY[static_cast(EFontGlyphType::Count)] = { 1 }; + S32 mMaxCharWidth = 0; + S32 mMaxCharHeight = 0; std::vector> mImageRawVec[static_cast(EFontGlyphType::Count)]; std::vector> mImageGLVec[static_cast(EFontGlyphType::Count)]; }; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index f2dc5771e9..1d7d930e6f 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -482,6 +482,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) 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(sys_path + MACOSX_FONT_SUPPLEMENTAL); #endif // The fontname string may contain multiple font file names separated by semicolons. @@ -491,8 +493,6 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) ++font_file_it) { LLFontGL *fontp = NULL; - 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); 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()); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 9005d70b2e..0447e7070c 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -208,7 +208,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 : 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), diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 281777e492..85c9318b8a 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -140,7 +140,7 @@ class ViewerManifest(LLManifest): self.path("*.tga") # Include our fonts - with self.prefix(src="../packages/fonts"): + with self.prefix(src="../packages/fonts",src_dst="fonts"): self.path("*.ttf") self.path("*.txt") -- cgit v1.2.3 From cf2afdc541b540582650f89c6b95aacfeaef516f Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 11 Sep 2022 21:44:00 +0100 Subject: Add emoji as its own font to promote character reuse --- indra/llrender/llfontgl.cpp | 7 +++++++ indra/llrender/llfontgl.h | 1 + indra/newview/skins/default/xui/en/fonts.xml | 5 +++++ 3 files changed, 13 insertions(+) (limited to 'indra') diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 4770f79395..e9899c9567 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -1005,6 +1005,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 a60feb87cb..29bdb798e1 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -191,6 +191,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/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index ed35546322..681f670f08 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -70,6 +70,11 @@ DejaVuSans-BoldOblique.ttf + + Twemoji.ttf + + DejaVuSansMono.ttf -- cgit v1.2.3 From 063fe5953ada75177c1668f8b805cd9b79724581 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 2 Nov 2022 14:25:27 +0100 Subject: Create a separate segment for emoji characters so that we can display them in a slightly larger font size than the surrounding text --- indra/llui/lltextbase.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++--- indra/llui/lltextbase.h | 12 ++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0447e7070c..2a6e6901e4 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2302,6 +2302,36 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s insertStringNoUndo(getLength(), widget_wide_text, &segments); } +void LLTextBase::createTextWithEmojiSegment(const LLWString& text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments) +{ + LLStyleSP emoji_style; + + S32 text_start = 0, text_kitty = 0, text_len = text.size(); + for (; text_kitty < text_len; text_kitty++) + { + if (LLStringOps::isEmoji(text[text_kitty])) + { + if (text_kitty > text_start) + { + segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_kitty, *this)); + } + + if (!emoji_style) + { + emoji_style = new LLStyle(*style); + emoji_style->setFont(LLFontGL::getFontEmoji()); + } + segments.push_back(new LLEmojiTextSegment(emoji_style, segment_start + text_kitty, segment_start + text_kitty + 1, *this)); + text_start = text_kitty + 1; + } + } + + if (text_start < text_len) + { + segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_len, *this)); + } +} + void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) { // Save old state @@ -2334,6 +2364,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp; + segment_vec_t segments; if (underline_on_hover_only || mSkipLinkUnderline) { highlight_params.font.style("NORMAL"); @@ -2342,9 +2373,8 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); + createTextWithEmojiSegment(wide_text, cur_length, sp, segments); } - segment_vec_t segments; segments.push_back(segmentp); insertStringNoUndo(cur_length, wide_text, &segments); } @@ -2367,7 +2397,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this )); + createTextWithEmojiSegment(wide_text, segment_start, sp, segments); } insertStringNoUndo(getLength(), wide_text, &segments); @@ -3514,6 +3544,19 @@ const S32 LLLabelTextSegment::getLength() const return mEditor.getWlabel().length(); } +// +// 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) +{ +} + // // LLOnHoverChangeableTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 590e7c9dbb..fc999c4cca 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -178,6 +178,17 @@ 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; } +}; + // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) class LLOnHoverChangeableTextSegment : public LLNormalTextSegment { @@ -629,6 +640,7 @@ protected: void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); + void createTextWithEmojiSegment(const LLWString& wide_text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments); S32 normalizeUri(std::string& uri); protected: -- cgit v1.2.3 From 8694f055b64eb7ce13897e49afe73c4d3295a29a Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:09:30 +0200 Subject: Add emoji helper support to LLTextEditor --- indra/llui/lltexteditor.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ indra/llui/lltexteditor.h | 5 +++++ 2 files changed, 45 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index b1f8b00cab..889940cf9a 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"); @@ -259,6 +261,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mPrevalidateFunc(p.prevalidate_callback()), mContextMenu(NULL), mShowContextMenu(p.show_context_menu), + mShowEmojiHelper(p.show_emoji_helper), mEnableTooltipPaste(p.enable_tooltip_paste), mPassDelete(FALSE), mKeepSelectionOnReturn(false) @@ -501,6 +504,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()) @@ -930,6 +942,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) ) { @@ -1124,6 +1142,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); + const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos); + LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode)); + } + } + if (!mReadOnly && mAutoreplaceCallback != NULL) { // autoreplace the text, if necessary @@ -1774,6 +1803,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) @@ -1815,6 +1849,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 26702b2412..04910b6f68 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; @@ -201,6 +202,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: @@ -317,6 +321,7 @@ private: BOOL mAllowEmbeddedItems; bool mShowContextMenu; + bool mShowEmojiHelper; bool mEnableTooltipPaste; bool mPassDelete; bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter -- cgit v1.2.3 From d95571cf7cd319e17338bc509d46ab5eab4eb968 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:10:06 +0200 Subject: Add mini emoji (auto-)complete helper --- indra/newview/CMakeLists.txt | 2 + indra/newview/llpanelemojicomplete.cpp | 210 +++++++++++++++++++++ indra/newview/llpanelemojicomplete.h | 99 ++++++++++ indra/newview/llviewerfloaterreg.cpp | 2 + .../default/xui/en/floater_emoji_complete.xml | 26 +++ .../default/xui/en/widgets/emoji_complete.xml | 7 + 6 files changed, 346 insertions(+) create mode 100644 indra/newview/llpanelemojicomplete.cpp create mode 100644 indra/newview/llpanelemojicomplete.h create mode 100644 indra/newview/skins/default/xui/en/floater_emoji_complete.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/emoji_complete.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8d902ce618..0bb1814322 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -441,6 +441,7 @@ set(viewer_SOURCE_FILES llpaneleditsky.cpp llpaneleditwater.cpp llpaneleditwearable.cpp + llpanelemojicomplete.cpp llpanelenvironment.cpp llpanelexperiencelisteditor.cpp llpanelexperiencelog.cpp @@ -1072,6 +1073,7 @@ set(viewer_HEADER_FILES llpaneleditsky.h llpaneleditwater.h llpaneleditwearable.h + llpanelemojicomplete.h llpanelenvironment.h llpanelexperiencelisteditor.h llpanelexperiencelog.h diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp new file mode 100644 index 0000000000..e1d80b62e2 --- /dev/null +++ b/indra/newview/llpanelemojicomplete.cpp @@ -0,0 +1,210 @@ +/** +* @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 "llpanelemojicomplete.h" +#include "lluictrlfactory.h" + +constexpr U32 MIN_MOUSE_MOVE_DELTA = 4; + +// ============================================================================ +// LLPanelEmojiComplete +// + +static LLDefaultChildRegistry::Register r("emoji_complete"); + +LLPanelEmojiComplete::Params::Params() + : selected_image("selected_image") +{ +} + +LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p) + : LLUICtrl(p) + , 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) +{ + if (MASK_NONE == mask) + { + bool handled = false; + switch (key) + { + case KEY_LEFT: + case KEY_UP: + selectPrevious(); + handled = true; + break; + case KEY_RIGHT: + case KEY_DOWN: + selectNext(); + handled = true; + break; + } + return handled; + } + + return false; +} + +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) +{ + mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint); + mScrollPos = llmin(mScrollPos, mEmojis.size()); + updateConstraints(); +} + +size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const +{ + if (mRenderRect.pointInRect(x, y)) + { + return llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); + } + return npos; +} + +void LLPanelEmojiComplete::select(size_t emoji_idx) +{ + mCurSelected = llclamp(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); +} + +void LLFloaterEmojiComplete::onOpen(const LLSD& key) +{ + findChild("emoji_complete_ctrl")->setEmojiHint(key["hint"].asString()); +} + +// ============================================================================ diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h new file mode 100644 index 0000000000..85b0609ae9 --- /dev/null +++ b/indra/newview/llpanelemojicomplete.h @@ -0,0 +1,99 @@ +/** +* @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 + { + Optional 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; + void reshape(S32 width, S32 height, BOOL called_from_parent) override; + +public: + 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::max(); + + const LLFontGL* mFont; + U16 mEmojiWidth = 0; + LLUIImagePtr mSelectedImage; + + LLWString mEmojis; + U16 mVisibleEmojis = 0; + size_t mFirstVisible = 0; + size_t mScrollPos = 0; + size_t mCurSelected = 0; + LLVector2 mLastHover; + + S32 mPadding = 8; + LLRect mRenderRect; +}; + +// ============================================================================ +// LLFloaterEmojiComplete +// + +class LLFloaterEmojiComplete : public LLFloater +{ +public: + LLFloaterEmojiComplete(const LLSD& sdKey); + +public: + void onOpen(const LLSD& key) override; +}; + +// ============================================================================ diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5a05f89758..a54b91030e 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -155,6 +155,7 @@ #include "llfloaterimnearbychat.h" #include "llpanelblockedlist.h" #include "llpanelclassified.h" +#include "llpanelemojicomplete.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" #include "llpreviewnotecard.h" @@ -229,6 +230,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", &LLFloaterReg::build); LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); 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..eb666bc32c --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml @@ -0,0 +1,26 @@ + + + + + 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..f35105ff7e --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml @@ -0,0 +1,7 @@ + + + -- cgit v1.2.3 From ec23b4bc633b853223d8442f60e769d44a25fe2d Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:06:41 +0200 Subject: Add the basic emoji dictionary class (responsible for loading them from disk and providing helpful lookup functions) --- indra/llui/CMakeLists.txt | 2 + indra/llui/llemojidictionary.cpp | 177 +++++++++++++++++++++++++++++++++++++++ indra/llui/llemojidictionary.h | 71 ++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 indra/llui/llemojidictionary.cpp create mode 100644 indra/llui/llemojidictionary.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index f781ff4110..4e007e429a 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -53,6 +53,7 @@ set(llui_SOURCE_FILES lldockcontrol.cpp lldraghandle.cpp lleditmenuhandler.cpp + llemojidictionary.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -163,6 +164,7 @@ set(llui_HEADER_FILES lldockablefloater.h lldockcontrol.h lleditmenuhandler.h + llemojidictionary.h llf32uictrl.h llfiltereditor.h llflashtimer.h diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp new file mode 100644 index 0000000000..e149832a8b --- /dev/null +++ b/indra/llui/llemojidictionary.cpp @@ -0,0 +1,177 @@ +/** +* @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 + +// ============================================================================ +// Constants +// + +constexpr char SKINNED_EMOJI_FILENAME[] = "emoji_characters.xml"; + +// ============================================================================ +// Helper functions +// + +template +std::list llsd_array_to_list(const LLSD& sd, std::function mutator = {}); + +template<> +std::list llsd_array_to_list(const LLSD& sd, std::function mutator) +{ + std::list 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(descriptor_sd["ShortCodes"], toLower); + Categories = llsd_array_to_list(descriptor_sd["Categories"], toLower); + + if (Name.empty()) + { + Name = ShortCodes.front(); + } +} + +bool LLEmojiDescriptor::isValid() const +{ + return + Character && + !ShortCodes.empty() && + !Categories.empty(); +} + +// ============================================================================ +// 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(std::string needle) +{ + // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category + LLStringUtil::toLower(needle); + const auto kitty_needle = boost::make_iterator_range((boost::starts_with(needle, ":")) ? needle.begin() + 1 : needle.begin(), needle.end()); + + LLWString wstr; + for (const auto& descr : mEmojis) + { + for (const auto& short_code : descr.ShortCodes) + { + if (boost::icontains(short_code, kitty_needle)) + { + wstr.push_back(descr.Character); + continue; + } + } + + for (const auto& category : descr.Categories) + { + if (boost::icontains(category, kitty_needle)) + { + wstr.push_back(descr.Character); + continue; + } + } + } + + return wstr; +} + +std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) +{ + const auto it = mEmoji2Descr.find(ch); + return (mEmoji2Descr.end() != it) ? it->second->Name : LLStringUtil::null; +} + +void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr) +{ + mEmojis.push_back(descr); + const LLEmojiDescriptor& back = mEmojis.back(); + mEmoji2Descr.insert(std::make_pair(descr.Character, &back)); +} + +// ============================================================================ diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h new file mode 100644 index 0000000000..87ea4a5aef --- /dev/null +++ b/indra/llui/llemojidictionary.h @@ -0,0 +1,71 @@ +/** +* @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 ShortCodes; + std::list Categories; +}; + +// ============================================================================ +// LLEmojiDictionary class +// + +class LLEmojiDictionary : public LLParamSingleton, public LLInitClass +{ + LLSINGLETON(LLEmojiDictionary); + ~LLEmojiDictionary() override {}; + +public: + static void initClass(); + LLWString findMatchingEmojis(std::string needle); + std::string getNameFromEmoji(llwchar ch); + +private: + void addEmoji(LLEmojiDescriptor&& descr); + +private: + std::list mEmojis; + std::map mEmoji2Descr; +}; + +// ============================================================================ -- cgit v1.2.3 From dad25bcb1e17e3dc384a9fb35d21b669bc3bbacd Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:17:02 +0200 Subject: Add the emoji helper class which can be used by text-input controls to provide emoji picker support --- indra/llui/CMakeLists.txt | 2 + indra/llui/llemojihelper.cpp | 142 +++++++++++++++++++++++++++++++++++++++++++ indra/llui/llemojihelper.h | 64 +++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 indra/llui/llemojihelper.cpp create mode 100644 indra/llui/llemojihelper.h (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 4e007e429a..68019734ab 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -54,6 +54,7 @@ set(llui_SOURCE_FILES lldraghandle.cpp lleditmenuhandler.cpp llemojidictionary.cpp + llemojihelper.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -165,6 +166,7 @@ set(llui_HEADER_FILES lldockcontrol.h lleditmenuhandler.h llemojidictionary.h + llemojihelper.h llf32uictrl.h llfiltereditor.h llflashtimer.h diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp new file mode 100644 index 0000000000..d4c31ee986 --- /dev/null +++ b/indra/llui/llemojihelper.cpp @@ -0,0 +1,142 @@ +/** +* @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) +{ + S32 shortCodePos = cursorPos; + + while (shortCodePos > 1 && + (LLStringOps::isAlnum(wtext[shortCodePos - 1]) || wtext[shortCodePos - 1] == L'-' || wtext[shortCodePos - 1] == L'_') ) + { + 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 cb) +{ + 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) +{ + 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..7ed042fc5f --- /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 + +class LLFloater; +class LLUICtrl; + +class LLEmojiHelper : public LLSingleton +{ + 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 commit_cb); + void hideHelper(const LLUICtrl* ctrl_p); + + // 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 mHostHandle; + LLHandle mHelperHandle; + boost::signals2::connection mHostCtrlFocusLostConn; + boost::signals2::connection mHelperCommitConn; + std::function mEmojiCommitCb; +}; -- cgit v1.2.3 From 3acb4caa0fb9d381be6cfbe1693ace389d90a16c Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:18:22 +0200 Subject: Add emoji helper support to LLTextEditor --- indra/llui/lltexteditor.cpp | 21 ++++++++++++++++++--- indra/llui/lltexteditor.h | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 889940cf9a..168c260c7d 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -676,6 +676,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; @@ -1147,9 +1162,9 @@ void LLTextEditor::addChar(llwchar wc) LLWString wtext(getWText()); S32 shortCodePos; if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) { - const LLRect cursorRect = getLocalRectFromDocIndex(mCursorPos); - const LLWString shortCode = wtext.substr(shortCodePos, mCursorPos); - LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, wstring_to_utf8str(shortCode)); + 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)); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 04910b6f68..4c8175a286 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -92,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); -- cgit v1.2.3 From 90e272993bb4c591fd2a98772d7fe1104dbff921 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:24:25 +0200 Subject: Autosize the mini emoji helper to fit the number of shown emojis --- indra/newview/llpanelemojicomplete.cpp | 49 ++++++++++++++++++++-- indra/newview/llpanelemojicomplete.h | 17 ++++++-- .../default/xui/en/floater_emoji_complete.xml | 22 +++++----- 3 files changed, 72 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index e1d80b62e2..f6823befac 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -39,12 +39,18 @@ constexpr U32 MIN_MOUSE_MOVE_DELTA = 4; static LLDefaultChildRegistry::Register r("emoji_complete"); LLPanelEmojiComplete::Params::Params() - : selected_image("selected_image") + : 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); @@ -125,9 +131,23 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) { + llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0; + size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; + mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint); + 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()); - updateConstraints(); } size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const @@ -200,11 +220,34 @@ LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey) setFocusStealsFrontmost(false); setAutoFocus(false); setBackgroundVisible(false); + setIsChrome(true); } void LLFloaterEmojiComplete::onOpen(const LLSD& key) { - findChild("emoji_complete_ctrl")->setEmojiHint(key["hint"].asString()); + mEmojiCtrl->setEmojiHint(key["hint"].asString()); +} + +BOOL LLFloaterEmojiComplete::postBuild() +{ + mEmojiCtrl = findChild("emoji_complete_ctrl"); + mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth(); + + return TRUE; +} + +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 index 85b0609ae9..b389ac9d53 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -39,6 +39,10 @@ class LLPanelEmojiComplete : public LLUICtrl public: struct Params : public LLInitParam::Block { + Optional autosize; + Optional max_emoji, + padding; + Optional selected_image; Params(); @@ -68,8 +72,12 @@ protected: protected: static constexpr auto npos = std::numeric_limits::max(); + bool mAutoSize = false; const LLFontGL* mFont; U16 mEmojiWidth = 0; + size_t mMaxVisible = 0; + S32 mPadding = 8; + LLRect mRenderRect; LLUIImagePtr mSelectedImage; LLWString mEmojis; @@ -78,9 +86,6 @@ protected: size_t mScrollPos = 0; size_t mCurSelected = 0; LLVector2 mLastHover; - - S32 mPadding = 8; - LLRect mRenderRect; }; // ============================================================================ @@ -94,6 +99,12 @@ public: public: 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/skins/default/xui/en/floater_emoji_complete.xml b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml index eb666bc32c..e9ea8f4de7 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_complete.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_complete.xml @@ -13,14 +13,16 @@ single_instance="true" width="240" > - - + + -- cgit v1.2.3 From f6f52d327be5f03265d66a95df6fc0716f91ca07 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:35:44 +0200 Subject: Provide a way for a floater to remain the topmost floater, even when focus is given to a different floater --- indra/llui/llfloater.cpp | 24 +++++++++++++++++++++++- indra/llui/llfloater.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e42922543..04f6b11b7c 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -3039,7 +3039,29 @@ void LLFloaterView::syncFloaterTabOrder() LLFloater* floaterp = dynamic_cast(*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 listTop; + if (mFrontChild && !mFrontChild->canFocusStealFrontmost()) + { + for (LLView* childfloaterp : *getChildList()) + { + if (static_cast(childfloaterp)->canFocusStealFrontmost()) + break; + listTop.push_back(childfloaterp); + } + } + + bringToFront(floaterp, FALSE); + + // Restore top floaters + for (LLView* childp :listTop) + { + sendChildToFront(childp); + } + } + break; } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2672d600c6..1d4aff31eb 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()); @@ -478,6 +481,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; -- cgit v1.2.3 From 8d08f417dc1f5b2681774f000951993e0f0cf79f Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 16:37:10 +0200 Subject: Show tooltip when hovering over an emoji text segment (currently will show its shortcode) --- indra/llui/lltextbase.cpp | 14 ++++++++++++++ indra/llui/lltextbase.h | 1 + 2 files changed, 15 insertions(+) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2a6e6901e4..693dcb7b8d 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -3557,6 +3557,20 @@ LLEmojiTextSegment::LLEmojiTextSegment(const LLColor4& color, S32 start, S32 end { } +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 fc999c4cca..31e9f16110 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -187,6 +187,7 @@ public: 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); }; // Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) -- cgit v1.2.3 From 58cdcd5dd23778c6fad9fa0da31b670ceff8eeeb Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 17:47:51 +0200 Subject: Handle return and escape in the mini emoji helper --- indra/llui/llemojihelper.cpp | 5 ++++ indra/llui/llemojihelper.h | 2 +- indra/newview/llpanelemojicomplete.cpp | 48 +++++++++++++++++++++++++++++++--- indra/newview/llpanelemojicomplete.h | 1 + 4 files changed, 51 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index d4c31ee986..54c801ab7b 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -98,6 +98,11 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p) { + if (ctrl_p && !isActive(ctrl_p)) + { + return; + } + setHostCtrl(nullptr); } diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 7ed042fc5f..63f5c640c9 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -45,7 +45,7 @@ public: 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 commit_cb); - void hideHelper(const LLUICtrl* ctrl_p); + void hideHelper(const LLUICtrl* ctrl_p = nullptr); // Eventing bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index f6823befac..61b08ad48d 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llemojidictionary.h" +#include "llemojihelper.h" #include "llpanelemojicomplete.h" #include "lluictrlfactory.h" @@ -101,9 +102,9 @@ BOOL LLPanelEmojiComplete::handleHover(S32 x, S32 y, MASK mask) BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent) { + bool handled = false; if (MASK_NONE == mask) { - bool handled = false; switch (key) { case KEY_LEFT: @@ -116,11 +117,24 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent selectNext(); handled = true; break; + case KEY_RETURN: + if (!mEmojis.empty()) + { + LLWString wstr; + wstr.push_back(mEmojis.at(mCurSelected)); + setValue(wstring_to_utf8str(wstr)); + onCommit(); + handled = true; + } + break; } - return handled; } - return false; + if (handled) + { + return TRUE; + } + return LLUICtrl::handleKey(key, mask, called_from_parent); } void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -223,6 +237,26 @@ LLFloaterEmojiComplete::LLFloaterEmojiComplete(const LLSD& sdKey) 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()); @@ -231,9 +265,15 @@ void LLFloaterEmojiComplete::onOpen(const LLSD& key) BOOL LLFloaterEmojiComplete::postBuild() { mEmojiCtrl = findChild("emoji_complete_ctrl"); + mEmojiCtrl->setCommitCallback( + std::bind([&](const LLSD& sdValue) + { + setValue(sdValue); + onCommit(); + }, std::placeholders::_2)); mEmojiCtrlHorz = getRect().getWidth() - mEmojiCtrl->getRect().getWidth(); - return TRUE; + return LLFloater::postBuild(); } void LLFloaterEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_parent) diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index b389ac9d53..361a2dc9b7 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -98,6 +98,7 @@ 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; -- cgit v1.2.3 From cb0bb91108b628e1134f1f655eaca9d305961cda Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 17:51:22 +0200 Subject: Mini emoji helper shows as a small slice when there are no matching emojis --- indra/newview/llpanelemojicomplete.cpp | 4 ++++ indra/newview/llpanelemojicomplete.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index 61b08ad48d..a7058a6724 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -260,6 +260,10 @@ BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_pare void LLFloaterEmojiComplete::onOpen(const LLSD& key) { mEmojiCtrl->setEmojiHint(key["hint"].asString()); + if (0 == mEmojiCtrl->getEmojiCount()) + { + LLEmojiHelper::instance().hideHelper(); + } } BOOL LLFloaterEmojiComplete::postBuild() diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index 361a2dc9b7..138cc465ba 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -59,7 +59,8 @@ public: void reshape(S32 width, S32 height, BOOL called_from_parent) override; public: - void setEmojiHint(const std::string& hint); + 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); -- cgit v1.2.3 From fb1553d8cf704eeb222de7ebd520a81fa242b317 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 17:55:13 +0200 Subject: Cannot use the :+1 emoji shortcode --- indra/llui/llemojihelper.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 54c801ab7b..551f0331e7 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -59,8 +59,18 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S { S32 shortCodePos = cursorPos; - while (shortCodePos > 1 && - (LLStringOps::isAlnum(wtext[shortCodePos - 1]) || wtext[shortCodePos - 1] == L'-' || wtext[shortCodePos - 1] == L'_') ) + 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--; } -- cgit v1.2.3 From d1dbefc09b77990563d22aaf08d0c5708cc6cbbe Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 23 Oct 2022 19:05:19 +0200 Subject: Refactor emoji matching --- indra/llui/llemojidictionary.cpp | 70 ++++++++++++++++++++++++---------------- indra/llui/llemojidictionary.h | 2 +- 2 files changed, 43 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index e149832a8b..eefa4047a2 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -31,6 +31,8 @@ #include "llsdserialize.h" #include +#include +#include // ============================================================================ // Constants @@ -89,6 +91,41 @@ bool LLEmojiDescriptor::isValid() const !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 // @@ -130,35 +167,12 @@ void LLEmojiDictionary::initClass() } } -LLWString LLEmojiDictionary::findMatchingEmojis(std::string needle) +LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const { - // Search without the colon (if present) so the user can type ':food' and see all emojis in the 'Food' category - LLStringUtil::toLower(needle); - const auto kitty_needle = boost::make_iterator_range((boost::starts_with(needle, ":")) ? needle.begin() + 1 : needle.begin(), needle.end()); - - LLWString wstr; - for (const auto& descr : mEmojis) - { - for (const auto& short_code : descr.ShortCodes) - { - if (boost::icontains(short_code, kitty_needle)) - { - wstr.push_back(descr.Character); - continue; - } - } - - for (const auto& category : descr.Categories) - { - if (boost::icontains(category, kitty_needle)) - { - wstr.push_back(descr.Character); - continue; - } - } - } - - return wstr; + 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; } std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 87ea4a5aef..3fa55cd417 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -57,7 +57,7 @@ class LLEmojiDictionary : public LLParamSingleton, public LLI public: static void initClass(); - LLWString findMatchingEmojis(std::string needle); + LLWString findMatchingEmojis(const std::string& needle) const; std::string getNameFromEmoji(llwchar ch); private: -- cgit v1.2.3 From c40d3351d511b19f4468f7467be38499bf16588f Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 2 Nov 2022 19:05:24 +0100 Subject: Commit immediately if the user already typed a full shortcode --- indra/llui/llemojidictionary.cpp | 17 +++++++++++++---- indra/llui/llemojidictionary.h | 6 ++++-- indra/llui/llemojihelper.cpp | 8 ++++++++ indra/llui/lltextbase.cpp | 1 + 4 files changed, 26 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index eefa4047a2..c31638b0bf 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -175,17 +175,26 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const return result; } -std::string LLEmojiDictionary::getNameFromEmoji(llwchar ch) +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; + return (mEmoji2Descr.end() != it) ? it->second.Name : LLStringUtil::null; } void LLEmojiDictionary::addEmoji(LLEmojiDescriptor&& descr) { mEmojis.push_back(descr); - const LLEmojiDescriptor& back = mEmojis.back(); - mEmoji2Descr.insert(std::make_pair(descr.Character, &back)); + 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 index 3fa55cd417..0cde663719 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -58,14 +58,16 @@ class LLEmojiDictionary : public LLParamSingleton, public LLI public: static void initClass(); LLWString findMatchingEmojis(const std::string& needle) const; - std::string getNameFromEmoji(llwchar ch); + const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const; + std::string getNameFromEmoji(llwchar ch) const; private: void addEmoji(LLEmojiDescriptor&& descr); private: std::list mEmojis; - std::map mEmoji2Descr; + std::map mEmoji2Descr; + std::map mShortCode2Descr; }; // ============================================================================ diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 551f0331e7..32471e59a8 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -83,6 +83,14 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function 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); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 693dcb7b8d..b88c7ced40 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" -- cgit v1.2.3 From 97300c608153d21a441ed34b0a5b9a2ea815df2e Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 2 Nov 2022 19:11:20 +0100 Subject: Add (partial) emoji set descriptors --- .../skins/default/xui/en/emoji_characters.xml | 10955 +++++++++++++++++++ 1 file changed, 10955 insertions(+) create mode 100644 indra/newview/skins/default/xui/en/emoji_characters.xml (limited to 'indra') 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 @@ + + + + + Character + 😀 + ShortCodes + + :grinning: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😄 + ShortCodes + + :smile: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😆 + ShortCodes + + :laughing: + + + + Categories + + Smiley + Face Smiling + + + + Character + 🤣 + ShortCodes + + :rofl: + :satisfied: + + + Categories + + Smiley + Face Smiling + + + + Character + 🙂 + ShortCodes + + :slightly_smiling_face: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😉 + ShortCodes + + :wink: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😇 + ShortCodes + + :innocent: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😃 + ShortCodes + + :smiley: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😁 + ShortCodes + + :grin: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😅 + ShortCodes + + :sweat_smile: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😂 + ShortCodes + + :joy: + + + + Categories + + Smiley + Face Smiling + + + + Character + 🙃 + ShortCodes + + :upside_down_face: + + + + Categories + + Smiley + Face Smiling + + + + Character + 😊 + ShortCodes + + :blush: + + + + Categories + + Smiley + Face Smiling + + + + Character + 🥰 + ShortCodes + + :smiling_face_with_three_hearts: + + + + Categories + + Smiley + Face Affection + + + + Character + 🤩 + ShortCodes + + :star_struck: + + + + Categories + + Smiley + Face Affection + + + + Character + 😗 + ShortCodes + + :kissing: + + + + Categories + + Smiley + Face Affection + + + + Character + 😚 + ShortCodes + + :kissing_closed_eyes: + + + + Categories + + Smiley + Face Affection + + + + Character + 🥲 + ShortCodes + + :smiling_face_with_tear: + + + + Categories + + Smiley + Face Affection + + + + Character + 😍 + ShortCodes + + :heart_eyes: + + + + Categories + + Smiley + Face Affection + + + + Character + 😘 + ShortCodes + + :kissing_heart: + + + + Categories + + Smiley + Face Affection + + + + Character + ☺️ + ShortCodes + + :relaxed: + + + + Categories + + Smiley + Face Affection + + + + Character + 😙 + ShortCodes + + :kissing_smiling_eyes: + + + + Categories + + Smiley + Face Affection + + + + Character + 😋 + ShortCodes + + :yum: + + + + Categories + + Smiley + Face Tongue + + + + Character + 😜 + ShortCodes + + :stuck_out_tongue_winking_eye: + + + + Categories + + Smiley + Face Tongue + + + + Character + 😝 + ShortCodes + + :stuck_out_tongue_closed_eyes: + + + + Categories + + Smiley + Face Tongue + + + + Character + 😛 + ShortCodes + + :stuck_out_tongue: + + + + Categories + + Smiley + Face Tongue + + + + Character + 🤪 + ShortCodes + + :zany_face: + + + + Categories + + Smiley + Face Tongue + + + + Character + 🤑 + ShortCodes + + :money_mouth_face: + + + + Categories + + Smiley + Face Tongue + + + + Character + 🤗 + ShortCodes + + :hugs: + + + + Categories + + Smiley + Face Hand + + + + Character + 🤫 + ShortCodes + + :shushing_face: + + + + Categories + + Smiley + Face Hand + + + + Character + 🤭 + ShortCodes + + :hand_over_mouth: + + + + Categories + + Smiley + Face Hand + + + + Character + 🤔 + ShortCodes + + :thinking: + + + + Categories + + Smiley + Face Hand + + + + Character + 🤐 + ShortCodes + + :zipper_mouth_face: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😐 + ShortCodes + + :neutral_face: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😶 + ShortCodes + + :no_mouth: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😏 + ShortCodes + + :smirk: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 🙄 + ShortCodes + + :roll_eyes: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😮‍💨 + ShortCodes + + :face_exhaling: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 🤨 + ShortCodes + + :raised_eyebrow: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😑 + ShortCodes + + :expressionless: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😶‍🌫️ + ShortCodes + + :face_in_clouds: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😒 + ShortCodes + + :unamused: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😬 + ShortCodes + + :grimacing: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 🤥 + ShortCodes + + :lying_face: + + + + Categories + + Smiley + Face Neutral Skeptical + + + + Character + 😌 + ShortCodes + + :relieved: + + + + Categories + + Smiley + Face Sleepy + + + + Character + 😪 + ShortCodes + + :sleepy: + + + + Categories + + Smiley + Face Sleepy + + + + Character + 😴 + ShortCodes + + :sleeping: + + + + Categories + + Smiley + Face Sleepy + + + + Character + 😔 + ShortCodes + + :pensive: + + + + Categories + + Smiley + Face Sleepy + + + + Character + 🤤 + ShortCodes + + :drooling_face: + + + + Categories + + Smiley + Face Sleepy + + + + Character + 😷 + ShortCodes + + :mask: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤕 + ShortCodes + + :face_with_head_bandage: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤮 + ShortCodes + + :vomiting_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🥵 + ShortCodes + + :hot_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🥴 + ShortCodes + + :woozy_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 😵‍💫 + ShortCodes + + :face_with_spiral_eyes: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤒 + ShortCodes + + :face_with_thermometer: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤢 + ShortCodes + + :nauseated_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤧 + ShortCodes + + :sneezing_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🥶 + ShortCodes + + :cold_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 😵 + ShortCodes + + :dizzy_face: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤯 + ShortCodes + + :exploding_head: + + + + Categories + + Smiley + Face Unwell + + + + Character + 🤠 + ShortCodes + + :cowboy_hat_face: + + + + Categories + + Smiley + Face Hat + + + + Character + 🥸 + ShortCodes + + :disguised_face: + + + + Categories + + Smiley + Face Hat + + + + Character + 🥳 + ShortCodes + + :partying_face: + + + + Categories + + Smiley + Face Hat + + + + Character + 😎 + ShortCodes + + :sunglasses: + + + + Categories + + Smiley + Face Glasses + + + + Character + 🧐 + ShortCodes + + :monocle_face: + + + + Categories + + Smiley + Face Glasses + + + + Character + 🤓 + ShortCodes + + :nerd_face: + + + + Categories + + Smiley + Face Glasses + + + + Character + 😕 + ShortCodes + + :confused: + + + + Categories + + Smiley + Face Concerned + + + + Character + 🙁 + ShortCodes + + :slightly_frowning_face: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😮 + ShortCodes + + :open_mouth: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😲 + ShortCodes + + :astonished: + + + + Categories + + Smiley + Face Concerned + + + + Character + 🥺 + ShortCodes + + :pleading_face: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😧 + ShortCodes + + :anguished: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😰 + ShortCodes + + :cold_sweat: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😢 + ShortCodes + + :cry: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😱 + ShortCodes + + :scream: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😣 + ShortCodes + + :persevere: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😓 + ShortCodes + + :sweat: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😫 + ShortCodes + + :tired_face: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😟 + ShortCodes + + :worried: + + + + Categories + + Smiley + Face Concerned + + + + Character + ☹️ + ShortCodes + + :frowning_face: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😯 + ShortCodes + + :hushed: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😳 + ShortCodes + + :flushed: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😦 + ShortCodes + + :frowning: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😨 + ShortCodes + + :fearful: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😥 + ShortCodes + + :disappointed_relieved: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😭 + ShortCodes + + :sob: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😖 + ShortCodes + + :confounded: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😞 + ShortCodes + + :disappointed: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😩 + ShortCodes + + :weary: + + + + Categories + + Smiley + Face Concerned + + + + Character + 🥱 + ShortCodes + + :yawning_face: + + + + Categories + + Smiley + Face Concerned + + + + Character + 😤 + ShortCodes + + :triumph: + + + + Categories + + Smiley + Face Negative + + + + Character + 😠 + ShortCodes + + :angry: + + + + Categories + + Smiley + Face Negative + + + + Character + 😈 + ShortCodes + + :smiling_imp: + + + + Categories + + Smiley + Face Negative + + + + Character + 💀 + ShortCodes + + :skull: + + + + Categories + + Smiley + Face Negative + + + + Character + 😡 + ShortCodes + + :pout: + :rage: + + + Categories + + Smiley + Face Negative + + + + Character + 🤬 + ShortCodes + + :cursing_face: + + + + Categories + + Smiley + Face Negative + + + + Character + 👿 + ShortCodes + + :imp: + + + + Categories + + Smiley + Face Negative + + + + Character + ☠️ + ShortCodes + + :skull_and_crossbones: + + + + Categories + + Smiley + Face Negative + + + + Character + 💩 + ShortCodes + + :hankey: + :poop: + :shit: + + Categories + + Smiley + Face Costume + + + + Character + 👹 + ShortCodes + + :japanese_ogre: + + + + Categories + + Smiley + Face Costume + + + + Character + 👻 + ShortCodes + + :ghost: + + + + Categories + + Smiley + Face Costume + + + + Character + 👾 + ShortCodes + + :space_invader: + + + + Categories + + Smiley + Face Costume + + + + Character + 🤡 + ShortCodes + + :clown_face: + + + + Categories + + Smiley + Face Costume + + + + Character + 👺 + ShortCodes + + :japanese_goblin: + + + + Categories + + Smiley + Face Costume + + + + Character + 👽 + ShortCodes + + :alien: + + + + Categories + + Smiley + Face Costume + + + + Character + 🤖 + ShortCodes + + :robot: + + + + Categories + + Smiley + Face Costume + + + + Character + 😺 + ShortCodes + + :smiley_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😹 + ShortCodes + + :joy_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😼 + ShortCodes + + :smirk_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 🙀 + ShortCodes + + :scream_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😾 + ShortCodes + + :pouting_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😸 + ShortCodes + + :smile_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😻 + ShortCodes + + :heart_eyes_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😽 + ShortCodes + + :kissing_cat: + + + + Categories + + Smiley + Cat Face + + + + Character + 😿 + ShortCodes + + :crying_cat_face: + + + + Categories + + Smiley + Cat Face + + + + Character + 🙈 + ShortCodes + + :see_no_evil: + + + + Categories + + Smiley + Monkey Face + + + + Character + 🙊 + ShortCodes + + :speak_no_evil: + + + + Categories + + Smiley + Monkey Face + + + + Character + 🙉 + ShortCodes + + :hear_no_evil: + + + + Categories + + Smiley + Monkey Face + + + + Character + 💋 + ShortCodes + + :kiss: + + + + Categories + + Emotion + + + + + Character + 💘 + ShortCodes + + :cupid: + + + + Categories + + Emotion + + + + + Character + 💖 + ShortCodes + + :sparkling_heart: + + + + Categories + + Emotion + + + + + Character + 💓 + ShortCodes + + :heartbeat: + + + + Categories + + Emotion + + + + + Character + 💕 + ShortCodes + + :two_hearts: + + + + Categories + + Emotion + + + + + Character + ❣️ + ShortCodes + + :heavy_heart_exclamation: + + + + Categories + + Emotion + + + + + Character + ❤️‍🔥 + ShortCodes + + :heart_on_fire: + + + + Categories + + Emotion + + + + + Character + ❤️ + ShortCodes + + :heart: + + + + Categories + + Emotion + + + + + Character + 💛 + ShortCodes + + :yellow_heart: + + + + Categories + + Emotion + + + + + Character + 💙 + ShortCodes + + :blue_heart: + + + + Categories + + Emotion + + + + + Character + 🤎 + ShortCodes + + :brown_heart: + + + + Categories + + Emotion + + + + + Character + 🤍 + ShortCodes + + :white_heart: + + + + Categories + + Emotion + + + + + Character + 💢 + ShortCodes + + :anger: + + + + Categories + + Emotion + + + + + Character + 💫 + ShortCodes + + :dizzy: + + + + Categories + + Emotion + + + + + Character + 💨 + ShortCodes + + :dash: + + + + Categories + + Emotion + + + + + Character + 💣 + ShortCodes + + :bomb: + + + + Categories + + Emotion + + + + + Character + 👁️‍🗨️ + ShortCodes + + :eye_speech_bubble: + + + + Categories + + Emotion + + + + + Character + 🗯️ + ShortCodes + + :right_anger_bubble: + + + + Categories + + Emotion + + + + + Character + 💤 + ShortCodes + + :zzz: + + + + Categories + + Emotion + + + + + Character + 💌 + ShortCodes + + :love_letter: + + + + Categories + + Emotion + + + + + Character + 💝 + ShortCodes + + :gift_heart: + + + + Categories + + Emotion + + + + + Character + 💗 + ShortCodes + + :heartpulse: + + + + Categories + + Emotion + + + + + Character + 💞 + ShortCodes + + :revolving_hearts: + + + + Categories + + Emotion + + + + + Character + 💟 + ShortCodes + + :heart_decoration: + + + + Categories + + Emotion + + + + + Character + 💔 + ShortCodes + + :broken_heart: + + + + Categories + + Emotion + + + + + Character + ❤️‍🩹 + ShortCodes + + :mending_heart: + + + + Categories + + Emotion + + + + + Character + 🧡 + ShortCodes + + :orange_heart: + + + + Categories + + Emotion + + + + + Character + 💚 + ShortCodes + + :green_heart: + + + + Categories + + Emotion + + + + + Character + 💜 + ShortCodes + + :purple_heart: + + + + Categories + + Emotion + + + + + Character + 🖤 + ShortCodes + + :black_heart: + + + + Categories + + Emotion + + + + + Character + 💯 + ShortCodes + + :100: + + + + Categories + + Emotion + + + + + Character + 💥 + ShortCodes + + :boom: + :collision: + + + Categories + + Emotion + + + + + Character + 💦 + ShortCodes + + :sweat_drops: + + + + Categories + + Emotion + + + + + Character + 🕳️ + ShortCodes + + :hole: + + + + Categories + + Emotion + + + + + Character + 💬 + ShortCodes + + :speech_balloon: + + + + Categories + + Emotion + + + + + Character + 🗨️ + ShortCodes + + :left_speech_bubble: + + + + Categories + + Emotion + + + + + Character + 💭 + ShortCodes + + :thought_balloon: + + + + Categories + + Emotion + + + + + Character + 👋 + ShortCodes + + :wave: + + + + Categories + + Body + Hand Fingers Open + + + + Character + 🖐️ + ShortCodes + + :raised_hand_with_fingers_splayed: + + + + Categories + + Body + Hand Fingers Open + + + + Character + 🖖 + ShortCodes + + :vulcan_salute: + + + + Categories + + Body + Hand Fingers Open + + + + Character + 🤚 + ShortCodes + + :raised_back_of_hand: + + + + Categories + + Body + Hand Fingers Open + + + + Character + + ShortCodes + + :hand: + :raised_hand: + + + Categories + + Body + Hand Fingers Open + + + + Character + 👌 + ShortCodes + + :ok_hand: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤏 + ShortCodes + + :pinching_hand: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤞 + ShortCodes + + :crossed_fingers: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤘 + ShortCodes + + :metal: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤌 + ShortCodes + + :pinched_fingers: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + ✌️ + ShortCodes + + :v: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤟 + ShortCodes + + :love_you_gesture: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 🤙 + ShortCodes + + :call_me_hand: + + + + Categories + + Body + Hand Fingers Partial + + + + Character + 👈 + ShortCodes + + :point_left: + + + + Categories + + Body + Hand Single Finger + + + + Character + 👆 + ShortCodes + + :point_up_2: + + + + Categories + + Body + Hand Single Finger + + + + Character + 👇 + ShortCodes + + :point_down: + + + + Categories + + Body + Hand Single Finger + + + + Character + 👉 + ShortCodes + + :point_right: + + + + Categories + + Body + Hand Single Finger + + + + Character + 🖕 + ShortCodes + + :fu: + :middle_finger: + + + Categories + + Body + Hand Single Finger + + + + Character + ☝️ + ShortCodes + + :point_up: + + + + Categories + + Body + Hand Single Finger + + + + Character + 👍 + ShortCodes + + :+1: + :thumbsup: + + + Categories + + Body + Hand Fingers Closed + + + + Character + + ShortCodes + + :fist: + :fist_raised: + + + Categories + + Body + Hand Fingers Closed + + + + Character + 🤛 + ShortCodes + + :fist_left: + + + + Categories + + Body + Hand Fingers Closed + + + + Character + 👎 + ShortCodes + + :-1: + :thumbsdown: + + + Categories + + Body + Hand Fingers Closed + + + + Character + 👊 + ShortCodes + + :facepunch: + :fist_oncoming: + :punch: + + Categories + + Body + Hand Fingers Closed + + + + Character + 🤜 + ShortCodes + + :fist_right: + + + + Categories + + Body + Hand Fingers Closed + + + + Character + 👏 + ShortCodes + + :clap: + + + + Categories + + Body + Hands + + + + Character + 👐 + ShortCodes + + :open_hands: + + + + Categories + + Body + Hands + + + + Character + 🤝 + ShortCodes + + :handshake: + + + + Categories + + Body + Hands + + + + Character + 🙌 + ShortCodes + + :raised_hands: + + + + Categories + + Body + Hands + + + + Character + 🤲 + ShortCodes + + :palms_up_together: + + + + Categories + + Body + Hands + + + + Character + 🙏 + ShortCodes + + :pray: + + + + Categories + + Body + Hands + + + + Character + ✍️ + ShortCodes + + :writing_hand: + + + + Categories + + Body + Hand Prop + + + + Character + 🤳 + ShortCodes + + :selfie: + + + + Categories + + Body + Hand Prop + + + + Character + 💅 + ShortCodes + + :nail_care: + + + + Categories + + Body + Hand Prop + + + + Character + 💪 + ShortCodes + + :muscle: + + + + Categories + + Body + Body Parts + + + + Character + 🦿 + ShortCodes + + :mechanical_leg: + + + + Categories + + Body + Body Parts + + + + Character + 🦶 + ShortCodes + + :foot: + + + + Categories + + Body + Body Parts + + + + Character + 🦻 + ShortCodes + + :ear_with_hearing_aid: + + + + Categories + + Body + Body Parts + + + + Character + 🧠 + ShortCodes + + :brain: + + + + Categories + + Body + Body Parts + + + + Character + 🫁 + ShortCodes + + :lungs: + + + + Categories + + Body + Body Parts + + + + Character + 🦴 + ShortCodes + + :bone: + + + + Categories + + Body + Body Parts + + + + Character + 👁️ + ShortCodes + + :eye: + + + + Categories + + Body + Body Parts + + + + Character + 👄 + ShortCodes + + :lips: + + + + Categories + + Body + Body Parts + + + + Character + 🦾 + ShortCodes + + :mechanical_arm: + + + + Categories + + Body + Body Parts + + + + Character + 🦵 + ShortCodes + + :leg: + + + + Categories + + Body + Body Parts + + + + Character + 👂 + ShortCodes + + :ear: + + + + Categories + + Body + Body Parts + + + + Character + 👃 + ShortCodes + + :nose: + + + + Categories + + Body + Body Parts + + + + Character + 🫀 + ShortCodes + + :anatomical_heart: + + + + Categories + + Body + Body Parts + + + + Character + 🦷 + ShortCodes + + :tooth: + + + + Categories + + Body + Body Parts + + + + Character + 👀 + ShortCodes + + :eyes: + + + + Categories + + Body + Body Parts + + + + Character + 👅 + ShortCodes + + :tongue: + + + + Categories + + Body + Body Parts + + + + Character + 👶 + ShortCodes + + :baby: + + + + Categories + + Person + + + + + Character + 👦 + ShortCodes + + :boy: + + + + Categories + + Person + + + + + Character + 🧑 + ShortCodes + + :adult: + + + + Categories + + Person + + + + + Character + 👨 + ShortCodes + + :man: + + + + Categories + + Person + + + + + Character + 🧔‍♂️ + ShortCodes + + :man_beard: + + + + Categories + + Person + + + + + Character + 👨‍🦰 + ShortCodes + + :red_haired_man: + + + + Categories + + Person + + + + + Character + 👨‍🦳 + ShortCodes + + :white_haired_man: + + + + Categories + + Person + + + + + Character + 👩 + ShortCodes + + :woman: + + + + Categories + + Person + + + + + Character + 🧑‍🦰 + ShortCodes + + :person_red_hair: + + + + Categories + + Person + + + + + Character + 🧑‍🦱 + ShortCodes + + :person_curly_hair: + + + + Categories + + Person + + + + + Character + 🧑‍🦳 + ShortCodes + + :person_white_hair: + + + + Categories + + Person + + + + + Character + 🧑‍🦲 + ShortCodes + + :person_bald: + + + + Categories + + Person + + + + + Character + 👱‍♂️ + ShortCodes + + :blond_haired_man: + + + + Categories + + Person + + + + + Character + 👴 + ShortCodes + + :older_man: + + + + Categories + + Person + + + + + Character + 🧒 + ShortCodes + + :child: + + + + Categories + + Person + + + + + Character + 👧 + ShortCodes + + :girl: + + + + Categories + + Person + + + + + Character + 👱 + ShortCodes + + :blond_haired_person: + + + + Categories + + Person + + + + + Character + 🧔 + ShortCodes + + :bearded_person: + + + + Categories + + Person + + + + + Character + 🧔‍♀️ + ShortCodes + + :woman_beard: + + + + Categories + + Person + + + + + Character + 👨‍🦱 + ShortCodes + + :curly_haired_man: + + + + Categories + + Person + + + + + Character + 👨‍🦲 + ShortCodes + + :bald_man: + + + + Categories + + Person + + + + + Character + 👩‍🦰 + ShortCodes + + :red_haired_woman: + + + + Categories + + Person + + + + + Character + 👩‍🦱 + ShortCodes + + :curly_haired_woman: + + + + Categories + + Person + + + + + Character + 👩‍🦳 + ShortCodes + + :white_haired_woman: + + + + Categories + + Person + + + + + Character + 👩‍🦲 + ShortCodes + + :bald_woman: + + + + Categories + + Person + + + + + Character + 👱‍♀️ + ShortCodes + + :blond_haired_woman: + :blonde_woman: + + + Categories + + Person + + + + + Character + 🧓 + ShortCodes + + :older_adult: + + + + Categories + + Person + + + + + Character + 👵 + ShortCodes + + :older_woman: + + + + Categories + + Person + + + + + Character + 🙍 + ShortCodes + + :frowning_person: + + + + Categories + + Person Gesture + + + + + Character + 🙍‍♀️ + ShortCodes + + :frowning_woman: + + + + Categories + + Person Gesture + + + + + Character + 🙎‍♂️ + ShortCodes + + :pouting_man: + + + + Categories + + Person Gesture + + + + + Character + 🙅 + ShortCodes + + :no_good: + + + + Categories + + Person Gesture + + + + + Character + 🙅‍♀️ + ShortCodes + + :ng_woman: + :no_good_woman: + + + Categories + + Person Gesture + + + + + Character + 🙆‍♂️ + ShortCodes + + :ok_man: + + + + Categories + + Person Gesture + + + + + Character + 💁 + ShortCodes + + :information_desk_person: + :tipping_hand_person: + + + Categories + + Person Gesture + + + + + Character + 💁‍♀️ + ShortCodes + + :sassy_woman: + :tipping_hand_woman: + + + Categories + + Person Gesture + + + + + Character + 🙋‍♂️ + ShortCodes + + :raising_hand_man: + + + + Categories + + Person Gesture + + + + + Character + 🧏 + ShortCodes + + :deaf_person: + + + + Categories + + Person Gesture + + + + + Character + 🧏‍♀️ + ShortCodes + + :deaf_woman: + + + + Categories + + Person Gesture + + + + + Character + 🙇‍♂️ + ShortCodes + + :bowing_man: + + + + Categories + + Person Gesture + + + + + Character + 🤦 + ShortCodes + + :facepalm: + + + + Categories + + Person Gesture + + + + + Character + 🤦‍♀️ + ShortCodes + + :woman_facepalming: + + + + Categories + + Person Gesture + + + + + Character + 🤷‍♂️ + ShortCodes + + :man_shrugging: + + + + Categories + + Person Gesture + + + + + Character + 🙍‍♂️ + ShortCodes + + :frowning_man: + + + + Categories + + Person Gesture + + + + + Character + 🙎 + ShortCodes + + :pouting_face: + + + + Categories + + Person Gesture + + + + + Character + 🙎‍♀️ + ShortCodes + + :pouting_woman: + + + + Categories + + Person Gesture + + + + + Character + 🙅‍♂️ + ShortCodes + + :ng_man: + :no_good_man: + + + Categories + + Person Gesture + + + + + Character + 🙆 + ShortCodes + + :ok_person: + + + + Categories + + Person Gesture + + + + + Character + 🙆‍♀️ + ShortCodes + + :ok_woman: + + + + Categories + + Person Gesture + + + + + Character + 💁‍♂️ + ShortCodes + + :sassy_man: + :tipping_hand_man: + + + Categories + + Person Gesture + + + + + Character + 🙋 + ShortCodes + + :raising_hand: + + + + Categories + + Person Gesture + + + + + Character + 🙋‍♀️ + ShortCodes + + :raising_hand_woman: + + + + Categories + + Person Gesture + + + + + Character + 🧏‍♂️ + ShortCodes + + :deaf_man: + + + + Categories + + Person Gesture + + + + + Character + 🙇 + ShortCodes + + :bow: + + + + Categories + + Person Gesture + + + + + Character + 🙇‍♀️ + ShortCodes + + :bowing_woman: + + + + Categories + + Person Gesture + + + + + Character + 🤦‍♂️ + ShortCodes + + :man_facepalming: + + + + Categories + + Person Gesture + + + + + Character + 🤷 + ShortCodes + + :shrug: + + + + Categories + + Person Gesture + + + + + Character + 🤷‍♀️ + ShortCodes + + :woman_shrugging: + + + + Categories + + Person Gesture + + + + + Character + 🧑‍⚕️ + ShortCodes + + :health_worker: + + + + Categories + + Person Role + + + + + Character + 👩‍⚕️ + ShortCodes + + :woman_health_worker: + + + + Categories + + Person Role + + + + + Character + 👨‍🎓 + ShortCodes + + :man_student: + + + + Categories + + Person Role + + + + + Character + 🧑‍🏫 + ShortCodes + + :teacher: + + + + Categories + + Person Role + + + + + Character + 👩‍🏫 + ShortCodes + + :woman_teacher: + + + + Categories + + Person Role + + + + + Character + 👨‍⚖️ + ShortCodes + + :man_judge: + + + + Categories + + Person Role + + + + + Character + 🧑‍🌾 + ShortCodes + + :farmer: + + + + Categories + + Person Role + + + + + Character + 👩‍🌾 + ShortCodes + + :woman_farmer: + + + + Categories + + Person Role + + + + + Character + 👨‍🍳 + ShortCodes + + :man_cook: + + + + Categories + + Person Role + + + + + Character + 🧑‍🔧 + ShortCodes + + :mechanic: + + + + Categories + + Person Role + + + + + Character + 👩‍🔧 + ShortCodes + + :woman_mechanic: + + + + Categories + + Person Role + + + + + Character + 👨‍🏭 + ShortCodes + + :man_factory_worker: + + + + Categories + + Person Role + + + + + Character + 🧑‍💼 + ShortCodes + + :office_worker: + + + + Categories + + Person Role + + + + + Character + 👩‍💼 + ShortCodes + + :woman_office_worker: + + + + Categories + + Person Role + + + + + Character + 👨‍🔬 + ShortCodes + + :man_scientist: + + + + Categories + + Person Role + + + + + Character + 🧑‍💻 + ShortCodes + + :technologist: + + + + Categories + + Person Role + + + + + Character + 👩‍💻 + ShortCodes + + :woman_technologist: + + + + Categories + + Person Role + + + + + Character + 👨‍🎤 + ShortCodes + + :man_singer: + + + + Categories + + Person Role + + + + + Character + 🧑‍🎨 + ShortCodes + + :artist: + + + + Categories + + Person Role + + + + + Character + 👩‍🎨 + ShortCodes + + :woman_artist: + + + + Categories + + Person Role + + + + + Character + 👨‍✈️ + ShortCodes + + :man_pilot: + + + + Categories + + Person Role + + + + + Character + 🧑‍🚀 + ShortCodes + + :astronaut: + + + + Categories + + Person Role + + + + + Character + 👩‍🚀 + ShortCodes + + :woman_astronaut: + + + + Categories + + Person Role + + + + + Character + 👨‍🚒 + ShortCodes + + :man_firefighter: + + + + Categories + + Person Role + + + + + Character + 👮 + ShortCodes + + :cop: + :police_officer: + + + Categories + + Person Role + + + + + Character + 👮‍♀️ + ShortCodes + + :policewoman: + + + + Categories + + Person Role + + + + + Character + 🕵️‍♂️ + ShortCodes + + :male_detective: + + + + Categories + + Person Role + + + + + Character + 💂 + ShortCodes + + :guard: + + + + Categories + + Person Role + + + + + Character + 💂‍♀️ + ShortCodes + + :guardswoman: + + + + Categories + + Person Role + + + + + Character + 👷 + ShortCodes + + :construction_worker: + + + + Categories + + Person Role + + + + + Character + 👷‍♀️ + ShortCodes + + :construction_worker_woman: + + + + Categories + + Person Role + + + + + Character + 👸 + ShortCodes + + :princess: + + + + Categories + + Person Role + + + + + Character + 👳‍♂️ + ShortCodes + + :man_with_turban: + + + + Categories + + Person Role + + + + + Character + 👲 + ShortCodes + + :man_with_gua_pi_mao: + + + + Categories + + Person Role + + + + + Character + 🤵 + ShortCodes + + :person_in_tuxedo: + + + + Categories + + Person Role + + + + + Character + 🤵‍♀️ + ShortCodes + + :woman_in_tuxedo: + + + + Categories + + Person Role + + + + + Character + 👰‍♂️ + ShortCodes + + :man_with_veil: + + + + Categories + + Person Role + + + + + Character + 🤰 + ShortCodes + + :pregnant_woman: + + + + Categories + + Person Role + + + + + Character + 👩‍🍼 + ShortCodes + + :woman_feeding_baby: + + + + Categories + + Person Role + + + + + Character + 🧑‍🍼 + ShortCodes + + :person_feeding_baby: + + + + Categories + + Person Role + + + + + Character + 👨‍⚕️ + ShortCodes + + :man_health_worker: + + + + Categories + + Person Role + + + + + Character + 🧑‍🎓 + ShortCodes + + :student: + + + + Categories + + Person Role + + + + + Character + 👩‍🎓 + ShortCodes + + :woman_student: + + + + Categories + + Person Role + + + + + Character + 👨‍🏫 + ShortCodes + + :man_teacher: + + + + Categories + + Person Role + + + + + Character + 🧑‍⚖️ + ShortCodes + + :judge: + + + + Categories + + Person Role + + + + + Character + 👩‍⚖️ + ShortCodes + + :woman_judge: + + + + Categories + + Person Role + + + + + Character + 👨‍🌾 + ShortCodes + + :man_farmer: + + + + Categories + + Person Role + + + + + Character + 🧑‍🍳 + ShortCodes + + :cook: + + + + Categories + + Person Role + + + + + Character + 👩‍🍳 + ShortCodes + + :woman_cook: + + + + Categories + + Person Role + + + + + Character + 👨‍🔧 + ShortCodes + + :man_mechanic: + + + + Categories + + Person Role + + + + + Character + 🧑‍🏭 + ShortCodes + + :factory_worker: + + + + Categories + + Person Role + + + + + Character + 👩‍🏭 + ShortCodes + + :woman_factory_worker: + + + + Categories + + Person Role + + + + + Character + 👨‍💼 + ShortCodes + + :man_office_worker: + + + + Categories + + Person Role + + + + + Character + 🧑‍🔬 + ShortCodes + + :scientist: + + + + Categories + + Person Role + + + + + Character + 👩‍🔬 + ShortCodes + + :woman_scientist: + + + + Categories + + Person Role + + + + + Character + 👨‍💻 + ShortCodes + + :man_technologist: + + + + Categories + + Person Role + + + + + Character + 🧑‍🎤 + ShortCodes + + :singer: + + + + Categories + + Person Role + + + + + Character + 👩‍🎤 + ShortCodes + + :woman_singer: + + + + Categories + + Person Role + + + + + Character + 👨‍🎨 + ShortCodes + + :man_artist: + + + + Categories + + Person Role + + + + + Character + 🧑‍✈️ + ShortCodes + + :pilot: + + + + Categories + + Person Role + + + + + Character + 👩‍✈️ + ShortCodes + + :woman_pilot: + + + + Categories + + Person Role + + + + + Character + 👨‍🚀 + ShortCodes + + :man_astronaut: + + + + Categories + + Person Role + + + + + Character + 🧑‍🚒 + ShortCodes + + :firefighter: + + + + Categories + + Person Role + + + + + Character + 👩‍🚒 + ShortCodes + + :woman_firefighter: + + + + Categories + + Person Role + + + + + Character + 👮‍♂️ + ShortCodes + + :policeman: + + + + Categories + + Person Role + + + + + Character + 🕵️ + ShortCodes + + :detective: + + + + Categories + + Person Role + + + + + Character + 🕵️‍♀️ + ShortCodes + + :female_detective: + + + + Categories + + Person Role + + + + + Character + 💂‍♂️ + ShortCodes + + :guardsman: + + + + Categories + + Person Role + + + + + Character + 🥷 + ShortCodes + + :ninja: + + + + Categories + + Person Role + + + + + Character + 👷‍♂️ + ShortCodes + + :construction_worker_man: + + + + Categories + + Person Role + + + + + Character + 🤴 + ShortCodes + + :prince: + + + + Categories + + Person Role + + + + + Character + 👳 + ShortCodes + + :person_with_turban: + + + + Categories + + Person Role + + + + + Character + 👳‍♀️ + ShortCodes + + :woman_with_turban: + + + + Categories + + Person Role + + + + + Character + 🧕 + ShortCodes + + :woman_with_headscarf: + + + + Categories + + Person Role + + + + + Character + 🤵‍♂️ + ShortCodes + + :man_in_tuxedo: + + + + Categories + + Person Role + + + + + Character + 👰 + ShortCodes + + :person_with_veil: + + + + Categories + + Person Role + + + + + Character + 👰‍♀️ + ShortCodes + + :bride_with_veil: + :woman_with_veil: + + + Categories + + Person Role + + + + + Character + 🤱 + ShortCodes + + :breast_feeding: + + + + Categories + + Person Role + + + + + Character + 👨‍🍼 + ShortCodes + + :man_feeding_baby: + + + + Categories + + Person Role + + + + + Character + 👼 + ShortCodes + + :angel: + + + + Categories + + Person Fantasy + + + + + Character + 🤶 + ShortCodes + + :mrs_claus: + + + + Categories + + Person Fantasy + + + + + Character + 🦸 + ShortCodes + + :superhero: + + + + Categories + + Person Fantasy + + + + + Character + 🦸‍♀️ + ShortCodes + + :superhero_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🦹‍♂️ + ShortCodes + + :supervillain_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧙 + ShortCodes + + :mage: + + + + Categories + + Person Fantasy + + + + + Character + 🧙‍♀️ + ShortCodes + + :mage_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧚‍♂️ + ShortCodes + + :fairy_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧛 + ShortCodes + + :vampire: + + + + Categories + + Person Fantasy + + + + + Character + 🧛‍♀️ + ShortCodes + + :vampire_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧜‍♂️ + ShortCodes + + :merman: + + + + Categories + + Person Fantasy + + + + + Character + 🧝 + ShortCodes + + :elf: + + + + Categories + + Person Fantasy + + + + + Character + 🧝‍♀️ + ShortCodes + + :elf_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧞‍♂️ + ShortCodes + + :genie_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧟 + ShortCodes + + :zombie: + + + + Categories + + Person Fantasy + + + + + Character + 🧟‍♀️ + ShortCodes + + :zombie_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🎅 + ShortCodes + + :santa: + + + + Categories + + Person Fantasy + + + + + Character + 🧑‍🎄 + ShortCodes + + :mx_claus: + + + + Categories + + Person Fantasy + + + + + Character + 🦸‍♂️ + ShortCodes + + :superhero_man: + + + + Categories + + Person Fantasy + + + + + Character + 🦹 + ShortCodes + + :supervillain: + + + + Categories + + Person Fantasy + + + + + Character + 🦹‍♀️ + ShortCodes + + :supervillain_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧙‍♂️ + ShortCodes + + :mage_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧚 + ShortCodes + + :fairy: + + + + Categories + + Person Fantasy + + + + + Character + 🧚‍♀️ + ShortCodes + + :fairy_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧛‍♂️ + ShortCodes + + :vampire_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧜 + ShortCodes + + :merperson: + + + + Categories + + Person Fantasy + + + + + Character + 🧜‍♀️ + ShortCodes + + :mermaid: + + + + Categories + + Person Fantasy + + + + + Character + 🧝‍♂️ + ShortCodes + + :elf_man: + + + + Categories + + Person Fantasy + + + + + Character + 🧞 + ShortCodes + + :genie: + + + + Categories + + Person Fantasy + + + + + Character + 🧞‍♀️ + ShortCodes + + :genie_woman: + + + + Categories + + Person Fantasy + + + + + Character + 🧟‍♂️ + ShortCodes + + :zombie_man: + + + + Categories + + Person Fantasy + + + + + Character + 💆 + ShortCodes + + :massage: + + + + Categories + + Person Activity + + + + + Character + 💆‍♀️ + ShortCodes + + :massage_woman: + + + + Categories + + Person Activity + + + + + Character + 💇‍♂️ + ShortCodes + + :haircut_man: + + + + Categories + + Person Activity + + + + + Character + 🚶 + ShortCodes + + :walking: + + + + Categories + + Person Activity + + + + + Character + 🚶‍♀️ + ShortCodes + + :walking_woman: + + + + Categories + + Person Activity + + + + + Character + 🧍‍♂️ + ShortCodes + + :standing_man: + + + + Categories + + Person Activity + + + + + Character + 🧎 + ShortCodes + + :kneeling_person: + + + + Categories + + Person Activity + + + + + Character + 🧎‍♀️ + ShortCodes + + :kneeling_woman: + + + + Categories + + Person Activity + + + + + Character + 👨‍🦯 + ShortCodes + + :man_with_probing_cane: + + + + Categories + + Person Activity + + + + + Character + 🧑‍🦼 + ShortCodes + + :person_in_motorized_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 👩‍🦼 + ShortCodes + + :woman_in_motorized_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 👨‍🦽 + ShortCodes + + :man_in_manual_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 🏃 + ShortCodes + + :runner: + :running: + + + Categories + + Person Activity + + + + + Character + 🏃‍♀️ + ShortCodes + + :running_woman: + + + + Categories + + Person Activity + + + + + Character + 🕺 + ShortCodes + + :man_dancing: + + + + Categories + + Person Activity + + + + + Character + 👯 + ShortCodes + + :dancers: + + + + Categories + + Person Activity + + + + + Character + 👯‍♀️ + ShortCodes + + :dancing_women: + + + + Categories + + Person Activity + + + + + Character + 🧖‍♂️ + ShortCodes + + :sauna_man: + + + + Categories + + Person Activity + + + + + Character + 🧗 + ShortCodes + + :climbing: + + + + Categories + + Person Activity + + + + + Character + 🧗‍♀️ + ShortCodes + + :climbing_woman: + + + + Categories + + Person Activity + + + + + Character + 💆‍♂️ + ShortCodes + + :massage_man: + + + + Categories + + Person Activity + + + + + Character + 💇 + ShortCodes + + :haircut: + + + + Categories + + Person Activity + + + + + Character + 💇‍♀️ + ShortCodes + + :haircut_woman: + + + + Categories + + Person Activity + + + + + Character + 🚶‍♂️ + ShortCodes + + :walking_man: + + + + Categories + + Person Activity + + + + + Character + 🧍 + ShortCodes + + :standing_person: + + + + Categories + + Person Activity + + + + + Character + 🧍‍♀️ + ShortCodes + + :standing_woman: + + + + Categories + + Person Activity + + + + + Character + 🧎‍♂️ + ShortCodes + + :kneeling_man: + + + + Categories + + Person Activity + + + + + Character + 🧑‍🦯 + ShortCodes + + :person_with_probing_cane: + + + + Categories + + Person Activity + + + + + Character + 👩‍🦯 + ShortCodes + + :woman_with_probing_cane: + + + + Categories + + Person Activity + + + + + Character + 👨‍🦼 + ShortCodes + + :man_in_motorized_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 🧑‍🦽 + ShortCodes + + :person_in_manual_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 👩‍🦽 + ShortCodes + + :woman_in_manual_wheelchair: + + + + Categories + + Person Activity + + + + + Character + 🏃‍♂️ + ShortCodes + + :running_man: + + + + Categories + + Person Activity + + + + + Character + 💃 + ShortCodes + + :dancer: + :woman_dancing: + + + Categories + + Person Activity + + + + + Character + 🕴️ + ShortCodes + + :business_suit_levitating: + + + + Categories + + Person Activity + + + + + Character + 👯‍♂️ + ShortCodes + + :dancing_men: + + + + Categories + + Person Activity + + + + + Character + 🧖 + ShortCodes + + :sauna_person: + + + + Categories + + Person Activity + + + + + Character + 🧖‍♀️ + ShortCodes + + :sauna_woman: + + + + Categories + + Person Activity + + + + + Character + 🧗‍♂️ + ShortCodes + + :climbing_man: + + + + Categories + + Person Activity + + + + + Character + 🤺 + ShortCodes + + :person_fencing: + + + + Categories + + Person Sport + + + + + Character + ⛷️ + ShortCodes + + :skier: + + + + Categories + + Person Sport + + + + + Character + 🏌️ + ShortCodes + + :golfing: + + + + Categories + + Person Sport + + + + + Character + 🏌️‍♀️ + ShortCodes + + :golfing_woman: + + + + Categories + + Person Sport + + + + + Character + 🏄‍♂️ + ShortCodes + + :surfing_man: + + + + Categories + + Person Sport + + + + + Character + 🚣 + ShortCodes + + :rowboat: + + + + Categories + + Person Sport + + + + + Character + 🚣‍♀️ + ShortCodes + + :rowing_woman: + + + + Categories + + Person Sport + + + + + Character + 🏊‍♂️ + ShortCodes + + :swimming_man: + + + + Categories + + Person Sport + + + + + Character + ⛹️ + ShortCodes + + :bouncing_ball_person: + + + + Categories + + Person Sport + + + + + Character + ⛹️‍♀️ + ShortCodes + + :basketball_woman: + :bouncing_ball_woman: + + + Categories + + Person Sport + + + + + Character + 🏋️‍♂️ + ShortCodes + + :weight_lifting_man: + + + + Categories + + Person Sport + + + + + Character + 🚴 + ShortCodes + + :bicyclist: + + + + Categories + + Person Sport + + + + + Character + 🚴‍♀️ + ShortCodes + + :biking_woman: + + + + Categories + + Person Sport + + + + + Character + 🚵‍♂️ + ShortCodes + + :mountain_biking_man: + + + + Categories + + Person Sport + + + + + Character + 🤸 + ShortCodes + + :cartwheeling: + + + + Categories + + Person Sport + + + + + Character + 🤸‍♀️ + ShortCodes + + :woman_cartwheeling: + + + + Categories + + Person Sport + + + + + Character + 🤼‍♂️ + ShortCodes + + :men_wrestling: + + + + Categories + + Person Sport + + + + + Character + 🤽 + ShortCodes + + :water_polo: + + + + Categories + + Person Sport + + + + + Character + 🤽‍♀️ + ShortCodes + + :woman_playing_water_polo: + + + + Categories + + Person Sport + + + + + Character + 🤾‍♂️ + ShortCodes + + :man_playing_handball: + + + + Categories + + Person Sport + + + + + Character + 🤹 + ShortCodes + + :juggling_person: + + + + Categories + + Person Sport + + + + + Character + 🤹‍♀️ + ShortCodes + + :woman_juggling: + + + + Categories + + Person Sport + + + + + Character + 🏇 + ShortCodes + + :horse_racing: + + + + Categories + + Person Sport + + + + + Character + 🏂 + ShortCodes + + :snowboarder: + + + + Categories + + Person Sport + + + + + Character + 🏌️‍♂️ + ShortCodes + + :golfing_man: + + + + Categories + + Person Sport + + + + + Character + 🏄 + ShortCodes + + :surfer: + + + + Categories + + Person Sport + + + + + Character + 🏄‍♀️ + ShortCodes + + :surfing_woman: + + + + Categories + + Person Sport + + + + + Character + 🚣‍♂️ + ShortCodes + + :rowing_man: + + + + Categories + + Person Sport + + + + + Character + 🏊 + ShortCodes + + :swimmer: + + + + Categories + + Person Sport + + + + + Character + 🏊‍♀️ + ShortCodes + + :swimming_woman: + + + + Categories + + Person Sport + + + + + Character + ⛹️‍♂️ + ShortCodes + + :basketball_man: + :bouncing_ball_man: + + + Categories + + Person Sport + + + + + Character + 🏋️ + ShortCodes + + :weight_lifting: + + + + Categories + + Person Sport + + + + + Character + 🏋️‍♀️ + ShortCodes + + :weight_lifting_woman: + + + + Categories + + Person Sport + + + + + Character + 🚴‍♂️ + ShortCodes + + :biking_man: + + + + Categories + + Person Sport + + + + + Character + 🚵 + ShortCodes + + :mountain_bicyclist: + + + + Categories + + Person Sport + + + + + Character + 🚵‍♀️ + ShortCodes + + :mountain_biking_woman: + + + + Categories + + Person Sport + + + + + Character + 🤸‍♂️ + ShortCodes + + :man_cartwheeling: + + + + Categories + + Person Sport + + + + + Character + 🤼 + ShortCodes + + :wrestling: + + + + Categories + + Person Sport + + + + + Character + 🤼‍♀️ + ShortCodes + + :women_wrestling: + + + + Categories + + Person Sport + + + + + Character + 🤽‍♂️ + ShortCodes + + :man_playing_water_polo: + + + + Categories + + Person Sport + + + + + Character + 🤾 + ShortCodes + + :handball_person: + + + + Categories + + Person Sport + + + + + Character + 🤾‍♀️ + ShortCodes + + :woman_playing_handball: + + + + Categories + + Person Sport + + + + + Character + 🤹‍♂️ + ShortCodes + + :man_juggling: + + + + Categories + + Person Sport + + + + + Character + 🧘 + ShortCodes + + :lotus_position: + + + + Categories + + Person Resting + + + + + Character + 🧘‍♀️ + ShortCodes + + :lotus_position_woman: + + + + Categories + + Person Resting + + + + + Character + 🛌 + ShortCodes + + :sleeping_bed: + + + + Categories + + Person Resting + + + + + Character + 🧘‍♂️ + ShortCodes + + :lotus_position_man: + + + + Categories + + Person Resting + + + + + Character + 🛀 + ShortCodes + + :bath: + + + + Categories + + Person Resting + + + + + Character + 🧑‍🤝‍🧑 + ShortCodes + + :people_holding_hands: + + + + Categories + + Person + Family + + + + Character + 👫 + ShortCodes + + :couple: + + + + Categories + + Person + Family + + + + Character + 💏 + ShortCodes + + :couplekiss: + + + + Categories + + Person + Family + + + + Character + 👨‍❤️‍💋‍👨 + ShortCodes + + :couplekiss_man_man: + + + + Categories + + Person + Family + + + + Character + 💑 + ShortCodes + + :couple_with_heart: + + + + Categories + + Person + Family + + + + Character + 👨‍❤️‍👨 + ShortCodes + + :couple_with_heart_man_man: + + + + Categories + + Person + Family + + + + Character + 👪 + ShortCodes + + :family: + + + + Categories + + Person + Family + + + + Character + 👨‍👩‍👧 + ShortCodes + + :family_man_woman_girl: + + + + Categories + + Person + Family + + + + Character + 👨‍👩‍👦‍👦 + ShortCodes + + :family_man_woman_boy_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👨‍👦 + ShortCodes + + :family_man_man_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👨‍👧‍👦 + ShortCodes + + :family_man_man_girl_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👨‍👧‍👧 + ShortCodes + + :family_man_man_girl_girl: + + + + Categories + + Person + Family + + + + Character + 👩‍👩‍👧 + ShortCodes + + :family_woman_woman_girl: + + + + Categories + + Person + Family + + + + Character + 👩‍👩‍👦‍👦 + ShortCodes + + :family_woman_woman_boy_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👦 + ShortCodes + + :family_man_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👧 + ShortCodes + + :family_man_girl: + + + + Categories + + Person + Family + + + + Character + 👨‍👧‍👧 + ShortCodes + + :family_man_girl_girl: + + + + Categories + + Person + Family + + + + Character + 👩‍👦‍👦 + ShortCodes + + :family_woman_boy_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👧‍👦 + ShortCodes + + :family_woman_girl_boy: + + + + Categories + + Person + Family + + + + Character + 👭 + ShortCodes + + :two_women_holding_hands: + + + + Categories + + Person + Family + + + + Character + 👬 + ShortCodes + + :two_men_holding_hands: + + + + Categories + + Person + Family + + + + Character + 👩‍❤️‍💋‍👨 + ShortCodes + + :couplekiss_man_woman: + + + + Categories + + Person + Family + + + + Character + 👩‍❤️‍💋‍👩 + ShortCodes + + :couplekiss_woman_woman: + + + + Categories + + Person + Family + + + + Character + 👩‍❤️‍👨 + ShortCodes + + :couple_with_heart_woman_man: + + + + Categories + + Person + Family + + + + Character + 👩‍❤️‍👩 + ShortCodes + + :couple_with_heart_woman_woman: + + + + Categories + + Person + Family + + + + Character + 👨‍👩‍👦 + ShortCodes + + :family_man_woman_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👩‍👧‍👦 + ShortCodes + + :family_man_woman_girl_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👩‍👧‍👧 + ShortCodes + + :family_man_woman_girl_girl: + + + + Categories + + Person + Family + + + + Character + 👨‍👨‍👧 + ShortCodes + + :family_man_man_girl: + + + + Categories + + Person + Family + + + + Character + 👨‍👨‍👦‍👦 + ShortCodes + + :family_man_man_boy_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👩‍👦 + ShortCodes + + :family_woman_woman_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👩‍👧‍👦 + ShortCodes + + :family_woman_woman_girl_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👩‍👧‍👧 + ShortCodes + + :family_woman_woman_girl_girl: + + + + Categories + + Person + Family + + + + Character + 👨‍👦‍👦 + ShortCodes + + :family_man_boy_boy: + + + + Categories + + Person + Family + + + + Character + 👨‍👧‍👦 + ShortCodes + + :family_man_girl_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👦 + ShortCodes + + :family_woman_boy: + + + + Categories + + Person + Family + + + + Character + 👩‍👧 + ShortCodes + + :family_woman_girl: + + + + Categories + + Person + Family + + + + Character + 👩‍👧‍👧 + ShortCodes + + :family_woman_girl_girl: + + + + Categories + + Person + Family + + + + Character + 🗣️ + ShortCodes + + :speaking_head: + + + + Categories + + Person Symbol + + + + + Character + 👥 + ShortCodes + + :busts_in_silhouette: + + + + Categories + + Person Symbol + + + + + Character + 👣 + ShortCodes + + :footprints: + + + + Categories + + Person Symbol + + + + + Character + 👤 + ShortCodes + + :bust_in_silhouette: + + + + Categories + + Person Symbol + + + + + Character + 🫂 + ShortCodes + + :people_hugging: + + + + Categories + + Person Symbol + + + + + Character + 🐵 + ShortCodes + + :monkey_face: + + + + Categories + + Animal Mammal + + + + + Character + 🦍 + ShortCodes + + :gorilla: + + + + Categories + + Animal Mammal + + + + + Character + 🐶 + ShortCodes + + :dog: + + + + Categories + + Animal Mammal + + + + + Character + 🦮 + ShortCodes + + :guide_dog: + + + + Categories + + Animal Mammal + + + + + Character + 🐩 + ShortCodes + + :poodle: + + + + Categories + + Animal Mammal + + + + + Character + 🦊 + ShortCodes + + :fox_face: + + + + Categories + + Animal Mammal + + + + + Character + 🐱 + ShortCodes + + :cat: + + + + Categories + + Animal Mammal + + + + + Character + 🐈‍⬛ + ShortCodes + + :black_cat: + + + + Categories + + Animal Mammal + + + + + Character + 🐯 + ShortCodes + + :tiger: + + + + Categories + + Animal Mammal + + + + + Character + 🐆 + ShortCodes + + :leopard: + + + + Categories + + Animal Mammal + + + + + Character + 🐎 + ShortCodes + + :racehorse: + + + + Categories + + Animal Mammal + + + + + Character + 🦓 + ShortCodes + + :zebra: + + + + Categories + + Animal Mammal + + + + + Character + 🦬 + ShortCodes + + :bison: + + + + Categories + + Animal Mammal + + + + + Character + 🐂 + ShortCodes + + :ox: + + + + Categories + + Animal Mammal + + + + + Character + 🐄 + ShortCodes + + :cow2: + + + + Categories + + Animal Mammal + + + + + Character + 🐖 + ShortCodes + + :pig2: + + + + Categories + + Animal Mammal + + + + + Character + 🐽 + ShortCodes + + :pig_nose: + + + + Categories + + Animal Mammal + + + + + Character + 🐑 + ShortCodes + + :sheep: + + + + Categories + + Animal Mammal + + + + + Character + 🐪 + ShortCodes + + :dromedary_camel: + + + + Categories + + Animal Mammal + + + + + Character + 🦙 + ShortCodes + + :llama: + + + + Categories + + Animal Mammal + + + + + Character + 🐘 + ShortCodes + + :elephant: + + + + Categories + + Animal Mammal + + + + + Character + 🦏 + ShortCodes + + :rhinoceros: + + + + Categories + + Animal Mammal + + + + + Character + 🐭 + ShortCodes + + :mouse: + + + + Categories + + Animal Mammal + + + + + Character + 🐀 + ShortCodes + + :rat: + + + + Categories + + Animal Mammal + + + + + Character + 🐰 + ShortCodes + + :rabbit: + + + + Categories + + Animal Mammal + + + + + Character + 🐿️ + ShortCodes + + :chipmunk: + + + + Categories + + Animal Mammal + + + + + Character + 🦔 + ShortCodes + + :hedgehog: + + + + Categories + + Animal Mammal + + + + + Character + 🐻 + ShortCodes + + :bear: + + + + Categories + + Animal Mammal + + + + + Character + 🐨 + ShortCodes + + :koala: + + + + Categories + + Animal Mammal + + + + + Character + 🦥 + ShortCodes + + :sloth: + + + + Categories + + Animal Mammal + + + + + Character + 🦨 + ShortCodes + + :skunk: + + + + Categories + + Animal Mammal + + + + + Character + 🦡 + ShortCodes + + :badger: + + + + Categories + + Animal Mammal + + + + + Character + 🐒 + ShortCodes + + :monkey: + + + + Categories + + Animal Mammal + + + + + Character + 🦧 + ShortCodes + + :orangutan: + + + + Categories + + Animal Mammal + + + + + Character + 🐕 + ShortCodes + + :dog2: + + + + Categories + + Animal Mammal + + + + + Character + 🐕‍🦺 + ShortCodes + + :service_dog: + + + + Categories + + Animal Mammal + + + + + Character + 🐺 + ShortCodes + + :wolf: + + + + Categories + + Animal Mammal + + + + + Character + 🦝 + ShortCodes + + :raccoon: + + + + Categories + + Animal Mammal + + + + + Character + 🐈 + ShortCodes + + :cat2: + + + + Categories + + Animal Mammal + + + + + Character + 🦁 + ShortCodes + + :lion: + + + + Categories + + Animal Mammal + + + + + Character + 🐅 + ShortCodes + + :tiger2: + + + + Categories + + Animal Mammal + + + + + Character + 🐴 + ShortCodes + + :horse: + + + + Categories + + Animal Mammal + + + + + Character + 🦄 + ShortCodes + + :unicorn: + + + + Categories + + Animal Mammal + + + + + Character + 🦌 + ShortCodes + + :deer: + + + + Categories + + Animal Mammal + + + + + Character + 🐮 + ShortCodes + + :cow: + + + + Categories + + Animal Mammal + + + + + Character + 🐃 + ShortCodes + + :water_buffalo: + + + + Categories + + Animal Mammal + + + + + Character + 🐷 + ShortCodes + + :pig: + + + + Categories + + Animal Mammal + + + + + Character + 🐗 + ShortCodes + + :boar: + + + + Categories + + Animal Mammal + + + + + Character + 🐏 + ShortCodes + + :ram: + + + + Categories + + Animal Mammal + + + + + Character + 🐐 + ShortCodes + + :goat: + + + + Categories + + Animal Mammal + + + + + Character + 🐫 + ShortCodes + + :camel: + + + + Categories + + Animal Mammal + + + + + Character + 🦒 + ShortCodes + + :giraffe: + + + + Categories + + Animal Mammal + + + + + Character + 🦣 + ShortCodes + + :mammoth: + + + + Categories + + Animal Mammal + + + + + Character + 🦛 + ShortCodes + + :hippopotamus: + + + + Categories + + Animal Mammal + + + + + Character + 🐁 + ShortCodes + + :mouse2: + + + + Categories + + Animal Mammal + + + + + Character + 🐹 + ShortCodes + + :hamster: + + + + Categories + + Animal Mammal + + + + + Character + 🐇 + ShortCodes + + :rabbit2: + + + + Categories + + Animal Mammal + + + + + Character + 🦫 + ShortCodes + + :beaver: + + + + Categories + + Animal Mammal + + + + + Character + 🦇 + ShortCodes + + :bat: + + + + Categories + + Animal Mammal + + + + + Character + 🐻‍❄️ + ShortCodes + + :polar_bear: + + + + Categories + + Animal Mammal + + + + + Character + 🐼 + ShortCodes + + :panda_face: + + + + Categories + + Animal Mammal + + + + + Character + 🦦 + ShortCodes + + :otter: + + + + Categories + + Animal Mammal + + + + + Character + 🦘 + ShortCodes + + :kangaroo: + + + + Categories + + Animal Mammal + + + + + Character + 🐾 + ShortCodes + + :feet: + :paw_prints: + + + Categories + + Animal Mammal + + + + + Character + 🦃 + ShortCodes + + :turkey: + + + + Categories + + Animal Bird + + + + + Character + 🐓 + ShortCodes + + :rooster: + + + + Categories + + Animal Bird + + + + + Character + 🐤 + ShortCodes + + :baby_chick: + + + + Categories + + Animal Bird + + + + + Character + 🐦 + ShortCodes + + :bird: + + + + Categories + + Animal Bird + + + + + Character + 🕊️ + ShortCodes + + :dove: + + + + Categories + + Animal Bird + + + + + Character + 🦆 + ShortCodes + + :duck: + + + + Categories + + Animal Bird + + + + + Character + 🦉 + ShortCodes + + :owl: + + + + Categories + + Animal Bird + + + + + Character + 🪶 + ShortCodes + + :feather: + + + + Categories + + Animal Bird + + + + + Character + 🦚 + ShortCodes + + :peacock: + + + + Categories + + Animal Bird + + + + + Character + 🐔 + ShortCodes + + :chicken: + + + + Categories + + Animal Bird + + + + + Character + 🐣 + ShortCodes + + :hatching_chick: + + + + Categories + + Animal Bird + + + + + Character + 🐥 + ShortCodes + + :hatched_chick: + + + + Categories + + Animal Bird + + + + + Character + 🐧 + ShortCodes + + :penguin: + + + + Categories + + Animal Bird + + + + + Character + 🦅 + ShortCodes + + :eagle: + + + + Categories + + Animal Bird + + + + + Character + 🦢 + ShortCodes + + :swan: + + + + Categories + + Animal Bird + + + + + Character + 🦤 + ShortCodes + + :dodo: + + + + Categories + + Animal Bird + + + + + Character + 🦩 + ShortCodes + + :flamingo: + + + + Categories + + Animal Bird + + + + + Character + 🦜 + ShortCodes + + :parrot: + + + + Categories + + Animal Bird + + + + + Character + 🐸 + ShortCodes + + :frog: + + + + Categories + + Animal Amphibian + + + + + Character + 🐊 + ShortCodes + + :crocodile: + + + + Categories + + Animal Reptile + + + + + Character + 🦎 + ShortCodes + + :lizard: + + + + Categories + + Animal Reptile + + + + + Character + 🐲 + ShortCodes + + :dragon_face: + + + + Categories + + Animal Reptile + + + + + Character + 🦕 + ShortCodes + + :sauropod: + + + + Categories + + Animal Reptile + + + + + Character + 🐢 + ShortCodes + + :turtle: + + + + Categories + + Animal Reptile + + + + + Character + 🐍 + ShortCodes + + :snake: + + + + Categories + + Animal Reptile + + + + + Character + 🐉 + ShortCodes + + :dragon: + + + + Categories + + Animal Reptile + + + + + Character + 🦖 + ShortCodes + + :t-rex: + + + + Categories + + Animal Reptile + + + + + Character + 🐳 + ShortCodes + + :whale: + + + + Categories + + Animal Marine + + + + + Character + 🐬 + ShortCodes + + :dolphin: + :flipper: + + + Categories + + Animal Marine + + + + + Character + 🐟 + ShortCodes + + :fish: + + + + Categories + + Animal Marine + + + + + Character + 🐡 + ShortCodes + + :blowfish: + + + + Categories + + Animal Marine + + + + + Character + 🐙 + ShortCodes + + :octopus: + + + + Categories + + Animal Marine + + + + + Character + 🐋 + ShortCodes + + :whale2: + + + + Categories + + Animal Marine + + + + + Character + 🦭 + ShortCodes + + :seal: + + + + Categories + + Animal Marine + + + + + Character + 🐠 + ShortCodes + + :tropical_fish: + + + + Categories + + Animal Marine + + + + + Character + 🦈 + ShortCodes + + :shark: + + + + Categories + + Animal Marine + + + + + Character + 🐚 + ShortCodes + + :shell: + + + + Categories + + Animal Marine + + + + + Character + 🐌 + ShortCodes + + :snail: + + + + Categories + + Animal Bug + + + + + Character + 🐛 + ShortCodes + + :bug: + + + + Categories + + Animal Bug + + + + + Character + 🐝 + ShortCodes + + :bee: + :honeybee: + + + Categories + + Animal Bug + + + + + Character + 🐞 + ShortCodes + + :lady_beetle: + + + + Categories + + Animal Bug + + + + + Character + 🪳 + ShortCodes + + :cockroach: + + + + Categories + + Animal Bug + + + + + Character + 🕸️ + ShortCodes + + :spider_web: + + + + Categories + + Animal Bug + + + + + Character + 🦟 + ShortCodes + + :mosquito: + + + + Categories + + Animal Bug + + + + + Character + 🪱 + ShortCodes + + :worm: + + + + Categories + + Animal Bug + + + + + Character + 🦋 + ShortCodes + + :butterfly: + + + + Categories + + Animal Bug + + + + + Character + 🐜 + ShortCodes + + :ant: + + + + Categories + + Animal Bug + + + + + Character + 🪲 + ShortCodes + + :beetle: + + + + Categories + + Animal Bug + + + + + Character + 🦗 + ShortCodes + + :cricket: + + + + Categories + + Animal Bug + + + + + Character + 🕷️ + ShortCodes + + :spider: + + + + Categories + + Animal Bug + + + + + Character + 🦂 + ShortCodes + + :scorpion: + + + + Categories + + Animal Bug + + + + + Character + 🪰 + ShortCodes + + :fly: + + + + Categories + + Animal Bug + + + + + Character + 🦠 + ShortCodes + + :microbe: + + + + Categories + + Animal Bug + + + + + Character + 💐 + ShortCodes + + :bouquet: + + + + Categories + + Plant Flower + + + + + Character + 💮 + ShortCodes + + :white_flower: + + + + Categories + + Plant Flower + + + + + Character + 🌹 + ShortCodes + + :rose: + + + + Categories + + Plant Flower + + + + + Character + 🌺 + ShortCodes + + :hibiscus: + + + + Categories + + Plant Flower + + + + + Character + 🌼 + ShortCodes + + :blossom: + + + + Categories + + Plant Flower + + + + + Character + 🌸 + ShortCodes + + :cherry_blossom: + + + + Categories + + Plant Flower + + + + + Character + 🏵️ + ShortCodes + + :rosette: + + + + Categories + + Plant Flower + + + + + Character + 🥀 + ShortCodes + + :wilted_flower: + + + + Categories + + Plant Flower + + + + + Character + 🌻 + ShortCodes + + :sunflower: + + + + Categories + + Plant Flower + + + + + Character + 🌷 + ShortCodes + + :tulip: + + + + Categories + + Plant Flower + + + + + Character + 🌱 + ShortCodes + + :seedling: + + + + Categories + + Plant Other + + + + + Character + 🌲 + ShortCodes + + :evergreen_tree: + + + + Categories + + Plant Other + + + + + Character + 🌴 + ShortCodes + + :palm_tree: + + + + Categories + + Plant Other + + + + + Character + 🌾 + ShortCodes + + :ear_of_rice: + + + + Categories + + Plant Other + + + + + Character + ☘️ + ShortCodes + + :shamrock: + + + + Categories + + Plant Other + + + + + Character + 🍁 + ShortCodes + + :maple_leaf: + + + + Categories + + Plant Other + + + + + Character + 🍃 + ShortCodes + + :leaves: + + + + Categories + + Plant Other + + + + + Character + 🪴 + ShortCodes + + :potted_plant: + + + + Categories + + Plant Other + + + + + Character + 🌳 + ShortCodes + + :deciduous_tree: + + + + Categories + + Plant Other + + + + + Character + 🌵 + ShortCodes + + :cactus: + + + + Categories + + Plant Other + + + + + Character + 🌿 + ShortCodes + + :herb: + + + + Categories + + Plant Other + + + + + Character + 🍀 + ShortCodes + + :four_leaf_clover: + + + + Categories + + Plant Other + + + + + Character + 🍂 + ShortCodes + + :fallen_leaf: + + + + Categories + + Plant Other + + + + + Character + 🍇 + ShortCodes + + :grapes: + + + + Categories + + Food Fruit + + + + + Character + 🍉 + ShortCodes + + :watermelon: + + + + Categories + + Food Fruit + + + + + Character + 🍋 + ShortCodes + + :lemon: + + + + Categories + + Food Fruit + + + + + Character + 🍍 + ShortCodes + + :pineapple: + + + + Categories + + Food Fruit + + + + + Character + 🍎 + ShortCodes + + :apple: + + + + Categories + + Food Fruit + + + + + Character + 🍐 + ShortCodes + + :pear: + + + + Categories + + Food Fruit + + + + + Character + 🍒 + ShortCodes + + :cherries: + + + + Categories + + Food Fruit + + + + + Character + 🫐 + ShortCodes + + :blueberries: + + + + Categories + + Food Fruit + + + + + Character + 🍅 + ShortCodes + + :tomato: + + + + Categories + + Food Fruit + + + + + Character + 🥥 + ShortCodes + + :coconut: + + + + Categories + + Food Fruit + + + + + Character + 🍈 + ShortCodes + + :melon: + + + + Categories + + Food Fruit + + + + + Character + 🍊 + ShortCodes + + :mandarin: + :orange: + :tangerine: + + Categories + + Food Fruit + + + + + Character + 🍌 + ShortCodes + + :banana: + + + + Categories + + Food Fruit + + + + + Character + 🥭 + ShortCodes + + :mango: + + + + Categories + + Food Fruit + + + + + Character + 🍏 + ShortCodes + + :green_apple: + + + + Categories + + Food Fruit + + + + + Character + 🍑 + ShortCodes + + :peach: + + + + Categories + + Food Fruit + + + + + Character + 🍓 + ShortCodes + + :strawberry: + + + + Categories + + Food Fruit + + + + + Character + 🥝 + ShortCodes + + :kiwi_fruit: + + + + Categories + + Food Fruit + + + + + Character + 🫒 + ShortCodes + + :olive: + + + + Categories + + Food Fruit + + + + + Character + 🥑 + ShortCodes + + :avocado: + + + + Categories + + Food Vegetable + + + + + Character + 🥔 + ShortCodes + + :potato: + + + + Categories + + Food Vegetable + + + + + Character + 🌽 + ShortCodes + + :corn: + + + + Categories + + Food Vegetable + + + + + Character + 🫑 + ShortCodes + + :bell_pepper: + + + + Categories + + Food Vegetable + + + + + Character + 🥬 + ShortCodes + + :leafy_green: + + + + Categories + + Food Vegetable + + + + + Character + 🧄 + ShortCodes + + :garlic: + + + + Categories + + Food Vegetable + + + + + Character + 🍄 + ShortCodes + + :mushroom: + + + + Categories + + Food Vegetable + + + + + Character + 🌰 + ShortCodes + + :chestnut: + + + + Categories + + Food Vegetable + + + + + Character + 🍆 + ShortCodes + + :eggplant: + + + + Categories + + Food Vegetable + + + + + Character + 🥕 + ShortCodes + + :carrot: + + + + Categories + + Food Vegetable + + + + + Character + 🌶️ + ShortCodes + + :hot_pepper: + + + + Categories + + Food Vegetable + + + + + Character + 🥒 + ShortCodes + + :cucumber: + + + + Categories + + Food Vegetable + + + + + Character + 🥦 + ShortCodes + + :broccoli: + + + + Categories + + Food Vegetable + + + + + Character + 🧅 + ShortCodes + + :onion: + + + + Categories + + Food Vegetable + + + + + Character + 🥜 + ShortCodes + + :peanuts: + + + + Categories + + Food Vegetable + + + + + Character + 🍞 + ShortCodes + + :bread: + + + + Categories + + Food Prepared + + + + + Character + 🥖 + ShortCodes + + :baguette_bread: + + + + Categories + + Food Prepared + + + + + Character + 🥨 + ShortCodes + + :pretzel: + + + + Categories + + Food Prepared + + + + + Character + 🥞 + ShortCodes + + :pancakes: + + + + Categories + + Food Prepared + + + + + Character + 🧀 + ShortCodes + + :cheese: + + + + Categories + + Food Prepared + + + + + Character + 🍗 + ShortCodes + + :poultry_leg: + + + + Categories + + Food Prepared + + + + + Character + 🥓 + ShortCodes + + :bacon: + + + + Categories + + Food Prepared + + + + + Character + 🍟 + ShortCodes + + :fries: + + + + Categories + + Food Prepared + + + + + Character + 🌭 + ShortCodes + + :hotdog: + + + + Categories + + Food Prepared + + + + + Character + 🌮 + ShortCodes + + :taco: + + + + Categories + + Food Prepared + + + + + Character + 🫔 + ShortCodes + + :tamale: + + + + Categories + + Food Prepared + + + + + Character + 🧆 + ShortCodes + + :falafel: + + + + Categories + + Food Prepared + + + + + Character + 🍳 + ShortCodes + + :fried_egg: + + + + Categories + + Food Prepared + + + + + Character + 🍲 + ShortCodes + + :stew: + + + + Categories + + Food Prepared + + + + + Character + 🥣 + ShortCodes + + :bowl_with_spoon: + + + + Categories + + Food Prepared + + + + + Character + 🍿 + ShortCodes + + :popcorn: + + + + Categories + + Food Prepared + + + + + Character + 🧂 + ShortCodes + + :salt: + + + + Categories + + Food Prepared + + + + + Character + 🥐 + ShortCodes + + :croissant: + + + + Categories + + Food Prepared + + + + + Character + 🫓 + ShortCodes + + :flatbread: + + + + Categories + + Food Prepared + + + + + Character + 🥯 + ShortCodes + + :bagel: + + + + Categories + + Food Prepared + + + + + Character + 🧇 + ShortCodes + + :waffle: + + + + Categories + + Food Prepared + + + + + Character + 🍖 + ShortCodes + + :meat_on_bone: + + + + Categories + + Food Prepared + + + + + Character + 🥩 + ShortCodes + + :cut_of_meat: + + + + Categories + + Food Prepared + + + + + Character + 🍔 + ShortCodes + + :hamburger: + + + + Categories + + Food Prepared + + + + + Character + 🍕 + ShortCodes + + :pizza: + + + + Categories + + Food Prepared + + + + + Character + 🥪 + ShortCodes + + :sandwich: + + + + Categories + + Food Prepared + + + + + Character + 🌯 + ShortCodes + + :burrito: + + + + Categories + + Food Prepared + + + + + Character + 🥙 + ShortCodes + + :stuffed_flatbread: + + + + Categories + + Food Prepared + + + + + Character + 🥚 + ShortCodes + + :egg: + + + + Categories + + Food Prepared + + + + + Character + 🥘 + ShortCodes + + :shallow_pan_of_food: + + + + Categories + + Food Prepared + + + + + Character + 🫕 + ShortCodes + + :fondue: + + + + Categories + + Food Prepared + + + + + Character + 🥗 + ShortCodes + + :green_salad: + + + + Categories + + Food Prepared + + + + + Character + 🧈 + ShortCodes + + :butter: + + + + Categories + + Food Prepared + + + + + Character + 🥫 + ShortCodes + + :canned_food: + + + + Categories + + Food Prepared + + + + + Character + 🍱 + ShortCodes + + :bento: + + + + Categories + + Food Asian + + + + + Character + 🍙 + ShortCodes + + :rice_ball: + + + + Categories + + Food Asian + + + + + Character + 🍛 + ShortCodes + + :curry: + + + + Categories + + Food Asian + + + + + Character + 🍝 + ShortCodes + + :spaghetti: + + + + Categories + + Food Asian + + + + + Character + 🍢 + ShortCodes + + :oden: + + + + Categories + + Food Asian + + + + + Character + 🍤 + ShortCodes + + :fried_shrimp: + + + + Categories + + Food Asian + + + + + Character + 🥮 + ShortCodes + + :moon_cake: + + + + Categories + + Food Asian + + + + + Character + 🥟 + ShortCodes + + :dumpling: + + + + Categories + + Food Asian + + + + + Character + 🥡 + ShortCodes + + :takeout_box: + + + + Categories + + Food Asian + + + + + Character + 🍘 + ShortCodes + + :rice_cracker: + + + + Categories + + Food Asian + + + + + Character + 🍚 + ShortCodes + + :rice: + + + + Categories + + Food Asian + + + + + Character + 🍜 + ShortCodes + + :ramen: + + + + Categories + + Food Asian + + + + + Character + 🍠 + ShortCodes + + :sweet_potato: + + + + Categories + + Food Asian + + + + + Character + 🍣 + ShortCodes + + :sushi: + + + + Categories + + Food Asian + + + + + Character + 🍥 + ShortCodes + + :fish_cake: + + + + Categories + + Food Asian + + + + + Character + 🍡 + ShortCodes + + :dango: + + + + Categories + + Food Asian + + + + + Character + 🥠 + ShortCodes + + :fortune_cookie: + + + + Categories + + Food Asian + + + + + -- cgit v1.2.3 From 24bd7b2311e6fdd8bcf0a223d6dafaf4266ca4c7 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 6 Nov 2022 16:25:35 +0100 Subject: Add support for OT-SVG fonts --- indra/cmake/ViewerMiscLibs.cmake | 1 + indra/llrender/CMakeLists.txt | 2 + indra/llrender/llfontfreetype.cpp | 13 +++ indra/llrender/llfontfreetypesvg.cpp | 205 +++++++++++++++++++++++++++++++++++ indra/llrender/llfontfreetypesvg.h | 54 +++++++++ 5 files changed, 275 insertions(+) create mode 100644 indra/llrender/llfontfreetypesvg.cpp create mode 100644 indra/llrender/llfontfreetypesvg.h (limited to 'indra') diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index f213de100c..aa204a7406 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -11,3 +11,4 @@ if (NOT USESYSTEMLIBS) endif(NOT USESYSTEMLIBS) use_prebuilt_binary(fonts) +use_prebuilt_binary(nanosvg) \ No newline at end of file diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 47e7ad915b..282a5c70ad 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -35,6 +35,7 @@ set(llrender_SOURCE_FILES llcubemap.cpp llfontbitmapcache.cpp llfontfreetype.cpp + llfontfreetypesvg.cpp llfontgl.cpp llfontregistry.cpp llgl.cpp @@ -62,6 +63,7 @@ set(llrender_HEADER_FILES llcubemap.h llfontgl.h llfontfreetype.h + llfontfreetypesvg.h llfontbitmapcache.h llfontregistry.h llgl.h diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 25740a5f87..d3a49339da 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -34,6 +34,7 @@ #ifdef LL_WINDOWS #include #endif +#include "llfontfreetypesvg.h" // For some reason, this won't work if it's not wrapped in the ifdef #ifdef FT_FREETYPE_H @@ -51,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; @@ -83,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() 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 +#define NANOSVGRAST_IMPLEMENTATION +#include + +#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(objectp); + + LLSvgRenderData* pData = static_cast(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(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(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(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 +#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); +}; -- cgit v1.2.3 From ec6c4f102f8b23e0c79dd2c1c0ecbad54f019566 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 6 Nov 2022 16:30:44 +0100 Subject: Switch to using the Twemoji OT-SVG font --- indra/newview/skins/default/xui/en/fonts.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 681f670f08..40045625fd 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -3,7 +3,7 @@ DejaVuSans.ttf - Twemoji.ttf + TwemojiSVG.ttf meiryo.TTC MSGOTHIC.TTC @@ -72,7 +72,7 @@ - Twemoji.ttf + TwemojiSVG.ttf Date: Tue, 8 Nov 2022 00:16:58 +0100 Subject: [FIXED] Various minor issues - Typing :+1: doesn't replace the short code with the thumbs-up emoji - Moving the mouse over the emoji complete panel highlights the wrong emoji when mScrollPos > 0 - Emoji complete panel is missing attributes - Crash when attempting to show the tooltip for an emoji text segment - Emoji autocomplete panel can sometimes show empty (type ':cat', select the heart eyed one, Ctrl-Z and then type 2 which should show the emoji for :cat2 but shows an empty square instead) --- indra/llui/llemojidictionary.cpp | 8 ++++---- indra/llui/llemojidictionary.h | 4 ++-- indra/llui/llemojihelper.cpp | 3 ++- indra/newview/llpanelemojicomplete.cpp | 4 ++-- indra/newview/skins/default/xui/en/widgets/emoji_complete.xml | 3 +++ 5 files changed, 13 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index c31638b0bf..b70a9b2e7a 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -178,22 +178,22 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromShortCode(const std::string& short_code) const { const auto it = mShortCode2Descr.find(short_code); - return (mShortCode2Descr.end() != it) ? &it->second : nullptr; + 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; + 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())); + mEmoji2Descr.insert(std::make_pair(descr.Character, &mEmojis.back())); for (const std::string& shortCode : descr.ShortCodes) { - mShortCode2Descr.insert(std::make_pair(shortCode, mEmojis.back())); + mShortCode2Descr.insert(std::make_pair(shortCode, &mEmojis.back())); } } diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 0cde663719..46a61f1cd7 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -66,8 +66,8 @@ private: private: std::list mEmojis; - std::map mEmoji2Descr; - std::map mShortCode2Descr; + std::map mEmoji2Descr; + std::map mShortCode2Descr; }; // ============================================================================ diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 32471e59a8..1e4c19a183 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -57,7 +57,8 @@ bool LLEmojiHelper::isActive(const LLUICtrl* ctrl_p) const // static bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S32* pShortCodePos) { - S32 shortCodePos = cursorPos; + // 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) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index a7058a6724..f890a14e8e 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -146,9 +146,9 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) { llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0; - size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint); + size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0; if (mAutoSize) @@ -168,7 +168,7 @@ size_t LLPanelEmojiComplete::posToIndex(S32 x, S32 y) const { if (mRenderRect.pointInRect(x, y)) { - return llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); + return mScrollPos + llmin((size_t)x / mEmojiWidth, mEmojis.size() - 1); } return npos; } diff --git a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml index f35105ff7e..370f1d174e 100644 --- a/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml +++ b/indra/newview/skins/default/xui/en/widgets/emoji_complete.xml @@ -1,7 +1,10 @@ -- cgit v1.2.3 From 17a3924a28770e6910022ad8f627bb8e2b667730 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Tue, 8 Nov 2022 01:10:09 +0100 Subject: Add proper mouse down handler to the emoji complete panel -> the previous commit didn't properly set mFrontChild after restoring the topmost floaters -> additionally we don't want mouse clicks in "can't steal focus from frontmost" floaters to set focus to them --- indra/llui/llfloater.cpp | 23 ++++++++++++++--------- indra/newview/llpanelemojicomplete.cpp | 30 +++++++++++++++++++++++++++--- indra/newview/llpanelemojicomplete.h | 3 +++ 3 files changed, 44 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 04f6b11b7c..6f341bc0cd 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2486,7 +2486,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); } @@ -3042,24 +3042,29 @@ void LLFloaterView::syncFloaterTabOrder() if (mFrontChild != floaterp) { // Grab a list of the top floaters that want to stay on top of the focused floater - std::list listTop; + std::list listTop; if (mFrontChild && !mFrontChild->canFocusStealFrontmost()) { - for (LLView* childfloaterp : *getChildList()) + for (LLView* childp : *getChildList()) { - if (static_cast(childfloaterp)->canFocusStealFrontmost()) + LLFloater* child_floaterp = static_cast(childp); + if (child_floaterp->canFocusStealFrontmost()) break; - listTop.push_back(childfloaterp); + listTop.push_back(child_floaterp); } } bringToFront(floaterp, FALSE); // Restore top floaters - for (LLView* childp :listTop) - { - sendChildToFront(childp); - } + if (!listTop.empty()) + { + for (LLView* childp : listTop) + { + sendChildToFront(childp); + } + mFrontChild = listTop.back(); + } } break; diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index f890a14e8e..8b89e3aa14 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -120,9 +120,6 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent case KEY_RETURN: if (!mEmojis.empty()) { - LLWString wstr; - wstr.push_back(mEmojis.at(mCurSelected)); - setValue(wstring_to_utf8str(wstr)); onCommit(); handled = true; } @@ -137,6 +134,33 @@ BOOL LLPanelEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_parent 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); diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index 138cc465ba..2116b350be 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -56,6 +56,9 @@ public: 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: -- cgit v1.2.3 From f3e7c7454f6647aa09f220baa20c9bbc7480a37b Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Tue, 8 Nov 2022 01:14:10 +0100 Subject: Enable color emojis (and the emoji helper) on the chat history and editor --- indra/newview/llchathistory.cpp | 2 ++ indra/newview/skins/default/xui/en/widgets/chat_editor.xml | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index c110e0d815..f07d4658f9 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -1010,6 +1010,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(editor_params, this); mEditor->setIsFriendCallback(LLAvatarActions::isFriend); mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0)); 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 @@ + show_context_menu="true" + show_emoji_helper="true" + use_color="true" + /> -- cgit v1.2.3 From 62d62abe9c35066bb7bb29155046311245854563 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 9 Nov 2022 00:08:43 +0100 Subject: [FIXED] Using the Windows emoji picker or pasting text containing emojis doesn't create emoji segments (=emoji size is same size as the text size) -> Partial revert of 063fe59 --- indra/llui/lltextbase.cpp | 55 +++++++++++++++++++---------------------------- indra/llui/lltextbase.h | 1 - 2 files changed, 22 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b88c7ced40..28165aa1ef 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -834,6 +834,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() ) @@ -2303,36 +2322,6 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s insertStringNoUndo(getLength(), widget_wide_text, &segments); } -void LLTextBase::createTextWithEmojiSegment(const LLWString& text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments) -{ - LLStyleSP emoji_style; - - S32 text_start = 0, text_kitty = 0, text_len = text.size(); - for (; text_kitty < text_len; text_kitty++) - { - if (LLStringOps::isEmoji(text[text_kitty])) - { - if (text_kitty > text_start) - { - segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_kitty, *this)); - } - - if (!emoji_style) - { - emoji_style = new LLStyle(*style); - emoji_style->setFont(LLFontGL::getFontEmoji()); - } - segments.push_back(new LLEmojiTextSegment(emoji_style, segment_start + text_kitty, segment_start + text_kitty + 1, *this)); - text_start = text_kitty + 1; - } - } - - if (text_start < text_len) - { - segments.push_back(new LLNormalTextSegment(style, segment_start + text_start, segment_start + text_len, *this)); - } -} - void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) { // Save old state @@ -2365,7 +2354,6 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp; - segment_vec_t segments; if (underline_on_hover_only || mSkipLinkUnderline) { highlight_params.font.style("NORMAL"); @@ -2374,8 +2362,9 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - createTextWithEmojiSegment(wide_text, cur_length, sp, segments); + segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); } + segment_vec_t segments; segments.push_back(segmentp); insertStringNoUndo(cur_length, wide_text, &segments); } @@ -2398,7 +2387,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } else { - createTextWithEmojiSegment(wide_text, segment_start, sp, segments); + segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this )); } insertStringNoUndo(getLength(), wide_text, &segments); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 31e9f16110..a047db25b2 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -641,7 +641,6 @@ protected: void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); - void createTextWithEmojiSegment(const LLWString& wide_text, S32 segment_start, LLStyleConstSP style, segment_vec_t& segments); S32 normalizeUri(std::string& uri); protected: -- cgit v1.2.3 From 1727a31db0e3434adec087d6442fc5eca0ea68cf Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 9 Nov 2022 00:11:22 +0100 Subject: Show color emojis and emoji helper in notecards --- indra/newview/skins/default/xui/en/floater_preview_notecard.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') 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... -- cgit v1.2.3 From b5033a8859b38df045cc74e074aaee864985f145 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 9 Nov 2022 00:14:51 +0100 Subject: Enable color on HUD text --- indra/newview/llhudrender.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') 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(); -- cgit v1.2.3 From f9fbd0333abb474ed265e1be67b2c5b1a4174444 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Mon, 23 Jan 2023 15:10:17 -0800 Subject: DRTVWR-489-emoji: Update the machinery that copies over the ICU4C DLLs into the right place in Windows builds --- indra/cmake/Copy3rdPartyLibs.cmake | 9 +++++++++ indra/newview/viewer_manifest.py | 10 ++++++++++ 2 files changed, 19 insertions(+) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index ff705101de..439bec865c 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -61,6 +61,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/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8cc1cc5bb4..26983bbba8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -517,6 +517,16 @@ class WindowsManifest(ViewerManifest): self.path("OpenAL32.dll") self.path("alut.dll") + # For ICU4C + self.path("") + self.path("icudt48.dll") + self.path("icuin48.dll") + self.path("icuio48.dll") + self.path("icule48.dll") + self.path("iculx48.dll") + self.path("icutu48.dll") + self.path("icuuc48.dll") + # For textures self.path("openjpeg.dll") -- cgit v1.2.3 From a3e80762f1724388fc6e892a337895966cf942e8 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Tue, 24 Jan 2023 11:07:56 -0800 Subject: DRTVWR-489-emoji: Fix a warning when packaging Viewer installer. TeamCity builds fail because of 'compiler error' in NSIS - wondering if this warning triggers the error (it doesn't locally) - yes, grasphing at straws --- indra/newview/installers/windows/lang_zh.nsi | Bin 10144 -> 10154 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'indra') diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index 7922d9df52..0985663041 100755 Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ -- cgit v1.2.3 From 054f57151541654ab8b68fc935e184377747ab75 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Tue, 24 Jan 2023 13:14:25 -0800 Subject: DRTVWR-489-emoji: Trying to get to the bottom of a TeamCity build failure with access to TeramCity - one theory is that the extra size of these DLLs consumes too much disk space and results in the NSIS internal compiler error we observe - removing these tempoorarily to see what difference that makes --- indra/newview/viewer_manifest.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 26983bbba8..76cd4ce049 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -518,14 +518,13 @@ class WindowsManifest(ViewerManifest): self.path("alut.dll") # For ICU4C - self.path("") - self.path("icudt48.dll") - self.path("icuin48.dll") - self.path("icuio48.dll") - self.path("icule48.dll") - self.path("iculx48.dll") - self.path("icutu48.dll") - self.path("icuuc48.dll") + # self.path("icudt48.dll") + # self.path("icuin48.dll") + # self.path("icuio48.dll") + # self.path("icule48.dll") + # self.path("iculx48.dll") + # self.path("icutu48.dll") + # self.path("icuuc48.dll") # For textures self.path("openjpeg.dll") -- cgit v1.2.3 From 5dcdf8330409779591d35c05888efd02e412cf50 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Tue, 24 Jan 2023 16:00:53 -0800 Subject: DRTVWR-489-emoji: Trying to get to the bottom of a TeamCity build failure with access to TeramCity - with all the ICU4C DLLs removed, the viewer builds fine which does suggest a size/disk space issue. Trying with the (porposed) minimum set to see if this helps. Likely it won't because the main one (icudt48.dll) is much, much bigger than the others combined - but we shall see --- indra/newview/viewer_manifest.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 76cd4ce049..60f8cfc26b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -518,13 +518,8 @@ class WindowsManifest(ViewerManifest): self.path("alut.dll") # For ICU4C - # self.path("icudt48.dll") - # self.path("icuin48.dll") - # self.path("icuio48.dll") - # self.path("icule48.dll") - # self.path("iculx48.dll") - # self.path("icutu48.dll") - # self.path("icuuc48.dll") + self.path("icudt48.dll") + self.path("icuuc48.dll") # For textures self.path("openjpeg.dll") -- cgit v1.2.3 From 66f59478d09122ddf43c4ba3445754d1698bf016 Mon Sep 17 00:00:00 2001 From: Callum Linden Date: Wed, 25 Jan 2023 10:57:29 -0800 Subject: DRTVWR-489-emoji: declaring this variable as a U16 leads to a warning (and therefore an error) but only on 32bit Windows builds - 64bit is fine. I don't know why that's the case (should be both surely) but in any case, I think the variable should be declared as a size_t --- indra/newview/llpanelemojicomplete.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index 2116b350be..aa0f806525 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -85,7 +85,7 @@ protected: LLUIImagePtr mSelectedImage; LLWString mEmojis; - U16 mVisibleEmojis = 0; + size_t mVisibleEmojis = 0; size_t mFirstVisible = 0; size_t mScrollPos = 0; size_t mCurSelected = 0; -- cgit v1.2.3 From 3185bdea27b19e155c2ccc03c80624e113d312a6 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 14:45:45 -0800 Subject: DRTVWR-489-emoji: As part of the work to get macOS version of the Viewer working, the flag was introduced to warn (and therefore error out) when a virtual override was not marked with the 'override' keyword. Fixing this up involved a large number of changes and this commit represents just those changes - nothing specially from the DRTVWR-489 viewer --- indra/llappearance/llwearabletype.h | 2 +- indra/llcommon/llcoros.h | 2 +- indra/llcommon/llsingleton.h | 2 +- indra/llinventory/llfoldertype.cpp | 2 +- indra/llinventory/llinventorysettings.cpp | 2 +- indra/llmessage/llexperiencecache.h | 2 +- indra/llmessage/llproxy.h | 2 +- indra/llui/llnotifications.h | 6 +- indra/llui/llspellcheck.h | 2 +- indra/llui/lltextbase.cpp | 21 ---- indra/llui/lltextbase.h | 2 +- indra/llui/lluictrl.h | 2 +- indra/llui/llview.cpp | 4 +- indra/llui/llviewquery.h | 12 +-- indra/newview/llautoreplace.h | 2 +- indra/newview/llchannelmanager.h | 2 +- indra/newview/llchicletbar.h | 4 +- indra/newview/llconversationlog.h | 10 +- indra/newview/llfeaturemanager.h | 2 +- indra/newview/llfriendcard.h | 2 +- indra/newview/llgesturemgr.h | 4 +- indra/newview/llimagefiltersmanager.h | 2 +- indra/newview/llimview.h | 2 +- indra/newview/llmutelist.h | 2 +- indra/newview/llnavigationbar.h | 8 +- indra/newview/lloutfitobserver.h | 2 +- indra/newview/llpaneltopinfobar.h | 6 +- indra/newview/llpathfindingpathtool.h | 18 ++-- indra/newview/llproductinforequest.h | 2 +- indra/newview/llrecentpeople.h | 2 +- indra/newview/llspeakers.h | 4 +- indra/newview/llspeakingindicatormanager.cpp | 2 +- indra/newview/lltoolbrush.h | 20 ++-- indra/newview/lltoolcomp.h | 72 ++++++------- indra/newview/lltooldraganddrop.h | 12 +-- indra/newview/lltoolface.h | 10 +- indra/newview/lltoolfocus.h | 14 +-- indra/newview/lltoolindividual.h | 8 +- indra/newview/lltoolobjpicker.h | 14 +-- indra/newview/lltoolpie.h | 32 +++--- indra/newview/lltoolpipette.h | 8 +- indra/newview/lltoolselectland.h | 16 +-- indra/newview/llversioninfo.h | 2 +- indra/newview/llviewerhelp.h | 10 +- indra/newview/llviewermedia.h | 2 +- indra/newview/llviewermediafocus.h | 16 +-- indra/newview/llviewerparcelaskplay.h | 4 +- indra/newview/llviewerparcelmedia.h | 2 +- indra/newview/llviewerparcelmediaautoplay.h | 2 +- indra/newview/llviewertexturelist.h | 6 +- indra/newview/llvoicechannel.h | 22 ++-- indra/newview/llvoicevivox.h | 146 +++++++++++++-------------- indra/newview/llwearableitemslist.h | 6 +- indra/newview/llwindebug.h | 4 +- 54 files changed, 272 insertions(+), 295 deletions(-) (limited to 'indra') 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 { LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans); ~LLWearableType(); - void initSingleton(); + void initSingleton() override; public: enum EType { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index dbff921f16..a6da94005b 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -92,7 +92,7 @@ class LL_COMMON_API LLCoros: public LLSingleton 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/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(__VA_ARGS__) 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, { 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, { LLSINGLETON(LLSettingsDictionary); - void initSingleton(); + void initSingleton() override; }; LLSettingsDictionary::LLSettingsDictionary() 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 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 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/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 dict_list_t; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index b2c0577604..dff4bf9617 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1997,19 +1997,8 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaini LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) { - static LLPointer index_segment = new LLIndexSegment(); - S32 text_len = 0; - if (!useLabel()) - { - text_len = getLength(); - } - else - { - text_len = mLabel.getWString().length(); - } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -2023,16 +2012,6 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i { static LLPointer index_segment = new LLIndexSegment(); - S32 text_len = 0; - if (!useLabel()) - { - text_len = getLength(); - } - else - { - text_len = mLabel.getWString().length(); - } - // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 7e1f727607..9b3691e404 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -187,7 +187,7 @@ public: 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); + 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) 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 { 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(view)->acceptsTextInput(), TRUE); } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 74abe54690..2b7f05dcda 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1953,7 +1953,7 @@ private: class SortByTabOrder : public LLQuerySorter, public LLSingleton { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 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 LLSINGLETON(LLChannelManager); virtual ~LLChannelManager(); - void cleanupSingleton(); + void cleanupSingleton() override; public: 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/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 mFiltersList; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 326e8f22e3..353373f3b4 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -506,7 +506,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/llmutelist.h b/indra/newview/llmutelist.h index 0d426fbd48..f86c2acd10 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -73,7 +73,7 @@ class LLMuteList : public LLSingleton { 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, public: typedef boost::signals2::signal 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/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 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 event, const LLSD& userdata); + /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) override; void updateAvatarsArrivalTime(uuid_vec_t& uuids); F32 getArrivalTimeByID(const LLUUID& id); 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 @@ -347,7 +347,7 @@ class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton speaker_ids_t; 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 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 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 cfc235b6c2..c9dd39ff4b 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; } static void pickCallback(const LLPickInfo& pick_info); BOOL mouseSteerMode() { return mMouseSteering; } 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 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 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 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 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 { LLSINGLETON(LLVersionInfo); - void initSingleton(); + void initSingleton() override; public: ~LLVersionInfo(); 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 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 { 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 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/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 { 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 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 getUIImageByID(const LLUUID& id, S32 priority); - /*virtual*/ LLPointer getUIImage(const std::string& name, S32 priority); - void cleanUp(); + /*virtual*/ LLPointer getUIImageByID(const LLUUID& id, S32 priority) override; + /*virtual*/ LLPointer getUIImage(const std::string& name, S32 priority) override; + void cleanUp() override; bool initFromFile(); 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 &participants); - virtual bool isParticipant(const LLUUID& speaker_id); + virtual void getParticipantList(std::set &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; //////////////////////////// @@ -134,21 +134,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; //@} @@ -156,59 +156,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 @@ -218,32 +218,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; //@} //@} @@ -754,7 +754,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/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index ba8488b237..602e8f0711 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -413,7 +413,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); @@ -426,7 +426,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); @@ -456,7 +456,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); }; -- cgit v1.2.3 From a804b98e4ed127ce1a11f639babb82574f2e5204 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 17:03:58 -0800 Subject: DRTVWR-489-emoji: A couple of tabs slipped into this file and our new no-tabs coding policy caught it and failed the build --- indra/llui/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 44c61dcdbc..4fc3836248 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -53,8 +53,8 @@ set(llui_SOURCE_FILES lldockcontrol.cpp lldraghandle.cpp lleditmenuhandler.cpp - llemojidictionary.cpp - llemojihelper.cpp + llemojidictionary.cpp + llemojihelper.cpp llf32uictrl.cpp llfiltereditor.cpp llflashtimer.cpp @@ -165,8 +165,8 @@ set(llui_HEADER_FILES lldockablefloater.h lldockcontrol.h lleditmenuhandler.h - llemojidictionary.h - llemojihelper.h + llemojidictionary.h + llemojihelper.h llf32uictrl.h llfiltereditor.h llflashtimer.h -- cgit v1.2.3 From d9e82ab14aaa3e0daceacda8cf72ade379e9caf1 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 17:04:35 -0800 Subject: DRTVWR-489-emoji: Pull in some small changes from Kitty's work to move the macOS build forwards --- indra/cmake/ICU4C.cmake | 4 ++-- indra/llrender/llfontregistry.cpp | 2 +- indra/newview/CMakeLists.txt | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake index 007a9b6937..b51087e0e7 100644 --- a/indra/cmake/ICU4C.cmake +++ b/indra/cmake/ICU4C.cmake @@ -10,8 +10,8 @@ else (USESYSTEMLIBS) use_prebuilt_binary(icu4c) if (WINDOWS) set(ICU4C_LIBRARY icuuc) - #elseif(DARWIN) - # set(ICU4C_LIBRARY ...) + elseif(DARWIN) + set(ICU4C_LIBRARY icuuc) #elseif(LINUX) # set(ICU4C_LIBRARY ...) else() diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 44f2bd4cc5..c9a9ee3a03 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -483,7 +483,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) #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(sys_path + 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. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 36f4680c44..ee55657dd8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -449,7 +449,7 @@ set(viewer_SOURCE_FILES llpaneleditsky.cpp llpaneleditwater.cpp llpaneleditwearable.cpp - llpanelemojicomplete.cpp + llpanelemojicomplete.cpp llpanelenvironment.cpp llpanelexperiencelisteditor.cpp llpanelexperiencelog.cpp @@ -1081,7 +1081,7 @@ set(viewer_HEADER_FILES llpaneleditsky.h llpaneleditwater.h llpaneleditwearable.h - llpanelemojicomplete.h + llpanelemojicomplete.h llpanelenvironment.h llpanelexperiencelisteditor.h llpanelexperiencelog.h @@ -1506,12 +1506,6 @@ if (WINDOWS) set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp) endif(USE_PRECOMPILED_HEADERS) - 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") - # Replace the icons with the appropriate ones for the channel # ('test' is the default) set(ICON_PATH "test") @@ -2087,6 +2081,12 @@ endif (USE_BUGSPLAT) 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}) -- cgit v1.2.3 From 923733e591eb547ad5dfec395ce7d3e8f0468c16 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 18:01:25 -0800 Subject: DRTVWR-489-emoji: missed the override warning/error in the tests... grr... --- indra/llcommon/tests/llsingleton_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 15ffe68e67..49cf76b07e 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 -- cgit v1.2.3 From 6f31fabbc2d082b77c8f09bce30234ec9c506e33 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Thu, 26 Jan 2023 19:17:21 -0800 Subject: DRTVWR-489-emoji: less haste. more speed. Missed another test issue. Rebuilt locally with tests and confirmed it works now --- indra/llcommon/tests/llsingleton_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 49cf76b07e..6f8aaaa0cb 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -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(); -- cgit v1.2.3 From b2f890408e2dc63a0f842273c41c0efed770cb9a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 2 Feb 2023 00:34:24 +0200 Subject: SL-19089 Changing UI scale crashes viewer This makes no sense, trying to add a glyph now will have no width or height set, neither character width or heigh, yet release viewer does that. Fixed code to match release and set width and height despite char width not being up to date. --- indra/llrender/llfontbitmapcache.cpp | 14 ++++++++++++++ indra/llrender/llfontfreetype.cpp | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index 8809f9f475..42b0045cf3 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -92,6 +92,20 @@ BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp { // We're out of space in the current image, or no image // has been allocated yet. Make a new one. + + 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; diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 5535c07615..e4010579b3 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -798,11 +798,11 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 llassert(!mIsFallback); llassert(image_raw && (image_raw->getComponents() == 2)); - U8 *target = image_raw->getData(); + llassert(target); - if (!data) + if (!data || !target) { return; } -- cgit v1.2.3 From 4df2c0b8d67af267d3c9c6d58d63df3ed063a89e Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Wed, 8 Feb 2023 17:17:47 +0100 Subject: Post-merge fix for xcode-14.1 branch --- indra/llcommon/llsdserialize.cpp | 2 +- indra/llcommon/llsdserialize.h | 2 +- indra/newview/llmeshrepository.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 73206f3d40..f66c4ff843 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -2388,7 +2388,7 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size 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 = ""; constexpr size_t deprecated_header_size = 17; diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 2f12c6d1ff..5ddf0ff552 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -873,5 +873,5 @@ LL_COMMON_API std::string zip_llsd(LLSD& data); 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/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; -- cgit v1.2.3 From abdb4941cf42c405dda433d2e9a6a510d5bc2377 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Tue, 7 Mar 2023 14:49:57 -0800 Subject: DRTVWR-489: Clean up a new warning-as-error failure on macOS --- indra/newview/llspeakingindicatormanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 37c7ea55ae..c4c9673be3 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -53,7 +53,7 @@ class SpeakingIndicatorManager : public LLSingleton, L LOG_CLASS(SpeakingIndicatorManager); protected: - void cleanupSingleton(); + void cleanupSingleton() override; public: -- cgit v1.2.3 From 337d2f984ff7f448fdbdc8dc2448e2b67cd23572 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 4 Apr 2023 03:32:40 +0200 Subject: Fix CMake files related to ICU4C --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/FindICU4C.cmake | 33 --------------------------------- indra/cmake/ICU4C.cmake | 37 +++++++++++++++++++------------------ indra/llcommon/CMakeLists.txt | 2 +- indra/newview/CMakeLists.txt | 2 +- 5 files changed, 22 insertions(+), 53 deletions(-) delete mode 100644 indra/cmake/FindICU4C.cmake (limited to 'indra') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index f0b35c08f3..286ef3d411 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -30,6 +30,7 @@ set(cmake_SOURCE_FILES GoogleMock.cmake Havok.cmake Hunspell.cmake + ICU4C.cmake JsonCpp.cmake LLAddBuildTest.cmake LLAppearance.cmake diff --git a/indra/cmake/FindICU4C.cmake b/indra/cmake/FindICU4C.cmake deleted file mode 100644 index 327d761a88..0000000000 --- a/indra/cmake/FindICU4C.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# -*- 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 index b51087e0e7..7b27665483 100644 --- a/indra/cmake/ICU4C.cmake +++ b/indra/cmake/ICU4C.cmake @@ -1,22 +1,23 @@ # -*- cmake -*- include(Prebuilt) -set(ICU4C_FIND_QUIETLY ON) -set(ICU4C_FIND_REQUIRED ON) +include_guard() -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) +add_library( ll::icu4c INTERFACE IMPORTED ) + + +use_system_binary(icu4c) +use_prebuilt_binary(icu4c) +if (WINDOWS) + target_link_libraries( ll::icu4c INTERFACE icuuc) +elseif(DARWIN) + target_link_libraries( ll::icu4c INTERFACE icuuc) +#elseif(LINUX) +## target_link_libraries( ll::icu4c INTERFACE ) +else() + message(FATAL_ERROR "Invalid platform") +endif() + +target_include_directories( ll::icu4c SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/unicode ) + +use_prebuilt_binary(dictionaries) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 620b2c636c..0dcdf7f7cd 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -265,7 +265,6 @@ add_library (llcommon ${llcommon_SOURCE_FILES}) target_link_libraries( llcommon - ${ICU4C_LIBRARY} ll::apr ll::expat ll::jsoncpp @@ -274,6 +273,7 @@ target_link_libraries( ll::uriparser ll::oslibraries ll::tracy + ll::icu4c ) target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b63100fc2b..f3c601dff5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1897,7 +1897,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICSEXTENSIONS_LIBRARIES} ll::bugsplat ll::tracy - ${ICU4C_LIBRARY} + ll::icu4u ) if( TARGET ll::intel_memops ) -- cgit v1.2.3 From 1bc57d0ae0135d624d0b6ea8dbe460273e1171b5 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 10 Apr 2023 16:57:48 -0700 Subject: SL-19078: the emoji/short-code mappings come in via a 3p package now --- .../skins/default/xui/en/emoji_characters.xml | 10955 ------------------- 1 file changed, 10955 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/emoji_characters.xml (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/emoji_characters.xml b/indra/newview/skins/default/xui/en/emoji_characters.xml deleted file mode 100644 index 55aefe6745..0000000000 --- a/indra/newview/skins/default/xui/en/emoji_characters.xml +++ /dev/null @@ -1,10955 +0,0 @@ - - - - - Character - 😀 - ShortCodes - - :grinning: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😄 - ShortCodes - - :smile: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😆 - ShortCodes - - :laughing: - - - - Categories - - Smiley - Face Smiling - - - - Character - 🤣 - ShortCodes - - :rofl: - :satisfied: - - - Categories - - Smiley - Face Smiling - - - - Character - 🙂 - ShortCodes - - :slightly_smiling_face: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😉 - ShortCodes - - :wink: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😇 - ShortCodes - - :innocent: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😃 - ShortCodes - - :smiley: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😁 - ShortCodes - - :grin: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😅 - ShortCodes - - :sweat_smile: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😂 - ShortCodes - - :joy: - - - - Categories - - Smiley - Face Smiling - - - - Character - 🙃 - ShortCodes - - :upside_down_face: - - - - Categories - - Smiley - Face Smiling - - - - Character - 😊 - ShortCodes - - :blush: - - - - Categories - - Smiley - Face Smiling - - - - Character - 🥰 - ShortCodes - - :smiling_face_with_three_hearts: - - - - Categories - - Smiley - Face Affection - - - - Character - 🤩 - ShortCodes - - :star_struck: - - - - Categories - - Smiley - Face Affection - - - - Character - 😗 - ShortCodes - - :kissing: - - - - Categories - - Smiley - Face Affection - - - - Character - 😚 - ShortCodes - - :kissing_closed_eyes: - - - - Categories - - Smiley - Face Affection - - - - Character - 🥲 - ShortCodes - - :smiling_face_with_tear: - - - - Categories - - Smiley - Face Affection - - - - Character - 😍 - ShortCodes - - :heart_eyes: - - - - Categories - - Smiley - Face Affection - - - - Character - 😘 - ShortCodes - - :kissing_heart: - - - - Categories - - Smiley - Face Affection - - - - Character - ☺️ - ShortCodes - - :relaxed: - - - - Categories - - Smiley - Face Affection - - - - Character - 😙 - ShortCodes - - :kissing_smiling_eyes: - - - - Categories - - Smiley - Face Affection - - - - Character - 😋 - ShortCodes - - :yum: - - - - Categories - - Smiley - Face Tongue - - - - Character - 😜 - ShortCodes - - :stuck_out_tongue_winking_eye: - - - - Categories - - Smiley - Face Tongue - - - - Character - 😝 - ShortCodes - - :stuck_out_tongue_closed_eyes: - - - - Categories - - Smiley - Face Tongue - - - - Character - 😛 - ShortCodes - - :stuck_out_tongue: - - - - Categories - - Smiley - Face Tongue - - - - Character - 🤪 - ShortCodes - - :zany_face: - - - - Categories - - Smiley - Face Tongue - - - - Character - 🤑 - ShortCodes - - :money_mouth_face: - - - - Categories - - Smiley - Face Tongue - - - - Character - 🤗 - ShortCodes - - :hugs: - - - - Categories - - Smiley - Face Hand - - - - Character - 🤫 - ShortCodes - - :shushing_face: - - - - Categories - - Smiley - Face Hand - - - - Character - 🤭 - ShortCodes - - :hand_over_mouth: - - - - Categories - - Smiley - Face Hand - - - - Character - 🤔 - ShortCodes - - :thinking: - - - - Categories - - Smiley - Face Hand - - - - Character - 🤐 - ShortCodes - - :zipper_mouth_face: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😐 - ShortCodes - - :neutral_face: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😶 - ShortCodes - - :no_mouth: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😏 - ShortCodes - - :smirk: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 🙄 - ShortCodes - - :roll_eyes: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😮‍💨 - ShortCodes - - :face_exhaling: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 🤨 - ShortCodes - - :raised_eyebrow: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😑 - ShortCodes - - :expressionless: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😶‍🌫️ - ShortCodes - - :face_in_clouds: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😒 - ShortCodes - - :unamused: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😬 - ShortCodes - - :grimacing: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 🤥 - ShortCodes - - :lying_face: - - - - Categories - - Smiley - Face Neutral Skeptical - - - - Character - 😌 - ShortCodes - - :relieved: - - - - Categories - - Smiley - Face Sleepy - - - - Character - 😪 - ShortCodes - - :sleepy: - - - - Categories - - Smiley - Face Sleepy - - - - Character - 😴 - ShortCodes - - :sleeping: - - - - Categories - - Smiley - Face Sleepy - - - - Character - 😔 - ShortCodes - - :pensive: - - - - Categories - - Smiley - Face Sleepy - - - - Character - 🤤 - ShortCodes - - :drooling_face: - - - - Categories - - Smiley - Face Sleepy - - - - Character - 😷 - ShortCodes - - :mask: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤕 - ShortCodes - - :face_with_head_bandage: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤮 - ShortCodes - - :vomiting_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🥵 - ShortCodes - - :hot_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🥴 - ShortCodes - - :woozy_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 😵‍💫 - ShortCodes - - :face_with_spiral_eyes: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤒 - ShortCodes - - :face_with_thermometer: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤢 - ShortCodes - - :nauseated_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤧 - ShortCodes - - :sneezing_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🥶 - ShortCodes - - :cold_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 😵 - ShortCodes - - :dizzy_face: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤯 - ShortCodes - - :exploding_head: - - - - Categories - - Smiley - Face Unwell - - - - Character - 🤠 - ShortCodes - - :cowboy_hat_face: - - - - Categories - - Smiley - Face Hat - - - - Character - 🥸 - ShortCodes - - :disguised_face: - - - - Categories - - Smiley - Face Hat - - - - Character - 🥳 - ShortCodes - - :partying_face: - - - - Categories - - Smiley - Face Hat - - - - Character - 😎 - ShortCodes - - :sunglasses: - - - - Categories - - Smiley - Face Glasses - - - - Character - 🧐 - ShortCodes - - :monocle_face: - - - - Categories - - Smiley - Face Glasses - - - - Character - 🤓 - ShortCodes - - :nerd_face: - - - - Categories - - Smiley - Face Glasses - - - - Character - 😕 - ShortCodes - - :confused: - - - - Categories - - Smiley - Face Concerned - - - - Character - 🙁 - ShortCodes - - :slightly_frowning_face: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😮 - ShortCodes - - :open_mouth: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😲 - ShortCodes - - :astonished: - - - - Categories - - Smiley - Face Concerned - - - - Character - 🥺 - ShortCodes - - :pleading_face: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😧 - ShortCodes - - :anguished: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😰 - ShortCodes - - :cold_sweat: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😢 - ShortCodes - - :cry: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😱 - ShortCodes - - :scream: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😣 - ShortCodes - - :persevere: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😓 - ShortCodes - - :sweat: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😫 - ShortCodes - - :tired_face: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😟 - ShortCodes - - :worried: - - - - Categories - - Smiley - Face Concerned - - - - Character - ☹️ - ShortCodes - - :frowning_face: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😯 - ShortCodes - - :hushed: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😳 - ShortCodes - - :flushed: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😦 - ShortCodes - - :frowning: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😨 - ShortCodes - - :fearful: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😥 - ShortCodes - - :disappointed_relieved: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😭 - ShortCodes - - :sob: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😖 - ShortCodes - - :confounded: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😞 - ShortCodes - - :disappointed: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😩 - ShortCodes - - :weary: - - - - Categories - - Smiley - Face Concerned - - - - Character - 🥱 - ShortCodes - - :yawning_face: - - - - Categories - - Smiley - Face Concerned - - - - Character - 😤 - ShortCodes - - :triumph: - - - - Categories - - Smiley - Face Negative - - - - Character - 😠 - ShortCodes - - :angry: - - - - Categories - - Smiley - Face Negative - - - - Character - 😈 - ShortCodes - - :smiling_imp: - - - - Categories - - Smiley - Face Negative - - - - Character - 💀 - ShortCodes - - :skull: - - - - Categories - - Smiley - Face Negative - - - - Character - 😡 - ShortCodes - - :pout: - :rage: - - - Categories - - Smiley - Face Negative - - - - Character - 🤬 - ShortCodes - - :cursing_face: - - - - Categories - - Smiley - Face Negative - - - - Character - 👿 - ShortCodes - - :imp: - - - - Categories - - Smiley - Face Negative - - - - Character - ☠️ - ShortCodes - - :skull_and_crossbones: - - - - Categories - - Smiley - Face Negative - - - - Character - 💩 - ShortCodes - - :hankey: - :poop: - :shit: - - Categories - - Smiley - Face Costume - - - - Character - 👹 - ShortCodes - - :japanese_ogre: - - - - Categories - - Smiley - Face Costume - - - - Character - 👻 - ShortCodes - - :ghost: - - - - Categories - - Smiley - Face Costume - - - - Character - 👾 - ShortCodes - - :space_invader: - - - - Categories - - Smiley - Face Costume - - - - Character - 🤡 - ShortCodes - - :clown_face: - - - - Categories - - Smiley - Face Costume - - - - Character - 👺 - ShortCodes - - :japanese_goblin: - - - - Categories - - Smiley - Face Costume - - - - Character - 👽 - ShortCodes - - :alien: - - - - Categories - - Smiley - Face Costume - - - - Character - 🤖 - ShortCodes - - :robot: - - - - Categories - - Smiley - Face Costume - - - - Character - 😺 - ShortCodes - - :smiley_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😹 - ShortCodes - - :joy_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😼 - ShortCodes - - :smirk_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 🙀 - ShortCodes - - :scream_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😾 - ShortCodes - - :pouting_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😸 - ShortCodes - - :smile_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😻 - ShortCodes - - :heart_eyes_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😽 - ShortCodes - - :kissing_cat: - - - - Categories - - Smiley - Cat Face - - - - Character - 😿 - ShortCodes - - :crying_cat_face: - - - - Categories - - Smiley - Cat Face - - - - Character - 🙈 - ShortCodes - - :see_no_evil: - - - - Categories - - Smiley - Monkey Face - - - - Character - 🙊 - ShortCodes - - :speak_no_evil: - - - - Categories - - Smiley - Monkey Face - - - - Character - 🙉 - ShortCodes - - :hear_no_evil: - - - - Categories - - Smiley - Monkey Face - - - - Character - 💋 - ShortCodes - - :kiss: - - - - Categories - - Emotion - - - - - Character - 💘 - ShortCodes - - :cupid: - - - - Categories - - Emotion - - - - - Character - 💖 - ShortCodes - - :sparkling_heart: - - - - Categories - - Emotion - - - - - Character - 💓 - ShortCodes - - :heartbeat: - - - - Categories - - Emotion - - - - - Character - 💕 - ShortCodes - - :two_hearts: - - - - Categories - - Emotion - - - - - Character - ❣️ - ShortCodes - - :heavy_heart_exclamation: - - - - Categories - - Emotion - - - - - Character - ❤️‍🔥 - ShortCodes - - :heart_on_fire: - - - - Categories - - Emotion - - - - - Character - ❤️ - ShortCodes - - :heart: - - - - Categories - - Emotion - - - - - Character - 💛 - ShortCodes - - :yellow_heart: - - - - Categories - - Emotion - - - - - Character - 💙 - ShortCodes - - :blue_heart: - - - - Categories - - Emotion - - - - - Character - 🤎 - ShortCodes - - :brown_heart: - - - - Categories - - Emotion - - - - - Character - 🤍 - ShortCodes - - :white_heart: - - - - Categories - - Emotion - - - - - Character - 💢 - ShortCodes - - :anger: - - - - Categories - - Emotion - - - - - Character - 💫 - ShortCodes - - :dizzy: - - - - Categories - - Emotion - - - - - Character - 💨 - ShortCodes - - :dash: - - - - Categories - - Emotion - - - - - Character - 💣 - ShortCodes - - :bomb: - - - - Categories - - Emotion - - - - - Character - 👁️‍🗨️ - ShortCodes - - :eye_speech_bubble: - - - - Categories - - Emotion - - - - - Character - 🗯️ - ShortCodes - - :right_anger_bubble: - - - - Categories - - Emotion - - - - - Character - 💤 - ShortCodes - - :zzz: - - - - Categories - - Emotion - - - - - Character - 💌 - ShortCodes - - :love_letter: - - - - Categories - - Emotion - - - - - Character - 💝 - ShortCodes - - :gift_heart: - - - - Categories - - Emotion - - - - - Character - 💗 - ShortCodes - - :heartpulse: - - - - Categories - - Emotion - - - - - Character - 💞 - ShortCodes - - :revolving_hearts: - - - - Categories - - Emotion - - - - - Character - 💟 - ShortCodes - - :heart_decoration: - - - - Categories - - Emotion - - - - - Character - 💔 - ShortCodes - - :broken_heart: - - - - Categories - - Emotion - - - - - Character - ❤️‍🩹 - ShortCodes - - :mending_heart: - - - - Categories - - Emotion - - - - - Character - 🧡 - ShortCodes - - :orange_heart: - - - - Categories - - Emotion - - - - - Character - 💚 - ShortCodes - - :green_heart: - - - - Categories - - Emotion - - - - - Character - 💜 - ShortCodes - - :purple_heart: - - - - Categories - - Emotion - - - - - Character - 🖤 - ShortCodes - - :black_heart: - - - - Categories - - Emotion - - - - - Character - 💯 - ShortCodes - - :100: - - - - Categories - - Emotion - - - - - Character - 💥 - ShortCodes - - :boom: - :collision: - - - Categories - - Emotion - - - - - Character - 💦 - ShortCodes - - :sweat_drops: - - - - Categories - - Emotion - - - - - Character - 🕳️ - ShortCodes - - :hole: - - - - Categories - - Emotion - - - - - Character - 💬 - ShortCodes - - :speech_balloon: - - - - Categories - - Emotion - - - - - Character - 🗨️ - ShortCodes - - :left_speech_bubble: - - - - Categories - - Emotion - - - - - Character - 💭 - ShortCodes - - :thought_balloon: - - - - Categories - - Emotion - - - - - Character - 👋 - ShortCodes - - :wave: - - - - Categories - - Body - Hand Fingers Open - - - - Character - 🖐️ - ShortCodes - - :raised_hand_with_fingers_splayed: - - - - Categories - - Body - Hand Fingers Open - - - - Character - 🖖 - ShortCodes - - :vulcan_salute: - - - - Categories - - Body - Hand Fingers Open - - - - Character - 🤚 - ShortCodes - - :raised_back_of_hand: - - - - Categories - - Body - Hand Fingers Open - - - - Character - - ShortCodes - - :hand: - :raised_hand: - - - Categories - - Body - Hand Fingers Open - - - - Character - 👌 - ShortCodes - - :ok_hand: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤏 - ShortCodes - - :pinching_hand: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤞 - ShortCodes - - :crossed_fingers: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤘 - ShortCodes - - :metal: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤌 - ShortCodes - - :pinched_fingers: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - ✌️ - ShortCodes - - :v: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤟 - ShortCodes - - :love_you_gesture: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 🤙 - ShortCodes - - :call_me_hand: - - - - Categories - - Body - Hand Fingers Partial - - - - Character - 👈 - ShortCodes - - :point_left: - - - - Categories - - Body - Hand Single Finger - - - - Character - 👆 - ShortCodes - - :point_up_2: - - - - Categories - - Body - Hand Single Finger - - - - Character - 👇 - ShortCodes - - :point_down: - - - - Categories - - Body - Hand Single Finger - - - - Character - 👉 - ShortCodes - - :point_right: - - - - Categories - - Body - Hand Single Finger - - - - Character - 🖕 - ShortCodes - - :fu: - :middle_finger: - - - Categories - - Body - Hand Single Finger - - - - Character - ☝️ - ShortCodes - - :point_up: - - - - Categories - - Body - Hand Single Finger - - - - Character - 👍 - ShortCodes - - :+1: - :thumbsup: - - - Categories - - Body - Hand Fingers Closed - - - - Character - - ShortCodes - - :fist: - :fist_raised: - - - Categories - - Body - Hand Fingers Closed - - - - Character - 🤛 - ShortCodes - - :fist_left: - - - - Categories - - Body - Hand Fingers Closed - - - - Character - 👎 - ShortCodes - - :-1: - :thumbsdown: - - - Categories - - Body - Hand Fingers Closed - - - - Character - 👊 - ShortCodes - - :facepunch: - :fist_oncoming: - :punch: - - Categories - - Body - Hand Fingers Closed - - - - Character - 🤜 - ShortCodes - - :fist_right: - - - - Categories - - Body - Hand Fingers Closed - - - - Character - 👏 - ShortCodes - - :clap: - - - - Categories - - Body - Hands - - - - Character - 👐 - ShortCodes - - :open_hands: - - - - Categories - - Body - Hands - - - - Character - 🤝 - ShortCodes - - :handshake: - - - - Categories - - Body - Hands - - - - Character - 🙌 - ShortCodes - - :raised_hands: - - - - Categories - - Body - Hands - - - - Character - 🤲 - ShortCodes - - :palms_up_together: - - - - Categories - - Body - Hands - - - - Character - 🙏 - ShortCodes - - :pray: - - - - Categories - - Body - Hands - - - - Character - ✍️ - ShortCodes - - :writing_hand: - - - - Categories - - Body - Hand Prop - - - - Character - 🤳 - ShortCodes - - :selfie: - - - - Categories - - Body - Hand Prop - - - - Character - 💅 - ShortCodes - - :nail_care: - - - - Categories - - Body - Hand Prop - - - - Character - 💪 - ShortCodes - - :muscle: - - - - Categories - - Body - Body Parts - - - - Character - 🦿 - ShortCodes - - :mechanical_leg: - - - - Categories - - Body - Body Parts - - - - Character - 🦶 - ShortCodes - - :foot: - - - - Categories - - Body - Body Parts - - - - Character - 🦻 - ShortCodes - - :ear_with_hearing_aid: - - - - Categories - - Body - Body Parts - - - - Character - 🧠 - ShortCodes - - :brain: - - - - Categories - - Body - Body Parts - - - - Character - 🫁 - ShortCodes - - :lungs: - - - - Categories - - Body - Body Parts - - - - Character - 🦴 - ShortCodes - - :bone: - - - - Categories - - Body - Body Parts - - - - Character - 👁️ - ShortCodes - - :eye: - - - - Categories - - Body - Body Parts - - - - Character - 👄 - ShortCodes - - :lips: - - - - Categories - - Body - Body Parts - - - - Character - 🦾 - ShortCodes - - :mechanical_arm: - - - - Categories - - Body - Body Parts - - - - Character - 🦵 - ShortCodes - - :leg: - - - - Categories - - Body - Body Parts - - - - Character - 👂 - ShortCodes - - :ear: - - - - Categories - - Body - Body Parts - - - - Character - 👃 - ShortCodes - - :nose: - - - - Categories - - Body - Body Parts - - - - Character - 🫀 - ShortCodes - - :anatomical_heart: - - - - Categories - - Body - Body Parts - - - - Character - 🦷 - ShortCodes - - :tooth: - - - - Categories - - Body - Body Parts - - - - Character - 👀 - ShortCodes - - :eyes: - - - - Categories - - Body - Body Parts - - - - Character - 👅 - ShortCodes - - :tongue: - - - - Categories - - Body - Body Parts - - - - Character - 👶 - ShortCodes - - :baby: - - - - Categories - - Person - - - - - Character - 👦 - ShortCodes - - :boy: - - - - Categories - - Person - - - - - Character - 🧑 - ShortCodes - - :adult: - - - - Categories - - Person - - - - - Character - 👨 - ShortCodes - - :man: - - - - Categories - - Person - - - - - Character - 🧔‍♂️ - ShortCodes - - :man_beard: - - - - Categories - - Person - - - - - Character - 👨‍🦰 - ShortCodes - - :red_haired_man: - - - - Categories - - Person - - - - - Character - 👨‍🦳 - ShortCodes - - :white_haired_man: - - - - Categories - - Person - - - - - Character - 👩 - ShortCodes - - :woman: - - - - Categories - - Person - - - - - Character - 🧑‍🦰 - ShortCodes - - :person_red_hair: - - - - Categories - - Person - - - - - Character - 🧑‍🦱 - ShortCodes - - :person_curly_hair: - - - - Categories - - Person - - - - - Character - 🧑‍🦳 - ShortCodes - - :person_white_hair: - - - - Categories - - Person - - - - - Character - 🧑‍🦲 - ShortCodes - - :person_bald: - - - - Categories - - Person - - - - - Character - 👱‍♂️ - ShortCodes - - :blond_haired_man: - - - - Categories - - Person - - - - - Character - 👴 - ShortCodes - - :older_man: - - - - Categories - - Person - - - - - Character - 🧒 - ShortCodes - - :child: - - - - Categories - - Person - - - - - Character - 👧 - ShortCodes - - :girl: - - - - Categories - - Person - - - - - Character - 👱 - ShortCodes - - :blond_haired_person: - - - - Categories - - Person - - - - - Character - 🧔 - ShortCodes - - :bearded_person: - - - - Categories - - Person - - - - - Character - 🧔‍♀️ - ShortCodes - - :woman_beard: - - - - Categories - - Person - - - - - Character - 👨‍🦱 - ShortCodes - - :curly_haired_man: - - - - Categories - - Person - - - - - Character - 👨‍🦲 - ShortCodes - - :bald_man: - - - - Categories - - Person - - - - - Character - 👩‍🦰 - ShortCodes - - :red_haired_woman: - - - - Categories - - Person - - - - - Character - 👩‍🦱 - ShortCodes - - :curly_haired_woman: - - - - Categories - - Person - - - - - Character - 👩‍🦳 - ShortCodes - - :white_haired_woman: - - - - Categories - - Person - - - - - Character - 👩‍🦲 - ShortCodes - - :bald_woman: - - - - Categories - - Person - - - - - Character - 👱‍♀️ - ShortCodes - - :blond_haired_woman: - :blonde_woman: - - - Categories - - Person - - - - - Character - 🧓 - ShortCodes - - :older_adult: - - - - Categories - - Person - - - - - Character - 👵 - ShortCodes - - :older_woman: - - - - Categories - - Person - - - - - Character - 🙍 - ShortCodes - - :frowning_person: - - - - Categories - - Person Gesture - - - - - Character - 🙍‍♀️ - ShortCodes - - :frowning_woman: - - - - Categories - - Person Gesture - - - - - Character - 🙎‍♂️ - ShortCodes - - :pouting_man: - - - - Categories - - Person Gesture - - - - - Character - 🙅 - ShortCodes - - :no_good: - - - - Categories - - Person Gesture - - - - - Character - 🙅‍♀️ - ShortCodes - - :ng_woman: - :no_good_woman: - - - Categories - - Person Gesture - - - - - Character - 🙆‍♂️ - ShortCodes - - :ok_man: - - - - Categories - - Person Gesture - - - - - Character - 💁 - ShortCodes - - :information_desk_person: - :tipping_hand_person: - - - Categories - - Person Gesture - - - - - Character - 💁‍♀️ - ShortCodes - - :sassy_woman: - :tipping_hand_woman: - - - Categories - - Person Gesture - - - - - Character - 🙋‍♂️ - ShortCodes - - :raising_hand_man: - - - - Categories - - Person Gesture - - - - - Character - 🧏 - ShortCodes - - :deaf_person: - - - - Categories - - Person Gesture - - - - - Character - 🧏‍♀️ - ShortCodes - - :deaf_woman: - - - - Categories - - Person Gesture - - - - - Character - 🙇‍♂️ - ShortCodes - - :bowing_man: - - - - Categories - - Person Gesture - - - - - Character - 🤦 - ShortCodes - - :facepalm: - - - - Categories - - Person Gesture - - - - - Character - 🤦‍♀️ - ShortCodes - - :woman_facepalming: - - - - Categories - - Person Gesture - - - - - Character - 🤷‍♂️ - ShortCodes - - :man_shrugging: - - - - Categories - - Person Gesture - - - - - Character - 🙍‍♂️ - ShortCodes - - :frowning_man: - - - - Categories - - Person Gesture - - - - - Character - 🙎 - ShortCodes - - :pouting_face: - - - - Categories - - Person Gesture - - - - - Character - 🙎‍♀️ - ShortCodes - - :pouting_woman: - - - - Categories - - Person Gesture - - - - - Character - 🙅‍♂️ - ShortCodes - - :ng_man: - :no_good_man: - - - Categories - - Person Gesture - - - - - Character - 🙆 - ShortCodes - - :ok_person: - - - - Categories - - Person Gesture - - - - - Character - 🙆‍♀️ - ShortCodes - - :ok_woman: - - - - Categories - - Person Gesture - - - - - Character - 💁‍♂️ - ShortCodes - - :sassy_man: - :tipping_hand_man: - - - Categories - - Person Gesture - - - - - Character - 🙋 - ShortCodes - - :raising_hand: - - - - Categories - - Person Gesture - - - - - Character - 🙋‍♀️ - ShortCodes - - :raising_hand_woman: - - - - Categories - - Person Gesture - - - - - Character - 🧏‍♂️ - ShortCodes - - :deaf_man: - - - - Categories - - Person Gesture - - - - - Character - 🙇 - ShortCodes - - :bow: - - - - Categories - - Person Gesture - - - - - Character - 🙇‍♀️ - ShortCodes - - :bowing_woman: - - - - Categories - - Person Gesture - - - - - Character - 🤦‍♂️ - ShortCodes - - :man_facepalming: - - - - Categories - - Person Gesture - - - - - Character - 🤷 - ShortCodes - - :shrug: - - - - Categories - - Person Gesture - - - - - Character - 🤷‍♀️ - ShortCodes - - :woman_shrugging: - - - - Categories - - Person Gesture - - - - - Character - 🧑‍⚕️ - ShortCodes - - :health_worker: - - - - Categories - - Person Role - - - - - Character - 👩‍⚕️ - ShortCodes - - :woman_health_worker: - - - - Categories - - Person Role - - - - - Character - 👨‍🎓 - ShortCodes - - :man_student: - - - - Categories - - Person Role - - - - - Character - 🧑‍🏫 - ShortCodes - - :teacher: - - - - Categories - - Person Role - - - - - Character - 👩‍🏫 - ShortCodes - - :woman_teacher: - - - - Categories - - Person Role - - - - - Character - 👨‍⚖️ - ShortCodes - - :man_judge: - - - - Categories - - Person Role - - - - - Character - 🧑‍🌾 - ShortCodes - - :farmer: - - - - Categories - - Person Role - - - - - Character - 👩‍🌾 - ShortCodes - - :woman_farmer: - - - - Categories - - Person Role - - - - - Character - 👨‍🍳 - ShortCodes - - :man_cook: - - - - Categories - - Person Role - - - - - Character - 🧑‍🔧 - ShortCodes - - :mechanic: - - - - Categories - - Person Role - - - - - Character - 👩‍🔧 - ShortCodes - - :woman_mechanic: - - - - Categories - - Person Role - - - - - Character - 👨‍🏭 - ShortCodes - - :man_factory_worker: - - - - Categories - - Person Role - - - - - Character - 🧑‍💼 - ShortCodes - - :office_worker: - - - - Categories - - Person Role - - - - - Character - 👩‍💼 - ShortCodes - - :woman_office_worker: - - - - Categories - - Person Role - - - - - Character - 👨‍🔬 - ShortCodes - - :man_scientist: - - - - Categories - - Person Role - - - - - Character - 🧑‍💻 - ShortCodes - - :technologist: - - - - Categories - - Person Role - - - - - Character - 👩‍💻 - ShortCodes - - :woman_technologist: - - - - Categories - - Person Role - - - - - Character - 👨‍🎤 - ShortCodes - - :man_singer: - - - - Categories - - Person Role - - - - - Character - 🧑‍🎨 - ShortCodes - - :artist: - - - - Categories - - Person Role - - - - - Character - 👩‍🎨 - ShortCodes - - :woman_artist: - - - - Categories - - Person Role - - - - - Character - 👨‍✈️ - ShortCodes - - :man_pilot: - - - - Categories - - Person Role - - - - - Character - 🧑‍🚀 - ShortCodes - - :astronaut: - - - - Categories - - Person Role - - - - - Character - 👩‍🚀 - ShortCodes - - :woman_astronaut: - - - - Categories - - Person Role - - - - - Character - 👨‍🚒 - ShortCodes - - :man_firefighter: - - - - Categories - - Person Role - - - - - Character - 👮 - ShortCodes - - :cop: - :police_officer: - - - Categories - - Person Role - - - - - Character - 👮‍♀️ - ShortCodes - - :policewoman: - - - - Categories - - Person Role - - - - - Character - 🕵️‍♂️ - ShortCodes - - :male_detective: - - - - Categories - - Person Role - - - - - Character - 💂 - ShortCodes - - :guard: - - - - Categories - - Person Role - - - - - Character - 💂‍♀️ - ShortCodes - - :guardswoman: - - - - Categories - - Person Role - - - - - Character - 👷 - ShortCodes - - :construction_worker: - - - - Categories - - Person Role - - - - - Character - 👷‍♀️ - ShortCodes - - :construction_worker_woman: - - - - Categories - - Person Role - - - - - Character - 👸 - ShortCodes - - :princess: - - - - Categories - - Person Role - - - - - Character - 👳‍♂️ - ShortCodes - - :man_with_turban: - - - - Categories - - Person Role - - - - - Character - 👲 - ShortCodes - - :man_with_gua_pi_mao: - - - - Categories - - Person Role - - - - - Character - 🤵 - ShortCodes - - :person_in_tuxedo: - - - - Categories - - Person Role - - - - - Character - 🤵‍♀️ - ShortCodes - - :woman_in_tuxedo: - - - - Categories - - Person Role - - - - - Character - 👰‍♂️ - ShortCodes - - :man_with_veil: - - - - Categories - - Person Role - - - - - Character - 🤰 - ShortCodes - - :pregnant_woman: - - - - Categories - - Person Role - - - - - Character - 👩‍🍼 - ShortCodes - - :woman_feeding_baby: - - - - Categories - - Person Role - - - - - Character - 🧑‍🍼 - ShortCodes - - :person_feeding_baby: - - - - Categories - - Person Role - - - - - Character - 👨‍⚕️ - ShortCodes - - :man_health_worker: - - - - Categories - - Person Role - - - - - Character - 🧑‍🎓 - ShortCodes - - :student: - - - - Categories - - Person Role - - - - - Character - 👩‍🎓 - ShortCodes - - :woman_student: - - - - Categories - - Person Role - - - - - Character - 👨‍🏫 - ShortCodes - - :man_teacher: - - - - Categories - - Person Role - - - - - Character - 🧑‍⚖️ - ShortCodes - - :judge: - - - - Categories - - Person Role - - - - - Character - 👩‍⚖️ - ShortCodes - - :woman_judge: - - - - Categories - - Person Role - - - - - Character - 👨‍🌾 - ShortCodes - - :man_farmer: - - - - Categories - - Person Role - - - - - Character - 🧑‍🍳 - ShortCodes - - :cook: - - - - Categories - - Person Role - - - - - Character - 👩‍🍳 - ShortCodes - - :woman_cook: - - - - Categories - - Person Role - - - - - Character - 👨‍🔧 - ShortCodes - - :man_mechanic: - - - - Categories - - Person Role - - - - - Character - 🧑‍🏭 - ShortCodes - - :factory_worker: - - - - Categories - - Person Role - - - - - Character - 👩‍🏭 - ShortCodes - - :woman_factory_worker: - - - - Categories - - Person Role - - - - - Character - 👨‍💼 - ShortCodes - - :man_office_worker: - - - - Categories - - Person Role - - - - - Character - 🧑‍🔬 - ShortCodes - - :scientist: - - - - Categories - - Person Role - - - - - Character - 👩‍🔬 - ShortCodes - - :woman_scientist: - - - - Categories - - Person Role - - - - - Character - 👨‍💻 - ShortCodes - - :man_technologist: - - - - Categories - - Person Role - - - - - Character - 🧑‍🎤 - ShortCodes - - :singer: - - - - Categories - - Person Role - - - - - Character - 👩‍🎤 - ShortCodes - - :woman_singer: - - - - Categories - - Person Role - - - - - Character - 👨‍🎨 - ShortCodes - - :man_artist: - - - - Categories - - Person Role - - - - - Character - 🧑‍✈️ - ShortCodes - - :pilot: - - - - Categories - - Person Role - - - - - Character - 👩‍✈️ - ShortCodes - - :woman_pilot: - - - - Categories - - Person Role - - - - - Character - 👨‍🚀 - ShortCodes - - :man_astronaut: - - - - Categories - - Person Role - - - - - Character - 🧑‍🚒 - ShortCodes - - :firefighter: - - - - Categories - - Person Role - - - - - Character - 👩‍🚒 - ShortCodes - - :woman_firefighter: - - - - Categories - - Person Role - - - - - Character - 👮‍♂️ - ShortCodes - - :policeman: - - - - Categories - - Person Role - - - - - Character - 🕵️ - ShortCodes - - :detective: - - - - Categories - - Person Role - - - - - Character - 🕵️‍♀️ - ShortCodes - - :female_detective: - - - - Categories - - Person Role - - - - - Character - 💂‍♂️ - ShortCodes - - :guardsman: - - - - Categories - - Person Role - - - - - Character - 🥷 - ShortCodes - - :ninja: - - - - Categories - - Person Role - - - - - Character - 👷‍♂️ - ShortCodes - - :construction_worker_man: - - - - Categories - - Person Role - - - - - Character - 🤴 - ShortCodes - - :prince: - - - - Categories - - Person Role - - - - - Character - 👳 - ShortCodes - - :person_with_turban: - - - - Categories - - Person Role - - - - - Character - 👳‍♀️ - ShortCodes - - :woman_with_turban: - - - - Categories - - Person Role - - - - - Character - 🧕 - ShortCodes - - :woman_with_headscarf: - - - - Categories - - Person Role - - - - - Character - 🤵‍♂️ - ShortCodes - - :man_in_tuxedo: - - - - Categories - - Person Role - - - - - Character - 👰 - ShortCodes - - :person_with_veil: - - - - Categories - - Person Role - - - - - Character - 👰‍♀️ - ShortCodes - - :bride_with_veil: - :woman_with_veil: - - - Categories - - Person Role - - - - - Character - 🤱 - ShortCodes - - :breast_feeding: - - - - Categories - - Person Role - - - - - Character - 👨‍🍼 - ShortCodes - - :man_feeding_baby: - - - - Categories - - Person Role - - - - - Character - 👼 - ShortCodes - - :angel: - - - - Categories - - Person Fantasy - - - - - Character - 🤶 - ShortCodes - - :mrs_claus: - - - - Categories - - Person Fantasy - - - - - Character - 🦸 - ShortCodes - - :superhero: - - - - Categories - - Person Fantasy - - - - - Character - 🦸‍♀️ - ShortCodes - - :superhero_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🦹‍♂️ - ShortCodes - - :supervillain_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧙 - ShortCodes - - :mage: - - - - Categories - - Person Fantasy - - - - - Character - 🧙‍♀️ - ShortCodes - - :mage_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧚‍♂️ - ShortCodes - - :fairy_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧛 - ShortCodes - - :vampire: - - - - Categories - - Person Fantasy - - - - - Character - 🧛‍♀️ - ShortCodes - - :vampire_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧜‍♂️ - ShortCodes - - :merman: - - - - Categories - - Person Fantasy - - - - - Character - 🧝 - ShortCodes - - :elf: - - - - Categories - - Person Fantasy - - - - - Character - 🧝‍♀️ - ShortCodes - - :elf_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧞‍♂️ - ShortCodes - - :genie_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧟 - ShortCodes - - :zombie: - - - - Categories - - Person Fantasy - - - - - Character - 🧟‍♀️ - ShortCodes - - :zombie_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🎅 - ShortCodes - - :santa: - - - - Categories - - Person Fantasy - - - - - Character - 🧑‍🎄 - ShortCodes - - :mx_claus: - - - - Categories - - Person Fantasy - - - - - Character - 🦸‍♂️ - ShortCodes - - :superhero_man: - - - - Categories - - Person Fantasy - - - - - Character - 🦹 - ShortCodes - - :supervillain: - - - - Categories - - Person Fantasy - - - - - Character - 🦹‍♀️ - ShortCodes - - :supervillain_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧙‍♂️ - ShortCodes - - :mage_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧚 - ShortCodes - - :fairy: - - - - Categories - - Person Fantasy - - - - - Character - 🧚‍♀️ - ShortCodes - - :fairy_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧛‍♂️ - ShortCodes - - :vampire_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧜 - ShortCodes - - :merperson: - - - - Categories - - Person Fantasy - - - - - Character - 🧜‍♀️ - ShortCodes - - :mermaid: - - - - Categories - - Person Fantasy - - - - - Character - 🧝‍♂️ - ShortCodes - - :elf_man: - - - - Categories - - Person Fantasy - - - - - Character - 🧞 - ShortCodes - - :genie: - - - - Categories - - Person Fantasy - - - - - Character - 🧞‍♀️ - ShortCodes - - :genie_woman: - - - - Categories - - Person Fantasy - - - - - Character - 🧟‍♂️ - ShortCodes - - :zombie_man: - - - - Categories - - Person Fantasy - - - - - Character - 💆 - ShortCodes - - :massage: - - - - Categories - - Person Activity - - - - - Character - 💆‍♀️ - ShortCodes - - :massage_woman: - - - - Categories - - Person Activity - - - - - Character - 💇‍♂️ - ShortCodes - - :haircut_man: - - - - Categories - - Person Activity - - - - - Character - 🚶 - ShortCodes - - :walking: - - - - Categories - - Person Activity - - - - - Character - 🚶‍♀️ - ShortCodes - - :walking_woman: - - - - Categories - - Person Activity - - - - - Character - 🧍‍♂️ - ShortCodes - - :standing_man: - - - - Categories - - Person Activity - - - - - Character - 🧎 - ShortCodes - - :kneeling_person: - - - - Categories - - Person Activity - - - - - Character - 🧎‍♀️ - ShortCodes - - :kneeling_woman: - - - - Categories - - Person Activity - - - - - Character - 👨‍🦯 - ShortCodes - - :man_with_probing_cane: - - - - Categories - - Person Activity - - - - - Character - 🧑‍🦼 - ShortCodes - - :person_in_motorized_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 👩‍🦼 - ShortCodes - - :woman_in_motorized_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 👨‍🦽 - ShortCodes - - :man_in_manual_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 🏃 - ShortCodes - - :runner: - :running: - - - Categories - - Person Activity - - - - - Character - 🏃‍♀️ - ShortCodes - - :running_woman: - - - - Categories - - Person Activity - - - - - Character - 🕺 - ShortCodes - - :man_dancing: - - - - Categories - - Person Activity - - - - - Character - 👯 - ShortCodes - - :dancers: - - - - Categories - - Person Activity - - - - - Character - 👯‍♀️ - ShortCodes - - :dancing_women: - - - - Categories - - Person Activity - - - - - Character - 🧖‍♂️ - ShortCodes - - :sauna_man: - - - - Categories - - Person Activity - - - - - Character - 🧗 - ShortCodes - - :climbing: - - - - Categories - - Person Activity - - - - - Character - 🧗‍♀️ - ShortCodes - - :climbing_woman: - - - - Categories - - Person Activity - - - - - Character - 💆‍♂️ - ShortCodes - - :massage_man: - - - - Categories - - Person Activity - - - - - Character - 💇 - ShortCodes - - :haircut: - - - - Categories - - Person Activity - - - - - Character - 💇‍♀️ - ShortCodes - - :haircut_woman: - - - - Categories - - Person Activity - - - - - Character - 🚶‍♂️ - ShortCodes - - :walking_man: - - - - Categories - - Person Activity - - - - - Character - 🧍 - ShortCodes - - :standing_person: - - - - Categories - - Person Activity - - - - - Character - 🧍‍♀️ - ShortCodes - - :standing_woman: - - - - Categories - - Person Activity - - - - - Character - 🧎‍♂️ - ShortCodes - - :kneeling_man: - - - - Categories - - Person Activity - - - - - Character - 🧑‍🦯 - ShortCodes - - :person_with_probing_cane: - - - - Categories - - Person Activity - - - - - Character - 👩‍🦯 - ShortCodes - - :woman_with_probing_cane: - - - - Categories - - Person Activity - - - - - Character - 👨‍🦼 - ShortCodes - - :man_in_motorized_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 🧑‍🦽 - ShortCodes - - :person_in_manual_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 👩‍🦽 - ShortCodes - - :woman_in_manual_wheelchair: - - - - Categories - - Person Activity - - - - - Character - 🏃‍♂️ - ShortCodes - - :running_man: - - - - Categories - - Person Activity - - - - - Character - 💃 - ShortCodes - - :dancer: - :woman_dancing: - - - Categories - - Person Activity - - - - - Character - 🕴️ - ShortCodes - - :business_suit_levitating: - - - - Categories - - Person Activity - - - - - Character - 👯‍♂️ - ShortCodes - - :dancing_men: - - - - Categories - - Person Activity - - - - - Character - 🧖 - ShortCodes - - :sauna_person: - - - - Categories - - Person Activity - - - - - Character - 🧖‍♀️ - ShortCodes - - :sauna_woman: - - - - Categories - - Person Activity - - - - - Character - 🧗‍♂️ - ShortCodes - - :climbing_man: - - - - Categories - - Person Activity - - - - - Character - 🤺 - ShortCodes - - :person_fencing: - - - - Categories - - Person Sport - - - - - Character - ⛷️ - ShortCodes - - :skier: - - - - Categories - - Person Sport - - - - - Character - 🏌️ - ShortCodes - - :golfing: - - - - Categories - - Person Sport - - - - - Character - 🏌️‍♀️ - ShortCodes - - :golfing_woman: - - - - Categories - - Person Sport - - - - - Character - 🏄‍♂️ - ShortCodes - - :surfing_man: - - - - Categories - - Person Sport - - - - - Character - 🚣 - ShortCodes - - :rowboat: - - - - Categories - - Person Sport - - - - - Character - 🚣‍♀️ - ShortCodes - - :rowing_woman: - - - - Categories - - Person Sport - - - - - Character - 🏊‍♂️ - ShortCodes - - :swimming_man: - - - - Categories - - Person Sport - - - - - Character - ⛹️ - ShortCodes - - :bouncing_ball_person: - - - - Categories - - Person Sport - - - - - Character - ⛹️‍♀️ - ShortCodes - - :basketball_woman: - :bouncing_ball_woman: - - - Categories - - Person Sport - - - - - Character - 🏋️‍♂️ - ShortCodes - - :weight_lifting_man: - - - - Categories - - Person Sport - - - - - Character - 🚴 - ShortCodes - - :bicyclist: - - - - Categories - - Person Sport - - - - - Character - 🚴‍♀️ - ShortCodes - - :biking_woman: - - - - Categories - - Person Sport - - - - - Character - 🚵‍♂️ - ShortCodes - - :mountain_biking_man: - - - - Categories - - Person Sport - - - - - Character - 🤸 - ShortCodes - - :cartwheeling: - - - - Categories - - Person Sport - - - - - Character - 🤸‍♀️ - ShortCodes - - :woman_cartwheeling: - - - - Categories - - Person Sport - - - - - Character - 🤼‍♂️ - ShortCodes - - :men_wrestling: - - - - Categories - - Person Sport - - - - - Character - 🤽 - ShortCodes - - :water_polo: - - - - Categories - - Person Sport - - - - - Character - 🤽‍♀️ - ShortCodes - - :woman_playing_water_polo: - - - - Categories - - Person Sport - - - - - Character - 🤾‍♂️ - ShortCodes - - :man_playing_handball: - - - - Categories - - Person Sport - - - - - Character - 🤹 - ShortCodes - - :juggling_person: - - - - Categories - - Person Sport - - - - - Character - 🤹‍♀️ - ShortCodes - - :woman_juggling: - - - - Categories - - Person Sport - - - - - Character - 🏇 - ShortCodes - - :horse_racing: - - - - Categories - - Person Sport - - - - - Character - 🏂 - ShortCodes - - :snowboarder: - - - - Categories - - Person Sport - - - - - Character - 🏌️‍♂️ - ShortCodes - - :golfing_man: - - - - Categories - - Person Sport - - - - - Character - 🏄 - ShortCodes - - :surfer: - - - - Categories - - Person Sport - - - - - Character - 🏄‍♀️ - ShortCodes - - :surfing_woman: - - - - Categories - - Person Sport - - - - - Character - 🚣‍♂️ - ShortCodes - - :rowing_man: - - - - Categories - - Person Sport - - - - - Character - 🏊 - ShortCodes - - :swimmer: - - - - Categories - - Person Sport - - - - - Character - 🏊‍♀️ - ShortCodes - - :swimming_woman: - - - - Categories - - Person Sport - - - - - Character - ⛹️‍♂️ - ShortCodes - - :basketball_man: - :bouncing_ball_man: - - - Categories - - Person Sport - - - - - Character - 🏋️ - ShortCodes - - :weight_lifting: - - - - Categories - - Person Sport - - - - - Character - 🏋️‍♀️ - ShortCodes - - :weight_lifting_woman: - - - - Categories - - Person Sport - - - - - Character - 🚴‍♂️ - ShortCodes - - :biking_man: - - - - Categories - - Person Sport - - - - - Character - 🚵 - ShortCodes - - :mountain_bicyclist: - - - - Categories - - Person Sport - - - - - Character - 🚵‍♀️ - ShortCodes - - :mountain_biking_woman: - - - - Categories - - Person Sport - - - - - Character - 🤸‍♂️ - ShortCodes - - :man_cartwheeling: - - - - Categories - - Person Sport - - - - - Character - 🤼 - ShortCodes - - :wrestling: - - - - Categories - - Person Sport - - - - - Character - 🤼‍♀️ - ShortCodes - - :women_wrestling: - - - - Categories - - Person Sport - - - - - Character - 🤽‍♂️ - ShortCodes - - :man_playing_water_polo: - - - - Categories - - Person Sport - - - - - Character - 🤾 - ShortCodes - - :handball_person: - - - - Categories - - Person Sport - - - - - Character - 🤾‍♀️ - ShortCodes - - :woman_playing_handball: - - - - Categories - - Person Sport - - - - - Character - 🤹‍♂️ - ShortCodes - - :man_juggling: - - - - Categories - - Person Sport - - - - - Character - 🧘 - ShortCodes - - :lotus_position: - - - - Categories - - Person Resting - - - - - Character - 🧘‍♀️ - ShortCodes - - :lotus_position_woman: - - - - Categories - - Person Resting - - - - - Character - 🛌 - ShortCodes - - :sleeping_bed: - - - - Categories - - Person Resting - - - - - Character - 🧘‍♂️ - ShortCodes - - :lotus_position_man: - - - - Categories - - Person Resting - - - - - Character - 🛀 - ShortCodes - - :bath: - - - - Categories - - Person Resting - - - - - Character - 🧑‍🤝‍🧑 - ShortCodes - - :people_holding_hands: - - - - Categories - - Person - Family - - - - Character - 👫 - ShortCodes - - :couple: - - - - Categories - - Person - Family - - - - Character - 💏 - ShortCodes - - :couplekiss: - - - - Categories - - Person - Family - - - - Character - 👨‍❤️‍💋‍👨 - ShortCodes - - :couplekiss_man_man: - - - - Categories - - Person - Family - - - - Character - 💑 - ShortCodes - - :couple_with_heart: - - - - Categories - - Person - Family - - - - Character - 👨‍❤️‍👨 - ShortCodes - - :couple_with_heart_man_man: - - - - Categories - - Person - Family - - - - Character - 👪 - ShortCodes - - :family: - - - - Categories - - Person - Family - - - - Character - 👨‍👩‍👧 - ShortCodes - - :family_man_woman_girl: - - - - Categories - - Person - Family - - - - Character - 👨‍👩‍👦‍👦 - ShortCodes - - :family_man_woman_boy_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👨‍👦 - ShortCodes - - :family_man_man_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👨‍👧‍👦 - ShortCodes - - :family_man_man_girl_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👨‍👧‍👧 - ShortCodes - - :family_man_man_girl_girl: - - - - Categories - - Person - Family - - - - Character - 👩‍👩‍👧 - ShortCodes - - :family_woman_woman_girl: - - - - Categories - - Person - Family - - - - Character - 👩‍👩‍👦‍👦 - ShortCodes - - :family_woman_woman_boy_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👦 - ShortCodes - - :family_man_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👧 - ShortCodes - - :family_man_girl: - - - - Categories - - Person - Family - - - - Character - 👨‍👧‍👧 - ShortCodes - - :family_man_girl_girl: - - - - Categories - - Person - Family - - - - Character - 👩‍👦‍👦 - ShortCodes - - :family_woman_boy_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👧‍👦 - ShortCodes - - :family_woman_girl_boy: - - - - Categories - - Person - Family - - - - Character - 👭 - ShortCodes - - :two_women_holding_hands: - - - - Categories - - Person - Family - - - - Character - 👬 - ShortCodes - - :two_men_holding_hands: - - - - Categories - - Person - Family - - - - Character - 👩‍❤️‍💋‍👨 - ShortCodes - - :couplekiss_man_woman: - - - - Categories - - Person - Family - - - - Character - 👩‍❤️‍💋‍👩 - ShortCodes - - :couplekiss_woman_woman: - - - - Categories - - Person - Family - - - - Character - 👩‍❤️‍👨 - ShortCodes - - :couple_with_heart_woman_man: - - - - Categories - - Person - Family - - - - Character - 👩‍❤️‍👩 - ShortCodes - - :couple_with_heart_woman_woman: - - - - Categories - - Person - Family - - - - Character - 👨‍👩‍👦 - ShortCodes - - :family_man_woman_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👩‍👧‍👦 - ShortCodes - - :family_man_woman_girl_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👩‍👧‍👧 - ShortCodes - - :family_man_woman_girl_girl: - - - - Categories - - Person - Family - - - - Character - 👨‍👨‍👧 - ShortCodes - - :family_man_man_girl: - - - - Categories - - Person - Family - - - - Character - 👨‍👨‍👦‍👦 - ShortCodes - - :family_man_man_boy_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👩‍👦 - ShortCodes - - :family_woman_woman_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👩‍👧‍👦 - ShortCodes - - :family_woman_woman_girl_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👩‍👧‍👧 - ShortCodes - - :family_woman_woman_girl_girl: - - - - Categories - - Person - Family - - - - Character - 👨‍👦‍👦 - ShortCodes - - :family_man_boy_boy: - - - - Categories - - Person - Family - - - - Character - 👨‍👧‍👦 - ShortCodes - - :family_man_girl_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👦 - ShortCodes - - :family_woman_boy: - - - - Categories - - Person - Family - - - - Character - 👩‍👧 - ShortCodes - - :family_woman_girl: - - - - Categories - - Person - Family - - - - Character - 👩‍👧‍👧 - ShortCodes - - :family_woman_girl_girl: - - - - Categories - - Person - Family - - - - Character - 🗣️ - ShortCodes - - :speaking_head: - - - - Categories - - Person Symbol - - - - - Character - 👥 - ShortCodes - - :busts_in_silhouette: - - - - Categories - - Person Symbol - - - - - Character - 👣 - ShortCodes - - :footprints: - - - - Categories - - Person Symbol - - - - - Character - 👤 - ShortCodes - - :bust_in_silhouette: - - - - Categories - - Person Symbol - - - - - Character - 🫂 - ShortCodes - - :people_hugging: - - - - Categories - - Person Symbol - - - - - Character - 🐵 - ShortCodes - - :monkey_face: - - - - Categories - - Animal Mammal - - - - - Character - 🦍 - ShortCodes - - :gorilla: - - - - Categories - - Animal Mammal - - - - - Character - 🐶 - ShortCodes - - :dog: - - - - Categories - - Animal Mammal - - - - - Character - 🦮 - ShortCodes - - :guide_dog: - - - - Categories - - Animal Mammal - - - - - Character - 🐩 - ShortCodes - - :poodle: - - - - Categories - - Animal Mammal - - - - - Character - 🦊 - ShortCodes - - :fox_face: - - - - Categories - - Animal Mammal - - - - - Character - 🐱 - ShortCodes - - :cat: - - - - Categories - - Animal Mammal - - - - - Character - 🐈‍⬛ - ShortCodes - - :black_cat: - - - - Categories - - Animal Mammal - - - - - Character - 🐯 - ShortCodes - - :tiger: - - - - Categories - - Animal Mammal - - - - - Character - 🐆 - ShortCodes - - :leopard: - - - - Categories - - Animal Mammal - - - - - Character - 🐎 - ShortCodes - - :racehorse: - - - - Categories - - Animal Mammal - - - - - Character - 🦓 - ShortCodes - - :zebra: - - - - Categories - - Animal Mammal - - - - - Character - 🦬 - ShortCodes - - :bison: - - - - Categories - - Animal Mammal - - - - - Character - 🐂 - ShortCodes - - :ox: - - - - Categories - - Animal Mammal - - - - - Character - 🐄 - ShortCodes - - :cow2: - - - - Categories - - Animal Mammal - - - - - Character - 🐖 - ShortCodes - - :pig2: - - - - Categories - - Animal Mammal - - - - - Character - 🐽 - ShortCodes - - :pig_nose: - - - - Categories - - Animal Mammal - - - - - Character - 🐑 - ShortCodes - - :sheep: - - - - Categories - - Animal Mammal - - - - - Character - 🐪 - ShortCodes - - :dromedary_camel: - - - - Categories - - Animal Mammal - - - - - Character - 🦙 - ShortCodes - - :llama: - - - - Categories - - Animal Mammal - - - - - Character - 🐘 - ShortCodes - - :elephant: - - - - Categories - - Animal Mammal - - - - - Character - 🦏 - ShortCodes - - :rhinoceros: - - - - Categories - - Animal Mammal - - - - - Character - 🐭 - ShortCodes - - :mouse: - - - - Categories - - Animal Mammal - - - - - Character - 🐀 - ShortCodes - - :rat: - - - - Categories - - Animal Mammal - - - - - Character - 🐰 - ShortCodes - - :rabbit: - - - - Categories - - Animal Mammal - - - - - Character - 🐿️ - ShortCodes - - :chipmunk: - - - - Categories - - Animal Mammal - - - - - Character - 🦔 - ShortCodes - - :hedgehog: - - - - Categories - - Animal Mammal - - - - - Character - 🐻 - ShortCodes - - :bear: - - - - Categories - - Animal Mammal - - - - - Character - 🐨 - ShortCodes - - :koala: - - - - Categories - - Animal Mammal - - - - - Character - 🦥 - ShortCodes - - :sloth: - - - - Categories - - Animal Mammal - - - - - Character - 🦨 - ShortCodes - - :skunk: - - - - Categories - - Animal Mammal - - - - - Character - 🦡 - ShortCodes - - :badger: - - - - Categories - - Animal Mammal - - - - - Character - 🐒 - ShortCodes - - :monkey: - - - - Categories - - Animal Mammal - - - - - Character - 🦧 - ShortCodes - - :orangutan: - - - - Categories - - Animal Mammal - - - - - Character - 🐕 - ShortCodes - - :dog2: - - - - Categories - - Animal Mammal - - - - - Character - 🐕‍🦺 - ShortCodes - - :service_dog: - - - - Categories - - Animal Mammal - - - - - Character - 🐺 - ShortCodes - - :wolf: - - - - Categories - - Animal Mammal - - - - - Character - 🦝 - ShortCodes - - :raccoon: - - - - Categories - - Animal Mammal - - - - - Character - 🐈 - ShortCodes - - :cat2: - - - - Categories - - Animal Mammal - - - - - Character - 🦁 - ShortCodes - - :lion: - - - - Categories - - Animal Mammal - - - - - Character - 🐅 - ShortCodes - - :tiger2: - - - - Categories - - Animal Mammal - - - - - Character - 🐴 - ShortCodes - - :horse: - - - - Categories - - Animal Mammal - - - - - Character - 🦄 - ShortCodes - - :unicorn: - - - - Categories - - Animal Mammal - - - - - Character - 🦌 - ShortCodes - - :deer: - - - - Categories - - Animal Mammal - - - - - Character - 🐮 - ShortCodes - - :cow: - - - - Categories - - Animal Mammal - - - - - Character - 🐃 - ShortCodes - - :water_buffalo: - - - - Categories - - Animal Mammal - - - - - Character - 🐷 - ShortCodes - - :pig: - - - - Categories - - Animal Mammal - - - - - Character - 🐗 - ShortCodes - - :boar: - - - - Categories - - Animal Mammal - - - - - Character - 🐏 - ShortCodes - - :ram: - - - - Categories - - Animal Mammal - - - - - Character - 🐐 - ShortCodes - - :goat: - - - - Categories - - Animal Mammal - - - - - Character - 🐫 - ShortCodes - - :camel: - - - - Categories - - Animal Mammal - - - - - Character - 🦒 - ShortCodes - - :giraffe: - - - - Categories - - Animal Mammal - - - - - Character - 🦣 - ShortCodes - - :mammoth: - - - - Categories - - Animal Mammal - - - - - Character - 🦛 - ShortCodes - - :hippopotamus: - - - - Categories - - Animal Mammal - - - - - Character - 🐁 - ShortCodes - - :mouse2: - - - - Categories - - Animal Mammal - - - - - Character - 🐹 - ShortCodes - - :hamster: - - - - Categories - - Animal Mammal - - - - - Character - 🐇 - ShortCodes - - :rabbit2: - - - - Categories - - Animal Mammal - - - - - Character - 🦫 - ShortCodes - - :beaver: - - - - Categories - - Animal Mammal - - - - - Character - 🦇 - ShortCodes - - :bat: - - - - Categories - - Animal Mammal - - - - - Character - 🐻‍❄️ - ShortCodes - - :polar_bear: - - - - Categories - - Animal Mammal - - - - - Character - 🐼 - ShortCodes - - :panda_face: - - - - Categories - - Animal Mammal - - - - - Character - 🦦 - ShortCodes - - :otter: - - - - Categories - - Animal Mammal - - - - - Character - 🦘 - ShortCodes - - :kangaroo: - - - - Categories - - Animal Mammal - - - - - Character - 🐾 - ShortCodes - - :feet: - :paw_prints: - - - Categories - - Animal Mammal - - - - - Character - 🦃 - ShortCodes - - :turkey: - - - - Categories - - Animal Bird - - - - - Character - 🐓 - ShortCodes - - :rooster: - - - - Categories - - Animal Bird - - - - - Character - 🐤 - ShortCodes - - :baby_chick: - - - - Categories - - Animal Bird - - - - - Character - 🐦 - ShortCodes - - :bird: - - - - Categories - - Animal Bird - - - - - Character - 🕊️ - ShortCodes - - :dove: - - - - Categories - - Animal Bird - - - - - Character - 🦆 - ShortCodes - - :duck: - - - - Categories - - Animal Bird - - - - - Character - 🦉 - ShortCodes - - :owl: - - - - Categories - - Animal Bird - - - - - Character - 🪶 - ShortCodes - - :feather: - - - - Categories - - Animal Bird - - - - - Character - 🦚 - ShortCodes - - :peacock: - - - - Categories - - Animal Bird - - - - - Character - 🐔 - ShortCodes - - :chicken: - - - - Categories - - Animal Bird - - - - - Character - 🐣 - ShortCodes - - :hatching_chick: - - - - Categories - - Animal Bird - - - - - Character - 🐥 - ShortCodes - - :hatched_chick: - - - - Categories - - Animal Bird - - - - - Character - 🐧 - ShortCodes - - :penguin: - - - - Categories - - Animal Bird - - - - - Character - 🦅 - ShortCodes - - :eagle: - - - - Categories - - Animal Bird - - - - - Character - 🦢 - ShortCodes - - :swan: - - - - Categories - - Animal Bird - - - - - Character - 🦤 - ShortCodes - - :dodo: - - - - Categories - - Animal Bird - - - - - Character - 🦩 - ShortCodes - - :flamingo: - - - - Categories - - Animal Bird - - - - - Character - 🦜 - ShortCodes - - :parrot: - - - - Categories - - Animal Bird - - - - - Character - 🐸 - ShortCodes - - :frog: - - - - Categories - - Animal Amphibian - - - - - Character - 🐊 - ShortCodes - - :crocodile: - - - - Categories - - Animal Reptile - - - - - Character - 🦎 - ShortCodes - - :lizard: - - - - Categories - - Animal Reptile - - - - - Character - 🐲 - ShortCodes - - :dragon_face: - - - - Categories - - Animal Reptile - - - - - Character - 🦕 - ShortCodes - - :sauropod: - - - - Categories - - Animal Reptile - - - - - Character - 🐢 - ShortCodes - - :turtle: - - - - Categories - - Animal Reptile - - - - - Character - 🐍 - ShortCodes - - :snake: - - - - Categories - - Animal Reptile - - - - - Character - 🐉 - ShortCodes - - :dragon: - - - - Categories - - Animal Reptile - - - - - Character - 🦖 - ShortCodes - - :t-rex: - - - - Categories - - Animal Reptile - - - - - Character - 🐳 - ShortCodes - - :whale: - - - - Categories - - Animal Marine - - - - - Character - 🐬 - ShortCodes - - :dolphin: - :flipper: - - - Categories - - Animal Marine - - - - - Character - 🐟 - ShortCodes - - :fish: - - - - Categories - - Animal Marine - - - - - Character - 🐡 - ShortCodes - - :blowfish: - - - - Categories - - Animal Marine - - - - - Character - 🐙 - ShortCodes - - :octopus: - - - - Categories - - Animal Marine - - - - - Character - 🐋 - ShortCodes - - :whale2: - - - - Categories - - Animal Marine - - - - - Character - 🦭 - ShortCodes - - :seal: - - - - Categories - - Animal Marine - - - - - Character - 🐠 - ShortCodes - - :tropical_fish: - - - - Categories - - Animal Marine - - - - - Character - 🦈 - ShortCodes - - :shark: - - - - Categories - - Animal Marine - - - - - Character - 🐚 - ShortCodes - - :shell: - - - - Categories - - Animal Marine - - - - - Character - 🐌 - ShortCodes - - :snail: - - - - Categories - - Animal Bug - - - - - Character - 🐛 - ShortCodes - - :bug: - - - - Categories - - Animal Bug - - - - - Character - 🐝 - ShortCodes - - :bee: - :honeybee: - - - Categories - - Animal Bug - - - - - Character - 🐞 - ShortCodes - - :lady_beetle: - - - - Categories - - Animal Bug - - - - - Character - 🪳 - ShortCodes - - :cockroach: - - - - Categories - - Animal Bug - - - - - Character - 🕸️ - ShortCodes - - :spider_web: - - - - Categories - - Animal Bug - - - - - Character - 🦟 - ShortCodes - - :mosquito: - - - - Categories - - Animal Bug - - - - - Character - 🪱 - ShortCodes - - :worm: - - - - Categories - - Animal Bug - - - - - Character - 🦋 - ShortCodes - - :butterfly: - - - - Categories - - Animal Bug - - - - - Character - 🐜 - ShortCodes - - :ant: - - - - Categories - - Animal Bug - - - - - Character - 🪲 - ShortCodes - - :beetle: - - - - Categories - - Animal Bug - - - - - Character - 🦗 - ShortCodes - - :cricket: - - - - Categories - - Animal Bug - - - - - Character - 🕷️ - ShortCodes - - :spider: - - - - Categories - - Animal Bug - - - - - Character - 🦂 - ShortCodes - - :scorpion: - - - - Categories - - Animal Bug - - - - - Character - 🪰 - ShortCodes - - :fly: - - - - Categories - - Animal Bug - - - - - Character - 🦠 - ShortCodes - - :microbe: - - - - Categories - - Animal Bug - - - - - Character - 💐 - ShortCodes - - :bouquet: - - - - Categories - - Plant Flower - - - - - Character - 💮 - ShortCodes - - :white_flower: - - - - Categories - - Plant Flower - - - - - Character - 🌹 - ShortCodes - - :rose: - - - - Categories - - Plant Flower - - - - - Character - 🌺 - ShortCodes - - :hibiscus: - - - - Categories - - Plant Flower - - - - - Character - 🌼 - ShortCodes - - :blossom: - - - - Categories - - Plant Flower - - - - - Character - 🌸 - ShortCodes - - :cherry_blossom: - - - - Categories - - Plant Flower - - - - - Character - 🏵️ - ShortCodes - - :rosette: - - - - Categories - - Plant Flower - - - - - Character - 🥀 - ShortCodes - - :wilted_flower: - - - - Categories - - Plant Flower - - - - - Character - 🌻 - ShortCodes - - :sunflower: - - - - Categories - - Plant Flower - - - - - Character - 🌷 - ShortCodes - - :tulip: - - - - Categories - - Plant Flower - - - - - Character - 🌱 - ShortCodes - - :seedling: - - - - Categories - - Plant Other - - - - - Character - 🌲 - ShortCodes - - :evergreen_tree: - - - - Categories - - Plant Other - - - - - Character - 🌴 - ShortCodes - - :palm_tree: - - - - Categories - - Plant Other - - - - - Character - 🌾 - ShortCodes - - :ear_of_rice: - - - - Categories - - Plant Other - - - - - Character - ☘️ - ShortCodes - - :shamrock: - - - - Categories - - Plant Other - - - - - Character - 🍁 - ShortCodes - - :maple_leaf: - - - - Categories - - Plant Other - - - - - Character - 🍃 - ShortCodes - - :leaves: - - - - Categories - - Plant Other - - - - - Character - 🪴 - ShortCodes - - :potted_plant: - - - - Categories - - Plant Other - - - - - Character - 🌳 - ShortCodes - - :deciduous_tree: - - - - Categories - - Plant Other - - - - - Character - 🌵 - ShortCodes - - :cactus: - - - - Categories - - Plant Other - - - - - Character - 🌿 - ShortCodes - - :herb: - - - - Categories - - Plant Other - - - - - Character - 🍀 - ShortCodes - - :four_leaf_clover: - - - - Categories - - Plant Other - - - - - Character - 🍂 - ShortCodes - - :fallen_leaf: - - - - Categories - - Plant Other - - - - - Character - 🍇 - ShortCodes - - :grapes: - - - - Categories - - Food Fruit - - - - - Character - 🍉 - ShortCodes - - :watermelon: - - - - Categories - - Food Fruit - - - - - Character - 🍋 - ShortCodes - - :lemon: - - - - Categories - - Food Fruit - - - - - Character - 🍍 - ShortCodes - - :pineapple: - - - - Categories - - Food Fruit - - - - - Character - 🍎 - ShortCodes - - :apple: - - - - Categories - - Food Fruit - - - - - Character - 🍐 - ShortCodes - - :pear: - - - - Categories - - Food Fruit - - - - - Character - 🍒 - ShortCodes - - :cherries: - - - - Categories - - Food Fruit - - - - - Character - 🫐 - ShortCodes - - :blueberries: - - - - Categories - - Food Fruit - - - - - Character - 🍅 - ShortCodes - - :tomato: - - - - Categories - - Food Fruit - - - - - Character - 🥥 - ShortCodes - - :coconut: - - - - Categories - - Food Fruit - - - - - Character - 🍈 - ShortCodes - - :melon: - - - - Categories - - Food Fruit - - - - - Character - 🍊 - ShortCodes - - :mandarin: - :orange: - :tangerine: - - Categories - - Food Fruit - - - - - Character - 🍌 - ShortCodes - - :banana: - - - - Categories - - Food Fruit - - - - - Character - 🥭 - ShortCodes - - :mango: - - - - Categories - - Food Fruit - - - - - Character - 🍏 - ShortCodes - - :green_apple: - - - - Categories - - Food Fruit - - - - - Character - 🍑 - ShortCodes - - :peach: - - - - Categories - - Food Fruit - - - - - Character - 🍓 - ShortCodes - - :strawberry: - - - - Categories - - Food Fruit - - - - - Character - 🥝 - ShortCodes - - :kiwi_fruit: - - - - Categories - - Food Fruit - - - - - Character - 🫒 - ShortCodes - - :olive: - - - - Categories - - Food Fruit - - - - - Character - 🥑 - ShortCodes - - :avocado: - - - - Categories - - Food Vegetable - - - - - Character - 🥔 - ShortCodes - - :potato: - - - - Categories - - Food Vegetable - - - - - Character - 🌽 - ShortCodes - - :corn: - - - - Categories - - Food Vegetable - - - - - Character - 🫑 - ShortCodes - - :bell_pepper: - - - - Categories - - Food Vegetable - - - - - Character - 🥬 - ShortCodes - - :leafy_green: - - - - Categories - - Food Vegetable - - - - - Character - 🧄 - ShortCodes - - :garlic: - - - - Categories - - Food Vegetable - - - - - Character - 🍄 - ShortCodes - - :mushroom: - - - - Categories - - Food Vegetable - - - - - Character - 🌰 - ShortCodes - - :chestnut: - - - - Categories - - Food Vegetable - - - - - Character - 🍆 - ShortCodes - - :eggplant: - - - - Categories - - Food Vegetable - - - - - Character - 🥕 - ShortCodes - - :carrot: - - - - Categories - - Food Vegetable - - - - - Character - 🌶️ - ShortCodes - - :hot_pepper: - - - - Categories - - Food Vegetable - - - - - Character - 🥒 - ShortCodes - - :cucumber: - - - - Categories - - Food Vegetable - - - - - Character - 🥦 - ShortCodes - - :broccoli: - - - - Categories - - Food Vegetable - - - - - Character - 🧅 - ShortCodes - - :onion: - - - - Categories - - Food Vegetable - - - - - Character - 🥜 - ShortCodes - - :peanuts: - - - - Categories - - Food Vegetable - - - - - Character - 🍞 - ShortCodes - - :bread: - - - - Categories - - Food Prepared - - - - - Character - 🥖 - ShortCodes - - :baguette_bread: - - - - Categories - - Food Prepared - - - - - Character - 🥨 - ShortCodes - - :pretzel: - - - - Categories - - Food Prepared - - - - - Character - 🥞 - ShortCodes - - :pancakes: - - - - Categories - - Food Prepared - - - - - Character - 🧀 - ShortCodes - - :cheese: - - - - Categories - - Food Prepared - - - - - Character - 🍗 - ShortCodes - - :poultry_leg: - - - - Categories - - Food Prepared - - - - - Character - 🥓 - ShortCodes - - :bacon: - - - - Categories - - Food Prepared - - - - - Character - 🍟 - ShortCodes - - :fries: - - - - Categories - - Food Prepared - - - - - Character - 🌭 - ShortCodes - - :hotdog: - - - - Categories - - Food Prepared - - - - - Character - 🌮 - ShortCodes - - :taco: - - - - Categories - - Food Prepared - - - - - Character - 🫔 - ShortCodes - - :tamale: - - - - Categories - - Food Prepared - - - - - Character - 🧆 - ShortCodes - - :falafel: - - - - Categories - - Food Prepared - - - - - Character - 🍳 - ShortCodes - - :fried_egg: - - - - Categories - - Food Prepared - - - - - Character - 🍲 - ShortCodes - - :stew: - - - - Categories - - Food Prepared - - - - - Character - 🥣 - ShortCodes - - :bowl_with_spoon: - - - - Categories - - Food Prepared - - - - - Character - 🍿 - ShortCodes - - :popcorn: - - - - Categories - - Food Prepared - - - - - Character - 🧂 - ShortCodes - - :salt: - - - - Categories - - Food Prepared - - - - - Character - 🥐 - ShortCodes - - :croissant: - - - - Categories - - Food Prepared - - - - - Character - 🫓 - ShortCodes - - :flatbread: - - - - Categories - - Food Prepared - - - - - Character - 🥯 - ShortCodes - - :bagel: - - - - Categories - - Food Prepared - - - - - Character - 🧇 - ShortCodes - - :waffle: - - - - Categories - - Food Prepared - - - - - Character - 🍖 - ShortCodes - - :meat_on_bone: - - - - Categories - - Food Prepared - - - - - Character - 🥩 - ShortCodes - - :cut_of_meat: - - - - Categories - - Food Prepared - - - - - Character - 🍔 - ShortCodes - - :hamburger: - - - - Categories - - Food Prepared - - - - - Character - 🍕 - ShortCodes - - :pizza: - - - - Categories - - Food Prepared - - - - - Character - 🥪 - ShortCodes - - :sandwich: - - - - Categories - - Food Prepared - - - - - Character - 🌯 - ShortCodes - - :burrito: - - - - Categories - - Food Prepared - - - - - Character - 🥙 - ShortCodes - - :stuffed_flatbread: - - - - Categories - - Food Prepared - - - - - Character - 🥚 - ShortCodes - - :egg: - - - - Categories - - Food Prepared - - - - - Character - 🥘 - ShortCodes - - :shallow_pan_of_food: - - - - Categories - - Food Prepared - - - - - Character - 🫕 - ShortCodes - - :fondue: - - - - Categories - - Food Prepared - - - - - Character - 🥗 - ShortCodes - - :green_salad: - - - - Categories - - Food Prepared - - - - - Character - 🧈 - ShortCodes - - :butter: - - - - Categories - - Food Prepared - - - - - Character - 🥫 - ShortCodes - - :canned_food: - - - - Categories - - Food Prepared - - - - - Character - 🍱 - ShortCodes - - :bento: - - - - Categories - - Food Asian - - - - - Character - 🍙 - ShortCodes - - :rice_ball: - - - - Categories - - Food Asian - - - - - Character - 🍛 - ShortCodes - - :curry: - - - - Categories - - Food Asian - - - - - Character - 🍝 - ShortCodes - - :spaghetti: - - - - Categories - - Food Asian - - - - - Character - 🍢 - ShortCodes - - :oden: - - - - Categories - - Food Asian - - - - - Character - 🍤 - ShortCodes - - :fried_shrimp: - - - - Categories - - Food Asian - - - - - Character - 🥮 - ShortCodes - - :moon_cake: - - - - Categories - - Food Asian - - - - - Character - 🥟 - ShortCodes - - :dumpling: - - - - Categories - - Food Asian - - - - - Character - 🥡 - ShortCodes - - :takeout_box: - - - - Categories - - Food Asian - - - - - Character - 🍘 - ShortCodes - - :rice_cracker: - - - - Categories - - Food Asian - - - - - Character - 🍚 - ShortCodes - - :rice: - - - - Categories - - Food Asian - - - - - Character - 🍜 - ShortCodes - - :ramen: - - - - Categories - - Food Asian - - - - - Character - 🍠 - ShortCodes - - :sweet_potato: - - - - Categories - - Food Asian - - - - - Character - 🍣 - ShortCodes - - :sushi: - - - - Categories - - Food Asian - - - - - Character - 🍥 - ShortCodes - - :fish_cake: - - - - Categories - - Food Asian - - - - - Character - 🍡 - ShortCodes - - :dango: - - - - Categories - - Food Asian - - - - - Character - 🥠 - ShortCodes - - :fortune_cookie: - - - - Categories - - Food Asian - - - - - -- cgit v1.2.3 From 12e044755e9d9cf886ceb63ef7af3010303d31c4 Mon Sep 17 00:00:00 2001 From: Callum Prentice Date: Mon, 10 Apr 2023 17:01:10 -0700 Subject: SL-19078: changes to autobuild to unpack the emoji/shortcode 3p library and then copy the XML files to the right place in the Viewer dev tree (indra/newview/skins/xui/*/emoji_characters.xml) --- indra/cmake/ViewerMiscLibs.cmake | 1 + indra/newview/CMakeLists.txt | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'indra') diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index 7eed456833..cae68fbc11 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -20,3 +20,4 @@ use_prebuilt_binary(slvoice) use_prebuilt_binary(nanosvg) use_prebuilt_binary(viewer-fonts) +use_prebuilt_binary(emoji_shortcodes) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b63100fc2b..ab0c60a402 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1917,6 +1917,22 @@ file(GLOB FONT_FILE_GLOB_LIST ) file(COPY ${FONT_FILE_GLOB_LIST} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/fonts") +# Copy over the Emoji/shortcodes mapping XML files (and create dependency +# if they are changed, CMake will run again and copy over new versions) +message("Copying Emoji/shortcode mappings") +set(emoji_mapping_src_folder ${AUTOBUILD_INSTALL_DIR}/xui) +set(emoji_mapping_dst_folder ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui) + +# Note Turkey is missing from this set (not available in Emoji package yet) +set(country_codes "da;de;en;es;fr;it;ja;pl;pt;ru;zh") +foreach(elem ${country_codes}) + set(emoji_mapping_src_file + "${emoji_mapping_src_folder}/${elem}/emoji_characters.xml") + set(emoji_mapping_dst_file + "${emoji_mapping_dst_folder}/${elem}/emoji_characters.xml") + configure_file(${emoji_mapping_src_file} ${emoji_mapping_dst_file} COPYONLY) +endforeach() + if (LINUX) set(product SecondLife-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) -- cgit v1.2.3 From ff7ebf08922293c1623b7bdb8c9923c14fc9db48 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 14 Apr 2023 07:44:56 +0200 Subject: SL-19575 Create emoji gallery access icon --- indra/llui/llemojidictionary.h | 2 + indra/llui/llemojihelper.cpp | 10 +- indra/llui/llemojihelper.h | 6 +- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/lltexteditor.cpp | 22 ++-- indra/llui/lltexteditor.h | 3 +- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloateremojipicker.cpp | 143 +++++++++++++++++++++ indra/newview/llfloateremojipicker.h | 59 +++++++++ indra/newview/llfloaterimsessiontab.cpp | 30 ++++- indra/newview/llfloaterimsessiontab.h | 4 + indra/newview/llviewerfloaterreg.cpp | 20 +-- .../default/textures/icons/emoji_picker_icon.png | Bin 0 -> 316 bytes indra/newview/skins/default/textures/textures.xml | 5 +- .../skins/default/xui/en/floater_emoji_picker.xml | 39 ++++++ .../skins/default/xui/en/floater_im_session.xml | 14 +- indra/newview/skins/default/xui/en/strings.xml | 10 +- 17 files changed, 335 insertions(+), 36 deletions(-) create mode 100644 indra/newview/llfloateremojipicker.cpp create mode 100644 indra/newview/llfloateremojipicker.h create mode 100644 indra/newview/skins/default/textures/icons/emoji_picker_icon.png create mode 100644 indra/newview/skins/default/xui/en/floater_emoji_picker.xml (limited to 'indra') diff --git a/indra/llui/llemojidictionary.h b/indra/llui/llemojidictionary.h index 46a61f1cd7..adc22ced58 100644 --- a/indra/llui/llemojidictionary.h +++ b/indra/llui/llemojidictionary.h @@ -61,6 +61,8 @@ public: const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const; std::string getNameFromEmoji(llwchar ch) const; + const std::map& getEmoji2Descr() const { return mEmoji2Descr; } + private: void addEmoji(LLEmojiDescriptor&& descr); diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index 1e4c19a183..fb660a9e5b 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -82,12 +82,12 @@ bool LLEmojiHelper::isCursorInEmojiCode(const LLWString& wtext, S32 cursorPos, S return isShortCode; } -void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function cb) +void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function 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)); + cb(emojiDescrp->Character); hideHelper(); return; } @@ -96,7 +96,7 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c { 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)); + mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); } setHostCtrl(hostctrl_p); mEmojiCommitCb = cb; @@ -135,11 +135,11 @@ bool LLEmojiHelper::handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask) return mHelperHandle.get()->handleKey(key, mask, true); } -void LLEmojiHelper::onCommitEmoji(const LLWString& wstr) +void LLEmojiHelper::onCommitEmoji(llwchar emoji) { if (!mHostHandle.isDead() && mEmojiCommitCb) { - mEmojiCommitCb(wstr); + mEmojiCommitCb(emoji); } } diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 63f5c640c9..58f68d12a4 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -44,12 +44,12 @@ public: 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 commit_cb); + void showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, const std::string& short_code, std::function 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); + void onCommitEmoji(llwchar emoji); protected: LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } @@ -60,5 +60,5 @@ private: LLHandle mHelperHandle; boost::signals2::connection mHostCtrlFocusLostConn; boost::signals2::connection mHelperCommitConn; - std::function mEmojiCommitCb; + std::function mEmojiCommitCb; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 219667f766..2a6e8a6b76 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -411,7 +411,7 @@ void LLScrollListCtrl::clearRows() LLScrollListItem* LLScrollListCtrl::getFirstSelected() const { item_list::const_iterator iter; - for(iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; if (item->getSelected()) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index a85ac2a5a3..95d8b666ab 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -680,18 +680,24 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p endSelection(); } -void LLTextEditor::handleEmojiCommit(const LLWString& wstr) +void LLTextEditor::insertEmoji(llwchar emoji) { - LLWString wtext(getWText()); S32 shortCodePos; - if (LLEmojiHelper::isCursorInEmojiCode(wtext, mCursorPos, &shortCodePos)) + auto styleParams = LLStyle::Params(); + styleParams.font = LLFontGL::getFontEmoji(); + auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); + insert(mCursorPos, LLWString(1, emoji), false, segment); + setCursorPos(mCursorPos + 1); +} + +void LLTextEditor::handleEmojiCommit(llwchar emoji) +{ + S32 shortCodePos; + if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos)) { remove(shortCodePos, mCursorPos - shortCodePos, true); + setCursorPos(shortCodePos); - 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); + insertEmoji(emoji); } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index dabd0460c6..f830732cb8 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -92,7 +92,8 @@ public: static S32 spacesPerTab(); - void handleEmojiCommit(const LLWString& wstr); + void insertEmoji(llwchar emoji); + void handleEmojiCommit(llwchar emoji); // mousehandler overrides virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ab0c60a402..1f8b937965 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -205,6 +205,7 @@ set(viewer_SOURCE_FILES llfloaterdisplayname.cpp llfloatereditenvironmentbase.cpp llfloatereditextdaycycle.cpp + llfloateremojipicker.cpp llfloaterenvironmentadjust.cpp llfloaterevent.cpp llfloaterexperiencepicker.cpp @@ -845,6 +846,7 @@ set(viewer_HEADER_FILES llfloaterdisplayname.h llfloatereditenvironmentbase.h llfloatereditextdaycycle.h + llfloateremojipicker.h llfloaterenvironmentadjust.h llfloaterevent.h llfloaterexperiencepicker.h diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp new file mode 100644 index 0000000000..c828a95a59 --- /dev/null +++ b/indra/newview/llfloateremojipicker.cpp @@ -0,0 +1,143 @@ +/** + * @file llfloateremojipicker.cpp + * + * $LicenseInfo:firstyear=2003&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 "llviewerprecompiledheaders.h" + +#include "llfloateremojipicker.h" + +#include "llfloaterreg.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "llemojidictionary.h" + +class LLEmojiScrollListItem : public LLScrollListItem +{ +public: + LLEmojiScrollListItem(const llwchar emoji, const LLScrollListItem::Params& params) + : LLScrollListItem(params) + , mEmoji(emoji) + { + } + + llwchar getEmoji() const { return mEmoji; } + + virtual void draw(const LLRect& rect, + const LLColor4& fg_color, + const LLColor4& hover_color, // highlight/hover selection of whole item or cell + const LLColor4& select_color, // highlight/hover selection of whole item or cell + const LLColor4& highlight_color, // highlights contents of cells (ex: text) + S32 column_padding) override + { + LLScrollListItem::draw(rect, fg_color, hover_color, select_color, highlight_color, column_padding); + + S32 width = getColumn(0)->getWidth(); + LLFontGL::getFontEmoji()->render(LLWString(1, mEmoji), 0, rect.mLeft + width / 2, rect.getCenterY(), LLColor4::white, + LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true); + } + +private: + llwchar mEmoji; +}; + +LLFloaterEmojiPicker* LLFloaterEmojiPicker::getInstance() +{ + LLFloaterEmojiPicker* floater = LLFloaterReg::getTypedInstance("emoji_picker"); + if (!floater) + LL_WARNS() << "Cannot instantiate emoji picker" << LL_ENDL; + return floater; +} + +LLFloaterEmojiPicker* LLFloaterEmojiPicker::showInstance(select_callback_t callback) +{ + LLFloaterEmojiPicker* floater = getInstance(); + if (LLFloaterEmojiPicker* floater = getInstance()) + floater->show(callback); + return floater; +} + +void LLFloaterEmojiPicker::show(select_callback_t callback) +{ + mSelectCallback = callback; + openFloater(mKey); + setFocus(TRUE); +} + +LLFloaterEmojiPicker::LLFloaterEmojiPicker(const LLSD& key) +: LLFloater(key) +{ +} + +BOOL LLFloaterEmojiPicker::postBuild() +{ + if (mEmojis = getChild("Emojis")) + { + mEmojis->setDoubleClickCallback(boost::bind(&LLFloaterEmojiPicker::onSelect, this)); + + mEmojis->clearRows(); + + const std::map& emoji2Descr = LLEmojiDictionary::instance().getEmoji2Descr(); + for (const std::pair& it : emoji2Descr) + { + LLScrollListItem::Params params; + params.columns.add().column("name").value(it.second->Name); + mEmojis->addRow(new LLEmojiScrollListItem(it.first, params), params); + } + } + + return TRUE; +} + +LLFloaterEmojiPicker::~LLFloaterEmojiPicker() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +void LLFloaterEmojiPicker::onSelect() +{ + if (mEmojis && mSelectCallback) + { + if (LLEmojiScrollListItem* item = dynamic_cast(mEmojis->getFirstSelected())) + { + mSelectCallback(item->getEmoji()); + } + } +} + +// virtual +BOOL LLFloaterEmojiPicker::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_RETURN && mask == MASK_NONE) + { + onSelect(); + return TRUE; + } + else if (key == KEY_ESCAPE && mask == MASK_NONE) + { + closeFloater(); + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); +} diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h new file mode 100644 index 0000000000..9b442064d0 --- /dev/null +++ b/indra/newview/llfloateremojipicker.h @@ -0,0 +1,59 @@ +/** + * @file llfloateremojipicker.h + * @brief Header file for llfloateremojipicker + * + * $LicenseInfo:firstyear=2003&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$ + */ + +#ifndef LLFLOATEREMOJIPICKER_H +#define LLFLOATEREMOJIPICKER_H + +#include "llfloater.h" + +class LLFloaterEmojiPicker : public LLFloater +{ +public: + // The callback function will be called with an emoji char. + typedef boost::function select_callback_t; + + // Call this to select an emoji. + static LLFloaterEmojiPicker* getInstance(); + static LLFloaterEmojiPicker* showInstance(select_callback_t callback); + + LLFloaterEmojiPicker(const LLSD& key); + virtual ~LLFloaterEmojiPicker(); + + virtual BOOL postBuild(); + + void show(select_callback_t callback); + +private: + void onSelect(); + + virtual BOOL handleKeyHere(KEY key, MASK mask); + + class LLScrollListCtrl* mEmojis; + select_callback_t mSelectCallback; + std::string mEmojiName; +}; + +#endif diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 78271369d2..3d9751dd35 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -40,6 +40,7 @@ #include "llchicletbar.h" #include "lldraghandle.h" #include "llfloaterreg.h" +#include "llfloateremojipicker.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container #include "lllayoutstack.h" @@ -250,10 +251,13 @@ BOOL LLFloaterIMSessionTab::postBuild() mTearOffBtn = getChild("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); + mEmojiBtn = getChild("emoji_panel_btn"); + mEmojiBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onEmojiPanelBtnClicked, this)); + mGearBtn = getChild("gear_btn"); mAddBtn = getChild("add_btn"); mVoiceButton = getChild("voice_call_btn"); - + mParticipantListPanel = getChild("speakers_list_panel"); mRightPartPanel = getChild("right_part_holder"); @@ -424,6 +428,30 @@ void LLFloaterIMSessionTab::onInputEditorClicked() gToolBarView->flashCommand(LLCommandId("chat"), false); } +void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self) +{ + if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance()) + { + if (!picker->isShown()) + { + picker->show(boost::bind(&LLFloaterIMSessionTab::onEmojiSelected, self, _1)); + if (LLFloater* root_floater = gFloaterView->getParentFloater(self)) + { + root_floater->addDependentFloater(picker); + } + } + else + { + picker->closeFloater(); + } + } +} + +void LLFloaterIMSessionTab::onEmojiSelected(llwchar emoji) +{ + mInputEditor->insertEmoji(emoji); +} + std::string LLFloaterIMSessionTab::appendTime() { time_t utc_time; diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 9f00917647..cd5065420d 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -181,6 +181,7 @@ protected: LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; + LLButton* mEmojiBtn; LLButton* mCloseBtn; LLButton* mGearBtn; LLButton* mAddBtn; @@ -206,6 +207,9 @@ private: void onInputEditorClicked(); + static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self); + void onEmojiSelected(llwchar emoji); + bool checkIfTornOff(); bool mIsHostAttached; bool mHasVisibleBeenInitialized; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1c1aa9ea47..483b22adc8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -65,6 +65,7 @@ #include "llfloaterdestinations.h" #include "llfloaterdisplayname.h" #include "llfloatereditextdaycycle.h" +#include "llfloateremojipicker.h" #include "llfloaterenvironmentadjust.h" #include "llfloaterexperienceprofile.h" #include "llfloaterexperiences.h" @@ -329,7 +330,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); - LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -337,19 +338,20 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", &LLFloaterReg::build); + LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/textures/icons/emoji_picker_icon.png b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png new file mode 100644 index 0000000000..668dcaf193 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/emoji_picker_icon.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 1f2c0867c4..f69f1df71a 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -205,6 +205,7 @@ with the same filename but different name + @@ -212,7 +213,7 @@ with the same filename but different name - + @@ -328,7 +329,7 @@ with the same filename but different name - + diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml new file mode 100644 index 0000000000..a3e504cc31 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index da84fbeea6..1592352d1b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -297,8 +297,20 @@ tab_group="3" bottom="-8" left_pad="5" - right="-5" + right="-30" wrap="true" /> +