v/vlib/gg/image.v

147 lines
3.0 KiB
V
Raw Normal View History

2020-08-05 03:15:37 +02:00
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
module gg
import os
import sokol
import sokol.sgl
import stbi
pub struct Image {
pub mut:
width int
height int
nr_channels int
ok bool
data voidptr
ext string
path string
2020-08-05 07:42:29 +02:00
cache_slot &ImageCacheSlot = 0
2020-08-05 03:15:37 +02:00
}
2020-08-05 07:09:25 +02:00
//
struct ImageCacheSlot {
2020-08-05 07:42:29 +02:00
id int
mut:
is_simg_ok bool
simg C.sg_image
}
fn (mut cs ImageCacheSlot) set_sokol_image(simg C.sg_image) {
cs.simg = simg
cs.is_simg_ok = true
2020-08-05 07:09:25 +02:00
}
2020-08-05 07:42:29 +02:00
//
2020-08-05 07:09:25 +02:00
[ref_only]
2020-08-05 03:15:37 +02:00
struct ImageCache {
mut:
2020-08-05 07:09:25 +02:00
current_image_id int = -1
slots []ImageCacheSlot
2020-08-05 03:15:37 +02:00
}
2020-08-05 07:42:29 +02:00
fn (ic &ImageCache) get_new_cache_slot() &ImageCacheSlot {
2020-08-05 07:09:25 +02:00
mut mic := &ImageCache(0)
unsafe {
mic = ic
}
mic.current_image_id++
mic.slots << ImageCacheSlot {
id: mic.current_image_id
2020-08-05 07:42:29 +02:00
is_simg_ok: false
2020-08-05 07:09:25 +02:00
}
2020-08-05 07:42:29 +02:00
return &mic.slots[mic.slots.len-1]
2020-08-05 07:09:25 +02:00
}
const (
2020-08-05 07:42:29 +02:00
image_cache = &ImageCache{}
2020-08-05 07:09:25 +02:00
)
//
2020-08-05 03:15:37 +02:00
pub fn create_image(file string) Image {
if !os.exists(file) {
println('gg.create_image(): file not found: $file')
return Image{} // none
}
stb_img := stbi.load(file)
mut img := Image{
width: stb_img.width
height: stb_img.height
nr_channels: stb_img.nr_channels
ok: stb_img.ok
data: stb_img.data
ext: stb_img.ext
path: file
2020-08-05 07:42:29 +02:00
cache_slot: image_cache.get_new_cache_slot()
2020-08-05 03:15:37 +02:00
}
return img
}
pub fn create_image_from_memory(buf byteptr, bufsize int) Image {
stb_img := stbi.load_from_memory(buf, bufsize)
mut img := Image{
width: stb_img.width
height: stb_img.height
nr_channels: stb_img.nr_channels
ok: stb_img.ok
data: stb_img.data
ext: stb_img.ext
2020-08-05 07:42:29 +02:00
cache_slot: image_cache.get_new_cache_slot()
2020-08-05 03:15:37 +02:00
}
return img
}
pub fn create_image_from_byte_array(b []byte) Image {
return create_image_from_memory(b.data, b.len)
}
2020-08-05 07:09:25 +02:00
pub fn (img &Image) new_sokol_image() C.sg_image {
//eprintln('> new_sokol_image from img: $img')
2020-08-05 03:15:37 +02:00
mut img_desc := C.sg_image_desc{
width: img.width
height: img.height
num_mipmaps: 0
wrap_u: .clamp_to_edge
wrap_v: .clamp_to_edge
label: &byte(0)
d3d11_texture: 0
}
img_desc.content.subimage[0][0] = C.sg_subimage_content{
ptr: img.data
size: img.nr_channels * img.width * img.height
}
2020-08-05 07:09:25 +02:00
simg := C.sg_make_image(&img_desc)
return simg
2020-08-05 03:15:37 +02:00
}
2020-08-05 07:09:25 +02:00
pub fn (img &Image) get_sokol_image() C.sg_image {
2020-08-05 07:42:29 +02:00
slot := img.cache_slot
if slot.is_simg_ok {
2020-08-05 07:09:25 +02:00
return slot.simg
2020-08-05 03:15:37 +02:00
}
2020-08-05 07:09:25 +02:00
simg := img.new_sokol_image()
2020-08-05 07:42:29 +02:00
unsafe {
mut cs := slot
cs.set_sokol_image(simg)
}
2020-08-05 07:09:25 +02:00
return simg
2020-08-05 03:15:37 +02:00
}
pub fn (ctx &Context) draw_image(x, y, width, height f32, img &Image) {
2020-08-05 07:09:25 +02:00
simg := img.get_sokol_image()
2020-08-05 03:15:37 +02:00
u0 := f32(0.0)
v0 := f32(0.0)
u1 := f32(1.0)
v1 := f32(1.0)
x0 := f32(x) * ctx.scale
y0 := f32(y) * ctx.scale
x1 := f32(x + width) * ctx.scale
y1 := f32(y + height) * ctx.scale
//
sgl.load_pipeline(ctx.timage_pip)
sgl.enable_texture()
2020-08-05 07:09:25 +02:00
sgl.texture(simg)
2020-08-05 03:15:37 +02:00
sgl.begin_quads()
sgl.c4b(255, 255, 255, 255)
sgl.v2f_t2f(x0, y0, u0, v0)
sgl.v2f_t2f(x1, y0, u1, v0)
sgl.v2f_t2f(x1, y1, u1, v1)
sgl.v2f_t2f(x0, y1, u0, v1)
sgl.end()
sgl.disable_texture()
}