From db98dbcb3deae44416a388f6982ca8560d2d3bea Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Fri, 2 Oct 2026 09:18:24 +0100 Subject: [PATCH] test(qa): measure a DOCX fidelity line from its first letter, not from a space before it --- CHANGELOG.md | 6 ++ .../fidelity/DocxFidelityGateTest.java | 28 +++++++ .../document/templates/fidelity/PdfLines.java | 10 ++- .../docx-fidelity/word-windows-lines.tsv | 74 +++++++++---------- .../resources/docx-fidelity/word-windows.tsv | 10 +-- 5 files changed, 85 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01566aaf9..28ddaa4d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1521,6 +1521,12 @@ follow semantic versioning; release dates are ISO 8601. ### Tests +- **The DOCX fidelity corpus measures a line from its first letter.** A space opened a line + (`PdfLines`), and Word writes one for an empty paragraph: drawn just before a line of text + beside it, a few points off its baseline, it gave that line its own. The lines measured past + 2pt in Word fall from 9 to 0 in `SlateOrange`, from 14 to 2 in `VioletGrid` and from 2 to 0 + in `OrangeOps`; the text did not move. LibreOffice's measurement is unchanged. + - **The DOCX fidelity corpus reports which presets are set as the page sets them.** Each run writes `measured--acceptance.md` (`FidelityAcceptance`): a preset passes when the editor sets it on the page's pages, finds 95% of its lines, sets them a median of 1pt or less from diff --git a/qa/src/test/java/com/demcha/compose/document/templates/fidelity/DocxFidelityGateTest.java b/qa/src/test/java/com/demcha/compose/document/templates/fidelity/DocxFidelityGateTest.java index 96acae759..d9a63dc6e 100644 --- a/qa/src/test/java/com/demcha/compose/document/templates/fidelity/DocxFidelityGateTest.java +++ b/qa/src/test/java/com/demcha/compose/document/templates/fidelity/DocxFidelityGateTest.java @@ -194,6 +194,34 @@ void linesOfTheSameLettersArePairedNearestFirst() { assertThat(found.getValue().drift()).isEqualTo(0.5); } + @Test + void aLineStandsWhereItsFirstLetterDoesNotWhereASpaceBeforeItDoes() throws Exception { + // An empty paragraph's space, drawn just before a label 4pt lower beside it. + Path page = Files.createTempFile("first-letter", ".pdf"); + try (org.apache.pdfbox.pdmodel.PDDocument document = new org.apache.pdfbox.pdmodel.PDDocument()) { + org.apache.pdfbox.pdmodel.PDPage sheet = new org.apache.pdfbox.pdmodel.PDPage(); + document.addPage(sheet); + var font = new org.apache.pdfbox.pdmodel.font.PDType1Font( + org.apache.pdfbox.pdmodel.font.Standard14Fonts.FontName.HELVETICA); + try (var content = new org.apache.pdfbox.pdmodel.PDPageContentStream(document, sheet)) { + content.beginText(); + content.setFont(font, 10); + content.newLineAtOffset(50, 700); + content.showText(" "); + content.newLineAtOffset(2, -4); + content.showText("Label"); + content.endText(); + } + document.save(page.toFile()); + } + double height = 792; + + PdfLines.Line line = PdfLines.of(page).lines().get(0); + assertThat(line.key()).isEqualTo("label"); + assertThat(line.baseline()).isCloseTo(height - 696, org.assertj.core.data.Offset.offset(0.01)); + assertThat(line.x()).isCloseTo(52, org.assertj.core.data.Offset.offset(0.01)); + } + @Test void twoColumnsOnOneBaselineAreTwoLines() throws Exception { Path page = pdf("columns", flow -> flow.addRow("Row", row -> row diff --git a/qa/src/test/java/com/demcha/compose/document/templates/fidelity/PdfLines.java b/qa/src/test/java/com/demcha/compose/document/templates/fidelity/PdfLines.java index 3324823b5..d34f25544 100644 --- a/qa/src/test/java/com/demcha/compose/document/templates/fidelity/PdfLines.java +++ b/qa/src/test/java/com/demcha/compose/document/templates/fidelity/PdfLines.java @@ -84,16 +84,24 @@ protected void processTextPosition(TextPosition glyph) { double y = glyph.getYDirAdj(); double left = glyph.getXDirAdj(); double size = Math.max(1, glyph.getFontSizeInPt()); + String letters = glyph.getUnicode(); + // A space opens no line: Word writes one for an empty paragraph, and one drawn just + // before a line of text beside it, on a baseline a few points off, gave that line + // the space's baseline instead of its letters'. + boolean blank = letters == null + || letters.codePoints().allMatch(c -> Character.isWhitespace(c) || Character.isSpaceChar(c)); boolean sameLine = !Double.isNaN(baseline) && Math.abs(y - baseline) < size * 0.5 && left >= lastX - 1 && left - lastEnd < size * 1.5; if (!sameLine) { endLine(); + if (blank) { + return; + } baseline = y; x = left; } - String letters = glyph.getUnicode(); if (letters != null) { letters.codePoints() .filter(c -> !Character.isWhitespace(c) && !Character.isSpaceChar(c)) diff --git a/qa/src/test/resources/docx-fidelity/word-windows-lines.tsv b/qa/src/test/resources/docx-fidelity/word-windows-lines.tsv index 53e9cbaae..e87ab8138 100644 --- a/qa/src/test/resources/docx-fidelity/word-windows-lines.tsv +++ b/qa/src/test/resources/docx-fidelity/word-windows-lines.tsv @@ -1070,8 +1070,8 @@ cv-orange_ops 0:9806038f6123 0.49 •assistedwithkpireportingandperf cv-orange_ops 0:c2ec5b8c794d 0.61 •ensuredcompliancewithcompanypol cv-orange_ops 0:a691a9aab3fc 0.61 keykpisnapshot(recent12months) cv-orange_ops 0:b5f6dbae04bd 0.46 15% -cv-orange_ops 0:e918ea42a538 -6.02 99.2% -cv-orange_ops 0:16906b6f3827 -6.02 98.4% +cv-orange_ops 0:e918ea42a538 0.46 99.2% +cv-orange_ops 0:16906b6f3827 0.46 98.4% cv-orange_ops 0:bd1b16004d22 0.71 productivity cv-orange_ops 0:b11a85b296a9 0.71 inventory cv-orange_ops 0:b1e25044bf23 0.71 on-time @@ -1233,7 +1233,7 @@ cv-serif_headline 0:0a52c5f62d73 0.01 github.com/alexmorgan cv-serif_headline 0:ff00f99bc03c -0.25 softwareengineerwith5+yearsofexp cv-serif_headline 0:7fd0d2d0fde8 -0.27 backendservices.proficientinjava cv-serif_headline 0:81bb94512f0b -0.29 systemdesign,anddeliveringhigh-q -cv-serif_headline 0:53e5e7c5a884 -1.33 experience +cv-serif_headline 0:53e5e7c5a884 0.11 experience cv-serif_headline 0:b37c6a2d5d11 0.07 seniorsoftwareengineer cv-serif_headline 0:e7227bbe0c40 0.14 jan2022–present cv-serif_headline 0:f4e5af202d87 0.12 techsolutionsinc.|newyork,ny @@ -1255,7 +1255,7 @@ cv-serif_headline 0:2198cdea3aba 0.50 devsphere|newyork,ny cv-serif_headline 0:173ed9f7b6b1 0.55 •assistedindevelopingandmaintain cv-serif_headline 0:0a1fbe0c94d9 0.52 •wroteunitandintegrationteststoe cv-serif_headline 0:bd5eec545fa8 0.50 •participatedinagileceremoniesan -cv-serif_headline 0:2577c0f557b2 -0.79 projects +cv-serif_headline 0:2577c0f557b2 0.65 projects cv-serif_headline 0:c03ade0f8985 0.67 e-commerceplatform cv-serif_headline 0:f726495cb8e6 0.64 java,springboot,react,postgresql cv-serif_headline 0:09271909c2c5 0.40 developedafull-stacke-commerce @@ -1393,15 +1393,15 @@ cv-slate_orange 0:88cc29c2fda2 0.56 microsoftoffice&googlesuite cv-slate_orange 0:e37d86244e99 0.57 crmsystems(salesforce,hubspot) cv-slate_orange 0:d70e5edb4685 0.58 timemanagement&prioritization cv-slate_orange 0:8bab53aa1bee 0.04 selectedachievements -cv-slate_orange 0:b08c44dac044 4.50 processimprovement +cv-slate_orange 0:b08c44dac044 0.54 processimprovement cv-slate_orange 0:c7966365f508 1.29 designedanewtrackingsystemthat cv-slate_orange 0:3a5ad5d0dc8d 0.79 reducedreportingtimeby30%and cv-slate_orange 0:74821a85e7b9 0.29 improvedaccuracy. -cv-slate_orange 0:dd9532e202a3 4.52 customersatisfaction +cv-slate_orange 0:dd9532e202a3 0.56 customersatisfaction cv-slate_orange 0:dfc9a4fd0657 1.19 maintaineda96%customer cv-slate_orange 0:5e04b5e4dbf9 0.81 satisfactionratingthroughrespons cv-slate_orange 0:c119f318eaae 0.31 supportandissueresolution. -cv-slate_orange 0:365853229c97 4.54 revenuecontribution +cv-slate_orange 0:365853229c97 0.58 revenuecontribution cv-slate_orange 0:292a456730c2 1.21 consistentlyexceededmonthlysales cv-slate_orange 0:8eb387deb3e1 0.83 goalsby15–20%throughrelationship cv-slate_orange 0:77706bc9ed09 0.33 buildingandconsultativeservice. @@ -1410,8 +1410,8 @@ cv-slate_orange 0:890744623577 0.99 spanishprofessionalworking cv-slate_orange 0:21bb36ad0638 1.15 french cv-slate_orange 0:fbb7b5bf4ca3 1.18 basic cv-slate_orange 0:676dfdd56ad2 0.92 additionalinformation -cv-slate_orange 0:ef68dac1790b 4.15 availability:full-time -cv-slate_orange 0:6795aec0e50a 4.13 willingtorelocate:yes +cv-slate_orange 0:ef68dac1790b 1.39 availability:full-time +cv-slate_orange 0:6795aec0e50a 1.37 willingtorelocate:yes cv-slate_orange 0:b8eeb230ca32 1.48 remotework:opento cv-slate_orange 0:b73078ca247c 1.42 hybrid/remote cv-slate_orange 0:3c69d6bb4892 0.04 professionalprofile @@ -1421,21 +1421,21 @@ cv-slate_orange 0:41221430e3f8 0.09 organizationalskills,andtheabili cv-slate_orange 0:324c4509a3e4 0.06 managingpriorities,buildingrelat cv-slate_orange 0:57271827af78 0.03 customersatisfaction,andbusiness cv-slate_orange 0:c2f296ef30a3 0.21 professionalexperience -cv-slate_orange 0:da2ea6509bec -3.46 operationscoordinator +cv-slate_orange 0:da2ea6509bec 0.74 operationscoordinator cv-slate_orange 0:e7227bbe0c40 0.63 jan2022–present cv-slate_orange 0:9f7cecddf317 0.57 brightstartlogistics,austin,tx cv-slate_orange 0:e0bbd6c9782e 0.62 •coordinatedailyoperationsandsch cv-slate_orange 0:dc9a542f8db9 0.66 •developandmaintaindashboardsand cv-slate_orange 0:66acc2e5b891 0.58 •streamlinecommunicationbetweend cv-slate_orange 0:8bd3fd672f95 0.62 •managevendorrelationshipsandass -cv-slate_orange 0:dd7872236383 -3.58 customersupportspecialist +cv-slate_orange 0:dd7872236383 0.62 customersupportspecialist cv-slate_orange 0:1734c189cfe2 0.63 jun2020–dec2021 cv-slate_orange 0:b9dfc8902d16 0.57 techwavesolutions,remote cv-slate_orange 0:56391e23e83a 0.52 •providedtechnicalsupporttocusto cv-slate_orange 0:7eb50a39cf50 0.56 •resolvedanaverageof40+inquiries cv-slate_orange 0:46f632748ba8 0.60 •createdknowledgebasearticlesand cv-slate_orange 0:02b44f46125c 0.52 •collaboratedwithproductandengin -cv-slate_orange 0:a1707ef6164e -3.68 salesassociate +cv-slate_orange 0:a1707ef6164e 0.64 salesassociate cv-slate_orange 0:2bc613d4e516 0.53 mar2019–may2020 cv-slate_orange 0:bb7253ff7002 0.47 urbanoutfitters,austin,tx cv-slate_orange 0:aaa52372c317 -0.08 •consistentlyexceededsalestarget @@ -1443,7 +1443,7 @@ cv-slate_orange 0:198e638fe8f3 0.13 personalizedcustomerservice. cv-slate_orange 0:dabead95ee7e 0.53 •builtandmaintainedstrongcustome cv-slate_orange 0:ff3f5f9ca7a0 0.45 •merchandisedfloordisplaysandcon cv-slate_orange 0:05a39f2908ba 0.52 •recognizedas“topperformer”forq4 -cv-slate_orange 0:832235539465 -3.68 administrativeassistant/projecta +cv-slate_orange 0:832235539465 0.52 administrativeassistant/projecta cv-slate_orange 0:2ccfc04a3ae7 0.53 may2018–feb2019 cv-slate_orange 0:cfc5fd80ae80 0.47 greenfieldnonprofitinitiative,au cv-slate_orange 0:b8aecb03e7ed 0.40 •supportedprojectmanagerswithsch @@ -1612,10 +1612,10 @@ cv-terracotta_rail 0:bdc5f821f737 -0.42 sustainablemasterplan;achievedhi cv-terracotta_rail 0:208ed62d3df6 -0.70 environmentalstandardsandstrongs cv-terracotta_rail 0:ac5e63220124 -0.98 performance. cv-terracotta_rail 0:68bf0109c6f8 -0.81 education -cv-terracotta_rail 0:1d1dcf789873 -1.87 marcharchitecture +cv-terracotta_rail 0:1d1dcf789873 -0.91 marcharchitecture cv-terracotta_rail 0:00583a6bed38 -0.91 2014–2016 cv-terracotta_rail 0:5761434c99d8 -0.81 universityofsheffield -cv-terracotta_rail 0:e3f2f6a4e375 -1.88 ba(hons)architecture +cv-terracotta_rail 0:e3f2f6a4e375 -0.92 ba(hons)architecture cv-terracotta_rail 0:2920a7fb42fc -0.92 2011–2014 cv-terracotta_rail 0:af625dd0aa20 -0.82 universityofthewestofengland cv-timeline_minimal 0:8f1010120ed6 -0.20 jordanrivera @@ -1742,23 +1742,23 @@ cv-violet_grid 0:5a0774260e0c 0.48 2022-present cv-violet_grid 0:204f460767ff 0.43 seniorux/uidesigner|novafin(fint cv-violet_grid 0:318bba211bdc 0.60 sanfrancisco,ca cv-violet_grid 0:318bba211bdc#1 0.44 sanfrancisco,ca -cv-violet_grid 0:3883e88c63c3 2.43 ledend-to-enddesignforapersonalf -cv-violet_grid 0:ccc00663f089 2.38 conducteduserresearch,builtperso -cv-violet_grid 0:7d0f908c7e5f 2.33 designedwireframes,prototypes,an -cv-violet_grid 0:9b57c4a85aad 2.41 establishedandmaintainedascalabl -cv-violet_grid 0:6894eafb99c2 2.38 collaboratedwithproductmanagers, +cv-violet_grid 0:3883e88c63c3 0.51 ledend-to-enddesignforapersonalf +cv-violet_grid 0:ccc00663f089 0.46 conducteduserresearch,builtperso +cv-violet_grid 0:7d0f908c7e5f 0.41 designedwireframes,prototypes,an +cv-violet_grid 0:9b57c4a85aad 0.49 establishedandmaintainedascalabl +cv-violet_grid 0:6894eafb99c2 0.46 collaboratedwithproductmanagers, cv-violet_grid 0:01e4455cec51 0.44 2020-2022 cv-violet_grid 0:24d722f0cfbe 0.39 uxdesigner|brighthealth(healthte -cv-violet_grid 0:530707fb0897 2.39 redesignedpatientportalexperienc -cv-violet_grid 0:b2e27a1d9270 2.34 plannedandfacilitatedusabilityte -cv-violet_grid 0:ab80a52d70fe 2.29 partneredwithengineerstoensurefe -cv-violet_grid 0:11cbf615189b 2.37 createdreusablecomponentsandstyl +cv-violet_grid 0:530707fb0897 0.47 redesignedpatientportalexperienc +cv-violet_grid 0:b2e27a1d9270 0.42 plannedandfacilitatedusabilityte +cv-violet_grid 0:ab80a52d70fe 0.37 partneredwithengineerstoensurefe +cv-violet_grid 0:11cbf615189b 0.45 createdreusablecomponentsandstyl cv-violet_grid 0:7e5081a3ed48 0.31 2018-2020 cv-violet_grid 0:73f7bbf7cd60 0.26 juniorux/uidesigner|lumendigital cv-violet_grid 0:c6b06045332f 0.43 austin,tx -cv-violet_grid 0:5ea8234925c5 2.26 supporteddiscoveryworkshops,user -cv-violet_grid 0:46f00c76528c 2.33 designedresponsivewebsitesandlan -cv-violet_grid 0:f3cea36a9d83 2.28 collaboratedwithcopywritersandde +cv-violet_grid 0:5ea8234925c5 0.34 supporteddiscoveryworkshops,user +cv-violet_grid 0:46f00c76528c 0.41 designedresponsivewebsitesandlan +cv-violet_grid 0:f3cea36a9d83 0.36 collaboratedwithcopywritersandde cv-violet_grid 0:d94eccbb1fbe 0.31 selectedprojects cv-violet_grid 0:45dc8bf81211 0.35 novafinmobileapp|personalfinance cv-violet_grid 0:d398b29d3dbb 0.43 2023 @@ -3332,16 +3332,16 @@ invoice-subscription 0:2474519f77a9#2 -0.63 unitedkingdom invoice-subscription 0:bfdec553b85a 0.32 billing@halstead.example invoice-subscription 0:78acb3cb907b 0.32 www.halstead.example invoice-subscription 0:f1c030eb4329 0.43 vatnogb418227603 -invoice-subscription 0:77ead61b5875 -0.11 invoiceno +invoice-subscription 0:77ead61b5875 0.37 invoiceno invoice-subscription 0:0b0c0ee24de8 0.34 hs-inv-2026-0417 invoice-subscription 0:0b0c0ee24de8#1 0.56 hs-inv-2026-0417 -invoice-subscription 0:8feaf8016bab -0.04 issuedate +invoice-subscription 0:8feaf8016bab 0.32 issuedate invoice-subscription 0:4d49cb78b810 0.41 27august2026 -invoice-subscription 0:ac10f8c16320 0.03 duedate +invoice-subscription 0:ac10f8c16320 0.39 duedate invoice-subscription 0:b55571aaabac 0.49 10september2026 -invoice-subscription 0:fb854bac39c8 0.11 paymentterms +invoice-subscription 0:fb854bac39c8 0.47 paymentterms invoice-subscription 0:56a2e019b8aa 0.44 14days -invoice-subscription 0:466e5b9cd57f 0.06 currency +invoice-subscription 0:466e5b9cd57f 0.54 currency invoice-subscription 0:54f8e1b3fe44 0.51 gbp invoice-subscription 0:aeba3a7b3598 0.59 billto invoice-subscription 0:7bfc2b791f41 -0.66 northlineconsultingltd @@ -3786,8 +3786,8 @@ proposal-editorial 1:06ebb5670fa8 3.16 ownershipofallfinaldeliverables proposal-editorial 1:c1514c6cdad1 2.62 acceptance proposal-editorial 1:893663b06769 2.26 bysigningbelow,youagreetothescop proposal-editorial 1:df16232de5b9 2.41 acceptedby: -proposal-editorial 1:f089d24d7cf3 4.57 signature: -proposal-editorial 1:c74c9cd82f13 4.57 date: +proposal-editorial 1:f089d24d7cf3 2.41 signature: +proposal-editorial 1:c74c9cd82f13 2.41 date: proposal-editorial 1:026890c58de9 0.12 northlinestudio|northlinestudio. proposal-indigo 0:07f15cde5b18 0.22 kestrel proposal-indigo 0:ecd1378bc9dc 0.18 proposal @@ -4165,7 +4165,7 @@ rota-cobalt 0:e594a1e64b7d 0.52 l22/d48 rota-cobalt 0:7062fafe1dab 0.52 l65/d112 rota-cobalt 0:778cb57b62fa 0.52 l73/d112 rota-cobalt 0:1b4471920f01 0.52 l72/d83 -rota-cobalt 0:288965a1f2c8 -0.17 management +rota-cobalt 0:288965a1f2c8 0.31 management rota-cobalt 0:6a61eb7383e8 0.42 rosa rota-cobalt 0:3bb0f0bb5552 0.53 09:00-18:00 rota-cobalt 0:3bb0f0bb5552#1 0.68 09:00-18:00 @@ -4210,7 +4210,7 @@ rota-cobalt 0:6d43df86fe4b#11 1.60 16:00-00:00 rota-cobalt 0:6d43df86fe4b#12 1.60 16:00-00:00 rota-cobalt 0:6d43df86fe4b#13 0.97 16:00-00:00 rota-cobalt 0:5a5f719aae11 -0.02 11:00-16:00 -rota-cobalt 0:df9ba122242c 0.01 bartenders +rota-cobalt 0:df9ba122242c 0.49 bartenders rota-cobalt 0:dbaf86dd80e3 0.58 nadia rota-cobalt 0:0cdd9d9e75dc -0.12 09:00-16:00 rota-cobalt 0:0cdd9d9e75dc#1 0.14 09:00-16:00 @@ -4240,7 +4240,7 @@ rota-cobalt 0:86846e84f9bf 1.13 sofia rota-cobalt 0:effcc54ba75f 1.14 karol rota-cobalt 0:5c1e134d2d34 1.28 henrik rota-cobalt 0:6326e0e8cfda 1.42 lucia -rota-cobalt 0:c235e502637c 0.87 barbacks +rota-cobalt 0:c235e502637c 1.35 barbacks rota-cobalt 0:bd558de5f794 1.35 oskar rota-cobalt 0:4941d6993ee9 1.36 teodor rota-cobalt 0:1d3d3d6a07bd 1.62 vesna diff --git a/qa/src/test/resources/docx-fidelity/word-windows.tsv b/qa/src/test/resources/docx-fidelity/word-windows.tsv index 5971c4d59..cae92ba64 100644 --- a/qa/src/test/resources/docx-fidelity/word-windows.tsv +++ b/qa/src/test/resources/docx-fidelity/word-windows.tsv @@ -16,16 +16,16 @@ cv-modern_professional 2 2 61 59 0.20 0.77 5 cv-monogram_sidebar 1 1 53 50 0.79 2.95 17 cv-navy_sidebar 1 1 71 69 0.13 0.22 0 cv-nordic_clean 1 1 63 58 0.22 0.61 0 -cv-orange_ops 1 1 108 99 0.42 0.71 2 +cv-orange_ops 1 1 108 99 0.42 0.71 0 cv-panel 1 1 79 73 0.43 0.94 0 cv-professional_sidebar 1 1 68 64 0.11 0.27 0 -cv-serif_headline 1 1 103 103 0.51 1.05 0 +cv-serif_headline 1 1 103 103 0.50 1.03 0 cv-sidebar_portrait 1 1 49 49 0.08 0.27 0 -cv-slate_orange 1 1 87 85 0.54 3.46 9 +cv-slate_orange 1 1 87 85 0.53 1.18 0 cv-teal_pulse 1 1 57 57 0.11 0.38 0 cv-terracotta_rail 1 1 102 102 0.42 0.87 0 cv-timeline_minimal 2 2 89 86 1.44 1.57 0 -cv-violet_grid 1 1 80 77 0.35 2.34 14 +cv-violet_grid 1 1 80 77 0.35 0.81 2 invoice-classic 1 1 56 56 0.48 1.22 0 invoice-classic_long 2 2 166 166 0.51 0.88 0 invoice-consulting 1 1 92 92 1.10 1.65 3 @@ -39,7 +39,7 @@ invoice-modern_long 2 2 162 162 0.44 0.60 0 invoice-obsidian 1 1 81 81 0.26 0.62 0 invoice-payments 1 1 104 100 0.50 1.10 2 invoice-platform 1 1 111 111 0.19 0.41 0 -invoice-subscription 1 1 81 81 0.45 0.64 0 +invoice-subscription 1 1 81 81 0.47 0.64 0 invoice-workspace 1 1 90 90 0.44 1.26 0 letter-blue_banner 1 1 10 10 0.39 0.50 0 letter-boxed_sections 1 1 10 10 0.55 0.63 0