You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
922 lines
25 KiB
922 lines
25 KiB
/*++
|
|
|
|
Copyright (c) 1990-2003 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
brush.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module implements the code to realize brushes. BRUSHOBJS, are
|
|
representations of logical objects. These objects are created in the
|
|
win32 world and eventually need to be converted (or realized) to
|
|
something that makes sense in the target device. This is done by realizing
|
|
a brush. We look at the logical representation of the brush, then based
|
|
on physical device characteristics, do the best job we can of simulating
|
|
it on the target device. This conversion is done once, and the result
|
|
is stored in the structure that represents the REALIZED brush. This
|
|
is optimal since brushes tend to get re-used, and REALIZING them
|
|
once, keeps us from having to execute the code every time a brush is used.
|
|
|
|
|
|
Author:
|
|
|
|
19:15 on Mon 15 Apr 1991
|
|
Created it
|
|
|
|
15-Nov-1993 Mon 19:29:07 updated
|
|
clean up / fixed
|
|
|
|
27-Jan-1994 Thu 23:39:34 updated
|
|
Add fill type cache. which we do not have to send FT if same one
|
|
already on the plotter
|
|
|
|
|
|
[Environment:]
|
|
|
|
GDI Device Driver - Plotter.
|
|
|
|
|
|
[Notes:]
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define DBG_PLOTFILENAME DbgBrush
|
|
|
|
#define DBG_RBRUSH 0x00000001
|
|
#define DBG_HATCHTYPE 0x00000002
|
|
#define DBG_SHOWSTDPAT 0x00000004
|
|
#define DBG_COPYUSERPATBGR 0x00000008
|
|
#define DBG_MINHTSIZE 0x00000010
|
|
#define DBG_FINDDBCACHE 0x00000020
|
|
|
|
|
|
DEFINE_DBGVAR(0);
|
|
|
|
//
|
|
// The pHSFillType's #d is the line spacing param
|
|
//
|
|
// for hatch brushes, we want the lines to be .01" thick and .0666666666667"
|
|
// this is 15 LPI according to DC. That is, .254mm thick and 2.54mm apart.
|
|
// for now, assume the pen is the correct thickness (.3 is right) to figure
|
|
// out the separation, in device coordinates, we do 2.54 mm * (device units /
|
|
// mm), or (254 * resolution / 100) where resolution is in device units /
|
|
// milimeter.
|
|
//
|
|
|
|
#define PATLINESPACE(pPDev) FXTODEVL(pPDev,LTOFX(pPDev->lCurResolution+7)/15)
|
|
|
|
static const BYTE CellSizePrims[10][4] = {
|
|
|
|
{ 2, 0, 0, 0 }, // 2x 2
|
|
{ 2, 2, 0, 0 }, // 4x 4
|
|
{ 2, 3, 0, 0 }, // 6x 6
|
|
{ 2, 2, 2, 0 }, // 8x 8
|
|
{ 2, 5, 0, 0 }, // 10x10
|
|
{ 2, 2, 3, 0 }, // 12x12
|
|
{ 2, 7, 0, 0 }, // 14x14
|
|
{ 2, 2, 2, 2 }, // 16x16
|
|
{ 91,0, 0, 0 }, // 91x91
|
|
{ 91,0, 0, 0 } // 91x91
|
|
};
|
|
|
|
|
|
|
|
VOID
|
|
ResetDBCache(
|
|
PPDEV pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function clears the Device brush cach mechanism.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
27-Jan-1994 Thu 20:30:35 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCACHE pDBCache;
|
|
UINT i;
|
|
|
|
|
|
pDBCache = (PDBCACHE)&pPDev->DBCache[0];
|
|
|
|
|
|
for (i = RF_MAX_IDX; i; i--, pDBCache++) {
|
|
|
|
pDBCache->RFIndex = (WORD)i;
|
|
pDBCache->DBUniq = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
FindDBCache(
|
|
PPDEV pPDev,
|
|
WORD DBUniq
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function finds the RF Index number, if not there then it will add it
|
|
to the cache.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
DBUniq - Uniq number to be search for
|
|
|
|
|
|
Return Value:
|
|
|
|
LONG value >0 found and RetVal is the RFIndex
|
|
<0 NOT Found and -RetVal is the new RFIndex
|
|
|
|
|
|
Author:
|
|
|
|
27-Jan-1994 Thu 20:32:12 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PDBCACHE pDBCache;
|
|
DBCACHE DBCache;
|
|
LONG RetVal;
|
|
UINT i;
|
|
|
|
|
|
PLOTASSERT(1, "FindDevBrushCache: DBUniq is 0", DBUniq, 0);
|
|
|
|
pDBCache = (PDBCACHE)&pPDev->DBCache[0];
|
|
|
|
for (i = 0; i < RF_MAX_IDX; i++, pDBCache++) {
|
|
|
|
if (pDBCache->DBUniq == DBUniq) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < RF_MAX_IDX) {
|
|
|
|
DBCache = *pDBCache;
|
|
RetVal = (LONG)DBCache.RFIndex;
|
|
|
|
PLOTDBG(DBG_FINDDBCACHE, ("FindDBCache: Found Uniq=%lu, RFIdx=%ld",
|
|
(DWORD)DBCache.DBUniq, (DWORD)DBCache.RFIndex));
|
|
|
|
} else {
|
|
|
|
//
|
|
// Since we did not find the pattern in the cache, we will add it
|
|
// to the beggining and move the rest of the entries down the list.
|
|
// We need to remember the last one.
|
|
//
|
|
|
|
pDBCache = (PDBCACHE)&pPDev->DBCache[i = (RF_MAX_IDX - 1)];
|
|
DBCache = *pDBCache;
|
|
DBCache.DBUniq = DBUniq;
|
|
RetVal = -(LONG)DBCache.RFIndex;
|
|
|
|
PLOTDBG(DBG_FINDDBCACHE, ("FindDBCache: NOT Found, NEW DBCache: Uniq=%lu, RFIdx=%ld",
|
|
(DWORD)DBCache.DBUniq, (DWORD)DBCache.RFIndex));
|
|
}
|
|
|
|
PLOTASSERT(1, "FindDBCache: Invalid RFIndex=%ld in the cache",
|
|
(DBCache.RFIndex > 0) && (DBCache.RFIndex <= RF_MAX_IDX),
|
|
(DWORD)DBCache.RFIndex);
|
|
|
|
//
|
|
// Move everything down by one slot, so the first one is the most
|
|
// recently used.
|
|
//
|
|
|
|
while (i--) {
|
|
|
|
*pDBCache = *(pDBCache - 1);
|
|
--pDBCache;
|
|
}
|
|
|
|
//
|
|
// Save the current cach back and return the RF index.
|
|
//
|
|
|
|
*pDBCache = DBCache;
|
|
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
CopyUserPatBGR(
|
|
PPDEV pPDev,
|
|
SURFOBJ *psoPat,
|
|
XLATEOBJ *pxlo,
|
|
LPBYTE pBGRBmp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function take a pattern surface and converts it to a form suitable,
|
|
for downloading to the target device. The target device in this case,
|
|
expects a pattern made up of different pens that define the color of each
|
|
individual pixel. This conversion is done by first creating a
|
|
BitmapSurface (24 bpp) of the passed in size, then EngBitBliting, the
|
|
passed surface (that defines the pattern) into that 24 bpp surface, and
|
|
finally copying the color data into the passed buffer.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to our PDEV
|
|
|
|
psoSrc - source surface object
|
|
|
|
pxlo - translate object
|
|
|
|
pBGRBmp - Pointer a 8x8 palette location for the bitmap
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if sucessful, FALSE if failed
|
|
|
|
Author:
|
|
|
|
18-Jan-1994 Tue 03:20:10 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
SURFOBJ *pso24;
|
|
HBITMAP hBmp24;
|
|
|
|
|
|
if (pso24 = CreateBitmapSURFOBJ(pPDev,
|
|
&hBmp24,
|
|
psoPat->sizlBitmap.cx,
|
|
psoPat->sizlBitmap.cy,
|
|
BMF_24BPP,
|
|
NULL)) {
|
|
LPBYTE pbSrc;
|
|
RECTL rclDst;
|
|
DWORD SizeBGRPerScan;
|
|
BOOL Ok;
|
|
|
|
|
|
rclDst.left =
|
|
rclDst.top = 0;
|
|
rclDst.right = pso24->sizlBitmap.cx;
|
|
rclDst.bottom = pso24->sizlBitmap.cy;
|
|
|
|
if (!(Ok = EngBitBlt(pso24, // psoDst
|
|
psoPat, // psoSrc
|
|
NULL, // psoMask
|
|
NULL, // pco
|
|
pxlo, // pxlo
|
|
&rclDst, // prclDst
|
|
(PPOINTL)&rclDst, // pptlSrc
|
|
NULL, // pptlMask
|
|
NULL, // pbo
|
|
NULL, // pptlBrushOrg
|
|
0xCCCC))) {
|
|
|
|
PLOTERR(("CopyUserPatBGR: EngBitBlt() FALIED"));
|
|
return(FALSE);
|
|
}
|
|
|
|
SizeBGRPerScan = (DWORD)(pso24->sizlBitmap.cx * 3);
|
|
pbSrc = (LPBYTE)pso24->pvScan0;
|
|
|
|
PLOTDBG(DBG_COPYUSERPATBGR, ("CopyUserPatBGR: PerScan=%ld [%ld], cy=%ld",
|
|
SizeBGRPerScan, pso24->lDelta, rclDst.bottom));
|
|
|
|
while (rclDst.bottom--) {
|
|
|
|
CopyMemory(pBGRBmp, pbSrc, SizeBGRPerScan);
|
|
|
|
pBGRBmp += SizeBGRPerScan;
|
|
pbSrc += pso24->lDelta;
|
|
}
|
|
|
|
if (pso24) {
|
|
|
|
EngUnlockSurface(pso24);
|
|
}
|
|
|
|
if (hBmp24) {
|
|
|
|
EngDeleteSurface((HSURF)hBmp24);
|
|
}
|
|
|
|
return(Ok);
|
|
|
|
} else {
|
|
|
|
PLOTERR(("CopyUserPatBGR: CANNOT Create 24BPP for UserPat"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
GetMinHTSize(
|
|
PPDEV pPDev,
|
|
SIZEL *pszlPat
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function computes and returns the minimum pattern size in pszlPat for
|
|
a halftone tile-able pattern size. This is required in order to tile a
|
|
repeating pattern correctly when filling an object. If the original
|
|
brush wasn't useable, we create a composite of that original bitmap, by
|
|
halftoning into a surface. In order for the result to be tile-able,
|
|
we must take into account the different Cell/Patter sizes for our
|
|
halftone data.
|
|
|
|
Arguments:
|
|
|
|
pPDev - Point to our PDEV
|
|
|
|
pszlPat - Points to a SIZEL structure for the original pattern size
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
26-Jan-1994 Wed 10:10:15 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
LPBYTE pCellPrims;
|
|
LPBYTE pPrims;
|
|
LONG Prim;
|
|
SIZEL szlPat;
|
|
LONG CellSize;
|
|
UINT i;
|
|
|
|
if (0 == pszlPat->cx || 0 == pszlPat->cy)
|
|
{
|
|
return;
|
|
}
|
|
|
|
szlPat = *pszlPat;
|
|
CellSize = (LONG)HTPATSIZE(pPDev);
|
|
pCellPrims = (LPBYTE)&CellSizePrims[(CellSize >> 1) - 1][0];
|
|
|
|
if (!(CellSize % szlPat.cx)) {
|
|
|
|
szlPat.cx = CellSize;
|
|
|
|
} else if (szlPat.cx % CellSize) {
|
|
|
|
//
|
|
// Since it's not an exact fit, calculate the correct number now.
|
|
//
|
|
|
|
i = 4;
|
|
pPrims = pCellPrims;
|
|
|
|
while ((i--) && (Prim = (LONG)*pPrims++)) {
|
|
|
|
if (!(szlPat.cx % Prim)) {
|
|
|
|
szlPat.cx /= Prim;
|
|
}
|
|
}
|
|
|
|
szlPat.cx *= CellSize;
|
|
}
|
|
|
|
if (!(CellSize % szlPat.cy)) {
|
|
|
|
szlPat.cy = CellSize;
|
|
|
|
} else if (szlPat.cy % CellSize) {
|
|
|
|
//
|
|
// Since it's not an exact fit, calculate the correct number now.
|
|
//
|
|
|
|
i = 4;
|
|
pPrims = pCellPrims;
|
|
|
|
while ((i--) && (Prim = (LONG)*pPrims++)) {
|
|
|
|
if (!(szlPat.cy % Prim)) {
|
|
|
|
szlPat.cy /= Prim;
|
|
}
|
|
}
|
|
|
|
szlPat.cy *= CellSize;
|
|
}
|
|
|
|
PLOTDBG(DBG_MINHTSIZE, ("GetMinHTSize: PatSize=%ld x %ld, HTSize=%ld x %ld, MinSize=%ld x %ld",
|
|
pszlPat->cx, pszlPat->cy, CellSize, CellSize,
|
|
szlPat.cx, szlPat.cy));
|
|
|
|
*pszlPat = szlPat;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
DrvRealizeBrush(
|
|
BRUSHOBJ *pbo,
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoPattern,
|
|
SURFOBJ *psoMask,
|
|
XLATEOBJ *pxlo,
|
|
ULONG iHatch
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DrvRealizeBrush requests the driver to realize a specified brush for a
|
|
specified surface. NT's GDI will usually realize a brush before using it.
|
|
Realing a brush allows our driver to take a logical representation of
|
|
a brush, and convert it to something that makes sense in the target device.
|
|
By having the NT GDI realize the brush, in essence allows us to cache the
|
|
physical representation of the brush, for future use.
|
|
|
|
Arguments:
|
|
|
|
pbo - Points to the BRUSHOBJ which is to be realized. All the other
|
|
parameters, except for psoDst, can be queried from this
|
|
object. Parameter specifications are provided as an
|
|
optimization. This parameter is best used only as a parameter
|
|
for BRUSHOBJ_pvAllocRBrush, which allocates the memory for
|
|
the realized brush.
|
|
|
|
psoDst - Points to the surface for which the brush is to be realized.
|
|
This surface could be the physical surface for the device,
|
|
a device format bitmap, or a standard format bitmap.
|
|
|
|
psoPattern - Points to the surface that describes the pattern for the
|
|
brush. For a raster device, this always represents a bitmap.
|
|
For a vector device, this is always one of the pattern
|
|
surfaces returned by DrvEnablePDEV.
|
|
|
|
psoMask - Points to a transparency mask for the brush. This is a one
|
|
bit per pixel bitmap that has the same extent as the pattern.
|
|
A mask of zero means the pixel is considered a background
|
|
pixel for the brush. (In transparent background mode, the
|
|
background pixels are unaffected in a fill.) Pen Plotters can
|
|
ignore this parameter because they never draw background
|
|
information.
|
|
|
|
pxlo - Points to an XLATEOBJ that tells how to interpret the colors
|
|
in the pattern. An XLATEOBJXxx service routine can be called
|
|
to translate the colors to device color indexes. Vector
|
|
devices should translate color zero through the XLATEOBJ to
|
|
get the foreground color for the brush.
|
|
|
|
iHatch - If this is less than HS_API_MAX, then it indicates that
|
|
psoPattern is one of the hatch brushes returned by
|
|
DrvEnablePDEV, such as HS_HORIZONTAL.
|
|
|
|
Return Value:
|
|
|
|
DrvRealizeBrush returns TRUE if the brush was successfully realized.
|
|
Otherwise, FALSE is returned and an error code is logged.
|
|
|
|
|
|
Author:
|
|
|
|
09-Feb-1994 Wed 10:04:17 updated
|
|
Put the CloneSURFOBJToHT() back for all psoPatterns, (this was to
|
|
prevent GDI go into GP), now we will raised a bug against it.
|
|
|
|
13-Jan-1994 Thu 23:12:40 updated
|
|
Totally re-write so that we will cached the psoPattern always
|
|
|
|
01-Dec-1993 Wed 17:27:19 updated
|
|
clean up, and re-write to generate the standard brush string.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDEV pPDev;
|
|
|
|
|
|
if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
|
|
|
|
PLOTERR(("DrvRealizeBrush has invalid pPDev"));
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// We don't check if iHatch is valid or not at this poin.
|
|
// We should always get a psoPattern that either points to the user
|
|
// defined pattern or to the standard monochrome pattern.
|
|
//
|
|
|
|
if ((psoPattern) &&
|
|
(psoPattern->iType == STYPE_BITMAP)) {
|
|
|
|
PDEVBRUSH pBrush;
|
|
SURFOBJ *psoHT;
|
|
HBITMAP hBmp;
|
|
SIZEL szlPat;
|
|
SIZEL szlHT;
|
|
RECTL rclHT;
|
|
LONG Size;
|
|
DWORD OffBGR;
|
|
BOOL RetOk;
|
|
|
|
//
|
|
// leave room for the color table. then allocate the new device brush
|
|
//
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("DrvRealizeBrush: psoPat=%08lx [%ld], psoMask=%08lx, iHatch=%ld",
|
|
psoPattern, psoPattern->iBitmapFormat, psoMask, iHatch));
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("psoPattern size = %ld x %ld",
|
|
(LONG)psoPattern->sizlBitmap.cx,
|
|
(LONG)psoPattern->sizlBitmap.cy));
|
|
|
|
#if DBG
|
|
if ((DBG_PLOTFILENAME & DBG_SHOWSTDPAT) &&
|
|
((psoPattern->iBitmapFormat == BMF_1BPP) ||
|
|
(iHatch < HS_DDI_MAX))) {
|
|
|
|
LPBYTE pbSrc;
|
|
LPBYTE pbCur;
|
|
LONG x;
|
|
LONG y;
|
|
BYTE bData;
|
|
BYTE Mask;
|
|
BYTE Buf[128];
|
|
|
|
|
|
//
|
|
// Debug code that allows the pattern to be displayed with
|
|
// ASCII codes on the debug terminal. This was very helpful
|
|
// during development.
|
|
//
|
|
|
|
pbSrc = psoPattern->pvScan0;
|
|
|
|
for (y = 0; y < psoPattern->sizlBitmap.cy; y++) {
|
|
|
|
pbCur = pbSrc;
|
|
pbSrc += psoPattern->lDelta;
|
|
Mask = 0x0;
|
|
Size = 0;
|
|
|
|
for (x = 0;
|
|
x < psoPattern->sizlBitmap.cx && Size < sizeof(Buf);
|
|
x++)
|
|
{
|
|
|
|
if (!(Mask >>= 1)) {
|
|
|
|
Mask = 0x80;
|
|
bData = *pbCur++;
|
|
}
|
|
|
|
Buf[Size++] = (BYTE)((bData & Mask) ? 0xdb : 0xb0);
|
|
}
|
|
|
|
if (Size < sizeof(Buf))
|
|
{
|
|
Buf[Size] = '\0';
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Error case. Null-terminate anyway.
|
|
//
|
|
Buf[sizeof(Buf) - 1] = '\0';
|
|
}
|
|
|
|
DBGP((Buf));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// For pen plotter, we need to remember this one as well.
|
|
//
|
|
|
|
szlHT =
|
|
szlPat = psoPattern->sizlBitmap;
|
|
|
|
PLOTDBG(DBG_RBRUSH,
|
|
("DrvRealizeBrush: BG=%08lx, FG=%08lx",
|
|
(DWORD)XLATEOBJ_iXlate(pxlo, 1),
|
|
(DWORD)XLATEOBJ_iXlate(pxlo, 0)));
|
|
|
|
if (IS_RASTER(pPDev)) {
|
|
|
|
//
|
|
// For raster plotters, we will clone the surface and halftone
|
|
// the orignal pattern into a halftone bitmap which itself is
|
|
// tile-able. This allows us to use our color reduction code,
|
|
// to make the pattern look good.
|
|
//
|
|
|
|
if ((iHatch >= HS_DDI_MAX) &&
|
|
(!IsHTCompatibleSurfObj(pPDev,
|
|
psoPattern,
|
|
pxlo,
|
|
ISHTF_ALTFMT | ISHTF_DSTPRIM_OK))) {
|
|
|
|
GetMinHTSize(pPDev, &szlHT);
|
|
}
|
|
|
|
rclHT.left =
|
|
rclHT.top = 0;
|
|
rclHT.right = szlHT.cx;
|
|
rclHT.bottom = szlHT.cy;
|
|
|
|
PLOTDBG(DBG_RBRUSH,
|
|
("DrvRealizeBrush: PatSize=%ld x %ld, HT=%ld x %ld",
|
|
szlPat.cx, szlPat.cy, szlHT.cx, szlHT.cy));
|
|
|
|
//
|
|
// Go generate the bits for the pattern.
|
|
//
|
|
|
|
if (psoHT = CloneSURFOBJToHT(pPDev, // pPDev,
|
|
psoDst, // psoDst,
|
|
psoPattern, // psoSrc,
|
|
pxlo, // pxlo,
|
|
&hBmp, // hBmp,
|
|
&rclHT, // prclDst,
|
|
NULL)) { // prclSrc,
|
|
|
|
RetOk = TRUE;
|
|
|
|
} else {
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("DrvRealizeBrush: Clone PATTERN FAILED"));
|
|
return(FALSE);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// For Pen type plotter we will never do a standard pattern in the
|
|
// memory (compatible DC). For user defined patterns we will
|
|
// only hatch '\' with background color and a '/' with foreground
|
|
// color with double standard line spacing. This is the best we
|
|
// can hope for on a pen plotter.
|
|
//
|
|
|
|
RetOk = TRUE;
|
|
psoHT = psoPattern;
|
|
hBmp = NULL;
|
|
}
|
|
|
|
if (RetOk) {
|
|
|
|
//
|
|
// Now Allocate device brush, remember we will only allocate the
|
|
// minimum size.
|
|
//
|
|
|
|
Size = (LONG)psoHT->cjBits - (LONG)sizeof(pBrush->BmpBits);
|
|
|
|
if (Size < 0) {
|
|
|
|
Size = sizeof(DEVBRUSH);
|
|
|
|
} else {
|
|
|
|
Size += sizeof(DEVBRUSH);
|
|
}
|
|
|
|
//
|
|
// Following are the user defined pattern sizes which can be handled
|
|
// internally by HPGL2. This is only for raster plotters. Pen
|
|
// plotters will have a cross hatch to show an emulation of the
|
|
// pattern.
|
|
//
|
|
|
|
if ((iHatch >= HS_DDI_MAX) &&
|
|
(IS_RASTER(pPDev)) &&
|
|
((szlPat.cx == 8) ||
|
|
(szlPat.cx == 16) ||
|
|
(szlPat.cx == 32) ||
|
|
(szlPat.cx == 64)) &&
|
|
((szlPat.cy == 8) ||
|
|
(szlPat.cy == 16) ||
|
|
(szlPat.cy == 32) ||
|
|
(szlPat.cy == 64))) {
|
|
|
|
//
|
|
// Adding the size which stored the BGR format of the pattern
|
|
//
|
|
|
|
OffBGR = Size;
|
|
Size += (psoPattern->sizlBitmap.cx * 3) *
|
|
psoPattern->sizlBitmap.cy;
|
|
|
|
} else {
|
|
|
|
OffBGR = 0;
|
|
}
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("DrvRealizeBrush: AllocDEVBRUSH(Bmp=%ld,BGR=%ld), TOT=%ld",
|
|
psoHT->cjBits, Size - OffBGR, Size));
|
|
|
|
//
|
|
// Now ask the NT graphics engine to allocate the device
|
|
// brush memory for us. This is done, so NT knows how to discard
|
|
// the memory when it is no longer needed (The brush getting
|
|
// destroyed).
|
|
//
|
|
|
|
if (pBrush = (PDEVBRUSH)BRUSHOBJ_pvAllocRbrush(pbo, Size)) {
|
|
|
|
//
|
|
// Set up either standard pattern or user defined pattern
|
|
// HPGL/2 FT command string pointer and parameters.
|
|
//
|
|
|
|
pBrush->psoMask = psoMask;
|
|
pBrush->PatIndex = (WORD)iHatch;
|
|
pBrush->Uniq = (WORD)(pPDev->DevBrushUniq += 1);
|
|
pBrush->LineSpacing = (LONG)PATLINESPACE(pPDev);
|
|
pBrush->ColorFG = (DWORD)XLATEOBJ_iXlate(pxlo, 1);
|
|
pBrush->ColorBG = (DWORD)XLATEOBJ_iXlate(pxlo, 0);
|
|
pBrush->sizlBitmap = psoHT->sizlBitmap;
|
|
pBrush->ScanLineDelta = psoHT->lDelta;
|
|
pBrush->BmpFormat = (WORD)psoHT->iBitmapFormat;
|
|
pBrush->BmpFlags = (WORD)psoHT->fjBitmap;
|
|
pBrush->pbgr24 = NULL;
|
|
pBrush->cxbgr24 =
|
|
pBrush->cybgr24 = 0;
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("DrvRealizeBrush: DevBrush's Uniq = %ld",
|
|
pBrush->Uniq));
|
|
|
|
//
|
|
// Check to see if the cache is wrapping and handle it.
|
|
//
|
|
|
|
if (pBrush->Uniq == 0) {
|
|
|
|
ResetDBCache(pPDev);
|
|
|
|
pBrush->Uniq =
|
|
pPDev->DevBrushUniq = 1;
|
|
|
|
PLOTDBG(DBG_RBRUSH, ("DrvRealizeBrush: Reset DB Cache, (Uniq WRAP)"));
|
|
}
|
|
|
|
//
|
|
// Is it a user defined pattern.
|
|
//
|
|
|
|
if (iHatch >= HS_DDI_MAX) {
|
|
|
|
//
|
|
// Check to see if the brush could be downloaded to the
|
|
// target device as an HPGL2 brush. If this is the case
|
|
// save that information.
|
|
//
|
|
|
|
if (OffBGR) {
|
|
|
|
pBrush->pbgr24 = (LPBYTE)pBrush + OffBGR;
|
|
pBrush->cxbgr24 = (WORD)psoPattern->sizlBitmap.cx;
|
|
pBrush->cybgr24 = (WORD)psoPattern->sizlBitmap.cy;
|
|
|
|
ZeroMemory(pBrush->pbgr24, Size - OffBGR);
|
|
|
|
CopyUserPatBGR(pPDev, psoPattern, pxlo, pBrush->pbgr24);
|
|
|
|
} else if (!IS_RASTER(pPDev)) {
|
|
|
|
//
|
|
// If we are not talking to a RASTER plotter, not much
|
|
// we can do here. Trigger the simulation.
|
|
//
|
|
|
|
pBrush->pbgr24 = (LPBYTE)-1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy down the halftoned bits if any.
|
|
//
|
|
|
|
if (psoHT->cjBits) {
|
|
|
|
CopyMemory((LPBYTE)pBrush->BmpBits,
|
|
(LPBYTE)psoHT->pvBits,
|
|
psoHT->cjBits);
|
|
}
|
|
|
|
//
|
|
// Now record the realized brush pointer in the BRUSHOBJ.
|
|
//
|
|
|
|
pbo->pvRbrush = (LPVOID)pBrush;
|
|
|
|
} else {
|
|
|
|
PLOTERR(("DrvRealizeBrush: brush allocation failed"));
|
|
|
|
RetOk = FALSE;
|
|
}
|
|
|
|
} else {
|
|
|
|
PLOTERR(("DrvRealizeBrush: Cloning the psoPattern failed!"));
|
|
RetOk = FALSE;
|
|
}
|
|
|
|
if (psoHT != psoPattern) {
|
|
|
|
EngUnlockSurface(psoHT);
|
|
}
|
|
|
|
if (hBmp) {
|
|
|
|
EngDeleteSurface((HSURF)hBmp);
|
|
}
|
|
|
|
return(RetOk);
|
|
|
|
} else {
|
|
|
|
PLOTASSERT(0, "The psoPattern is not a bitmap (psoPattern= %08lx)",
|
|
(psoPattern) &&
|
|
(psoPattern->iType == STYPE_BITMAP), psoPattern);
|
|
|
|
return(FALSE);
|
|
}
|
|
}
|