Skip to content

Commit

Permalink
c
Browse files Browse the repository at this point in the history
  • Loading branch information
xErik committed May 15, 2023
1 parent 17fc53f commit ccadc86
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 116 deletions.
20 changes: 15 additions & 5 deletions lib/hyphenatorx.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import 'dart:core';

import 'package:flutter/material.dart';
import 'package:hyphenatorx/src/calculationhelper.dart';
import 'package:hyphenatorx/src/extensions.dart';
import 'package:hyphenatorx/src/token/tokens.dart';

import 'languages/languageconfig.dart';
import 'src/pattern.dart';
import 'token/linewrapper.dart';
import 'token/wrapresult.dart';

/// Wrapper class hyphenating text.
class Hyphenator {
late final CalculationHelper calc;
final RegExp _reBoundaries = RegExp(r'[\t\ ]+');
final RegExp _split = RegExp(r'\n|[\t ]+');

static Language getLanguageEnum(String lang) {
Language l;
Expand Down Expand Up @@ -99,8 +104,14 @@ class Hyphenator {
List<String> get cachedNonHyphendWords =>
calc.cacheNonHyphendWords.values.toList();

// RegExp reLetter = RegExp(r'\p{Letter}', unicode: true);
final RegExp reBoundaries = RegExp(r'[\t\ ]+');
/// Wraps the [text] with respect to the given [style] and [maxWidth].
///
/// [WrapResult] holds a [Text] with the correctly hyphened [String].
WrapResult wrap(final Text text, final TextStyle style, final maxWidth) {
final tokens = hyphenateTextToTokens(text.data!);
final wrapper = LineWrapper(tokens, text, style, maxWidth);
return wrapper.render();
}

/// Hyphenates a text and returns this text broken down into a tree.
/// Each node being a potential candidate for leding and triling hyphenation.
Expand All @@ -120,10 +131,9 @@ class Hyphenator {
///
/// [[The], WS, [arts], WS, [are], WS, [a], NL, [vast], WS, [sub, di, vi, sion], WS]
///
final RegExp split = RegExp(r'\n|[\t ]+');
TextTokens hyphenateTextToTokens(final String text) {
final hyph = hyphenateText(text);
final parts = hyph.replaceAll(r'\r', '').splitWithDelim(split);
final parts = hyph.replaceAll(r'\r', '').splitWithDelim(_split);
final List<TextPartToken> partsResult = [];

for (final part in parts) {
Expand Down Expand Up @@ -203,7 +213,7 @@ class Hyphenator {
// including punctuation etc. following or preceeding a syllable.
return hyphenateText(text)
.toString()
.splitWithDelim(reBoundaries)
.splitWithDelim(_reBoundaries)
.join(calc.symbol);
}
}
Expand Down
71 changes: 0 additions & 71 deletions lib/hyphenatorx_flutter.dart

This file was deleted.

2 changes: 1 addition & 1 deletion lib/src/token/tokens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class WordPartToken extends TextPartToken {

WordPartToken(this.text);
int get length => text.length;
toString() => text;
toString() => text + ' c:${sizeCurrent} h:${sizeHyphen} no-h:${sizeNoHyphen}';
String render() => text;
WordPartToken toHyphenAndSize(String hyphen) =>
WordPartToken(text + hyphen)..sizeCurrent = sizeHyphen;
Expand Down
35 changes: 23 additions & 12 deletions lib/src/token/linewrapper.dart → lib/token/linewrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import 'dart:math';
import 'package:flutter/widgets.dart';
import 'package:hyphenatorx/src/token/texthelper.dart';

import '../../wrapresult.dart';
import 'tokeniterator.dart';
import 'tokens.dart';
import '../src/token/tokeniterator.dart';
import '../src/token/tokens.dart';
import 'wrapresult.dart';

/// Hyphenates tokens with respect to the attributes of
/// [Text], [TextStyle] and [maxWidth].
class LineWrapper {
final String _hyphen = '-\n';
final String _hyphen = '-';
late final double _maxWidth;
final List<List<TextPartToken>> _lines = [];
late final TextPainter _painter;
Expand Down Expand Up @@ -47,6 +47,8 @@ class LineWrapper {
part.sizeCurrent = part.sizeHyphen;
}
}

// print('=== CACHE: ${tokensWidthCache}');
}

/// Sets the widths of the token with respect to hyphend and not-hyphened.
Expand Down Expand Up @@ -91,17 +93,17 @@ class LineWrapper {
// ------------------------------------------------------------
if (currToken is NewlineToken) {
line.add(currToken);
_lines.add([...line]);
_lines.add([NewlineToken()]);
line.clear();
} else
// ------------------------------------------------------------
// TABS AND SPACES
// ------------------------------------------------------------
if (currToken is TabsAndSpacesToken) {
if (currToken is TabsAndSpacesToken && line.isNotEmpty) {
if (_canAddNoHyphen([currToken], line)) {
line.add(currToken);
} else {
_lines.add([...line]);
_lines.add([...line]..add(NewlineToken()));
line.clear();
line.add(currToken);
}
Expand All @@ -117,15 +119,14 @@ class LineWrapper {
for (int i = partLength; i > 0; i--) {
prelist = currToken.parts.sublist(0, i);
postlist = currToken.parts.sublist(i, partLength);

if (i == partLength && _canAddNoHyphen(prelist, line)) {
line.addAll([...prelist]);
line.add(currToken); // add whole word
prelist.clear();
postlist.clear();
break;
} else if (_canAddHyphenlast(prelist, line)) {
line.addAll(_doHyphenLast(prelist));
_lines.add([...line]);
_lines.add([...line]..add(NewlineToken()));
line.clear();
line.addAll(postlist);
prelist.clear();
Expand All @@ -137,6 +138,11 @@ class LineWrapper {
// if (prelist.isNotEmpty || postlist.isNotEmpty) {
// throw 'Cannot fit: $currToken in $_maxWidth px with fontSize ${_style.fontSize}';
// }

if (line.isNotEmpty) {
_lines.add([...line]..add(NewlineToken()));
line.clear();
}
}

// ------------------------------------------------------------
Expand All @@ -154,12 +160,17 @@ class LineWrapper {
_lines.add(line);
}

while (_lines.last.last is NewlineToken) {
_lines.last.removeLast();
}

final str =
_lines.map<String>((line) => line.map((e) => e.render()).join()).join();

_painter.text = TextSpan(text: str, style: _style);
_painter.layout();

// print('=== RENDERED: $str ${_painter.size}');

return WrapResult(
TextHelper.clone(_text, str), _style, _maxWidth, _painter.size, _lines);
}
Expand All @@ -169,7 +180,7 @@ class LineWrapper {
double w =
line.fold<double>(0, (sum, item) => sum + item.sizeCurrent!.width);

w += tokens.fold<double>(0, (sum, item) => item.sizeCurrent!.width);
w += tokens.fold<double>(0, (sum, item) => sum + item.sizeCurrent!.width);

return w <= _maxWidth;
}
Expand Down
9 changes: 7 additions & 2 deletions lib/wrapresult.dart → lib/token/wrapresult.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';

import 'src/token/tokens.dart';
import '../src/token/tokens.dart';

class WrapResult {
final Text text;
Expand All @@ -9,14 +9,19 @@ class WrapResult {
final double maxWidth;
final Size size;
final List<List<TextPartToken>> tokens;
late final bool isSizeMatching;

WrapResult(this.text, this.style, this.maxWidth, this.size, this.tokens) {
textStr = text.data!;
isSizeMatching = size.width <= maxWidth;
}

toString() {
String ret = '>' + textStr.split('\n').join('<\n>') + '<';
ret += '\n' + tokens.join('\n');
// ret += '\n' + tokens.join('\n');
ret += '\n' + size.toString() + ' vs. max-width: $maxWidth';
ret += '\nfontSize: ${style.fontSize}';
ret += '\nisSizeMatching: $isSizeMatching';
return ret;
}
}
46 changes: 29 additions & 17 deletions lib/widget/texthyphenated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,36 @@ class _TextHyphenatedState extends State<TextHyphenated> {
throw snapshot.error!;
}

return Text(
snapshot.data!.hyphenateText(widget.text),
style: widget.style,
key: widget.textKey,
strutStyle: widget.strutStyle,
textAlign: widget.textAlign,
textDirection: widget.textDirection,
locale: widget.locale,
softWrap: widget.softWrap,
overflow: widget.overflow,
textScaleFactor: widget.textScaleFactor,
maxLines: widget.maxLines,
semanticsLabel: widget.semanticsLabel,
textWidthBasis: widget.textWidthBasis,
textHeightBehavior: widget.textHeightBehavior,
selectionColor: widget.selectionColor,
);
return LayoutBuilder(builder: (ctx, cnt) {
final txt = _makeText(widget.text);
final defaultStyle =
widget.style != null ? widget.style! : TextStyle();
final result =
snapshot.data!.wrap(txt, defaultStyle, cnt.maxWidth).textStr;

return _makeText(result);
});
},
);
}

Text _makeText(String str) {
return Text(
str,
style: widget.style,
key: widget.textKey,
strutStyle: widget.strutStyle,
textAlign: widget.textAlign,
textDirection: widget.textDirection,
locale: widget.locale,
softWrap: widget.softWrap,
overflow: widget.overflow,
textScaleFactor: widget.textScaleFactor,
maxLines: widget.maxLines,
semanticsLabel: widget.semanticsLabel,
textWidthBasis: widget.textWidthBasis,
textHeightBehavior: widget.textHeightBehavior,
selectionColor: widget.selectionColor,
);
}
}
19 changes: 11 additions & 8 deletions test/hyphenator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import 'dart:math' as Math show min, max;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hyphenatorx/hyphenatorx.dart';
import 'package:hyphenatorx/hyphenatorx_flutter.dart';
import 'package:hyphenatorx/languages/language_en_us.dart';
import 'package:hyphenatorx/languages/languageconfig.dart';
import 'package:hyphenatorx/wrapresult.dart';
import 'package:hyphenatorx/token/wrapresult.dart';

final text =
'''The arts are a vast subdivision of culture, composed of many creative endeavors and disciplines. It is a broader term than "art", which as a description of a field usually means only the visual arts. The arts encompass the visual arts, the literary arts and the performing arts – music, theatre, dance and film, among others. This list is by no means comprehensive, but only meant to introduce the concept of the arts. For all intents and purposes, the history of the arts begins with the history of art. The arts might have origins in early human evolutionary prehistory. According to a recent suggestion, several forms of audio and visual arts (rhythmic singing and drumming on external objects, dancing, body and face painting) were developed very early in hominid evolution by the forces of natural selection in order to reach an altered state of consciousness. In this state, which Jordania calls battle trance, hominids and early human were losing their individuality, and were acquiring a new collective identity, where they were not feeling fear or pain, and were religiously dedicated to the group interests, in total disregards of their individual safety and life. This state was needed to defend early hominids from predators, and also to help to obtain food by aggressive scavenging. Ritualistic actions involving heavy rhythmic music, rhythmic drill, coupled sometimes with dance and body painting had been universally used in traditional cultures before the hunting or military sessions in order to put them in a specific altered state of consciousness and raise the morale of participants.''';
Expand Down Expand Up @@ -147,15 +146,19 @@ _ _It_ _is_ _a_ _broader_ _term_ _than_ _"art",_ _which_ _as_ _a_ _de
});

test('linewrapper', () {
final text = Text("""A vast subdivision of culture,
composed of many creative endeavors and disciplines.""");
final style = TextStyle(color: Colors.red);
final maxWidth = 250.0;
final style = TextStyle(fontWeight: FontWeight.normal, fontSize: 14);
// final text = Text("""A vast subdivision of culture,
// composed of many creative endeavors and disciplines.""");
// final maxWidth = 250.0;
final text = Text("""disciplines.""");
final hyphenator = Hyphenator(config);

final hyphenator = HyphenatorWrap(config);
final WrapResult res = hyphenator.wrap(text, style, maxWidth);
// WrapResult res = hyphenator.wrap(text, style, 75.0);
// expect(res.isSizeMatching, false);

WrapResult res = hyphenator.wrap(text, style, 100.0);
print(res);
// expect(res.isSizeMatching, true);
});

test('min letter count', () {
Expand Down

0 comments on commit ccadc86

Please sign in to comment.