Set up image resources for the app #230

Merged
savanni merged 3 commits from otg/graphics into main 2024-04-05 13:34:57 +00:00
6 changed files with 105 additions and 56 deletions

View File

@ -3,5 +3,7 @@
<gresource prefix="/com/luminescent-dreams/otg-gtk/">
<file>wood_texture.jpg</file>
<file>style.css</file>
<file>black_stone.png</file>
<file>white_stone.png</file>
</gresource>
</gresources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

After

Width:  |  Height:  |  Size: 698 KiB

View File

@ -37,14 +37,16 @@ You should have received a copy of the GNU General Public License along with On
use crate::perftrace;
use gio::resources_lookup_data;
use glib::Object;
use gtk::{
gdk_pixbuf::{Colorspace, InterpType, Pixbuf},
prelude::*,
subclass::prelude::*,
};
use image::{io::Reader as ImageReader, ImageError};
use otg_core::{Color, Coordinate};
use std::{cell::RefCell, rc::Rc};
use std::{cell::RefCell, io::Cursor, rc::Rc};
const WIDTH: i32 = 800;
const HEIGHT: i32 = 800;
@ -105,29 +107,12 @@ impl Goban {
fn redraw(&self, ctx: &cairo::Context, width: i32, height: i32) {
println!("{} x {}", width, height);
/*
let wood_texture = resources_lookup_data(
let background = load_pixbuf(
"/com/luminescent-dreams/otg-gtk/wood_texture.jpg",
gio::ResourceLookupFlags::NONE,
)
.unwrap();
let background = ImageReader::new(Cursor::new(wood_texture))
.with_guessed_format()
.unwrap()
.decode();
let background = background.map(|background| {
Pixbuf::from_bytes(
&glib::Bytes::from(background.as_bytes()),
gtk::gdk_pixbuf::Colorspace::Rgb,
false,
8,
background.width() as i32,
background.height() as i32,
background.to_rgb8().sample_layout().height_stride as i32,
)
.scale_simple(WIDTH, HEIGHT, InterpType::Nearest)
});
false,
WIDTH + 40,
HEIGHT + 40,
);
match background {
Ok(Some(ref background)) => {
@ -136,10 +121,6 @@ impl Goban {
}
Ok(None) | Err(_) => ctx.set_source_rgb(0.7, 0.7, 0.7),
}
*/
ctx.set_source_rgb(0.7, 0.7, 0.7);
let _ = ctx.paint();
let board = self.imp().board_state.borrow();
@ -148,12 +129,7 @@ impl Goban {
let hspace_between = ((width - 40) as f64) / ((board.size.width - 1) as f64);
let vspace_between = ((height - 40) as f64) / ((board.size.height - 1) as f64);
let pen = Pen {
x_offset: MARGIN as f64,
y_offset: MARGIN as f64,
hspace_between,
vspace_between,
};
let pen = Pen::new(MARGIN as f64, MARGIN as f64, hspace_between, vspace_between);
(0..board.size.width).for_each(|col| {
ctx.move_to(
@ -188,8 +164,8 @@ impl Goban {
(0..board.size.height).for_each(|row| {
(0..board.size.width).for_each(|column| {
match board.stone(&Coordinate{ row, column }) {
None => {},
match board.stone(&Coordinate { row, column }) {
None => {}
Some(Color::White) => pen.stone(ctx, row, column, Color::White, None),
Some(Color::Black) => pen.stone(ctx, row, column, Color::Black, None),
}
@ -203,9 +179,45 @@ struct Pen {
y_offset: f64,
hspace_between: f64,
vspace_between: f64,
black_stone: Pixbuf,
white_stone: Pixbuf,
}
impl Pen {
fn new(x_offset: f64, y_offset: f64, hspace_between: f64, vspace_between: f64) -> Self {
let radius = (hspace_between / 2. - 2.) as i32;
let black_stone = load_pixbuf(
"/com/luminescent-dreams/otg-gtk/black_stone.png",
true,
512,
512,
)
.unwrap()
.unwrap();
let black_stone = black_stone
.scale_simple(radius * 2, radius * 2, InterpType::Nearest)
.unwrap();
let white_stone = load_pixbuf(
"/com/luminescent-dreams/otg-gtk/white_stone.png",
true,
512,
512,
)
.unwrap()
.unwrap();
let white_stone = white_stone
.scale_simple(radius * 2, radius * 2, InterpType::Nearest)
.unwrap();
Pen {
x_offset,
y_offset,
hspace_between,
vspace_between,
black_stone,
white_stone,
}
}
fn star_point(&self, context: &cairo::Context, row: u8, col: u8) {
context.arc(
self.x_offset + (col as f64) * self.hspace_between,
@ -217,20 +229,22 @@ impl Pen {
let _ = context.fill();
}
fn stone(
&self,
context: &cairo::Context,
row: u8,
col: u8,
color: Color,
liberties: Option<u8>,
) {
fn stone(&self, ctx: &cairo::Context, row: u8, col: u8, color: Color, _liberties: Option<u8>) {
let (x_loc, y_loc) = self.stone_location(row, col);
match color {
Color::White => context.set_source_rgb(0.9, 0.9, 0.9),
Color::Black => context.set_source_rgb(0.0, 0.0, 0.0),
Color::White => ctx.set_source_pixbuf(&self.white_stone, x_loc, y_loc),
Color::Black => ctx.set_source_pixbuf(&self.black_stone, x_loc, y_loc),
}
ctx.paint().expect("paint should never fail");
/*
match color {
Color::White => ctx.set_source_rgb(0.9, 0.9, 0.9),
Color::Black => ctx.set_source_rgb(0.0, 0.0, 0.0),
};
self.draw_stone(context, row, col);
self.draw_stone(ctx, row, col);
*/
/*
if let Some(liberties) = liberties {
let stone_location = self.stone_location(row, col);
context.set_source_rgb(1., 0., 1.);
@ -238,28 +252,61 @@ impl Pen {
context.move_to(stone_location.0 - 10., stone_location.1 + 10.);
let _ = context.show_text(&format!("{}", liberties));
}
*/
}
#[allow(dead_code)]
fn ghost_stone(&self, context: &cairo::Context, row: u8, col: u8, color: Color) {
fn ghost_stone(&self, ctx: &cairo::Context, row: u8, col: u8, color: Color) {
match color {
Color::White => context.set_source_rgba(0.9, 0.9, 0.9, 0.5),
Color::Black => context.set_source_rgba(0.0, 0.0, 0.0, 0.5),
Color::White => ctx.set_source_rgba(0.9, 0.9, 0.9, 0.5),
Color::Black => ctx.set_source_rgba(0.0, 0.0, 0.0, 0.5),
};
self.draw_stone(context, row, col);
self.draw_stone(ctx, row, col);
}
fn draw_stone(&self, context: &cairo::Context, row: u8, col: u8) {
fn draw_stone(&self, ctx: &cairo::Context, row: u8, col: u8) {
let radius = self.hspace_between / 2. - 2.;
let (x_loc, y_loc) = self.stone_location(row, col);
context.arc(x_loc, y_loc, radius, 0.0, 2.0 * std::f64::consts::PI);
let _ = context.fill();
ctx.arc(x_loc, y_loc, radius, 0.0, 2.0 * std::f64::consts::PI);
let _ = ctx.fill();
}
fn stone_location(&self, row: u8, col: u8) -> (f64, f64) {
let radius = self.hspace_between / 2. - 2.;
(
self.x_offset + (col as f64) * self.hspace_between,
self.y_offset + (row as f64) * self.vspace_between,
self.x_offset + (col as f64) * self.hspace_between - radius,
self.y_offset + (row as f64) * self.vspace_between - radius,
)
}
}
fn load_pixbuf(
path: &str,
transparency: bool,
width: i32,
height: i32,
) -> Result<Option<Pixbuf>, ImageError> {
let image_bytes = resources_lookup_data(path, gio::ResourceLookupFlags::NONE).unwrap();
let image = ImageReader::new(Cursor::new(image_bytes))
.with_guessed_format()
.unwrap()
.decode();
image.map(|image| {
let stride = if transparency {
image.to_rgba8().sample_layout().height_stride
} else {
image.to_rgb8().sample_layout().height_stride
};
Pixbuf::from_bytes(
&glib::Bytes::from(image.as_bytes()),
Colorspace::Rgb,
transparency,
8,
image.width() as i32,
image.height() as i32,
stride as i32,
)
.scale_simple(width, height, InterpType::Nearest)
})
}