Exemple #1
0
static inline void
jxr_unpack_alpha_sample(fz_context *ctx, struct info *info, jxr_image_t image, int *sp, unsigned char *dp)
{
	int bpc = jxr_get_CONTAINER_BPC(image);
	switch (bpc)
	{
	default: fz_throw(ctx, FZ_ERROR_GENERIC, "unknown alpha sample type: %d", bpc);
	case JXR_BD8: dp[0] = sp[0]; break;
	case JXR_BD10: dp[0] = sp[0] >> 2; break;
	case JXR_BD16: dp[0] = sp[0] >> 8; break;

	case JXR_BD16S:
		dp[0] = fz_clamp(sp[0] * (1.0f / (1 << 13)), 0, 1) * 255 + 0.5f;
		break;
	case JXR_BD32S:
		dp[0] = fz_clamp(sp[0] * (1.0f / (1 << 24)), 0, 1) * 255 + 0.5f;
		break;
	case JXR_BD16F:
		dp[0] = fz_clamp(float32_from_float16(sp[0]), 0, 1) * 255 + 0.5f;
		break;
	case JXR_BD32F:
		dp[0] = fz_clamp(float32_from_int32_bits(sp[0]), 0, 1) * 255 + 0.5f;
		break;
	}
}
Exemple #2
0
static inline void
jxr_unpack_sample(fz_context *ctx, struct info *info, jxr_image_t image, int *sp, unsigned char *dp)
{
	int k, bpc, comps, alpha;
	float v;

	if (info->format == JXRC_FMT_32bppRGBE)
	{
		dp[0] = sRGB_from_scRGB(ldexpf(sp[0], sp[3] - 128 - 8)) * 255 + 0.5f;
		dp[1] = sRGB_from_scRGB(ldexpf(sp[1], sp[3] - 128 - 8)) * 255 + 0.5f;
		dp[2] = sRGB_from_scRGB(ldexpf(sp[2], sp[3] - 128 - 8)) * 255 + 0.5f;
		return;
	}
	if (info->format == JXRC_FMT_16bppBGR565)
	{
		dp[0] = sp[0] << 3;
		dp[1] = sp[1] << 2;
		dp[2] = sp[2] << 3;
		return;
	}

	comps = fz_mini(fz_colorspace_n(ctx, info->cspace), jxr_get_IMAGE_CHANNELS(image));
	alpha = jxr_get_ALPHACHANNEL_FLAG(image);
	bpc = jxr_get_CONTAINER_BPC(image);

	for (k = 0; k < comps + alpha; k++)
	{
		switch (bpc)
		{
		default: fz_throw(ctx, FZ_ERROR_GENERIC, "unknown sample type: %d", bpc);
		case JXR_BD1WHITE1: dp[k] = sp[k] ? 255 : 0; break;
		case JXR_BD1BLACK1: dp[k] = sp[k] ? 0 : 255; break;
		case JXR_BD5: dp[k] = sp[k] << 3; break;
		case JXR_BD8: dp[k] = sp[k]; break;
		case JXR_BD10: dp[k] = sp[k] >> 2; break;
		case JXR_BD16: dp[k] = sp[k] >> 8; break;

		case JXR_BD16S:
			v = sp[k] * (1.0f / (1 << 13));
			goto decode_float32;
		case JXR_BD32S:
			v = sp[k] * (1.0f / (1 << 24));
			goto decode_float32;
		case JXR_BD16F:
			v = float32_from_float16(sp[k]);
			goto decode_float32;
		case JXR_BD32F:
			v = float32_from_int32_bits(sp[k]);
			goto decode_float32;
		decode_float32:
			if (k < comps)
				dp[k] = sRGB_from_scRGB(fz_clamp(v, 0, 1)) * 255 + 0.5f;
			else
				dp[k] = fz_clamp(v, 0, 1) * 255 + 0.5f;
			break;
		}
	}
}
static void
lab_to_rgb(fz_context *ctx, fz_colorspace *cs, float *lab, float *rgb)
{
	/* input is in range (0..100, -128..127, -128..127) not (0..1, 0..1, 0..1) */
	float lstar, astar, bstar, l, m, n, x, y, z, r, g, b;
	lstar = lab[0];
	astar = lab[1];
	bstar = lab[2];
	m = (lstar + 16) / 116;
	l = m + astar / 500;
	n = m - bstar / 200;
	x = fung(l);
	y = fung(m);
	z = fung(n);
	r = (3.240449f * x + -1.537136f * y + -0.498531f * z) * 0.830026f;
	g = (-0.969265f * x + 1.876011f * y + 0.041556f * z) * 1.05452f;
	b = (0.055643f * x + -0.204026f * y + 1.057229f * z) * 1.1003f;
	rgb[0] = sqrtf(fz_clamp(r, 0, 1));
	rgb[1] = sqrtf(fz_clamp(g, 0, 1));
	rgb[2] = sqrtf(fz_clamp(b, 0, 1));
}
Exemple #4
0
void
fz_insert_gel_rect(fz_context *ctx, fz_gel *gel, float fx0, float fy0, float fx1, float fy1)
{
	int x0, y0, x1, y1;
	const int hscale = fz_aa_hscale;
	const int vscale = fz_aa_vscale;

	if (fx0 <= fx1)
	{
		fx0 = floorf(fx0 * hscale);
		fx1 = ceilf(fx1 * hscale);
	}
	else
	{
		fx0 = ceilf(fx0 * hscale);
		fx1 = floorf(fx1 * hscale);
	}
	if (fy0 <= fy1)
	{
		fy0 = floorf(fy0 * vscale);
		fy1 = ceilf(fy1 * vscale);
	}
	else
	{
		fy0 = ceilf(fy0 * vscale);
		fy1 = floorf(fy1 * vscale);
	}

	fx0 = fz_clamp(fx0, gel->clip.x0, gel->clip.x1);
	fx1 = fz_clamp(fx1, gel->clip.x0, gel->clip.x1);
	fy0 = fz_clamp(fy0, gel->clip.y0, gel->clip.y1);
	fy1 = fz_clamp(fy1, gel->clip.y0, gel->clip.y1);

	/* Call fz_clamp so that clamping is done in the float domain, THEN
	 * cast down to an int. Calling fz_clampi causes problems due to the
	 * implicit cast down from float to int of the first argument
	 * over/underflowing and flipping sign at extreme values. */
	x0 = (int)fz_clamp(fx0, BBOX_MIN * hscale, BBOX_MAX * hscale);
	y0 = (int)fz_clamp(fy0, BBOX_MIN * vscale, BBOX_MAX * vscale);
	x1 = (int)fz_clamp(fx1, BBOX_MIN * hscale, BBOX_MAX * hscale);
	y1 = (int)fz_clamp(fy1, BBOX_MIN * vscale, BBOX_MAX * vscale);

	fz_insert_gel_raw(ctx, gel, x1, y0, x1, y1);
	fz_insert_gel_raw(ctx, gel, x0, y1, x0, y0);
}
Exemple #5
0
static void
fz_std_conv_color(fz_context *ctx, fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv)
{
	float rgb[3];
	int i;

	if (srcs != dsts)
	{
		assert(srcs->to_rgb && dsts->from_rgb);
		srcs->to_rgb(ctx, srcs, srcv, rgb);
		dsts->from_rgb(ctx, dsts, rgb, dstv);
		for (i = 0; i < dsts->n; i++)
			dstv[i] = fz_clamp(dstv[i], 0, 1);
	}
	else
	{
		for (i = 0; i < srcs->n; i++)
			dstv[i] = srcv[i];
	}
}
Exemple #6
0
static void cmyk_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *cmyk, float *rgb)
{
#ifdef SLOWCMYK /* from poppler */
	float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
	float r, g, b, x;
	float cm = c * m;
	float c1m = m - cm;
	float cm1 = c - cm;
	float c1m1 = 1 - m - cm1;
	float c1m1y = c1m1 * y;
	float c1m1y1 = c1m1 - c1m1y;
	float c1my = c1m * y;
	float c1my1 = c1m - c1my;
	float cm1y = cm1 * y;
	float cm1y1 = cm1 - cm1y;
	float cmy = cm * y;
	float cmy1 = cm - cmy;

	/* this is a matrix multiplication, unrolled for performance */
	x = c1m1y1 * k;		/* 0 0 0 1 */
	r = g = b = c1m1y1 - x;	/* 0 0 0 0 */
	r += 0.1373 * x;
	g += 0.1216 * x;
	b += 0.1255 * x;

	x = c1m1y * k;		/* 0 0 1 1 */
	r += 0.1098 * x;
	g += 0.1020 * x;
	x = c1m1y - x;		/* 0 0 1 0 */
	r += x;
	g += 0.9490 * x;

	x = c1my1 * k;		/* 0 1 0 1 */
	r += 0.1412 * x;
	x = c1my1 - x;		/* 0 1 0 0 */
	r += 0.9255 * x;
	b += 0.5490 * x;

	x = c1my * k;		/* 0 1 1 1 */
	r += 0.1333 * x;
	x = c1my - x;		/* 0 1 1 0 */
	r += 0.9294 * x;
	g += 0.1098 * x;
	b += 0.1412 * x;

	x = cm1y1 * k;		/* 1 0 0 1 */
	g += 0.0588 * x;
	b += 0.1412 * x;
	x = cm1y1 - x;		/* 1 0 0 0 */
	g += 0.6784 * x;
	b += 0.9373 * x;

	x = cm1y * k;		/* 1 0 1 1 */
	g += 0.0745 * x;
	x = cm1y - x;		/* 1 0 1 0 */
	g += 0.6510 * x;
	b += 0.3137 * x;

	x = cmy1 * k;		/* 1 1 0 1 */
	b += 0.0078 * x;
	x = cmy1 - x;		/* 1 1 0 0 */
	r += 0.1804 * x;
	g += 0.1922 * x;
	b += 0.5725 * x;

	x = cmy * (1-k);	/* 1 1 1 0 */
	r += 0.2118 * x;
	g += 0.2119 * x;
	b += 0.2235 * x;
	rgb[0] = fz_clamp(r, 0, 1);
	rgb[1] = fz_clamp(g, 0, 1);
	rgb[2] = fz_clamp(b, 0, 1);
#else
	rgb[0] = 1 - fz_min(1, cmyk[0] + cmyk[3]);
	rgb[1] = 1 - fz_min(1, cmyk[1] + cmyk[3]);
	rgb[2] = 1 - fz_min(1, cmyk[2] + cmyk[3]);
#endif
}
Exemple #7
0
void
fz_insert_gel(fz_context *ctx, fz_gel *gel, float fx0, float fy0, float fx1, float fy1)
{
	int x0, y0, x1, y1;
	int d, v;
	const int hscale = fz_aa_hscale;
	const int vscale = fz_aa_vscale;

	fx0 = floorf(fx0 * hscale);
	fx1 = floorf(fx1 * hscale);
	fy0 = floorf(fy0 * vscale);
	fy1 = floorf(fy1 * vscale);

	/* Call fz_clamp so that clamping is done in the float domain, THEN
	 * cast down to an int. Calling fz_clampi causes problems due to the
	 * implicit cast down from float to int of the first argument
	 * over/underflowing and flipping sign at extreme values. */
	x0 = (int)fz_clamp(fx0, BBOX_MIN * hscale, BBOX_MAX * hscale);
	y0 = (int)fz_clamp(fy0, BBOX_MIN * vscale, BBOX_MAX * vscale);
	x1 = (int)fz_clamp(fx1, BBOX_MIN * hscale, BBOX_MAX * hscale);
	y1 = (int)fz_clamp(fy1, BBOX_MIN * vscale, BBOX_MAX * vscale);

	d = clip_lerp_y(gel->clip.y0, 0, x0, y0, x1, y1, &v);
	if (d == OUTSIDE) return;
	if (d == LEAVE) { y1 = gel->clip.y0; x1 = v; }
	if (d == ENTER) { y0 = gel->clip.y0; x0 = v; }

	d = clip_lerp_y(gel->clip.y1, 1, x0, y0, x1, y1, &v);
	if (d == OUTSIDE) return;
	if (d == LEAVE) { y1 = gel->clip.y1; x1 = v; }
	if (d == ENTER) { y0 = gel->clip.y1; x0 = v; }

	d = clip_lerp_x(gel->clip.x0, 0, x0, y0, x1, y1, &v);
	if (d == OUTSIDE) {
		x0 = x1 = gel->clip.x0;
	}
	if (d == LEAVE) {
		fz_insert_gel_raw(ctx, gel, gel->clip.x0, v, gel->clip.x0, y1);
		x1 = gel->clip.x0;
		y1 = v;
	}
	if (d == ENTER) {
		fz_insert_gel_raw(ctx, gel, gel->clip.x0, y0, gel->clip.x0, v);
		x0 = gel->clip.x0;
		y0 = v;
	}

	d = clip_lerp_x(gel->clip.x1, 1, x0, y0, x1, y1, &v);
	if (d == OUTSIDE) {
		x0 = x1 = gel->clip.x1;
	}
	if (d == LEAVE) {
		fz_insert_gel_raw(ctx, gel, gel->clip.x1, v, gel->clip.x1, y1);
		x1 = gel->clip.x1;
		y1 = v;
	}
	if (d == ENTER) {
		fz_insert_gel_raw(ctx, gel, gel->clip.x1, y0, gel->clip.x1, v);
		x0 = gel->clip.x1;
		y0 = v;
	}

	fz_insert_gel_raw(ctx, gel, x0, y0, x1, y1);
}
Exemple #8
0
static void do_app(void)
{
    if (ui.key == KEY_F4 && ui.mod == GLFW_MOD_ALT)
        quit();

    if (ui.down || ui.middle || ui.right || ui.key)
        showinfo = 0;

    if (!ui.focus && ui.key)
    {
        switch (ui.key)
        {
        case 'q':
            quit();
            break;
        case 'm':
            if (number == 0)
                push_history();
            else if (number > 0 && number < nelem(marks))
                marks[number] = currentpage;
            break;
        case 't':
            if (number == 0)
            {
                if (history_count > 0)
                    pop_history();
            }
            else if (number > 0 && number < nelem(marks))
            {
                jump_to_page(marks[number]);
            }
            break;
        case 'T':
            if (number == 0)
            {
                if (future_count > 0)
                    pop_future();
            }
            break;
        case 'N':
            search_dir = -1;
            if (search_hit_page == currentpage)
                search_page = currentpage + search_dir;
            else
                search_page = currentpage;
            if (search_page >= 0 && search_page < fz_count_pages(ctx, doc))
            {
                search_hit_page = -1;
                if (search_needle)
                    search_active = 1;
            }
            break;
        case 'n':
            search_dir = 1;
            if (search_hit_page == currentpage)
                search_page = currentpage + search_dir;
            else
                search_page = currentpage;
            if (search_page >= 0 && search_page < fz_count_pages(ctx, doc))
            {
                search_hit_page = -1;
                if (search_needle)
                    search_active = 1;
            }
            break;
        case 'f':
            toggle_fullscreen();
            break;
        case 'w':
            shrinkwrap();
            break;
        case 'r':
            reload();
            break;
        case 'o':
            toggle_outline();
            break;
        case 'W':
            auto_zoom_w();
            break;
        case 'H':
            auto_zoom_h();
            break;
        case 'Z':
            auto_zoom();
            break;
        case 'z':
            currentzoom = number > 0 ? number : DEFRES;
            break;
        case '<':
            currentpage -= 10 * fz_maxi(number, 1);
            break;
        case '>':
            currentpage += 10 * fz_maxi(number, 1);
            break;
        case ',':
        case KEY_PAGE_UP:
            currentpage -= fz_maxi(number, 1);
            break;
        case '.':
        case KEY_PAGE_DOWN:
            currentpage += fz_maxi(number, 1);
            break;
        case 'b':
            number = fz_maxi(number, 1);
            while (number--) smart_move_backward();
            break;
        case ' ':
            number = fz_maxi(number, 1);
            while (number--) smart_move_forward();
            break;
        case 'g':
            jump_to_page(number - 1);
            break;
        case 'G':
            jump_to_page(fz_count_pages(ctx, doc) - 1);
            break;
        case '+':
            currentzoom = zoom_in(currentzoom);
            break;
        case '-':
            currentzoom = zoom_out(currentzoom);
            break;
        case '[':
            currentrotate += 90;
            break;
        case ']':
            currentrotate -= 90;
            break;
        case 'l':
            showlinks = !showlinks;
            break;
        case 'i':
            showinfo = !showinfo;
            break;
        case '/':
            search_dir = 1;
            showsearch = 1;
            search_input.p = search_input.text;
            search_input.q = search_input.end;
            break;
        case '?':
            search_dir = -1;
            showsearch = 1;
            search_input.p = search_input.text;
            search_input.q = search_input.end;
            break;
        case KEY_UP:
            scroll_y -= 10;
            break;
        case KEY_DOWN:
            scroll_y += 10;
            break;
        case KEY_LEFT:
            scroll_x -= 10;
            break;
        case KEY_RIGHT:
            scroll_x += 10;
            break;
        }

        if (ui.key >= '0' && ui.key <= '9')
            number = number * 10 + ui.key - '0';
        else
            number = 0;

        currentpage = fz_clampi(currentpage, 0, fz_count_pages(ctx, doc) - 1);
        currentzoom = fz_clamp(currentzoom, MINRES, MAXRES);
        while (currentrotate < 0) currentrotate += 360;
        while (currentrotate >= 360) currentrotate -= 360;

        if (search_hit_page != currentpage)
            search_hit_page = -1; /* clear highlights when navigating */

        ui_needs_update = 1;

        ui.key = 0; /* we ate the key event, so zap it */
    }
}
Exemple #9
0
static void auto_zoom_h(void)
{
    currentzoom = fz_clamp(currentzoom * canvas_h / (float)page_tex.h, MINRES, MAXRES);
}
Exemple #10
0
static void do_canvas(void)
{
    static int saved_scroll_x = 0;
    static int saved_scroll_y = 0;
    static int saved_ui_x = 0;
    static int saved_ui_y = 0;

    float x, y;

    if (oldpage != currentpage || oldzoom != currentzoom || oldrotate != currentrotate)
    {
        render_page();
        update_title();
        oldpage = currentpage;
        oldzoom = currentzoom;
        oldrotate = currentrotate;
    }

    if (ui.x >= canvas_x && ui.x < canvas_x + canvas_w && ui.y >= canvas_y && ui.y < canvas_y + canvas_h)
    {
        ui.hot = doc;
        if (!ui.active && ui.middle)
        {
            ui.active = doc;
            saved_scroll_x = scroll_x;
            saved_scroll_y = scroll_y;
            saved_ui_x = ui.x;
            saved_ui_y = ui.y;
        }
    }

    if (ui.hot == doc)
    {
        scroll_x -= ui.scroll_x * ui.lineheight * 3;
        scroll_y -= ui.scroll_y * ui.lineheight * 3;
    }

    if (ui.active == doc)
    {
        scroll_x = saved_scroll_x + saved_ui_x - ui.x;
        scroll_y = saved_scroll_y + saved_ui_y - ui.y;
    }

    if (page_tex.w <= canvas_w)
    {
        scroll_x = 0;
        x = canvas_x + (canvas_w - page_tex.w) / 2;
    }
    else
    {
        scroll_x = fz_clamp(scroll_x, 0, page_tex.w - canvas_w);
        x = canvas_x - scroll_x;
    }

    if (page_tex.h <= canvas_h)
    {
        scroll_y = 0;
        y = canvas_y + (canvas_h - page_tex.h) / 2;
    }
    else
    {
        scroll_y = fz_clamp(scroll_y, 0, page_tex.h - canvas_h);
        y = canvas_y - scroll_y;
    }

    ui_draw_image(&page_tex, x - page_tex.x, y - page_tex.y);

    do_forms(x, y);

    if (!search_active)
    {
        do_links(links, x, y);
        do_page_selection(x, y, x+page_tex.w, y+page_tex.h);
        if (search_hit_page == currentpage && search_hit_count > 0)
            do_search_hits(x, y);
    }
}