static void render_text_end(void) { render_text--; if (text_really_locked) { render_unlock(); text_really_locked = 0; } assert(!text_locked); }
static void render_text_unlock(void) { text_locked--; #if 1 /* nothing: we coalesce multiple locks */ #else render_unlock(); text_really_locked = 0; #endif }
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; } bool firsthit = true; 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); if (nohlsearch == false) { document_draw_search_results(zathura, true); } /* 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); render_lock(zathura->sync.render_thread); girara_list_t* result = zathura_page_search_text(page, input, &error); render_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 (firsthit == true) { if (page_id != 0) { page_set_delayed(zathura, zathura_page_get_index(page)); } 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); } firsthit = false; } } return true; }
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; }