From a5e335819d035281af1f41a5d3187b2e182bb777 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 18 Jan 2015 14:31:21 +0900 Subject: [PATCH] Add example/internal and move font rendering into it --- .../{blocks/font.png => arcadefont.png} | Bin _docs/public/example/images/license.md | 2 +- example/blocks/blocks/font.go | 90 +------------- example/blocks/blocks/gamescene.go | 5 +- example/blocks/blocks/titlescene.go | 9 +- .../{blocks/font.png => arcadefont.png} | Bin example/images/license.md | 2 +- example/internal/font.go | 111 ++++++++++++++++++ 8 files changed, 126 insertions(+), 93 deletions(-) rename _docs/public/example/images/{blocks/font.png => arcadefont.png} (100%) rename example/images/{blocks/font.png => arcadefont.png} (100%) create mode 100644 example/internal/font.go diff --git a/_docs/public/example/images/blocks/font.png b/_docs/public/example/images/arcadefont.png similarity index 100% rename from _docs/public/example/images/blocks/font.png rename to _docs/public/example/images/arcadefont.png diff --git a/_docs/public/example/images/license.md b/_docs/public/example/images/license.md index 2c2bb03c7..6c7ad47f8 100644 --- a/_docs/public/example/images/license.md +++ b/_docs/public/example/images/license.md @@ -1,6 +1,6 @@ # License -## blocks/font.png +## arcadefont.png ``` 9031 Font ReadMe diff --git a/example/blocks/blocks/font.go b/example/blocks/blocks/font.go index c935c5020..76ba71707 100644 --- a/example/blocks/blocks/font.go +++ b/example/blocks/blocks/font.go @@ -16,98 +16,18 @@ package blocks import ( "github.com/hajimehoshi/ebiten" - "github.com/hajimehoshi/ebiten/ebitenutil" + "github.com/hajimehoshi/ebiten/example/internal" "image/color" - "math" - "strings" ) -var imageFont *ebiten.Image - -func init() { - var err error - imageFont, _, err = ebitenutil.NewImageFromFile("images/blocks/font.png", ebiten.FilterNearest) - if err != nil { - panic(err) - } -} - -const charWidth = 8 -const charHeight = 8 - -func textWidth(str string) int { - // TODO: Take care about '\n' - return charWidth * len(str) -} - -type fontImageParts string - -func (f fontImageParts) Len() int { - return len(f) -} - -func (f fontImageParts) Dst(i int) (x0, y0, x1, y1 int) { - x := i - strings.LastIndex(string(f)[:i], "\n") - 1 - y := strings.Count(string(f)[:i], "\n") - x *= charWidth - y *= charHeight - if x < 0 { - return 0, 0, 0, 0 - } - return x, y, x + charWidth, y + charHeight -} - -func (f fontImageParts) Src(i int) (x0, y0, x1, y1 int) { - code := int(f[i]) - if code == '\n' { - return 0, 0, 0, 0 - } - x := (code % 16) * charWidth - y := ((code - 32) / 16) * charHeight - return x, y, x + charWidth, y + charHeight -} - -func drawText(rt *ebiten.Image, str string, ox, oy, scale int, c color.Color) error { - options := &ebiten.DrawImageOptions{ - ImageParts: fontImageParts(str), - } - options.GeoM.Scale(float64(scale), float64(scale)) - options.GeoM.Translate(float64(ox), float64(oy)) - - ur, ug, ub, ua := c.RGBA() - const max = math.MaxUint16 - r := float64(ur) / max - g := float64(ug) / max - b := float64(ub) / max - a := float64(ua) / max - if 0 < a { - r /= a - g /= a - b /= a - } - options.ColorM.Scale(r, g, b, a) - - return rt.DrawImage(imageFont, options) -} - -func drawTextWithShadow(rt *ebiten.Image, str string, x, y, scale int, clr color.Color) error { - if err := drawText(rt, str, x+1, y+1, scale, color.NRGBA{0, 0, 0, 0x80}); err != nil { - return err - } - if err := drawText(rt, str, x, y, scale, clr); err != nil { - return err - } - return nil -} - func drawTextWithShadowCenter(rt *ebiten.Image, str string, x, y, scale int, clr color.Color, width int) error { - w := textWidth(str) * scale + w := internal.ArcadeFont.TextWidth(str) * scale x += (width - w) / 2 - return drawTextWithShadow(rt, str, x, y, scale, clr) + return internal.ArcadeFont.DrawTextWithShadow(rt, str, x, y, scale, clr) } func drawTextWithShadowRight(rt *ebiten.Image, str string, x, y, scale int, clr color.Color, width int) error { - w := textWidth(str) * scale + w := internal.ArcadeFont.TextWidth(str) * scale x += width - w - return drawTextWithShadow(rt, str, x, y, scale, clr) + return internal.ArcadeFont.DrawTextWithShadow(rt, str, x, y, scale, clr) } diff --git a/example/blocks/blocks/gamescene.go b/example/blocks/blocks/gamescene.go index fcebcb6ac..96f9c9d9b 100644 --- a/example/blocks/blocks/gamescene.go +++ b/example/blocks/blocks/gamescene.go @@ -17,6 +17,7 @@ package blocks import ( "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" + "github.com/hajimehoshi/ebiten/example/internal" "image/color" _ "image/jpeg" "math/rand" @@ -84,7 +85,7 @@ func init() { } // Windows: Next x, y = nextWindowLabelPosition() - if err := drawTextWithShadow(imageWindows, "NEXT", x, y, 1, fontColor); err != nil { + if err := internal.ArcadeFont.DrawTextWithShadow(imageWindows, "NEXT", x, y, 1, fontColor); err != nil { panic(err) } x, y = nextWindowPosition() @@ -126,7 +127,7 @@ func drawWindow(r *ebiten.Image, x, y, width, height int) error { var fontColor = color.NRGBA{0x40, 0x40, 0xff, 0xff} func drawTextBox(r *ebiten.Image, label string, x, y, width int) error { - if err := drawTextWithShadow(r, label, x, y, 1, fontColor); err != nil { + if err := internal.ArcadeFont.DrawTextWithShadow(r, label, x, y, 1, fontColor); err != nil { return err } y += blockWidth diff --git a/example/blocks/blocks/titlescene.go b/example/blocks/blocks/titlescene.go index 2ae20fcf9..371a40572 100644 --- a/example/blocks/blocks/titlescene.go +++ b/example/blocks/blocks/titlescene.go @@ -17,6 +17,7 @@ package blocks import ( "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" + "github.com/hajimehoshi/ebiten/example/internal" "image/color" ) @@ -83,9 +84,9 @@ func (s *TitleScene) Draw(r *ebiten.Image) error { } message := "PRESS SPACE TO START" - x := (ScreenWidth - textWidth(message)) / 2 + x := (ScreenWidth - internal.ArcadeFont.TextWidth(message)) / 2 y := ScreenHeight - 48 - return drawTextWithShadow(r, message, x, y, 1, color.NRGBA{0x80, 0, 0, 0xff}) + return internal.ArcadeFont.DrawTextWithShadow(r, message, x, y, 1, color.NRGBA{0x80, 0, 0, 0xff}) } func (s *TitleScene) drawTitleBackground(r *ebiten.Image, c int) error { @@ -97,8 +98,8 @@ func (s *TitleScene) drawTitleBackground(r *ebiten.Image, c int) error { func drawLogo(r *ebiten.Image, str string) error { scale := 4 - textWidth := textWidth(str) * scale + textWidth := internal.ArcadeFont.TextWidth(str) * scale x := (ScreenWidth - textWidth) / 2 y := 32 - return drawTextWithShadow(r, str, x, y, scale, color.NRGBA{0x00, 0x00, 0x80, 0xff}) + return internal.ArcadeFont.DrawTextWithShadow(r, str, x, y, scale, color.NRGBA{0x00, 0x00, 0x80, 0xff}) } diff --git a/example/images/blocks/font.png b/example/images/arcadefont.png similarity index 100% rename from example/images/blocks/font.png rename to example/images/arcadefont.png diff --git a/example/images/license.md b/example/images/license.md index 2c2bb03c7..6c7ad47f8 100644 --- a/example/images/license.md +++ b/example/images/license.md @@ -1,6 +1,6 @@ # License -## blocks/font.png +## arcadefont.png ``` 9031 Font ReadMe diff --git a/example/internal/font.go b/example/internal/font.go new file mode 100644 index 000000000..c8a81ebea --- /dev/null +++ b/example/internal/font.go @@ -0,0 +1,111 @@ +// Copyright 2015 Hajime Hoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import ( + "github.com/hajimehoshi/ebiten" + "github.com/hajimehoshi/ebiten/ebitenutil" + "image/color" + "math" + "strings" +) + +var ( + ArcadeFont *Font +) + +type Font struct { + image *ebiten.Image + offset int + charNumPerLine int + charWidth int + charHeight int +} + +func (f *Font) TextWidth(str string) int { + // TODO: Take care about '\n' + return f.charWidth * len(str) +} + +func init() { + arcadeFontImage, _, err := ebitenutil.NewImageFromFile("images/arcadefont.png", ebiten.FilterNearest) + if err != nil { + panic(err) + } + ArcadeFont = &Font{arcadeFontImage, 32, 16, 8, 8} +} + +type fontImageParts struct { + str string + font *Font +} + +func (f *fontImageParts) Len() int { + return len(f.str) +} + +func (f *fontImageParts) Dst(i int) (x0, y0, x1, y1 int) { + x := i - strings.LastIndex(f.str[:i], "\n") - 1 + y := strings.Count(f.str[:i], "\n") + x *= f.font.charWidth + y *= f.font.charHeight + if x < 0 { + return 0, 0, 0, 0 + } + return x, y, x + f.font.charWidth, y + f.font.charHeight +} + +func (f *fontImageParts) Src(i int) (x0, y0, x1, y1 int) { + code := int(f.str[i]) + if code == '\n' { + return 0, 0, 0, 0 + } + x := (code % f.font.charNumPerLine) * f.font.charWidth + y := ((code - f.font.offset) / f.font.charNumPerLine) * f.font.charHeight + return x, y, x + f.font.charWidth, y + f.font.charHeight +} + +func (f *Font) DrawText(rt *ebiten.Image, str string, ox, oy, scale int, c color.Color) error { + options := &ebiten.DrawImageOptions{ + ImageParts: &fontImageParts{str, f}, + } + options.GeoM.Scale(float64(scale), float64(scale)) + options.GeoM.Translate(float64(ox), float64(oy)) + + ur, ug, ub, ua := c.RGBA() + const max = math.MaxUint16 + r := float64(ur) / max + g := float64(ug) / max + b := float64(ub) / max + a := float64(ua) / max + if 0 < a { + r /= a + g /= a + b /= a + } + options.ColorM.Scale(r, g, b, a) + + return rt.DrawImage(f.image, options) +} + +func (f *Font) DrawTextWithShadow(rt *ebiten.Image, str string, x, y, scale int, clr color.Color) error { + if err := f.DrawText(rt, str, x+1, y+1, scale, color.NRGBA{0, 0, 0, 0x80}); err != nil { + return err + } + if err := f.DrawText(rt, str, x, y, scale, clr); err != nil { + return err + } + return nil +}