Ejemplo n.º 1
0
bool
sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument),
         girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  bool clear_search = true;
  girara_setting_get(session, "abort-clear-search", &clear_search);

  if (zathura->document != NULL) {
    unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
    for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
      zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
      if (page == NULL) {
        continue;
      }

      g_object_set(zathura_page_get_widget(zathura, page), "draw-links", FALSE, NULL);
      if (clear_search == true) {
        g_object_set(zathura_page_get_widget(zathura, page), "search-results", NULL, NULL);
      }
    }
  }

  girara_mode_set(session, session->modes.normal);
  girara_sc_abort(session, NULL, NULL, 0);

  return false;
}
Ejemplo n.º 2
0
/* Helper function; see sc_display_link and sc_follow. */
static bool
draw_links(zathura_t* zathura)
{
  /* set pages to draw links */
  bool show_links = false;
  unsigned int page_offset = 0;
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    GObject* obj_page_widget = G_OBJECT(page_widget);
    g_object_set(obj_page_widget, "draw-search-results", FALSE, NULL);
    if (zathura_page_get_visibility(page) == true) {
      g_object_set(obj_page_widget, "draw-links", TRUE, NULL);

      int number_of_links = 0;
      g_object_get(obj_page_widget, "number-of-links", &number_of_links, NULL);
      if (number_of_links != 0) {
        show_links = true;
      }
      g_object_set(obj_page_widget, "offset-links", page_offset, NULL);
      page_offset += number_of_links;
    } else {
      g_object_set(obj_page_widget, "draw-links", FALSE, NULL);
    }
  }
  return show_links;
}
Ejemplo n.º 3
0
bool
sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument),
         girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  bool clear_search = true;
  girara_setting_get(session, "abort-clear-search", &clear_search);

  if (zathura->document != NULL) {
    unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
    for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
      zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
      if (page == NULL) {
        continue;
      }

      GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
      g_object_set(page_widget, "draw-links", FALSE, NULL);
      if (clear_search == true) {
        g_object_set(page_widget, "draw-search-results", FALSE, NULL);
      }
    }
  }

  /* Setting the mode back here has not worked for ages. We need another way to
   * do this. Let's disable this for now.
   */
  /* girara_mode_set(session, session->modes.normal); */
  girara_sc_abort(session, NULL, NULL, 0);

  return false;
}
Ejemplo n.º 4
0
void
cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) {
    return;
  }

  GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));

  GdkRectangle view_rect;
  /* get current adjustment values */
  view_rect.y      = 0;
  view_rect.height = gtk_adjustment_get_page_size(view_vadjustment);
  view_rect.x      = 0;
  view_rect.width  = gtk_adjustment_get_page_size(view_hadjustment);

  int page_padding = 1;
  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);

  GdkRectangle center;
  center.x = (view_rect.width + 1) / 2;
  center.y = (view_rect.height + 1) / 2;
  center.height = center.width = (2 * page_padding) + 1;

  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  double scale = zathura_document_get_scale(zathura->document);

  bool updated = false;
  /* find page that fits */
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);

    GdkRectangle page_rect;
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    gtk_widget_translate_coordinates(page_widget,
        zathura->ui.session->gtk.view, 0, 0, &page_rect.x, &page_rect.y);
    page_rect.width  = zathura_page_get_width(page)  * scale;
    page_rect.height = zathura_page_get_height(page) * scale;

    if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) {
      zathura_page_set_visibility(page, true);
      if (zathura->global.update_page_number == true && updated == false
          && gdk_rectangle_intersect(&center, &page_rect, NULL) == TRUE) {
        zathura_document_set_current_page_number(zathura->document, page_id);
        updated = true;
      }
    } else {
      zathura_page_set_visibility(page, false);
    }
    zathura_page_widget_update_view_time(ZATHURA_PAGE(page_widget));
  }

  statusbar_page_number_update(zathura);
}
Ejemplo n.º 5
0
void
page_calculate_offset(zathura_t* zathura, zathura_page_t* page, page_offset_t* offset)
{
  g_return_if_fail(page != NULL);
  g_return_if_fail(offset != NULL);
  GtkWidget* widget = zathura_page_get_widget(zathura, page);

  g_return_if_fail(gtk_widget_translate_coordinates(widget,
                   zathura->ui.page_widget, 0, 0, &(offset->x), &(offset->y)) == true);
}
Ejemplo n.º 6
0
bool
cb_sc_follow(GtkEntry* entry, girara_session_t* session)
{
  g_return_val_if_fail(session != NULL, FALSE);
  g_return_val_if_fail(session->global.data != NULL, FALSE);

  zathura_t* zathura = session->global.data;
  bool eval = true;

  char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
  if (input == NULL || strlen(input) == 0) {
    eval = false;
  }

  int index = 0;
  if (eval == true) {
    index = atoi(input);
    if (index == 0 && g_strcmp0(input, "0") != 0) {
      girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input);
      eval = false;
    }
    index = index - 1;
  }

  /* set pages to draw links */
  bool invalid_index = true;
  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    if (page == NULL || zathura_page_get_visibility(page) == false) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    g_object_set(page_widget, "draw-links", FALSE, NULL);

    if (eval == true) {
      zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index);
      if (link != NULL) {
        zathura_link_evaluate(zathura, link);
        invalid_index = false;
      }
    }
  }

  if (eval == true && invalid_index == true) {
    girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input);
  }

  g_free(input);

  return (eval == TRUE) ? TRUE : FALSE;
}
Ejemplo n.º 7
0
void
render_all(zathura_t* zathura)
{
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

  /* unmark all pages */
  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    unsigned int page_height = 0, page_width = 0;
    page_calc_height_width(page, &page_height, &page_width, true);

    GtkWidget* widget = zathura_page_get_widget(zathura, page);
    gtk_widget_set_size_request(widget, page_width, page_height);
    gtk_widget_queue_resize(widget);
  }
}
Ejemplo n.º 8
0
void
update_visible_pages(zathura_t* zathura)
{
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);

  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget);

    if (page_is_visible(zathura->document, page_id) == true) {
      /* make page visible */
      if (zathura_page_get_visibility(page) == false) {
        zathura_page_set_visibility(page, true);
        zathura_page_widget_update_view_time(zathura_page_widget);
        zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page));
      }

    } else {
      /* make page invisible */
      if (zathura_page_get_visibility(page) == true) {
        zathura_page_set_visibility(page, false);
        /* If a page becomes invisible, abort the render request. */
        zathura_page_widget_abort_render_request(zathura_page_widget);
      }

      /* reset current search result */
      girara_list_t* results = NULL;
      GObject* obj_page_widget = G_OBJECT(page_widget);
      g_object_get(obj_page_widget, "search-results", &results, NULL);
      if (results != NULL) {
        g_object_set(obj_page_widget, "search-current", 0, NULL);
      }
    }
  }
}
Ejemplo n.º 9
0
bool
sc_search(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  const unsigned int num_pages = zathura_document_get_number_of_pages(zathura->document);
  const unsigned int cur_page  = zathura_document_get_current_page_number(zathura->document);
  GtkWidget *cur_page_widget = zathura_page_get_widget(zathura, zathura_document_get_page(zathura->document, cur_page));
  bool nohlsearch, first_time_after_abort;
  gboolean draw;

  nohlsearch = first_time_after_abort = false;
  draw = FALSE;
  girara_setting_get(session, "nohlsearch", &nohlsearch);

  if (nohlsearch == false) {
    g_object_get(G_OBJECT(cur_page_widget), "draw-search-results", &draw, NULL);

    if (draw == false) {
      first_time_after_abort = true;
    }

    document_draw_search_results(zathura, true);
  }

  int diff = argument->n == FORWARD ? 1 : -1;
  if (zathura->global.search_direction == BACKWARD)
    diff = -diff;

  zathura_page_t* target_page = NULL;
  int target_idx = 0;

  for (unsigned int page_id = 0; page_id < num_pages; ++page_id) {
    int tmp = cur_page + diff * page_id;
    zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);

    int num_search_results = 0, current = -1;
    g_object_get(G_OBJECT(page_widget), "search-current", &current, "search-length", &num_search_results, NULL);
    if (num_search_results == 0 || current == -1) {
      continue;
    }

    if (first_time_after_abort == true || (tmp + num_pages) % num_pages != cur_page) {
      target_page = page;
      target_idx = diff == 1 ? 0 : num_search_results - 1;
      break;
    }

    if (diff == 1 && current < num_search_results - 1) {
      /* the next result is on the same page */
      target_page = page;
      target_idx = current + 1;
    } else if (diff == -1 && current > 0) {
      target_page = page;
      target_idx = current - 1;
    } else {
      /* the next result is on a different page */
      g_object_set(G_OBJECT(page_widget), "search-current", -1, NULL);

      for (int npage_id = 1; page_id < num_pages; ++npage_id) {
        int ntmp = cur_page + diff * (page_id + npage_id);
        zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages);
        GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage);
        g_object_get(G_OBJECT(npage_page_widget), "search-length", &num_search_results, NULL);
        if (num_search_results != 0) {
          target_page = npage;
          target_idx = diff == 1 ? 0 : num_search_results - 1;
          break;
        }
      }
    }

    break;
  }

  if (target_page != NULL) {
    girara_list_t* results = NULL;
    GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page);
    GObject* obj_page_widget = G_OBJECT(page_widget);
    g_object_set(obj_page_widget, "search-current", target_idx, NULL);
    g_object_get(obj_page_widget, "search-results", &results, NULL);

    /* Need to adjust rectangle to page scale and orientation */
    zathura_rectangle_t* rect = girara_list_nth(results, target_idx);
    zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect);

    bool search_hadjust = true;
    girara_setting_get(session, "search-hadjust", &search_hadjust);

    /* compute the position of the center of the page */
    double pos_x = 0;
    double pos_y = 0;
    page_number_to_position(zathura->document, zathura_page_get_index(target_page),
                            0.5, 0.5, &pos_x, &pos_y);

    /* correction to center the current result                          */
    /* NOTE: rectangle is in viewport units, already scaled and rotated */
    unsigned int cell_height = 0;
    unsigned int cell_width = 0;
    zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width);

    unsigned int doc_height = 0;
    unsigned int doc_width = 0;
    zathura_document_get_document_size(zathura->document, &doc_height, &doc_width);

    /* compute the center of the rectangle, which will be aligned to the center
       of the viewport */
    double center_x = (rectangle.x1 + rectangle.x2) / 2;
    double center_y = (rectangle.y1 + rectangle.y2) / 2;

    pos_y += (center_y - (double)cell_height/2) / (double)doc_height;
    if (search_hadjust == true) {
      pos_x += (center_x - (double)cell_width/2) / (double)doc_width;
    }

    /* move to position */
    zathura_jumplist_add(zathura);
    position_set(zathura, pos_x, pos_y);
    zathura_jumplist_add(zathura);
  }

  return false;
}
Ejemplo n.º 10
0
bool
sc_search(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  const int num_pages = zathura_document_get_number_of_pages(zathura->document);
  const int cur_page  = zathura_document_get_current_page_number(zathura->document);

  int diff = argument->n == FORWARD ? 1 : -1;
  if (zathura->global.search_direction == BACKWARD)
    diff = -diff;

  zathura_page_t* target_page = NULL;
  int target_idx = 0;

  for (int page_id = 0; page_id < num_pages; ++page_id) {
    int tmp = cur_page + diff * page_id;
    zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);

    int num_search_results = 0, current = -1;
    g_object_get(page_widget, "search-current", &current,
                 "search-length", &num_search_results, NULL);
    if (num_search_results == 0 || current == -1) {
      continue;
    }

    if (diff == 1 && current < num_search_results - 1) {
      /* the next result is on the same page */
      target_page = page;
      target_idx = current + 1;
    } else if (diff == -1 && current > 0) {
      target_page = page;
      target_idx = current - 1;
    } else {
      /* the next result is on a different page */
      zathura_jumplist_save(zathura);

      g_object_set(page_widget, "search-current", -1, NULL);

      for (int npage_id = 1; page_id < num_pages; ++npage_id) {
        int ntmp = cur_page + diff * (page_id + npage_id);
        zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages);
        zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(npage));
        GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage);
        g_object_get(npage_page_widget, "search-length", &num_search_results, NULL);
        if (num_search_results != 0) {
          target_page = npage;
          target_idx = diff == 1 ? 0 : num_search_results - 1;
          break;
        }
      }

      zathura_jumplist_add(zathura);
    }

    break;
  }

  if (target_page != NULL) {
    girara_list_t* results = NULL;
    GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page);
    g_object_set(page_widget, "search-current", target_idx, NULL);
    g_object_get(page_widget, "search-results", &results, NULL);

    zathura_rectangle_t* rect = girara_list_nth(results, target_idx);
    zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect);
    page_offset_t offset;
    page_calculate_offset(zathura, target_page, &offset);

    GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
    int y = offset.y - gtk_adjustment_get_page_size(view_vadjustment) / 2 + rectangle.y1;
    set_adjustment(view_vadjustment, y);

    bool search_hadjust = true;
    girara_setting_get(session, "search-hadjust", &search_hadjust);
    if (search_hadjust == true) {
      GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
      int x = offset.x - gtk_adjustment_get_page_size(view_hadjustment) / 2 + rectangle.x1;
      set_adjustment(view_hadjustment, x);
    }
  }

  return false;
}
Ejemplo n.º 11
0
bool
cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(input != NULL, false);
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  if (zathura->document == NULL || strlen(input) == 0) {
    return false;
  }

  zathura_error_t error = ZATHURA_ERROR_OK;

  /* set search direction */
  zathura->global.search_direction = argument->n;

  unsigned int number_of_pages     = zathura_document_get_number_of_pages(zathura->document);
  unsigned int current_page_number = zathura_document_get_current_page_number(zathura->document);

  /* reset search highlighting */
  bool nohlsearch = false;
  girara_setting_get(session, "nohlsearch", &nohlsearch);

  /* search pages */
  for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
    unsigned int index = (page_id + current_page_number) % number_of_pages;
    zathura_page_t* page = zathura_document_get_page(zathura->document, index);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    g_object_set(page_widget, "draw-links", FALSE, NULL);

    zathura_renderer_lock(zathura->sync.render_thread);
    girara_list_t* result = zathura_page_search_text(page, input, &error);
    zathura_renderer_unlock(zathura->sync.render_thread);

    if (result == NULL || girara_list_size(result) == 0) {
      girara_list_free(result);
      g_object_set(page_widget, "search-results", NULL, NULL);

      if (error == ZATHURA_ERROR_NOT_IMPLEMENTED) {
        break;
      } else {
        continue;
      }
    }

    g_object_set(page_widget, "search-results", result, NULL);

    if (argument->n == BACKWARD) {
      /* start at bottom hit in page */
      g_object_set(page_widget, "search-current", girara_list_size(result) - 1, NULL);
    } else {
      g_object_set(page_widget, "search-current", 0, NULL);
    }
  }

  girara_argument_t* arg = g_try_malloc0(sizeof(girara_argument_t));
  if (arg == NULL) {
    return false;
  }

  arg->n = FORWARD;
  sc_search(session, arg, NULL, 0);
  g_free(arg);

  return true;
}
Ejemplo n.º 12
0
void
cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) {
    return;
  }

  GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));

  /* current adjustment values */
  GdkRectangle view_rect = {
    .x      = 0,
    .y      = 0,
    .width  = gtk_adjustment_get_page_size(view_hadjustment),
    .height = gtk_adjustment_get_page_size(view_vadjustment)
  };

  int page_padding = 1;
  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);

  GdkRectangle center = {
    .x      = (view_rect.width  + 1) / 2,
    .y      = (view_rect.height + 1) / 2,
    .width  = (2 * page_padding) + 1,
    .height = (2 * page_padding) + 1
  };

  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  double scale = zathura_document_get_scale(zathura->document);

  bool updated = false;
  /* find page that fits */
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);

    GdkRectangle page_rect = {
      .width  = zathura_page_get_width(page)  * scale,
      .height = zathura_page_get_height(page) * scale
    };
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    gtk_widget_translate_coordinates(page_widget,
                                     zathura->ui.session->gtk.view, 0, 0, &page_rect.x, &page_rect.y);

    if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) {
      zathura_page_set_visibility(page, true);
      if (zathura->global.update_page_number == true && updated == false
          && gdk_rectangle_intersect(&center, &page_rect, NULL) == TRUE) {
        zathura_document_set_current_page_number(zathura->document, page_id);
        updated = true;
      }
    } else {
      zathura_page_set_visibility(page, false);
    }
    zathura_page_widget_update_view_time(ZATHURA_PAGE(page_widget));
  }

  statusbar_page_number_update(zathura);
}

