cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t		*pdf_operators,
					const cairo_stroke_style_t	*style,
					double				 scale)
{
    double *dash = style->dash;
    int num_dashes = style->num_dashes;
    double dash_offset = style->dash_offset;
    double line_width = style->line_width * scale;

    /* PostScript has "special needs" when it comes to zero-length
     * dash segments with butt caps. It apparently (at least
     * according to ghostscript) draws hairlines for this
     * case. That's not what the cairo semantics want, so we first
     * touch up the array to eliminate any 0.0 values that will
     * result in "on" segments.
     */
    if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) {
	int i;

	/* If there's an odd number of dash values they will each get
	 * interpreted as both on and off. So we first explicitly
	 * expand the array to remove the duplicate usage so that we
	 * can modify some of the values.
	 */
	if (num_dashes % 2) {
	    dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
	    if (unlikely (dash == NULL))
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);

	    memcpy (dash, style->dash, num_dashes * sizeof (double));
	    memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));

	    num_dashes *= 2;
	}

	for (i = 0; i < num_dashes; i += 2) {
	    if (dash[i] == 0.0) {
		/* Do not modify the dashes in-place, as we may need to also
		 * replay this stroke to an image fallback.
		 */
		if (dash == style->dash) {
		    dash = _cairo_malloc_ab (num_dashes, sizeof (double));
		    if (unlikely (dash == NULL))
			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
		    memcpy (dash, style->dash, num_dashes * sizeof (double));
		}

		/* If we're at the front of the list, we first rotate
		 * two elements from the end of the list to the front
		 * of the list before folding away the 0.0. Or, if
		 * there are only two dash elements, then there is
		 * nothing at all to draw.
		 */
		if (i == 0) {
		    double last_two[2];

		    if (num_dashes == 2) {
			free (dash);
			return CAIRO_INT_STATUS_NOTHING_TO_DO;
		    }

		    /* The cases of num_dashes == 0, 1, or 3 elements
		     * cannot exist, so the rotation of 2 elements
		     * will always be safe */
		    memcpy (last_two, dash + num_dashes - 2, sizeof (last_two));
		    memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double));
		    memcpy (dash, last_two, sizeof (last_two));
		    dash_offset += dash[0] + dash[1];
		    i = 2;
		}
		dash[i-1] += dash[i+1];
		num_dashes -= 2;
		memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double));
		/* If we might have just rotated, it's possible that
		 * we rotated a 0.0 value to the front of the list.
		 * Set i to -2 so it will get incremented to 0. */
		if (i == 2)
		    i = -2;
	    }
	}
    }

    if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "%f w\n",
				     line_width);
	pdf_operators->line_width = line_width;
    }

    if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "%d J\n",
				     _cairo_pdf_line_cap (style->line_cap));
	pdf_operators->line_cap = style->line_cap;
    }

    if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "%d j\n",
				     _cairo_pdf_line_join (style->line_join));
	pdf_operators->line_join = style->line_join;
    }

    if (num_dashes) {
	int d;

	_cairo_output_stream_printf (pdf_operators->stream, "[");
	for (d = 0; d < num_dashes; d++)
	    _cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
	_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
				     dash_offset * scale);
	pdf_operators->has_dashes = TRUE;
    } else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) {
	_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
	pdf_operators->has_dashes = FALSE;
    }
    if (dash != style->dash)
        free (dash);

    if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "%f M ",
				     style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
	pdf_operators->miter_limit = style->miter_limit;
    }
    pdf_operators->has_line_style = TRUE;

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
                                  const cairo_pattern_t *source,
                                  cairo_glyph_t	 *glyphs,
                                  int			  num_glyphs,
                                  cairo_scaled_font_t	 *scaled_font,
                                  cairo_bool_t		  glyph_indexing)
{
#if CAIRO_HAS_WIN32_FONT
    WORD glyph_buf_stack[STACK_GLYPH_SIZE];
    WORD *glyph_buf = glyph_buf_stack;
    int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
    int *dxy_buf = dxy_buf_stack;

    BOOL win_result = 0;
    int i, j;

    cairo_solid_pattern_t *solid_pattern;
    COLORREF color;

    cairo_matrix_t device_to_logical;

    int start_x, start_y;
    double user_x, user_y;
    int logical_x, logical_y;
    unsigned int glyph_index_option;

    /* We can only handle win32 fonts */
    assert (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32);

    /* We can only handle opaque solid color sources and destinations */
    assert (_cairo_pattern_is_opaque_solid(source));
    assert (dst->format == CAIRO_FORMAT_RGB24);

    solid_pattern = (cairo_solid_pattern_t *)source;
    color = RGB(((int)solid_pattern->color.red_short) >> 8,
                ((int)solid_pattern->color.green_short) >> 8,
                ((int)solid_pattern->color.blue_short) >> 8);

    cairo_win32_scaled_font_get_device_to_logical(scaled_font, &device_to_logical);

    SaveDC(dst->dc);

    cairo_win32_scaled_font_select_font(scaled_font, dst->dc);
    SetTextColor(dst->dc, color);
    SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT);
    SetBkMode(dst->dc, TRANSPARENT);

    if (num_glyphs > STACK_GLYPH_SIZE) {
        glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
        dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
    }

    /* It is vital that dx values for dxy_buf are calculated from the delta of
     * _logical_ x coordinates (not user x coordinates) or else the sum of all
     * previous dx values may start to diverge from the current glyph's x
     * coordinate due to accumulated rounding error. As a result strings could
     * be painted shorter or longer than expected. */

    user_x = glyphs[0].x;
    user_y = glyphs[0].y;

    cairo_matrix_transform_point(&device_to_logical,
                                 &user_x, &user_y);

    logical_x = _cairo_lround (user_x);
    logical_y = _cairo_lround (user_y);

    start_x = logical_x;
    start_y = logical_y;

    for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
        glyph_buf[i] = (WORD) glyphs[i].index;
        if (i == num_glyphs - 1) {
            dxy_buf[j] = 0;
            dxy_buf[j+1] = 0;
        } else {
            double next_user_x = glyphs[i+1].x;
            double next_user_y = glyphs[i+1].y;
            int next_logical_x, next_logical_y;

            cairo_matrix_transform_point(&device_to_logical,
                                         &next_user_x, &next_user_y);

            next_logical_x = _cairo_lround (next_user_x);
            next_logical_y = _cairo_lround (next_user_y);

            dxy_buf[j] = _cairo_lround (next_logical_x - logical_x);
            dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y);

            logical_x = next_logical_x;
            logical_y = next_logical_y;
        }
    }

    if (glyph_indexing)
        glyph_index_option = ETO_GLYPH_INDEX;
    else
        glyph_index_option = 0;

    win_result = ExtTextOutW(dst->dc,
                             start_x,
                             start_y,
                             glyph_index_option | ETO_PDY,
                             NULL,
                             glyph_buf,
                             num_glyphs,
                             dxy_buf);
    if (!win_result) {
        _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
    }

    RestoreDC(dst->dc, -1);

    if (glyph_buf != glyph_buf_stack) {
        free(glyph_buf);
        free(dxy_buf);
    }
    return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
#else
    return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}