Skip to content

Commit

Permalink
Add fastread mode
Browse files Browse the repository at this point in the history
  • Loading branch information
ahrm committed Apr 13, 2022
1 parent f1da91f commit 036a110
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 17 deletions.
49 changes: 49 additions & 0 deletions pdf_viewer/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1817,3 +1817,52 @@ bool Document::needs_authentication() {
return false;
}
}

std::vector<fz_rect> Document::get_highlighted_character_masks(int page) {
fz_stext_page* stext_page = get_stext_with_page_number(page);
std::vector<fz_stext_char*> flat_chars;
get_flat_chars_from_stext_page(stext_page, flat_chars);

std::vector<std::wstring> words;
std::vector<std::vector<fz_rect>> word_rects;
get_word_rect_list_from_flat_chars(flat_chars, words, word_rects);

std::vector<fz_rect> res;

for (int i = 0; i < words.size(); i++) {

std::vector<fz_rect> highlighted_characters;

if (words[i].size() == 1) {
highlighted_characters.push_back(word_rects[i][0]);
}
else if (words[i].size() == 2) {
highlighted_characters.push_back(word_rects[i][0]);
}
else if (words[i].size() == 3) {
highlighted_characters.push_back(word_rects[i][0]);
highlighted_characters.push_back(word_rects[i][1]);
}
else {
int num_highlighted = static_cast<int>(words[i].size() * 0.4f);
for (int j = 0; j < num_highlighted; j++) {
highlighted_characters.push_back(word_rects[i][j]);
}

}
res.push_back(create_word_rect(highlighted_characters));
}

//std::vector<fz_rect> res;

//std::vector<fz_rect> pending_word;
//pending_word.push_back(flat_chars[0]);

//for (int i = 1; i < flat_chars.size(); i++) {
// if (flat_chars[i - 1]->c == ' ') {
// res.push_back(fz_rect_from_quad(flat_chars[i]->quad));
// }
//}
return res;
}

1 change: 1 addition & 0 deletions pdf_viewer/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class Document {
bool needs_password();
bool needs_authentication();
bool apply_password(const char* password);
std::vector<fz_rect> get_highlighted_character_masks(int page);

friend class DocumentManager;
};
Expand Down
1 change: 1 addition & 0 deletions pdf_viewer/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ CommandManager::CommandManager() {
commands.push_back({ "goto_prev_highlight_of_type", false, false, false, false});
commands.push_back({ "add_highlight_with_current_type", false, false, false, false});
commands.push_back({ "enter_password", true, false , false, false});
commands.push_back({ "toggle_fastread", false, false , false, false});
}

