static int _write (int fd, char *buf, int maxlen, int buflen, const unsigned char *src, int srclen) { if (buflen < 0) return buflen; while (srclen) { int len; len = buflen + srclen; if (len > maxlen) len = maxlen; len -= buflen; memcpy (buf + buflen, src, len); buflen += len; srclen -= len; src += len; if (buflen == maxlen) { if (! _writen (fd, buf, buflen)) return -1; buflen = 0; } } return buflen; }
static const char * write_ppm (cairo_surface_t *surface, int fd) { char buf[4096]; cairo_format_t format; const char *format_str; const unsigned char *data; int len; int width, height, stride; int i, j; data = cairo_image_surface_get_data (surface); height = cairo_image_surface_get_height (surface); width = cairo_image_surface_get_width (surface); stride = cairo_image_surface_get_stride (surface); format = cairo_image_surface_get_format (surface); if (format == CAIRO_FORMAT_ARGB32) { /* see if we can convert to a standard ppm type and trim a few bytes */ const unsigned char *alpha = data; for (j = height; j--; alpha += stride) { for (i = 0; i < width; i++) { if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000) goto done; } } format = CAIRO_FORMAT_RGB24; done: ; } switch (format) { case CAIRO_FORMAT_ARGB32: /* XXX need true alpha for svg */ format_str = "P7"; break; case CAIRO_FORMAT_RGB24: format_str = "P6"; break; case CAIRO_FORMAT_A8: format_str = "P5"; break; case CAIRO_FORMAT_A1: default: return "unhandled image format"; } len = sprintf (buf, "%s %d %d 255\n", format_str, width, height); for (j = 0; j < height; j++) { const unsigned int *row = (unsigned int *) (data + stride * j); switch ((int) format) { case CAIRO_FORMAT_ARGB32: len = _write (fd, buf, sizeof (buf), len, (unsigned char *) row, 4 * width); break; case CAIRO_FORMAT_RGB24: for (i = 0; i < width; i++) { unsigned char rgb[3]; unsigned int p = *row++; rgb[0] = (p & 0xff0000) >> 16; rgb[1] = (p & 0x00ff00) >> 8; rgb[2] = (p & 0x0000ff) >> 0; len = _write (fd, buf, sizeof (buf), len, rgb, 3); } break; case CAIRO_FORMAT_A8: len = _write (fd, buf, sizeof (buf), len, (unsigned char *) row, width); break; } if (len < 0) return "write failed"; } if (len && ! _writen (fd, buf, len)) return "write failed"; return NULL; }
int writen(register int fd, register char *ptr, register int nbytes) { return _writen(fd, ptr, nbytes, &timeout, 1); }