// 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. import 'dart:sky' as sky; import 'box.dart'; import 'object.dart'; class RenderInline extends RenderObject { String data; RenderInline(this.data); } // Unfortunately, using full precision floating point here causes bad layouts // because floating point math isn't associative. If we add and subtract // padding, for example, we'll get different values when we estimate sizes and // when we actually compute layout because the operations will end up associated // differently. To work around this problem for now, we round fractional pixel // values up to the nearest whole pixel value. The right long-term fix is to do // layout using fixed precision arithmetic. double _applyFloatingPointHack(double layoutValue) { return layoutValue.ceilToDouble(); } class RenderParagraph extends RenderBox { RenderParagraph({ String text, Color color }) : _color = color { _layoutRoot.rootElement = _document.createElement('p'); this.text = text; } final sky.Document _document = new sky.Document(); final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot(); String get text => (_layoutRoot.rootElement.firstChild as sky.Text).data; void set text (String value) { _layoutRoot.rootElement.setChild(_document.createText(value)); markNeedsLayout(); } Color _color = const Color(0xFF000000); Color get color => _color; void set color (Color value) { if (_color != value) { _color = value; markNeedsPaint(); } } BoxConstraints _constraintsForCurrentLayout; sky.Element _layout(BoxConstraints constraints) { _layoutRoot.maxWidth = constraints.maxWidth; _layoutRoot.minWidth = constraints.minWidth; _layoutRoot.minHeight = constraints.minHeight; _layoutRoot.maxHeight = constraints.maxHeight; _layoutRoot.layout(); _constraintsForCurrentLayout = constraints; } double getMinIntrinsicWidth(BoxConstraints constraints) { _layout(constraints); return constraints.constrainWidth( _applyFloatingPointHack(_layoutRoot.rootElement.minContentWidth)); } double getMaxIntrinsicWidth(BoxConstraints constraints) { _layout(constraints); return constraints.constrainWidth( _applyFloatingPointHack(_layoutRoot.rootElement.maxContentWidth)); } double _getIntrinsicHeight(BoxConstraints constraints) { _layout(constraints); return constraints.constrainHeight( _applyFloatingPointHack(_layoutRoot.rootElement.height.ceilToDouble)); } double getMinIntrinsicHeight(BoxConstraints constraints) { return _getIntrinsicHeight(constraints); } double getMaxIntrinsicHeight(BoxConstraints constraints) { return _getIntrinsicHeight(constraints); } void performLayout() { _layout(constraints); sky.Element root = _layoutRoot.rootElement; // rootElement.width always expands to fill, use maxContentWidth instead. size = constraints.constrain(new Size(_applyFloatingPointHack(root.maxContentWidth), _applyFloatingPointHack(root.height))); } void paint(RenderObjectDisplayList canvas) { // Ideally we could compute the min/max intrinsic width/height with a // non-destructive operation. However, currently, computing these values // will destroy state inside the layout root. If that happens, we need to // get back the correct state by calling _layout again. // // TODO(abarth): Make computing the min/max intrinsic width/height a // non-destructive operation. if (_constraintsForCurrentLayout != constraints && constraints != null) _layout(constraints); if (_color != null) { _layoutRoot.rootElement.style['color'] = 'rgba(${_color.red}, ${_color.green}, ${_color.blue}, ${_color.alpha / 255.0 })'; } _layoutRoot.paint(canvas); } // we should probably expose a way to do precise (inter-glpyh) hit testing String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}color: ${color}\n${prefix}text: ${text}\n'; }