dvi_document_do_color_special (DviContext *dvi, const char *prefix, const char *arg)
{
        if (strncmp (arg, "pop", 3) == 0) {
                mdvi_pop_color (dvi);
        } else if (strncmp (arg, "push", 4) == 0) {
                /* Find color source: Named, CMYK or RGB */
                const char *tmp = arg + 4;
		
                while (isspace (*tmp)) tmp++;

                if (!strncmp ("rgb", tmp, 3)) {
			gdouble rgb[3];
                        guchar red, green, blue;

			parse_color (tmp + 4, rgb, 3);
			
                        red = 255 * rgb[0];
                        green = 255 * rgb[1];
                        blue = 255 * rgb[2];

                        mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
                } else if (!strncmp ("hsb", tmp, 4)) {
                        gdouble hsb[3];
                        guchar red, green, blue;

			parse_color (tmp + 4, hsb, 3);
			
                        if (hsb2rgb (hsb[0], hsb[1], hsb[2], &red, &green, &blue))
                                mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
                } else if (!strncmp ("cmyk", tmp, 4)) {
			gdouble cmyk[4];
                        double r, g, b;
			guchar red, green, blue;
			
			parse_color (tmp + 5, cmyk, 4);

                        r = 1.0 - cmyk[0] - cmyk[3];
                        if (r < 0.0)
                                r = 0.0;
                        g = 1.0 - cmyk[1] - cmyk[3];
                        if (g < 0.0)
                                g = 0.0;
                        b = 1.0 - cmyk[2] - cmyk[3];
                        if (b < 0.0)
                                b = 0.0;

			red = r * 255 + 0.5;
			green = g * 255 + 0.5;
			blue = b * 255 + 0.5;
			
                        mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
		} else if (!strncmp ("gray ", tmp, 5)) {
			gdouble gray;
			guchar rgb;

			parse_color (tmp + 5, &gray, 1);

			rgb = gray * 255 + 0.5;

			mdvi_push_color (dvi, RGB2ULONG (rgb, rgb, rgb), 0xFFFFFFFF);
                } else {
                        GdkColor color;
			
                        if (gdk_color_parse (tmp, &color)) {
				guchar red, green, blue;

				red = color.red * 255 / 65535.;
				green = color.green * 255 / 65535.;
				blue = color.blue * 255 / 65535.;

                                mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
			}
                }
        }
}
dvi_document_do_color_special (DviContext *dvi, const char *prefix, const char *arg)
{
        if (strncmp (arg, "pop", 3) == 0) {
                mdvi_pop_color (dvi);
        } else if (strncmp (arg, "push", 4) == 0) {
                 
                const char *tmp = arg + 4;
		
                while (isspace (*tmp)) tmp++;

                if (!strncmp ("rgb", tmp, 3)) {
			gdouble rgb[3];
                        guchar red, green, blue;

			parse_color (tmp + 4, rgb, 3);
			
                        red = 255 * rgb[0];
                        green = 255 * rgb[1];
                        blue = 255 * rgb[2];

                        mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
                } else if (!strncmp ("hsb", tmp, 4)) {
                        gdouble hsb[3];
                        guchar red, green, blue;

			parse_color (tmp + 4, hsb, 3);
			
                        if (hsb2rgb (hsb[0], hsb[1], hsb[2], &red, &green, &blue))
                                mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
                } else if (!strncmp ("cmyk", tmp, 4)) {
			gdouble cmyk[4];
                        double r, g, b;
			guchar red, green, blue;
			
			parse_color (tmp + 5, cmyk, 4);

                        r = 1.0 - cmyk[0] - cmyk[3];
                        if (r < 0.0)
                                r = 0.0;
                        g = 1.0 - cmyk[1] - cmyk[3];
                        if (g < 0.0)
                                g = 0.0;
                        b = 1.0 - cmyk[2] - cmyk[3];
                        if (b < 0.0)
                                b = 0.0;

			red = r * 255 + 0.5;
			green = g * 255 + 0.5;
			blue = b * 255 + 0.5;
			
                        mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
		} else if (!strncmp ("gray ", tmp, 5)) {
			gdouble gray;
			guchar rgb;

			parse_color (tmp + 5, &gray, 1);

			rgb = gray * 255 + 0.5;

			mdvi_push_color (dvi, RGB2ULONG (rgb, rgb, rgb), 0xFFFFFFFF);
                } else {
                        GdkColor color;
			
                        if (gdk_color_parse (tmp, &color)) {
				guchar red, green, blue;

				red = color.red * 255 / 65535.;
				green = color.green * 255 / 65535.;
				blue = color.blue * 255 / 65535.;

                                mdvi_push_color (dvi, RGB2ULONG (red, green, blue), 0xFFFFFFFF);
			}
                }
        }
}