Skip to main content

pushrod/render/
texture_cache.rs

1// Pushrod Rendering Library
2// Texture Caching Component
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use sdl2::image::LoadTexture;
17use sdl2::pixels::Color;
18use sdl2::render::{Canvas, Texture, TextureQuery};
19use sdl2::ttf::{FontStyle, Sdl2TtfContext};
20use sdl2::video::Window;
21use std::collections::HashMap;
22use std::path::Path;
23
24/// This is the structure for the `TextureCache`.
25pub struct TextureCache {
26    images: HashMap<String, Texture>,
27    ttf_context: Sdl2TtfContext,
28}
29
30/// This is a `Texture` cache object that is used by the `WidgetCache`.  This is responsible for loading
31/// in images into a cache in memory so that it can be copied multiple times as required by the
32/// application.
33impl TextureCache {
34    /// Creates a new `TextureCache`.
35    pub fn new() -> Self {
36        Self {
37            images: HashMap::new(),
38            ttf_context: sdl2::ttf::init().map_err(|e| e.to_string()).unwrap(),
39        }
40    }
41
42    /// Retrieves the current Text Rendering context (`Sdl2TtfContext`)
43    pub fn get_ttf_context(&self) -> &Sdl2TtfContext {
44        &self.ttf_context
45    }
46
47    /// Loads an image based on the `image_name`, which is the filename for the image to load.
48    /// Returns a reference to the `Texture` that was loaded.
49    pub fn get_image(&mut self, c: &mut Canvas<Window>, image_name: String) -> &Texture {
50        self.images.entry(image_name.clone()).or_insert({
51            c.texture_creator()
52                .load_texture(Path::new(&image_name))
53                .unwrap()
54        })
55    }
56
57    /// Renders text, given the font name, size, style, color, string, and max width.  Transfers
58    /// ownership of the `Texture` to the calling function, returns the width and height of the
59    /// texture after rendering.  By using the identical font name, size, and style, if SDL2 caches
60    /// the font data, this will allow the font to be cached internally.
61    pub fn render_text(
62        &mut self,
63        c: &mut Canvas<Window>,
64        font_name: String,
65        font_size: u16,
66        font_style: FontStyle,
67        font_string: String,
68        font_color: Color,
69        width: u32,
70    ) -> (Texture, u32, u32) {
71        let ttf_context = self.get_ttf_context();
72        let texture_creator = c.texture_creator();
73        let mut font = ttf_context
74            .load_font(Path::new(&font_name), font_size as u16)
75            .unwrap();
76
77        font.set_style(font_style);
78
79        let surface = font
80            .render(&font_string)
81            .blended_wrapped(font_color, width)
82            .map_err(|e| e.to_string())
83            .unwrap();
84        let font_texture = texture_creator
85            .create_texture_from_surface(&surface)
86            .map_err(|e| e.to_string())
87            .unwrap();
88
89        let TextureQuery { width, height, .. } = font_texture.query();
90
91        (font_texture, width, height)
92    }
93}
94
95impl Default for TextureCache {
96    fn default() -> Self {
97        Self::new()
98    }
99}