@@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
33import 'package:flutter/foundation.dart' ;
44import 'package:flutter/material.dart' ;
55import 'package:flutter/rendering.dart' ;
6+ import 'package:flutter/services.dart' ;
67import 'package:flutter_checks/flutter_checks.dart' ;
78import 'package:flutter_test/flutter_test.dart' ;
89import 'package:url_launcher/url_launcher.dart' ;
@@ -572,98 +573,65 @@ void main() {
572573 tester.widget (find.text ('λ' , findRichText: true ));
573574 });
574575
575- void checkKatexText (
576- WidgetTester tester,
577- String text, {
578- required String fontFamily,
579- required double fontSize,
580- required double fontHeight,
581- }) {
582- check (mergedStyleOf (tester, text)).isNotNull ()
583- ..fontFamily.equals (fontFamily)
584- ..fontSize.equals (fontSize);
585- check (tester.getSize (find.text (text)))
586- .height.isCloseTo (fontSize * fontHeight, 0.5 );
587- }
588-
589- testWidgets ('displays KaTeX content with different sizing' , (tester) async {
590- addTearDown (testBinding.reset);
591- final globalSettings = testBinding.globalStore.settings;
592- await globalSettings.setBool (BoolGlobalSetting .renderKatex, true );
593- check (globalSettings).getBool (BoolGlobalSetting .renderKatex).isTrue ();
594-
595- final content = ContentExample .mathBlockKatexSizing;
596- await prepareContent (tester, plainContent (content.html));
597-
598- final mathBlockNode = content.expectedNodes.single as MathBlockNode ;
599- final baseNode = mathBlockNode.nodes! .single as KatexSpanNode ;
600- final nodes = baseNode.nodes! .skip (1 ); // Skip .strut node.
601- for (var katexNode in nodes) {
602- katexNode = katexNode as KatexSpanNode ;
603- final fontSize = katexNode.styles.fontSizeEm! * kBaseKatexTextStyle.fontSize! ;
604- checkKatexText (tester, katexNode.text! ,
605- fontFamily: 'KaTeX_Main' ,
606- fontSize: fontSize,
607- fontHeight: kBaseKatexTextStyle.height! );
576+ group ('characters render at specific offsets with specific size' , () {
577+ const testCases = < (ContentExample , List <(String , Offset , Size )>, {bool ? skip})> [
578+ (ContentExample .mathBlockKatexSizing, skip: false , [
579+ ('1' , Offset (0.00 , 2.24 ), Size (25.59 , 61.00 )),
580+ ('2' , Offset (25.59 , 9.90 ), Size (21.33 , 51.00 )),
581+ ('3' , Offset (46.91 , 16.30 ), Size (17.77 , 43.00 )),
582+ ('4' , Offset (64.68 , 21.63 ), Size (14.80 , 36.00 )),
583+ ('5' , Offset (79.48 , 26.07 ), Size (12.34 , 30.00 )),
584+ ('6' , Offset (91.82 , 29.77 ), Size (10.28 , 25.00 )),
585+ ('7' , Offset (102.10 , 31.62 ), Size (9.25 , 22.00 )),
586+ ('8' , Offset (111.35 , 33.47 ), Size (8.23 , 20.00 )),
587+ ('9' , Offset (119.58 , 35.32 ), Size (7.20 , 17.00 )),
588+ ('0' , Offset (126.77 , 39.02 ), Size (5.14 , 12.00 )),
589+ ]),
590+ (ContentExample .mathBlockKatexNestedSizing, skip: false , [
591+ ('1' , Offset (0.00 , 39.58 ), Size (5.14 , 12.00 )),
592+ ('2' , Offset (5.14 , 2.80 ), Size (25.59 , 61.00 )),
593+ ]),
594+ // TODO: Re-enable this test after adding support for parsing
595+ // `vertical-align` in inline styles. Currently it fails
596+ // because `strut` span has `vertical-align`.
597+ (ContentExample .mathBlockKatexDelimSizing, skip: true , [
598+ ('(' , Offset (8.00 , 46.36 ), Size (9.42 , 25.00 )),
599+ ('[' , Offset (17.42 , 48.36 ), Size (9.71 , 25.00 )),
600+ ('⌈' , Offset (27.12 , 49.36 ), Size (11.99 , 25.00 )),
601+ ('⌊' , Offset (39.11 , 49.36 ), Size (13.14 , 25.00 )),
602+ ]),
603+ ];
604+
605+ for (final testCase in testCases) {
606+ testWidgets (testCase.$1.description, (tester) async {
607+ await _loadKatexFonts ();
608+
609+ addTearDown (testBinding.reset);
610+ final globalSettings = testBinding.globalStore.settings;
611+ await globalSettings.setBool (BoolGlobalSetting .renderKatex, true );
612+ check (globalSettings).getBool (BoolGlobalSetting .renderKatex).isTrue ();
613+
614+ await prepareContent (tester, plainContent (testCase.$1.html));
615+
616+ final baseRect = tester.getRect (find.byType (KatexWidget ));
617+
618+ for (final characterData in testCase.$2) {
619+ final character = characterData.$1;
620+ final expectedTopLeftOffset = characterData.$2;
621+ final expectedSize = characterData.$3;
622+
623+ final rect = tester.getRect (find.text (character));
624+ final topLeftOffset = rect.topLeft - baseRect.topLeft;
625+ final size = rect.size;
626+
627+ check (topLeftOffset)
628+ .within (distance: 0.05 , from: expectedTopLeftOffset);
629+ check (size)
630+ .within (distance: 0.05 , from: expectedSize);
631+ }
632+ }, skip: testCase.skip);
608633 }
609634 });
610-
611- testWidgets ('displays KaTeX content with nested sizing' , (tester) async {
612- addTearDown (testBinding.reset);
613- final globalSettings = testBinding.globalStore.settings;
614- await globalSettings.setBool (BoolGlobalSetting .renderKatex, true );
615- check (globalSettings).getBool (BoolGlobalSetting .renderKatex).isTrue ();
616-
617- final content = ContentExample .mathBlockKatexNestedSizing;
618- await prepareContent (tester, plainContent (content.html));
619-
620- var fontSize = 0.5 * kBaseKatexTextStyle.fontSize! ;
621- checkKatexText (tester, '1' ,
622- fontFamily: 'KaTeX_Main' ,
623- fontSize: fontSize,
624- fontHeight: kBaseKatexTextStyle.height! );
625-
626- fontSize = 4.976 * fontSize;
627- checkKatexText (tester, '2' ,
628- fontFamily: 'KaTeX_Main' ,
629- fontSize: fontSize,
630- fontHeight: kBaseKatexTextStyle.height! );
631- });
632-
633- testWidgets ('displays KaTeX content with different delimiter sizing' , (tester) async {
634- addTearDown (testBinding.reset);
635- final globalSettings = testBinding.globalStore.settings;
636- await globalSettings.setBool (BoolGlobalSetting .renderKatex, true );
637- check (globalSettings).getBool (BoolGlobalSetting .renderKatex).isTrue ();
638-
639- final content = ContentExample .mathBlockKatexDelimSizing;
640- await prepareContent (tester, plainContent (content.html));
641-
642- final mathBlockNode = content.expectedNodes.single as MathBlockNode ;
643- final baseNode = mathBlockNode.nodes! .single as KatexSpanNode ;
644- var nodes = baseNode.nodes! .skip (1 ); // Skip .strut node.
645-
646- final fontSize = kBaseKatexTextStyle.fontSize! ;
647-
648- final firstNode = nodes.first as KatexSpanNode ;
649- checkKatexText (tester, firstNode.text! ,
650- fontFamily: 'KaTeX_Main' ,
651- fontSize: fontSize,
652- fontHeight: kBaseKatexTextStyle.height! );
653- nodes = nodes.skip (1 );
654-
655- for (var katexNode in nodes) {
656- katexNode = katexNode as KatexSpanNode ;
657- katexNode = katexNode.nodes! .single as KatexSpanNode ; // Skip empty .mord parent.
658- final fontFamily = katexNode.styles.fontFamily! ;
659- checkKatexText (tester, katexNode.text! ,
660- fontFamily: fontFamily,
661- fontSize: fontSize,
662- fontHeight: kBaseKatexTextStyle.height! );
663- }
664- }, skip: true ); // TODO: Re-enable this test after adding support for parsing
665- // `vertical-align` in inline styles. Currently it fails
666- // because `strut` span has `vertical-align`.
667635 });
668636
669637 /// Make a [TargetFontSizeFinder] to pass to [checkFontSizeRatio] ,
@@ -1432,3 +1400,45 @@ void main() {
14321400 });
14331401 });
14341402}
1403+
1404+ Future <void > _loadKatexFonts () async {
1405+ const fonts = {
1406+ 'KaTeX_AMS' : ['KaTeX_AMS-Regular.ttf' ],
1407+ 'KaTeX_Caligraphic' : [
1408+ 'KaTeX_Caligraphic-Regular.ttf' ,
1409+ 'KaTeX_Caligraphic-Bold.ttf' ,
1410+ ],
1411+ 'KaTeX_Fraktur' : [
1412+ 'KaTeX_Fraktur-Regular.ttf' ,
1413+ 'KaTeX_Fraktur-Bold.ttf' ,
1414+ ],
1415+ 'KaTeX_Main' : [
1416+ 'KaTeX_Main-Regular.ttf' ,
1417+ 'KaTeX_Main-Bold.ttf' ,
1418+ 'KaTeX_Main-Italic.ttf' ,
1419+ 'KaTeX_Main-BoldItalic.ttf' ,
1420+ ],
1421+ 'KaTeX_Math' : [
1422+ 'KaTeX_Math-Italic.ttf' ,
1423+ 'KaTeX_Math-BoldItalic.ttf' ,
1424+ ],
1425+ 'KaTeX_SansSerif' : [
1426+ 'KaTeX_SansSerif-Regular.ttf' ,
1427+ 'KaTeX_SansSerif-Bold.ttf' ,
1428+ 'KaTeX_SansSerif-Italic.ttf' ,
1429+ ],
1430+ 'KaTeX_Script' : ['KaTeX_Script-Regular.ttf' ],
1431+ 'KaTeX_Size1' : ['KaTeX_Size1-Regular.ttf' ],
1432+ 'KaTeX_Size2' : ['KaTeX_Size2-Regular.ttf' ],
1433+ 'KaTeX_Size3' : ['KaTeX_Size3-Regular.ttf' ],
1434+ 'KaTeX_Size4' : ['KaTeX_Size4-Regular.ttf' ],
1435+ 'KaTeX_Typewriter' : ['KaTeX_Typewriter-Regular.ttf' ],
1436+ };
1437+ for (final MapEntry (key: fontFamily, value: fontFiles) in fonts.entries) {
1438+ final fontLoader = FontLoader (fontFamily);
1439+ for (final fontFile in fontFiles) {
1440+ fontLoader.addFont (rootBundle.load ('assets/KaTeX/$fontFile ' ));
1441+ }
1442+ await fontLoader.load ();
1443+ }
1444+ }
0 commit comments