void
cb_pages_per_row_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
  g_return_if_fail(value != NULL);
  g_return_if_fail(session != NULL);
  g_return_if_fail(session->global.data != NULL);
  zathura_t* zathura = session->global.data;

  int pages_per_row = *(int*) value;

  if (pages_per_row < 1) {
    pages_per_row = 1;
  }

  unsigned int first_page_column = 1;
  girara_setting_get(session, "first-page-column", &first_page_column);

  page_widget_set_mode(zathura, pages_per_row, first_page_column);

  if (zathura->document != NULL) {
    unsigned int current_page = zathura_document_get_current_page_number(zathura->document);
    page_set_delayed(zathura, current_page);
  }
}
Ejemplo n.º 13
0
static bool
render(zathura_t* zathura, zathura_page_t* page)
{
  if (zathura == NULL || page == NULL || zathura->sync.render_thread->about_to_close == true) {
    return false;
  }

  /* create cairo surface */
  unsigned int page_width  = 0;
  unsigned int page_height = 0;
  page_calc_height_width(page, &page_height, &page_width, false);

  cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height);

  if (surface == NULL) {
    return false;
  }

  cairo_t* cairo = cairo_create(surface);

  if (cairo == NULL) {
    cairo_surface_destroy(surface);
    return false;
  }

  cairo_save(cairo);
  cairo_set_source_rgb(cairo, 1, 1, 1);
  cairo_rectangle(cairo, 0, 0, page_width, page_height);
  cairo_fill(cairo);
  cairo_restore(cairo);
  cairo_save(cairo);

  double scale = zathura_document_get_scale(zathura->document);
  if (fabs(scale - 1.0f) > FLT_EPSILON) {
    cairo_scale(cairo, scale, scale);
  }

  render_lock(zathura->sync.render_thread);
  if (zathura_page_render(page, cairo, false) != ZATHURA_ERROR_OK) {
    render_unlock(zathura->sync.render_thread);
    cairo_destroy(cairo);
    cairo_surface_destroy(surface);
    return false;
  }

  render_unlock(zathura->sync.render_thread);
  cairo_restore(cairo);
  cairo_destroy(cairo);

  const int rowstride  = cairo_image_surface_get_stride(surface);
  unsigned char* image = cairo_image_surface_get_data(surface);

  /* recolor */
  /* uses a representation of a rgb color as follows:
     - a lightness scalar (between 0,1), which is a weighted average of r, g, b,
     - a hue vector, which indicates a radian direction from the grey axis, inside the equal lightness plane.
     - a saturation scalar between 0,1. It is 0 when grey, 1 when the color is in the boundary of the rgb cube.
  */
  if (zathura->global.recolor == true) {
    /* RGB weights for computing lightness. Must sum to one */
    double a[] = {0.30, 0.59, 0.11};

    double l1, l2, l, s, u, t;
    double h[3];
    double rgb1[3], rgb2[3], rgb[3];

    color2double(&zathura->ui.colors.recolor_dark_color, rgb1);
    color2double(&zathura->ui.colors.recolor_light_color, rgb2);

    l1 = (a[0]*rgb1[0] + a[1]*rgb1[1] + a[2]*rgb1[2]);
    l2 = (a[0]*rgb2[0] + a[1]*rgb2[1] + a[2]*rgb2[2]);

    for (unsigned int y = 0; y < page_height; y++) {
      unsigned char* data = image + y * rowstride;

      for (unsigned int x = 0; x < page_width; x++) {
        /* Careful. data color components blue, green, red. */
        rgb[0] = (double) data[2] / 256.;
        rgb[1] = (double) data[1] / 256.;
        rgb[2] = (double) data[0] / 256.;

        /* compute h, s, l data   */
        l = a[0]*rgb[0] + a[1]*rgb[1] + a[2]*rgb[2];

        h[0] = rgb[0] - l;
        h[1] = rgb[1] - l;
        h[2] = rgb[2] - l;

        /* u is the maximum possible saturation for given h and l. s is a rescaled saturation between 0 and 1 */
        u = colorumax(h, l, 0, 1);
        if (u == 0) {
          s = 0;
        } else {
          s = 1/u;
        }

        /* Interpolates lightness between light and dark colors. white goes to light, and black goes to dark. */
        t = l;
        l = t * (l2 - l1) + l1;

        if (zathura->global.recolor_keep_hue == true) {
          /* adjusting lightness keeping hue of current color. white and black go to grays of same ligtness
             as light and dark colors. */
          u = colorumax(h, l, l1, l2);
          data[2] = (unsigned char)round(255.*(l + s*u * h[0]));
          data[1] = (unsigned char)round(255.*(l + s*u * h[1]));
          data[0] = (unsigned char)round(255.*(l + s*u * h[2]));
        } else {
          /* Linear interpolation between dark and light with color ligtness as a parameter */
          data[2] = (unsigned char)round(255.*(t * (rgb2[0] - rgb1[0]) + rgb1[0]));
          data[1] = (unsigned char)round(255.*(t * (rgb2[1] - rgb1[1]) + rgb1[1]));
          data[0] = (unsigned char)round(255.*(t * (rgb2[2] - rgb1[2]) + rgb1[2]));
        }

        data += 4;
      }
    }
  }

  if (zathura->sync.render_thread->about_to_close == false) {
    /* update the widget */
    gdk_threads_enter();
    GtkWidget* widget = zathura_page_get_widget(zathura, page);
    zathura_page_widget_update_surface(ZATHURA_PAGE(widget), surface);
    gdk_threads_leave();
  } else {
    cairo_surface_destroy(surface);
  }

  return true;
}