From a38a0f42350c75c6b804e23902f945b4b20d3583 Mon Sep 17 00:00:00 2001 From: "5684185+vsariola@users.noreply.github.com" <5684185+vsariola@users.noreply.github.com> Date: Sun, 22 Oct 2023 19:10:24 +0300 Subject: [PATCH] fix(tracker/gioui): text.Shaper should not be a global variable text.Shaper is not thread safe, which caused crash when adding multiple VSTI plugins to a DAW project. This change fixes that crash. Further refactorings need to consider where that text.Shaper should actually reside. --- CHANGELOG.md | 1 + tracker/gioui/alert.go | 4 +++- tracker/gioui/dialog.go | 7 +++++-- tracker/gioui/instrumenteditor.go | 16 ++++++++-------- tracker/gioui/label.go | 9 +++++---- tracker/gioui/layout.go | 4 ++-- tracker/gioui/menu.go | 10 ++++++---- tracker/gioui/ordereditor.go | 6 +++--- tracker/gioui/parameditor.go | 4 ++-- tracker/gioui/parameter.go | 4 ++-- tracker/gioui/rowmarkers.go | 4 ++-- tracker/gioui/songpanel.go | 12 ++++++------ tracker/gioui/theme.go | 1 - tracker/gioui/trackeditor.go | 12 ++++++------ tracker/gioui/tracker.go | 5 +++++ 15 files changed, 56 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cd24c9..53b591a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). options ### Fixed +- Crash when running more than one sointu VSTI plugins in parallel - The scroll bars move in sync with the cursor. - The stereo version of delay in the go virtual machine (executables / plugins not ending with -native) applied the left delay taps on the right channel, and diff --git a/tracker/gioui/alert.go b/tracker/gioui/alert.go index 2e8a468..d168983 100644 --- a/tracker/gioui/alert.go +++ b/tracker/gioui/alert.go @@ -9,6 +9,7 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" + "gioui.org/text" "gioui.org/unit" ) @@ -22,6 +23,7 @@ type Alert struct { showTime time.Time pos float64 lastUpdate time.Time + shaper *text.Shaper } type AlertType int @@ -94,7 +96,7 @@ func (a *Alert) Layout(gtx C) D { }.Op()) return D{Size: gtx.Constraints.Min} } - labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16)} + labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16), Shaper: a.shaper} return alertMargin.Layout(gtx, func(gtx C) D { return layout.S.Layout(gtx, func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() diff --git a/tracker/gioui/dialog.go b/tracker/gioui/dialog.go index fecc2df..8800f14 100644 --- a/tracker/gioui/dialog.go +++ b/tracker/gioui/dialog.go @@ -3,6 +3,7 @@ package gioui import ( "gioui.org/layout" "gioui.org/op/paint" + "gioui.org/text" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" @@ -23,9 +24,10 @@ type DialogStyle struct { AltStyle material.ButtonStyle OkStyle material.ButtonStyle CancelStyle material.ButtonStyle + Shaper *text.Shaper } -func ConfirmDialog(th *material.Theme, dialog *Dialog, text string) DialogStyle { +func ConfirmDialog(th *material.Theme, dialog *Dialog, text string, shaper *text.Shaper) DialogStyle { ret := DialogStyle{ dialog: dialog, Text: text, @@ -33,6 +35,7 @@ func ConfirmDialog(th *material.Theme, dialog *Dialog, text string) DialogStyle AltStyle: HighEmphasisButton(th, &dialog.BtnAlt, "Alt"), OkStyle: HighEmphasisButton(th, &dialog.BtnOk, "Ok"), CancelStyle: HighEmphasisButton(th, &dialog.BtnCancel, "Cancel"), + Shaper: shaper, } return ret } @@ -44,7 +47,7 @@ func (d *DialogStyle) Layout(gtx C) D { return Popup(&d.dialog.Visible).Layout(gtx, func(gtx C) D { return d.Inset.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx, - layout.Rigid(Label(d.Text, highEmphasisTextColor)), + layout.Rigid(Label(d.Text, highEmphasisTextColor, d.Shaper)), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120)) if d.ShowAlt { diff --git a/tracker/gioui/instrumenteditor.go b/tracker/gioui/instrumenteditor.go index 2135e64..b3c1ea6 100644 --- a/tracker/gioui/instrumenteditor.go +++ b/tracker/gioui/instrumenteditor.go @@ -155,7 +155,7 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D { inset := layout.UniformInset(unit.Dp(6)) return inset.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("OCT:", white)), + layout.Rigid(Label("OCT:", white, t.TextShaper)), layout.Rigid(octave), ) }) @@ -193,7 +193,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { loadInstrumentBtnStyle := IconButton(t.Theme, ie.loadInstrumentBtn, icons.FileFolderOpen, true, "Load instrument") deleteInstrumentBtnStyle := IconButton(t.Theme, ie.deleteInstrumentBtn, icons.ActionDelete, t.CanDeleteInstrument(), "Delete\ninstrument") - m := PopupMenu(t.Theme, &ie.presetMenu) + m := t.PopupMenu(&ie.presetMenu) for item, clicked := ie.presetMenu.Clicked(); clicked; item, clicked = ie.presetMenu.Clicked() { t.SetInstrument(tracker.InstrumentPresets[item]) @@ -201,7 +201,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { header := func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, - layout.Rigid(Label("Voices: ", white)), + layout.Rigid(Label("Voices: ", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { maxRemain := t.MaxInstrumentVoices() t.InstrumentVoices.Value = t.Instrument().NumVoices @@ -277,7 +277,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { } for ie.deleteInstrumentBtn.Clickable.Clicked() { if t.CanDeleteInstrument() { - dialogStyle := ConfirmDialog(t.Theme, ie.confirmInstrDelete, "Are you sure you want to delete this instrument?") + dialogStyle := ConfirmDialog(t.Theme, ie.confirmInstrDelete, "Are you sure you want to delete this instrument?", t.TextShaper) ie.confirmInstrDelete.Visible = true t.ModalDialog = dialogStyle.Layout } @@ -303,7 +303,7 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D { element := func(gtx C, i int) D { gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(30)) - grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center} + grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center, Shaper: t.TextShaper} if i == t.InstrIndex() { grabhandle.Text = ":::" } @@ -346,7 +346,7 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D { if text == "" { text = "Instr" } - labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: color, FontSize: unit.Sp(12)} + labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: color, FontSize: unit.Sp(12), Shaper: t.TextShaper} return layout.Center.Layout(gtx, labelStyle.Layout) } return layout.Inset{Left: unit.Dp(6), Right: unit.Dp(6)}.Layout(gtx, func(gtx C) D { @@ -470,14 +470,14 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D { editor.Font = labelDefaultFont unitName = editor.Layout } else { - unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12)} + unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper} if unitNameLabel.Text == "" { unitNameLabel.Text = "---" } unitName = unitNameLabel.Layout } - stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12)} + stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper} rightMargin := layout.Inset{Right: unit.Dp(10)} return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Flexed(1, unitName), diff --git a/tracker/gioui/label.go b/tracker/gioui/label.go index d4b365d..b8958d9 100644 --- a/tracker/gioui/label.go +++ b/tracker/gioui/label.go @@ -20,6 +20,7 @@ type LabelStyle struct { Alignment layout.Direction Font font.Font FontSize unit.Sp + Shaper *text.Shaper } func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions { @@ -31,7 +32,7 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions { dims := widget.Label{ Alignment: text.Start, MaxLines: 1, - }.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{}) + }.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{}) return layout.Dimensions{ Size: dims.Size.Add(image.Pt(2, 2)), Baseline: dims.Baseline, @@ -42,11 +43,11 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions { return widget.Label{ Alignment: text.Start, MaxLines: 1, - }.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{}) + }.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{}) }), ) } -func Label(str string, color color.NRGBA) layout.Widget { - return LabelStyle{Text: str, Color: color, ShadeColor: black, Font: labelDefaultFont, FontSize: labelDefaultFontSize, Alignment: layout.W}.Layout +func Label(str string, color color.NRGBA, shaper *text.Shaper) layout.Widget { + return LabelStyle{Text: str, Color: color, ShadeColor: black, Font: labelDefaultFont, FontSize: labelDefaultFontSize, Alignment: layout.W, Shaper: shaper}.Layout } diff --git a/tracker/gioui/layout.go b/tracker/gioui/layout.go index 395c1c7..3c88a25 100644 --- a/tracker/gioui/layout.go +++ b/tracker/gioui/layout.go @@ -38,7 +38,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) { t.layoutBottom) } t.Alert.Layout(gtx) - dstyle := ConfirmDialog(t.Theme, t.ConfirmSongDialog, "Do you want to save your changes to the song? Your changes will be lost if you don't save them.") + dstyle := ConfirmDialog(t.Theme, t.ConfirmSongDialog, "Do you want to save your changes to the song? Your changes will be lost if you don't save them.", t.TextShaper) dstyle.ShowAlt = true dstyle.OkStyle.Text = "Save" dstyle.AltStyle.Text = "Don't save" @@ -56,7 +56,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) { for t.ConfirmSongDialog.BtnCancel.Clicked() { t.ConfirmSongDialog.Visible = false } - dstyle = ConfirmDialog(t.Theme, t.WaveTypeDialog, "Export .wav in int16 or float32 sample format?") + dstyle = ConfirmDialog(t.Theme, t.WaveTypeDialog, "Export .wav in int16 or float32 sample format?", t.TextShaper) dstyle.ShowAlt = true dstyle.OkStyle.Text = "Int16" dstyle.AltStyle.Text = "Float32" diff --git a/tracker/gioui/menu.go b/tracker/gioui/menu.go index cc34a3b..5d6e201 100644 --- a/tracker/gioui/menu.go +++ b/tracker/gioui/menu.go @@ -9,9 +9,9 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" + "gioui.org/text" "gioui.org/unit" "gioui.org/widget" - "gioui.org/widget/material" ) type Menu struct { @@ -33,6 +33,7 @@ type MenuStyle struct { FontSize unit.Sp IconSize unit.Dp HoverColor color.NRGBA + Shaper *text.Shaper } type MenuItem struct { @@ -97,11 +98,11 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { iconColor = mediumEmphasisTextColor } iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)} - textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor} + textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor, Shaper: m.Shaper} if item.Disabled { textLabel.Color = mediumEmphasisTextColor } - shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor} + shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor, Shaper: m.Shaper} shortcutInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(12), Bottom: unit.Dp(2), Top: unit.Dp(2)} dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -147,7 +148,7 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { return popup.Layout(gtx, contents) } -func PopupMenu(th *material.Theme, menu *Menu) MenuStyle { +func (t *Tracker) PopupMenu(menu *Menu) MenuStyle { return MenuStyle{ Menu: menu, IconColor: white, @@ -156,5 +157,6 @@ func PopupMenu(th *material.Theme, menu *Menu) MenuStyle { FontSize: unit.Sp(16), IconSize: unit.Dp(16), HoverColor: menuHoverColor, + Shaper: t.TextShaper, } } diff --git a/tracker/gioui/ordereditor.go b/tracker/gioui/ordereditor.go index 9315110..23a80dd 100644 --- a/tracker/gioui/ordereditor.go +++ b/tracker/gioui/ordereditor.go @@ -194,7 +194,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D { } else { title = "?" } - LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx) + LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: t.TextShaper}.Layout(gtx) return D{Size: gtx.Constraints.Min} } style := FilledDragList(t.Theme, oe.titleList, len(t.Song().Score.Tracks), elem, t.SwapTracks) @@ -211,7 +211,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D { paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}.Op()) } paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) stack := op.Offset(image.Pt(patternRowMarkerWidth, 0)).Push(gtx.Ops) for i, track := range t.Song().Score.Tracks { paint.FillShape(gtx.Ops, patternCellColor, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(patternCellWidth-1, patternCellHeight-1)}.Op()) @@ -220,7 +220,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D { gtx := gtx gtx.Constraints.Max.X = patternCellWidth op.Offset(image.Pt(0, -2)).Add(gtx.Ops) - widget.Label{Alignment: text.Middle}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j]), op.CallOp{}) + widget.Label{Alignment: text.Middle}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j]), op.CallOp{}) op.Offset(image.Pt(0, 2)).Add(gtx.Ops) } point := tracker.ScorePoint{Track: i, ScoreRow: tracker.ScoreRow{Pattern: j}} diff --git a/tracker/gioui/parameditor.go b/tracker/gioui/parameditor.go index 62b69d0..69d0d16 100644 --- a/tracker/gioui/parameditor.go +++ b/tracker/gioui/parameditor.go @@ -199,7 +199,7 @@ func (pe *ParamEditor) layoutUnitFooter(t *Tracker) layout.Widget { } else { text = strings.Title(text) } - hintText := Label(text, white) + hintText := Label(text, white, t.TextShaper) return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(deleteUnitBtnStyle.Layout), layout.Rigid(copyUnitBtnStyle.Layout), @@ -226,7 +226,7 @@ func (pe *ParamEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D { if t.InstrumentEditor.unitTypeEditor.Focused() && !strings.HasPrefix(text, t.InstrumentEditor.unitTypeEditor.Text()) { return D{} } - labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12)} + labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper} bg := func(gtx C) D { gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, 20)) var color color.NRGBA diff --git a/tracker/gioui/parameter.go b/tracker/gioui/parameter.go index 1548187..f68beec 100644 --- a/tracker/gioui/parameter.go +++ b/tracker/gioui/parameter.go @@ -52,7 +52,7 @@ func (p ParameterStyle) Layout(gtx C) D { layout.Rigid(func(gtx C) D { return p.ParameterWidget.labelBtn.Layout(gtx, func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(unit.Dp(110)) - return layout.E.Layout(gtx, Label(p.Parameter.Name, white)) + return layout.E.Layout(gtx, Label(p.Parameter.Name, white, p.tracker.TextShaper)) }) }), layout.Rigid(func(gtx C) D { @@ -154,7 +154,7 @@ func (p ParameterStyle) Layout(gtx C) D { }), layout.Rigid(func(gtx C) D { if p.Parameter.Type != tracker.IDParameter { - return Label(p.Parameter.Hint, white)(gtx) + return Label(p.Parameter.Hint, white, p.tracker.TextShaper)(gtx) } return D{} }), diff --git a/tracker/gioui/rowmarkers.go b/tracker/gioui/rowmarkers.go index 4e0dca0..1646c9a 100644 --- a/tracker/gioui/rowmarkers.go +++ b/tracker/gioui/rowmarkers.go @@ -43,7 +43,7 @@ func (t *Tracker) layoutRowMarkers(gtx C) D { } if j == 0 { paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i)), op.CallOp{}) } if t.TrackEditor.Focused() && songRow == cursorSongRow { paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops) @@ -51,7 +51,7 @@ func (t *Tracker) layoutRowMarkers(gtx C) D { paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops) } op.Offset(image.Pt(rowMarkerWidth/2, 0)).Add(gtx.Ops) - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) op.Offset(image.Pt(-rowMarkerWidth/2, trackRowHeight)).Add(gtx.Ops) } } diff --git a/tracker/gioui/songpanel.go b/tracker/gioui/songpanel.go index acf5701..d0bda4e 100644 --- a/tracker/gioui/songpanel.go +++ b/tracker/gioui/songpanel.go @@ -44,7 +44,7 @@ func (t *Tracker) layoutMenu(title string, clickable *widget.Clickable, menu *Me for clickable.Clicked() { menu.Visible = true } - m := PopupMenu(t.Theme, menu) + m := t.PopupMenu(menu) return func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() titleBtn := material.Button(t.Theme, clickable, title) @@ -145,7 +145,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("LEN:", white)), + layout.Rigid(Label("LEN:", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { t.SongLength.Value = t.Song().Score.Length numStyle := NumericUpDown(t.Theme, t.SongLength, 1, math.MaxInt32, "Song length") @@ -159,7 +159,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("BPM:", white)), + layout.Rigid(Label("BPM:", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { t.BPM.Value = t.Song().BPM numStyle := NumericUpDown(t.Theme, t.BPM, 1, 999, "Beats per minute") @@ -173,7 +173,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("RPP:", white)), + layout.Rigid(Label("RPP:", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { t.RowsPerPattern.Value = t.Song().Score.RowsPerPattern numStyle := NumericUpDown(t.Theme, t.RowsPerPattern, 1, 255, "Rows per pattern") @@ -187,7 +187,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("RPB:", white)), + layout.Rigid(Label("RPB:", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { t.RowsPerBeat.Value = t.Song().RowsPerBeat numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32, "Rows per beat") @@ -201,7 +201,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("STP:", white)), + layout.Rigid(Label("STP:", white, t.TextShaper)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { numStyle := NumericUpDown(t.Theme, t.Step, 0, 8, "Cursor step") numStyle.UnitsPerStep = unit.Dp(20) diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index 2c03f58..993898a 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -9,7 +9,6 @@ import ( ) var fontCollection []text.FontFace = gofont.Collection() -var textShaper = text.NewShaper(text.WithCollection(fontCollection)) var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255} var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255} diff --git a/tracker/gioui/trackeditor.go b/tracker/gioui/trackeditor.go index 6dc2819..488d9cd 100644 --- a/tracker/gioui/trackeditor.go +++ b/tracker/gioui/trackeditor.go @@ -253,7 +253,7 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions layout.Rigid(subtractOctaveBtnStyle.Layout), layout.Rigid(noteOffBtnStyle.Layout), layout.Rigid(hexCheckBoxStyle.Layout), - layout.Rigid(Label(" Voices:", white)), + layout.Rigid(Label(" Voices:", white, t.TextShaper)), layout.Rigid(voiceUpDown), layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }), layout.Rigid(deleteTrackBtnStyle.Layout), @@ -388,7 +388,7 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D { } } gtx.Constraints.Max.X = trackColWidth - LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx) + LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: t.TextShaper}.Layout(gtx) op.Offset(image.Point{trackColWidth, 0}).Add(gtx.Ops) curVoice += trk.NumVoices } @@ -461,11 +461,11 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D { } if s >= 0 && patRow == 0 { paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{}) } if s >= 0 && patRow == 1 && t.IsPatternUnique(trkIndex, s) { paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, "*", op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, "*", op.CallOp{}) } op.Offset(image.Point{patmarkWidth, 0}).Add(gtx.Ops) if te.Focused() && t.Cursor().Row == patRow && t.Cursor().Pattern == pat { @@ -487,9 +487,9 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D { default: text = fmt.Sprintf("%02x", c) } - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(text), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(text), op.CallOp{}) } else { - widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, noteStr(c), op.CallOp{}) + widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, noteStr(c), op.CallOp{}) } op.Offset(image.Point{-patmarkWidth, trackRowHeight}).Add(gtx.Ops) } diff --git a/tracker/gioui/tracker.go b/tracker/gioui/tracker.go index a44994a..1daaebc 100644 --- a/tracker/gioui/tracker.go +++ b/tracker/gioui/tracker.go @@ -11,6 +11,7 @@ import ( "gioui.org/io/system" "gioui.org/layout" "gioui.org/op" + "gioui.org/text" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" @@ -55,6 +56,8 @@ type Tracker struct { TrackEditor *TrackEditor Explorer *explorer.Explorer + TextShaper *text.Shaper + lastAvgVolume tracker.Volume lastPeakVolume tracker.Volume @@ -153,6 +156,8 @@ func NewTracker(model *tracker.Model, synther sointu.Synther) *Tracker { marshalRecoveryChannel: make(chan (chan []byte)), unmarshalRecoveryChannel: make(chan []byte), } + t.TextShaper = text.NewShaper(text.WithCollection(fontCollection)) + t.Alert.shaper = t.TextShaper t.Theme.Palette.Fg = primaryColor t.Theme.Palette.ContrastFg = black t.TrackEditor.Focus()