From de10cde63033dd482b8e1ad0eefc6c87dc0802a5 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 27 Feb 2023 12:48:44 -0500 Subject: [PATCH] Add image textures to theme --- artist/patterns/border.go | 4 +- artist/patterns/texture.go | 7 +-- elements/basic/textbox.go | 12 ++--- theme/assets/wintergreen.png | Bin 0 -> 2289 bytes theme/default.go | 92 +++++++++++++++++++++++++++++------ 5 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 theme/assets/wintergreen.png diff --git a/artist/patterns/border.go b/artist/patterns/border.go index 2723aa3..3202a0b 100644 --- a/artist/patterns/border.go +++ b/artist/patterns/border.go @@ -44,9 +44,7 @@ func (pattern Border) Draw (destination canvas.Canvas, clip image.Rectangle) { srcSections := nonasect(pattern.Bounds(), pattern.Inset) srcTextures := [9]Texture { } for index, section := range srcSections { - srcTextures[index] = Texture { - Canvas: canvas.Cut(pattern, section), - } + srcTextures[index].Canvas = canvas.Cut(pattern, section) } dstSections := nonasect(destination.Bounds(), pattern.Inset) diff --git a/artist/patterns/texture.go b/artist/patterns/texture.go index 5a97b8b..3c0b374 100644 --- a/artist/patterns/texture.go +++ b/artist/patterns/texture.go @@ -12,7 +12,8 @@ type Texture struct { // Draw tiles the pattern's canvas within the clipping bounds. The minimum // points of the pattern's canvas and the destination canvas will be lined up. func (pattern Texture) Draw (destination canvas.Canvas, clip image.Rectangle) { - bounds := clip.Canon().Intersect(destination.Bounds()) + realBounds := destination.Bounds() + bounds := clip.Canon().Intersect(realBounds) if bounds.Empty() { return } dstData, dstStride := destination.Buffer() @@ -23,8 +24,8 @@ func (pattern Texture) Draw (destination canvas.Canvas, clip image.Rectangle) { for x := bounds.Min.X; x < bounds.Max.X; x ++ { dstIndex := x + y * dstStride srcIndex := - wrap(x - bounds.Min.X, srcBounds.Min.X, srcBounds.Max.X) + - wrap(x - bounds.Min.Y, srcBounds.Min.Y, srcBounds.Max.Y) * srcStride + wrap(x - realBounds.Min.X, srcBounds.Min.X, srcBounds.Max.X) + + wrap(y - realBounds.Min.Y, srcBounds.Min.Y, srcBounds.Max.Y) * srcStride dstData[dstIndex] = srcData[srcIndex] }} } diff --git a/elements/basic/textbox.go b/elements/basic/textbox.go index 885cdae..1f99460 100644 --- a/elements/basic/textbox.go +++ b/elements/basic/textbox.go @@ -93,7 +93,7 @@ func (element *TextBox) HandleMouseMove (x, y int) { } func (element *TextBox) atPosition (position image.Point) int { - padding := element.theme.Padding(theme.PatternSunken) + padding := element.theme.Padding(theme.PatternInput) offset := element.Bounds().Min.Add (image.Pt ( padding[artist.SideLeft] - element.scroll, padding[artist.SideTop])) @@ -253,7 +253,7 @@ func (element *TextBox) ScrollViewportBounds () (bounds image.Rectangle) { } func (element *TextBox) scrollViewportWidth () (width int) { - padding := element.theme.Padding(theme.PatternSunken) + padding := element.theme.Padding(theme.PatternInput) return padding.Apply(element.Bounds()).Dx() } @@ -293,7 +293,7 @@ func (element *TextBox) runOnChange () { func (element *TextBox) scrollToCursor () { if !element.core.HasImage() { return } - padding := element.theme.Padding(theme.PatternSunken) + padding := element.theme.Padding(theme.PatternInput) bounds := padding.Apply(element.Bounds()) bounds = bounds.Sub(bounds.Min) bounds.Max.X -= element.valueDrawer.Em().Round() @@ -333,7 +333,7 @@ func (element *TextBox) SetConfig (new config.Config) { func (element *TextBox) updateMinimumSize () { textBounds := element.placeholderDrawer.LayoutBounds() - padding := element.theme.Padding(theme.PatternSunken) + padding := element.theme.Padding(theme.PatternInput) element.core.SetMinimumSize ( padding.Horizontal() + textBounds.Dx(), padding.Vertical() + @@ -354,8 +354,8 @@ func (element *TextBox) draw () { Disabled: !element.Enabled(), Focused: element.Focused(), } - pattern := element.theme.Pattern(theme.PatternSunken, state) - padding := element.theme.Padding(theme.PatternSunken) + pattern := element.theme.Pattern(theme.PatternInput, state) + padding := element.theme.Padding(theme.PatternInput) innerCanvas := canvas.Cut(element.core, padding.Apply(bounds)) pattern.Draw(element.core, bounds) diff --git a/theme/assets/wintergreen.png b/theme/assets/wintergreen.png new file mode 100644 index 0000000000000000000000000000000000000000..2abe477b4319a2a1733bda505866a42d1e6e6c3a GIT binary patch literal 2289 zcmYjTd03M97XE#JewYZPj$43GP1((Bj@zgSg5pSvNok{LCY4(jX62qD1f`a_v}x8P zrlu{@WLap7pG$?4shLSGCElr|Xwq>l4ZY0$>;7?`_dVx%-uFGv`Rn9xH~AVZvRVWH zFj~i9Z_%MpS5hn*07$Z-Vwrw3}f6G*4*F?S!knh65PyZ^R5 zc6rT?Pjx}$_Pq@)bE~#k_!Ul^=?ryJ?#%sj!VQ3c(b)q-;&IU7a>iX!^p1DiiR=K^q25VC+s%(5c&t6~hexEa<)I@$c>=@iB4RPYV z97Tr>gzvJqTf%m8TCsdJ$qbj2=k*lO5){(g`Yl|4Y*>)L{%k+(4z|n(+wqD&=S)-Y zweM0sky4`YiORB_4ZgS-Q?iv$m~zzWanRa)ukcP%T%2jP_X*d*xO>UpcGlFlwfDf6 zwmMe3^%X5rRgO;8MR(z}4Xjsz&-C|ILd|QmBO+PZkfTL_{$>fuGgm>N=X&{_=yr@3 zWG`{`l<2#Wmj8!ZxUw=@<=SdQ%Ic!Fv8q!NJFB=P33u`L)Q6H^h(teoE@`QLi;DO! zT0@)*SD8wZr%6r)$z0=QyvFb~vc;|*D4c0lHfz9La{Ricj~O;{Ku!|bBmd@Gl>%v|ephDbuXjFVd`XuAr>&KbhN7@oWXc!1L2v;=os{vg zIe3`yNqnErqBzAl{5YXv6hC%Vh#$QyHQ#A5wNDlVsDyEd^L@CEHnZ9K^-N@hono+_ zy6h0^Lx-N_c|%KJ-*}Y}lj%TEZx?!SI*uORd%TcmH(4|9K?vBE_4i#AI7G7+wnHg= zMTQq4f=!5!Q54w}#ddnZV!8qdQv$5J1fRrNdmq2m2i=QT4MTqA@McbtZ{wS0%&2!J z3Be2#nKx~mV6e{=4+X}W!k`CRB4{BF*0W2fE!afJ0~Ykx1l1(Z6T#fU5!Fo} zQ@LB#4V1u^K$BXa&w0nfBe9eU$T*bwR?GgiJr7sx6o_GKepWHoCQiDz#<*{z0(pC?P< z$~O_CK$tiTgkk1MXrzIt*YzA7%{&gFNnPg|(>$nJq7<1&z?Q>^p%<+YrQ|MTZ$aHEuP;h*e&>km!p1q7<# z?}p&~_<4)LfVrU^8wRp4W69rxp)psDTOrc1{KwG`=0mIfN~{g@_g?e34}91w@p=L>@f7yX4j=n)g@6rx8P(}-4k zsa~P?uZ&Nmt2BswGwd*}*CU`~4wmB;3D{~a1$BVzdK4+aU-aVn!5s!o$MF|UkI3;4 z#K?PhrgHCa-54XXQJc;zZV8y^#FQ;Ee(@aN<6D8!2v<-)EA^)K)Nu(!&qF}adc@RZ zP7j5SK!`MZjgZ#GV&C^bJ<=wjf?+$FFi~Z!BMfig?8p1V@;B!dnA>;@RP`Rz^!01g znLnPuq|Y^m!*XTw+!<{WSv9RGo$Wb)oj8`1BxP8=4~CtfeK#pc;|S^N2SXZl+7J`M zX?F4A^+Mj#qZP3e*ss$A20XG{0(wOousrft9Mt0^S{0qpTTE6p(|A&r|^=;5jLGW-O30fY~*h~{sVN!s!{{_fEv4P7+$peG`I?PtYm%?O&AoU zsZ223ttB$pRMdZXq4XxK{)Vg|r#yWm9L6eeWMpx{{@3RA7sU?Va6JBxpG_;*p#tGe zE18L^1RZ(n51h}Jp?l^Rx}kG#&2{N1;mDVFqMQs?pUGT=U&;lm@EwNnTT9-W+n}od zXkQ9Wyx4?_2#;q#wQF2UL7#d05v1rIf%DnW6dIae=r_+@lBgn&pmB!-qtu|zGmU}h zVs(4C*$n;e=4UK*k9UWzp{q=!?qdQ}bsLT>on9!$e}|GTRJqD&eoJ+~3s~o~i7oTu G9r-UUI0GdB literal 0 HcmV?d00001 diff --git a/theme/default.go b/theme/default.go index da0e868..ae9f482 100644 --- a/theme/default.go +++ b/theme/default.go @@ -1,6 +1,9 @@ package theme import "image" +import "bytes" +import _ "embed" +import _ "image/png" import "image/color" import "golang.org/x/image/font" import "git.tebibyte.media/sashakoshka/tomo/artist" @@ -8,6 +11,47 @@ import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/defaultfont" import "git.tebibyte.media/sashakoshka/tomo/artist/patterns" +//go:embed assets/wintergreen.png +var defaultAtlasBytes []byte +var defaultAtlas canvas.Canvas +var defaultTextures [8][10]artist.Pattern + +func atlasCell (col, row int, border artist.Inset) { + bounds := image.Rect(0, 0, 16, 16).Add(image.Pt(col, row).Mul(16)) + defaultTextures[col][row] = patterns.Border { + Canvas: canvas.Cut(defaultAtlas, bounds), + Inset: border, + } +} + +func atlasCol (col int, border artist.Inset) { + for index, _ := range defaultTextures[col] { + atlasCell(col, index, border) + } +} + +func init () { + defaultAtlasImage, _, _ := image.Decode(bytes.NewReader(defaultAtlasBytes)) + defaultAtlas = canvas.FromImage(defaultAtlasImage) + + // PatternDead + atlasCol(0, artist.Inset { }) + // PatternRaised + atlasCol(1, artist.Inset { 6, 6, 6, 6 }) + // PatternSunken + atlasCol(2, artist.Inset { 4, 4, 4, 4 }) + // PatternPinboard + atlasCol(3, artist.Inset { 2, 2, 2, 2 }) + // PatternButton + atlasCol(4, artist.Inset { 6, 6, 6, 6 }) + // PatternInput + atlasCol(5, artist.Inset { 4, 4, 4, 4 }) + // PatternGutter + atlasCol(6, artist.Inset { 4, 4, 4, 4 }) + // PatternHandle + atlasCol(7, artist.Inset { 6, 6, 6, 6 }) +} + // Default is the default theme. type Default struct { } @@ -34,36 +78,52 @@ func (Default) Icon (string, IconSize, Case) canvas.Image { // Pattern returns a pattern from the default theme corresponding to the given // pattern ID. func (Default) Pattern (id Pattern, state State, c Case) artist.Pattern { + offset := 0; switch { + case state.Disabled: offset = 1 + case state.Focused && state.Pressed: offset = 6 + case state.Focused && state.On: offset = 7 + case state.Invalid && state.Pressed: offset = 8 + case state.Invalid && state.On: offset = 9 + case state.Invalid: offset = 5 + case state.Focused: offset = 4 + case state.Pressed: offset = 2 + case state.On: offset = 3 + } + switch id { - case PatternBackground: return patterns.Uhex(0x000000FF) - // case PatternDead: - // case PatternRaised: - // case PatternSunken: - // case PatternPinboard: - // case PatternButton: - // case PatternInput: - // case PatternGutter: - // case PatternHandle: - default: return patterns.Uhex(0x888888FF) + case PatternBackground: return patterns.Uhex(0xaaaaaaFF) + case PatternDead: return defaultTextures[0][offset] + case PatternRaised: return defaultTextures[1][offset] + case PatternSunken: return defaultTextures[2][offset] + case PatternPinboard: return defaultTextures[3][offset] + case PatternButton: return defaultTextures[4][offset] + case PatternInput: return defaultTextures[5][offset] + case PatternGutter: return defaultTextures[6][offset] + case PatternHandle: return defaultTextures[7][offset] + default: return patterns.Uhex(0xFF00FFFF) } } func (Default) Color (id Color, state State, c Case) color.RGBA { - switch id { - case ColorAccent: return artist.Hex(0xFF8800FF) - case ColorForeground: return artist.Hex(0xFFFFFFFF) - default: return artist.Hex(0x888888FF) + if state.Disabled { + return artist.Hex(0x444444FF) + } else { + switch id { + case ColorAccent: return artist.Hex(0x408090FF) + case ColorForeground: return artist.Hex(0x000000FF) + default: return artist.Hex(0x888888FF) + } } } // Padding returns the default padding value for the given pattern. func (Default) Padding (pattern Pattern, c Case) artist.Inset { - return artist.Inset { 4, 4, 4, 4} + return artist.Inset { 8, 8, 8, 8 } } // Margin returns the default margin value for the given pattern. func (Default) Margin (id Pattern, c Case) image.Point { - return image.Pt(4, 4) + return image.Pt(8, 8) } // Hints returns rendering optimization hints for a particular pattern.