feat: para balance improvements
This commit is contained in:
parent
c5dfb15133
commit
79f8164650
2 changed files with 225 additions and 63 deletions
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
|
||||
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Archive" script:language="StarBasic" script:moduleType="normal">Sub archMark20
|
||||
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Archive" script:language="StarBasic" script:moduleType="normal">Sub archMark21
|
||||
|
||||
End Sub
|
||||
|
||||
|
@ -441,10 +441,27 @@ Sub stretchPrevPage()
|
|||
oViewCursor.goToRange(oSavePosition,false)
|
||||
End Sub
|
||||
|
||||
Sub adjustLastLineCurPara()
|
||||
Dim oViewCursor As Object
|
||||
Dim oTextCursor As Object
|
||||
Dim paraEnd As Object
|
||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||
oTextCursor = oViewCursor.Text.CreateTextCursorByRange(oViewCursor)
|
||||
paraEnd = getParaEnd(oTextCursor)
|
||||
oTextCursor.goToRange(paraEnd,false)
|
||||
oTextCursor.goLeft(1,true)
|
||||
If (oTextCursor.String = " ") Then
|
||||
oTextCursor.String = ""
|
||||
EndIf
|
||||
oTextCursor.ParaIsHyphenation = true
|
||||
adjustLastLine(oTextCursor.Start)
|
||||
End Sub
|
||||
|
||||
|
||||
|
||||
Sub adjustLastLine(anchor As Object)
|
||||
anchor.ParaAdjust = 2
|
||||
'anchor.ParaLastLineAdjust = 2
|
||||
anchor.ParaLastLineAdjust = 2
|
||||
balancePara(anchor)
|
||||
End Sub
|
||||
|
||||
|
@ -478,77 +495,221 @@ Sub balancePara(targetPara As Object)
|
|||
Dim lineCount As Integer
|
||||
Dim initialLineCount As Integer
|
||||
Dim lineLen As Integer
|
||||
Dim mathExpect As Integer
|
||||
Dim minLastLineLength As Integer
|
||||
paraLen = 0
|
||||
lineLen = 0
|
||||
minLastLineLength = 0
|
||||
initialLineCount = 0
|
||||
Dim medianLen As Integer
|
||||
Dim paraLines() As Object
|
||||
Dim decreaseKerningFailed As Boolean
|
||||
Dim increaseKerningFailed As Boolean
|
||||
Dim fallBackSuccess As Boolean
|
||||
fallBackSuccess = false
|
||||
decreaseKerningFailed = false
|
||||
increaseKerningFailed = false
|
||||
|
||||
|
||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||
oViewCursor.goToRange(targetPara, false)
|
||||
|
||||
oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
oPara = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
'Go to start of para
|
||||
oTextCursor.gotoStartOfParagraph(false)
|
||||
'Get start position
|
||||
oParaStart = oTextCursor.getStart()
|
||||
'Go to end of para
|
||||
oTextCursor.gotoEndOfParagraph(false)
|
||||
'Get end position
|
||||
oParaEnd = oTextCursor.getEnd()
|
||||
'return Text cursor to start
|
||||
oTextCursor.goToRange(oParaStart,false)
|
||||
'oPara is full para cursor
|
||||
oPara.goToRange(oParaStart,false)
|
||||
oPara.goToRange(oParaEnd,true)
|
||||
|
||||
Do
|
||||
'Not first iteration
|
||||
If minLastLineLength <> 0 Then
|
||||
If oPara.CharKerning < 50 Then
|
||||
If(IsEmpty(oPara.CharKerning)) Then
|
||||
oPara.CharKerning = 0
|
||||
Else
|
||||
oPara.CharKerning = oPara.CharKerning + 2
|
||||
End If
|
||||
Else
|
||||
'Failed to balance para
|
||||
oParaStart = getParaStart(oTextCursor)
|
||||
oParaEnd = getParaEnd(oTextCursor)
|
||||
oPara = getParaSelected(oParaStart,oParaEnd)
|
||||
paraLen = Len(oPara.String)
|
||||
paraLines = getParaLines(oPara)
|
||||
initialLineCount = getParaLinesCount(paraLines)
|
||||
lineLen = getParaLineLength(paraLines, 0)
|
||||
medianLen = calculateMedianParaLen(oPara)
|
||||
minLastLineLength = medianLen * 0.89
|
||||
|
||||
If Not IsEmpty(oPara.CharKerning) Then
|
||||
initialCharKerning = oPara.CharKerning
|
||||
Else
|
||||
initialCharKerning = 0
|
||||
End If
|
||||
|
||||
If initialLineCount < 2 Then
|
||||
Exit sub
|
||||
EndIf
|
||||
|
||||
Do While lastLineIsNotBalanced(lineLen, minLastLineLength) And Not (decreaseKerningFailed And increaseKerningFailed)
|
||||
If NOT decreaseKerningFailed Then
|
||||
decreaseCharKerning(oPara)
|
||||
EndIf
|
||||
If decreaseKerningFailed AND NOT increaseKerningFailed Then
|
||||
increaseCharKerning(oPara)
|
||||
EndIf
|
||||
paraLines = getParaLines(oPara)
|
||||
lineCount = getParaLinesCount(paraLines)
|
||||
lineLen = getParaLineLength(paraLines,0)
|
||||
If (lineCount > initialLineCount) Then
|
||||
MsgBox oPara.CharKerning
|
||||
increaseKerningFailed = true
|
||||
oPara.CharKerning = initialCharKerning
|
||||
EndIf
|
||||
If (lineCount = initialLineCount - 1 ) Then
|
||||
'Tightened last line but it is still smaller than we need
|
||||
decreaseKerningFailed = true
|
||||
fallBackSuccess = tryExpandPrevLine(oPara, minLastLineLength)
|
||||
If fallBackSuccess Then
|
||||
Exit Sub
|
||||
EndIf
|
||||
'Fall back to initial values
|
||||
MsgBox oPara.CharKerning
|
||||
oPara.CharKerning = initialCharKerning
|
||||
EndIf
|
||||
|
||||
oViewCursor.goToRange(oParaStart,false)
|
||||
oTextCursor.goToRange(oParaStart,false)
|
||||
lineCount = 0
|
||||
While NOT oTextCursor.isEndOfParagraph()
|
||||
oViewCursor.gotoEndOfLine(true)
|
||||
oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
lineLen = Len(oTextCursor.getString())
|
||||
paraLen = paraLen + lineLen
|
||||
lineCount = lineCount + 1
|
||||
oViewCursor.collapseToEnd()
|
||||
Wend
|
||||
'set initial line count
|
||||
If initialLineCount = 0 Then
|
||||
initialLineCount = lineCount
|
||||
ElseIf lineCount > initialLineCount Then
|
||||
'Undo last iteration as line overflow happened.
|
||||
'And exit
|
||||
If(IsEmpty(oPara.CharKerning)) Then
|
||||
oPara.CharKerning = 0
|
||||
Else
|
||||
oPara.CharKerning = oPara.CharKerning - 2
|
||||
End If
|
||||
Exit sub
|
||||
If (oPara.CharKerning > 50) Then
|
||||
MsgBox oPara.CharKerning
|
||||
increaseKerningFailed = true
|
||||
oPara.CharKerning = initialCharKerning
|
||||
EndIf
|
||||
mathExpect = paraLen / lineCount
|
||||
minLastLineLength = mathExpect * 0.9
|
||||
Loop Until minLastLineLength < lineLen
|
||||
|
||||
If (oPara.CharKerning < -15) Then
|
||||
decreaseKerningFailed = true
|
||||
MsgBox oPara.CharKerning
|
||||
oPara.CharKerning = initialCharKerning
|
||||
EndIf
|
||||
Loop
|
||||
MsgBox oPara.CharKerning
|
||||
End Sub
|
||||
|
||||
Function tryExpandPrevLine(oPara As Object, minLastLineLength As Integer) As Boolean
|
||||
Dim lineCount As Integer
|
||||
Dim initialLineCount As Integer
|
||||
paraLines = getParaLines(oPara)
|
||||
lineLen = getParaLineLength(paraLines,0)
|
||||
initialLineCount = getParaLinesCount(paraLines)
|
||||
lineCount = initialLineCount
|
||||
Do While lineCount = initialLineCount And lastLineIsNotBalanced(lineLen, minLastLineLength)
|
||||
increaseCharKerning(paraLines(UBound(paraLines)- 1))
|
||||
paraLines = getParaLines(oPara)
|
||||
lineCount = getParaLinesCount(paraLines)
|
||||
lineLen = getParaLineLength(paraLines,0)
|
||||
Loop
|
||||
If Not lastLineIsNotBalanced(lineLen, minLastLineLength) And lineCount = initialLineCount Then
|
||||
tryExpandPrevLine = true
|
||||
MsgBox paraLines(UBound(paraLines)- 1).CharKerning
|
||||
Else
|
||||
tryExpandPrevLine = false
|
||||
EndIf
|
||||
End Function
|
||||
|
||||
|
||||
Function getParaLinesCount(paraLines() As Object) As Integer
|
||||
getParaLinesCount = UBound(paraLines) + 1
|
||||
End Function
|
||||
|
||||
Function getParaLineLength(paraLines() As Object, lineNumber As Integer) As Integer
|
||||
Dim arrIndex As Integer
|
||||
arrIndex = UBound(paraLines) - lineNumber
|
||||
If (arrIndex >= 0) Then
|
||||
getParaLineLength = Len(paraLines(arrIndex).String)
|
||||
Else
|
||||
'Throw an error?
|
||||
getParaLineLength = 0
|
||||
EndIf
|
||||
|
||||
End Function
|
||||
|
||||
Function getParaLines(oPara As Object) As Variant
|
||||
Dim oTextCursor As Object
|
||||
Dim oViewCursor As Object
|
||||
Dim paraLine As Object
|
||||
Dim paraLines() As Object
|
||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||
'initial value is 1 As paragraph can't be 0 lines long
|
||||
oTextCursor = oPara.Text.createTextCursorByRange(oPara)
|
||||
oTextCursor.collapseToStart()
|
||||
oViewCursor.goToRange(oTextCursor,false)
|
||||
While NOT oTextCursor.isEndOfParagraph()
|
||||
oViewCursor.gotoEndOfLine(true)
|
||||
paraLine = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
AddToArray(paraLines, paraLine)
|
||||
oViewCursor.collapseToEnd()
|
||||
oTextCursor.goToRange(oViewCursor,false)
|
||||
Wend
|
||||
getParaLines = paraLines
|
||||
End Function
|
||||
|
||||
|
||||
Sub decreaseCharKerning(oPara As Object)
|
||||
If(IsEmpty(oPara.CharKerning)) Then
|
||||
oPara.CharKerning = 0
|
||||
Else
|
||||
oPara.CharKerning = oPara.CharKerning - 2
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Sub increaseCharKerning(oPara As Object)
|
||||
If(IsEmpty(oPara.CharKerning)) Then
|
||||
oPara.CharKerning = 0
|
||||
Else
|
||||
oPara.CharKerning = oPara.CharKerning + 2
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Function lastLineIsNotBalanced(lineLen As Integer,minLastLineLength As Integer) As Boolean
|
||||
lastLineIsNotBalanced = true
|
||||
If lineLen = 0 Then
|
||||
lastLineIsNotBalanced = false
|
||||
Exit Function
|
||||
EndIf
|
||||
If lineLen >= minLastLineLength Then
|
||||
lastLineIsNotBalanced = false
|
||||
EndIf
|
||||
End Function
|
||||
|
||||
Function getParaStart(oTextCursor As Object) As Object
|
||||
If NOT oTextCursor.isStartOfParagraph() Then
|
||||
oTextCursor.gotoStartOfParagraph(false)
|
||||
EndIf
|
||||
getParaStart = oTextCursor.getStart()
|
||||
End Function
|
||||
|
||||
Function getParaEnd(oTextCursor As Object) As Object
|
||||
If NOT oTextCursor.isEndOfParagraph() Then
|
||||
oTextCursor.gotoEndOfParagraph(false)
|
||||
EndIf
|
||||
getParaEnd = oTextCursor.getEnd()
|
||||
End Function
|
||||
|
||||
Function getParaSelected(oParaStart As Object,oParaEnd As Object) As Object
|
||||
Dim oPara As Object
|
||||
oPara = oParaStart.Text.createTextCursorByRange(oParaStart)
|
||||
oPara.goToRange(oParaEnd,true)
|
||||
getParaSelected = oPara
|
||||
End Function
|
||||
|
||||
|
||||
Function calculateMedianParaLen(oPara As Object) As Integer
|
||||
Dim oTextCursor As Object
|
||||
Dim oViewCursor As Object
|
||||
Dim lineCount As Integer
|
||||
Dim lineLen As Integer
|
||||
Dim linesLen As Integer
|
||||
linesLen = 0
|
||||
calculateMedianParaLen = 0
|
||||
lineCount = 0
|
||||
lineLen = 0
|
||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||
oViewCursor.goToRange(oPara, false)
|
||||
oViewCursor.collapseToStart()
|
||||
oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
oParaStart = getParaStart(oTextCursor)
|
||||
oViewCursor.goToRange(oParaStart,false)
|
||||
'Select first line
|
||||
oViewCursor.gotoEndOfLine(true)
|
||||
While NOT oTextCursor.isEndOfParagraph()
|
||||
lineLen = Len(oViewCursor.getString())
|
||||
linesLen = linesLen + lineLen
|
||||
lineCount = lineCount + 1
|
||||
oViewCursor.collapseToEnd()
|
||||
oViewCursor.gotoEndOfLine(true)
|
||||
oTextCursor.goToRange(oViewCursor,false)
|
||||
Wend
|
||||
If lineCount > 0 Then
|
||||
calculateMedianParaLen = linesLen / lineCount
|
||||
EndIf
|
||||
End Function
|
||||
|
||||
|
||||
|
||||
Sub convertBookmarksToFootnotes()
|
||||
Dim description As String
|
||||
|
|
|
@ -362,7 +362,7 @@ Sub setUniqPageStylesDEPRECATED
|
|||
End Sub
|
||||
|
||||
|
||||
Function hasPageStyleWith(pageStyleName)
|
||||
Function hasPageStyleWith(pageStyleName As String) As Boolean
|
||||
Dim enum1 As Object
|
||||
Dim enum1Element As Object
|
||||
Dim curPage As String
|
||||
|
@ -387,7 +387,7 @@ Function hasPageStyleWith(pageStyleName)
|
|||
hasPageStyleWith = false
|
||||
End Function
|
||||
|
||||
Function findFirstPageNumberWithStyle(pageStyleName)
|
||||
Function findFirstPageNumberWithStyle(pageStyleName As String) As Integer
|
||||
Dim enum1 As Object
|
||||
Dim enum1Element As Object
|
||||
Dim curPage As String
|
||||
|
@ -396,6 +396,7 @@ Function findFirstPageNumberWithStyle(pageStyleName)
|
|||
Dim oViewCursor As Object
|
||||
Dim anchor As Object
|
||||
Dim oSavePosition As Object
|
||||
Dim curPageStyleName As String
|
||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||
oSavePosition = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||
enum1 = ThisComponent.Text.createEnumeration()
|
||||
|
|
Loading…
Add table
Reference in a new issue