Skip to content

Commit

Permalink
[共通] DrawableText::fits() #1202
Browse files Browse the repository at this point in the history
  • Loading branch information
Reputeless committed Jul 2, 2024
1 parent 236a48c commit a46d190
Show file tree
Hide file tree
Showing 14 changed files with 383 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Siv3D/include/Siv3D/DrawableText.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ namespace s3d
[[nodiscard]]
RectF regionBaseAt(double size, Vec2 pos = Vec2{ 0, 0 }) const;

bool fits(const RectF& area) const;

bool fits(double size, const RectF& area) const;

RectF draw(double x, double y, const ColorF& color = Palette::White) const;

RectF draw(const Vec2& pos = Vec2{ 0, 0 }, const ColorF& color = Palette::White) const;
Expand Down
10 changes: 10 additions & 0 deletions Siv3D/src/Siv3D/DrawableText/SivDrawableText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,16 @@ namespace s3d
return rect.movedBy(pos.x - (rect.w * 0.5), pos.y);
}

bool DrawableText::fits(const RectF& area) const
{
return fits(font.fontSize(), area);
}

bool DrawableText::fits(const double size, const RectF& area) const
{
return SIV3D_ENGINE(Font)->fits(font.id(), text, clusters, area, size, 1.0);
}

RectF DrawableText::draw(const double x, const double y, const ColorF& color) const
{
return draw(TextStyle::Default(), font.fontSize(), Vec2{x, y}, color);
Expand Down
7 changes: 7 additions & 0 deletions Siv3D/src/Siv3D/Font/CFont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,13 @@ namespace s3d
}
}

bool CFont::fits(const Font::IDType handleID, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, const double lineHeightScale)
{
const auto& font = m_fonts[handleID];

return m_fonts[handleID]->getGlyphCache().fits(*font, s, clusters, area, fontSize, lineHeightScale);
}

