Skip to content

Commit

Permalink
Don't invert images in inverted mode
Browse files Browse the repository at this point in the history
Fixes #209.
  • Loading branch information
baskerville committed Dec 9, 2021
1 parent e0c558b commit 91d6181
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 37 deletions.
6 changes: 5 additions & 1 deletion src/document/djvu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{Document, Location, TextLocation, BoundedText, TocEntry};
use super::{chapter, chapter_relative};
use crate::metadata::TextAlign;
use crate::framebuffer::Pixmap;
use crate::geom::{Rectangle, CycleDir};
use crate::geom::{Rectangle, Boundary, CycleDir};

impl Into<DjvuRect> for Rectangle {
fn into(self) -> DjvuRect {
Expand Down Expand Up @@ -200,6 +200,10 @@ impl Document for DjvuDocument {
}
}

fn images(&mut self, _loc: Location) -> Option<(Vec<Boundary>, usize)> {
None
}

fn metadata(&self, key: &str) -> Option<String> {
unsafe {
let mut exp = ddjvu_document_get_anno(self.doc, 1);
Expand Down
40 changes: 20 additions & 20 deletions src/document/epub/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::framebuffer::Pixmap;
use crate::helpers::{Normalize, decode_entities};
use crate::document::{Document, Location, TextLocation, TocEntry, BoundedText, chapter_from_uri};
use crate::unit::pt_to_px;
use crate::geom::{Rectangle, Edge, CycleDir};
use crate::geom::{Rectangle, Boundary, Edge, CycleDir};
use super::pdf::PdfOpener;
use super::html::dom::{XmlTree, NodeRef};
use super::html::engine::{Page, Engine, ResourceFetcher};
Expand Down Expand Up @@ -332,25 +332,6 @@ impl EpubDocument {
}
}

fn images(&mut self, loc: Location) -> Option<(Vec<Rectangle>, usize)> {
if self.spine.is_empty() {
return None;
}

let offset = self.resolve_location(loc)?;
let (index, start_offset) = self.vertebra_coordinates(offset)?;
let page_index = self.page_index(offset, index, start_offset)?;

self.cache.get(&index).map(|display_list| {
(display_list[page_index].iter().filter_map(|dc| {
match dc {
DrawCommand::Image(ImageCommand { rect, .. }) => Some(*rect),
_ => None,
}
}).collect(), offset)
})
}

fn build_display_list(&mut self, index: usize, start_offset: usize) -> Vec<Page> {
let mut text = String::new();
let mut spine_dir = PathBuf::default();
Expand Down Expand Up @@ -857,6 +838,25 @@ impl Document for EpubDocument {
})
}

fn images(&mut self, loc: Location) -> Option<(Vec<Boundary>, usize)> {
if self.spine.is_empty() {
return None;
}

let offset = self.resolve_location(loc)?;
let (index, start_offset) = self.vertebra_coordinates(offset)?;
let page_index = self.page_index(offset, index, start_offset)?;

self.cache.get(&index).map(|display_list| {
(display_list[page_index].iter().filter_map(|dc| {
match dc {
DrawCommand::Image(ImageCommand { rect, .. }) => Some((*rect).into()),
_ => None,
}
}).collect(), offset)
})
}

fn pixmap(&mut self, loc: Location, scale: f32) -> Option<(Pixmap, usize)> {
if self.spine.is_empty() {
return None;
Expand Down
26 changes: 13 additions & 13 deletions src/document/html/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::framebuffer::Pixmap;
use crate::helpers::{Normalize, decode_entities};
use crate::document::{Document, Location, TextLocation, TocEntry, BoundedText};
use crate::unit::pt_to_px;
use crate::geom::{Rectangle, Edge, CycleDir};
use crate::geom::{Boundary, Edge, CycleDir};
use self::dom::{XmlTree, NodeRef};
use self::layout::{RootData, StyleData, DrawState, LoopContext};
use self::layout::{DrawCommand, TextCommand, ImageCommand, TextAlign};
Expand Down Expand Up @@ -159,18 +159,6 @@ impl HtmlDocument {
}
}

fn images(&mut self, loc: Location) -> Option<(Vec<Rectangle>, usize)> {
let offset = self.resolve_location(loc)?;
let page_index = self.page_index(offset)?;

Some((self.pages[page_index].iter().filter_map(|dc| {
match dc {
DrawCommand::Image(ImageCommand { rect, .. }) => Some(*rect),
_ => None,
}
}).collect(), offset))
}

fn build_pages(&mut self) -> Vec<Page> {
let mut stylesheet = StyleSheet::new();
let spine_dir = PathBuf::default();
Expand Down Expand Up @@ -353,6 +341,18 @@ impl Document for HtmlDocument {
None
}

fn images(&mut self, loc: Location) -> Option<(Vec<Boundary>, usize)> {
let offset = self.resolve_location(loc)?;
let page_index = self.page_index(offset)?;

Some((self.pages[page_index].iter().filter_map(|dc| {
match dc {
DrawCommand::Image(ImageCommand { rect, .. }) => Some((*rect).into()),
_ => None,
}
}).collect(), offset))
}

fn links(&mut self, loc: Location) -> Option<(Vec<BoundedText>, usize)> {
let offset = self.resolve_location(loc)?;
let page_index = self.page_index(offset)?;
Expand Down
1 change: 1 addition & 0 deletions src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub trait Document: Send+Sync {
fn words(&mut self, loc: Location) -> Option<(Vec<BoundedText>, usize)>;
fn lines(&mut self, loc: Location) -> Option<(Vec<BoundedText>, usize)>;
fn links(&mut self, loc: Location) -> Option<(Vec<BoundedText>, usize)>;
fn images(&mut self, loc: Location) -> Option<(Vec<Boundary>, usize)>;

fn pixmap(&mut self, loc: Location, scale: f32) -> Option<(Pixmap, usize)>;
fn layout(&mut self, width: u32, height: u32, font_size: f32, dpi: u16);
Expand Down
2 changes: 1 addition & 1 deletion src/document/mupdf_sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub struct FzStorable {

#[repr(C)]
pub struct FzTextOptions {
flags: libc::c_int,
pub flags: libc::c_int,
}

#[repr(C)]
Expand Down
31 changes: 31 additions & 0 deletions src/document/pdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ impl Document for PdfDocument {
self.page(index).and_then(|page| page.lines()).map(|lines| (lines, index))
}

fn images(&mut self, loc: Location) -> Option<(Vec<Boundary>, usize)> {
let index = self.resolve_location(loc)?;
self.page(index).and_then(|page| page.images()).map(|images| (images, index))
}

fn links(&mut self, loc: Location) -> Option<(Vec<BoundedText>, usize)> {
let index = self.resolve_location(loc)?;
self.page(index).and_then(|page| page.links()).map(|links| (links, index))
Expand Down Expand Up @@ -274,6 +279,32 @@ impl Document for PdfDocument {
}

impl<'a> PdfPage<'a> {
pub fn images(&self) -> Option<Vec<Boundary>> {
unsafe {
let mut images: Vec<Boundary> = Vec::new();
let opts = FzTextOptions { flags: FZ_TEXT_PRESERVE_IMAGES };
let tp = mp_new_stext_page_from_page(self.ctx.0, self.page, &opts);
if tp.is_null() {
return None;
}

let mut block = (*tp).first_block;

while !block.is_null() {
if (*block).kind == FZ_PAGE_BLOCK_IMAGE {
let bnd: Boundary = (*block).bbox.into();
images.retain(|img| !img.overlaps(&bnd));
images.push(bnd);
}

block = (*block).next;
}

fz_drop_stext_page(self.ctx.0, tp);
Some(images)
}
}

pub fn lines(&self) -> Option<Vec<BoundedText>> {
unsafe {
let mut lines = Vec::new();
Expand Down
4 changes: 4 additions & 0 deletions src/view/home/book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ impl View for Book {
let pt = pt!(self.rect.min.x + padding + dx,
self.rect.min.y + x_height / 2 + dy);
fb.draw_pixmap(&pixmap, pt);
if fb.inverted() {
let rect = pixmap.rect() + pt;
fb.invert_region(&rect);
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/view/intermission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ impl View for Intermission {
let dy = (self.rect.height() as i32 - pixmap.height as i32) / 2;
let pt = self.rect.min + pt!(dx, dy);
fb.draw_pixmap(&pixmap, pt);
if fb.inverted() {
let rect = pixmap.rect() + pt;
fb.invert_region(&rect);
}
}
}
},
Expand Down
33 changes: 31 additions & 2 deletions src/view/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub struct Reader {
chunks: Vec<RenderChunk>, // Chunks of pages being rendered.
text: FxHashMap<usize, Vec<BoundedText>>, // Text of the current chunks.
annotations: FxHashMap<usize, Vec<Annotation>>, // Annotations for the current chunks.
noninverted_regions: FxHashMap<usize, Vec<Boundary>>,
focus: Option<ViewId>,
search: Option<Search>,
search_direction: LinearDir,
Expand Down Expand Up @@ -337,9 +338,10 @@ impl Reader {
children: Vec::new(),
doc: Arc::new(Mutex::new(doc)),
cache: BTreeMap::new(),
chunks: Vec::new(),
text: FxHashMap::default(),
annotations: FxHashMap::default(),
chunks: Vec::new(),
noninverted_regions: FxHashMap::default(),
focus: None,
search: None,
search_direction: LinearDir::Forward,
Expand Down Expand Up @@ -401,9 +403,10 @@ impl Reader {
children: Vec::new(),
doc: Arc::new(Mutex::new(Box::new(doc))),
cache: BTreeMap::new(),
chunks: Vec::new(),
text: FxHashMap::default(),
annotations: FxHashMap::default(),
chunks: Vec::new(),
noninverted_regions: FxHashMap::default(),
focus: None,
search: None,
search_direction: LinearDir::Forward,
Expand Down Expand Up @@ -913,6 +916,18 @@ impl Reader {
}
}

#[inline]
fn update_noninverted_regions(&mut self, inverted: bool) {
self.noninverted_regions.clear();
if inverted {
for chunk in &self.chunks {
if let Some((images, _)) = self.doc.lock().unwrap().images(Location::Exact(chunk.location)) {
self.noninverted_regions.insert(chunk.location, images);
}
}
}
}

#[inline]
fn update_annotations(&mut self) {
self.annotations.clear();
Expand Down Expand Up @@ -1033,6 +1048,7 @@ impl Reader {
}

self.update_annotations();
self.update_noninverted_regions(context.fb.inverted());

if self.view_port.zoom_mode == ZoomMode::FitToPage ||
self.view_port.zoom_mode == ZoomMode::FitToWidth {
Expand Down Expand Up @@ -3668,6 +3684,10 @@ impl View for Reader {
}
true
},
Event::Select(EntryId::ToggleInverted) => {
self.update_noninverted_regions(!context.fb.inverted());
false
},
Event::Reseed => {
self.reseed(rq, context);
true
Expand Down Expand Up @@ -3725,6 +3745,15 @@ impl View for Reader {
let chunk_position = region_rect.min;
fb.draw_framed_pixmap_contrast(pixmap, &chunk_frame, chunk_position, self.contrast.exponent, self.contrast.gray);

if let Some(rects) = self.noninverted_regions.get(&chunk.location) {
for r in rects {
let rect = (*r * scale).to_rect() - chunk.frame.min + chunk.position;
if let Some(ref image_rect) = rect.intersection(&region_rect) {
fb.invert_region(image_rect);
}
}
}

if let Some(groups) = self.search.as_ref().and_then(|s| s.highlights.get(&chunk.location)) {
for rects in groups {
let mut last_rect: Option<Rectangle> = None;
Expand Down

0 comments on commit 91d6181

Please sign in to comment.