Skip to content

Commit

Permalink
Base "breakable" info in CrossReferenceHandler on BlockLineLocation
Browse files Browse the repository at this point in the history
Without this change it is possible that we end up in an endless
alternation between two volume renderings. (In other words,
brailleapps/dotify.formatter.impl#70 was not
completely fixed yet.)

I proposed this change in
brailleapps/dotify.formatter.impl#97 already
but we did not include it at the time.
  • Loading branch information
bertfrees committed May 6, 2021
1 parent de0cc4b commit 5f229ed
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 66 deletions.
24 changes: 12 additions & 12 deletions src/org/daisy/dotify/formatter/impl/page/PageSequenceBuilder2.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,8 @@ public class PageSequenceBuilder2 {
private int dataGroupsIndex;
private boolean nextEmpty = false;

// BlockLineLocation of the last line of the previous page
// (produced by this PageSequenceBuilder2 or the previous one)
private BlockLineLocation cbl;
// BlockLineLocation of the last line of the page before the previous page,
// or null if no page has been produced yet
private BlockLineLocation pcbl;
private BlockLineLocation prevCbl; // previous value of cbl

//From view, temporary
private final int fromIndex;
Expand All @@ -120,7 +116,8 @@ public class PageSequenceBuilder2 {
* @param context ?
* @param rcontext ?
* @param seqId identifier/position of the block sequence
* @param blc The {@link BlockLineLocation} of the last line of the previous PageSequenceBuilder2.
* @param blc The {@link BlockLineLocation} of the last line of the previous PageSequenceBuilder2, or
* null if there is no previous PageSequenceBuilder2.
*/
public PageSequenceBuilder2(
int fromIndex,
Expand Down Expand Up @@ -161,7 +158,7 @@ public PageSequenceBuilder2(
this.dataGroupsIndex = 0;
this.seqId = seqId;
this.cbl = blc;
this.pcbl = null;
this.prevCbl = null;
PageDetails details = new PageDetails(
master.duplex(),
new PageId(pageCount, getGlobalStartIndex(), seqId),
Expand Down Expand Up @@ -192,7 +189,7 @@ public PageSequenceBuilder2(PageSequenceBuilder2 template) {
this.fromIndex = template.fromIndex;
this.toIndex = template.toIndex;
this.cbl = template.cbl;
this.pcbl = template.pcbl;
this.prevCbl = template.prevCbl;
}

public static PageSequenceBuilder2 copyUnlessNull(PageSequenceBuilder2 template) {
Expand All @@ -216,6 +213,10 @@ public PageId nextPageId(int offset) {
return new PageId(pageCount + offset, getGlobalStartIndex(), seqId);
}

/**
* @return The BlockLineLocation of the last line of the page that was produced last (by this
* PageSequenceBuilder2 or the previous one), or null if no page has been produced yet.
*/
public BlockLineLocation currentBlockLineLocation() {
return cbl;
}
Expand Down Expand Up @@ -301,16 +302,15 @@ private PageImpl nextPageInner(
// PageStructBuilder.paginateInner
PageImpl current = newPage(pageNumberOffset);
if (
pcbl != null &&
prevCbl != null &&
// Store a mapping from the BlockLineLocation of the last line of the page before the
// previous page to the BlockLineLocation of the last line of the previous page. This
// info is used (in the next iteration) in SheetDataSource to obtain info about the
// verso page of a sheet when we are on a recto page of that sheet.
transitionContent.isPresent() &&
transitionContent.get().getType() == TransitionContent.Type.INTERRUPT
) {

blockContext.getRefs().setNextPageDetailsInSequence(pcbl, current.getDetails());
blockContext.getRefs().setNextPageDetailsInSequence(prevCbl, current.getDetails());
}
if (nextEmpty) {
nextEmpty = false;
Expand Down Expand Up @@ -565,7 +565,7 @@ private PageImpl nextPageInner(
if (!head.isEmpty()) {
int s = head.size();
RowGroup gr = head.get(s - 1);
pcbl = cbl;
prevCbl = cbl;
cbl = gr.getLineProperties().getBlockLineLocation();
}
// Add the body rows to the page.
Expand Down
55 changes: 34 additions & 21 deletions src/org/daisy/dotify/formatter/impl/search/SheetIdentity.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
package org.daisy.dotify.formatter.impl.search;

/**
* TODO: Write java doc.
* Sheet starting at a specific location within a block.
*/
public class SheetIdentity {
private final Space space;
private final Integer volumeIndex;
private final Integer volumeGroup;
private final int sheetIndex;
private final BlockLineLocation blockLineLocation;

public SheetIdentity(Space s, Integer volumeIndex, Integer volumeGroup, int sheetIndex) {
this.space = s;
/**
* Create a SheetIdentity from a BlockLineLocation. The BlockLineLocation points to the last
* line of the preceding sheet within the current volume group or pre-/post-content
* section. Additional arguments are needed to uniquely identify the sheet when it is the first
* of the current volume group or pre-/post-content section.
*
* @param blockLineLocation location of the last line of the preceding sheet within the current
* volume group or pre-/post-content section, or null if there is no
* preceding sheet.
* @param space the space ({@link Space#BODY}, {@link Space#PRE_CONTENT} or {@link
* Space#POST_CONTENT}).
* @param volumeIndex the volume index if <code>space</code> is {@link Space#PRE_CONTENT}
* or {@link Space#POST_CONTENT}.
* @param volumeGroup the volume group index if <code>space</code> is
* {@link Space#BODY}.
*/
public SheetIdentity(
BlockLineLocation blockLineLocation,
Space space,
Integer volumeIndex,
Integer volumeGroup
) {
this.space = space;
if (space == Space.BODY) {
if (volumeIndex != null) {
volumeIndex = null;
Expand All @@ -25,27 +46,15 @@ public SheetIdentity(Space s, Integer volumeIndex, Integer volumeGroup, int shee
}
this.volumeIndex = volumeIndex;
this.volumeGroup = volumeGroup;
this.sheetIndex = sheetIndex;
}

public Space getSpace() {
return space;
}

public Integer getVolumeIndex() {
return volumeIndex;
}

public int getSheetIndex() {
return sheetIndex;
this.blockLineLocation = blockLineLocation;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((space == null) ? 0 : space.hashCode());
result = prime * result + sheetIndex;
result = prime * result + (space == null ? 0 : space.hashCode());
result = prime * result + (blockLineLocation == null ? 0 : blockLineLocation.hashCode());
result = prime * result + (volumeIndex == null ? 0 : volumeIndex);
result = prime * result + (volumeGroup == null ? 0 : volumeGroup);
return result;
Expand All @@ -66,7 +75,11 @@ public boolean equals(Object obj) {
if (space != other.space) {
return false;
}
if (sheetIndex != other.sheetIndex) {
if (blockLineLocation == null) {
if (other.blockLineLocation != null) {
return false;
}
} else if (!blockLineLocation.equals(other.blockLineLocation)) {
return false;
}
if (volumeIndex == null) {
Expand All @@ -91,7 +104,7 @@ public String toString() {
return "SheetIdentity [space=" + space
+ (volumeIndex == null ? "" : ", volumeIndex=" + volumeIndex)
+ (volumeGroup == null ? "" : ", volumeGroup=" + volumeGroup)
+ ", sheetIndex=" + sheetIndex + "]";
+ ", blockLineLocation=" + blockLineLocation + "]";
}

}
64 changes: 31 additions & 33 deletions src/org/daisy/dotify/formatter/impl/sheet/SheetDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.daisy.dotify.formatter.impl.page.PageImpl;
import org.daisy.dotify.formatter.impl.page.PageSequenceBuilder2;
import org.daisy.dotify.formatter.impl.page.RestartPaginationException;
import org.daisy.dotify.formatter.impl.search.BlockAddress;
import org.daisy.dotify.formatter.impl.search.BlockLineLocation;
import org.daisy.dotify.formatter.impl.search.DefaultContext;
import org.daisy.dotify.formatter.impl.search.DocumentSpace;
Expand All @@ -24,6 +23,7 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

Expand Down Expand Up @@ -54,14 +54,14 @@ public class SheetDataSource implements SplitPointDataSource<Sheet, SheetDataSou
private DefaultContext rcontext;
private final Integer volumeGroup;
private final List<BlockSequence> seqsIterator;
private final int sheetOffset;
//Local state
private int seqsIndex;
private SequenceId seqId;
private PageSequenceBuilder2 psb;
private int psbCurStartIndex; // index of first page of current psb in current volume
private SectionProperties sectionProperties;
private int sheetIndex;
private int sheetIndex; // sheets created from current sequence or being created
private LinkedList<SheetIdentity> previousSheets; // all sheets created from the current sequence
private int pageIndex;
private String counter;
private int initialPageOffset;
Expand All @@ -71,8 +71,7 @@ public class SheetDataSource implements SplitPointDataSource<Sheet, SheetDataSou
private boolean isFirst;
private boolean wasSplitInsideSequence;
private boolean volumeEnded;
//Output buffer
private List<Sheet> sheetBuffer;
private List<Sheet> sheetBuffer; // output buffer

public SheetDataSource(
PageCounter pageCounter,
Expand All @@ -88,13 +87,13 @@ public SheetDataSource(
this.seqsIterator = seqsIterator;
this.sheetBuffer = new ArrayList<>();
this.volBreakAllowed = true;
this.sheetOffset = 0;
this.seqsIndex = 0;
this.seqId = null;
this.psb = null;
this.psbCurStartIndex = 0;
this.sectionProperties = null;
this.sheetIndex = 0;
this.previousSheets = new LinkedList<>();
this.pageIndex = 0;
this.counter = null;
this.initialPageOffset = 0;
Expand Down Expand Up @@ -130,9 +129,9 @@ private SheetDataSource(SheetDataSource template, int offset, boolean tail) {
this.psb = tail ? template.psb : PageSequenceBuilder2.copyUnlessNull(template.psb);
this.psbCurStartIndex = template.psbCurStartIndex;
this.sectionProperties = template.sectionProperties;
this.sheetOffset = template.sheetOffset + offset;
this.sheetIndex = template.sheetIndex;
this.pageIndex = template.pageIndex;
this.previousSheets = new LinkedList<>(template.previousSheets);
if (template.sheetBuffer.size() > offset) {
this.sheetBuffer = new ArrayList<>(template.sheetBuffer.subList(offset, template.sheetBuffer.size()));
} else {
Expand Down Expand Up @@ -202,8 +201,8 @@ public void setCurrentVolumeNumber(int volume) {
* @return returns true if the index element was available, false otherwise
*/
private boolean ensureBuffer(int index) {
Sheet.Builder s = null;
SheetIdentity si = null;
Sheet.Builder s = null; // sheet currently being built
SheetIdentity si = null; // sheet currently being built
while (index < 0 || sheetBuffer.size() < index) {
// this happens when a new volume is started
if (updateCounter) {
Expand All @@ -221,6 +220,7 @@ private boolean ensureBuffer(int index) {
if (s != null) {
//Last page in the sequence doesn't need volume keep priority
sheetBuffer.add(s.build());
previousSheets.push(si);
s = null;
continue;
}
Expand All @@ -246,9 +246,6 @@ private boolean ensureBuffer(int index) {
new DocumentSpace(rcontext.getSpace(), rcontext.getCurrentVolume()),
volumeGroup
);
BlockLineLocation cbl = psb != null ?
psb.currentBlockLineLocation() :
new BlockLineLocation(new BlockAddress(-1, -1), -1);
psbCurStartIndex = pageCounter.getPageCount();
psb = new PageSequenceBuilder2(
psbCurStartIndex,
Expand All @@ -258,20 +255,23 @@ private boolean ensureBuffer(int index) {
context,
rcontext,
seqId,
cbl
psb != null ? psb.currentBlockLineLocation() : null
);
sectionProperties = bs.getLayoutMaster().newSectionProperties();
s = null;
si = null;
sheetIndex = 0;
pageIndex = 0;
if (!previousSheets.isEmpty()) {
previousSheets = new LinkedList<>();
}
}
int currentSize = sheetBuffer.size();
while (psb.hasNext() && currentSize == sheetBuffer.size()) {
if (!sectionProperties.duplex() || pageIndex % 2 == 0 || volumeEnded || s == null) {
if (s != null) {
Sheet r = s.build();
sheetBuffer.add(r);
sheetBuffer.add(s.build());
previousSheets.push(si);
s = null;
if (volumeEnded) {
pageIndex += pageIndex % 2 == 1 ? 1 : 0;
Expand All @@ -283,10 +283,10 @@ private boolean ensureBuffer(int index) {
volBreakAllowed = true;
s = new Sheet.Builder(sectionProperties);
si = new SheetIdentity(
rcontext.getSpace(),
rcontext.getCurrentVolume(),
volumeGroup,
sheetBuffer.size() + sheetOffset
psb.currentBlockLineLocation(),
rcontext.getSpace(),
rcontext.getCurrentVolume(),
volumeGroup
);
sheetIndex++;
}
Expand All @@ -303,7 +303,9 @@ private boolean ensureBuffer(int index) {
// This id is the same id as the one created below in the call to nextPage
BlockLineLocation thisPageId = psb.currentBlockLineLocation();
// This gets the page details for the next page in this sequence (if any)
Optional<PageDetails> next = rcontext.getRefs().getNextPageDetailsInSequence(thisPageId);
Optional<PageDetails> next = thisPageId != null
? rcontext.getRefs().getNextPageDetailsInSequence(thisPageId)
: Optional.empty();
// If there is a page details in this sequence and volume break is preferred on this page
if (next.isPresent()) {
Optional<TransitionProperties> st1 = rcontext.getRefs().getTransitionProperties(
Expand Down Expand Up @@ -379,12 +381,7 @@ private boolean ensureBuffer(int index) {
}
s.breakable(br);
}

setPreviousSheet(
si.getSheetIndex() - 1,
Math.min(p.keepPreviousSheets(), sheetIndex - 1),
rcontext
);
keepWithPreviousSheets(previousSheets, p.keepPreviousSheets(), rcontext);
volBreakAllowed &= p.allowsVolumeBreak();
if (!sectionProperties.duplex() || pageIndex % 2 == 1 || volumeEnded) {
rcontext.getRefs().keepBreakable(si, volBreakAllowed);
Expand Down Expand Up @@ -420,13 +417,14 @@ private boolean ensureBuffer(int index) {
return true;
}

private void setPreviousSheet(int start, int p, DefaultContext rcontext) {
int i = 0;
//TODO: simplify this?
for (int x = start; i < p && x > 0; x--) {
SheetIdentity si = new SheetIdentity(rcontext.getSpace(), rcontext.getCurrentVolume(), volumeGroup, x);
rcontext.getRefs().keepBreakable(si, false);
i++;
private static void keepWithPreviousSheets(List<SheetIdentity> previousSheets, int n, DefaultContext rcontext) {
for (SheetIdentity s : previousSheets) {
if (n > 0) {
rcontext.getRefs().keepBreakable(s, false);
n--;
} else {
break;
}
}
}

Expand Down

0 comments on commit 5f229ed

Please sign in to comment.