Add extractURLFromGlyphLayouts which handles RTL layout properly
This commit is contained in:
parent
a4015beb29
commit
38cfd912bd
@ -367,6 +367,73 @@ inline void removeHighlightedURL(std::vector<GlyphLayout>& gls)
|
|||||||
gl.flags &= ~gui::GLF_URL;
|
gl.flags &= ~gui::GLF_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int getGlyphIndexFromCluster(const std::vector<GlyphLayout>& gls, int cluster, std::shared_ptr<std::u32string> orig_string_in_gls = nullptr)
|
||||||
|
{
|
||||||
|
if (gls.empty())
|
||||||
|
return -1;
|
||||||
|
if (!orig_string_in_gls)
|
||||||
|
orig_string_in_gls = gls[0].orig_string;
|
||||||
|
if (!orig_string_in_gls)
|
||||||
|
return -1;
|
||||||
|
for (int i = 0; i < (int)gls.size(); i++)
|
||||||
|
{
|
||||||
|
const GlyphLayout& gl = gls[i];
|
||||||
|
if (gl.orig_string != orig_string_in_gls)
|
||||||
|
continue;
|
||||||
|
if ((gl.flags & gui::GLF_NEWLINE) != 0)
|
||||||
|
continue;
|
||||||
|
for (int c : gl.cluster)
|
||||||
|
{
|
||||||
|
if (c == cluster)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::u32string extractURLFromGlyphLayouts(const std::vector<GlyphLayout>& gls, unsigned url_glyph)
|
||||||
|
{
|
||||||
|
if (gls.empty() || url_glyph >= gls.size())
|
||||||
|
return U"";
|
||||||
|
|
||||||
|
const gui::GlyphLayout& gl = gls[url_glyph];
|
||||||
|
if ((gl.flags & gui::GLF_URL) == 0 || !gl.orig_string || gl.cluster.empty())
|
||||||
|
return U"";
|
||||||
|
|
||||||
|
std::shared_ptr<std::u32string> orig_string_in_gls = gl.orig_string;
|
||||||
|
int start = gl.cluster.back();
|
||||||
|
while (start != 0)
|
||||||
|
{
|
||||||
|
char32_t ch = (*orig_string_in_gls)[start - 1];
|
||||||
|
if (ch == U'\n' || ch == U'\t' || ch == U'\r')
|
||||||
|
break;
|
||||||
|
int gi = getGlyphIndexFromCluster(gls, start - 1, orig_string_in_gls);
|
||||||
|
if (gi == -1 || gi >= (int)gls.size())
|
||||||
|
return U"";
|
||||||
|
const gui::GlyphLayout& cur_gl = gls[gi];
|
||||||
|
if ((cur_gl.flags & gui::GLF_URL) == 0)
|
||||||
|
break;
|
||||||
|
start--;
|
||||||
|
}
|
||||||
|
int end = gl.cluster.front();
|
||||||
|
while ((int)orig_string_in_gls->size() - end > 1)
|
||||||
|
{
|
||||||
|
size_t next_end = end + 1;
|
||||||
|
char32_t ch = (*orig_string_in_gls)[next_end];
|
||||||
|
if (ch == U'\n' || ch == U'\t' || ch == U'\r')
|
||||||
|
break;
|
||||||
|
int gi = getGlyphIndexFromCluster(gls, next_end, orig_string_in_gls);
|
||||||
|
if (gi == -1 || gi >= (int)gls.size())
|
||||||
|
return U"";
|
||||||
|
const gui::GlyphLayout& cur_gl = gls[gi];
|
||||||
|
if ((cur_gl.flags & gui::GLF_URL) == 0)
|
||||||
|
break;
|
||||||
|
end = next_end;
|
||||||
|
}
|
||||||
|
std::u32string url = orig_string_in_gls->substr(start, end - start + 1);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
/** Used it only for single line (ie without line breaking mark). */
|
/** Used it only for single line (ie without line breaking mark). */
|
||||||
|
@ -56,38 +56,9 @@ namespace Online
|
|||||||
if (cluster == -1 || (unsigned)cluster > s->size())
|
if (cluster == -1 || (unsigned)cluster > s->size())
|
||||||
return false;
|
return false;
|
||||||
const std::vector<gui::GlyphLayout>& gls = text->getGlyphLayouts();
|
const std::vector<gui::GlyphLayout>& gls = text->getGlyphLayouts();
|
||||||
const gui::GlyphLayout& gl = gls[glyph_idx];
|
std::u32string url = gui::extractURLFromGlyphLayouts(gls, glyph_idx);
|
||||||
if ((gl.flags & gui::GLF_URL) == 0)
|
if (url.empty())
|
||||||
return false;
|
return false;
|
||||||
int start = glyph_idx;
|
|
||||||
while (start != 0)
|
|
||||||
{
|
|
||||||
const gui::GlyphLayout& cur_gl = gls[start - 1];
|
|
||||||
if ((cur_gl.flags & gui::GLF_BREAKTEXT_NEWLINE) != 0)
|
|
||||||
{
|
|
||||||
start--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((cur_gl.flags & gui::GLF_URL) == 0)
|
|
||||||
break;
|
|
||||||
start--;
|
|
||||||
}
|
|
||||||
size_t end = glyph_idx;
|
|
||||||
while (gls.size() - end > 1)
|
|
||||||
{
|
|
||||||
size_t next_end = end + 1;
|
|
||||||
const gui::GlyphLayout& cur_gl = gls[next_end];
|
|
||||||
if ((cur_gl.flags & gui::GLF_BREAKTEXT_NEWLINE) != 0)
|
|
||||||
{
|
|
||||||
end = next_end;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((cur_gl.flags & gui::GLF_URL) == 0)
|
|
||||||
break;
|
|
||||||
end = next_end;
|
|
||||||
}
|
|
||||||
std::u32string url = s->substr(gls[start].cluster.front(),
|
|
||||||
gls[end].cluster.back() - gls[start].cluster.front() + 1);
|
|
||||||
openURL(StringUtils::utf32ToUtf8(url));
|
openURL(StringUtils::utf32ToUtf8(url));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user