const Command* CommandManager::get_command_with_name(std::string name) {
Expand Down
3 changes: 3 additions & 0 deletions pdf_viewer/main_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2411,6 +2411,9 @@ void MainWidget::handle_command(const Command* command, int num_repeats) {
}
else if (command->name == "debug") {
}
else if (command->name == "toggle_fastread") {
opengl_widget->toggle_fastread_mode();
}
else if (command->name == "smart_jump_under_cursor") {
QPoint mouse_pos = mapFromGlobal(QCursor::pos());
smart_jump_under_pos(mouse_pos.x(), mouse_pos.y());
Expand Down
61 changes: 44 additions & 17 deletions pdf_viewer/pdf_view_opengl_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ void PdfViewOpenGLWidget::initializeGL() {
shared_gl_objects.vertical_line_dark_program = LoadShaders(shader_path.slash(L"simple.vertex"), shader_path .slash(L"vertical_bar_dark.fragment"));
shared_gl_objects.custom_color_program = LoadShaders(shader_path.slash(L"simple.vertex"), shader_path.slash(L"custom_colors.fragment"));
shared_gl_objects.separator_program = LoadShaders(shader_path.slash(L"simple.vertex"), shader_path.slash(L"separator.fragment"));
shared_gl_objects.stencil_program = LoadShaders(shader_path.slash(L"stencil.vertex"), shader_path.slash(L"stencil.fragment"));

shared_gl_objects.dark_mode_contrast_uniform_location = glGetUniformLocation(shared_gl_objects.rendered_dark_program, "contrast");

Expand Down Expand Up @@ -688,6 +689,17 @@ void PdfViewOpenGLWidget::render(QPainter* painter) {
}
}

if (fastread_mode) {

enable_stencil();
write_to_stencil();
auto rects = document_view->get_document()->get_highlighted_character_masks(document_view->get_current_page_number());
draw_stencil_rects(document_view->get_current_page_number(), rects);
use_stencil_to_write();
render_transparent_white();
disable_stencil();
}

#ifndef NDEBUG
if (last_selected_block) {
glUseProgram(shared_gl_objects.highlight_program);
Expand Down Expand Up @@ -781,23 +793,6 @@ void PdfViewOpenGLWidget::render(QPainter* painter) {
render_overview(overview_page.value());
}

enable_stencil();
write_to_stencil();
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
//glBindBuffer(GL_ARRAY_BUFFER, shared_gl_objects.uv_buffer_object);
//glBindBuffer(GL_ARRAY_BUFFER, shared_gl_objects.vertex_buffer_object);
//render_overview(OverviewState{ 0, 0, 0 });
for (auto link : all_visible_links) {
render_highlight_document(shared_gl_objects.highlight_program, link.first, link.second->rect);
}

use_stencil_to_write();
for (int page : visible_pages) {
render_page(page);
}
render_transparent_white();
disable_stencil();

painter->endNativePainting();

Expand Down Expand Up @@ -1375,3 +1370,35 @@ void PdfViewOpenGLWidget::render_transparent_white() {
glDisableVertexAttribArray(1);
glDisable(GL_BLEND);
}

void PdfViewOpenGLWidget::draw_stencil_rects(int page, const std::vector<fz_rect>& rects) {

std::vector<float> window_rects;
for (auto rect : rects) {
fz_rect window_rect = document_view->document_to_window_rect(page, rect);
float triangle1[6] = {
window_rect.x0, window_rect.y0,
window_rect.x0, window_rect.y1,
window_rect.x1, window_rect.y0
};
float triangle2[6] = {
window_rect.x1, window_rect.y0,
window_rect.x0, window_rect.y1,
window_rect.x1, window_rect.y1
};
for (int i = 0; i < 6; i++) window_rects.push_back(triangle1[i]);
for (int i = 0; i < 6; i++) window_rects.push_back(triangle2[i]);
}

glUseProgram(shared_gl_objects.stencil_program);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, shared_gl_objects.vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, window_rects.size() * sizeof(float), window_rects.data(), GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, rects.size() * 6);
glDisableVertexAttribArray(0);

}

void PdfViewOpenGLWidget::toggle_fastread_mode() {
fastread_mode = !fastread_mode;
}
4 changes: 4 additions & 0 deletions pdf_viewer/pdf_view_opengl_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct OpenGLSharedResources {
GLuint vertical_line_program;
GLuint vertical_line_dark_program;
GLuint separator_program;
GLuint stencil_program;

GLint dark_mode_contrast_uniform_location;
GLint highlight_color_uniform_location;
Expand Down Expand Up @@ -123,6 +124,7 @@ class PdfViewOpenGLWidget : public QOpenGLWidget, protected QOpenGLExtraFunction

int rotation_index = 0;
bool is_dragging = false;
bool fastread_mode = false;

int last_mouse_down_window_x = 0;
int last_mouse_down_window_y = 0;
Expand Down Expand Up @@ -157,6 +159,7 @@ class PdfViewOpenGLWidget : public QOpenGLWidget, protected QOpenGLExtraFunction

void enable_stencil();
void write_to_stencil();
void draw_stencil_rects(int page, const std::vector<fz_rect>& rects);
void use_stencil_to_write();
void disable_stencil();

Expand Down Expand Up @@ -233,6 +236,7 @@ class PdfViewOpenGLWidget : public QOpenGLWidget, protected QOpenGLExtraFunction
void rotate_counterclockwise();

bool is_rotated();
void toggle_fastread_mode();


};
9 changes: 9 additions & 0 deletions pdf_viewer/shaders/stencil.fragment
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

#version 330 core

out vec4 color;
in vec2 screen_pos;

void main(){
color = vec4(0, 0, 0, 0);
}
10 changes: 10 additions & 0 deletions pdf_viewer/shaders/stencil.vertex
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

#version 330 core

out vec2 screen_pos;
layout (location=0) in vec2 vertex_pos;

void main(){
screen_pos = vertex_pos;
gl_Position = vec4(vertex_pos, 0.0, 1.0);
}
57 changes: 57 additions & 0 deletions pdf_viewer/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,23 @@ bool is_start_of_new_word(fz_stext_char* prev_char, fz_stext_char* current_char)
return is_start_of_new_line(prev_char, current_char);
}

fz_rect create_word_rect(const std::vector<fz_rect>& chars) {
fz_rect res;
res.x0 = res.x1 = res.y0 = res.y1 = 0;
if (chars.size() == 0) return res;
res = chars[0];

float min_x;
for (int i = 1; i < chars.size(); i++) {
if (res.x0 > chars[i].x0) res.x0 = chars[i].x0;
if (res.x1 < chars[i].x1) res.x1 = chars[i].x1;
if (res.y0 > chars[i].y0) res.y0 = chars[i].y0;
if (res.y1 < chars[i].y1) res.y1 = chars[i].y1;
}

return res;
}

fz_rect create_word_rect(const std::vector<fz_stext_char*>& chars) {
fz_rect res;
res.x0 = res.x1 = res.y0 = res.y1 = 0;
Expand All @@ -409,6 +426,7 @@ void get_flat_words_from_flat_chars(const std::vector<fz_stext_char*>& flat_char

if (flat_chars.size() == 0) return;

std::vector<std::wstring> res;
std::vector<fz_stext_char*> pending_word;
pending_word.push_back(flat_chars[0]);

Expand All @@ -427,6 +445,45 @@ void get_flat_words_from_flat_chars(const std::vector<fz_stext_char*>& flat_char
}
}

void get_word_rect_list_from_flat_chars(const std::vector<fz_stext_char*>& flat_chars,
std::vector<std::wstring>& words,
std::vector<std::vector<fz_rect>>& flat_word_rects) {

if (flat_chars.size() == 0) return;

std::vector<fz_stext_char*> pending_word;
pending_word.push_back(flat_chars[0]);

auto get_rects = [&]() {
std::vector<fz_rect> res;
for (auto chr : pending_word) {
res.push_back(fz_rect_from_quad(chr->quad));
}
return res;
};

auto get_word = [&]() {
std::wstring res;
for (auto chr : pending_word) {
res.push_back(chr->c);
}
return res;
};

for (int i = 1; i < flat_chars.size(); i++) {
if (is_start_of_new_word(flat_chars[i - 1], flat_chars[i])) {
flat_word_rects.push_back(get_rects());
words.push_back(get_word());

pending_word.clear();
pending_word.push_back(flat_chars[i]);
}
else {
pending_word.push_back(flat_chars[i]);
}
}
}

int get_num_tag_digits(int n) {
int res = 1;
while (n > 26) {
Expand Down
5 changes: 5 additions & 0 deletions pdf_viewer/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ fz_quad quad_from_rect(fz_rect r);
std::vector<fz_quad> quads_from_rects(const std::vector<fz_rect>& rects);
std::wifstream open_wifstream(const std::wstring& file_name);
void get_flat_words_from_flat_chars(const std::vector<fz_stext_char*>& flat_chars, std::vector<fz_rect>& flat_word_rects);
void get_word_rect_list_from_flat_chars(const std::vector<fz_stext_char*>& flat_chars,
std::vector<std::wstring>& words,
std::vector<std::vector<fz_rect>>& flat_word_rects);

std::vector<std::string> get_tags(int n);
int get_index_from_tag(const std::string& tag);
std::wstring truncate_string(const std::wstring& inp, int size);
std::wstring get_page_formatted_string(int page);
fz_rect create_word_rect(const std::vector<fz_rect>& chars);

0 comments on commit 036a110

Please sign in to comment.