Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-<editor>-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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
74 changes: 37 additions & 37 deletions qa/src/test/resources/docx-fidelity/word-windows-lines.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -1421,29 +1421,29 @@ 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
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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions qa/src/test/resources/docx-fidelity/word-windows.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading