mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
181 lines
5.5 KiB
C++
181 lines
5.5 KiB
C++
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/lib/ui/text/paragraph_impl_blink.h"
|
|
|
|
#include "flutter/common/threads.h"
|
|
#include "flutter/lib/ui/text/paragraph.h"
|
|
#include "flutter/lib/ui/text/paragraph_impl.h"
|
|
#include "flutter/sky/engine/core/rendering/PaintInfo.h"
|
|
#include "flutter/sky/engine/core/rendering/RenderParagraph.h"
|
|
#include "flutter/sky/engine/core/rendering/RenderText.h"
|
|
#include "flutter/sky/engine/core/rendering/style/RenderStyle.h"
|
|
#include "flutter/sky/engine/platform/fonts/FontCache.h"
|
|
#include "flutter/sky/engine/platform/graphics/GraphicsContext.h"
|
|
#include "flutter/sky/engine/platform/text/TextBoundaries.h"
|
|
#include "lib/fxl/tasks/task_runner.h"
|
|
#include "lib/tonic/converter/dart_converter.h"
|
|
#include "lib/tonic/dart_args.h"
|
|
#include "lib/tonic/dart_binding_macros.h"
|
|
#include "lib/tonic/dart_library_natives.h"
|
|
|
|
using tonic::ToDart;
|
|
|
|
namespace blink {
|
|
|
|
ParagraphImplBlink::ParagraphImplBlink(PassOwnPtr<RenderView> renderView)
|
|
: m_renderView(renderView) {}
|
|
|
|
ParagraphImplBlink::~ParagraphImplBlink() {
|
|
if (m_renderView) {
|
|
RenderView* renderView = m_renderView.leakPtr();
|
|
Threads::UI()->PostTask([renderView]() { renderView->destroy(); });
|
|
}
|
|
}
|
|
|
|
double ParagraphImplBlink::width() {
|
|
return firstChildBox()->width();
|
|
}
|
|
|
|
double ParagraphImplBlink::height() {
|
|
return firstChildBox()->height();
|
|
}
|
|
|
|
double ParagraphImplBlink::minIntrinsicWidth() {
|
|
return firstChildBox()->minPreferredLogicalWidth();
|
|
}
|
|
|
|
double ParagraphImplBlink::maxIntrinsicWidth() {
|
|
return firstChildBox()->maxPreferredLogicalWidth();
|
|
}
|
|
|
|
double ParagraphImplBlink::alphabeticBaseline() {
|
|
return firstChildBox()->firstLineBoxBaseline(
|
|
FontBaselineOrAuto(AlphabeticBaseline));
|
|
}
|
|
|
|
double ParagraphImplBlink::ideographicBaseline() {
|
|
return firstChildBox()->firstLineBoxBaseline(
|
|
FontBaselineOrAuto(IdeographicBaseline));
|
|
}
|
|
|
|
bool ParagraphImplBlink::didExceedMaxLines() {
|
|
RenderBox* box = firstChildBox();
|
|
ASSERT(box->isRenderParagraph());
|
|
RenderParagraph* paragraph = static_cast<RenderParagraph*>(box);
|
|
return paragraph->didExceedMaxLines();
|
|
}
|
|
|
|
void ParagraphImplBlink::layout(double width) {
|
|
FontCachePurgePreventer fontCachePurgePreventer;
|
|
|
|
int maxWidth = LayoutUnit(width); // Handles infinity properly.
|
|
m_renderView->setFrameViewSize(IntSize(maxWidth, intMaxForLayoutUnit));
|
|
m_renderView->layout();
|
|
}
|
|
|
|
void ParagraphImplBlink::paint(Canvas* canvas, double x, double y) {
|
|
SkCanvas* skCanvas = canvas->canvas();
|
|
if (!skCanvas)
|
|
return;
|
|
|
|
FontCachePurgePreventer fontCachePurgePreventer;
|
|
|
|
// Very simplified painting to allow painting an arbitrary (layer-less)
|
|
// subtree.
|
|
RenderBox* box = firstChildBox();
|
|
skCanvas->translate(x, y);
|
|
|
|
GraphicsContext context(skCanvas);
|
|
Vector<RenderBox*> layers;
|
|
LayoutRect bounds = box->absoluteBoundingBoxRect();
|
|
FXL_DCHECK(bounds.x() == 0 && bounds.y() == 0);
|
|
PaintInfo paintInfo(&context, enclosingIntRect(bounds), box);
|
|
box->paint(paintInfo, LayoutPoint(), layers);
|
|
// Note we're ignoring any layers encountered.
|
|
// TODO(abarth): Remove the concept of RenderLayers.
|
|
|
|
skCanvas->translate(-x, -y);
|
|
}
|
|
|
|
std::vector<TextBox> ParagraphImplBlink::getRectsForRange(unsigned start,
|
|
unsigned end) {
|
|
if (end <= start || start == end)
|
|
return std::vector<TextBox>();
|
|
|
|
unsigned offset = 0;
|
|
std::vector<TextBox> boxes;
|
|
for (RenderObject* object = m_renderView.get(); object;
|
|
object = object->nextInPreOrder()) {
|
|
if (!object->isText())
|
|
continue;
|
|
RenderText* text = toRenderText(object);
|
|
unsigned length = text->textLength();
|
|
if (offset + length > start) {
|
|
unsigned startOffset = offset > start ? 0 : start - offset;
|
|
unsigned endOffset = end - offset;
|
|
text->appendAbsoluteTextBoxesForRange(boxes, startOffset, endOffset);
|
|
}
|
|
offset += length;
|
|
if (offset >= end)
|
|
break;
|
|
}
|
|
|
|
return boxes;
|
|
}
|
|
|
|
int ParagraphImplBlink::absoluteOffsetForPosition(
|
|
const PositionWithAffinity& position) {
|
|
FXL_DCHECK(position.renderer());
|
|
unsigned offset = 0;
|
|
for (RenderObject* object = m_renderView.get(); object;
|
|
object = object->nextInPreOrder()) {
|
|
if (object == position.renderer())
|
|
return offset + position.offset();
|
|
if (object->isText()) {
|
|
RenderText* text = toRenderText(object);
|
|
offset += text->textLength();
|
|
}
|
|
}
|
|
FXL_DCHECK(false);
|
|
return 0;
|
|
}
|
|
|
|
Dart_Handle ParagraphImplBlink::getPositionForOffset(double dx, double dy) {
|
|
LayoutPoint point(dx, dy);
|
|
PositionWithAffinity position = m_renderView->positionForPoint(point);
|
|
Dart_Handle result = Dart_NewList(2);
|
|
Dart_ListSetAt(result, 0, ToDart(absoluteOffsetForPosition(position)));
|
|
Dart_ListSetAt(result, 1, ToDart(static_cast<int>(position.affinity())));
|
|
return result;
|
|
}
|
|
|
|
Dart_Handle ParagraphImplBlink::getWordBoundary(unsigned offset) {
|
|
String text;
|
|
int start = 0, end = 0;
|
|
|
|
for (RenderObject* object = m_renderView.get(); object;
|
|
object = object->nextInPreOrder()) {
|
|
if (!object->isText())
|
|
continue;
|
|
RenderText* renderText = toRenderText(object);
|
|
text.append(renderText->text());
|
|
}
|
|
|
|
TextBreakIterator* it = wordBreakIterator(text, 0, text.length());
|
|
if (it) {
|
|
end = it->following(offset);
|
|
if (end < 0)
|
|
end = it->last();
|
|
start = it->previous();
|
|
}
|
|
|
|
Dart_Handle result = Dart_NewList(2);
|
|
Dart_ListSetAt(result, 0, ToDart(start));
|
|
Dart_ListSetAt(result, 1, ToDart(end));
|
|
return result;
|
|
}
|
|
|
|
} // namespace blink
|