/*********************************************************************** * PSDRV_Rectangle */ BOOL PSDRV_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) { PSDRV_PDEVICE *physDev = get_psdrv_dev( dev ); 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 ); /* Windows does something truly hacky here. If we're in passthrough mode and our rop is R2_NOP, then we output the string below. This is used in Office 2k when inserting eps files */ if(physDev->job.in_passthrough && !physDev->job.had_passthrough_rect && GetROP2(dev->hdc) == R2_NOP) { char buf[256]; sprintf(buf, "N %d %d %d %d B\n", rect.right - rect.left, rect.bottom - rect.top, rect.left, rect.top); write_spool(dev, buf, strlen(buf)); physDev->job.had_passthrough_rect = TRUE; return TRUE; } PSDRV_SetPen(dev); PSDRV_SetClip(dev); PSDRV_WriteRectangle(dev, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top ); PSDRV_Brush(dev,0); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); 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_PolyPolyline */ BOOL PSDRV_PolyPolyline( PHYSDEV dev, const POINT* pts, const DWORD* counts, DWORD polylines ) { DWORD polyline, line, total; POINT *dev_pts, *pt; TRACE("\n"); for (polyline = total = 0; polyline < polylines; polyline++) total += counts[polyline]; if (!(dev_pts = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*dev_pts) ))) return FALSE; memcpy( dev_pts, pts, total * sizeof(*dev_pts) ); LPtoDP( dev->hdc, dev_pts, total ); pt = dev_pts; PSDRV_WriteSpool(dev, "%PolyPolyline\n",14); PSDRV_SetPen(dev); PSDRV_SetClip(dev); for(polyline = 0; polyline < polylines; polyline++) { PSDRV_WriteMoveTo(dev, pt->x, pt->y); pt++; for(line = 1; line < counts[polyline]; line++, pt++) PSDRV_WriteLineTo(dev, pt->x, pt->y); } HeapFree( GetProcessHeap(), 0, dev_pts ); 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_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; }
/*********************************************************************** * PSDRV_RoundRect */ BOOL PSDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height ) { RECT rect[2]; rect[0].left = left; rect[0].top = top; rect[0].right = right; rect[0].bottom = bottom; rect[1].left = 0; rect[1].top = 0; rect[1].right = ell_width; rect[1].bottom = ell_height; LPtoDP( dev->hdc, (POINT *)rect, 4 ); left = rect[0].left; top = rect[0].top; right = rect[0].right; bottom = rect[0].bottom; if (left > right) { INT tmp = left; left = right; right = tmp; } if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; } ell_width = rect[1].right - rect[1].left; ell_height = rect[1].bottom - rect[1].top; if (ell_width > right - left) ell_width = right - left; if (ell_height > bottom - top) ell_height = bottom - top; PSDRV_WriteSpool(dev, "%RoundRect\n",11); PSDRV_SetPen(dev); PSDRV_SetClip(dev); PSDRV_WriteMoveTo( dev, left, top + ell_height/2 ); PSDRV_WriteArc( dev, left + ell_width/2, top + ell_height/2, ell_width, ell_height, 90.0, 180.0); PSDRV_WriteLineTo( dev, right - ell_width/2, top ); PSDRV_WriteArc( dev, right - ell_width/2, top + ell_height/2, ell_width, ell_height, 0.0, 90.0); PSDRV_WriteLineTo( dev, right, bottom - ell_height/2 ); PSDRV_WriteArc( dev, right - ell_width/2, bottom - ell_height/2, ell_width, ell_height, -90.0, 0.0); PSDRV_WriteLineTo( dev, right - ell_width/2, bottom); PSDRV_WriteArc( dev, left + ell_width/2, bottom - ell_height/2, ell_width, ell_height, 180.0, -90.0); PSDRV_WriteClosePath( dev ); PSDRV_Brush(dev,0); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); return TRUE; }
/*********************************************************************** * * 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; } }
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; }
/*********************************************************************** * PSDRV_LineTo */ BOOL PSDRV_LineTo(PHYSDEV dev, INT x, INT y) { POINT pt[2]; TRACE("%d %d\n", x, y); GetCurrentPositionEx( dev->hdc, pt ); pt[1].x = x; pt[1].y = y; LPtoDP( dev->hdc, pt, 2 ); PSDRV_SetPen(dev); PSDRV_SetClip(dev); PSDRV_WriteMoveTo(dev, pt[0].x, pt[0].y ); PSDRV_WriteLineTo(dev, pt[1].x, pt[1].y ); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); return TRUE; }
/*********************************************************************** * 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; }
/*********************************************************************** * PSDRV_PolyBezier */ BOOL PSDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count ) { DWORD i; POINT *dev_pts; TRACE("\n"); if (!(dev_pts = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*dev_pts) ))) return FALSE; memcpy( dev_pts, pts, count * sizeof(*dev_pts) ); LPtoDP( dev->hdc, dev_pts, count ); PSDRV_WriteSpool(dev, "%PolyBezier\n",12); PSDRV_SetPen(dev); PSDRV_SetClip(dev); PSDRV_WriteMoveTo(dev, dev_pts[0].x, dev_pts[0].y ); for (i = 1; i < count; i += 3) PSDRV_WriteCurveTo( dev, dev_pts + i ); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); HeapFree( GetProcessHeap(), 0, dev_pts ); return TRUE; }
/*********************************************************************** * PSDRV_PolyPolygon */ BOOL PSDRV_PolyPolygon( PHYSDEV dev, const POINT* pts, const INT* counts, UINT polygons ) { DWORD polygon, total; INT line; POINT *dev_pts, *pt; TRACE("\n"); for (polygon = total = 0; polygon < polygons; polygon++) total += counts[polygon]; if (!(dev_pts = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*dev_pts) ))) return FALSE; memcpy( dev_pts, pts, total * sizeof(*dev_pts) ); LPtoDP( dev->hdc, dev_pts, total ); pt = dev_pts; PSDRV_WriteSpool(dev, "%PolyPolygon\n",13); PSDRV_SetPen(dev); PSDRV_SetClip(dev); for(polygon = 0; polygon < polygons; polygon++) { PSDRV_WriteMoveTo(dev, pt->x, pt->y); pt++; for(line = 1; line < counts[polygon]; line++, pt++) PSDRV_WriteLineTo(dev, pt->x, pt->y); PSDRV_WriteClosePath(dev); } HeapFree( GetProcessHeap(), 0, dev_pts ); if(GetPolyFillMode( dev->hdc ) == ALTERNATE) PSDRV_Brush(dev, 1); else /* WINDING */ PSDRV_Brush(dev, 0); PSDRV_DrawLine(dev); PSDRV_ResetClip(dev); return TRUE; }
/*********************************************************************** * 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; }