Beispiel #1
0
static void
xps_paint_tiling_brush(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *viewbox, int tile_mode, struct closure *c)
{
	fz_matrix ttm;

	xps_paint_tiling_brush_clipped(ctx, doc, ctm, viewbox, c);

	if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
	{
		ttm = *ctm;
		fz_pre_scale(fz_pre_translate(&ttm, viewbox->x1 * 2, 0), -1, 1);
		xps_paint_tiling_brush_clipped(ctx, doc, &ttm, viewbox, c);
	}

	if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
	{
		ttm = *ctm;
		fz_pre_scale(fz_pre_translate(&ttm, 0, viewbox->y1 * 2), 1, -1);
		xps_paint_tiling_brush_clipped(ctx, doc, &ttm, viewbox, c);
	}

	if (tile_mode == TILE_FLIP_X_Y)
	{
		ttm = *ctm;
		fz_pre_scale(fz_pre_translate(&ttm, viewbox->x1 * 2, viewbox->y1 * 2), -1, -1);
		xps_paint_tiling_brush_clipped(ctx, doc, &ttm, viewbox, c);
	}
}
Beispiel #2
0
void
fz_draw_html(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *inctm)
{
    fz_matrix ctm = *inctm;
    fz_pre_translate(&ctm, 0, -page_top);
    draw_block_box(ctx, box, page_top, page_bot, dev, &ctm);
}
Beispiel #3
0
static void
svg_run_use(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *root, const svg_state *inherit_state)
{
	svg_state local_state = *inherit_state;

	char *xlink_href_att = fz_xml_att(root, "xlink:href");
	char *x_att = fz_xml_att(root, "x");
	char *y_att = fz_xml_att(root, "y");

	float x = 0;
	float y = 0;

	svg_parse_common(ctx, doc, root, &local_state);
	if (x_att) x = svg_parse_length(x_att, local_state.viewbox_w, local_state.fontsize);
	if (y_att) y = svg_parse_length(y_att, local_state.viewbox_h, local_state.fontsize);

	fz_pre_translate(&local_state.transform, x, y);

	if (xlink_href_att && xlink_href_att[0] == '#')
	{
		fz_xml *linked = fz_tree_lookup(ctx, doc->idmap, xlink_href_att + 1);
		if (linked)
		{
			if (!strcmp(fz_xml_tag(linked), "symbol"))
				svg_run_use_symbol(ctx, dev, doc, root, linked, &local_state);
			else
				svg_run_element(ctx, dev, doc, linked, &local_state);
			return;
		}
	}

	fz_warn(ctx, "svg: cannot find linked symbol");
}
Beispiel #4
0
static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm)
{
	fz_html_flow *node;
	fz_text *text;
	fz_matrix trm;
	const char *s;
	float color[3];
	float x, y;
	int c, g;

	for (node = box->flow_head; node; node = node->next)
	{
		if (node->type == FLOW_IMAGE)
		{
			if (node->y > page_bot || node->y + node->h < page_top)
				continue;
		}
		else
		{
			if (node->y > page_bot || node->y < page_top)
				continue;
		}

		if (node->type == FLOW_WORD)
		{
			fz_scale(&trm, node->em, -node->em);
			text = fz_new_text(ctx, node->style->font, &trm, 0);

			x = node->x;
			y = node->y;
			s = node->text;
			while (*s)
			{
				s += fz_chartorune(&c, s);
				g = fz_encode_character(ctx, node->style->font, c);
				fz_add_text(ctx, text, g, c, x, y);
				x += fz_advance_glyph(ctx, node->style->font, g) * node->em;
			}

			color[0] = node->style->color.r / 255.0f;
			color[1] = node->style->color.g / 255.0f;
			color[2] = node->style->color.b / 255.0f;

			fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);

			fz_drop_text(ctx, text);
		}
		else if (node->type == FLOW_IMAGE)
		{
			fz_matrix local_ctm = *ctm;
			fz_pre_translate(&local_ctm, node->x, node->y);
			fz_pre_scale(&local_ctm, node->w, node->h);
			fz_fill_image(ctx, dev, node->image, &local_ctm, 1);
		}
	}
}
Beispiel #5
0
void
fz_show_string(fz_context *ctx, fz_text *text, fz_font *user_font, fz_matrix *trm, const char *s, int wmode)
{
	fz_font *font;
	int gid, ucs;
	float adv;

	while (*s)
	{
		s += fz_chartorune(&ucs, s);
		gid = fz_encode_character_with_fallback(ctx, user_font, ucs, 0, &font);
		fz_show_glyph(ctx, text, font, trm, gid, ucs, wmode);
		adv = fz_advance_glyph(ctx, font, gid, wmode);
		if (wmode == 0)
			fz_pre_translate(trm, adv, 0);
		else
			fz_pre_translate(trm, 0, -adv);
	}
}
Beispiel #6
0
static void
htdoc_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *ctm, fz_cookie *cookie)
{
	html_page *page = (html_page*)page_;
	html_document *doc = page->doc;
	fz_matrix local_ctm = *ctm;
	int n = page->number;

	fz_pre_translate(&local_ctm, doc->page_margin[L], doc->page_margin[T]);

	fz_draw_html(ctx, doc->box, n * doc->page_h, (n+1) * doc->page_h, dev, &local_ctm);
}
  QImage render(qreal dpiX, qreal dpiY, const QRectF& rect) {
    if (m_init) {
      fz_scale(&m_matrix, dpiX / 72.0f, dpiY / 72.0f);

      fz_bound_page(m_ctx, m_page, &m_bound);
      fz_transform_rect(&m_bound, &m_matrix);
      m_init = false;
    }

    if (!m_list) {
      m_list = fz_new_display_list(m_ctx);
    }

    if (!m_dev) {
      m_dev = fz_new_list_device(m_ctx, m_list);
      fz_run_page(m_ctx, m_page, m_dev, &m_matrix, 0);
    }

    fz_matrix tile;
    fz_translate(&tile, -m_bound.x0, -m_bound.y0);

    fz_pre_translate(&tile, -rect.x(), -rect.y());

    fz_rect tr;
    tr.x0 = tr.y0 = 0.0;
    int width = tr.x1 = rect.width();
    int height = tr.y1 = rect.height();

    QImage image(width, height, QImage::Format_RGB32);
    image.fill(Qt::white); // TODO: configurable

    fz_pixmap* pixmap =
      fz_new_pixmap_with_data(m_ctx,
			      fz_device_bgr(m_ctx),
			      image.width(),
			      image.height(),
			      image.bits());

    fz_device *device = fz_new_draw_device(m_ctx, pixmap);
    fz_run_display_list(m_ctx, m_list, device, &tile, &tr, 0);
    fz_drop_device(m_ctx, device);
    fz_drop_pixmap(m_ctx, pixmap);
    return image;
  }
Beispiel #8
0
static void
epub_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *ctm, fz_cookie *cookie)
{
	epub_page *page = (epub_page*)page_;
	epub_document *doc = page->doc;
	epub_chapter *ch;
	fz_matrix local_ctm = *ctm;
	int n = page->number;
	int count = 0;

	for (ch = doc->spine; ch; ch = ch->next)
	{
		int cn = ceilf(ch->box->h / ch->page_h);
		if (n < count + cn)
		{
			fz_pre_translate(&local_ctm, ch->page_margin[L], ch->page_margin[T]);
			fz_draw_html(ctx, ch->box, (n-count) * ch->page_h, (n-count+1) * ch->page_h, dev, &local_ctm);
			break;
		}
		count += cn;
	}
}
Beispiel #9
0
void
xps_parse_tiling_brush(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area,
	char *base_uri, xps_resource *dict, fz_xml *root,
	void (*func)(fz_context *ctx, xps_document*, const fz_matrix*, const fz_rect*, char*, xps_resource*, fz_xml*, void*), void *user)
{
	fz_device *dev = doc->dev;
	fz_xml *node;
	struct closure c;

	char *opacity_att;
	char *transform_att;
	char *viewbox_att;
	char *viewport_att;
	char *tile_mode_att;

	fz_xml *transform_tag = NULL;

	fz_matrix transform;
	fz_rect viewbox;
	fz_rect viewport;
	float xstep, ystep;
	float xscale, yscale;
	int tile_mode;

	opacity_att = fz_xml_att(root, "Opacity");
	transform_att = fz_xml_att(root, "Transform");
	viewbox_att = fz_xml_att(root, "Viewbox");
	viewport_att = fz_xml_att(root, "Viewport");
	tile_mode_att = fz_xml_att(root, "TileMode");

	c.base_uri = base_uri;
	c.dict = dict;
	c.root = root;
	c.user = user;
	c.func = func;

	for (node = fz_xml_down(root); node; node = fz_xml_next(node))
	{
		if (fz_xml_is_tag(node, "ImageBrush.Transform"))
			transform_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "VisualBrush.Transform"))
			transform_tag = fz_xml_down(node);
	}

	xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);

	transform = fz_identity;
	if (transform_att)
		xps_parse_render_transform(ctx, doc, transform_att, &transform);
	if (transform_tag)
		xps_parse_matrix_transform(ctx, doc, transform_tag, &transform);
	fz_concat(&transform, &transform, ctm);

	viewbox = fz_unit_rect;
	if (viewbox_att)
		xps_parse_rectangle(ctx, doc, viewbox_att, &viewbox);

	viewport = fz_unit_rect;
	if (viewport_att)
		xps_parse_rectangle(ctx, doc, viewport_att, &viewport);

	if (fabsf(viewport.x1 - viewport.x0) < 0.01f || fabsf(viewport.y1 - viewport.y0) < 0.01f)
		fz_warn(ctx, "not drawing tile for viewport size %.4f x %.4f", viewport.x1 - viewport.x0, viewport.y1 - viewport.y0);
	else if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f || fabsf(viewbox.y1 - viewbox.y0) < 0.01f)
		fz_warn(ctx, "not drawing tile for viewbox size %.4f x %.4f", viewbox.x1 - viewbox.x0, viewbox.y1 - viewbox.y0);

	/* some sanity checks on the viewport/viewbox size */
	if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return;
	if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return;
	if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return;
	if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return;

	xstep = viewbox.x1 - viewbox.x0;
	ystep = viewbox.y1 - viewbox.y0;

	xscale = (viewport.x1 - viewport.x0) / xstep;
	yscale = (viewport.y1 - viewport.y0) / ystep;

	tile_mode = TILE_NONE;
	if (tile_mode_att)
	{
		if (!strcmp(tile_mode_att, "None"))
			tile_mode = TILE_NONE;
		if (!strcmp(tile_mode_att, "Tile"))
			tile_mode = TILE_TILE;
		if (!strcmp(tile_mode_att, "FlipX"))
			tile_mode = TILE_FLIP_X;
		if (!strcmp(tile_mode_att, "FlipY"))
			tile_mode = TILE_FLIP_Y;
		if (!strcmp(tile_mode_att, "FlipXY"))
			tile_mode = TILE_FLIP_X_Y;
	}

	if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
		xstep *= 2;
	if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
		ystep *= 2;

	xps_begin_opacity(ctx, doc, &transform, area, base_uri, dict, opacity_att, NULL);

	fz_pre_translate(&transform, viewport.x0, viewport.y0);
	fz_pre_scale(&transform, xscale, yscale);
	fz_pre_translate(&transform, -viewbox.x0, -viewbox.y0);

	if (tile_mode != TILE_NONE)
	{
		int x0, y0, x1, y1;
		fz_matrix invctm;
		fz_rect local_area = *area;
		fz_transform_rect(&local_area, fz_invert_matrix(&invctm, &transform));
		x0 = floorf(local_area.x0 / xstep);
		y0 = floorf(local_area.y0 / ystep);
		x1 = ceilf(local_area.x1 / xstep);
		y1 = ceilf(local_area.y1 / ystep);

#ifdef TILE
		if ((x1 - x0) * (y1 - y0) > 1)
#else
		if (0)
#endif
		{
			fz_rect bigview = viewbox;
			bigview.x1 = bigview.x0 + xstep;
			bigview.y1 = bigview.y0 + ystep;
			fz_begin_tile(ctx, dev, &local_area, &bigview, xstep, ystep, &transform);
			xps_paint_tiling_brush(ctx, doc, &transform, &viewbox, tile_mode, &c);
			fz_end_tile(ctx, dev);
		}
		else
		{
			int x, y;
			for (y = y0; y < y1; y++)
			{
				for (x = x0; x < x1; x++)
				{
					fz_matrix ttm = transform;
					fz_pre_translate(&ttm, xstep * x, ystep * y);
					xps_paint_tiling_brush(ctx, doc, &ttm, &viewbox, tile_mode, &c);
				}
			}
		}
	}
	else
	{
		xps_paint_tiling_brush(ctx, doc, &transform, &viewbox, tile_mode, &c);
	}

	xps_end_opacity(ctx, doc, base_uri, dict, opacity_att, NULL);
}
Beispiel #10
0
static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm)
{
    fz_font *font;
    fz_html_flow *node;
    fz_text *text;
    fz_matrix trm;
    const char *s;
    float color[3];
    int c, g;

    for (node = box->flow_head; node; node = node->next)
    {
        if (node->type == FLOW_IMAGE)
        {
            if (node->y >= page_bot || node->y + node->h <= page_top)
                continue;
        }
        else
        {
            if (node->y > page_bot || node->y < page_top)
                continue;
        }

        if (node->type == FLOW_WORD)
        {
            fz_scale(&trm, node->em, -node->em);

            color[0] = node->style->color.r / 255.0f;
            color[1] = node->style->color.g / 255.0f;
            color[2] = node->style->color.b / 255.0f;

            /* TODO: reuse text object if color is unchanged */
            text = fz_new_text(ctx);


            trm.e = node->x;
            trm.f = node->y;
            s = node->content.text;
            if (node->char_r2l)
            {
                float w = 0;
                const char *t = s;

                while (*t)
                {
                    t += fz_chartorune(&c, t);
                    if (node->mirror)
                        c = ucdn_mirror(c);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    w += fz_advance_glyph(ctx, font, g) * node->em;
                }

                trm.e += w;
                while (*s)
                {
                    s += fz_chartorune(&c, s);
                    if (node->mirror)
                        c = ucdn_mirror(c);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    trm.e -= fz_advance_glyph(ctx, font, g) * node->em;
                    if (node->style->visibility == V_VISIBLE)
                        fz_add_text(ctx, text, font, 0, &trm, g, c);
                }
                trm.e += w;
            }
            else
            {
                while (*s)
                {
                    s += fz_chartorune(&c, s);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    if (node->style->visibility == V_VISIBLE)
                        fz_add_text(ctx, text, font, 0, &trm, g, c);
                    trm.e += fz_advance_glyph(ctx, font, g) * node->em;
                }
            }

            if (text)
            {
                fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);
                fz_drop_text(ctx, text);
            }
        }
        else if (node->type == FLOW_IMAGE)
        {
            if (node->style->visibility == V_VISIBLE)
            {
                fz_matrix local_ctm = *ctm;
                fz_pre_translate(&local_ctm, node->x, node->y);
                fz_pre_scale(&local_ctm, node->w, node->h);
                fz_fill_image(ctx, dev, node->content.image, &local_ctm, 1);
            }
        }
    }
}
Beispiel #11
0
/* Coordinate transformations */
fz_matrix
svg_parse_transform(fz_context *ctx, svg_document *doc, const char *str, fz_matrix transform)
{
	char keyword[20];
	int keywordlen;
	float args[6];
	int nargs;

	nargs = 0;
	keywordlen = 0;

	while (*str)
	{
		while (svg_is_whitespace_or_comma(*str))
			str ++;
		if (*str == 0)
			break;

		/*
		 * Parse keyword and opening parenthesis.
		 */

		keywordlen = 0;
		while (svg_is_alpha(*str) && keywordlen < sizeof(keyword) - 1)
			keyword[keywordlen++] = *str++;
		keyword[keywordlen] = 0;

		if (keywordlen == 0)
			fz_throw(ctx, FZ_ERROR_SYNTAX, "expected keyword in transform attribute");

		while (svg_is_whitespace(*str))
			str ++;

		if (*str != '(')
			fz_throw(ctx, FZ_ERROR_SYNTAX, "expected opening parenthesis in transform attribute");
		str ++;

		/*
		 * Parse list of numbers until closing parenthesis
		 */

		nargs = 0;
		while (*str && *str != ')' && nargs < 6)
		{
			while (svg_is_whitespace_or_comma(*str))
				str ++;
			if (svg_is_digit(*str))
				str = svg_lex_number(&args[nargs++], str);
		}

		if (*str != ')')
			fz_throw(ctx, FZ_ERROR_SYNTAX, "expected closing parenthesis in transform attribute");
		str ++;

		/*
		 * Execute the transform.
		 */

		if (!strcmp(keyword, "matrix"))
		{
			fz_matrix m;

			if (nargs != 6)
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to matrix(): %d", nargs);

			m.a = args[0];
			m.b = args[1];
			m.c = args[2];
			m.d = args[3];
			m.e = args[4];
			m.f = args[5];

			transform = fz_concat(transform, m);
		}

		else if (!strcmp(keyword, "translate"))
		{
			if (nargs != 2)
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to translate(): %d", nargs);

			transform = fz_pre_translate(transform, args[0], args[1]);
		}

		else if (!strcmp(keyword, "scale"))
		{
			if (nargs == 1)
				transform = fz_pre_scale(transform, args[0], args[0]);
			else if (nargs == 2)
				transform = fz_pre_scale(transform, args[0], args[1]);
			else
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to scale(): %d", nargs);
		}

		else if (!strcmp(keyword, "rotate"))
		{
			if (nargs != 1)
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to rotate(): %d", nargs);
			transform = fz_pre_rotate(transform, args[0]);
		}

		else if (!strcmp(keyword, "skewX"))
		{
			fz_matrix m;

			if (nargs != 1)
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to skewX(): %d", nargs);

			m.a = 1;
			m.b = 0;
			m.c = tanf(args[0] * FZ_DEGREE);
			m.d = 1;
			m.e = 0;
			m.f = 0;

			transform = fz_concat(transform, m);
		}

		else if (!strcmp(keyword, "skewY"))
		{
			fz_matrix m;

			if (nargs != 1)
				fz_throw(ctx, FZ_ERROR_SYNTAX, "wrong number of arguments to skewY(): %d", nargs);

			m.a = 1;
			m.b = tanf(args[0] * FZ_DEGREE);
			m.c = 0;
			m.d = 1;
			m.e = 0;
			m.f = 0;

			transform = fz_concat(transform, m);
		}

		else
		{
			fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown transform function: %s", keyword);
		}
	}

	return transform;
}