Commit f5c7aca8 authored by kojii's avatar kojii Committed by Commit bot

Add context information to BidiResolver.isolatedRuns()

This patch is a port of http://wkb.ug/149153, which is a port of a fix
for crbug.com/520282.

The WebKit patch has additional changes to carry more information of
isolated runs along with BidiRun. As we find we need to carry more
context with isolated runs in crbug.com/391260, this change is useful.

BUG=520282

Review URL: https://codereview.chromium.org/1468103002

Cr-Commit-Position: refs/heads/master@{#361258}
parent a4217fb0
......@@ -114,17 +114,6 @@ static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver,
}
}
static void restoreIsolatedMidpointStates(InlineBidiResolver& topResolver,
InlineBidiResolver& isolatedResolver)
{
while (!isolatedResolver.isolatedRuns().isEmpty()) {
BidiRun* run = isolatedResolver.isolatedRuns().last();
isolatedResolver.isolatedRuns().removeLast();
topResolver.setMidpointStateForIsolatedRun(run,
isolatedResolver.midpointStateForIsolatedRun(run));
}
}
void constructBidiRunsForLine(InlineBidiResolver& topResolver,
BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine,
VisualDirectionOverride override, bool previousLineBrokeCleanly,
......@@ -137,28 +126,15 @@ void constructBidiRunsForLine(InlineBidiResolver& topResolver,
const LayoutObject* currentRoot = topResolver.position().root();
topResolver.createBidiRunsForLine(endOfLine, override,
previousLineBrokeCleanly);
struct BidiRunsWithRoot {
const LayoutObject* root;
Vector<BidiRun*> isolatedRuns;
};
Vector<BidiRunsWithRoot> isolatedRunsStack;
while (true) {
if (topResolver.isolatedRuns().isEmpty()) {
if (isolatedRunsStack.isEmpty())
break;
topResolver.isolatedRuns().appendVector(isolatedRunsStack.last().isolatedRuns);
ASSERT(!topResolver.isolatedRuns().isEmpty());
currentRoot = isolatedRunsStack.last().root;
isolatedRunsStack.removeLast();
}
while (!topResolver.isolatedRuns().isEmpty()) {
// It does not matter which order we resolve the runs as long as we
// resolve them all.
BidiRun* isolatedRun = topResolver.isolatedRuns().last();
BidiIsolatedRun isolatedRun = topResolver.isolatedRuns().last();
topResolver.isolatedRuns().removeLast();
currentRoot = &isolatedRun.root;
LayoutObject* startObj = isolatedRun->object();
LayoutObject* startObj = &isolatedRun.object;
// Only inlines make sense with unicode-bidi: isolate (blocks are
// already isolated).
......@@ -176,7 +152,7 @@ void constructBidiRunsForLine(InlineBidiResolver& topResolver,
LineMidpointState& isolatedLineMidpointState =
isolatedResolver.midpointState();
isolatedLineMidpointState = topResolver.midpointStateForIsolatedRun(
isolatedRun);
isolatedRun.runToReplace);
EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi();
TextDirection direction;
if (unicodeBidi == Plaintext) {
......@@ -197,7 +173,7 @@ void constructBidiRunsForLine(InlineBidiResolver& topResolver,
// createBidiRunsForLine. This can be but is not necessarily the first
// run within the isolate.
InlineIterator iter = InlineIterator(LineLayoutItem(isolatedInline), LineLayoutItem(startObj),
isolatedRun->m_start);
isolatedRun.position);
isolatedResolver.setPositionIgnoringNestedIsolates(iter);
// We stop at the next end of line; we may re-enter this isolate in the
// next call to constructBidiRuns().
......@@ -209,16 +185,16 @@ void constructBidiRunsForLine(InlineBidiResolver& topResolver,
ASSERT(isolatedResolver.runs().runCount());
if (isolatedResolver.runs().runCount())
bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs());
bidiRuns.replaceRunWithRuns(&isolatedRun.runToReplace, isolatedResolver.runs());
// If we encountered any nested isolate runs, save them for later
// processing.
if (!isolatedResolver.isolatedRuns().isEmpty()) {
isolatedRunsStack.resize(isolatedRunsStack.size() + 1);
isolatedRunsStack.last().isolatedRuns.appendVector(
isolatedResolver.isolatedRuns());
isolatedRunsStack.last().root = isolatedInline;
restoreIsolatedMidpointStates(topResolver, isolatedResolver);
while (!isolatedResolver.isolatedRuns().isEmpty()) {
BidiIsolatedRun runWithContext = isolatedResolver.isolatedRuns().last();
isolatedResolver.isolatedRuns().removeLast();
topResolver.setMidpointStateForIsolatedRun(runWithContext.runToReplace,
isolatedResolver.midpointStateForIsolatedRun(runWithContext.runToReplace));
topResolver.isolatedRuns().append(runWithContext);
}
}
}
......
......@@ -33,6 +33,22 @@
namespace blink {
struct BidiIsolatedRun {
BidiIsolatedRun(LayoutObject& object, unsigned position, LayoutObject& root, BidiRun& runToReplace)
: object(object)
, root(root)
, runToReplace(runToReplace)
, position(position)
{
}
LayoutObject& object;
LayoutObject& root;
BidiRun& runToReplace;
unsigned position;
};
// This class is used to LayoutInline subtrees, stepping by character within the
// text children. InlineIterator will use bidiNext to find the next LayoutText
// optionally notifying a BidiResolver every time it steps into/out of a LayoutInline.
......@@ -565,14 +581,14 @@ static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter)
// FIXME: This belongs on InlineBidiResolver, except it's a template specialization
// of BidiResolver which knows nothing about LayoutObjects.
static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, LineLayoutItem obj, unsigned pos)
static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, LineLayoutItem obj, unsigned pos, LineLayoutItem root)
{
ASSERT(obj);
BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolver.dir());
resolver.runs().addRun(isolatedRun);
// FIXME: isolatedRuns() could be a hash of object->run and then we could cheaply
// ASSERT here that we didn't create multiple objects for the same inline.
resolver.isolatedRuns().append(isolatedRun);
resolver.isolatedRuns().append(BidiIsolatedRun(*obj, pos, *root, *isolatedRun));
return isolatedRun;
}
......@@ -616,7 +632,7 @@ public:
void commitExplicitEmbedding(BidiRunList<BidiRun>&) { }
BidiRunList<BidiRun>& runs() { return m_runs; }
void addFakeRunIfNecessary(LineLayoutItem obj, unsigned pos, unsigned end, InlineBidiResolver& resolver)
void addFakeRunIfNecessary(LineLayoutItem obj, unsigned pos, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver)
{
// We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine.
// We'll be called for every span inside the isolated span so we just ignore subsequent calls.
......@@ -624,8 +640,8 @@ public:
if (LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj))
return;
if (!m_haveAddedFakeRunForRootIsolate) {
BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos);
resolver.setMidpointStateForIsolatedRun(run, m_midpointStateForRootIsolate);
BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos, root);
resolver.setMidpointStateForIsolatedRun(*run, m_midpointStateForRootIsolate);
m_haveAddedFakeRunForRootIsolate = true;
}
// obj and pos together denote a single position in the inline, from which the parsing of the isolate will start.
......@@ -640,7 +656,7 @@ private:
BidiRunList<BidiRun>& m_runs;
};
static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker)
static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker)
{
// Trailing space code creates empty BidiRun objects, start == end, so
// that case needs to be handled specifically.
......@@ -655,14 +671,14 @@ static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start
if (end - start > limit)
limitedEnd = start + limit;
if (behavior == AppendingFakeRun)
tracker.addFakeRunIfNecessary(obj, start, limitedEnd, resolver);
tracker.addFakeRunIfNecessary(obj, start, limitedEnd, root, resolver);
else
resolver.runs().addRun(createRun(start, limitedEnd, obj, resolver));
start = limitedEnd;
}
}
static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker)
static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker)
{
if (start > end || LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj))
return;
......@@ -681,10 +697,10 @@ static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, un
start = nextMidpoint.offset();
lineMidpointState.incrementCurrentMidpoint();
if (start < end)
return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, resolver, behavior, tracker);
return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, root, resolver, behavior, tracker);
} else {
if (!haveNextMidpoint || (obj != nextMidpoint.object())) {
appendRunObjectIfNecessary(obj, start, end, resolver, behavior, tracker);
appendRunObjectIfNecessary(obj, start, end, root, resolver, behavior, tracker);
return;
}
......@@ -695,19 +711,19 @@ static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, un
lineMidpointState.incrementCurrentMidpoint();
if (nextMidpoint.offset() != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it.
if (nextMidpoint.offset() + 1 > start)
appendRunObjectIfNecessary(obj, start, nextMidpoint.offset() + 1, resolver, behavior, tracker);
return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.offset() + 1, end, resolver, behavior, tracker);
appendRunObjectIfNecessary(obj, start, nextMidpoint.offset() + 1, root, resolver, behavior, tracker);
return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.offset() + 1, end, root, resolver, behavior, tracker);
}
} else {
appendRunObjectIfNecessary(obj, start, end, resolver, behavior, tracker);
appendRunObjectIfNecessary(obj, start, end, root, resolver, behavior, tracker);
}
}
}
static inline void addFakeRunIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, IsolateTracker& tracker)
static inline void addFakeRunIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, IsolateTracker& tracker)
{
tracker.setMidpointStateForRootIsolate(resolver.midpointState());
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), resolver, AppendingFakeRun, tracker);
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), root, resolver, AppendingFakeRun, tracker);
}
template <>
......@@ -722,9 +738,9 @@ inline void InlineBidiResolver::appendRun(BidiRunList<BidiRun>& runs)
LineLayoutItem obj = m_sor.object();
while (obj && obj != m_eor.object() && obj != m_endOfRunAtEndOfLine.object()) {
if (isolateTracker.inIsolate())
addFakeRunIfNecessary(obj, start, obj.length(), *this, isolateTracker);
addFakeRunIfNecessary(obj, start, obj.length(), m_sor.root(), *this, isolateTracker);
else
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), *this, AppendingRunsForObject, isolateTracker);
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), m_sor.root(), *this, AppendingRunsForObject, isolateTracker);
// FIXME: start/obj should be an InlineIterator instead of two separate variables.
start = 0;
obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracker);
......@@ -739,9 +755,9 @@ inline void InlineBidiResolver::appendRun(BidiRunList<BidiRun>& runs)
// It's OK to add runs for zero-length LayoutObjects, just don't make the run larger than it should be
int end = obj.length() ? pos + 1 : 0;
if (isolateTracker.inIsolate())
addFakeRunIfNecessary(obj, start, end, *this, isolateTracker);
addFakeRunIfNecessary(obj, start, end, m_sor.root(), *this, isolateTracker);
else
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, *this, AppendingRunsForObject, isolateTracker);
adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, m_sor.root(), *this, AppendingRunsForObject, isolateTracker);
}
if (isEndOfLine)
......
......@@ -34,10 +34,11 @@ namespace blink {
class InlineIterator;
struct BidiRun;
struct BidiIsolatedRun;
template <class Iterator, class Run> class BidiResolver;
template <class Iterator, class Run, class IsolatedRun> class BidiResolver;
template <class Iterator> class MidpointState;
typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
typedef BidiResolver<InlineIterator, BidiRun, BidiIsolatedRun> InlineBidiResolver;
typedef MidpointState<InlineIterator> LineMidpointState;
// This class allows us to ensure lineboxes are created in the right place on the line when
......
......@@ -178,9 +178,12 @@ enum VisualDirectionOverride {
VisualRightToLeftOverride
};
class NoIsolatedRun {
};
// BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm
// http://unicode.org/reports/tr9
template <class Iterator, class Run> class BidiResolver {
template <class Iterator, class Run, class IsolatedRun = NoIsolatedRun> class BidiResolver {
WTF_MAKE_NONCOPYABLE(BidiResolver);
public:
BidiResolver()
......@@ -243,7 +246,7 @@ public:
// It's unclear if this is still needed.
void markCurrentRunEmpty() { m_emptyRun = true; }
Vector<Run*>& isolatedRuns() { return m_isolatedRuns; }
Vector<IsolatedRun>& isolatedRuns() { return m_isolatedRuns; }
bool isEndOfLine(const Iterator& end) { return m_current == end || m_current.atEnd(); }
......@@ -258,8 +261,8 @@ public:
return determineDirectionalityInternal(breakOnParagraph, hasStrongDirectionality);
}
void setMidpointStateForIsolatedRun(Run*, const MidpointState<Iterator>&);
MidpointState<Iterator> midpointStateForIsolatedRun(Run*);
void setMidpointStateForIsolatedRun(Run&, const MidpointState<Iterator>&);
MidpointState<Iterator> midpointStateForIsolatedRun(Run&);
Iterator endOfLine() const { return m_endOfLine; }
......@@ -294,7 +297,7 @@ protected:
MidpointState<Iterator> m_midpointState;
unsigned m_nestedIsolateCount;
Vector<Run*> m_isolatedRuns;
Vector<IsolatedRun> m_isolatedRuns;
Run* m_trailingSpaceRun;
TextDirection m_paragraphDirectionality;
......@@ -318,16 +321,16 @@ private:
};
#if ENABLE(ASSERT)
template <class Iterator, class Run>
BidiResolver<Iterator, Run>::~BidiResolver()
template <class Iterator, class Run, class IsolatedRun>
BidiResolver<Iterator, Run, IsolatedRun>::~BidiResolver()
{
// The owner of this resolver should have handled the isolated runs.
ASSERT(m_isolatedRuns.isEmpty());
}
#endif
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::appendRun(BidiRunList<Run>& runs)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::appendRun(BidiRunList<Run>& runs)
{
if (!m_emptyRun && !m_eor.atEnd()) {
unsigned startOffset = m_sor.offset();
......@@ -361,8 +364,8 @@ void BidiResolver<Iterator, Run>::appendRun(BidiRunList<Run>& runs)
m_status.eor = WTF::Unicode::OtherNeutral;
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source)
{
// Isolated spans compute base directionality during their own UBA run.
// Do not insert fake embed characters once we enter an isolated span.
......@@ -373,8 +376,8 @@ void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddi
m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source));
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel()
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::checkDirectionInLowerRaiseEmbeddingLevel()
{
using namespace WTF::Unicode;
......@@ -390,8 +393,8 @@ void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel()
m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::lowerExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from)
{
using namespace WTF::Unicode;
......@@ -428,8 +431,8 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(BidiRunList<Run>&
m_eor = Iterator();
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::raiseExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to)
{
using namespace WTF::Unicode;
......@@ -467,8 +470,8 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(BidiRunList<Run>&
m_eor = Iterator();
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::applyL1Rule(BidiRunList<Run>& runs)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::applyL1Rule(BidiRunList<Run>& runs)
{
ASSERT(runs.runCount());
if (!needsToApplyL1Rule(runs))
......@@ -506,8 +509,8 @@ void BidiResolver<Iterator, Run>::applyL1Rule(BidiRunList<Run>& runs)
m_trailingSpaceRun = trailingSpaceRun;
}
template <class Iterator, class Run>
bool BidiResolver<Iterator, Run>::commitExplicitEmbedding(BidiRunList<Run>& runs)
template <class Iterator, class Run, class IsolatedRun>
bool BidiResolver<Iterator, Run, IsolatedRun>::commitExplicitEmbedding(BidiRunList<Run>& runs)
{
// When we're "inIsolate()" we're resolving the parent context which
// ignores (skips over) the isolated content, including embedding levels.
......@@ -551,8 +554,8 @@ bool BidiResolver<Iterator, Run>::commitExplicitEmbedding(BidiRunList<Run>& runs
return fromLevel != toLevel;
}
template <class Iterator, class Run>
inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent)
template <class Iterator, class Run, class IsolatedRun>
inline void BidiResolver<Iterator, Run, IsolatedRun>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent)
{
using namespace WTF::Unicode;
switch (dirCurrent) {
......@@ -593,8 +596,8 @@ inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WT
}
}
template <class Iterator, class Run>
inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels(BidiRunList<Run>& runs) const
template <class Iterator, class Run, class IsolatedRun>
inline void BidiResolver<Iterator, Run, IsolatedRun>::reorderRunsFromLevels(BidiRunList<Run>& runs) const
{
unsigned char levelLow = BidiContext::kMaxLevel;
unsigned char levelHigh = 0;
......@@ -630,8 +633,8 @@ inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels(BidiRunList<Run>&
}
}
template <class Iterator, class Run>
TextDirection BidiResolver<Iterator, Run>::determineDirectionalityInternal(
template <class Iterator, class Run, class IsolatedRun>
TextDirection BidiResolver<Iterator, Run, IsolatedRun>::determineDirectionalityInternal(
bool breakOnParagraph, bool* hasStrongDirectionality)
{
while (!m_current.atEnd()) {
......@@ -682,8 +685,8 @@ inline TextDirection directionForCharacter(UChar32 character)
return LTR;
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak, bool reorderRuns)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak, bool reorderRuns)
{
using namespace WTF::Unicode;
......@@ -714,7 +717,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
m_last = m_current;
bool lastLineEnded = false;
BidiResolver<Iterator, Run> stateAtEnd;
BidiResolver<Iterator, Run, IsolatedRun> stateAtEnd;
while (true) {
if (inIsolate() && m_emptyRun) {
......@@ -1091,20 +1094,19 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis
applyL1Rule(m_runs);
}
template <class Iterator, class Run>
void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint)
template <class Iterator, class Run, class IsolatedRun>
void BidiResolver<Iterator, Run, IsolatedRun>::setMidpointStateForIsolatedRun(Run& run, const MidpointState<Iterator>& midpoint)
{
ASSERT(!m_midpointStateForIsolatedRun.contains(run));
m_midpointStateForIsolatedRun.add(run, midpoint);
ASSERT(!m_midpointStateForIsolatedRun.contains(&run));
m_midpointStateForIsolatedRun.add(&run, midpoint);
}
template<class Iterator, class Run>
MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun(Run* run)
template<class Iterator, class Run, class IsolatedRun>
MidpointState<Iterator> BidiResolver<Iterator, Run, IsolatedRun>::midpointStateForIsolatedRun(Run& run)
{
return m_midpointStateForIsolatedRun.take(run);
return m_midpointStateForIsolatedRun.take(&run);
}
} // namespace blink
#endif // BidiResolver_h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment