diff --git a/dlls/wineps/Makefile.in b/dlls/wineps/Makefile.in index e47c2fa4ec0..3ec1fb561c5 100644 --- a/dlls/wineps/Makefile.in +++ b/dlls/wineps/Makefile.in @@ -60,6 +60,7 @@ C_SRCS = \ color.c \ download.c \ driver.c \ + encode.c \ escape.c \ font.c \ glyphlist.c \ diff --git a/dlls/wineps/bitmap.c b/dlls/wineps/bitmap.c index c0da3b4bcaa..487a027c965 100644 --- a/dlls/wineps/bitmap.c +++ b/dlls/wineps/bitmap.c @@ -204,6 +204,15 @@ static BOOL PSDRV_WriteImageMaskHeader(PSDRV_PDEVICE *physDev, const BITMAPINFO return TRUE; } +static inline DWORD max_rle_size(DWORD size) +{ + return size + (size + 127) / 128 + 1; +} + +static inline DWORD max_ascii85_size(DWORD size) +{ + return (size + 3) / 4 * 5; +} /*************************************************************************** * @@ -222,9 +231,11 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs LONG fullSrcWidth, fullSrcHeight; INT widthbytes; WORD bpp, compression; - const char *ptr; INT line; POINT pt[2]; + const BYTE *src_ptr; + BYTE *dst_ptr, *bitmap, *rle, *ascii85; + DWORD rle_len, ascii85_len, bitmap_size; TRACE("%p (%d,%d %dx%d) -> (%d,%d %dx%d)\n", physDev->hdc, xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst); @@ -261,12 +272,14 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs /* Use imagemask rather than image */ PSDRV_WriteImageMaskHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); + src_ptr = bits; + src_ptr += (ySrc * widthbytes); if(xSrc & 7) FIXME("This won't work...\n"); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteBytes(physDev, ptr + xSrc/8, (widthSrc+7)/8); + bitmap_size = heightSrc * ((widthSrc + 7) / 8); + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += ((widthSrc + 7) / 8)) + memcpy(dst_ptr, src_ptr + xSrc / 8, (widthSrc + 7) / 8); break; case 4: @@ -274,12 +287,14 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs PSDRV_WriteGSave(physDev); PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); + src_ptr = bits; + src_ptr += (ySrc * widthbytes); if(xSrc & 1) FIXME("This won't work...\n"); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteBytes(physDev, ptr + xSrc/2, (widthSrc+1)/2); + bitmap_size = heightSrc * ((widthSrc + 1) / 2); + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += ((widthSrc + 1) / 2)) + memcpy(dst_ptr, src_ptr + xSrc/2, (widthSrc+1)/2); break; case 8: @@ -287,10 +302,12 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs PSDRV_WriteGSave(physDev); PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteBytes(physDev, ptr + xSrc, widthSrc); + src_ptr = bits; + src_ptr += (ySrc * widthbytes); + bitmap_size = heightSrc * widthSrc; + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes, dst_ptr += widthSrc) + memcpy(dst_ptr, src_ptr + xSrc, widthSrc); break; case 15: @@ -300,10 +317,31 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteDIBits16(physDev, (WORD *)ptr + xSrc, widthSrc); + + src_ptr = bits; + src_ptr += (ySrc * widthbytes); + bitmap_size = heightSrc * widthSrc * 2; + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) { + const WORD *words = (const WORD *)src_ptr + xSrc; + int i; + for(i = 0; i < widthSrc; i++) { + BYTE r, g, b; + + /* We want 0x0 -- 0x1f to map to 0x0 -- 0xff */ + r = words[i] >> 10 & 0x1f; + r = r << 3 | r >> 2; + g = words[i] >> 5 & 0x1f; + g = g << 3 | g >> 2; + b = words[i] & 0x1f; + b = b << 3 | b >> 2; + dst_ptr[0] = r; + dst_ptr[1] = g; + dst_ptr[2] = b; + dst_ptr += 3; + } + } break; case 24: @@ -312,10 +350,20 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteDIBits24(physDev, ptr + xSrc * 3, widthSrc); + src_ptr = bits; + src_ptr += (ySrc * widthbytes); + bitmap_size = heightSrc * widthSrc * 3; + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) { + const BYTE *byte = src_ptr + xSrc * 3; + int i; + for(i = 0; i < widthSrc; i++) { + dst_ptr[0] = byte[i * 3 + 2]; + dst_ptr[1] = byte[i * 3 + 1]; + dst_ptr[2] = byte[i * 3]; + dst_ptr += 3; + } + } break; case 32: @@ -324,10 +372,20 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc); - ptr = bits; - ptr += (ySrc * widthbytes); - for(line = 0; line < heightSrc; line++, ptr += widthbytes) - PSDRV_WriteDIBits32(physDev, ptr + xSrc * 3, widthSrc); + src_ptr = bits; + src_ptr += (ySrc * widthbytes); + bitmap_size = heightSrc * widthSrc * 3; + dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size); + for(line = 0; line < heightSrc; line++, src_ptr += widthbytes) { + const BYTE *byte = src_ptr + xSrc * 4; + int i; + for(i = 0; i < widthSrc; i++) { + dst_ptr[0] = byte[i * 4 + 2]; + dst_ptr[1] = byte[i * 4 + 1]; + dst_ptr[2] = byte[i * 4]; + dst_ptr += 3; + } + } break; default: @@ -335,7 +393,16 @@ INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDs return FALSE; } - PSDRV_WriteSpool(physDev, ">\n", 2); /* End-of-Data for /HexASCIIDecodeFilter */ + + rle = HeapAlloc(GetProcessHeap(), 0, max_rle_size(bitmap_size)); + rle_len = RLE_encode(bitmap, bitmap_size, rle); + HeapFree(GetProcessHeap(), 0, bitmap); + ascii85 = HeapAlloc(GetProcessHeap(), 0, max_ascii85_size(rle_len)); + ascii85_len = ASCII85_encode(rle, rle_len, ascii85); + HeapFree(GetProcessHeap(), 0, rle); + PSDRV_WriteData(physDev, ascii85, ascii85_len); + HeapFree(GetProcessHeap(), 0, ascii85); + PSDRV_WriteSpool(physDev, "~>\n", 3); PSDRV_WriteGRestore(physDev); PSDRV_ResetClip(physDev); return abs(heightSrc); diff --git a/dlls/wineps/encode.c b/dlls/wineps/encode.c new file mode 100644 index 00000000000..64e669cca38 --- /dev/null +++ b/dlls/wineps/encode.c @@ -0,0 +1,109 @@ +/* + * PostScript filter functions + * + * Copyright 2003 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include "psdrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(psdrv); + +DWORD RLE_encode(BYTE *in_buf, DWORD len, BYTE *out_buf) +{ + BYTE *next_in = in_buf, *next_out = out_buf; + DWORD rl; + + while(next_in < in_buf + len) { + if(next_in + 1 < in_buf + len) { + if(*next_in == *(next_in + 1)) { + next_in += 2; + rl = 2; + while(next_in < in_buf + len && *next_in == *(next_in - 1) && rl < 128) { + next_in++; + rl++; + } + *next_out++ = 257 - rl; + *next_out++ = *(next_in - 1); + } else { + rl = 0; + next_out++; + while(next_in < in_buf + len && rl < 128) { + if(next_in + 2 < in_buf + len && *next_in == *(next_in + 1)) { + if(rl == 127 || *next_in == *(next_in + 2)) + break; + } + *next_out++ = *next_in++; + rl++; + } + *(next_out - rl - 1) = rl - 1; + } + } else { /* special case: begin of run on last byte */ + *next_out++ = 0; + *next_out++ = *next_in; + break; + } + } + *next_out++ = 128; + return next_out - out_buf; +} + +DWORD ASCII85_encode(BYTE *in_buf, DWORD len, BYTE *out_buf) +{ + DWORD number; + BYTE *next_in = in_buf, *next_out = out_buf; + int i; + + while(next_in + 3 < in_buf + len) { + number = (next_in[0] << 24) | + (next_in[1] << 16) | + (next_in[2] << 8) | + (next_in[3] ); + next_in += 4; + if(number == 0) + *next_out++ = 'z'; + else { + for(i = 4; i >= 0; i--) { + next_out[i] = number % 85 + '!'; + number /= 85; + } + next_out += 5; + } + } + + if(next_in != in_buf + len) { + number = (*next_in++ << 24) & 0xff000000; + if(next_in < in_buf + len) + number |= ((*next_in++ << 16) & 0x00ff0000); + if(next_in < in_buf + len) + number |= ((*next_in++ << 8) & 0x0000ff00); + + for(i = len % 4 + 1; i < 5; i++) + number /= 85; + + for(i = len % 4; i >= 0; i--) { + next_out[i] = number % 85 + '!'; + number /= 85; + } + next_out += len % 4 + 1; + } + + return next_out - out_buf; +} diff --git a/dlls/wineps/ps.c b/dlls/wineps/ps.c index 4ff02000572..42634b5f762 100644 --- a/dlls/wineps/ps.c +++ b/dlls/wineps/ps.c @@ -636,8 +636,8 @@ BOOL PSDRV_WriteImageDict(PSDRV_PDEVICE *physDev, WORD depth, INT xDst, INT yDst const char decode1[] = " /Decode [0 %d]\n"; const char decode3[] = " /Decode [0 1 0 1 0 1]\n"; - const char end[] = " /DataSource currentfile /ASCIIHexDecode filter\n>> image\n"; - const char endmask[] = " /DataSource currentfile /ASCIIHexDecode filter\n>> imagemask\n"; + const char end[] = " /DataSource currentfile /ASCII85Decode filter /RunLengthDecode filter\n>> image\n"; + const char endmask[] = " /DataSource currentfile /ASCII85Decode filter /RunLengthDecode filter\n>> imagemask\n"; const char endbits[] = " /DataSource <%s>\n>> image\n"; @@ -683,7 +683,7 @@ BOOL PSDRV_WriteImageDict(PSDRV_PDEVICE *physDev, WORD depth, INT xDst, INT yDst } -BOOL PSDRV_WriteBytes(PSDRV_PDEVICE *physDev, const BYTE *bytes, int number) +BOOL PSDRV_WriteBytes(PSDRV_PDEVICE *physDev, const BYTE *bytes, DWORD number) { char *buf = HeapAlloc(PSDRV_Heap, 0, number * 3 + 1); char *ptr; @@ -704,81 +704,18 @@ BOOL PSDRV_WriteBytes(PSDRV_PDEVICE *physDev, const BYTE *bytes, int number) return TRUE; } -BOOL PSDRV_WriteDIBits16(PSDRV_PDEVICE *physDev, const WORD *words, int number) +BOOL PSDRV_WriteData(PSDRV_PDEVICE *physDev, const BYTE *data, DWORD number) { - char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1); - char *ptr; - int i; + int num, num_left = number; - ptr = buf; + do { + num = min(num_left, 60); + PSDRV_WriteSpool(physDev, data, num); + PSDRV_WriteSpool(physDev, "\n", 1); + data += num; + num_left -= num; + } while(num_left); - for(i = 0; i < number; i++) { - int r, g, b; - - /* We want 0x0 -- 0x1f to map to 0x0 -- 0xff */ - - r = words[i] >> 10 & 0x1f; - r = r << 3 | r >> 2; - g = words[i] >> 5 & 0x1f; - g = g << 3 | g >> 2; - b = words[i] & 0x1f; - b = b << 3 | b >> 2; - sprintf(ptr, "%02x%02x%02x", r, g, b); - ptr += 6; - if(((i & 0x7) == 0x7) || (i == number - 1)) { - strcpy(ptr, "\n"); - ptr++; - } - } - PSDRV_WriteSpool(physDev, buf, ptr - buf); - - HeapFree(PSDRV_Heap, 0, buf); - return TRUE; -} - -BOOL PSDRV_WriteDIBits24(PSDRV_PDEVICE *physDev, const BYTE *bits, int number) -{ - char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1); - char *ptr; - int i; - - ptr = buf; - - for(i = 0; i < number; i++) { - sprintf(ptr, "%02x%02x%02x", bits[i * 3 + 2], bits[i * 3 + 1], - bits[i * 3]); - ptr += 6; - if(((i & 0x7) == 0x7) || (i == number - 1)) { - strcpy(ptr, "\n"); - ptr++; - } - } - PSDRV_WriteSpool(physDev, buf, ptr - buf); - - HeapFree(PSDRV_Heap, 0, buf); - return TRUE; -} - -BOOL PSDRV_WriteDIBits32(PSDRV_PDEVICE *physDev, const BYTE *bits, int number) -{ - char *buf = HeapAlloc(PSDRV_Heap, 0, number * 7 + 1); - char *ptr; - int i; - - ptr = buf; - - for(i = 0; i < number; i++) { - sprintf(ptr, "%02x%02x%02x", bits[i * 4 + 2], bits[i * 4 + 1], - bits[i * 4]); - ptr += 6; - if(((i & 0x7) == 0x7) || (i == number - 1)) { - strcpy(ptr, "\n"); - ptr++; - } - } - PSDRV_WriteSpool(physDev, buf, ptr - buf); - - HeapFree(PSDRV_Heap, 0, buf); return TRUE; } diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h index 6b2eb70d46f..3eeed843f7f 100644 --- a/dlls/wineps/psdrv.h +++ b/dlls/wineps/psdrv.h @@ -446,10 +446,8 @@ extern BOOL PSDRV_WriteRGB(PSDRV_PDEVICE *physDev, COLORREF *map, int number); extern BOOL PSDRV_WriteImageDict(PSDRV_PDEVICE *physDev, WORD depth, INT xDst, INT yDst, INT widthDst, INT heightDst, INT widthSrc, INT heightSrc, char *bits, BOOL mask); -extern BOOL PSDRV_WriteBytes(PSDRV_PDEVICE *physDev, const BYTE *bytes, int number); -extern BOOL PSDRV_WriteDIBits16(PSDRV_PDEVICE *physDev, const WORD *words, int number); -extern BOOL PSDRV_WriteDIBits24(PSDRV_PDEVICE *physDev, const BYTE *bits, int number); -extern BOOL PSDRV_WriteDIBits32(PSDRV_PDEVICE *physDev, const BYTE *bits, int number); +extern BOOL PSDRV_WriteBytes(PSDRV_PDEVICE *physDev, const BYTE *bytes, DWORD number); +extern BOOL PSDRV_WriteData(PSDRV_PDEVICE *physDev, const BYTE *byte, DWORD number); extern DWORD PSDRV_WriteSpool(PSDRV_PDEVICE *physDev, LPCSTR lpData, DWORD cch); extern BOOL PSDRV_WritePatternDict(PSDRV_PDEVICE *physDev, BITMAP *bm, BYTE *bits); extern BOOL PSDRV_WriteDIBPatternDict(PSDRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage); @@ -543,4 +541,8 @@ extern TYPE42 *T42_download_header(PSDRV_PDEVICE *physDev, char *ps_name, extern BOOL T42_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, DWORD index, char *glyph_name); extern void T42_free(TYPE42 *t42); + +extern DWORD RLE_encode(BYTE *in_buf, DWORD len, BYTE *out_buf); +extern DWORD ASCII85_encode(BYTE *in_buf, DWORD len, BYTE *out_buf); + #endif