Commit 365d2277 authored by Adam Barth's avatar Adam Barth

Rename ParagraphPainter to TextPainter

Also, add asserts that the text has layout before being painted.
parent 5feb77f6
...@@ -90,8 +90,8 @@ class StyledTextSpan extends TextSpan { ...@@ -90,8 +90,8 @@ class StyledTextSpan extends TextSpan {
} }
} }
class ParagraphPainter { class TextPainter {
ParagraphPainter(TextSpan text) { TextPainter(TextSpan text) {
_layoutRoot.rootElement = _document.createElement('p'); _layoutRoot.rootElement = _document.createElement('p');
assert(text != null); assert(text != null);
this.text = text; this.text = text;
...@@ -99,40 +99,68 @@ class ParagraphPainter { ...@@ -99,40 +99,68 @@ class ParagraphPainter {
final sky.Document _document = new sky.Document(); final sky.Document _document = new sky.Document();
final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot(); final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot();
bool _needsLayout = true;
TextSpan _text; TextSpan _text;
TextSpan get text => _text; TextSpan get text => _text;
void set text(TextSpan value) { void set text(TextSpan value) {
if (_text == value)
return;
_text = value; _text = value;
_layoutRoot.rootElement.setChild(_text._toDOM(_document)); _layoutRoot.rootElement.setChild(_text._toDOM(_document));
_layoutRoot.rootElement.removeAttribute('style'); _layoutRoot.rootElement.removeAttribute('style');
_text._applyStyleToContainer(_layoutRoot.rootElement); _text._applyStyleToContainer(_layoutRoot.rootElement);
_needsLayout = true;
} }
double get minWidth => _layoutRoot.minWidth; double get minWidth => _layoutRoot.minWidth;
void set minWidth(value) { void set minWidth(value) {
if (_layoutRoot.minWidth == value)
return;
_layoutRoot.minWidth = value; _layoutRoot.minWidth = value;
_needsLayout = true;
} }
double get maxWidth => _layoutRoot.maxWidth; double get maxWidth => _layoutRoot.maxWidth;
void set maxWidth(value) { void set maxWidth(value) {
if (_layoutRoot.maxWidth == value)
return;
_layoutRoot.maxWidth = value; _layoutRoot.maxWidth = value;
_needsLayout = true;
} }
double get minHeight => _layoutRoot.minHeight; double get minHeight => _layoutRoot.minHeight;
void set minHeight(value) { void set minHeight(value) {
if (_layoutRoot.minHeight == value)
return;
_layoutRoot.minHeight = value; _layoutRoot.minHeight = value;
_needsLayout = true;
} }
double get maxHeight => _layoutRoot.maxHeight; double get maxHeight => _layoutRoot.maxHeight;
void set maxHeight(value) { void set maxHeight(value) {
if (_layoutRoot.maxHeight == value)
return;
_layoutRoot.maxHeight = value; _layoutRoot.maxHeight = value;
} }
double get minContentWidth => _layoutRoot.rootElement.minContentWidth; double get minContentWidth {
double get maxContentWidth => _layoutRoot.rootElement.maxContentWidth; assert(!_needsLayout);
double get height => _layoutRoot.rootElement.height; return _layoutRoot.rootElement.minContentWidth;
}
double get maxContentWidth {
assert(!_needsLayout);
return _layoutRoot.rootElement.maxContentWidth;
}
double get height {
assert(!_needsLayout);
return _layoutRoot.rootElement.height;
}
double computeDistanceToActualBaseline(TextBaseline baseline) { double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(!_needsLayout);
sky.Element root = _layoutRoot.rootElement; sky.Element root = _layoutRoot.rootElement;
switch (baseline) { switch (baseline) {
case TextBaseline.alphabetic: return root.alphabeticBaseline; case TextBaseline.alphabetic: return root.alphabeticBaseline;
...@@ -140,9 +168,15 @@ class ParagraphPainter { ...@@ -140,9 +168,15 @@ class ParagraphPainter {
} }
} }
void layout() => _layoutRoot.layout(); void layout() {
if (!_needsLayout)
return;
_layoutRoot.layout();
_needsLayout = false;
}
void paint(sky.Canvas canvas, sky.Offset offset) { void paint(sky.Canvas canvas, sky.Offset offset) {
assert(!_needsLayout && "Please call layout() before paint() to position the text before painting it." is String);
// TODO(ianh): Make LayoutRoot support a paint offset so we don't // TODO(ianh): Make LayoutRoot support a paint offset so we don't
// need to translate for each span of text. // need to translate for each span of text.
canvas.translate(offset.dx, offset.dy); canvas.translate(offset.dx, offset.dy);
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:sky/painting/paragraph_painter.dart'; import 'package:sky/painting/text_painter.dart';
import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/object.dart';
export 'package:sky/painting/paragraph_painter.dart'; export 'package:sky/painting/text_painter.dart';
// Unfortunately, using full precision floating point here causes bad layouts // Unfortunately, using full precision floating point here causes bad layouts
// because floating point math isn't associative. If we add and subtract // because floating point math isn't associative. If we add and subtract
...@@ -21,20 +21,19 @@ double _applyFloatingPointHack(double layoutValue) { ...@@ -21,20 +21,19 @@ double _applyFloatingPointHack(double layoutValue) {
class RenderParagraph extends RenderBox { class RenderParagraph extends RenderBox {
RenderParagraph(TextSpan text) RenderParagraph(TextSpan text) : _textPainter = new TextPainter(text) {
: _paragraphPainter = new ParagraphPainter(text) {
assert(text != null); assert(text != null);
} }
ParagraphPainter _paragraphPainter; TextPainter _textPainter;
BoxConstraints _constraintsForCurrentLayout; // when null, we don't have a current layout BoxConstraints _constraintsForCurrentLayout; // when null, we don't have a current layout
TextSpan get text => _paragraphPainter.text; TextSpan get text => _textPainter.text;
void set text(TextSpan value) { void set text(TextSpan value) {
if (_paragraphPainter.text == value) if (_textPainter.text == value)
return; return;
_paragraphPainter.text = value; _textPainter.text = value;
_constraintsForCurrentLayout = null; _constraintsForCurrentLayout = null;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -43,30 +42,30 @@ class RenderParagraph extends RenderBox { ...@@ -43,30 +42,30 @@ class RenderParagraph extends RenderBox {
assert(constraints != null); assert(constraints != null);
if (_constraintsForCurrentLayout == constraints) if (_constraintsForCurrentLayout == constraints)
return; // already cached this layout return; // already cached this layout
_paragraphPainter.maxWidth = constraints.maxWidth; _textPainter.maxWidth = constraints.maxWidth;
_paragraphPainter.minWidth = constraints.minWidth; _textPainter.minWidth = constraints.minWidth;
_paragraphPainter.minHeight = constraints.minHeight; _textPainter.minHeight = constraints.minHeight;
_paragraphPainter.maxHeight = constraints.maxHeight; _textPainter.maxHeight = constraints.maxHeight;
_paragraphPainter.layout(); _textPainter.layout();
_constraintsForCurrentLayout = constraints; _constraintsForCurrentLayout = constraints;
} }
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
_layout(constraints); _layout(constraints);
return constraints.constrainWidth( return constraints.constrainWidth(
_applyFloatingPointHack(_paragraphPainter.minContentWidth)); _applyFloatingPointHack(_textPainter.minContentWidth));
} }
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(BoxConstraints constraints) {
_layout(constraints); _layout(constraints);
return constraints.constrainWidth( return constraints.constrainWidth(
_applyFloatingPointHack(_paragraphPainter.maxContentWidth)); _applyFloatingPointHack(_textPainter.maxContentWidth));
} }
double _getIntrinsicHeight(BoxConstraints constraints) { double _getIntrinsicHeight(BoxConstraints constraints) {
_layout(constraints); _layout(constraints);
return constraints.constrainHeight( return constraints.constrainHeight(
_applyFloatingPointHack(_paragraphPainter.height)); _applyFloatingPointHack(_textPainter.height));
} }
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(BoxConstraints constraints) {
...@@ -80,14 +79,14 @@ class RenderParagraph extends RenderBox { ...@@ -80,14 +79,14 @@ class RenderParagraph extends RenderBox {
double computeDistanceToActualBaseline(TextBaseline baseline) { double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(!needsLayout); assert(!needsLayout);
_layout(constraints); _layout(constraints);
return _paragraphPainter.computeDistanceToActualBaseline(baseline); return _textPainter.computeDistanceToActualBaseline(baseline);
} }
void performLayout() { void performLayout() {
_layout(constraints); _layout(constraints);
// _paragraphPainter.width always expands to fill, use maxContentWidth instead. // _paragraphPainter.width always expands to fill, use maxContentWidth instead.
size = constraints.constrain(new Size(_applyFloatingPointHack(_paragraphPainter.maxContentWidth), size = constraints.constrain(new Size(_applyFloatingPointHack(_textPainter.maxContentWidth),
_applyFloatingPointHack(_paragraphPainter.height))); _applyFloatingPointHack(_textPainter.height)));
} }
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
...@@ -99,7 +98,7 @@ class RenderParagraph extends RenderBox { ...@@ -99,7 +98,7 @@ class RenderParagraph extends RenderBox {
// TODO(abarth): Make computing the min/max intrinsic width/height // TODO(abarth): Make computing the min/max intrinsic width/height
// a non-destructive operation. // a non-destructive operation.
_layout(constraints); _layout(constraints);
_paragraphPainter.paint(context.canvas, offset); _textPainter.paint(context.canvas, offset);
} }
// we should probably expose a way to do precise (inter-glpyh) hit testing // we should probably expose a way to do precise (inter-glpyh) hit testing
......
...@@ -9,8 +9,8 @@ import 'package:vector_math/vector_math.dart'; ...@@ -9,8 +9,8 @@ import 'package:vector_math/vector_math.dart';
import 'package:sky/base/image_resource.dart'; import 'package:sky/base/image_resource.dart';
import 'package:sky/mojo/asset_bundle.dart'; import 'package:sky/mojo/asset_bundle.dart';
import 'package:sky/mojo/net/image_cache.dart' as image_cache; import 'package:sky/mojo/net/image_cache.dart' as image_cache;
import 'package:sky/painting/text_painter.dart';
import 'package:sky/painting/text_style.dart'; import 'package:sky/painting/text_style.dart';
import 'package:sky/painting/paragraph_painter.dart';
import 'package:sky/rendering/block.dart'; import 'package:sky/rendering/block.dart';
import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/flex.dart'; import 'package:sky/rendering/flex.dart';
......
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