提交 17237e98 编写于 作者: M Matt Perry 提交者: GitHub

Add support for a maxLines property on Paragraph. (#3338)

Also fix 'ellipsis' overflow handling to work for multiline text.

Fixes https://github.com/flutter/flutter/issues/7271
上级 ccf1f099
......@@ -384,6 +384,7 @@ Int32List _encodeParagraphStyle(TextAlign textAlign,
String fontFamily,
double fontSize,
double lineHeight,
int maxLines,
String ellipsis) {
Int32List result = new Int32List(5);
if (textAlign != null) {
......@@ -414,10 +415,14 @@ Int32List _encodeParagraphStyle(TextAlign textAlign,
result[0] |= 1 << 7;
// Passed separately to native.
}
if (ellipsis != null) {
if (maxLines != null) {
result[0] |= 1 << 8;
// Passed separately to native.
}
if (ellipsis != null) {
result[0] |= 1 << 9;
// Passed separately to native.
}
return result;
}
......@@ -441,6 +446,7 @@ class ParagraphStyle {
String fontFamily,
double fontSize,
double lineHeight,
int maxLines,
String ellipsis
}) : _encoded = _encodeParagraphStyle(textAlign,
fontWeight,
......@@ -449,10 +455,12 @@ class ParagraphStyle {
fontFamily,
fontSize,
lineHeight,
maxLines,
ellipsis),
_fontFamily = fontFamily,
_fontSize = fontSize,
_lineHeight = lineHeight,
_maxLines = maxLines,
_ellipsis = ellipsis {
assert(lineCount == null);
}
......@@ -461,6 +469,7 @@ class ParagraphStyle {
final String _fontFamily;
final double _fontSize;
final double _lineHeight;
final int _maxLines;
final String _ellipsis;
bool operator ==(dynamic other) {
......@@ -472,6 +481,7 @@ class ParagraphStyle {
if ( _fontFamily != typedOther._fontFamily ||
_fontSize != typedOther._fontSize ||
_lineHeight != typedOther._lineHeight ||
_maxLines != typedOther._maxLines ||
_ellipsis != typedOther._ellipsis)
return false;
for (int index = 0; index < _encoded.length; index += 1) {
......@@ -481,7 +491,7 @@ class ParagraphStyle {
return true;
}
int get hashCode => hashValues(hashList(_encoded), _lineHeight);
int get hashCode => hashValues(hashList(_encoded), _lineHeight, _maxLines, _ellipsis);
String toString() {
return 'ParagraphStyle('
......@@ -492,7 +502,8 @@ class ParagraphStyle {
'fontFamily: ${ _encoded[0] & 0x20 == 0x20 ? _fontFamily : "unspecified"}, '
'fontSize: ${ _encoded[0] & 0x40 == 0x40 ? _fontSize : "unspecified"}, '
'lineHeight: ${ _encoded[0] & 0x80 == 0x80 ? "${_lineHeight}x" : "unspecified"}, '
'ellipsis: ${ _encoded[0] & 0x100 == 0x100 ? "\"$_ellipsis\"" : "unspecified"}'
'maxLines: ${ _encoded[0] & 0x100 == 0x100 ? _maxLines : "unspecified"}, '
'ellipsis: ${ _encoded[0] & 0x200 == 0x200 ? "\"$_ellipsis\"" : "unspecified"}'
')';
}
}
......@@ -716,8 +727,8 @@ abstract class Paragraph extends NativeFieldWrapperClass2 {
class ParagraphBuilder extends NativeFieldWrapperClass2 {
/// Creates a [ParagraphBuilder] object, which is used to create a
/// [Paragraph].
ParagraphBuilder(ParagraphStyle style) { _constructor(style._encoded, style._fontFamily, style._fontSize, style._lineHeight, style._ellipsis); }
void _constructor(Int32List encoded, String fontFamily, double fontSize, double lineHeight, String ellipsis) native "ParagraphBuilder_constructor";
ParagraphBuilder(ParagraphStyle style) { _constructor(style._encoded, style._fontFamily, style._fontSize, style._lineHeight, style._maxLines, style._ellipsis); }
void _constructor(Int32List encoded, String fontFamily, double fontSize, double lineHeight, int maxLines, String ellipsis) native "ParagraphBuilder_constructor";
/// Applies the given style to the added text until [pop] is called.
///
......
......@@ -57,7 +57,8 @@ const int psFontStyleIndex = 3;
const int psFontFamilyIndex = 5;
const int psFontSizeIndex = 6;
const int psLineHeightIndex = 7;
const int psEllipsisIndex = 8;
const int psMaxLinesIndex = 8;
const int psEllipsisIndex = 9;
const int psTextAlignMask = 1 << psTextAlignIndex;
const int psFontWeightMask = 1 << psFontWeightIndex;
......@@ -65,6 +66,7 @@ const int psFontStyleMask = 1 << psFontStyleIndex;
const int psFontFamilyMask = 1 << psFontFamilyIndex;
const int psFontSizeMask = 1 << psFontSizeIndex;
const int psLineHeightMask = 1 << psLineHeightIndex;
const int psMaxLinesMask = 1 << psMaxLinesIndex;
const int psEllipsisMask = 1 << psEllipsisIndex;
float getComputedSizeFromSpecifiedSize(float specifiedSize) {
......@@ -100,6 +102,7 @@ PassRefPtr<RenderStyle> decodeParagraphStyle(
const std::string& fontFamily,
double fontSize,
double lineHeight,
int maxLines,
const std::string& ellipsis) {
FTL_DCHECK(encoded.num_elements() == 5);
......@@ -144,10 +147,11 @@ PassRefPtr<RenderStyle> decodeParagraphStyle(
if (mask & psLineHeightMask)
style->setLineHeight(Length(lineHeight * 100.0, Percent));
if (mask & psEllipsisMask) {
if (mask & psMaxLinesMask)
style->setMaxLines(maxLines);
if (mask & psEllipsisMask)
style->setEllipsis(AtomicString::fromUTF8(ellipsis.c_str()));
style->setWordBreak(BreakAllWordBreak);
}
return style.release();
}
......@@ -175,7 +179,7 @@ FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
void ParagraphBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register(
{{"ParagraphBuilder_constructor", ParagraphBuilder_constructor, 6, true},
{{"ParagraphBuilder_constructor", ParagraphBuilder_constructor, 7, true},
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
......@@ -184,20 +188,22 @@ ftl::RefPtr<ParagraphBuilder> ParagraphBuilder::create(
const std::string& fontFamily,
double fontSize,
double lineHeight,
int maxLines,
const std::string& ellipsis) {
return ftl::MakeRefCounted<ParagraphBuilder>(
encoded, fontFamily, fontSize, lineHeight, ellipsis);
encoded, fontFamily, fontSize, lineHeight, maxLines, ellipsis);
}
ParagraphBuilder::ParagraphBuilder(tonic::Int32List& encoded,
const std::string& fontFamily,
double fontSize,
double lineHeight,
int maxLines,
const std::string& ellipsis) {
createRenderView();
RefPtr<RenderStyle> paragraphStyle = decodeParagraphStyle(
m_renderView->style(), encoded, fontFamily, fontSize, lineHeight, ellipsis);
m_renderView->style(), encoded, fontFamily, fontSize, lineHeight, maxLines, ellipsis);
encoded.Release();
m_renderParagraph = new RenderParagraph();
......
......@@ -25,6 +25,7 @@ class ParagraphBuilder : public ftl::RefCountedThreadSafe<ParagraphBuilder>,
const std::string& fontFamily,
double fontSize,
double lineHeight,
int maxLines,
const std::string& ellipsis);
~ParagraphBuilder() override;
......@@ -48,6 +49,7 @@ class ParagraphBuilder : public ftl::RefCountedThreadSafe<ParagraphBuilder>,
const std::string& fontFamily,
double fontSize,
double lineHeight,
int maxLines,
const std::string& ellipsis);
void createRenderView();
......
......@@ -23,7 +23,6 @@
#include "flutter/sky/engine/wtf/Vector.h"
#include "flutter/sky/engine/wtf/unicode/CharacterNames.h"
namespace blink {
using namespace WTF::Unicode;
......
......@@ -62,6 +62,8 @@ InlineIterator BreakingContext::handleEndOfLine()
} while (!m_lineBreak.atEnd() && isEmptyInline(m_lineBreak.object()));
}
m_lineInfo.incrementLineIndex();
return m_lineBreak;
}
......
......@@ -84,7 +84,6 @@ public:
void increment();
void handleBR();
void handleOutOfFlowPositioned(Vector<RenderBox*>& positionedObjects);
void handleEmptyInline();
void handleReplaced();
......@@ -225,26 +224,6 @@ inline void BreakingContext::increment()
m_atStart = false;
}
inline void BreakingContext::handleBR()
{
if (m_width.fitsOnLine()) {
RenderObject* br = m_current.object();
m_lineBreak.moveToStartOf(br);
m_lineBreak.increment();
// A <br> always breaks a line, so don't let the line be collapsed
// away. Also, the space at the end of a line with a <br> does not
// get collapsed away. It only does this if the previous line broke
// cleanly. Otherwise the <br> has no effect on whether the line is
// empty or not.
if (m_startingNewParagraph)
m_lineInfo.setEmpty(false, m_block, &m_width);
m_trailingObjects.clear();
m_lineInfo.setPreviousLineBrokeCleanly(true);
}
m_atEnd = true;
}
inline LayoutUnit borderPaddingMarginStart(RenderInline* child)
{
return child->marginStart() + child->paddingStart() + child->borderStart();
......@@ -467,12 +446,16 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
float hyphenWidth = 0;
bool ellipsizeMode = !m_blockStyle->ellipsis().isEmpty();
bool ellipsizeMode = false;
float ellipsisWidth = 0;
unsigned ellipsisBreakOffset = 0;
if (ellipsizeMode) {
ASSERT(breakAll);
ellipsisWidth = measureEllipsisWidth(renderText, font, m_blockStyle->ellipsis().string());
if (m_lineInfo.lineIndex() == m_blockStyle->maxLines() - 1 ||
m_blockStyle->maxLines() == INT_MAX) {
ellipsizeMode = !m_blockStyle->ellipsis().isEmpty();
if (ellipsizeMode) {
ellipsisWidth = measureEllipsisWidth(renderText, font, m_blockStyle->ellipsis().string());
breakAll = true;
}
}
if (m_renderTextInfo.m_text != renderText) {
......@@ -629,6 +612,7 @@ inline bool BreakingContext::handleText(WordMeasurements& wordMeasurements, bool
m_lineBreak.moveTo(m_current.object(), m_current.offset(), m_current.nextBreakablePosition());
m_lineBreak.increment();
m_lineInfo.setPreviousLineBrokeCleanly(true);
m_lineInfo.incrementLineIndex(); // caller only calls this if we return false
return true;
}
......
......@@ -36,6 +36,7 @@ public:
, m_isEmpty(true)
, m_previousLineBrokeCleanly(true)
, m_runsFromLeadingWhitespace(0)
, m_lineIndex(0)
{ }
bool isFirstLine() const { return m_isFirstLine; }
......@@ -53,6 +54,9 @@ public:
m_isEmpty = empty;
}
void incrementLineIndex() { ++m_lineIndex; }
int lineIndex() const { return m_lineIndex; }
void setPreviousLineBrokeCleanly(bool previousLineBrokeCleanly) { m_previousLineBrokeCleanly = previousLineBrokeCleanly; }
private:
......@@ -61,6 +65,7 @@ private:
bool m_isEmpty;
bool m_previousLineBrokeCleanly;
unsigned m_runsFromLeadingWhitespace;
int m_lineIndex;
};
}
......
......@@ -645,6 +645,7 @@ public:
// Flutter property getters
const AtomicString& ellipsis() const { return rareNonInheritedData->m_ellipsis; }
int maxLines() const { return rareNonInheritedData->m_maxLines; }
// attribute setter methods
......@@ -905,6 +906,7 @@ public:
// Flutter property setters
void setEllipsis(const AtomicString& e) { SET_VAR(rareNonInheritedData, m_ellipsis, e); }
void setMaxLines(int m) { SET_VAR(rareNonInheritedData, m_maxLines, m); }
static ClipPathOperation* initialClipPath() { return 0; }
......
......@@ -40,6 +40,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, m_textDecorationColor(StyleColor::currentColor())
, m_order(RenderStyle::initialOrder())
, m_objectPosition(RenderStyle::initialObjectPosition())
, m_maxLines(INT_MAX)
, m_transformStyle3D(RenderStyle::initialTransformStyle3D())
, m_alignContent(RenderStyle::initialAlignContent())
, m_alignItems(RenderStyle::initialAlignItems())
......@@ -79,6 +80,7 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, m_textDecorationColor(o.m_textDecorationColor)
, m_order(o.m_order)
, m_objectPosition(o.m_objectPosition)
, m_maxLines(o.m_maxLines)
, m_transformStyle3D(o.m_transformStyle3D)
, m_alignContent(o.m_alignContent)
, m_alignItems(o.m_alignItems)
......@@ -122,6 +124,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& m_textDecorationColor == o.m_textDecorationColor
&& m_order == o.m_order
&& m_objectPosition == o.m_objectPosition
&& m_maxLines == o.m_maxLines
&& m_transformStyle3D == o.m_transformStyle3D
&& m_alignContent == o.m_alignContent
&& m_alignItems == o.m_alignItems
......
......@@ -88,6 +88,7 @@ public:
LengthPoint m_objectPosition;
AtomicString m_ellipsis;
int m_maxLines;
unsigned m_transformStyle3D : 1; // ETransformStyle3D
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册