示例#1
0
static void
xps_draw_linear_gradient(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area,
	struct stop *stops, int count,
	fz_xml *root, int spread)
{
	float x0, y0, x1, y1;
	int i, mi, ma;
	float dx, dy, x, y, k;
	fz_point p1, p2;
	fz_matrix inv;
	fz_rect local_area = *area;

	char *start_point_att = fz_xml_att(root, "StartPoint");
	char *end_point_att = fz_xml_att(root, "EndPoint");

	x0 = y0 = 0;
	x1 = y1 = 1;

	if (start_point_att)
		xps_parse_point(ctx, doc, start_point_att, &x0, &y0);
	if (end_point_att)
		xps_parse_point(ctx, doc, end_point_att, &x1, &y1);

	p1.x = x0; p1.y = y0; p2.x = x1; p2.y = y1;
	fz_transform_rect(&local_area, fz_invert_matrix(&inv, ctm));
	x = p2.x - p1.x; y = p2.y - p1.y;
	k = ((local_area.x0 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y);
	mi = floorf(k); ma = ceilf(k);
	k = ((local_area.x1 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y);
	mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k));
	k = ((local_area.x0 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y);
	mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k));
	k = ((local_area.x1 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y);
	mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k));
	dx = x1 - x0; dy = y1 - y0;

	if (spread == SPREAD_REPEAT)
	{
		for (i = mi; i < ma; i++)
			xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy);
	}
	else if (spread == SPREAD_REFLECT)
	{
		if ((mi % 2) != 0)
			mi--;
		for (i = mi; i < ma; i += 2)
		{
			xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy);
			xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + (i + 2) * dx, y0 + (i + 2) * dy, x1 + i * dx, y1 + i * dy);
		}
	}
	else
	{
		xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 1, x0, y0, x1, y1);
	}
}
示例#2
0
fz_bbox
fz_union_bbox(fz_bbox a, fz_bbox b)
{
    fz_bbox r;
    /* Check for empty box before infinite box */
    if (fz_is_empty_rect(a)) return b;
    if (fz_is_empty_rect(b)) return a;
    if (fz_is_infinite_rect(a)) return a;
    if (fz_is_infinite_rect(b)) return b;
    r.x0 = fz_mini(a.x0, b.x0);
    r.y0 = fz_mini(a.y0, b.y0);
    r.x1 = fz_maxi(a.x1, b.x1);
    r.y1 = fz_maxi(a.y1, b.y1);
    return r;
}
示例#3
0
fz_bbox
fz_intersect_bbox(fz_bbox a, fz_bbox b)
{
    fz_bbox r;
    /* Check for empty box before infinite box */
    if (fz_is_empty_rect(a)) return fz_empty_bbox;
    if (fz_is_empty_rect(b)) return fz_empty_bbox;
    if (fz_is_infinite_rect(a)) return b;
    if (fz_is_infinite_rect(b)) return a;
    r.x0 = fz_maxi(a.x0, b.x0);
    r.y0 = fz_maxi(a.y0, b.y0);
    r.x1 = fz_mini(a.x1, b.x1);
    r.y1 = fz_mini(a.y1, b.y1);
    return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_bbox : r;
}
示例#4
0
static void
split_block(fz_context *ctx, fz_text_page *page, int block_num, int linenum)
{
	int split_len;
	fz_text_block *block, *block2;

	if (page->len == page->cap)
	{
		int new_cap = fz_maxi(16, page->cap * 2);
		page->blocks = fz_resize_array(ctx, page->blocks, new_cap, sizeof(*page->blocks));
		page->cap = new_cap;
	}

	memmove(page->blocks+block_num+1, page->blocks+block_num, (page->len - block_num)*sizeof(*page->blocks));
	page->len++;

	block2 = fz_malloc_struct(ctx, fz_text_block);
	block = page->blocks[block_num].u.text;

	page->blocks[block_num+1].type = FZ_PAGE_BLOCK_TEXT;
	page->blocks[block_num+1].u.text = block2;
	split_len = block->len - linenum;
	block2->bbox = block->bbox; /* FIXME! */
	block2->cap = 0;
	block2->len = 0;
	block2->lines = NULL;
	block2->lines = fz_malloc_array(ctx, split_len, sizeof(fz_text_line));
	block2->cap = block2->len;
	block2->len = split_len;
	block->len = linenum;
	memcpy(block2->lines, block->lines + linenum, split_len * sizeof(fz_text_line));
	block2->lines[0].distance = 0;
}
示例#5
0
static void
split_block(fz_context *ctx, fz_text_page *page, int blocknum, int linenum)
{
	int split_len;

	if (page->len == page->cap)
	{
		int new_cap = fz_maxi(16, page->cap * 2);
		page->blocks = fz_resize_array(ctx, page->blocks, new_cap, sizeof(*page->blocks));
		page->cap = new_cap;
	}

	memmove(page->blocks+blocknum+1, page->blocks+blocknum, (page->len - blocknum)*sizeof(*page->blocks));
	page->len++;

	split_len = page->blocks[blocknum].len - linenum;
	page->blocks[blocknum+1].bbox = page->blocks[blocknum].bbox; /* FIXME! */
	page->blocks[blocknum+1].cap = 0;
	page->blocks[blocknum+1].len = 0;
	page->blocks[blocknum+1].lines = NULL;
	page->blocks[blocknum+1].lines = fz_malloc_array(ctx, split_len, sizeof(fz_text_line));
	page->blocks[blocknum+1].cap = page->blocks[blocknum+1].len;
	page->blocks[blocknum+1].len = split_len;
	page->blocks[blocknum].len = linenum;
	memcpy(page->blocks[blocknum+1].lines, page->blocks[blocknum].lines + linenum, split_len * sizeof(fz_text_line));
}
示例#6
0
static void
append_line(fz_context *ctx, fz_text_block *block, fz_text_line *line)
{
	if (block->len == block->cap)
	{
		int new_cap = fz_maxi(16, block->cap * 2);
		block->lines = fz_resize_array(ctx, block->lines, new_cap, sizeof *block->lines);
		block->cap = new_cap;
	}
	fz_union_rect(&block->bbox, &line->bbox);
	block->lines[block->len++] = *line;
}
示例#7
0
文件: path.c 项目: haggl/mupdf
static void
push_cmd(fz_context *ctx, fz_path *path, int cmd)
{
    if (path->cmd_len + 1 >= path->cmd_cap)
    {
        int new_cmd_cap = fz_maxi(16, path->cmd_cap * 2);
        path->cmds = fz_resize_array(ctx, path->cmds, new_cmd_cap, sizeof(unsigned char));
        path->cmd_cap = new_cmd_cap;
    }

    path->cmds[path->cmd_len++] = cmd;
    path->last_cmd = cmd;
}
示例#8
0
static void
append_span(fz_context *ctx, fz_text_line *line, fz_text_span *span)
{
	if (span->len == 0)
		return;
	if (line->len == line->cap)
	{
		int new_cap = fz_maxi(8, line->cap * 2);
		line->spans = fz_resize_array(ctx, line->spans, new_cap, sizeof(*line->spans));
		line->cap = new_cap;
	}
	fz_union_rect(&line->bbox, &span->bbox);
	line->spans[line->len++] = *span;
}
示例#9
0
static void
append_char(fz_context *ctx, fz_text_span *span, int c, fz_rect bbox)
{
	if (span->len == span->cap)
	{
		int new_cap = fz_maxi(64, span->cap * 2);
		span->text = fz_resize_array(ctx, span->text, new_cap, sizeof(*span->text));
		span->cap = new_cap;
	}
	fz_union_rect(&span->bbox, &bbox);
	span->text[span->len].c = c;
	span->text[span->len].bbox = bbox;
	span->len++;
}
示例#10
0
/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1333 */
static fz_pixmap *
decomp_image_banded(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor, int native_l2factor)
{
	fz_pixmap *tile = NULL, *part = NULL;
	int w = (image->w + (1 << l2factor) - 1) >> l2factor;
	int h = (image->h + (1 << l2factor) - 1) >> l2factor;
	int part_h, orig_h = image->h;
	int band = 1 << fz_maxi(8, l2factor);

	fz_var(tile);
	fz_var(part);

	fz_try(ctx)
	{
		fz_colorspace *cs = image->colorspace;
		if (indexed)
			cs = *(fz_colorspace **)cs->data; // cf. struct indexed in res_colorspace.c
		tile = fz_new_pixmap(ctx, cs, w, h);
		tile->interpolate = image->interpolate;
		tile->has_alpha = 0; /* SumatraPDF: allow optimizing non-alpha pixmaps */
		/* decompress the image in bands of 256 lines */
		for (part_h = h; part_h > 0; part_h -= band >> l2factor)
		{
			image->h = part_h > band >> l2factor ? band : ((orig_h - 1) % band) + 1;
			part = fz_decomp_image_from_stream(ctx, fz_keep_stream(stm), image, -1 - indexed, l2factor, native_l2factor);
			memcpy(tile->samples + (h - part_h) * tile->w * tile->n, part->samples, part->h * part->w * part->n);
			tile->has_alpha |= part->has_alpha; /* SumatraPDF: allow optimizing non-alpha pixmaps */
			fz_drop_pixmap(ctx, part);
			part = NULL;
		}
		/* cf. http://bugs.ghostscript.com/show_bug.cgi?id=693517 */
		if (image->usecolorkey && image->mask)
			fz_unblend_masked_tile(ctx, tile, image);
	}
	fz_always(ctx)
	{
		image->h = orig_h;
		fz_close(stm);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, part);
		fz_drop_pixmap(ctx, tile);
		fz_rethrow(ctx);
	}

	return tile;
}
示例#11
0
文件: path.c 项目: haggl/mupdf
static void
push_coord(fz_context *ctx, fz_path *path, float x, float y)
{
    if (path->coord_len + 2 >= path->coord_cap)
    {
        int new_coord_cap = fz_maxi(32, path->coord_cap * 2);
        path->coords = fz_resize_array(ctx, path->coords, new_coord_cap, sizeof(float));
        path->coord_cap = new_coord_cap;
    }

    path->coords[path->coord_len++] = x;
    path->coords[path->coord_len++] = y;

    path->current.x = x;
    path->current.y = y;
}
示例#12
0
static fz_text_block *
lookup_block_for_line(fz_context *ctx, fz_text_page *page, fz_text_line *line)
{
	float size = line->len > 0 && line->spans[0].len > 0 ? line->spans[0].style->size : 1;
	int i;

	/* SumatraPDF: TODO: tweak heuristic below */
	if (page->len > 0)
		return page->blocks;

	for (i = 0; i < page->len; i++)
	{
		fz_text_block *block = page->blocks + i;
		float w = block->bbox.x1 - block->bbox.x0;
		float dx = line->bbox.x0 - block->bbox.x0;
		float dy = line->bbox.y0 - block->bbox.y1;
		if (dy > -size * 1.5f && dy < size * PARAGRAPH_DIST)
			if (line->bbox.x0 <= block->bbox.x1 && line->bbox.x1 >= block->bbox.x0)
				if (fz_abs(dx) < w / 2)
					return block;
	}

	if (page->len == page->cap)
	{
		int new_cap = fz_maxi(16, page->cap * 2);
		page->blocks = fz_resize_array(ctx, page->blocks, new_cap, sizeof(*page->blocks));
		page->cap = new_cap;
	}

	page->blocks[page->len].bbox = fz_empty_rect;
	page->blocks[page->len].len = 0;
	page->blocks[page->len].cap = 0;
	page->blocks[page->len].lines = NULL;

	return &page->blocks[page->len++];
}
示例#13
0
static void
xps_draw_radial_gradient(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area,
	struct stop *stops, int count,
	fz_xml *root, int spread)
{
	float x0, y0, r0;
	float x1, y1, r1;
	float xrad = 1;
	float yrad = 1;
	float invscale;
	int i, ma = 1;
	fz_matrix local_ctm = *ctm;
	fz_matrix inv;
	fz_rect local_area = *area;

	char *center_att = fz_xml_att(root, "Center");
	char *origin_att = fz_xml_att(root, "GradientOrigin");
	char *radius_x_att = fz_xml_att(root, "RadiusX");
	char *radius_y_att = fz_xml_att(root, "RadiusY");

	x0 = y0 = 0.0;
	x1 = y1 = 1.0;
	xrad = 1.0;
	yrad = 1.0;

	if (origin_att)
		xps_parse_point(ctx, doc, origin_att, &x0, &y0);
	if (center_att)
		xps_parse_point(ctx, doc, center_att, &x1, &y1);
	if (radius_x_att)
		xrad = fz_atof(radius_x_att);
	if (radius_y_att)
		yrad = fz_atof(radius_y_att);

	xrad = fz_max(0.01f, xrad);
	yrad = fz_max(0.01f, yrad);

	/* scale the ctm to make ellipses */
	if (fz_abs(xrad) > FLT_EPSILON)
	{
		fz_pre_scale(&local_ctm, 1, yrad/xrad);
	}

	if (yrad != 0.0)
	{
		invscale = xrad / yrad;
		y0 = y0 * invscale;
		y1 = y1 * invscale;
	}

	r0 = 0;
	r1 = xrad;

	fz_transform_rect(&local_area, fz_invert_matrix(&inv, &local_ctm));
	ma = fz_maxi(ma, ceilf(hypotf(local_area.x0 - x0, local_area.y0 - y0) / xrad));
	ma = fz_maxi(ma, ceilf(hypotf(local_area.x1 - x0, local_area.y0 - y0) / xrad));
	ma = fz_maxi(ma, ceilf(hypotf(local_area.x0 - x0, local_area.y1 - y0) / xrad));
	ma = fz_maxi(ma, ceilf(hypotf(local_area.x1 - x0, local_area.y1 - y0) / xrad));

	if (spread == SPREAD_REPEAT)
	{
		for (i = ma - 1; i >= 0; i--)
			xps_draw_one_radial_gradient(ctx, doc, &local_ctm, stops, count, 0, x0, y0, r0 + i * xrad, x1, y1, r1 + i * xrad);
	}
	else if (spread == SPREAD_REFLECT)
	{
		if ((ma % 2) != 0)
			ma++;
		for (i = ma - 2; i >= 0; i -= 2)
		{
			xps_draw_one_radial_gradient(ctx, doc, &local_ctm, stops, count, 0, x0, y0, r0 + i * xrad, x1, y1, r1 + i * xrad);
			xps_draw_one_radial_gradient(ctx, doc, &local_ctm, stops, count, 0, x0, y0, r0 + (i + 2) * xrad, x1, y1, r1 + i * xrad);
		}
	}
	else
	{
		xps_draw_one_radial_gradient(ctx, doc, &local_ctm, stops, count, 1, x0, y0, r0, x1, y1, r1);
	}
}
示例#14
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 */
    }
}
示例#15
0
static void ui_scrollbar(int x0, int y0, int x1, int y1, int *value, int page_size, int max)
{
    static float saved_top = 0;
    static int saved_ui_y = 0;
    float top;

    int total_h = y1 - y0;
    int thumb_h = fz_maxi(x1 - x0, total_h * page_size / max);
    int avail_h = total_h - thumb_h;

    max -= page_size;

    if (max <= 0)
    {
        *value = 0;
        glColor4f(0.6f, 0.6f, 0.6f, 1.0f);
        glRectf(x0, y0, x1, y1);
        return;
    }

    top = (float) *value * avail_h / max;

    if (ui.down && !ui.active)
    {
        if (ui.x >= x0 && ui.x < x1 && ui.y >= y0 && ui.y < y1)
        {
            if (ui.y < top)
            {
                ui.active = "pgdn";
                *value -= page_size;
            }
            else if (ui.y >= top + thumb_h)
            {
                ui.active = "pgup";
                *value += page_size;
            }
            else
            {
                ui.hot = value;
                ui.active = value;
                saved_top = top;
                saved_ui_y = ui.y;
            }
        }
    }

    if (ui.active == value)
    {
        *value = (saved_top + ui.y - saved_ui_y) * max / avail_h;
    }

    if (*value < 0)
        *value = 0;
    else if (*value > max)
        *value = max;

    top = (float) *value * avail_h / max;

    glColor4f(0.6f, 0.6f, 0.6f, 1.0f);
    glRectf(x0, y0, x1, y1);
    glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
    glRectf(x0, top, x1, top + thumb_h);
}
示例#16
0
static fz_pixmap *
decomp_image_banded(fz_context *ctx, fz_stream *stm, pdf_image *image, int indexed, int l2factor, int native_l2factor, int cache)
{
	fz_pixmap *tile = NULL, *part = NULL;
	int w = (image->base.w + (1 << l2factor) - 1) >> l2factor;
	int h = (image->base.h + (1 << l2factor) - 1) >> l2factor;
	int part_h, orig_h = image->base.h;
	int band = 1 << fz_maxi(8, l2factor);

	fz_var(tile);
	fz_var(part);

	fz_try(ctx)
	{
		tile = fz_new_pixmap(ctx, image->base.colorspace, w, h);
		tile->interpolate = image->interpolate;
		tile->has_alpha = 0; /* SumatraPDF: allow optimizing non-alpha pixmaps */
		/* decompress the image in bands of 256 lines */
		for (part_h = h; part_h > 0; part_h -= band >> l2factor)
		{
			image->base.h = part_h > band >> l2factor ? band : (orig_h - 1) % band + 1;
			part = decomp_image_from_stream(ctx, fz_keep_stream(stm), image, -1, indexed, l2factor, native_l2factor, 0);
			memcpy(tile->samples + (h - part_h) * tile->w * tile->n, part->samples, part->h * part->w * part->n);
			tile->has_alpha |= part->has_alpha; /* SumatraPDF: allow optimizing non-alpha pixmaps */
			fz_drop_pixmap(ctx, part);
			part = NULL;
		}
		/* cf. http://bugs.ghostscript.com/show_bug.cgi?id=693517 */
		if (image->usecolorkey && image->base.mask)
			pdf_unblend_masked_tile(ctx, tile, image);
	}
	fz_always(ctx)
	{
		image->base.h = orig_h;
		fz_close(stm);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, part);
		fz_drop_pixmap(ctx, tile);
		fz_rethrow(ctx);
	}

	if (cache)
	{
		pdf_image_key *key = NULL;
		fz_var(key);
		fz_try(ctx)
		{
			key = fz_malloc_struct(ctx, pdf_image_key);
			key->refs = 1;
			key->image = fz_keep_image(ctx, &image->base);
			key->l2factor = l2factor;
			fz_store_item(ctx, key, tile, fz_pixmap_size(ctx, tile), &pdf_image_store_type);
		}
		fz_always(ctx)
		{
			pdf_drop_image_key(ctx, key);
		}
		fz_catch(ctx) { }
	}

	return tile;
}