mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This CL generated by |sed -i '/sky\/engine\/config.h/d'| and a manual sweep to catch some oddballs. TBR=eseidel@chromium.org Review URL: https://codereview.chromium.org/1206763002.
210 lines
7.9 KiB
C++
210 lines
7.9 KiB
C++
/*
|
|
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
|
|
* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
|
|
* All right reserved.
|
|
* Copyright (C) 2010 Google Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "sky/engine/core/rendering/BidiRunForLine.h"
|
|
|
|
#include "sky/engine/core/rendering/InlineIterator.h"
|
|
|
|
namespace blink {
|
|
|
|
using namespace WTF::Unicode;
|
|
|
|
static RenderObject* firstRenderObjectForDirectionalityDetermination(
|
|
RenderObject* root, RenderObject* current = 0)
|
|
{
|
|
RenderObject* next = current;
|
|
while (current) {
|
|
if (isIsolated(current->style()->unicodeBidi())
|
|
&& (current->isRenderInline() || current->isRenderBlock())) {
|
|
if (current != root)
|
|
current = 0;
|
|
else
|
|
current = next;
|
|
break;
|
|
}
|
|
current = current->parent();
|
|
}
|
|
|
|
if (!current)
|
|
current = root->slowFirstChild();
|
|
|
|
while (current) {
|
|
next = 0;
|
|
if (isIteratorTarget(current) && !(current->isText()
|
|
&& toRenderText(current)->isAllCollapsibleWhitespace()))
|
|
break;
|
|
|
|
if (!isIteratorTarget(current)
|
|
&& !isIsolated(current->style()->unicodeBidi()))
|
|
next = current->slowFirstChild();
|
|
|
|
if (!next) {
|
|
while (current && current != root) {
|
|
next = current->nextSibling();
|
|
if (next)
|
|
break;
|
|
current = current->parent();
|
|
}
|
|
}
|
|
|
|
if (!next)
|
|
break;
|
|
|
|
current = next;
|
|
}
|
|
|
|
return current;
|
|
}
|
|
|
|
TextDirection determinePlaintextDirectionality(RenderObject* root,
|
|
RenderObject* current, unsigned pos)
|
|
{
|
|
InlineIterator iter(root,
|
|
firstRenderObjectForDirectionalityDetermination(root, current), pos);
|
|
InlineBidiResolver observer;
|
|
observer.setStatus(BidiStatus(root->style()->direction(),
|
|
isOverride(root->style()->unicodeBidi())));
|
|
observer.setPositionIgnoringNestedIsolates(iter);
|
|
return observer.determineParagraphDirectionality();
|
|
}
|
|
|
|
// FIXME: This should be a BidiStatus constructor or create method.
|
|
static inline BidiStatus statusWithDirection(TextDirection textDirection,
|
|
bool isOverride)
|
|
{
|
|
WTF::Unicode::Direction direction = textDirection == LTR
|
|
? LeftToRight
|
|
: RightToLeft;
|
|
RefPtr<BidiContext> context = BidiContext::create(
|
|
textDirection == LTR ? 0 : 1, direction, isOverride, FromStyleOrDOM);
|
|
|
|
// This copies BidiStatus and may churn the ref on BidiContext.
|
|
// I doubt it matters.
|
|
return BidiStatus(direction, direction, direction, context.release());
|
|
}
|
|
|
|
static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver,
|
|
RenderObject* root, RenderObject* startObject)
|
|
{
|
|
if (root != startObject) {
|
|
RenderObject* parent = startObject->parent();
|
|
setupResolverToResumeInIsolate(resolver, root, parent);
|
|
notifyObserverEnteredObject(&resolver, startObject);
|
|
}
|
|
}
|
|
|
|
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,
|
|
bool isNewUBAParagraph)
|
|
{
|
|
// FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
|
|
// of the resolver owning the runs.
|
|
ASSERT(&topResolver.runs() == &bidiRuns);
|
|
ASSERT(topResolver.position() != endOfLine);
|
|
RenderObject* currentRoot = topResolver.position().root();
|
|
topResolver.createBidiRunsForLine(endOfLine, override,
|
|
previousLineBrokeCleanly);
|
|
|
|
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();
|
|
topResolver.isolatedRuns().removeLast();
|
|
|
|
RenderObject* startObj = isolatedRun->object();
|
|
|
|
// Only inlines make sense with unicode-bidi: isolate (blocks are
|
|
// already isolated).
|
|
// FIXME: Because enterIsolate is not passed a RenderObject, we have to
|
|
// crawl up the tree to see which parent inline is the isolate. We could
|
|
// change enterIsolate to take a RenderObject and do this logic there,
|
|
// but that would be a layering violation for BidiResolver (which knows
|
|
// nothing about RenderObject).
|
|
RenderInline* isolatedInline = toRenderInline(
|
|
highestContainingIsolateWithinRoot(startObj, currentRoot));
|
|
ASSERT(isolatedInline);
|
|
|
|
InlineBidiResolver isolatedResolver;
|
|
LineMidpointState& isolatedLineMidpointState =
|
|
isolatedResolver.midpointState();
|
|
isolatedLineMidpointState = topResolver.midpointStateForIsolatedRun(
|
|
isolatedRun);
|
|
EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi();
|
|
TextDirection direction;
|
|
if (unicodeBidi == Plaintext) {
|
|
direction = determinePlaintextDirectionality(isolatedInline,
|
|
isNewUBAParagraph ? startObj : 0);
|
|
} else {
|
|
ASSERT(unicodeBidi == Isolate || unicodeBidi == IsolateOverride);
|
|
direction = isolatedInline->style()->direction();
|
|
}
|
|
isolatedResolver.setStatus(statusWithDirection(direction,
|
|
isOverride(unicodeBidi)));
|
|
|
|
setupResolverToResumeInIsolate(isolatedResolver, isolatedInline,
|
|
startObj);
|
|
|
|
// The starting position is the beginning of the first run within the
|
|
// isolate that was identified during the earlier call to
|
|
// createBidiRunsForLine. This can be but is not necessarily the first
|
|
// run within the isolate.
|
|
InlineIterator iter = InlineIterator(isolatedInline, startObj,
|
|
isolatedRun->m_start);
|
|
isolatedResolver.setPositionIgnoringNestedIsolates(iter);
|
|
// We stop at the next end of line; we may re-enter this isolate in the
|
|
// next call to constructBidiRuns().
|
|
// FIXME: What should end and previousLineBrokeCleanly be?
|
|
// rniwa says previousLineBrokeCleanly is just a WinIE hack and could
|
|
// always be false here?
|
|
isolatedResolver.createBidiRunsForLine(endOfLine, NoVisualOverride,
|
|
previousLineBrokeCleanly);
|
|
|
|
ASSERT(isolatedResolver.runs().runCount());
|
|
if (isolatedResolver.runs().runCount())
|
|
bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs());
|
|
|
|
// If we encountered any nested isolate runs, just move them
|
|
// to the top resolver's list for later processing.
|
|
if (!isolatedResolver.isolatedRuns().isEmpty()) {
|
|
topResolver.isolatedRuns().appendVector(
|
|
isolatedResolver.isolatedRuns());
|
|
currentRoot = isolatedInline;
|
|
restoreIsolatedMidpointStates(topResolver, isolatedResolver);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace blink
|