Fast text-wrapping in Cobra
A fast implementation of text-wrapping (a.k.a. word-wrapping) for the Cobra programming language.
Program
Uses
keyset,
pure2d
Const
WT_ARRAY_SIZE = 1024
LINE_SPACING = 1.0
Var
breakPoint: Array [WT_ARRAY_SIZE] of Integer
breakPointString: String
breakPointLength: Array [WT_ARRAY_SIZE] of Integer
breakPointForce: Array [WT_ARRAY_SIZE] of Boolean
Function TextWrap(x: Integer, y:Integer, w: Integer, s: String, buf: Element) : Integer
Var
i, l, c, t, j: Integer
txtl, txth, txtx: Integer
lineStart: Integer
Begin
l = Length(s)
// First breakpoint
breakPoint[0] = 1
t = 1
// Find potential breakpoints (space or newline)
For i = 1 to l
c = Asc(Mid(s, i, 1))
If (c = 10) or (c = 32) then
// Remove linebreak
If (c = 10) then
s = Left(s, i-1) + " " + Right(s, l-i)
breakPointForce[t] = TRUE
Else
breakPointForce[t] = FALSE
Endif
breakPoint[t] = i + 1
Inc(t)
Endif
If t = (WT_ARRAY_SIZE - 2) then break
Next
// End
If t < (WT_ARRAY_SIZE - 2)
breakPoint[t] = l + 1
Inc(t)
Endif
// Determine breaks
txtl = 0
txtx = 0
lineStart = 1
For i = 1 to (t)
breakPointString = Mid(s, breakPoint[i-1], breakPoint[i] - breakPoint[i-1])
breakPointLength[i] = TextWidth(breakPointString, buf)
If i = 1 then txth = TextHeight(breakPointString, buf)
If (txtl + breakPointLength[i] > w) or (breakPointForce[i-1]) or (i = (t)) then
// Reached limit - render line
For j = lineStart to (i-1)
Text(x + txtx, y, Mid(s, breakPoint[j-1], breakPoint[j] - breakPoint[j-1]), buf)
txtx = txtx + breakPointLength[j] // Increment x
Next
If breakPointForce[i-1] = TRUE then breakPointForce[i-1] = FALSE // Stop forced linebreak
lineStart = i // Increment line starting index
y = y + (txth * LINE_SPACING) // Increment y
If i < (t) then Dec(i) // Rewind loop
txtl = 0 // Reset Line length
txtx = 0 // Reset x
Else
txtl = txtl + breakPointLength[i]
Endif
Next
breakPointString = ""
result = y
End
Var
s1, s2, s3: String
y: Integer
Begin
OpenScreen(1024, 768, 32, FALSE, COB_SHOWBORDER)
// First two paragraphs of Orwell's 1984
s1 = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."+Chr(10)+Chr(10)+"The hallway smelt of boiled cabbage and old rag mats. At one end of it a coloured poster, too large for indoor display, had been tacked to the wall. It depicted simply an enormous face, more than a metre wide: the face of a man of about forty-five, with a heavy black moustache and ruggedly handsome features. Winston made for the stairs. It was no use trying the lift. Even at the best of times it was seldom working, and at present the electric current was cut off during daylight hours. It was part of the economy drive in preparation for Hate Week. The flat was seven flights up, and Winston, who was thirty-nine and had a varicose ulcer above his right ankle, went slowly, resting several times on the way. On each landing, opposite the lift-shaft, the poster with the enormous face gazed from the wall. It was one of those pictures which are so contrived that the eyes follow you about when you move. BIG BROTHER IS WATCHING YOU, the caption beneath it ran."
s2 = Chr(10)+"This is a Second call to TextWrap, continued after the first TextWrap returned the y position to continue from."
s3 = Chr(10)+"This is a short line."
SetFont("verdana", 10, 0, ScreenBuffer)
PenColor(ToRGBA(100,100,255))
y = TextWrap(10, 10, 390, s1, screenbuffer)
PenColor(ToRGBA(100,255,100))
TextWrap(10, y, 390, s2, screenbuffer)
PenColor(ToRGBA(200,200,100))
y = TextWrap(420, 10, 594, s1, screenbuffer)
PenColor(ToRGBA(255,100,100))
TextWrap(420, y, 594, s3, screenbuffer)
While KeyHits(VK_ESCAPE) < 1
Flip
Pause(1)
Wend
End
Uses
keyset,
pure2d
Const
WT_ARRAY_SIZE = 1024
LINE_SPACING = 1.0
Var
breakPoint: Array [WT_ARRAY_SIZE] of Integer
breakPointString: String
breakPointLength: Array [WT_ARRAY_SIZE] of Integer
breakPointForce: Array [WT_ARRAY_SIZE] of Boolean
Function TextWrap(x: Integer, y:Integer, w: Integer, s: String, buf: Element) : Integer
Var
i, l, c, t, j: Integer
txtl, txth, txtx: Integer
lineStart: Integer
Begin
l = Length(s)
// First breakpoint
breakPoint[0] = 1
t = 1
// Find potential breakpoints (space or newline)
For i = 1 to l
c = Asc(Mid(s, i, 1))
If (c = 10) or (c = 32) then
// Remove linebreak
If (c = 10) then
s = Left(s, i-1) + " " + Right(s, l-i)
breakPointForce[t] = TRUE
Else
breakPointForce[t] = FALSE
Endif
breakPoint[t] = i + 1
Inc(t)
Endif
If t = (WT_ARRAY_SIZE - 2) then break
Next
// End
If t < (WT_ARRAY_SIZE - 2)
breakPoint[t] = l + 1
Inc(t)
Endif
// Determine breaks
txtl = 0
txtx = 0
lineStart = 1
For i = 1 to (t)
breakPointString = Mid(s, breakPoint[i-1], breakPoint[i] - breakPoint[i-1])
breakPointLength[i] = TextWidth(breakPointString, buf)
If i = 1 then txth = TextHeight(breakPointString, buf)
If (txtl + breakPointLength[i] > w) or (breakPointForce[i-1]) or (i = (t)) then
// Reached limit - render line
For j = lineStart to (i-1)
Text(x + txtx, y, Mid(s, breakPoint[j-1], breakPoint[j] - breakPoint[j-1]), buf)
txtx = txtx + breakPointLength[j] // Increment x
Next
If breakPointForce[i-1] = TRUE then breakPointForce[i-1] = FALSE // Stop forced linebreak
lineStart = i // Increment line starting index
y = y + (txth * LINE_SPACING) // Increment y
If i < (t) then Dec(i) // Rewind loop
txtl = 0 // Reset Line length
txtx = 0 // Reset x
Else
txtl = txtl + breakPointLength[i]
Endif
Next
breakPointString = ""
result = y
End
Var
s1, s2, s3: String
y: Integer
Begin
OpenScreen(1024, 768, 32, FALSE, COB_SHOWBORDER)
// First two paragraphs of Orwell's 1984
s1 = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."+Chr(10)+Chr(10)+"The hallway smelt of boiled cabbage and old rag mats. At one end of it a coloured poster, too large for indoor display, had been tacked to the wall. It depicted simply an enormous face, more than a metre wide: the face of a man of about forty-five, with a heavy black moustache and ruggedly handsome features. Winston made for the stairs. It was no use trying the lift. Even at the best of times it was seldom working, and at present the electric current was cut off during daylight hours. It was part of the economy drive in preparation for Hate Week. The flat was seven flights up, and Winston, who was thirty-nine and had a varicose ulcer above his right ankle, went slowly, resting several times on the way. On each landing, opposite the lift-shaft, the poster with the enormous face gazed from the wall. It was one of those pictures which are so contrived that the eyes follow you about when you move. BIG BROTHER IS WATCHING YOU, the caption beneath it ran."
s2 = Chr(10)+"This is a Second call to TextWrap, continued after the first TextWrap returned the y position to continue from."
s3 = Chr(10)+"This is a short line."
SetFont("verdana", 10, 0, ScreenBuffer)
PenColor(ToRGBA(100,100,255))
y = TextWrap(10, 10, 390, s1, screenbuffer)
PenColor(ToRGBA(100,255,100))
TextWrap(10, y, 390, s2, screenbuffer)
PenColor(ToRGBA(200,200,100))
y = TextWrap(420, 10, 594, s1, screenbuffer)
PenColor(ToRGBA(255,100,100))
TextWrap(420, y, 594, s3, screenbuffer)
While KeyHits(VK_ESCAPE) < 1
Flip
Pause(1)
Wend
End
Please modify & use this code freely.
Stay Subscribed
RSS feed or get updates by e-mail.
, subscribe to theYou can also contact me directly - I make an effort to reply to every e-mail.