Blame SOURCES/0001-Make-Noto-Color-Emoji-font-work-on-Linux.patch

2ceb93
From 96012f88aac95147ae1fd4834cea5c5bb184d52b Mon Sep 17 00:00:00 2001
2ceb93
From: Khaled Hosny <khaledhosny@eglug.org>
2ceb93
Date: Tue, 27 Aug 2019 15:19:15 +0200
2ceb93
Subject: [PATCH] Make Noto Color Emoji font work on Linux
2ceb93
MIME-Version: 1.0
2ceb93
Content-Type: text/plain; charset=UTF-8
2ceb93
Content-Transfer-Encoding: 8bit
2ceb93
2ceb93
Noto Color Emoji is a bitmap color font, Cairo knows how to scale such
2ceb93
fonts and FontConfig will identify them as scalable but not outline
2ceb93
fonts, so change the FontConfig checks to checks for scalability.
2ceb93
2ceb93
Make sft.cxx:doOpenTTFont() accept non-outline fonts, the text will not
2ceb93
show in PDF but that is not worse than the status quo.
2ceb93
2ceb93
Reviewed-on: https://gerrit.libreoffice.org/78218
2ceb93
Tested-by: Jenkins
2ceb93
Reviewed-by: Khaled Hosny <khaledhosny@eglug.org>
2ceb93
(cherry picked from commit dcf7792da2aa2a1ef774a124f7b21f68fff0fd15)
2ceb93
2ceb93
Change-Id: I756c718296d2c43e3165cd2f07b11bbb981318d3
2ceb93
2ceb93
Related: rhbz#1648281 improve fontconfig fallback for emojis
2ceb93
2ceb93
disregard text language for emoji and tag with und-zsye to
2ceb93
get fontconfig to give us the default emoji font
2ceb93
2ceb93
Change-Id: I8f94b0c41dea3204c9db77b96ad8f0d98bae2239
2ceb93
2ceb93
ctrl+shift+e emoji ibus engine problems converting UCS-4 positions to UTF-16
2ceb93
2ceb93
e.g. ctrl+shift+e type rabbit then space in writer and the len of underline
2ceb93
is 2 which should encompass the displayed e + 2 UTF-16 units
2ceb93
2ceb93
Change-Id: I424db7dd6cbcc5845922ac17208fed643e672dbd
2ceb93
2ceb93
rework IM underline impl wrt mix of UTF-8/16/32 units
2ceb93
2ceb93
e.g. ctrl+shift+e type boy then space twice in writer. The UTF-32 units
2ceb93
are 0x65 0x1f466 0x1f3fb. The underline should encompass the whole range,
2ceb93
prior to this the trailing Emoji Modifier Fitzpatrick was separated from
2ceb93
the boy base emoji by an incomplete underline
2ceb93
2ceb93
Reviewed-on: https://gerrit.libreoffice.org/78878
2ceb93
Tested-by: Jenkins
2ceb93
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2ceb93
Tested-by: Caolán McNamara <caolanm@redhat.com>
2ceb93
(cherry picked from commit 5e4d564e27d062a48fd04cb7263b769819dd3a50)
2ceb93
2ceb93
Change-Id: I2e846e8eeedf96f341ed7f50d504883768e9eff0
2ceb93
---
2ceb93
 vcl/source/font/fontmetric.cxx                |  4 +-
2ceb93
 vcl/source/fontsubset/sft.cxx                 |  5 +-
2ceb93
 vcl/unx/generic/fontmanager/fontconfig.cxx    | 60 +++++++++--------
2ceb93
 .../generic/glyphs/freetype_glyphcache.cxx    |  6 +-
2ceb93
 vcl/unx/gtk3/gtk3gtkframe.cxx                 | 64 +++++++++++++------
2ceb93
 5 files changed, 87 insertions(+), 52 deletions(-)
