Esempio n. 1
0
/***********************************************************************
 *           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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/***********************************************************************
 *           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);
}
Esempio n. 4
0
/***********************************************************************
 *
 *                    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;
    }
}
Esempio n. 5
0
/***********************************************************************
 *           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;
}
Esempio n. 6
0
/**********************************************************************
 *           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;
    }
}
Esempio n. 7
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;
}
Esempio n. 8
0
/**********************************************************************
 *
 *	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;
}