/*********************************************************************** * PSDRV_ExtTextOut */ BOOL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx ) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); BOOL bResult = TRUE; BOOL bClipped = FALSE; BOOL bOpaque = FALSE; TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x, y, flags, debugstr_wn(str, count), count, lpDx); if(physDev->job.id == 0) return FALSE; /* write font if not already written */ PSDRV_SetFont(dev); PSDRV_SetClip(dev); /* set clipping and/or draw background */ if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL)) { PSDRV_WriteGSave(dev); PSDRV_WriteRectangle(dev, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top); if (flags & ETO_OPAQUE) { bOpaque = TRUE; PSDRV_WriteGSave(dev); PSDRV_WriteSetColor(dev, &physDev->bkColor); PSDRV_WriteFill(dev); PSDRV_WriteGRestore(dev); } if (flags & ETO_CLIPPED) { bClipped = TRUE; PSDRV_WriteClip(dev); } bResult = PSDRV_Text(dev, x, y, flags, str, count, !(bClipped && bOpaque), lpDx); PSDRV_WriteGRestore(dev); } else { bResult = PSDRV_Text(dev, x, y, flags, str, count, TRUE, lpDx); } PSDRV_ResetClip(dev); return bResult; }
static BOOL PSDRV_WriteImageMaskHeader(PHYSDEV dev, const BITMAPINFO *info, INT xDst, INT yDst, INT widthDst, INT heightDst, INT widthSrc, INT heightSrc) { PSCOLOR bkgnd, foregnd; assert(info->bmiHeader.biBitCount == 1); /* We'll write the mask with -ve polarity so that the foregnd color corresponds to a bit equal to 0 in the bitmap. */ PSDRV_CreateColor(dev, &foregnd, RGB(info->bmiColors[0].rgbRed, info->bmiColors[0].rgbGreen, info->bmiColors[0].rgbBlue) ); PSDRV_CreateColor(dev, &bkgnd, RGB(info->bmiColors[1].rgbRed, info->bmiColors[1].rgbGreen, info->bmiColors[1].rgbBlue) ); PSDRV_WriteGSave(dev); PSDRV_WriteNewPath(dev); PSDRV_WriteRectangle(dev, xDst, yDst, widthDst, heightDst); PSDRV_WriteSetColor(dev, &bkgnd); PSDRV_WriteFill(dev); PSDRV_WriteGRestore(dev); PSDRV_WriteSetColor(dev, &foregnd); PSDRV_WriteImage(dev, 1, xDst, yDst, widthDst, heightDst, widthSrc, heightSrc, TRUE, info->bmiHeader.biHeight < 0); return TRUE; }
/*********************************************************************** * PSDRV_ResetClip */ void PSDRV_ResetClip( PHYSDEV dev ) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); HRGN hrgn = CreateRectRgn(0,0,0,0); BOOL empty; empty = !GetClipRgn(dev->hdc, hrgn); if(!empty && !physDev->pathdepth) PSDRV_WriteGRestore(dev); DeleteObject(hrgn); }
/*********************************************************************** * * PSDRV_PatBlt */ BOOL PSDRV_PatBlt(PHYSDEV dev, struct bitblt_coords *dst, DWORD dwRop) { switch(dwRop) { case PATCOPY: PSDRV_SetClip(dev); PSDRV_WriteGSave(dev); PSDRV_WriteRectangle(dev, dst->visrect.left, dst->visrect.top, dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top ); PSDRV_Brush(dev, FALSE); PSDRV_WriteGRestore(dev); PSDRV_ResetClip(dev); return TRUE; case BLACKNESS: case WHITENESS: { PSCOLOR pscol; PSDRV_SetClip(dev); PSDRV_WriteGSave(dev); PSDRV_WriteRectangle(dev, dst->visrect.left, dst->visrect.top, dst->visrect.right - dst->visrect.left, dst->visrect.bottom - dst->visrect.top ); PSDRV_CreateColor( dev, &pscol, (dwRop == BLACKNESS) ? RGB(0,0,0) : RGB(0xff,0xff,0xff) ); PSDRV_WriteSetColor(dev, &pscol); PSDRV_WriteFill(dev); PSDRV_WriteGRestore(dev); PSDRV_ResetClip(dev); return TRUE; } default: FIXME("Unsupported rop %06x\n", dwRop); return FALSE; } }
/*********************************************************************** * PSDRV_SetPixel */ COLORREF PSDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) { PSCOLOR pscolor; POINT pt; pt.x = x; pt.y = y; LPtoDP( dev->hdc, &pt, 1 ); PSDRV_SetClip(dev); /* we bracket the setcolor in gsave/grestore so that we don't trash the current pen colour */ PSDRV_WriteGSave(dev); PSDRV_WriteRectangle( dev, pt.x, pt.y, 0, 0 ); PSDRV_CreateColor( dev, &pscolor, color ); PSDRV_WriteSetColor( dev, &pscolor ); PSDRV_WriteFill( dev ); PSDRV_WriteGRestore(dev); PSDRV_ResetClip(dev); return color; }
/********************************************************************** * ExtEscape (WINEPS.@) */ INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data, INT cbOutput, LPVOID out_data ) { switch(nEscape) { case QUERYESCSUPPORT: if(cbInput < sizeof(INT)) { WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput); return 0; } else { UINT num = *(const UINT *)in_data; TRACE("QUERYESCSUPPORT for %d\n", num); switch(num) { case NEXTBAND: /*case BANDINFO:*/ case SETCOPYCOUNT: case GETTECHNOLOGY: case SETLINECAP: case SETLINEJOIN: case SETMITERLIMIT: case SETCHARSET: case EXT_DEVICE_CAPS: case SET_BOUNDS: case EPSPRINTING: case POSTSCRIPT_DATA: case PASSTHROUGH: case POSTSCRIPT_PASSTHROUGH: case POSTSCRIPT_IGNORE: case BEGIN_PATH: case CLIP_TO_PATH: case END_PATH: /*case DRAWPATTERNRECT:*/ return TRUE; default: FIXME("QUERYESCSUPPORT(%d) - not supported.\n", num); return FALSE; } } case MFCOMMENT: { FIXME("MFCOMMENT(%p, %d)\n", in_data, cbInput); return 1; } case DRAWPATTERNRECT: { DRAWPATRECT *dpr = (DRAWPATRECT*)in_data; FIXME("DRAWPATTERNRECT(pos (%ld,%ld), size %ldx%ld, style %d, pattern %x), stub!\n", dpr->ptPosition.x, dpr->ptPosition.y, dpr->ptSize.x, dpr->ptSize.y, dpr->wStyle, dpr->wPattern ); return 1; } case BANDINFO: { BANDINFOSTRUCT *ibi = (BANDINFOSTRUCT*)in_data; BANDINFOSTRUCT *obi = (BANDINFOSTRUCT*)out_data; FIXME("BANDINFO(graphics %d, text %d, rect [%ldx%ld-%ldx%ld]), stub!\n", ibi->GraphicsFlag, ibi->TextFlag, ibi->GraphicsRect.top, ibi->GraphicsRect.bottom, ibi->GraphicsRect.left, ibi->GraphicsRect.right ); memcpy (obi, ibi, sizeof(*ibi)); return 1; } case NEXTBAND: { RECT *r = out_data; if(!physDev->job.banding) { physDev->job.banding = TRUE; r->left = 0; r->top = 0; r->right = physDev->horzRes; r->bottom = physDev->vertRes; TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom ); return 1; } r->left = 0; r->top = 0; r->right = 0; r->bottom = 0; TRACE("NEXTBAND rect to 0,0 - 0,0\n" ); physDev->job.banding = FALSE; return EndPage( physDev->hdc ); } case SETCOPYCOUNT: { const INT *NumCopies = in_data; INT *ActualCopies = out_data; if(cbInput != sizeof(INT)) { WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput); return 0; } TRACE("SETCOPYCOUNT %d\n", *NumCopies); *ActualCopies = 1; return 1; } case GETTECHNOLOGY: { LPSTR p = out_data; strcpy(p, "PostScript"); *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */ return 1; } case SETLINECAP: { INT newCap = *(const INT *)in_data; if(cbInput != sizeof(INT)) { WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput); return 0; } TRACE("SETLINECAP %d\n", newCap); return 0; } case SETLINEJOIN: { INT newJoin = *(const INT *)in_data; if(cbInput != sizeof(INT)) { WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput); return 0; } TRACE("SETLINEJOIN %d\n", newJoin); return 0; } case SETMITERLIMIT: { INT newLimit = *(const INT *)in_data; if(cbInput != sizeof(INT)) { WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput); return 0; } TRACE("SETMITERLIMIT %d\n", newLimit); return 0; } case SETCHARSET: /* Undocumented escape used by winword6. Switches between ANSI and a special charset. If *lpInData == 1 we require that 0x91 is quoteleft 0x92 is quoteright 0x93 is quotedblleft 0x94 is quotedblright 0x95 is bullet 0x96 is endash 0x97 is emdash 0xa0 is non break space - yeah right. If *lpInData == 0 we get ANSI. Since there's nothing else there, let's just make these the default anyway and see what happens... */ return 1; case EXT_DEVICE_CAPS: { UINT cap = *(const UINT *)in_data; if(cbInput != sizeof(UINT)) { WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput); return 0; } TRACE("EXT_DEVICE_CAPS %d\n", cap); return 0; } case SET_BOUNDS: { const RECT *r = in_data; if(cbInput != sizeof(RECT)) { WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput); return 0; } TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top, r->right, r->bottom); return 0; } case EPSPRINTING: { UINT epsprint = *(const UINT*)in_data; /* FIXME: In this mode we do not need to send page intros and page * ends according to the doc. But I just ignore that detail * for now. */ TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis"); return 1; } case POSTSCRIPT_DATA: case PASSTHROUGH: case POSTSCRIPT_PASSTHROUGH: { /* Write directly to spool file, bypassing normal PS driver * processing that is done along with writing PostScript code * to the spool. * We have a WORD before the data counting the size, but * cbInput is just this +2. * However Photoshop 7 has a bug that sets cbInput to 2 less than the * length of the string, rather than 2 more. So we'll use the WORD at * in_data[0] instead. */ if(!physDev->job.in_passthrough) { WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1); physDev->job.in_passthrough = TRUE; } return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data); } case POSTSCRIPT_IGNORE: { BOOL ret = physDev->job.quiet; TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data); physDev->job.quiet = *(const short*)in_data; return ret; } case GETSETPRINTORIENT: { /* If lpInData is present, it is a 20 byte structure, first 32 * bit LONG value is the orientation. if lpInData is NULL, it * returns the current orientation. */ FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data); return 1; } case BEGIN_PATH: TRACE("BEGIN_PATH\n"); if(physDev->pathdepth) FIXME("Nested paths not yet handled\n"); return ++physDev->pathdepth; case END_PATH: { const struct PATH_INFO *info = (const struct PATH_INFO*)in_data; TRACE("END_PATH\n"); if(!physDev->pathdepth) { ERR("END_PATH called without a BEIGN_PATH\n"); return -1; } TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n", info->RenderMode, info->FillMode, info->BkMode); switch(info->RenderMode) { case RENDERMODE_NO_DISPLAY: PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */ break; case RENDERMODE_OPEN: case RENDERMODE_CLOSED: default: FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode); break; } return --physDev->pathdepth; } case CLIP_TO_PATH: { WORD mode = *(const WORD*)in_data; switch(mode) { case CLIP_SAVE: TRACE("CLIP_TO_PATH: CLIP_SAVE\n"); PSDRV_WriteGSave(physDev); return 1; case CLIP_RESTORE: TRACE("CLIP_TO_PATH: CLIP_RESTORE\n"); PSDRV_WriteGRestore(physDev); return 1; case CLIP_INCLUSIVE: TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n"); /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */ PSDRV_WriteClip(physDev); PSDRV_WriteNewPath(physDev); return 1; case CLIP_EXCLUSIVE: FIXME("CLIP_EXCLUSIVE: not implemented\n"); return 0; default: FIXME("Unknown CLIP_TO_PATH mode %d\n", mode); return 0; } } default: FIXME("Unimplemented code 0x%x\n", nEscape); return 0; } }
/*********************************************************************** * PSDRV_PutImage */ DWORD PSDRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info, const struct gdi_image_bits *bits, struct bitblt_coords *src, struct bitblt_coords *dst, DWORD rop ) { int src_stride, dst_stride, size, x, y, width, height, bit_offset; int dst_x, dst_y, dst_width, dst_height; unsigned char *src_ptr, *dst_ptr; struct gdi_image_bits dst_bits; if (hbitmap) return ERROR_NOT_SUPPORTED; if (info->bmiHeader.biPlanes != 1) goto update_format; if (info->bmiHeader.biCompression != BI_RGB) goto update_format; if (info->bmiHeader.biBitCount == 16 || info->bmiHeader.biBitCount == 32) goto update_format; if (!bits) return ERROR_SUCCESS; /* just querying the format */ TRACE( "bpp %u %s -> %s\n", info->bmiHeader.biBitCount, wine_dbgstr_rect(&src->visrect), wine_dbgstr_rect(&dst->visrect) ); width = src->visrect.right - src->visrect.left; height = src->visrect.bottom - src->visrect.top; src_stride = get_dib_width_bytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount ); dst_stride = (width * info->bmiHeader.biBitCount + 7) / 8; src_ptr = bits->ptr; if (info->bmiHeader.biHeight > 0) src_ptr += (info->bmiHeader.biHeight - src->visrect.bottom) * src_stride; else src_ptr += src->visrect.top * src_stride; bit_offset = src->visrect.left * info->bmiHeader.biBitCount; src_ptr += bit_offset / 8; bit_offset &= 7; if (bit_offset) FIXME( "pos %s not supported\n", wine_dbgstr_rect(&src->visrect) ); size = height * dst_stride; if (src_stride != dst_stride || (info->bmiHeader.biBitCount == 24 && !bits->is_copy)) { if (!(dst_bits.ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY; dst_bits.is_copy = TRUE; dst_bits.free = free_heap_bits; } else { dst_bits.ptr = src_ptr; dst_bits.is_copy = bits->is_copy; dst_bits.free = NULL; } dst_ptr = dst_bits.ptr; switch (info->bmiHeader.biBitCount) { case 1: case 4: case 8: if (src_stride != dst_stride) for (y = 0; y < height; y++, src_ptr += src_stride, dst_ptr += dst_stride) memcpy( dst_ptr, src_ptr, dst_stride ); break; case 24: if (dst_ptr != src_ptr) for (y = 0; y < height; y++, src_ptr += src_stride, dst_ptr += dst_stride) for (x = 0; x < width; x++) { dst_ptr[x * 3] = src_ptr[x * 3 + 2]; dst_ptr[x * 3 + 1] = src_ptr[x * 3 + 1]; dst_ptr[x * 3 + 2] = src_ptr[x * 3]; } else /* swap R and B in place */ for (y = 0; y < height; y++, src_ptr += src_stride, dst_ptr += dst_stride) for (x = 0; x < width; x++) { unsigned char tmp = dst_ptr[x * 3]; dst_ptr[x * 3] = dst_ptr[x * 3 + 2]; dst_ptr[x * 3 + 2] = tmp; } break; } dst_x = dst->visrect.left; dst_y = dst->visrect.top, dst_width = dst->visrect.right - dst->visrect.left; dst_height = dst->visrect.bottom - dst->visrect.top; if (src->width * dst->width < 0) { dst_x += dst_width; dst_width = -dst_width; } if (src->height * dst->height < 0) { dst_y += dst_height; dst_height = -dst_height; } PSDRV_SetClip(dev); PSDRV_WriteGSave(dev); if (clip) PSDRV_AddClip( dev, clip ); PSDRV_WriteImageBits( dev, info, dst_x, dst_y, dst_width, dst_height, width, height, dst_bits.ptr, size ); PSDRV_WriteGRestore(dev); PSDRV_ResetClip(dev); if (dst_bits.free) dst_bits.free( &dst_bits ); return ERROR_SUCCESS; update_format: info->bmiHeader.biPlanes = 1; if (info->bmiHeader.biBitCount > 8) info->bmiHeader.biBitCount = 24; info->bmiHeader.biCompression = BI_RGB; return ERROR_BAD_FORMAT; }
/********************************************************************** * * PSDRV_Brush * */ BOOL PSDRV_Brush(PHYSDEV dev, BOOL EO) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); LOGBRUSH logbrush; BOOL ret = TRUE; if(physDev->pathdepth) return FALSE; if (!GetObjectA( GetCurrentObject(dev->hdc,OBJ_BRUSH), sizeof(logbrush), &logbrush )) { ERR("Can't get BRUSHOBJ\n"); return FALSE; } switch (logbrush.lbStyle) { case BS_SOLID: PSDRV_WriteGSave(dev); PSDRV_SetBrush(dev); PSDRV_Fill(dev, EO); PSDRV_WriteGRestore(dev); break; case BS_HATCHED: PSDRV_WriteGSave(dev); PSDRV_SetBrush(dev); switch(logbrush.lbHatch) { case HS_VERTICAL: case HS_CROSS: PSDRV_WriteGSave(dev); PSDRV_Clip(dev, EO); PSDRV_WriteHatch(dev); PSDRV_WriteStroke(dev); PSDRV_WriteGRestore(dev); if(logbrush.lbHatch == HS_VERTICAL) break; /* else fallthrough for HS_CROSS */ case HS_HORIZONTAL: PSDRV_WriteGSave(dev); PSDRV_Clip(dev, EO); PSDRV_WriteRotate(dev, 90.0); PSDRV_WriteHatch(dev); PSDRV_WriteStroke(dev); PSDRV_WriteGRestore(dev); break; case HS_FDIAGONAL: case HS_DIAGCROSS: PSDRV_WriteGSave(dev); PSDRV_Clip(dev, EO); PSDRV_WriteRotate(dev, -45.0); PSDRV_WriteHatch(dev); PSDRV_WriteStroke(dev); PSDRV_WriteGRestore(dev); if(logbrush.lbHatch == HS_FDIAGONAL) break; /* else fallthrough for HS_DIAGCROSS */ case HS_BDIAGONAL: PSDRV_WriteGSave(dev); PSDRV_Clip(dev, EO); PSDRV_WriteRotate(dev, 45.0); PSDRV_WriteHatch(dev); PSDRV_WriteStroke(dev); PSDRV_WriteGRestore(dev); break; default: ERR("Unknown hatch style\n"); ret = FALSE; break; } PSDRV_WriteGRestore(dev); break; case BS_NULL: break; case BS_PATTERN: { BITMAP bm; BYTE *bits; GetObjectA( (HBITMAP)logbrush.lbHatch, sizeof(BITMAP), &bm); TRACE("BS_PATTERN %dx%d %d bpp\n", bm.bmWidth, bm.bmHeight, bm.bmBitsPixel); bits = HeapAlloc(PSDRV_Heap, 0, bm.bmWidthBytes * bm.bmHeight); GetBitmapBits( (HBITMAP)logbrush.lbHatch, bm.bmWidthBytes * bm.bmHeight, bits); if(physDev->pi->ppd->LanguageLevel > 1) { PSDRV_WriteGSave(dev); PSDRV_WritePatternDict(dev, &bm, bits); PSDRV_Fill(dev, EO); PSDRV_WriteGRestore(dev); } else { FIXME("Trying to set a pattern brush on a level 1 printer\n"); ret = FALSE; } HeapFree(PSDRV_Heap, 0, bits); } break; case BS_DIBPATTERN: { BITMAPINFO *bmi = (BITMAPINFO *)logbrush.lbHatch; UINT usage = logbrush.lbColor; TRACE("size %dx%dx%d\n", bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bmi->bmiHeader.biBitCount); if(physDev->pi->ppd->LanguageLevel > 1) { PSDRV_WriteGSave(dev); ret = PSDRV_WriteDIBPatternDict(dev, bmi, usage); PSDRV_Fill(dev, EO); PSDRV_WriteGRestore(dev); } else { FIXME("Trying to set a pattern brush on a level 1 printer\n"); ret = FALSE; } } break; default: ret = FALSE; break; } return ret; }