2ceb93
2ceb93
diff --git a/vcl/source/font/fontmetric.cxx b/vcl/source/font/fontmetric.cxx
2ceb93
index cd0b9f8557e9..816525c8773e 100644
2ceb93
--- a/vcl/source/font/fontmetric.cxx
2ceb93
+++ b/vcl/source/font/fontmetric.cxx
2ceb93
@@ -462,8 +462,8 @@ void ImplFontMetricData::ImplCalcLineSpacing(const std::vector<uint8_t>& rHheaDa
2ceb93
     if (mnAscent || mnDescent)
2ceb93
         mnIntLeading = mnAscent + mnDescent - mnHeight;
2ceb93
 
2ceb93
-    SAL_INFO("vcl.gdi.fontmetric",
2ceb93
-                  "fsSelection: "   << rInfo.fsSelection
2ceb93
+    SAL_INFO("vcl.gdi.fontmetric", GetFamilyName()
2ceb93
+             << ": fsSelection: "   << rInfo.fsSelection
2ceb93
              << ", typoAscender: "  << rInfo.typoAscender
2ceb93
              << ", typoDescender: " << rInfo.typoDescender
2ceb93
              << ", typoLineGap: "   << rInfo.typoLineGap
2ceb93
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx
2ceb93
index 365b9401b95e..04921294ab21 100644
2ceb93
--- a/vcl/source/fontsubset/sft.cxx
2ceb93
+++ b/vcl/source/fontsubset/sft.cxx
2ceb93
@@ -1666,7 +1666,10 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
2ceb93
         /* TODO: implement to get subsetting */
2ceb93
         assert(t->goffsets != nullptr);
2ceb93
     } else {
2ceb93
-        return SF_TTFORMAT;
2ceb93
+        // Bitmap font, accept for now.
2ceb93
+        t->goffsets = static_cast<sal_uInt32 *>(calloc(1+t->nglyphs, sizeof(sal_uInt32)));
2ceb93
+        /* TODO: implement to get subsetting */
2ceb93
+        assert(t->goffsets != nullptr);
2ceb93
     }
2ceb93
 
2ceb93
     table = getTable(t, O_hhea);
2ceb93
diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx b/vcl/unx/generic/fontmanager/fontconfig.cxx
2ceb93
index 2c16e040cdab..33c50d082912 100644
2ceb93
--- a/vcl/unx/generic/fontmanager/fontconfig.cxx
2ceb93
+++ b/vcl/unx/generic/fontmanager/fontconfig.cxx
2ceb93
@@ -67,7 +67,7 @@ namespace
2ceb93
 
2ceb93
 class FontCfgWrapper
2ceb93
 {
2ceb93
-    FcFontSet* m_pOutlineSet;
2ceb93
+    FcFontSet* m_pFontSet;
2ceb93
 
2ceb93
     void addFontSet( FcSetName );
2ceb93
 
2ceb93
@@ -95,19 +95,15 @@ private:
2ceb93
 };
2ceb93
 
2ceb93
 FontCfgWrapper::FontCfgWrapper()
2ceb93
-    :
2ceb93
-        m_pOutlineSet( nullptr ),
2ceb93
-        m_pLanguageTag( nullptr )
2ceb93
+    : m_pFontSet(nullptr)
2ceb93
+    , m_pLanguageTag(nullptr)
2ceb93
 {
2ceb93
     FcInit();
2ceb93
 }
2ceb93
 
2ceb93
 void FontCfgWrapper::addFontSet( FcSetName eSetName )
2ceb93
 {
2ceb93
-    /*
2ceb93
-      add only acceptable outlined fonts to our config,
2ceb93
-      for future fontconfig use
2ceb93
-    */
2ceb93
+    // Add only acceptable fonts to our config, for future fontconfig use.
2ceb93
     FcFontSet* pOrig = FcConfigGetFonts( FcConfigGetCurrent(), eSetName );
2ceb93
     if( !pOrig )
2ceb93
         return;
2ceb93
@@ -116,10 +112,12 @@ void FontCfgWrapper::addFontSet( FcSetName eSetName )
2ceb93
     for( int i = 0; i < pOrig->nfont; ++i )
2ceb93
     {
2ceb93
         FcPattern* pPattern = pOrig->fonts[i];
2ceb93
-        // #i115131# ignore non-outline fonts
2ceb93
-        FcBool bOutline = FcFalse;
2ceb93
-        FcResult eOutRes = FcPatternGetBool( pPattern, FC_OUTLINE, 0, &bOutline );
2ceb93
-        if( (eOutRes != FcResultMatch) || (bOutline == FcFalse) )
2ceb93
+        // #i115131# ignore non-scalable fonts
2ceb93
+        // Scalable fonts are usually outline fonts, but some bitmaps fonts
2ceb93
+        // (like Noto Color Emoji) are also scalable.
2ceb93
+        FcBool bScalable = FcFalse;
2ceb93
+        FcResult eScalableRes = FcPatternGetBool(pPattern, FC_SCALABLE, 0, &bScalable);
2ceb93
+        if ((eScalableRes != FcResultMatch) || (bScalable == FcFalse))
2ceb93
             continue;
2ceb93
 
2ceb93
         // Ignore Type 1 fonts, too.
2ceb93
@@ -129,7 +127,7 @@ void FontCfgWrapper::addFontSet( FcSetName eSetName )
2ceb93
             continue;
2ceb93
 
2ceb93
         FcPatternReference( pPattern );
2ceb93
-        FcFontSetAdd( m_pOutlineSet, pPattern );
2ceb93
+        FcFontSetAdd( m_pFontSet, pPattern );
2ceb93
     }
2ceb93
 
2ceb93
     // TODO?: FcFontSetDestroy( pOrig );
2ceb93
@@ -220,16 +218,16 @@ namespace
2ceb93
 
2ceb93
 FcFontSet* FontCfgWrapper::getFontSet()
2ceb93
 {
2ceb93
-    if( !m_pOutlineSet )
2ceb93
+    if( !m_pFontSet )
2ceb93
     {
2ceb93
-        m_pOutlineSet = FcFontSetCreate();
2ceb93
+        m_pFontSet = FcFontSetCreate();
2ceb93
         addFontSet( FcSetSystem );
2ceb93
         addFontSet( FcSetApplication );
2ceb93
 
2ceb93
-        ::std::sort(m_pOutlineSet->fonts,m_pOutlineSet->fonts+m_pOutlineSet->nfont,SortFont());
2ceb93
+        ::std::sort(m_pFontSet->fonts,m_pFontSet->fonts+m_pFontSet->nfont,SortFont());
2ceb93
     }
2ceb93
 
2ceb93
-    return m_pOutlineSet;
2ceb93
+    return m_pFontSet;
2ceb93
 }
2ceb93
 
2ceb93
 FontCfgWrapper::~FontCfgWrapper()
2ceb93
@@ -376,10 +374,10 @@ void FontCfgWrapper::clear()
2ceb93
 {
2ceb93
     m_aFontNameToLocalized.clear();
2ceb93
     m_aLocalizedToCanonical.clear();
2ceb93
-    if( m_pOutlineSet )
2ceb93
+    if( m_pFontSet )
2ceb93
     {
2ceb93
-        FcFontSetDestroy( m_pOutlineSet );
2ceb93
-        m_pOutlineSet = nullptr;
2ceb93
+        FcFontSetDestroy( m_pFontSet );
2ceb93
+        m_pFontSet = nullptr;
2ceb93
     }
2ceb93
     delete m_pLanguageTag;
2ceb93
     m_pLanguageTag = nullptr;
2ceb93
@@ -499,7 +497,7 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
2ceb93
             int width = 0;
2ceb93
             int spacing = 0;
2ceb93
             int nCollectionEntry = -1;
2ceb93
-            FcBool outline = false;
2ceb93
+            FcBool scalable = false;
2ceb93
 
2ceb93
             FcResult eFileRes         = FcPatternGetString(pFSet->fonts[i], FC_FILE, 0, &file;;
2ceb93
             FcResult eFamilyRes       = rWrapper.LocalizedElementFromPattern( pFSet->fonts[i], &family, FC_FAMILY, FC_FAMILYLANG );
2ceb93
@@ -510,11 +508,11 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
2ceb93
             FcResult eWeightRes       = FcPatternGetInteger(pFSet->fonts[i], FC_WEIGHT, 0, &weight);
2ceb93
             FcResult eWidthRes        = FcPatternGetInteger(pFSet->fonts[i], FC_WIDTH, 0, &width);
2ceb93
             FcResult eSpacRes         = FcPatternGetInteger(pFSet->fonts[i], FC_SPACING, 0, &spacing);
2ceb93
-            FcResult eOutRes          = FcPatternGetBool(pFSet->fonts[i], FC_OUTLINE, 0, &outline);
2ceb93
+            FcResult eScalableRes     = FcPatternGetBool(pFSet->fonts[i], FC_SCALABLE, 0, &scalable);
2ceb93
             FcResult eIndexRes        = FcPatternGetInteger(pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntry);
2ceb93
             FcResult eFormatRes       = FcPatternGetString(pFSet->fonts[i], FC_FONTFORMAT, 0, &format);
2ceb93
 
2ceb93
-            if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch )
2ceb93
+            if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eScalableRes != FcResultMatch )
2ceb93
                 continue;
2ceb93
 
2ceb93
 #if (OSL_DEBUG_LEVEL > 2)
2ceb93
@@ -528,14 +526,15 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
2ceb93
                      , eWeightRes == FcResultMatch ? width : -1
2ceb93
                      , eSpacRes == FcResultMatch ? spacing : -1
2ceb93
                      , eOutRes == FcResultMatch ? outline : -1
2ceb93
+                     , eScalableRes == FcResultMatch ? scalable : -1
2ceb93
                      , eFormatRes == FcResultMatch ? (const char*)format : "<unknown>"
2ceb93
                      );
2ceb93
 #endif
2ceb93
 
2ceb93
-//            OSL_ASSERT(eOutRes != FcResultMatch || outline);
2ceb93
+//            OSL_ASSERT(eScalableRes != FcResultMatch || scalable);
2ceb93
 
2ceb93
-            // only outline fonts are usable to psprint anyway
2ceb93
-            if( eOutRes == FcResultMatch && ! outline )
2ceb93
+            // only scalable fonts are usable to psprint anyway
2ceb93
+            if( eScalableRes == FcResultMatch && ! scalable )
2ceb93
                 continue;
2ceb93
 
2ceb93
             if (isPreviouslyDuplicateOrObsoleted(pFSet, i))
2ceb93
@@ -807,6 +806,11 @@ namespace
2ceb93
 #endif
2ceb93
     }
2ceb93
 
2ceb93
+    bool isEmoji(sal_uInt32 nCurrentChar)
2ceb93
+    {
2ceb93
+        return u_hasBinaryProperty(nCurrentChar, UCHAR_EMOJI);
2ceb93
+    }
2ceb93
+
2ceb93
     //returns true if the given code-point couldn't possibly be in rLangTag.
2ceb93
     bool isImpossibleCodePointForLang(const LanguageTag &rLangTag, sal_uInt32 currentChar)
2ceb93
     {
2ceb93
@@ -855,6 +859,8 @@ namespace
2ceb93
 
2ceb93
     OUString getExemplarLangTagForCodePoint(sal_uInt32 currentChar)
2ceb93
     {
2ceb93
+        if (isEmoji(currentChar))
2ceb93
+            return "und-zsye";
2ceb93
         int32_t script = u_getIntPropertyValue(currentChar, UCHAR_SCRIPT);
2ceb93
         UScriptCode eScript = static_cast<UScriptCode>(script);
2ceb93
         OStringBuffer aBuf(unicode::getExemplarLanguageForUScriptCode(eScript));
2ceb93
@@ -981,7 +987,7 @@ void PrintFontManager::Substitute( FontSelectPattern &rPattern, OUString& rMissi
2ceb93
             FcCharSetAddChar( codePoints, nCode );
2ceb93
             //if the codepoint is impossible for this lang tag, then clear it
2ceb93
             //and autodetect something useful
2ceb93
-            if (!aLangAttrib.isEmpty() && isImpossibleCodePointForLang(aLangTag, nCode))
2ceb93
+            if (!aLangAttrib.isEmpty() && (isImpossibleCodePointForLang(aLangTag, nCode) || isEmoji(nCode)))
2ceb93
                 aLangAttrib.clear();
2ceb93
             //#i105784#/rhbz#527719  improve selection of fallback font
2ceb93
             if (aLangAttrib.isEmpty())
2ceb93
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
2ceb93
index 5a55ee47bff3..0b03f428c3fa 100644
2ceb93
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
2ceb93
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
2ceb93
@@ -409,9 +409,9 @@ FreetypeFont::FreetypeFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI
2ceb93
 
2ceb93
     FT_New_Size( maFaceFT, &maSizeFT );
2ceb93
     FT_Activate_Size( maSizeFT );
2ceb93
-    FT_Error rc = FT_Set_Pixel_Sizes( maFaceFT, mnWidth, rFSD.mnHeight );
2ceb93
-    if( rc != FT_Err_Ok )
2ceb93
-        return;
2ceb93
+    /* This might fail for color bitmap fonts, but that is fine since we will
2ceb93
+     * not need any glyph data from FreeType in this case */
2ceb93
+    /*FT_Error rc = */ FT_Set_Pixel_Sizes( maFaceFT, mnWidth, rFSD.mnHeight );
2ceb93
 
2ceb93
     FT_Select_Charmap(maFaceFT, FT_ENCODING_UNICODE);
2ceb93
 
2ceb93
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
2ceb93
index 4ee63a98da95..2f80d03f542b 100644
2ceb93
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
2ceb93
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
2ceb93
@@ -4031,34 +4031,59 @@ void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_
2ceb93
     pThis->m_bPreeditJustChanged = true;
2ceb93
 
2ceb93
     bool bEndPreedit = (!pText || !*pText) && pThis->m_aInputEvent.mpTextAttr != nullptr;
2ceb93
-    pThis->m_aInputEvent.maText             = pText ? OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 ) : OUString();
2ceb93
-    pThis->m_aInputEvent.mnCursorPos        = nCursorPos;
2ceb93
-    pThis->m_aInputEvent.mnCursorFlags      = 0;
2ceb93
+    gint nUtf8Len = pText ? strlen(pText) : 0;
2ceb93
+    pThis->m_aInputEvent.maText             = pText ? OUString(pText, nUtf8Len, RTL_TEXTENCODING_UTF8) : OUString();
2ceb93
+    const OUString& rText = pThis->m_aInputEvent.maText;
2ceb93
 
2ceb93
-    pThis->m_aInputFlags = std::vector<ExtTextInputAttr>( std::max( 1, (int)pThis->m_aInputEvent.maText.getLength() ), ExtTextInputAttr::NONE );
2ceb93
+    std::vector<sal_Int32> aUtf16Offsets;
2ceb93
+    for (sal_Int32 nUtf16Offset = 0; nUtf16Offset < rText.getLength(); rText.iterateCodePoints(&nUtf16Offset))
2ceb93
+        aUtf16Offsets.push_back(nUtf16Offset);
2ceb93
+
2ceb93
+    sal_Int32 nUtf32Len = aUtf16Offsets.size();
2ceb93
+    aUtf16Offsets.push_back(rText.getLength());
2ceb93
+
2ceb93
+    // sanitize the CurPos which is in utf-32
2ceb93
+    if (nCursorPos < 0)
2ceb93
+        nCursorPos = 0;
2ceb93
+    else if (nCursorPos > nUtf32Len)
2ceb93
+        nCursorPos = nUtf32Len;
2ceb93
+
2ceb93
+    pThis->m_aInputEvent.mnCursorPos = aUtf16Offsets[nCursorPos];
2ceb93
+    pThis->m_aInputEvent.mnCursorFlags = 0;
2ceb93
+
2ceb93
+    pThis->m_aInputFlags = std::vector<ExtTextInputAttr>( std::max( 1, static_cast<int>(rText.getLength()) ), ExtTextInputAttr::NONE );
2ceb93
 
2ceb93
     PangoAttrIterator *iter = pango_attr_list_get_iterator(pAttrs);
2ceb93
     do
2ceb93
     {
2ceb93
         GSList *attr_list = nullptr;
2ceb93
         GSList *tmp_list = nullptr;
2ceb93
-        gint start, end;
2ceb93
+        gint nUtf8Start, nUtf8End;
2ceb93
         ExtTextInputAttr sal_attr = ExtTextInputAttr::NONE;
2ceb93
 
2ceb93
-        pango_attr_iterator_range (iter, &start, &end;;
2ceb93
-        if (start == G_MAXINT || end == G_MAXINT)
2ceb93
-        {
2ceb93
-            auto len = pText ? g_utf8_strlen(pText, -1) : 0;
2ceb93
-            if (end == G_MAXINT)
2ceb93
-                end = len;
2ceb93
-            if (start == G_MAXINT)
2ceb93
-                start = len;
2ceb93
-        }
2ceb93
-        if (end == start)
2ceb93
+        // docs say... "Get the range of the current segment ... the stored
2ceb93
+        // return values are signed, not unsigned like the values in
2ceb93
+        // PangoAttribute", which implies that the units are otherwise the same
2ceb93
+        // as that of PangoAttribute whose docs state these units are "in
2ceb93
+        // bytes"
2ceb93
+        // so this is the utf8 range
2ceb93
+        pango_attr_iterator_range(iter, &nUtf8Start, &nUtf8End);
2ceb93
+
2ceb93
+        // sanitize the utf8 range
2ceb93
+        nUtf8Start = std::min(nUtf8Start, nUtf8Len);
2ceb93
+        nUtf8End = std::min(nUtf8End, nUtf8Len);
2ceb93
+        if (nUtf8Start >= nUtf8End)
2ceb93
             continue;
2ceb93
 
2ceb93
-        start = g_utf8_pointer_to_offset (pText, pText + start);
2ceb93
-        end = g_utf8_pointer_to_offset (pText, pText + end);
2ceb93
+        // get the utf32 range
2ceb93
+        sal_Int32 nUtf32Start = g_utf8_pointer_to_offset(pText, pText + nUtf8Start);
2ceb93
+        sal_Int32 nUtf32End = g_utf8_pointer_to_offset(pText, pText + nUtf8End);
2ceb93
+
2ceb93
+        // sanitize the utf32 range
2ceb93
+        nUtf32Start = std::min(nUtf32Start, nUtf32Len);
2ceb93
+        nUtf32End = std::min(nUtf32End, nUtf32Len);
2ceb93
+        if (nUtf32Start >= nUtf32End)
2ceb93
+            continue;
2ceb93
 
2ceb93
         tmp_list = attr_list = pango_attr_iterator_get_attrs (iter);
2ceb93
         while (tmp_list)
2ceb93
@@ -4088,11 +4113,12 @@ void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_
2ceb93
         g_slist_free (attr_list);
2ceb93
 
2ceb93
         // Set the sal attributes on our text
2ceb93
-        for (int i = start; i < end; ++i)
2ceb93
+        // rhbz#1648281 apply over our utf-16 range derived from the input utf-32 range
2ceb93
+        for (sal_Int32 i = aUtf16Offsets[nUtf32Start]; i < aUtf16Offsets[nUtf32End]; ++i)
2ceb93
         {
2ceb93
             SAL_WARN_IF(i >= static_cast<int>(pThis->m_aInputFlags.size()),
2ceb93
                 "vcl.gtk3", "pango attrib out of range. Broken range: "
2ceb93
-                << start << "," << end << " Legal range: 0,"
2ceb93
+                << aUtf16Offsets[nUtf32Start] << "," << aUtf16Offsets[nUtf32End] << " Legal range: 0,"
2ceb93
                 << pThis->m_aInputFlags.size());
2ceb93
             if (i >= static_cast<int>(pThis->m_aInputFlags.size()))
2ceb93
                 continue;
2ceb93
-- 
2ceb93
2.21.0
2ceb93