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_PaintRgn */ BOOL PSDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) { RGNDATA *rgndata = NULL; RECT *pRect; DWORD size, i; TRACE("hdc=%p\n", dev->hdc); size = GetRegionData(hrgn, 0, NULL); rgndata = HeapAlloc( GetProcessHeap(), 0, size ); if(!rgndata) { ERR("Can't allocate buffer\n"); return FALSE; } GetRegionData(hrgn, size, rgndata); if (rgndata->rdh.nCount == 0) goto end; LPtoDP(dev->hdc, (POINT*)rgndata->Buffer, rgndata->rdh.nCount * 2); PSDRV_SetClip(dev); for(i = 0, pRect = (RECT*)rgndata->Buffer; i < rgndata->rdh.nCount; i++, pRect++) PSDRV_WriteRectangle(dev, pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); PSDRV_Brush(dev, 0); PSDRV_WriteNewPath(dev); PSDRV_ResetClip(dev); end: HeapFree(GetProcessHeap(), 0, rgndata); return TRUE; }
/*********************************************************************** * PSDRV_Ellipse */ BOOL PSDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom) { INT x, y, w, h; RECT rect; TRACE("%d %d - %d %d\n", left, top, right, bottom); rect.left = left; rect.top = top; rect.right = right; rect.bottom = bottom; LPtoDP( dev->hdc, (POINT *)&rect, 2 ); x = (rect.left + rect.right) / 2; y = (rect.top + rect.bottom) / 2; w = rect.right - rect.left; h = rect.bottom - rect.top; PSDRV_WriteSpool(dev, "%Ellipse\n", 9); PSDRV_SetPen(dev); PSDRV_SetClip(dev); PSDRV_WriteNewPath(dev); PSDRV_WriteArc(dev, x, y, w, h, 0.0, 360.0); PSDRV_WriteClosePath(dev); PSDRV_Brush(dev,0); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); return TRUE; }
/*********************************************************************** * PSDRV_DrawArc * * Does the work of Arc, Chord and Pie. lines is 0, 1 or 2 respectively. */ static BOOL PSDRV_DrawArc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend, int lines ) { INT x, y, h, w; double start_angle, end_angle, ratio; RECT rect; POINT start, end; rect.left = left; rect.top = top; rect.right = right; rect.bottom = bottom; LPtoDP( dev->hdc, (POINT *)&rect, 2 ); start.x = xstart; start.y = ystart; end.x = xend; end.y = yend; LPtoDP( dev->hdc, &start, 1 ); LPtoDP( dev->hdc, &end, 1 ); x = (rect.left + rect.right) / 2; y = (rect.top + rect.bottom) / 2; w = rect.right - rect.left; h = rect.bottom - rect.top; if(w < 0) w = -w; if(h < 0) h = -h; ratio = ((double)w)/h; /* angle is the angle after the rectangle is transformed to a square and is measured anticlockwise from the +ve x-axis */ start_angle = atan2((double)(y - start.y) * ratio, (double)(start.x - x)); end_angle = atan2((double)(y - end.y) * ratio, (double)(end.x - x)); start_angle *= 180.0 / PI; end_angle *= 180.0 / PI; PSDRV_WriteSpool(dev,"%DrawArc\n", 9); PSDRV_SetPen(dev); PSDRV_SetClip(dev); if(lines == 2) /* pie */ PSDRV_WriteMoveTo(dev, x, y); else PSDRV_WriteNewPath( dev ); PSDRV_WriteArc(dev, x, y, w, h, start_angle, end_angle); if(lines == 1 || lines == 2) { /* chord or pie */ PSDRV_WriteClosePath(dev); PSDRV_Brush(dev,0); } PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); return TRUE; }
/*********************************************************************** * PSDRV_DrawLine */ static void PSDRV_DrawLine( PHYSDEV dev ) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); if(physDev->pathdepth) return; if (physDev->pen.style == PS_NULL) PSDRV_WriteNewPath(dev); else PSDRV_WriteStroke(dev); }
static BOOL paint_path( PHYSDEV dev, BOOL stroke, BOOL fill ) { POINT *points; BYTE *types; BOOL ret = FALSE; int i, size = GetPath( dev->hdc, NULL, NULL, 0 ); if (size == -1) return FALSE; if (!size) return TRUE; points = HeapAlloc( GetProcessHeap(), 0, size * sizeof(*points) ); types = HeapAlloc( GetProcessHeap(), 0, size * sizeof(*types) ); if (!points || !types) goto done; if (GetPath( dev->hdc, points, types, size ) == -1) goto done; if (stroke) PSDRV_SetPen(dev); PSDRV_SetClip(dev); for (i = 0; i < size; i++) { switch (types[i]) { case PT_MOVETO: PSDRV_WriteMoveTo( dev, points[i].x, points[i].y ); break; case PT_LINETO: case PT_LINETO | PT_CLOSEFIGURE: PSDRV_WriteLineTo( dev, points[i].x, points[i].y ); if (types[i] & PT_CLOSEFIGURE) PSDRV_WriteClosePath( dev ); break; case PT_BEZIERTO: case PT_BEZIERTO | PT_CLOSEFIGURE: PSDRV_WriteCurveTo( dev, points + i ); if (types[i] & PT_CLOSEFIGURE) PSDRV_WriteClosePath( dev ); i += 2; break; } } if (fill) PSDRV_Brush( dev, GetPolyFillMode(dev->hdc) == ALTERNATE ); if (stroke) PSDRV_DrawLine(dev); else PSDRV_WriteNewPath(dev); PSDRV_ResetClip(dev); done: HeapFree( GetProcessHeap(), 0, points ); HeapFree( GetProcessHeap(), 0, types ); return ret; }
/********************************************************************** * 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; } }