Skip to content

Commit a742fe8

Browse files
committed
feat(rendering): pick the right font
1 parent 4c99f05 commit a742fe8

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

src/document.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ pub struct Document {
2828
pub custom_tags: Option<String>,
2929

3030
#[serde(skip)]
31-
pub res: DocumentRes,
31+
pub doc_res: DocumentRes,
32+
#[serde(skip)]
33+
pub public_res: PublicRes,
3234
}
3335

3436
#[derive(Deserialize, Debug, Default)]
@@ -110,4 +112,43 @@ impl DocumentRes {
110112
pub fn from_xml(xml: &str) -> Result<DocumentRes, serde_xml_rs::Error> {
111113
serde_xml_rs::from_str(xml)
112114
}
115+
}
116+
117+
118+
/* PublicRes.xml
119+
<?xml version="1.0" encoding="UTF-8"?><ofd:Res xmlns:ofd="http://www.ofdspec.org/2016" BaseLoc="Res">
120+
<ofd:Fonts>
121+
<ofd:Font FamilyName="宋体" FontName="宋体" ID="3"/>
122+
<ofd:Font FamilyName="楷体" FontName="楷体" ID="5"/>
123+
<ofd:Font FamilyName="Courier New" FontName="Courier New" ID="7"/>
124+
</ofd:Fonts>
125+
</ofd:Res>
126+
*/
127+
128+
#[derive(Deserialize, Debug, Default)]
129+
#[serde(rename_all = "PascalCase")]
130+
pub struct PublicRes {
131+
pub base_loc: String,
132+
pub fonts: Fonts,
133+
}
134+
135+
#[derive(Deserialize, Debug, Default)]
136+
#[serde(rename_all = "PascalCase")]
137+
pub struct Fonts {
138+
pub font: Vec<Font>,
139+
}
140+
141+
#[derive(Deserialize, Debug, Default)]
142+
#[serde(rename_all = "PascalCase")]
143+
pub struct Font {
144+
#[serde(rename = "ID")]
145+
pub id: u32,
146+
pub family_name: String,
147+
pub font_name: String,
148+
}
149+
150+
impl PublicRes {
151+
pub fn from_xml(xml: &str) -> Result<PublicRes, serde_xml_rs::Error> {
152+
serde_xml_rs::from_str(xml)
153+
}
113154
}

src/lib.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::Path;
1111

1212
use zip::ZipArchive;
1313

14-
use document::{Document, DocumentRes};
14+
use document::{Document, DocumentRes, PublicRes};
1515
use ofd::{Ofd, OfdNode};
1616
use page::Page;
1717
use render::Renderable;
@@ -55,7 +55,7 @@ pub fn export_ofd_to_png(ofd: &mut Ofd, output_path: &str) -> Result<(), Box<dyn
5555
let mut document = Document::from_xml(&content)?;
5656
println!("document: {:#?}", document);
5757

58-
// Find the DocumentRes.xml file and parse the content to a document_res object.
58+
// Find the DocumentRes.xml file and parse the content to a DocumentRes object.
5959
{
6060
let doc_root_path = ofd.node.doc_body.doc_root.as_str();
6161
let root_path = Path::new(doc_root_path);
@@ -70,7 +70,24 @@ pub fn export_ofd_to_png(ofd: &mut Ofd, output_path: &str) -> Result<(), Box<dyn
7070

7171
let document_res = DocumentRes::from_xml(&content)?;
7272
println!("document_res: {:#?}", document_res);
73-
document.res = document_res;
73+
document.doc_res = document_res;
74+
75+
// Find the PublicRes.xml file and parse the content to a PublicRes object.
76+
{
77+
let doc_root_path = ofd.node.doc_body.doc_root.as_str();
78+
let root_path = Path::new(doc_root_path);
79+
let res_path = root_path
80+
.parent().ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Parent directory not found"))?
81+
.join(document.common_data.public_res.as_str());
82+
let mut public_res_file = ofd.zip_archive.by_name(res_path.to_str().unwrap())?;
83+
84+
content.clear();
85+
public_res_file.read_to_string(&mut content)?;
86+
}
87+
88+
let public_res = PublicRes::from_xml(&content)?;
89+
println!("public_res: {:#?}", public_res);
90+
document.public_res = public_res;
7491

7592
// Create a cairo surface and context.
7693
let pybox = CT_PageArea::from(document.common_data.page_area.physical_box.clone()).toPixel();

src/render.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,15 @@ impl Renderable for TextObject {
7171
let color = self.fill_color.as_ref().unwrap_or(&Color::default()).value.clone();
7272
let fill_color = CT_Color::from(color);
7373

74-
// TODO(hualet): load the right font
75-
context.select_font_face("Sans", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
74+
let font_id = self.font;
75+
for font in document.public_res.fonts.font.iter() {
76+
if font.id == font_id {
77+
// TODO(hualet): custom font file loading.
78+
context.select_font_face(font.family_name.as_str(),
79+
cairo::FontSlant::Normal, cairo::FontWeight::Normal);
80+
break;
81+
}
82+
}
7683
context.set_font_size(mmtopx(self.size) as f64);
7784

7885
context.set_source_rgb(fill_color.value[0] as f64 / 255.0,
@@ -99,11 +106,11 @@ impl Renderable for ImageObject {
99106
// 1) find the resource file in DocumentRes with the resource id
100107
// 2) construct the path of the image file
101108
// 3) load the image file and draw
102-
for resource in document.res.multi_medias.multi_media.iter() {
109+
for resource in document.doc_res.multi_medias.multi_media.iter() {
103110
if resource.id == self.resource_id {
104111
let path = Path::new(ofd.node.doc_body.doc_root.as_str());
105112
let res_path = &path.parent().unwrap()
106-
.join(document.res.base_loc.as_str())
113+
.join(document.doc_res.base_loc.as_str())
107114
.join(resource.media_file.as_str());
108115

109116
let mut file = ofd.zip_archive.by_name(res_path.to_str().unwrap()).unwrap();

0 commit comments

Comments
 (0)