Skip to content

Commit

Permalink
Add the ability to find a word in a document
Browse files Browse the repository at this point in the history
  • Loading branch information
baskerville committed Mar 9, 2018
1 parent 6039636 commit 70463fd
Show file tree
Hide file tree
Showing 22 changed files with 1,213 additions and 359 deletions.
119 changes: 54 additions & 65 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ error-chain = "0.11.0"
fnv = "1.0.6"
isbn = "0.1.0"
lazy_static = "1.0.0"
libc = "0.2.36"
libc = "0.2.37"
png = "0.11.0"
regex = "0.2.6"
serde = "1.0.27"
serde_derive = "1.0.27"
serde_json = "1.0.9"
serde_json = "1.0.10"
titlecase = "0.10.0"
unicode-normalization = "0.1.5"

Expand All @@ -42,7 +42,7 @@ version = "0.2.17"
optional = true

[dependencies.reqwest]
version = "0.8.4"
version = "0.8.5"
optional = true

[dependencies.chrono]
Expand Down
1 change: 1 addition & 0 deletions artworks/touch_regions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 19 additions & 24 deletions doc/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,33 @@

## Viewer

The screen is divided into three regions:

┌─────────┬─────────┬─────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ P │ B │ N │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
└─────────┴─────────┴─────────┘

The screen is divided into seven regions:

![Touch Regions](../artworks/touch_regions.svg)

Gestures by region:

- *P*:
- *LE* (Left Ear):
- tap: previous page.
- hold: previous chapter.
- *B*:
- *MB* (Middle Band):
- tap: toggle the top and bottom bars.
- hold: perform a full screen refresh.
- *N*:
- *RE* (Right Ear):
- tap: next page.
- hold: next chapter.
- *TL* (Top Left Corner):
- tap: previous bookmark.
- hold: previous location.
- *TR* (Top Right Corner):
- tap: next bookmark.
- hold: toggle bookmark.
- *BL* (Bottom Left Corner):
- tap: previous page.
- hold: toggle frontlight.
- *BR* (Bottom Right Corner):
- tap: next page.
- hold: invert colors.

Swipe west/east to go to the next/previous page.

Expand Down
12 changes: 6 additions & 6 deletions doc/TODO.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
- Search text within document.
- Add, remove, rename categories.
- Metadata: Load, Remove, Undo.
- Fit to width.
- ePUB renderer.
- Pocket articles.
- Add, remove, rename categories.
- Preload next/previous page.
- Landscape mode.
- Fit to width. Repage.
- Input field completions bar.
- Metadata view.
- Bookmarks.
- Complex/fuzzy search queries?
- Dictionary.
- Calculator.
- Browser.
- Applications: Sketch, Calculator, Browser.
57 changes: 17 additions & 40 deletions src/document/djvu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::rc::Rc;
use std::path::Path;
use std::ffi::{CStr, CString};
use std::os::unix::ffi::OsStrExt;
use document::{Document, TextLayer, LayerGrain, TocEntry, Link};
use document::{Document, BoundedText, TocEntry, Link};
use framebuffer::Pixmap;
use geom::Rectangle;

Expand Down Expand Up @@ -60,21 +60,6 @@ impl DjvuContext {
}
}

impl LayerGrain {
pub fn from_bytes(name: &[u8]) -> LayerGrain {
match name {
b"page" => LayerGrain::Page,
b"column" => LayerGrain::Column,
b"region" => LayerGrain::Region,
b"para" => LayerGrain::Paragraph,
b"line" => LayerGrain::Line,
b"word" => LayerGrain::Word,
b"char" => LayerGrain::Character,
_ => LayerGrain::Character,
}
}
}

