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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
|
<!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
|
End Sub
|
||||||
|
|
||||||
|
@ -441,10 +441,27 @@ Sub stretchPrevPage()
|
||||||
oViewCursor.goToRange(oSavePosition,false)
|
oViewCursor.goToRange(oSavePosition,false)
|
||||||
End Sub
|
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)
|
Sub adjustLastLine(anchor As Object)
|
||||||
anchor.ParaAdjust = 2
|
anchor.ParaAdjust = 2
|
||||||
'anchor.ParaLastLineAdjust = 2
|
anchor.ParaLastLineAdjust = 2
|
||||||
balancePara(anchor)
|
balancePara(anchor)
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
@ -478,77 +495,221 @@ Sub balancePara(targetPara As Object)
|
||||||
Dim lineCount As Integer
|
Dim lineCount As Integer
|
||||||
Dim initialLineCount As Integer
|
Dim initialLineCount As Integer
|
||||||
Dim lineLen As Integer
|
Dim lineLen As Integer
|
||||||
Dim mathExpect As Integer
|
|
||||||
Dim minLastLineLength As Integer
|
Dim minLastLineLength As Integer
|
||||||
paraLen = 0
|
Dim medianLen As Integer
|
||||||
lineLen = 0
|
Dim paraLines() As Object
|
||||||
minLastLineLength = 0
|
Dim decreaseKerningFailed As Boolean
|
||||||
initialLineCount = 0
|
Dim increaseKerningFailed As Boolean
|
||||||
|
Dim fallBackSuccess As Boolean
|
||||||
|
fallBackSuccess = false
|
||||||
|
decreaseKerningFailed = false
|
||||||
|
increaseKerningFailed = false
|
||||||
|
|
||||||
|
|
||||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||||
oViewCursor.goToRange(targetPara, false)
|
oViewCursor.goToRange(targetPara, false)
|
||||||
|
|
||||||
oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
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
|
oParaStart = getParaStart(oTextCursor)
|
||||||
'Not first iteration
|
oParaEnd = getParaEnd(oTextCursor)
|
||||||
If minLastLineLength <> 0 Then
|
oPara = getParaSelected(oParaStart,oParaEnd)
|
||||||
If oPara.CharKerning < 50 Then
|
paraLen = Len(oPara.String)
|
||||||
If(IsEmpty(oPara.CharKerning)) Then
|
paraLines = getParaLines(oPara)
|
||||||
oPara.CharKerning = 0
|
initialLineCount = getParaLinesCount(paraLines)
|
||||||
Else
|
lineLen = getParaLineLength(paraLines, 0)
|
||||||
oPara.CharKerning = oPara.CharKerning + 2
|
medianLen = calculateMedianParaLen(oPara)
|
||||||
End If
|
minLastLineLength = medianLen * 0.89
|
||||||
Else
|
|
||||||
'Failed to balance para
|
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
|
Exit Sub
|
||||||
EndIf
|
EndIf
|
||||||
|
'Fall back to initial values
|
||||||
|
MsgBox oPara.CharKerning
|
||||||
|
oPara.CharKerning = initialCharKerning
|
||||||
EndIf
|
EndIf
|
||||||
|
If (oPara.CharKerning > 50) Then
|
||||||
oViewCursor.goToRange(oParaStart,false)
|
MsgBox oPara.CharKerning
|
||||||
oTextCursor.goToRange(oParaStart,false)
|
increaseKerningFailed = true
|
||||||
lineCount = 0
|
oPara.CharKerning = initialCharKerning
|
||||||
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
|
|
||||||
EndIf
|
EndIf
|
||||||
mathExpect = paraLen / lineCount
|
If (oPara.CharKerning < -15) Then
|
||||||
minLastLineLength = mathExpect * 0.9
|
decreaseKerningFailed = true
|
||||||
Loop Until minLastLineLength < lineLen
|
MsgBox oPara.CharKerning
|
||||||
|
oPara.CharKerning = initialCharKerning
|
||||||
|
EndIf
|
||||||
|
Loop
|
||||||
|
MsgBox oPara.CharKerning
|
||||||
End Sub
|
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()
|
Sub convertBookmarksToFootnotes()
|
||||||
Dim description As String
|
Dim description As String
|
||||||
|
|
|
@ -362,7 +362,7 @@ Sub setUniqPageStylesDEPRECATED
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
Function hasPageStyleWith(pageStyleName)
|
Function hasPageStyleWith(pageStyleName As String) As Boolean
|
||||||
Dim enum1 As Object
|
Dim enum1 As Object
|
||||||
Dim enum1Element As Object
|
Dim enum1Element As Object
|
||||||
Dim curPage As String
|
Dim curPage As String
|
||||||
|
@ -387,7 +387,7 @@ Function hasPageStyleWith(pageStyleName)
|
||||||
hasPageStyleWith = false
|
hasPageStyleWith = false
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
Function findFirstPageNumberWithStyle(pageStyleName)
|
Function findFirstPageNumberWithStyle(pageStyleName As String) As Integer
|
||||||
Dim enum1 As Object
|
Dim enum1 As Object
|
||||||
Dim enum1Element As Object
|
Dim enum1Element As Object
|
||||||
Dim curPage As String
|
Dim curPage As String
|
||||||
|
@ -396,6 +396,7 @@ Function findFirstPageNumberWithStyle(pageStyleName)
|
||||||
Dim oViewCursor As Object
|
Dim oViewCursor As Object
|
||||||
Dim anchor As Object
|
Dim anchor As Object
|
||||||
Dim oSavePosition As Object
|
Dim oSavePosition As Object
|
||||||
|
Dim curPageStyleName As String
|
||||||
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
oViewCursor = ThisComponent.CurrentController.getViewCursor()
|
||||||
oSavePosition = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
oSavePosition = oViewCursor.Text.createTextCursorByRange(oViewCursor)
|
||||||
enum1 = ThisComponent.Text.createEnumeration()
|
enum1 = ThisComponent.Text.createEnumeration()
|
||||||
|
|
Loading…
Add table
Reference in a new issue