mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Add ShapedText::accessTogetherWith and remove ShapedText::access
Since the original function template has been exposed, we can now use it directly. Also ShapedText::Detail has been removed, because it wouldn't work across module boundaries.
This commit is contained in:
parent
1b595311d0
commit
fab1de34ab
6 changed files with 77 additions and 114 deletions
|
|
@ -214,8 +214,8 @@ static float getCrossAxisStartingAnchor (Justification justification,
|
||||||
return minimumTop;
|
return minimumTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
JustifiedText::JustifiedText (const SimpleShapedText& t, const ShapedTextOptions& options)
|
JustifiedText::JustifiedText (const SimpleShapedText* t, const ShapedTextOptions& options)
|
||||||
: shapedText (t)
|
: shapedText (*t)
|
||||||
{
|
{
|
||||||
const auto leading = options.getLeading() - 1.0f;
|
const auto leading = options.getLeading() - 1.0f;
|
||||||
|
|
||||||
|
|
@ -443,32 +443,26 @@ JustifiedText::JustifiedText (const SimpleShapedText& t, const ShapedTextOptions
|
||||||
realign.extraWhitespaceAdvance);
|
realign.extraWhitespaceAdvance);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callable>
|
|
||||||
void JustifiedText::access (Callable&& callback) const
|
|
||||||
{
|
|
||||||
accessTogetherWith (std::forward<Callable> (callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawJustifiedText (const JustifiedText& text, const Graphics& g, AffineTransform transform)
|
void drawJustifiedText (const JustifiedText& text, const Graphics& g, AffineTransform transform)
|
||||||
{
|
{
|
||||||
auto& context = g.getInternalContext();
|
auto& context = g.getInternalContext();
|
||||||
context.saveState();
|
context.saveState();
|
||||||
const ScopeGuard restoreGraphicsContext { [&context] { context.restoreState(); } };
|
const ScopeGuard restoreGraphicsContext { [&context] { context.restoreState(); } };
|
||||||
|
|
||||||
text.access ([&] (auto glyphs, auto positions, auto font, auto, auto)
|
text.accessTogetherWith ([&] (auto glyphs, auto positions, auto font, auto, auto)
|
||||||
{
|
{
|
||||||
if (context.getFont() != font)
|
if (context.getFont() != font)
|
||||||
context.setFont (font);
|
context.setFont (font);
|
||||||
|
|
||||||
std::vector<uint16_t> glyphIds (glyphs.size());
|
std::vector<uint16_t> glyphIds (glyphs.size());
|
||||||
|
|
||||||
std::transform (glyphs.begin(),
|
std::transform (glyphs.begin(),
|
||||||
glyphs.end(),
|
glyphs.end(),
|
||||||
glyphIds.begin(),
|
glyphIds.begin(),
|
||||||
[] (auto& glyph) { return (uint16_t) glyph.glyphId; });
|
[] (auto& glyph) { return (uint16_t) glyph.glyphId; });
|
||||||
|
|
||||||
context.drawGlyphs (glyphIds, positions, transform);
|
context.drawGlyphs (glyphIds, positions, transform);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace juce::detail
|
} // namespace juce::detail
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,26 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JustifiedText (const SimpleShapedText& t, const ShapedTextOptions& options);
|
JustifiedText (const SimpleShapedText* t, const ShapedTextOptions& options);
|
||||||
|
|
||||||
|
/* Provides access to the data stored in the ShapedText.
|
||||||
|
|
||||||
|
The provided callable will be called multiple times for "uniform glyph runs", for which all
|
||||||
|
callback parameters are the same.
|
||||||
|
|
||||||
|
Between each subsequent callback at least one of the provided parameters will be different.
|
||||||
|
|
||||||
|
The callbacks happen in visual order i.e. left to right, which is irrespective of the
|
||||||
|
underlying text's writing direction.
|
||||||
|
|
||||||
|
The callback parameters in order are:
|
||||||
|
- the glyphs
|
||||||
|
- the positions for each glyph in the previous parameter
|
||||||
|
- the Font with which these glyphs should be rendered
|
||||||
|
- the range in all glyphs this ShapedText object holds, that correspond to the current glyphs
|
||||||
|
- a line number which increases by one for each new line
|
||||||
|
- followed by any number of ValueType parameters for the supplied RangedValues<ValueType> arguments
|
||||||
|
*/
|
||||||
template <typename Callable, typename... RangedValues>
|
template <typename Callable, typename... RangedValues>
|
||||||
void accessTogetherWith (Callable&& callback, RangedValues&&... rangedValues) const
|
void accessTogetherWith (Callable&& callback, RangedValues&&... rangedValues) const
|
||||||
{
|
{
|
||||||
|
|
@ -115,17 +133,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The callback receives (Span<const ShapedGlyph> glyphs,
|
|
||||||
Span<Point<float>> positions,
|
|
||||||
Font font,
|
|
||||||
Range<int64> glyphRange,
|
|
||||||
int64 lineNumber) // So far this has been indexed from 0 per SimpleShapedText
|
|
||||||
// object, but maybe we'll find we want global text level
|
|
||||||
// line numbers, so only assume they are increasing by one
|
|
||||||
*/
|
|
||||||
template <typename Callable>
|
|
||||||
void access (Callable&& callback) const;
|
|
||||||
|
|
||||||
/* This is how much cumulative widths glyphs take up in each line. Whether the trailing
|
/* This is how much cumulative widths glyphs take up in each line. Whether the trailing
|
||||||
whitespace is included depends on the ShapedTextOptions::getWhitespaceShouldFitInLine()
|
whitespace is included depends on the ShapedTextOptions::getWhitespaceShouldFitInLine()
|
||||||
setting.
|
setting.
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,6 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void access (const std::function<void (Span<const ShapedGlyph>, Span<Point<float>>, Font, Range<int64>, int64)>& cb) const
|
|
||||||
{
|
|
||||||
justifiedText.access (cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw (const Graphics& g, AffineTransform transform) const
|
void draw (const Graphics& g, AffineTransform transform) const
|
||||||
{
|
{
|
||||||
drawJustifiedText (justifiedText, g, transform);
|
drawJustifiedText (justifiedText, g, transform);
|
||||||
|
|
@ -78,7 +73,7 @@ private:
|
||||||
ShapedTextOptions options;
|
ShapedTextOptions options;
|
||||||
String text;
|
String text;
|
||||||
SimpleShapedText simpleShapedText { &text, options };
|
SimpleShapedText simpleShapedText { &text, options };
|
||||||
JustifiedText justifiedText { simpleShapedText, options };
|
JustifiedText justifiedText { &simpleShapedText, options };
|
||||||
};
|
};
|
||||||
|
|
||||||
ShapedText::ShapedText() : ShapedText ("", {})
|
ShapedText::ShapedText() : ShapedText ("", {})
|
||||||
|
|
@ -94,11 +89,6 @@ ShapedText::ShapedText (String text, Options options)
|
||||||
impl = std::make_shared<Impl> (std::move (text), std::move (options));
|
impl = std::make_shared<Impl> (std::move (text), std::move (options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapedText::access (const std::function<void (Span<const ShapedGlyph>, Span<Point<float>>, Font, Range<int64>, int64)>& cb) const
|
|
||||||
{
|
|
||||||
impl->access (cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShapedText::draw (const Graphics& g, AffineTransform transform) const
|
void ShapedText::draw (const Graphics& g, AffineTransform transform) const
|
||||||
{
|
{
|
||||||
impl->draw (g, transform);
|
impl->draw (g, transform);
|
||||||
|
|
@ -119,24 +109,8 @@ Span<const float> ShapedText::getMinimumRequiredWidthForLines() const
|
||||||
return impl->getMinimumRequiredWidthForLines();
|
return impl->getMinimumRequiredWidthForLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShapedText::Detail
|
const JustifiedText& ShapedText::getJustifiedText() const { return impl->getJustifiedText(); }
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Detail (const ShapedText* shapedTextIn)
|
|
||||||
: shapedText (*shapedTextIn)
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto& getJustifiedText() const { return shapedText.impl->getJustifiedText(); }
|
const SimpleShapedText& ShapedText::getSimpleShapedText() const { return impl->getSimpleShapedText(); }
|
||||||
|
|
||||||
auto& getSimpleShapedText() const { return shapedText.impl->getSimpleShapedText(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const ShapedText& shapedText;
|
|
||||||
};
|
|
||||||
|
|
||||||
ShapedText::Detail ShapedText::getDetail() const
|
|
||||||
{
|
|
||||||
return Detail { this };
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace juce::detail
|
} // namespace juce::detail
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
namespace juce::detail
|
namespace juce::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Class that can visually shape a Unicode string provided a list of Fonts corresponding to
|
/* Class that can visually shape a Unicode string provided a list of Fonts corresponding to
|
||||||
sub-ranges of the string.
|
sub-ranges of the string.
|
||||||
*/
|
*/
|
||||||
class JUCE_API ShapedText
|
class JUCE_API ShapedText
|
||||||
|
|
@ -49,17 +49,17 @@ public:
|
||||||
|
|
||||||
ShapedText (String text, Options options);
|
ShapedText (String text, Options options);
|
||||||
|
|
||||||
/** Returns the text which was used to construct this object. */
|
/* Returns the text which was used to construct this object. */
|
||||||
const String& getText() const;
|
const String& getText() const;
|
||||||
|
|
||||||
/** Returns the text's codepoint range, to which the glyph under the provided index belongs.
|
/* Returns the text's codepoint range, to which the glyph under the provided index belongs.
|
||||||
|
|
||||||
This range will have a length of at least one, and potentially more than one if ligatures
|
This range will have a length of at least one, and potentially more than one if ligatures
|
||||||
are enabled.
|
are enabled.
|
||||||
*/
|
*/
|
||||||
Range<int64> getTextRange (int64 glyphIndex) const;
|
Range<int64> getTextRange (int64 glyphIndex) const;
|
||||||
|
|
||||||
/** Returns the widths for each line, that the glyphs would require to be rendered without being
|
/* Returns the widths for each line, that the glyphs would require to be rendered without being
|
||||||
truncated. This will or will not include the space required by trailing whitespaces in the
|
truncated. This will or will not include the space required by trailing whitespaces in the
|
||||||
line based on the ShapedTextOptions::withTrailingWhitespacesShouldFit() value.
|
line based on the ShapedTextOptions::withTrailingWhitespacesShouldFit() value.
|
||||||
|
|
||||||
|
|
@ -68,33 +68,22 @@ public:
|
||||||
*/
|
*/
|
||||||
Span<const float> getMinimumRequiredWidthForLines() const;
|
Span<const float> getMinimumRequiredWidthForLines() const;
|
||||||
|
|
||||||
/** Provides access to the data stored in the ShapedText.
|
/* @see JustifiedText::accessTogetherWith */
|
||||||
|
template <typename Callable, typename... RangedValues>
|
||||||
|
void accessTogetherWith (Callable&& callback, RangedValues&&... rangedValues) const
|
||||||
|
{
|
||||||
|
getJustifiedText().accessTogetherWith (std::forward<Callable> (callback),
|
||||||
|
std::forward<RangedValues> (rangedValues)...);
|
||||||
|
}
|
||||||
|
|
||||||
The provided function callback will be called multiple times for "uniform glyph runs", for which all
|
/* Draws the text. */
|
||||||
callback parameters are the same.
|
|
||||||
|
|
||||||
Between each subsequent callback at least one of the provided parameters will be different.
|
|
||||||
|
|
||||||
The callbacks happen in visual order i.e. left to right, which is irrespective of the
|
|
||||||
underlying text's writing direction.
|
|
||||||
|
|
||||||
The callback parameters in order are:
|
|
||||||
- the glyphs
|
|
||||||
- the positions for each glyph in the previous parameter
|
|
||||||
- the Font with which these glyphs should be rendered
|
|
||||||
- the range in all glyphs this ShapedText object holds, that correspond to the current glyphs
|
|
||||||
- a line number which increases by one for each new line
|
|
||||||
*/
|
|
||||||
void access (const std::function<void (Span<const ShapedGlyph>, Span<Point<float>>, Font, Range<int64>, int64)>&) const;
|
|
||||||
|
|
||||||
/** Draws the text. */
|
|
||||||
void draw (const Graphics& g, AffineTransform transform) const;
|
void draw (const Graphics& g, AffineTransform transform) const;
|
||||||
|
|
||||||
/** @internal */
|
/* @internal */
|
||||||
class Detail;
|
const JustifiedText& getJustifiedText() const;
|
||||||
|
|
||||||
/** @internal */
|
/* @internal */
|
||||||
Detail getDetail() const;
|
const SimpleShapedText& getSimpleShapedText() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
|
|
|
||||||
|
|
@ -173,26 +173,26 @@ void GlyphArrangement::addLineOfText (const Font& font, const String& text, floa
|
||||||
|
|
||||||
static void addGlyphsFromShapedText (GlyphArrangement& ga, const detail::ShapedText& st, float x, float y)
|
static void addGlyphsFromShapedText (GlyphArrangement& ga, const detail::ShapedText& st, float x, float y)
|
||||||
{
|
{
|
||||||
st.access ([&] (auto shapedGlyphs, auto positions, auto font, auto glyphRange, auto)
|
st.accessTogetherWith ([&] (auto shapedGlyphs, auto positions, auto font, auto glyphRange, auto)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < shapedGlyphs.size(); ++i)
|
for (size_t i = 0; i < shapedGlyphs.size(); ++i)
|
||||||
{
|
{
|
||||||
const auto glyphIndex = (int64) i + glyphRange.getStart();
|
const auto glyphIndex = (int64) i + glyphRange.getStart();
|
||||||
|
|
||||||
auto& glyph = shapedGlyphs[i];
|
auto& glyph = shapedGlyphs[i];
|
||||||
auto& position = positions[i];
|
auto& position = positions[i];
|
||||||
|
|
||||||
PositionedGlyph pg { font,
|
PositionedGlyph pg { font,
|
||||||
st.getText()[(int) st.getTextRange (glyphIndex).getStart()],
|
st.getText()[(int) st.getTextRange (glyphIndex).getStart()],
|
||||||
(int) glyph.glyphId,
|
(int) glyph.glyphId,
|
||||||
position.getX() + x,
|
position.getX() + x,
|
||||||
position.getY() + y,
|
position.getY() + y,
|
||||||
glyph.advance.getX(),
|
glyph.advance.getX(),
|
||||||
glyph.whitespace };
|
glyph.whitespace };
|
||||||
|
|
||||||
ga.addGlyph (std::move (pg));
|
ga.addGlyph (std::move (pg));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text,
|
void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text,
|
||||||
|
|
|
||||||
|
|
@ -362,9 +362,9 @@ static Range<int64> getLineInputRange (const detail::ShapedText& st, int64 lineN
|
||||||
{
|
{
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
|
|
||||||
return getInputRange (st, ShapedText::Detail { &st }.getSimpleShapedText()
|
return getInputRange (st, st.getSimpleShapedText()
|
||||||
.getLineNumbers()
|
.getLineNumbers()
|
||||||
.getItem ((size_t) lineNumber).range);
|
.getItem ((size_t) lineNumber).range);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MaxFontAscentAndDescent
|
struct MaxFontAscentAndDescent
|
||||||
|
|
@ -375,7 +375,7 @@ struct MaxFontAscentAndDescent
|
||||||
static MaxFontAscentAndDescent getMaxFontAscentAndDescentInEnclosingLine (const detail::ShapedText& st,
|
static MaxFontAscentAndDescent getMaxFontAscentAndDescentInEnclosingLine (const detail::ShapedText& st,
|
||||||
Range<int64> lineChunkRange)
|
Range<int64> lineChunkRange)
|
||||||
{
|
{
|
||||||
const auto sst = detail::ShapedText::Detail { &st }.getSimpleShapedText();
|
const auto sst = st.getSimpleShapedText();
|
||||||
|
|
||||||
const auto lineRange = sst.getLineNumbers()
|
const auto lineRange = sst.getLineNumbers()
|
||||||
.getItemWithEnclosingRange (lineChunkRange.getStart())->range;
|
.getItemWithEnclosingRange (lineChunkRange.getStart())->range;
|
||||||
|
|
@ -435,13 +435,12 @@ void TextLayout::createStandardLayout (const AttributedString& text)
|
||||||
if (text.getWordWrap() != AttributedString::none)
|
if (text.getWordWrap() != AttributedString::none)
|
||||||
shapedTextOptions = shapedTextOptions.withMaxWidth (width);
|
shapedTextOptions = shapedTextOptions.withMaxWidth (width);
|
||||||
|
|
||||||
ShapedText shapedText { text.getText(), shapedTextOptions };
|
ShapedText st { text.getText(), shapedTextOptions };
|
||||||
|
|
||||||
std::optional<int64> lastLineNumber;
|
std::optional<int64> lastLineNumber;
|
||||||
std::unique_ptr<Line> line;
|
std::unique_ptr<Line> line;
|
||||||
|
|
||||||
auto& jt = ShapedText::Detail { &shapedText }.getJustifiedText();
|
st.accessTogetherWith ([&] (Span<const ShapedGlyph> glyphs,
|
||||||
jt.accessTogetherWith ([&] (Span<const ShapedGlyph> glyphs,
|
|
||||||
Span<Point<float>> positions,
|
Span<Point<float>> positions,
|
||||||
Font font,
|
Font font,
|
||||||
Range<int64> glyphRange,
|
Range<int64> glyphRange,
|
||||||
|
|
@ -453,10 +452,10 @@ void TextLayout::createStandardLayout (const AttributedString& text)
|
||||||
if (line != nullptr)
|
if (line != nullptr)
|
||||||
addLine (std::move (line));
|
addLine (std::move (line));
|
||||||
|
|
||||||
const auto ascentAndDescent = getMaxFontAscentAndDescentInEnclosingLine (shapedText,
|
const auto ascentAndDescent = getMaxFontAscentAndDescentInEnclosingLine (st,
|
||||||
glyphRange);
|
glyphRange);
|
||||||
|
|
||||||
line = std::make_unique<Line> (castTo<int> (getLineInputRange (shapedText, lineNumber)),
|
line = std::make_unique<Line> (castTo<int> (getLineInputRange (st, lineNumber)),
|
||||||
positions[0],
|
positions[0],
|
||||||
ascentAndDescent.ascent,
|
ascentAndDescent.ascent,
|
||||||
ascentAndDescent.descent,
|
ascentAndDescent.descent,
|
||||||
|
|
@ -464,7 +463,7 @@ void TextLayout::createStandardLayout (const AttributedString& text)
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto run = std::make_unique<Run> (castTo<int> (getInputRange (shapedText, glyphRange)), 0);
|
auto run = std::make_unique<Run> (castTo<int> (getInputRange (st, glyphRange)), 0);
|
||||||
|
|
||||||
run->font = font;
|
run->font = font;
|
||||||
run->colour = colour;
|
run->colour = colour;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue