Пример #1
0
static void
fz_draw_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_draw_device *dev = devp->user;
	unsigned char colorbv[FZ_MAX_COLORS + 1];
	float colorfv[FZ_MAX_COLORS];
	fz_matrix tm, trm, trunc_trm;
	fz_pixmap *glyph;
	int i, x, y, gid;
	fz_draw_state *state = &dev->stack[dev->top];
	fz_colorspace *model = state->dest->colorspace;
	fz_bbox scissor = state->scissor;

	if (state->blendmode & FZ_BLEND_KNOCKOUT)
		state = fz_knockout_begin(dev);

	fz_convert_color(dev->ctx, model, colorfv, colorspace, color);
	for (i = 0; i < model->n; i++)
		colorbv[i] = colorfv[i] * 255;
	colorbv[i] = alpha * 255;

	tm = text->trm;

	for (i = 0; i < text->len; i++)
	{
		gid = text->items[i].gid;
		if (gid < 0)
			continue;

		tm.e = text->items[i].x;
		tm.f = text->items[i].y;
		trm = fz_concat(tm, ctm);
		x = floorf(trm.e);
		y = floorf(trm.f);

		trunc_trm = trm;
		trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
		trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

		scissor.x0 -= x; scissor.x1 -= x;
		scissor.y0 -= y; scissor.y1 -= y;

		glyph = fz_render_stroked_glyph(dev->ctx, text->font, gid, trunc_trm, ctm, stroke, scissor);
		if (glyph)
		{
			draw_glyph(colorbv, state->dest, glyph, x, y, state->scissor);
			if (state->shape)
				draw_glyph(colorbv, state->shape, glyph, x, y, state->scissor);
			fz_drop_pixmap(dev->ctx, glyph);
		}
		else
		{
			fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm);
			if (path)
			{
				fz_draw_stroke_path(devp, path, stroke, fz_identity, colorspace, color, alpha);
				fz_free_path(dev->ctx, path);
			}
			else
			{
				fz_warn(dev->ctx, "cannot render glyph");
			}
		}
	}

	if (state->blendmode & FZ_BLEND_KNOCKOUT)
		fz_knockout_end(dev);
}
Пример #2
0
static void
fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate)
{
	fz_draw_device *dev = devp->user;
	fz_context *ctx = dev->ctx;
	fz_bbox bbox;
	fz_pixmap *mask, *dest, *shape;
	fz_matrix tm, trm, trunc_trm;
	fz_pixmap *glyph;
	int i, x, y, gid;
	fz_draw_state *state;
	fz_colorspace *model;

	/* If accumulate == 0 then this text object is guaranteed complete */
	/* If accumulate == 1 then this text object is the first (or only) in a sequence */
	/* If accumulate == 2 then this text object is a continuation */

	state = push_stack(dev);
	model = state->dest->colorspace;

	if (accumulate == 0)
	{
		/* make the mask the exact size needed */
		bbox = fz_bbox_covering_rect(fz_bound_text(dev->ctx, text, ctm));
		bbox = fz_intersect_bbox(bbox, state->scissor);
	}
	else
	{
		/* be conservative about the size of the mask needed */
		bbox = state->scissor;
	}

	if (accumulate == 0 || accumulate == 1)
	{
		mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox);
		fz_clear_pixmap(dev->ctx, mask);
		dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox);
		fz_clear_pixmap(dev->ctx, dest);
		if (state->shape)
		{
			shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox);
			fz_clear_pixmap(dev->ctx, shape);
		}
		else
			shape = NULL;

		state[1].blendmode |= FZ_BLEND_ISOLATED;
		state[1].scissor = bbox;
		state[1].dest = dest;
		state[1].mask = mask;
		state[1].shape = shape;
#ifdef DUMP_GROUP_BLENDS
		dump_spaces(dev->top-1, "Clip (text) begin\n");
#endif
	}
	else
	{
		mask = state->mask;
		dev->top--;
	}

	if (!fz_is_empty_rect(bbox) && mask)
	{
		tm = text->trm;

		for (i = 0; i < text->len; i++)
		{
			gid = text->items[i].gid;
			if (gid < 0)
				continue;

			tm.e = text->items[i].x;
			tm.f = text->items[i].y;
			trm = fz_concat(tm, ctm);
			x = floorf(trm.e);
			y = floorf(trm.f);

			trunc_trm = trm;
			trunc_trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
			trunc_trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

			glyph = fz_render_glyph(dev->ctx, text->font, gid, trunc_trm, model, bbox);
			if (glyph)
			{
				draw_glyph(NULL, mask, glyph, x, y, bbox);
				if (state[1].shape)
					draw_glyph(NULL, state[1].shape, glyph, x, y, bbox);
				fz_drop_pixmap(dev->ctx, glyph);
			}
			else
			{
				fz_path *path = fz_outline_glyph(dev->ctx, text->font, gid, trm);
				if (path)
				{
					fz_pixmap *old_dest;
					float white = 1;

					state = &dev->stack[dev->top];
					old_dest = state[0].dest;
					state[0].dest = state[0].mask;
					state[0].mask = NULL;
					fz_try(ctx)
					{
						fz_draw_fill_path(devp, path, 0, fz_identity, fz_device_gray, &white, 1);
					}
					fz_always(ctx)
					{
						state[0].mask = state[0].dest;
						state[0].dest = old_dest;
						fz_free_path(dev->ctx, path);
					}
					fz_catch(ctx)
					{
						fz_rethrow(ctx);
					}
				}
				else
				{
					fz_warn(dev->ctx, "cannot render glyph for clipping");
				}
			}
		}
Пример #3
0
static font *
svg_dev_text_span_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text_span *span, const fz_matrix *ctm)
{
	svg_device *sdev = (svg_device*)dev;
	fz_output *out = sdev->out;
	int i, font_idx;
	font *fnt;
	fz_matrix shift = fz_identity;

	for (font_idx = 0; font_idx < sdev->num_fonts; font_idx++)
	{
		if (sdev->fonts[font_idx].font == span->font)
			break;
	}
	if (font_idx == sdev->num_fonts)
	{
		/* New font */
		if (font_idx == sdev->max_fonts)
		{
			int newmax = sdev->max_fonts * 2;
			if (newmax == 0)
				newmax = 4;
			sdev->fonts = fz_resize_array(ctx, sdev->fonts, newmax, sizeof(*sdev->fonts));
			memset(&sdev->fonts[font_idx], 0, (newmax - font_idx) * sizeof(sdev->fonts[0]));
			sdev->max_fonts = newmax;
		}
		sdev->fonts[font_idx].id = sdev->id++;
		sdev->fonts[font_idx].font = fz_keep_font(ctx, span->font);
		sdev->num_fonts++;
	}
	fnt = &sdev->fonts[font_idx];

	for (i=0; i < span->len; i++)
	{
		fz_text_item *it = &span->items[i];
		int gid = it->gid;

		if (gid < 0)
			continue;
		if (gid >= fnt->max_sentlist)
		{
			int j;
			fnt->sentlist = fz_resize_array(ctx, fnt->sentlist, gid+1, sizeof(fnt->sentlist[0]));
			for (j = fnt->max_sentlist; j <= gid; j++)
			{
				fnt->sentlist[j].x_off = FLT_MIN;
				fnt->sentlist[j].y_off = FLT_MIN;
			}
			fnt->max_sentlist = gid+1;
		}
		if (fnt->sentlist[gid].x_off == FLT_MIN)
		{
			/* Need to send this one */
			fz_rect rect;
			fz_path *path;
			path = fz_outline_glyph(ctx, span->font, gid, &fz_identity);
			if (path)
			{
				fz_bound_path(ctx, path, NULL, &fz_identity, &rect);
				shift.e = -rect.x0;
				shift.f = -rect.y0;
				fz_transform_path(ctx, path, &shift);
				out = start_def(ctx, sdev);
				fz_printf(ctx, out, "<symbol id=\"font_%x_%x\">", fnt->id, gid);
				fz_printf(ctx, out, "<path");
				svg_dev_path(ctx, sdev, path);
				fz_printf(ctx, out, "/>\n");
			}
			else
			{
				fz_bound_glyph(ctx, span->font, gid, &fz_identity, &rect);
				shift.e = -rect.x0;
				shift.f = -rect.y0;
				out = start_def(ctx, sdev);
				fz_printf(ctx, out, "<symbol id=\"font_%x_%x\">", fnt->id, gid);
				fz_run_t3_glyph(ctx, span->font, gid, &shift, dev);
			}
			fz_printf(ctx, out, "</symbol>");
			out = end_def(ctx, sdev);
			fnt->sentlist[gid].x_off = rect.x0;
			fnt->sentlist[gid].y_off = rect.y0;
		}
	}
	return fnt;
}