1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::ptr;
use enums::*;
use winapi::*;
use error::DWriteError;
use helpers::ToWide;
use internal::FromParams;
use comptr::ComPtr;

#[derive(Clone, Debug, PartialEq)]
pub struct TextFormat {
    ptr: ComPtr<IDWriteTextFormat>,
}

impl TextFormat {
    pub unsafe fn from_ptr(ptr: ComPtr<IDWriteTextFormat>) -> Self {
        TextFormat { ptr: ptr }
    }

    pub unsafe fn get_ptr(&self) -> ComPtr<IDWriteTextFormat> {
        self.ptr.clone()
    }

    pub unsafe fn get_raw(&self) -> *mut IDWriteTextFormat {
        self.ptr.raw_value()
    }
}

unsafe impl FromParams for TextFormat {
    type Params = Params;

    fn from_params(factory: &mut IDWriteFactory, params: Params) -> Result<Self, DWriteError> {
        unsafe {
            let mut ptr: ComPtr<IDWriteTextFormat> = ComPtr::new();
            let result = factory.CreateTextFormat(params.family.as_ptr(),
                                                  ptr::null_mut(),
                                                  DWRITE_FONT_WEIGHT(params.weight as u32),
                                                  DWRITE_FONT_STYLE(params.style as u32),
                                                  DWRITE_FONT_STRETCH(params.stretch as u32),
                                                  params.size,
                                                  params.locale.as_ptr(),
                                                  ptr.raw_addr());

            if SUCCEEDED(result) {
                Ok(TextFormat { ptr: ptr })
            } else {
                Err(From::from(result))
            }
        }
    }
}

pub struct Params {
    family: Vec<u16>,
    weight: FontWeight,
    style: FontStyle,
    stretch: FontStretch,
    size: f32,
    locale: Vec<u16>,
}

pub struct ParamBuilder<'a> {
    family: Option<&'a str>,
    weight: FontWeight,
    style: FontStyle,
    stretch: FontStretch,
    size: Option<f32>,
    locale: Option<&'a str>,
}

impl<'a> ParamBuilder<'a> {
    pub fn new() -> ParamBuilder<'static> {
        ParamBuilder {
            family: None,
            weight: FontWeight::Normal,
            style: FontStyle::Normal,
            stretch: FontStretch::Normal,
            size: None,
            locale: None,
        }
    }

    pub fn build(self) -> Option<Params> {
        if self.size == None || self.family == None {
            return None;
        }

        Some(Params {
            family: self.family.unwrap().to_wide_null(),
            weight: self.weight,
            style: self.style,
            stretch: self.stretch,
            size: self.size.unwrap(),
            locale: self.locale.unwrap_or("en-US").to_wide_null(),
        })
    }

    pub fn family(mut self, family: &'a str) -> Self {
        self.family = Some(family);
        self
    }

    pub fn weight(mut self, weight: FontWeight) -> Self {
        self.weight = weight;
        self
    }

    pub fn style(mut self, style: FontStyle) -> Self {
        self.style = style;
        self
    }

    pub fn stretch(mut self, stretch: FontStretch) -> Self {
        self.stretch = stretch;
        self
    }

    pub fn size(mut self, size: f32) -> Self {
        self.size = Some(size);
        self
    }

    pub fn locale(mut self, locale: &'a str) -> Self {
        self.locale = Some(locale);
        self
    }
}