use std::ffi::{CString, CStr};
use std::str;
use libc::{c_float, c_uint, size_t};
use traits::Wrappable;
use graphics::{Drawable, Transformable, RenderTarget, Font, FloatRect,
Color, Transform, RenderStates, TextStyle};
use sfml_types::Vector2f;
use csfml_graphics_sys as ffi;
pub struct Text<'s> {
text: *mut ffi::sfText,
string_length: u32,
font: Option<&'s Font>
}
impl<'s> Text<'s> {
pub fn new() -> Option<Text<'s>> {
let text = unsafe { ffi::sfText_create() };
if text.is_null() {
None
} else {
Some(Text {
text: text,
string_length: 0,
font: None
})
}
}
pub fn new_init(string: &str,
font: &'s Font,
character_size: u32) ->Option<Text<'s>> {
let text = unsafe { ffi::sfText_create() };
if text.is_null() {
None
} else {
let c_str = CString::new(string.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfText_setString(text, c_str);
ffi::sfText_setFont(text, font.unwrap());
ffi::sfText_setCharacterSize(text, character_size as c_uint)
}
Some(Text {
text: text,
string_length: string.len() as u32,
font: Some(font)
})
}
}
pub fn clone_opt(&self) -> Option<Text<'s>> {
let sp = unsafe { ffi::sfText_copy(self.text) };
if sp.is_null() {
None
} else {
Some(Text {
text: self.text,
string_length: self.string_length as u32,
font: self.font
})
}
}
pub fn set_string(&mut self, string: &str) {
unsafe {
let c_str = CString::new(string.as_bytes()).unwrap();
ffi::sfText_setString(self.text, c_str.as_ptr());
}
self.string_length = string.len() as u32
}
pub fn get_string(&self) -> String {
unsafe {
let string = ffi::sfText_getString(self.text);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
pub fn get_unicode_string(&self) -> Vec<u32> {
let string: *const u32 = unsafe {
ffi::sfText_getUnicodeString(self.text)
};
let string_slice: &[u32] = unsafe {
::std::slice::from_raw_parts(string, self.string_length as usize)
};
string_slice.to_vec()
}
pub fn get_character_size(&self) -> u32 {
unsafe {
ffi::sfText_getCharacterSize(self.text) as u32
}
}
pub fn set_font(&mut self, font: &'s Font) {
self.font = Some(font);
unsafe {
ffi::sfText_setFont(self.text, font.unwrap())
}
}
pub fn set_style(&mut self, style: TextStyle) {
unsafe {
ffi::sfText_setStyle(self.text, style.bits())
}
}
pub fn set_character_size(&mut self, size: u32) {
unsafe {
ffi::sfText_setCharacterSize(self.text, size as c_uint)
}
}
pub fn get_style(&self) -> TextStyle {
unsafe { TextStyle::from_bits_truncate(ffi::sfText_getStyle(self.text)) }
}
pub fn get_font(&self) -> Option<&'s Font> {
self.font
}
pub fn set_color(&mut self, color: &Color) {
unsafe {
ffi::sfText_setColor(self.text, color.0)
}
}
pub fn get_color(&self) -> Color {
unsafe {
Color(ffi::sfText_getColor(self.text))
}
}
pub fn find_character_pos(&self, index: u64) -> Vector2f {
unsafe {
ffi::sfText_findCharacterPos(self.text, index as size_t)
}
}
pub fn get_local_bounds(&self) -> FloatRect {
unsafe {
ffi::sfText_getLocalBounds(self.text)
}
}
pub fn get_global_bounds(&self) -> FloatRect {
unsafe {
ffi::sfText_getGlobalBounds(self.text)
}
}
pub fn set_unicode_string(&mut self, string: Vec<u32>) {
unsafe {
self.string_length = string.len() as u32;
ffi::sfText_setUnicodeString(self.text, string.as_ptr())
}
}
}
impl<'s> Clone for Text<'s> {
fn clone(&self) -> Text<'s> {
let sp = unsafe { ffi::sfText_copy(self.text) };
if sp.is_null() {
panic!("Not enough memory to clone Text")
} else {
Text {
text: self.text,
string_length: self.string_length,
font: self.font
}
}
}
}
impl<'s> Drawable for Text<'s> {
fn draw<RT:RenderTarget>(&self,
render_target: &mut RT,
render_states: &mut RenderStates) {
render_target.draw_text(self, render_states)
}
}
impl<'s> Transformable for Text<'s> {
fn set_position(&mut self, position: &Vector2f) {
unsafe {
ffi::sfText_setPosition(self.text, *position)
}
}
fn set_position2f(&mut self, x: f32, y: f32) {
unsafe {
ffi::sfText_setPosition(self.text, Vector2f::new(x, y))
}
}
fn set_rotation(&mut self, angle: f32) {
unsafe {
ffi::sfText_setRotation(self.text, angle as c_float)
}
}
fn set_scale(&mut self, scale: &Vector2f) {
unsafe {
ffi::sfText_setScale(self.text, *scale)
}
}
fn set_scale2f(&mut self, scale_x: f32, scale_y: f32) {
unsafe {
ffi::sfText_setScale(self.text, Vector2f::new(scale_x, scale_y))
}
}
fn set_origin(&mut self, origin: &Vector2f) {
unsafe {
ffi::sfText_setOrigin(self.text, *origin)
}
}
fn set_origin2f(&mut self, x: f32, y: f32) {
unsafe {
ffi::sfText_setOrigin(self.text, Vector2f::new(x, y))
}
}
fn get_position(&self) -> Vector2f {
unsafe {
ffi::sfText_getPosition(self.text)
}
}
fn get_rotation(&self) -> f32 {
unsafe {
ffi::sfText_getRotation(self.text) as f32
}
}
fn get_scale(&self) -> Vector2f {
unsafe {
ffi::sfText_getScale(self.text)
}
}
fn get_origin(&self) -> Vector2f {
unsafe {
ffi::sfText_getOrigin(self.text)
}
}
fn move_(&mut self, offset: &Vector2f) {
unsafe {
ffi::sfText_move(self.text, *offset)
}
}
fn move2f(&mut self, offset_x: f32, offset_y: f32) {
unsafe {
ffi::sfText_move(self.text, Vector2f::new(offset_x, offset_y))
}
}
fn rotate(&mut self, angle: f32) {
unsafe {
ffi::sfText_rotate(self.text, angle as c_float)
}
}
fn scale(&mut self, factors: &Vector2f) {
unsafe {
ffi::sfText_scale(self.text, *factors)
}
}
fn scale2f(&mut self, factor_x: f32, factor_y: f32) {
unsafe {
ffi::sfText_scale(self.text, Vector2f::new(factor_x, factor_y))
}
}
fn get_transform(&self) -> Transform {
unsafe {
Transform(ffi::sfText_getTransform(self.text))
}
}
fn get_inverse_transform(&self) -> Transform {
unsafe {
Transform(ffi::sfText_getInverseTransform(self.text))
}
}
}
impl<'s> Wrappable<*mut ffi::sfText> for Text<'s> {
fn wrap(text: *mut ffi::sfText) -> Text<'s> {
Text {
text: text,
string_length: 0,
font: None
}
}
fn unwrap(&self) -> *mut ffi::sfText {
self.text
}
}
impl<'s> Drop for Text<'s> {
fn drop(&mut self) {
unsafe {
ffi::sfText_destroy(self.text);
}
}
}