bool CFont::draw(const Font::IDType handleID, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, const TextStyle& textStyle, const ColorF& color, const double lineHeightScale)
{
const auto& font = m_fonts[handleID];
Expand Down
2 changes: 2 additions & 0 deletions Siv3D/src/Siv3D/Font/CFont.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ namespace s3d

RectF draw(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const Vec2& pos, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;

bool fits(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, double lineHeightScale);

bool draw(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;

RectF drawBase(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const Vec2& pos, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;
Expand Down
6 changes: 6 additions & 0 deletions Siv3D/src/Siv3D/Font/CFont_Headless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,12 @@ namespace s3d
}
}

bool CFont_Headless::fits(const Font::IDType, const StringView, const Array<GlyphCluster>&, const RectF&, const double, const double)
{
// [Siv3D ToDo]
return false;
}

bool CFont_Headless::draw(const Font::IDType, const StringView, const Array<GlyphCluster>&, const RectF&, const double, const TextStyle&, const ColorF&, const double)
{
// [Siv3D ToDo]
Expand Down
2 changes: 2 additions & 0 deletions Siv3D/src/Siv3D/Font/CFont_Headless.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ namespace s3d

RectF draw(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const Vec2& pos, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;

bool fits(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, double lineHeightScale);

bool draw(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;

RectF drawBase(Font::IDType handleID, StringView s, const Array<GlyphCluster>& clusters, const Vec2& pos, double fontSize, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) override;
Expand Down
114 changes: 114 additions & 0 deletions Siv3D/src/Siv3D/Font/GlyphCache/BitmapGlyphCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,120 @@ namespace s3d
return{ topLeft, (xMax - basePos.x), (lineCount * prop.height() * scale * lineHeightScale) };
}

bool BitmapGlyphCache::fits(const FontData& font, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, const double size, const double lineHeightScale)
{
if (not prerender(font, clusters, true))
{
return false;
}

// 「.」のグリフ
const Array<GlyphCluster> dotGlyphCluster = font.getGlyphClusters(U".", false, Ligature::Yes);
if (not prerender(font, dotGlyphCluster, true))
{
// do tnohing
}
updateTexture();

const double dotXAdvance = m_glyphTable.find(dotGlyphCluster[0].glyphIndex)->second.info.xAdvance;
const Vec2 areaBottomRight = area.br();

const auto& prop = font.getProperty();
const double scale = (size / prop.fontPixelSize);
const double lineHeight = (prop.height() * scale * lineHeightScale);

if ((area.w < (dotXAdvance * 3)) || (area.h < lineHeight))
{
return false;
}

const int32 maxLines = Max(static_cast<int32>(area.h / (lineHeight ? lineHeight : 1)), 1);
const Vec2 basePos{ area.pos };

Array<Vec2> penPositions;
size_t clusterIndex = 0;
{
Array<double> xAdvances(Arg::reserve = clusters.size());
Vec2 penPos{ basePos };
int32 lineIndex = 0;
double currentLineWidth = 0.0;
double previousLineWidth = 0.0;

for (; clusterIndex < clusters.size(); ++clusterIndex)
{
const auto& cluster = clusters[clusterIndex];
double xAdvance = 0.0;
bool nextLine = false;

if (const char32 ch = s[cluster.pos];
IsControl(ch))
{
if (ch == U'\t')
{
xAdvance = GetTabAdvance(prop.spaceWidth, scale, basePos.x, penPos.x, prop.indentSize);
}
else
{
xAdvance = 0.0;
nextLine = (ch == U'\n');
}
}
else if (cluster.fontIndex != 0)
{
const size_t fallbackIndex = (cluster.fontIndex - 1);
xAdvance = SIV3D_ENGINE(Font)->regionBaseFallback(font.getFallbackFont(fallbackIndex).lock()->id(),
cluster, penPos.movedBy(0, prop.ascender * scale), size, lineHeightScale).w;
}
else
{
const auto& cache = m_glyphTable.find(cluster.glyphIndex)->second;
xAdvance = (cache.info.xAdvance * scale);
}

if (areaBottomRight.x < (penPos.x + xAdvance))
{
nextLine = true;
}

if (nextLine)
{
++lineIndex;
previousLineWidth = currentLineWidth;

penPos.x = basePos.x;
penPos.y = basePos.y + (lineIndex * lineHeight);
}

penPositions << penPos;
xAdvances << xAdvance;
penPos.x += xAdvance;
currentLineWidth = (penPos.x - basePos.x);

// エリア外
if (maxLines <= lineIndex)
{
const double dotsWidth = (dotXAdvance * 3);
double xEliminatedWidth = (area.w - previousLineWidth);

while (clusterIndex > 0)
{
xEliminatedWidth += xAdvances[clusterIndex];
--clusterIndex;

if (dotsWidth <= xEliminatedWidth)
{
break;
}
}

break;
}
}
}

return (clusterIndex == clusters.size());
}

bool BitmapGlyphCache::draw(const FontData& font, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, const double size, const TextStyle& textStyle, const ColorF& color, const double lineHeightScale)
{
if (not prerender(font, clusters, true))
Expand Down
2 changes: 2 additions & 0 deletions Siv3D/src/Siv3D/Font/GlyphCache/BitmapGlyphCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace s3d

RectF draw(const FontData & font, StringView s, const Array<GlyphCluster>&clusters, bool usebasePos, const Vec2 & pos, double size, const TextStyle & textStyle, const ColorF & color, double lineHeightScale) override;

bool fits(const FontData& font, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double size, double lineHeightScale);

bool draw(const FontData & font, StringView s, const Array<GlyphCluster>&clusters, const RectF & area, double size, const TextStyle & textStyle, const ColorF & color, double lineHeightScale) override;

[[nodiscard]]
Expand Down
2 changes: 2 additions & 0 deletions Siv3D/src/Siv3D/Font/GlyphCache/IGlyphCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace s3d

virtual RectF draw(const FontData& font, StringView s, const Array<GlyphCluster>& clusters, bool useBasePos, const Vec2& pos, double size, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) = 0;

virtual bool fits(const FontData& font, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double size, double lineHeightScale) = 0;

virtual bool draw(const FontData& font, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double size, const TextStyle& textStyle, const ColorF& color, double lineHeightScale) = 0;

virtual RectF drawFallback(const FontData& font, const GlyphCluster& cluster, bool useBasePos, const Vec2& pos, const double size, const ColorF& color, double lineHeightScale) = 0;
Expand Down
114 changes: 114 additions & 0 deletions Siv3D/src/Siv3D/Font/GlyphCache/MSDFGlyphCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,120 @@ namespace s3d
return{ topLeft, (xMax - basePos.x), (lineCount * prop.height() * scale * lineHeightScale) };
}

bool MSDFGlyphCache::fits(const FontData& font, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, const double size, const double lineHeightScale)
{
if (not prerender(font, clusters, true))
{
return false;
}

// 「.」のグリフ
const Array<GlyphCluster> dotGlyphCluster = font.getGlyphClusters(U".", false, Ligature::Yes);
if (not prerender(font, dotGlyphCluster, true))
{
// do tnohing
}
updateTexture();

const double dotXAdvance = m_glyphTable.find(dotGlyphCluster[0].glyphIndex)->second.info.xAdvance;
const Vec2 areaBottomRight = area.br();

const auto& prop = font.getProperty();
const double scale = (size / prop.fontPixelSize);
const double lineHeight = (prop.height() * scale * lineHeightScale);

if ((area.w < (dotXAdvance * 3)) || (area.h < lineHeight))
{
return false;
}

const int32 maxLines = Max(static_cast<int32>(area.h / (lineHeight ? lineHeight : 1)), 1);
const Vec2 basePos{ area.pos };

Array<Vec2> penPositions;
size_t clusterIndex = 0;
{
Array<double> xAdvances(Arg::reserve = clusters.size());
Vec2 penPos{ basePos };
int32 lineIndex = 0;
double currentLineWidth = 0.0;
double previousLineWidth = 0.0;

for (; clusterIndex < clusters.size(); ++clusterIndex)
{
const auto& cluster = clusters[clusterIndex];
double xAdvance = 0.0;
bool nextLine = false;

if (const char32 ch = s[cluster.pos];
IsControl(ch))
{
if (ch == U'\t')
{
xAdvance = GetTabAdvance(prop.spaceWidth, scale, basePos.x, penPos.x, prop.indentSize);
}
else
{
xAdvance = 0.0;
nextLine = (ch == U'\n');
}
}
else if (cluster.fontIndex != 0)
{
const size_t fallbackIndex = (cluster.fontIndex - 1);
xAdvance = SIV3D_ENGINE(Font)->regionBaseFallback(font.getFallbackFont(fallbackIndex).lock()->id(),
cluster, penPos.movedBy(0, prop.ascender * scale), size, lineHeightScale).w;
}
else
{
const auto& cache = m_glyphTable.find(cluster.glyphIndex)->second;
xAdvance = (cache.info.xAdvance * scale);
}

if (areaBottomRight.x < (penPos.x + xAdvance))
{
nextLine = true;
}

if (nextLine)
{
++lineIndex;
previousLineWidth = currentLineWidth;

penPos.x = basePos.x;
penPos.y = basePos.y + (lineIndex * lineHeight);
}

penPositions << penPos;
xAdvances << xAdvance;
penPos.x += xAdvance;
currentLineWidth = (penPos.x - basePos.x);

// エリア外
if (maxLines <= lineIndex)
{
const double dotsWidth = (dotXAdvance * 3);
double xEliminatedWidth = (area.w - previousLineWidth);

while (clusterIndex > 0)
{
xEliminatedWidth += xAdvances[clusterIndex];
--clusterIndex;

if (dotsWidth <= xEliminatedWidth)
{
break;
}
}

break;
}
}
}

return (clusterIndex == clusters.size());
}

bool MSDFGlyphCache::draw(const FontData& font, const StringView s, const Array<GlyphCluster>& clusters, const RectF& area, const double size, const TextStyle& textStyle, const ColorF& color, const double lineHeightScale)
{
if (not prerender(font, clusters, true))
Expand Down
2 changes: 2 additions & 0 deletions Siv3D/src/Siv3D/Font/GlyphCache/MSDFGlyphCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace s3d

RectF draw(const FontData & font, StringView s, const Array<GlyphCluster>&clusters, bool usebasePos, const Vec2 & pos, double size, const TextStyle & textStyle, const ColorF & color, double lineHeightScale) override;

bool fits(const FontData& font, StringView s, const Array<GlyphCluster>& clusters, const RectF& area, double size, double lineHeightScale);

bool draw(const FontData & font, StringView s, const Array<GlyphCluster>&clusters, const RectF & area, double size, const TextStyle & textStyle, const ColorF & color, double lineHeightScale) override;

[[nodiscard]]
Expand Down
Loading

0 comments on commit a46d190

Please sign in to comment.