impl DjvuOpener {
pub fn new() -> Option<DjvuOpener> {
unsafe {
Expand Down Expand Up @@ -114,6 +99,9 @@ impl DjvuOpener {
}
}

unsafe impl Send for DjvuDocument {}
unsafe impl Sync for DjvuDocument {}

impl Document for DjvuDocument {
fn pages_count(&self) -> usize {
unsafe { ddjvu_document_get_pagenum(self.doc) as usize }
Expand Down Expand Up @@ -147,13 +135,10 @@ impl Document for DjvuDocument {
}
}

fn text(&self, index: usize) -> Option<TextLayer> {
fn words(&self, index: usize) -> Option<Vec<BoundedText>> {
unsafe {
let page = self.page(index);
if page.is_none() {
return None;
}
let height = page.unwrap().height() as i32;
let page = self.page(index)?;
let height = page.height() as i32;
let grain = CString::new("word").unwrap();
let mut exp = ddjvu_document_get_pagetext(self.doc, index as libc::c_int, grain.as_ptr());
while exp == MINIEXP_DUMMY {
Expand All @@ -163,9 +148,10 @@ impl Document for DjvuDocument {
if exp == MINIEXP_NIL {
None
} else {
let text_page = Self::walk_text(exp, height);
let mut words = Vec::new();
Self::walk_words(exp, height, &mut words);
ddjvu_miniexp_release(self.doc, exp);
Some(text_page)
Some(words)
}
}
}
Expand Down Expand Up @@ -248,11 +234,10 @@ impl DjvuDocument {
}
}

fn walk_text(exp: *mut MiniExp, height: i32) -> TextLayer {
fn walk_words(exp: *mut MiniExp, height: i32, words: &mut Vec<BoundedText>) {
unsafe {
let len = miniexp_length(exp);
let mut text: Option<String> = None;
let p_rect = {
let rect = {
let x_min = miniexp_nth(1, exp) as i32 >> 2;
let y_max = height - (miniexp_nth(2, exp) as i32 >> 2);
let x_max = miniexp_nth(3, exp) as i32 >> 2;
Expand All @@ -261,26 +246,18 @@ impl DjvuDocument {
};
let grain = {
let raw = miniexp_to_name(miniexp_nth(0, exp));
let c_str = CStr::from_ptr(raw);
LayerGrain::from_bytes(c_str.to_bytes())
CStr::from_ptr(raw).to_bytes()
};
let mut children = Vec::new();
if miniexp_stringp(miniexp_nth(5, exp)) == 1 {
if grain == b"word" && miniexp_stringp(miniexp_nth(5, exp)) == 1 {
let raw = miniexp_to_str(miniexp_nth(5, exp));
let c_str = CStr::from_ptr(raw);
text = Some(c_str.to_string_lossy().into_owned());
let text = c_str.to_string_lossy().into_owned();
words.push(BoundedText { rect, text });
} else {
for i in 5..len {
let child = miniexp_nth(i, exp);
children.push(Self::walk_text(child, height));
Self::walk_words(miniexp_nth(i, exp), height, words);
}
}
TextLayer {
grain: grain,
rect: p_rect,
text: text,
children: children,
}
}
}

Expand Down
53 changes: 7 additions & 46 deletions src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,18 @@ use document::djvu::{DjvuOpener};
use document::pdf::{PdfOpener};
use framebuffer::Pixmap;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LayerGrain {
Page,
Column,
Region,
Paragraph,
Line,
Word,
Character,
}

#[derive(Debug, Clone)]
pub struct TextLayer {
pub grain: LayerGrain,
pub struct BoundedText {
pub rect: Rectangle,
pub text: Option<String>,
pub children: Vec<TextLayer>,
pub text: String,
}


#[derive(Debug, Clone)]
pub struct Link {
pub uri: String,
pub rect: Rectangle,
}

impl TextLayer {
fn is_empty(&self) -> bool {
self.text.is_none() &&
self.children.iter().all(|t| t.is_empty())
}
}

#[derive(Debug, Clone)]
pub struct TocEntry {
pub title: String,
Expand Down Expand Up @@ -132,13 +111,13 @@ fn chapter_relative_prev<'a>(toc: &'a [TocEntry], index: usize, page: &mut Optio
}
}

pub trait Document {
pub trait Document: Send+Sync {
fn pages_count(&self) -> usize;
fn pixmap(&self, index: usize, scale: f32) -> Option<Pixmap>;
fn dims(&self, index: usize) -> Option<(f32, f32)>;

fn toc(&self) -> Option<Vec<TocEntry>>;
fn text(&self, index: usize) -> Option<TextLayer>;
fn words(&self, index: usize) -> Option<Vec<BoundedText>>;
fn links(&self, index: usize) -> Option<Vec<Link>>;

fn title(&self) -> Option<String>;
Expand All @@ -148,7 +127,7 @@ pub trait Document {
fn layout(&mut self, width: f32, height: f32, em: f32);

fn has_text(&self) -> bool {
(0..self.pages_count()).any(|i| self.text(i).map_or(false, |t| !t.is_empty()))
(0..self.pages_count()).any(|i| self.words(i).map_or(false, |w| !w.is_empty()))
}

fn has_toc(&self) -> bool {
Expand All @@ -159,8 +138,8 @@ pub trait Document {
let mut found = false;
let mut result = None;
'pursuit: for index in 0..10 {
if let Some(ref text) = self.text(index) {
for word in text.words() {
if let Some(ref words) = self.words(index) {
for word in words.iter().map(|w| &*w.text) {
if word.contains("ISBN") {
found = true;
continue;
Expand Down Expand Up @@ -202,24 +181,6 @@ impl HumanSize for u64 {
}
}

impl TextLayer {
pub fn words(&self) -> Vec<String> {
match self.grain {
LayerGrain::Word => {
vec![self.text.as_ref().unwrap().to_string()]
},
LayerGrain::Character => vec![],
_ => {
let mut result = Vec::new();
for child in &self.children {
result.extend_from_slice(&child.words());
}
result
}
}
}
}

pub fn asciify(name: &str) -> String {
name.nfkd().filter(|&c| !is_combining_mark(c)).collect::<String>()
.replace('œ', "oe")
Expand Down
Loading

0 comments on commit 70463fd

Please sign in to comment.