[INTERPRETER]

* BUG: Fix a possible crash in String.Code().

[GB.FORM.TERMINAL]
* OPT: Compress the attribute array associated with each line.
* OPT: Drawing line routine uses the JIT compiler.



git-svn-id: svn://localhost/gambas/trunk@7701 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2016-03-31 19:06:03 +00:00
parent 0c158f7788
commit d7e88bf641
6 changed files with 271 additions and 160 deletions

View file

@ -7,7 +7,7 @@ VersionFile=1
Component=gb.image
Component=gb.gui
Component=gb.form
Environment="GB_GUI=gb.qt5"
Environment="GB_GUI=gb.gtk3"
TabSize=2
Language=fr
Type=Component

View file

@ -4,38 +4,102 @@ Public Text As String
Public Length As Integer
Public Attr As New Integer[]
Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
Private Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
Public Sub GetAttr(hAttr As TerminalAttr, X As Integer)
Private Sub Uncompress() As Integer[]
Dim I As Integer
Dim iAttr As Integer
Try iAttr = Attr[X]
If BTst(iAttr, FLAG_BG) Then
hAttr.Background = Lsr(iAttr, 16) And 255
Else
hAttr.Background = Color.Default
Endif
Dim iCount As Integer
Dim aAttr As New Integer[]
Dim aTemp As Integer[]
If BTst(iAttr, FLAG_FG) Then
hAttr.Foreground = Lsr(iAttr, 24) And 255
Else
hAttr.Foreground = Color.Default
Endif
For I = 0 To Attr.Max
iAttr = Attr[I]
iCount = (Lsr(iAttr, 8) And 255) + 1
iAttr = iAttr And &HFFFF00FF
aTemp = New Integer[iCount]
aTemp.Fill(iAttr)
aAttr.Insert(aTemp)
Next
hAttr.Bold = BTst(iAttr, FLAG_BOLD)
hAttr.Dim = BTst(iAttr, FLAG_DIM)
hAttr.Reverse = BTst(iAttr, FLAG_REV)
hAttr.Underscore = BTst(iAttr, FLAG_UND)
hAttr.Blink = BTst(iAttr, FLAG_BLK)
'If aAttr.Count > String.Len(Text) Then Stop
Return aAttr
End
Private Sub Compress(aAttr As Integer[])
Dim I As Integer
Dim iAttr As Integer
Dim iOldAttr As Integer
Dim iCount As Integer
Dim N As Integer
Attr.Clear
For I = 0 To aAttr.Max
iAttr = aAttr[I]
If iAttr = iOldAttr And If iCount < 256 Then
Inc iCount
Continue
Endif
GoSub ADD_ATTR
iCount = 1
iOldAttr = iAttr
Next
GoSub ADD_ATTR
'Debug aAttr.Count; " -> "; N;; "/";; String.Len(Text)
'If N > String.Len(Text) Then Stop
Return
ADD_ATTR:
If iCount Then
N += iCount
Attr.Add(iOldAttr Or Lsl(iCount - 1, 8))
Endif
Return
End
' Public Sub GetAttr(hAttr As TerminalAttr, X As Integer)
'
' Dim iAttr As Integer
'
' Try iAttr = Attr[X]
'
' If BTst(iAttr, FLAG_BG) Then
' hAttr.Background = Lsr(iAttr, 16) And 255
' Else
' hAttr.Background = Color.Default
' Endif
'
' If BTst(iAttr, FLAG_FG) Then
' hAttr.Foreground = Lsr(iAttr, 24) And 255
' Else
' hAttr.Foreground = Color.Default
' Endif
'
' hAttr.Bold = BTst(iAttr, FLAG_BOLD)
' hAttr.Dim = BTst(iAttr, FLAG_DIM)
' hAttr.Reverse = BTst(iAttr, FLAG_REV)
' hAttr.Underscore = BTst(iAttr, FLAG_UND)
' hAttr.Blink = BTst(iAttr, FLAG_BLK)
'
' End
'
Public Sub SetAttr(hAttr As TerminalAttr, X As Integer, Optional L As Integer = 1, Optional bInsert As Boolean)
Dim iAttr As Integer
Dim aAttr As Integer[]
Dim aTemp As Integer[]
If hAttr.Background <> Color.Default Then iAttr = BSet(iAttr, FLAG_BG) + Lsl(hAttr.Background And 255, 16)
If hAttr.Foreground <> Color.Default Then iAttr = BSet(iAttr, FLAG_FG) + Lsl(hAttr.Foreground And 255, 24)
@ -46,18 +110,30 @@ Public Sub SetAttr(hAttr As TerminalAttr, X As Integer, Optional L As Integer =
If hAttr.Underscore Then iAttr = BSet(iAttr, FLAG_UND)
If hAttr.Blink Then iAttr = BSet(iAttr, FLAG_BLK)
If iAttr = 0 And If X + L >= Attr.Count Then
Attr.Resize(X)
aAttr = Uncompress()
If iAttr = 0 And If X >= aAttr.Count Then
'aAttr.Resize(X)
Else
If bInsert Then
aAttr = New Integer[L]
aAttr.Fill(iAttr)
Attr.Insert(aAttr, X)
If aAttr.Count < X Then aAttr.Resize(X)
aTemp = New Integer[L]
aTemp.Fill(iAttr)
aAttr.Insert(aTemp, X)
Else
If Attr.Count < X + L Then Attr.Resize(X + L)
Attr.Fill(iAttr, X, L)
If aAttr.Count < X + L Then aAttr.Resize(X + L)
aAttr.Fill(iAttr, X, L)
Endif
Endif
Compress(aAttr)
End
Public Sub Clear()
Text = ""
Length = 0
Attr.Clear
End

View file

@ -2,6 +2,8 @@
Export
Private Enum FLAG_BG, FLAG_FG, FLAG_BOLD, FLAG_DIM, FLAG_REV, FLAG_UND, FLAG_BLK
Public Foreground As Integer = -1
Public Background As Integer = -1
Public Bold As Boolean
@ -31,3 +33,24 @@ Public Sub IsVoid() As Boolean
End
Public Sub FillFrom(iAttr As Integer)
If BTst(iAttr, FLAG_BG) Then
Background = Lsr(iAttr, 16) And 255
Else
Background = Color.Default
Endif
If BTst(iAttr, FLAG_FG) Then
Foreground = Lsr(iAttr, 24) And 255
Else
Foreground = Color.Default
Endif
Bold = BTst(iAttr, FLAG_BOLD)
{Dim} = BTst(iAttr, FLAG_DIM)
Reverse = BTst(iAttr, FLAG_REV)
Underscore = BTst(iAttr, FLAG_UND)
Blink = BTst(iAttr, FLAG_BLK)
End

View file

@ -170,9 +170,8 @@ Private Sub ClearLine(Y As Integer)
If Y > Lines.Max Then Return
hLine = Lines[Y]
If Not hLine Then Return
hLine.Text = ""
hLine.Length = 0
hLine.Attr.Clear
hLine.Clear()
End
@ -202,17 +201,19 @@ Private Sub Insert(sText As String, Optional X As Integer = $X)
If hLine.Length < X Then
hLine.Text &= Space$(X - hLine.Length) & sText & String.Mid(hLine.Text, X + iLen)
hLine.Length = String.Len(hLine.Text)
hLine.SetAttr($hAttr, X, iLen)
Else
If InsertMode Then
hLine.Text = String.Left(String.Left(hLine.Text, X) & sText & String.Mid(hLine.Text, X + 1), $W)
hLine.Length = String.Len(hLine.Text)
hLine.SetAttr($hAttr, X, iLen, True)
Else
hLine.Text = String.Left(hLine.Text, X) & sText & String.Mid(hLine.Text, X + iLen + 1)
hLine.Length = String.Len(hLine.Text)
hLine.SetAttr($hAttr, X, iLen)
Endif
Endif
hLine.Length = String.Len(hLine.Text)
GetView()._RefreshLine($Y)
@ -454,8 +455,7 @@ Public Sub EraseStartOfLine()
hLine = GetLine($Y)
If hLine.Length <= $X Then
hLine.Text = ""
hLine.Length = 0
hLine.Clear()
GetView()._RefreshLine($Y)
Else
hLine.Text = Space$($X + 1) & String.Mid$(hLine.Text, $X + 1)
@ -470,8 +470,7 @@ Public Sub EraseLine()
hLine = GetLine($Y)
If $hAttr.IsVoid() Then
hLine.Text = ""
hLine.Length = 0
hLine.Clear()
Else
Insert(Space$($W), 0)
Endif
@ -664,8 +663,6 @@ Fast Private Sub DrawLine(L As Integer, X As Float, Y As Integer, LH As Integer,
Dim I As Integer
'Dim sText As String
Dim aAttr As Integer[]
Dim iAttr As Integer
Dim iOldAttr As Integer
Dim hAttr As New TerminalAttr
Dim iFg As Integer = hView.Foreground
Dim iBg As Integer = hView.Background
@ -688,137 +685,137 @@ Fast Private Sub DrawLine(L As Integer, X As Float, Y As Integer, LH As Integer,
aAttr = hLine.Attr
P = 1
For I = 1 To hLine.Length
If aAttr.Count >= I Then
iAttr = aAttr[I - 1]
For I = 0 To aAttr.Max
If P > hLine.Length Then Break
hAttr.FillFrom(aAttr[I])
iLen = Min((Lsr(aAttr[I], 8) And 255), hLine.Length - P) + 1
iBg = hAttr.Background
If iBg >= 0 Then
iBg = $aColor[iBg]
Else
iAttr = 0
iBg = hView.Background
Endif
If iAttr <> iOldAttr Then
GoSub DRAW_TEXT
iOldAttr = iAttr
hLine.GetAttr(hAttr, I - 1)
iBg = hAttr.Background
If iBg >= 0 Then
iBg = $aColor[iBg]
Else
iBg = hView.Background
Endif
iFg = hAttr.Foreground
If iFg >= 0 Then
'Debug iFg
iFg = $aColor[iFg]
Else
iFg = hView.Foreground
Endif
If hAttr.Reverse Then Swap iBg, iFg
If hAttr.Dim Then iFg = Color.Merge(iFg, hView.Background)
Paint.Background = Color.White
If hAttr.Bold Then
HC = LH
Else
HC = 0
Endif
iFg = hAttr.Foreground
If iFg >= 0 Then
'Debug iFg
iFg = $aColor[iFg]
Else
iFg = hView.Foreground
Endif
' Paint.FillRect(X, Y, $CW, $LH, iBg)
' If iFg = $hView.Foreground And If String.Code(sCar) <= 255 Then
' hRect = Rect(String.Code(sCar) * $CW, 0, $CW, $LH)
' Paint.DrawImage($hCacheFont, X, Y, $CW, $LH,, hRect)
' If hAttr.Bold Then Paint.DrawImage($hCacheFont, X + 1, Y, $CW, $LH,, hRect)
' Else
' Paint.DrawText(sCar, X, Y + $iAscent)
' If hAttr.Bold Then Paint.DrawText(sCar, X + 1, Y + $iAscent)
' Endif
' X += $CW
If hAttr.Reverse Then Swap iBg, iFg
If hAttr.Dim Then iFg = Color.Merge(iFg, hView.Background)
Paint.Background = Color.White
If hAttr.Bold Then
HC = LH
Else
HC = 0
Endif
GoSub DRAW_TEXT
Next
GoSub DRAW_TEXT
Paint.Operator = Paint.OperatorOver
If P <= hLine.Length Then
iLen = hLine.Length - P + 1
iFg = hView.Foreground
iBg = hView.Background
HC = 0
hAttr.FillFrom(0)
GoSub DRAW_TEXT
Endif
Return
DRAW_TEXT:
iLen = I - P
If iLen <= 0 Then Return
W = iLen * CW
Paint.Begin($hLineCache)
If hFontCache Then
Paint.FillRect(0, 0, W, LH, iFg)
XT = 0
hRect = Rect(0, 0, CW, LH)
Paint.Operator = Paint.OperatorDestATop
For J = P To P + iLen - 1
'sCar = String.Mid$(hLine.Text, J, 1)
C = String.Code(hLine.Text, J)
If C <= 255 Then
hRect.Move(C * CW, HC)
Paint.DrawImage(hFontCache, XT, 0, CW, LH,, hRect)
Else
If $cCharCache.Exist(C) Then
C = $cCharCache[C]
hRect.Move(C * CW, 0)
Paint.Begin($hLineCache)
Paint.FillRect(0, 0, W, LH, iFg)
XT = 0
hRect = Rect(0, 0, CW, LH)
Paint.Operator = Paint.OperatorDestATop
For J = P To P + iLen - 1
'sCar = String.Mid$(hLine.Text, J, 1)
C = String.Code(hLine.Text, J)
If C = 0 Then Stop
If C <= 255 Then
hRect.Move(C * CW, HC)
Paint.DrawImage(hFontCache, XT, 0, CW, LH,, hRect)
Else
If $cCharCache.Count < 32 Then
XC = $cCharCache.Count * CW
YC = 0
If $cCharCache.Exist(C) Then
C = $cCharCache[C]
hRect.Move(C * CW, 0)
Paint.DrawImage(hFontCache, XT, 0, CW, LH,, hRect)
Else
XC = 0
YC = LH
If $cCharCache.Count < 32 Then
XC = $cCharCache.Count * CW
YC = 0
Else
XC = 0
YC = LH
Endif
Paint.Begin(hFontCache)
Paint.Operator = Paint.OperatorSource
Paint.FillRect(XC, YC, CW, LH, Color.Transparent)
Paint.Font = hFont
Paint.DrawText(String.Chr$(C), XC, YC, CW, LH, Align.Center)
If hAttr.Bold Then Paint.DrawText(String.Chr$(C), XC + 1, YC, CW, LH, Align.Center)
Paint.End
hRect.Move(XC, YC)
Paint.DrawImage(hFontCache, XT, 0, CW, LH,, hRect)
If YC = 0 Then $cCharCache[C] = $cCharCache.Count
Endif
Paint.Begin(hFontCache)
Paint.Operator = Paint.OperatorSource
Paint.FillRect(XC, YC, CW, LH, Color.Transparent)
Paint.Font = hFont
Paint.DrawText(String.Chr$(C), XC, YC, CW, LH, Align.Center)
If hAttr.Bold Then Paint.DrawText(String.Chr$(C), XC + 1, YC, CW, LH, Align.Center)
Paint.End
hRect.Move(XC, YC)
Paint.DrawImage(hFontCache, XT, 0, CW, LH,, hRect)
If YC = 0 Then $cCharCache[C] = $cCharCache.Count
Endif
Endif
XT += CW
Next
Paint.End
XT = X
Paint.FillRect(XT, Y, W, LH, iBg)
Paint.DrawImage($hLineCache, XT, Y, W, LH,, Rect(0, 0, W, LH))
XT += CW
Next
Paint.End
XT = X
Paint.FillRect(XT, Y, W, LH, iBg)
Paint.DrawImage($hLineCache, XT, Y, W, LH,, Rect(0, 0, W, LH))
Else
XT = X
Paint.FillRect(XT, Y, W, LH, iBg)
Paint.Background = iFg
Paint.DrawText(String.Mid$(hLine.Text, P, iLen), XT, Y + LA)
If hAttr.Bold Then Paint.DrawText(String.Mid$(hLine.Text, P, iLen), XT + 1, Y + LA)
Endif
If hAttr.Underscore Then Paint.FillRect(XT, Y + LH - 1, W, 1, Color.SetAlpha(iFg, 64))
X += W
P = I
P += iLen
Return
End

View file

@ -155,25 +155,33 @@ Private Sub UpdateFont()
'Debug $CW
$CW = Ceil($CW)
' If .Fixed Then
'
' $hCacheFont = Null
'
' Else
$hCacheFont = New Image($CW * 256, $LH * 2, Color.Transparent)
Paint.Begin($hCacheFont)
Paint.Background = Color.White
Paint.Font = $hView.Font
For I = 33 To 126
Paint.DrawText(String.Chr(I), I * $CW, 0, $CW, $LH, Align.Center)
Next
For I = 160 To 255
Paint.DrawText(String.Chr(I), I * $CW, 0, $CW, $LH, Align.Center)
Next
Paint.End
Paint.Begin($hCacheFont)
Paint.DrawImage($hCacheFont, 0, $LH, $hCacheFont.W, $LH,, Rect(0, 0, $hCacheFont.W, $LH))
Paint.DrawImage($hCacheFont, 1, $LH, $hCacheFont.W, $LH, 0.8, Rect(0, 0, $hCacheFont.W, $LH))
Paint.End
' Endif
End With
$hCacheFont = New Image($CW * 256, $LH * 2, Color.Transparent)
Paint.Begin($hCacheFont)
Paint.Background = Color.White
Paint.Font = $hView.Font
For I = 33 To 126
Paint.DrawText(String.Chr(I), I * $CW, 0, $CW, $LH, Align.Center)
Next
For I = 160 To 255
Paint.DrawText(String.Chr(I), I * $CW, 0, $CW, $LH, Align.Center)
Next
Paint.End
Paint.Begin($hCacheFont)
Paint.DrawImage($hCacheFont, 0, $LH, $hCacheFont.W, $LH,, Rect(0, 0, $hCacheFont.W, $LH))
Paint.DrawImage($hCacheFont, 1, $LH, $hCacheFont.W, $LH, 0.8, Rect(0, 0, $hCacheFont.W, $LH))
Paint.End
' For I = 33 To 255
' Paint.DrawText(String.Chr(I), I * $CW, $LH, $CW, $LH, Align.Center)
' Paint.DrawText(String.Chr(I), I * $CW + 1, $LH, $CW, $LH, Align.Center)

View file

@ -747,6 +747,13 @@ BEGIN_METHOD(String_Code, GB_STRING str; GB_INTEGER index)
str = STRING(str);
len = LENGTH(str);
if (index > len)
{
GB_ReturnInteger(0);
return;
}
pos = utf8_get_pos(VARG(str).addr, str, len, index - 1);
lc = STRING_utf8_get_char_length(str[pos]);