VOID SetDefaultDMForm( PPLOTDEVMODE pPlotDM, _Out_opt_ PFORMSIZE pCurForm ) /*++ Routine Description: This function set the default form for the PLOTDEVMODE, these includes dmPaperSize, dmPaperWidth, dmPaperLength, dmFormName and set pCurForm if pointer is not NULL Arguments: pPlotDM - Pointer to the PLOTDEVMODE data structure pCurForm - pointer to the FORMSIZE data structure to store current default form set by this function Return Value: VOID Author: 01-Dec-1993 Wed 13:44:31 created Revision History: --*/ { PAPERINFO PaperInfo; HRESULT hr; pPlotDM->dm.dmFields &= ~DM_PAPER_FIELDS; pPlotDM->dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE); pPlotDM->dm.dmPaperSize = GetDefaultPaper(&PaperInfo); pPlotDM->dm.dmPaperWidth = SPLTODM(PaperInfo.Size.cx); pPlotDM->dm.dmPaperLength = SPLTODM(PaperInfo.Size.cy); hr = StringCchCopy((LPWSTR)pPlotDM->dm.dmFormName, CCHOF(pPlotDM->dm.dmFormName), PaperInfo.Name); if (FAILED(hr) ) { PLOTASSERT(0, "Couldn't copy the string %ls to devmode", SUCCEEDED(hr), PaperInfo.Name); } if (pCurForm) { pCurForm->Size = PaperInfo.Size; pCurForm->ImageArea = PaperInfo.ImageArea; } }
UINT CreatePenSetupOI( PPRINTERINFO pPI, POPTITEM pOptItem, POIDATA pOIData ) /*++ Routine Description: Arguments: Return Value: Author: 06-Nov-1995 Mon 16:23:36 created Revision History: --*/ { PPENDATA pPenData; POPTITEM pOI; POPTITEM pOIPen; POPTTYPE pOTPen; EXTRAINFO EI; UINT i; UINT j; UINT MaxPens; UINT cPenClr; WCHAR Buf[128]; DWORD dwchSize; HRESULT hr; MaxPens = (UINT)pPI->pPlotGPC->MaxPens; cPenClr = PC_IDX_TOTAL; if (!pOptItem) { return(((MaxPens + 1) * PRK_MAX_PENDATA_SET) + 1); } EI.Size = (UINT)((LoadString(hPlotUIModule, IDS_PEN_NUM, Buf, (sizeof(Buf) / sizeof(WCHAR)) - 1) + 5) * sizeof(WCHAR)); dwchSize = EI.Size; pPenData = PI_PPENDATA(pPI); pOTPen = NULL; pOIPen = NULL; pOI = pOptItem; // // First: Create PenSetup: HEADER // if (CreateOPTTYPE(pPI, pOI, pOIData, 0, NULL)) { pOI++; } // // Now Create Each pen set // for (i = (UINT)IDS_PENSET_FIRST; i <= (UINT)IDS_PENSET_LAST; i++) { if (CreateOPTTYPE(pPI, pOI, &OIPenSet, 0, NULL)) { pOI->pName = (LPTSTR)UIntToPtr(i); pOI->Flags |= OPTIF_EXT_IS_EXTPUSH; pOI->pExtPush = &PenSetExtPush; } pOI++; for (j = 1; j <= MaxPens; j++, pOI++, pPenData++) { if (CreateOPTTYPE(pPI, pOI, &OIPenNum, cPenClr, &EI)) { if (pOTPen) { pOI->pOptType = pOTPen; } else { pOTPen = pOI->pOptType; cPenClr = 0; } if (pOIPen) { pOI->pName = pOIPen->pName; pOIPen++; } else { pOI->pName = (LPTSTR)EI.pData; hr = StringCchPrintfW(pOI->pName, dwchSize, L"%ws%u", Buf, j); if ( FAILED(hr) ) { PLOTASSERT(0, "Couldn't format string into pName", SUCCEEDED(hr), 0); } } } pOI->Sel = pPenData->ColorIdx; } if (!pOIPen) { EI.Size = 0; pOIPen = pOI; } pOIPen -= MaxPens; } return (UINT)(pOI - pOptItem); }
BOOL DoRop3( PPDEV pPDev, SURFOBJ *psoDst, SURFOBJ *psoSrc, SURFOBJ *psoPat, SURFOBJ *psoTmp, CLIPOBJ *pco, XLATEOBJ *pxlo, PRECTL prclDst, PRECTL prclSrc, PRECTL prclPat, PPOINTL pptlPatOrg, BRUSHOBJ *pbo, DWORD Rop3 ) /*++ Routine Description: This function performs ROP3 operations (one at a time) Arguments: pPDev - Pointer to the PDEV psoDst - pointer to the destination surface object psoSrc - pointer to the source surface object psoPat - Pointer to the pattern surface object psoTmp - pointer to the temp buffer surface object pco - clip object prclDst - pointer to the destination rectangle prclSrc - pointer to the source rectangle prclPat - pointer to the pattern rectangle pptlPatOrg - Pointer to the brush origin, if this is NULL then its assumed the pattern's prclPat does not have to be aligned on the destination pbo - a Brush object if we need to call DoFill() Rop3 - a ROP3 to be performed Return Value: BOOL Author: 20-Jan-1994 Thu 02:36:00 created 27-Jan-1994 Thu 23:46:28 updated Re-write to take other parameter, also move the cloning surface objects to the caller (ie. DrvBitBlt()) Revision History: --*/ { RECTL rclTmp; DWORD SDMix; DWORD Mix2; BYTE Flags; UINT Count; BOOL InvertMix2; BOOL Ok; PLOTDBG(DBG_ROP3, ("DoRop3: Rop3=%08lx", Rop3)); switch (Rop3 &= 0xFF) { case 0x00: // 0 case 0xFF: // 1 case 0x55: // ~D DoSpecialRop3(psoDst, pco, prclDst, Rop3); case 0xAA: // D // // This is NOP // return(TRUE); } // // Invert Rop3 if we are out of the data range (128-255) and then invert // the final result (by inverting last Mix2 Rop2 code (0-15), all Rop3/Rop2 // codes are symmetric. // if (Rop3 >= 0x80) { InvertMix2 = TRUE; SDMix = (DWORD)Rop3ToSDMix[Rop3 ^ 0xFF]; PLOTDBG(DBG_ROP3, ("DoRop3: Need Invert ROP")); } else { InvertMix2 = FALSE; SDMix = (DWORD)Rop3ToSDMix[Rop3]; } if (psoTmp) { rclTmp.left = rclTmp.top = 0; rclTmp.right = psoTmp->sizlBitmap.cx; rclTmp.bottom = psoTmp->sizlBitmap.cy; } Flags = GET_SDMIX_MIX2F(SDMix); Count = (UINT)GET_MIX2F_COUNT(Flags); Ok = TRUE; PLOTDBG(DBG_ROP3, ("SDMix=%08lx, Flags=%02x, Count=%u", SDMix, Flags, Count)); if (Flags & MIX2F_MUL_DST) { PLOTWARN(("DoRop3: *** Rop3=%08lx Has Multiple DEST, Mix2s NOT complete ***", Rop3)); } while ((Ok) && (Count--)) { Mix2 = (DWORD)(SDMix & MIX2_MASK); if ((!Count) && (InvertMix2)) { PLOTDBG(DBG_ROP3, ("DoRop3: Invert Last MIX2 %02lx -> %02lx", Mix2, Mix2 ^ MIX2_MASK)); Mix2 ^= MIX2_MASK; } PLOTDBG(DBG_ROP3, ("DoRop3: SD=%02lx, Mix2=%02lx", SDMix & MIXSD_MASK, Mix2)); switch (SDMix & MIXSD_MASK) { case MIXSD_SRC_DST: PLOTASSERT(1, "DoRop3: MIXSD_SRC_DST but psoSrc = NULL, Rop3=%08lx", psoSrc, Rop3); Ok = DoMix2(pPDev, psoDst, psoSrc, pco, pxlo, prclDst, prclSrc, NULL, Mix2); break; case MIXSD_PAT_DST: if (psoPat) { Ok = DoMix2(pPDev, psoDst, psoPat, pco, NULL, prclDst, prclPat, pptlPatOrg, Mix2); } else { // // A compatible brush object is passed, use DoFill() to do // the actual work. // Mix2 += 1; Mix2 = MixToRop4(Mix2 | (Mix2 << 8)); PLOTDBG(DBG_ROP3, ("DoRop3: DoFill[%04lx] (%ld, %ld)-(%ld, %ld)=%ld x %ld", Mix2, prclDst->left, prclDst->top, prclDst->right, prclDst->bottom, prclDst->right - prclDst->left, prclDst->bottom - prclDst->top)); Ok = DoFill(psoDst, // psoDst NULL, // psoSrc pco, // pco NULL, // pxlo prclDst, // prclDst NULL, // prclSrc pbo, // pbo pptlPatOrg, // pptlBrushOrg Mix2); // Rop4 } break; case MIXSD_SRC_PAT: PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoSrc = NULL, Rop3=%08lx", psoSrc, Rop3); PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoPat = NULL, Rop3=%08lx", psoPat, Rop3); PLOTASSERT(1, "DoRop3: MIXSD_SRC_PAT but psoTmp = NULL, Rop3=%08lx", psoTmp, Rop3); // // Firs tile the pattern onto the temp buffer then do SRC/DST // using SRCCOPY = MIX2_S // if (pptlPatOrg) { // // This is a real pattern we have to tile and align it onto the // desination, but since psoTmp is 0,0 - cx,cy we must alter // the pptlPatOrg to make it align correctly. // pptlPatOrg->x -= prclDst->left; pptlPatOrg->y -= prclDst->top; } Ok = DoMix2(pPDev, psoTmp, psoPat, NULL, NULL, &rclTmp, prclPat, pptlPatOrg, MIX2_S); if (pptlPatOrg) { pptlPatOrg->x += prclDst->left; pptlPatOrg->y += prclDst->top; } // // Now We will do the MIX2 operation between SRC and PAT // if (Ok) { Ok = DoMix2(pPDev, psoTmp, psoSrc, NULL, NULL, &rclTmp, prclSrc, NULL, Mix2); } break; case MIXSD_TMP_DST: PLOTASSERT(1, "DoRop3: MIXSD_TMP_DST but psoTmp = NULL, Rop3=%08lx", psoTmp, Rop3); // // Since we already aligned the pattern on the temp buffer // we can just do the mix2 without aligning it again. // Ok = DoMix2(pPDev, psoDst, psoTmp, pco, NULL, prclDst, &rclTmp, NULL, Mix2); break; } SDMix >>= SDMIX_SHIFT_COUNT; } if (!Ok) { PLOTERR(("DoRop3: FAILED in DoMix2() operations")); } return(Ok); }
BOOL DoMix2( PPDEV pPDev, SURFOBJ *psoDst, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo, PRECTL prclDst, PRECTL prclSrc, PPOINTL pptlSrcOrg, DWORD Mix2 ) /*++ Routine Description: This function is responsible for doing a device copy of a bitmap with/without tiling and activating the proper Rop2 Arguments: pPDev - Pointer to the PDEV psoDst - pointer to the destination surface object psoSrc - pointer to the source surface object pco - Pointer to the CLIPOBJ pxlo - the translate object from the source to the destination prclDst - the output destination rectangle area prclSrc - the source rectangle area pptlSrcOrg - brush origin for the source rectangle, if this is NULL then prclSrc will not have to be aligned on the destination Mix2 - a rop2 mode 0 - 0x0F Return Value: BOOLEAN Author: 08-Feb-1994 Tue 16:33:41 updated fixed ptlSrcOrg problem, we need to modulate with source size before it get used. 27-Jan-1994 Thu 23:45:46 updated Re-write so that it can handle the tiling more efficient. 13-Jan-1994 Sat 09:34:06 created Revision History: --*/ { RECTL rclSrc; RECTL rclDst; POINTL ptlSrcOrg; LONG cxSrc; LONG cySrc; DWORD OHTFlags = 0; BOOL MemMix2; // // The final ROP is either a ROP3 or a ROP4 (no mask) and it is always // a rop2 operation which deals with the source and destination // // First make it into a Rop3 representation of Rop2 (Mix2) // PLOTASSERT(1, "DoMix2: Passed INVALID psoSrc (%08lx) = STYPE_DEVICE", (psoSrc) && (psoSrc->iType != STYPE_DEVICE), psoSrc); PLOTASSERT(1, "DoMix2: Unexpected Mix2 = %u, SHOULD NOT BE HERE", (Mix2 != MIX2_0) && (Mix2 != MIX2_1) && (Mix2 != MIX2_D) && (Mix2 != MIX2_nD), Mix2); Mix2 &= 0x0F; Mix2 |= (DWORD)(Mix2 << 4); switch (Mix2) { case 0x00: // 0 case 0xFF: // 1 case 0x55: // ~D DoSpecialRop3(psoDst, pco, prclDst, Mix2); case 0xAA: // D return(TRUE); } if (MemMix2 = (BOOL)(psoDst->iType != STYPE_DEVICE)) { // // Now make it into Rop4 representation of Rop2 (Mix2) // Mix2 |= (Mix2 << 8); } else { if (!IsHTCompatibleSurfObj(pPDev, psoSrc, pxlo, ((pxlo) ? ISHTF_ALTFMT : 0) | ISHTF_HTXB | ISHTF_DSTPRIM_OK)) { PLOTERR(("DoMix2: The psoSrc is not HT compatible format (%08lx", psoSrc->iBitmapFormat)); return(FALSE); } } cxSrc = prclSrc->right - prclSrc->left; cySrc = prclSrc->bottom - prclSrc->top; if (pptlSrcOrg) { ptlSrcOrg = *pptlSrcOrg; if ((ptlSrcOrg.x = (LONG)(prclDst->left - ptlSrcOrg.x) % cxSrc) < 0) { ptlSrcOrg.x += cxSrc; } if ((ptlSrcOrg.y = (LONG)(prclDst->top - ptlSrcOrg.y) % cySrc) < 0) { ptlSrcOrg.y += cySrc; } PLOTDBG(DBG_DOMIX2, ("DoMix2: ORG ptlSrcOrg=(%ld, %ld) -> (%ld, %ld)", pptlSrcOrg->x, pptlSrcOrg->y, ptlSrcOrg.x, ptlSrcOrg.y)); } else { ptlSrcOrg.x = ptlSrcOrg.y = 0; PLOTDBG(DBG_DOMIX2, ("DoMix2: >>> DO NOT NEED TO ALIGN SRC on DEST <<<")); } rclSrc.top = prclSrc->top + ptlSrcOrg.y; rclSrc.bottom = prclSrc->bottom; rclDst.top = prclDst->top; rclDst.bottom = rclDst.top + (rclSrc.bottom - rclSrc.top); PLOTDBG(DBG_DOMIX2, ("DoMix2: SrcFormat=%ld, DstFormat=%ld %hs", psoSrc->iBitmapFormat, psoDst->iBitmapFormat, (MemMix2) ? "[MemMix2]" : "")); PLOTDBG(DBG_DOMIX2, ("DoMix2: ORG: Dst=(%ld, %ld)-(%ld,%ld), Src=(%ld, %ld)-(%ld, %ld)", prclDst->left, prclDst->top, prclDst->right, prclDst->bottom, prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom)); while (rclDst.top < prclDst->bottom) { // // check if the destination bottom is overhanging, clip it, // // NOTE: This could happen the first time. // if (rclDst.bottom > prclDst->bottom) { // // Clip the source/destination rectangle, because we may do // EngBitBlt() or OutputHTBitmap() // rclSrc.bottom -= (rclDst.bottom - prclDst->bottom); rclDst.bottom = prclDst->bottom; } rclSrc.left = prclSrc->left + ptlSrcOrg.x; rclSrc.right = prclSrc->right; rclDst.left = prclDst->left; rclDst.right = rclDst.left + (rclSrc.right - rclSrc.left); while (rclDst.left < prclDst->right) { // // check if the destination right edge is overhanging, clip it if // necessary. // // NOTE: This could happen the first time. // if (rclDst.right > prclDst->right) { // // Clip the source/destination rectangle, because we may do a // EngBitBlt() or OutputHTBitmap() // rclSrc.right -= (rclDst.right - prclDst->right); rclDst.right = prclDst->right; } PLOTDBG(DBG_DOMIX2, ("DoMix2: TILE: Dst=(%ld, %ld)-(%ld,%ld), Src=(%ld, %ld)-(%ld, %ld)", rclDst.left, rclDst.top, rclDst.right, rclDst.bottom, rclSrc.left, rclSrc.top, rclSrc.right, rclSrc.bottom)); if (MemMix2) { // // In the memory version we don't have to worry about PCO so // just call EngBitBlt to do the work. // if (!(EngBitBlt(psoDst, // psoDst psoSrc, // psoSrc NULL, // psoMask pco, // pco NULL, // pxlo &rclDst, // prclDst (PPOINTL)&rclSrc, // pptlSrc NULL, // pptlMask NULL, // pbo (PPOINTL)&ptlZeroOrigin, // pptlBrushOrg Mix2))) { PLOTERR(("DoMix2: EngBitBlt(MemMix2=%04lx) Failed!!!",Mix2)); return(FALSE); } } else { if (!OutputHTBitmap(pPDev, psoSrc, pco, (PPOINTL)&rclDst, &rclSrc, Mix2, &OHTFlags)) { PLOTERR(("DoMix2: OutputHTBitmap() Failed!!!")); return(FALSE); } } // // Reset <source left> to the original left margin and move the // destination right to the left for the next destination RECTL. // rclSrc.left = prclSrc->left; rclDst.left = rclDst.right; rclDst.right += cxSrc; } // // Reset <source top> to the original top margin and move the // destination bottom to the top, and set bottom for the next destination // RECTL. // rclSrc.top = prclSrc->top; rclDst.top = rclDst.bottom; rclDst.bottom += cySrc; } if (OHTFlags & OHTF_MASK) { OHTFlags |= OHTF_EXIT_TO_HPGL2; OutputHTBitmap(pPDev, psoSrc, NULL, NULL, NULL, 0xAA, &OHTFlags); } return(TRUE); }
BOOL DoSpecialRop3( SURFOBJ *psoDst, CLIPOBJ *pco, PRECTL prclDst, DWORD Rop3 ) /*++ Routine Description: This function does a white or black fil Arguments: psoDst - The device surface must be DEVICE pco - Clipping object prclDst - RECTL area to be rop'ed Rop3 - a special Rop3, 0x00, 0xFF, 0x55, 0xAA Return Value: BOOLEAN Author: 15-Jan-1994 Sat 07:38:55 created Revision History: --*/ { BRUSHOBJ bo; DEVBRUSH DevBrush; PLOTASSERT(1, "DoSpecialRop3: Passed psoDst (%08lx) != STYPE_DEVICE", psoDst->iType == STYPE_DEVICE, psoDst); PLOTDBG(DBG_SPECIALROP, ("DoSpecialROP[%04lx] (%ld, %ld)-(%ld, %ld)=%ld x %ld", Rop3, prclDst->left, prclDst->top, prclDst->right, prclDst->bottom, prclDst->right - prclDst->left, prclDst->bottom - prclDst->top)); bo.iSolidColor = (DWORD)((Rop3) ? 0x000000000 : 0x00FFFFFF); bo.pvRbrush = (LPVOID)&DevBrush; ZeroMemory(&DevBrush, sizeof(DevBrush)); if (!DoFill(psoDst, // psoDst NULL, // psoSrc pco, // pco NULL, // pxlo prclDst, // prclDst NULL, // prclSrc &bo, // pbo (PPOINTL)&ptlZeroOrigin, // pptlBrushOrg Rop3 | (Rop3 << 8))) { // Rop4 PLOTERR(("DoSpecialRop3: Rop3=%08lx Failed!!!", Rop3)); return(FALSE); } return(TRUE); }
BOOL GetFormSelect( PPRINTERINFO pPI, POPTITEM pOptItem ) /*++ Routine Description: This function retrieve the form selected by the user from the combo box Arguments: pPI - Pointer to the PRINTERINFO pOptItem - Pointer to the FORM's OPTITEM Return Value: TRUE if sucessful and pPI will be set correctly, FALSE if error occurred Author: 09-Dec-1993 Thu 14:44:18 created 18-Dec-1993 Sat 03:55:30 updated Changed dmFields setting for the PAPER, now we will only set the DM_FORMNAME field, this way the returned document properties will be always in known form even user defines many forms in spooler. 06-Nov-1995 Mon 12:56:00 updated Re-write for the New UI Revision History: --*/ { PAPERINFO CurPaper; POPTPARAM pOptParam; pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel; if (pOptParam->Style == FS_ROLLPAPER) { PFORMSRC pFS; // // This was added from the GPC data for the roll feed // PLOTASSERT(0, "GetComboBoxSelForm: INTERNAL ERROR, ROLLPAPER In document properties", !(pPI->Flags & PIF_DOCPROP), 0); PLOTASSERT(0, "GetComboBoxSelForm: INTERNAL ERROR, device CANNOT have ROLLPAPER", pPI->pPlotGPC->Flags & PLOTF_ROLLFEED, 0); PLOTDBG(DBG_FORMS, ("Roll Feed Paper is selected, (%ld)", pOptParam->lParam)); if ((pOptParam->lParam >= 0) && ((DWORD)(pOptParam->lParam) < (DWORD)pPI->pPlotGPC->Forms.Count)) { pFS = (PFORMSRC)pPI->pPlotGPC->Forms.pData + pOptParam->lParam; // // Since the RollFeed paper has variable length, and the cy is set // to zero at GPC data, we must take that into account // CurPaper.Size = pFS->Size; CurPaper.ImageArea.left = pFS->Margin.left; CurPaper.ImageArea.top = pFS->Margin.top; CurPaper.ImageArea.right = CurPaper.Size.cx - pFS->Margin.right; CurPaper.ImageArea.bottom = pPI->pPlotGPC->DeviceSize.cy - pFS->Margin.bottom; str2Wstr(CurPaper.Name, CCHOF(CurPaper.Name), pFS->Name); } else { PLOTERR(("GetComboBoxSelForm: Internal Error, Invalid lParam=%ld", pOptParam->lParam)); return(FALSE); } } else { FORM_INFO_1 *pFI1; DWORD cb; // // This form is in the form data base // pFI1 = pPI->pFI1Base + pOptParam->lParam; CurPaper.Size = pFI1->Size; CurPaper.ImageArea = pFI1->ImageableArea; WCPYFIELDNAME(CurPaper.Name, CCHOF(CurPaper.Name), pFI1->pName); } // // Now we have current paper validated // if (pPI->Flags & PIF_DOCPROP) { // // Turn off first, then turn on paper fields as needed // pPI->PlotDM.dm.dmFields &= ~DM_PAPER_FIELDS; pPI->PlotDM.dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE); // // Copy down the dmFormName, dmPaperSize and set dmPaperWidth/Length, // the fields for PAPER will bb set to DM_FORMNAME so that we always // can find the form also we may set DM_PAPERSIZE if index number is // <= DMPAPER_LAST // WCPYFIELDNAME(pPI->PlotDM.dm.dmFormName, CCHOF(pPI->PlotDM.dm.dmFormName), CurPaper.Name); pPI->PlotDM.dm.dmPaperSize = (SHORT)(pOptParam->lParam + DMPAPER_FIRST); pPI->PlotDM.dm.dmPaperWidth = SPLTODM(CurPaper.Size.cx); pPI->PlotDM.dm.dmPaperLength = SPLTODM(CurPaper.Size.cy); #if DBG *(PRECTL)&pPI->PlotDM.dm.dmBitsPerPel = CurPaper.ImageArea; #endif } else { pPI->CurPaper = CurPaper; } PLOTDBG(DBG_FORMS, ("*** GetComboBoxSelForm from COMBO = '%s'", CurPaper.Name)); PLOTDBG(DBG_FORMS, ("Size=%ld x %ld", CurPaper.Size.cx, CurPaper.Size.cy)); PLOTDBG(DBG_FORMS, ("ImageArea=(%ld, %ld) - (%ld, %ld)", CurPaper.ImageArea.left, CurPaper.ImageArea.top, CurPaper.ImageArea.right, CurPaper.ImageArea.bottom)); return(TRUE); }
BOOL SetPlotRegData( HANDLE hPrinter, LPBYTE pData, DWORD RegIdx ) /*++ Routine Description: This function save pData to to the registry Arguments: hPrinter - Handle to the printer interested pData - Pointer to the data area buffer, it must large enough RegIdx - One of the PRKI_xxxx in LOWORD(Index), HIWORD(Index) specified total count for the PENDATA set Return Value: TRUE if sucessful, FALSE if failed, Author: 06-Dec-1993 Mon 22:25:55 created -by- Daniel Chou (danielc) Revision History: --*/ { PPLOTREGKEY pPRK; WCHAR wBuf[32]; PLOTREGKEY PRK; UINT Index; Index = (UINT)LOWORD(RegIdx); PLOTASSERT(0, "SetPlotRegData: Invalid PRKI_xxx Index %ld", Index <= PRKI_LAST, Index); if (Index >= PRKI_PENDATA1) { UINT cPenData; if ((cPenData = (UINT)HIWORD(RegIdx)) >= MAX_PENPLOTTER_PENS) { PLOTERR(("GetPlotRegData: cPenData too big %ld (Max=%ld)", cPenData, MAX_PENPLOTTER_PENS)); cPenData = MAX_PENPLOTTER_PENS; } PRK.pwKey = GetPenDataKey(wBuf, (WORD)(Index - PRKI_PENDATA1 + 1)); PRK.Size = (DWORD)sizeof(PENDATA) * (DWORD)cPenData; pPRK = &PRK; } else { pPRK = (PPLOTREGKEY)&PlotRegKey[Index]; } if (xSetPrinterData(hPrinter, pPRK->pwKey, REG_BINARY, pData, pPRK->Size) != NO_ERROR) { PLOTERR(("SetPlotRegData: SetPrinterData(%ls [%ld]) failed", pPRK->pwKey, pPRK->Size)); return(FALSE); } else { PLOTDBG(DBG_SETREGDATA, ("SAVE '%ws' registry data", pPRK->pwKey)); return(TRUE); } }
BOOL GetPlotRegData( HANDLE hPrinter, LPBYTE pData, DWORD RegIdx ) /*++ Routine Description: This function retrieve from registry to the pData Arguments: hPrinter - Handle to the printer interested pData - Pointer to the data area buffer, it must large enough RegIdx - One of the PRKI_xxxx in LOWORD(Index), HIWORD(Index) specified total count for the PENDATA set Return Value: TRUE if sucessful, FALSE if failed, Author: 06-Dec-1993 Mon 22:22:47 created -by- Daniel Chou (danielc) 10-Dec-1993 Fri 01:13:14 updated -by- Daniel Chou (danielc) Fixed nesty problem in spooler of GetPrinterData which if we passed a pbData and cb but if it cannot get any data then it will clear all our buffer, this is not we expected (we expected it just return error rather clear our buffer). Now we do extended test before we really go get the data. The other problem is, if we set pbData = NULL then spooler always have excption happened even we pass &cb as NULL also. Revision History: --*/ { PPLOTREGKEY pPRK; LONG lRet; DWORD cb; DWORD Type; WCHAR wBuf[32]; PLOTREGKEY PRK; UINT Index; Index = LOWORD(RegIdx); PLOTASSERT(0, "GetPlotRegData: Invalid PRKI_xxx Index %ld", Index <= PRKI_LAST, Index); if (Index >= PRKI_PENDATA1) { UINT cPenData; if ((cPenData = (UINT)HIWORD(RegIdx)) >= MAX_PENPLOTTER_PENS) { PLOTERR(("GetPlotRegData: cPenData too big %ld (Max=%ld)", cPenData, MAX_PENPLOTTER_PENS)); cPenData = MAX_PENPLOTTER_PENS; } PRK.pwKey = GetPenDataKey(wBuf, (WORD)(Index - PRKI_PENDATA1 + 1)); PRK.Size = (DWORD)sizeof(PENDATA) * (DWORD)cPenData; pPRK = &PRK; } else { pPRK = (PPLOTREGKEY)&PlotRegKey[Index]; } // // We must do following sequence or if an error occurred then the pData // will be filled with ZEROs // // 1. Set Type/cb to invalid value // 1. query the type/size of the keyword, (if more data available) // 2. and If size is exact as we want // 3. and if the type is as we want (REG_BINARY) // 4. assume data valid then query it // Type = 0xffffffff; cb = 0; if ((lRet = xGetPrinterData(hPrinter, pPRK->pwKey, &Type, (LPBYTE)pData, 0, &cb)) != ERROR_MORE_DATA) { if (lRet == ERROR_FILE_NOT_FOUND) { PLOTWARN(("GetPlotRegData: GetPrinterData(%ls) not found", pPRK->pwKey)); } else { PLOTERR(("GetPlotRegData: 1st GetPrinterData(%ls) failed, Error=%ld", pPRK->pwKey, lRet)); } } else if (cb != pPRK->Size) { PLOTERR(("GetPlotRegData: GetPrinterData(%ls) Size != %ld (%ld)", pPRK->pwKey, pPRK->Size, cb)); } else if (Type != REG_BINARY) { PLOTERR(("GetPlotRegData: GetPrinterData(%ls) Type != REG_BINARY (%ld)", pPRK->pwKey, Type)); } else if ((lRet = xGetPrinterData(hPrinter, pPRK->pwKey, &Type, (LPBYTE)pData, pPRK->Size, &cb)) == NO_ERROR) { PLOTDBG(DBG_GETREGDATA, ("READ '%ws' REG Data: Type=%ld, %ld bytes", pPRK->pwKey, Type, cb)); return(TRUE); } else { PLOTERR(("GetPlotRegData: 2nd GetPrinterData(%ls) failed, Error=%ld", pPRK->pwKey, lRet)); } return(FALSE); }
BOOL SetPlotForm( PPLOTFORM pPlotForm, PPLOTGPC pPlotGPC, PPAPERINFO pCurPaper, PFORMSIZE pCurForm, PPLOTDEVMODE pPlotDM, PPPDATA pPPData ) /*++ Routine Description: This function computes the current FORM based on the printed margin. Auto rotation, landscape and other attributes are taken into account. The result is put into a PLOTFORM data structure located in our PDEV. This information is used to report data to GDI, as well as compute the HPGL2 parameters for sizing the target surface. Arguments: pPlotForm - Pointer to the PLOTFROM data structure which will be updated pPlotGPC - Pointer to the PLOTGPC data structure pCurPaper - Pointer to the PAPERINFO for the paper loaded pCurForm - Pointer to the FORMSIZE for the requested form pPlotDM - Pointer to the validated PLOTDEVMODE data structure pPPData - Pointer to the PPDATA structure Return Value: TRUE if sucessful, FALSE if failed Author: 29-Nov-1993 Mon 13:58:09 created 17-Dec-1993 Fri 23:09:38 updated Re-write so that we will look at CurPaper rather than pCurForm when setting the PSSize, p1/p2 stuff, it also rotate the pCurPaper if GPC/user said that the paper should loaded side way 20-Dec-1993 Mon 12:59:38 updated correct PFF_xxxx flag setting so we always rotate the bitmap to the left 90 degree 23-Dec-1993 Thu 20:35:57 updated Fixed roll paper clipping problem, change behavior, if we have roll paper installed then the it will make hard clip limit as big as user specified form size. 24-Dec-1993 Fri 12:20:02 updated Re-plot again, this is become really paint just try to understand what HP plotter design problems 06-Jan-1994 Thu 00:22:45 updated Update SPLTOPLOTUNITS() macro 07-Feb-1996 Wed 15:46:06 updated Change it so that it always using the current devmode form and then clip it to the device size. Revision History: This assumes that the user inserted the paper with width of the form first, LEGEND: + = Original paper corners * = Original plotter origin and its X/Y coordinate @ = the rotated origin using 'RO' command, intended to rotate the X/Y axis to the correct orientation for the window system # = Final plotter origin and its X/Y coordinate p1,p2 = final P1/P2 which will be used by the plotter driver cx,cy = Original paper width/height The following explaines how HPGL/2 loads the paper/form and assigns the default coordinate system to it, it also shows which way the paper is moving, the illustration to the right is when we need to rotate the printing direction and coordinate system when user selects the non-conforming X/Y coordinate system as opposed to the HPGL/2 default. ======================================================================= LENGTH >= WIDTH (CY >= CX) case ======================================================================= Portrait Paper Rotate Change Origin Default Left 90 Negative Y p2 cx cx p1 cx +---------+ +---------+ +---------+ | | | <------@| | | | | | X || | ^| | | ^| | | || | | || c| M || RO90 c| M || IP c| M || y| o || =====> y| o || ====> y| o || | v || | v Y|| | v Y|| | e X|| | e || | e || | | || | | || | | || | V || | V || | V || | Y || | V| | X || | <------*| | | | <------#| +---------+ +---------+ +---------+ p1 p2 | IP| | V Change Origin Negative X cx +---------+ | <------#| | Y || | | || c| M || y| o || | v X|| | e || | | || | V || | V| | | +---------+ ======================================================================= LENGTH < WIDTH (CY < CX) case ======================================================================= Landscape Rotate Left 90 Change Origin Paper Default Negative X cx p2 p2 cx cx +---------------+ +---------------+ +---------------+ | | | | | <--------#| |^ | | | | ^| | | Y || c|| M | c| M || c| M || y|| o | y| o || y| o || || v | RO90 | v X|| IP | v X|| ||Y e | =====> | e || ====> | e || || | | | | || | | || || X V | | V Y || | V V| |*--------> | | <--------@| | | +---------------+ +---------------+ +---------------+ p1 p1 | IP| | V Change Origin Negative X cx +---------------+ | | | | ^| c| M || y| o || | v Y|| | e || | | || | V X || | <--------#| +---------------+ --*/ { PLOTFORM PF; FORMSIZE DevForm; FORMSIZE ReqForm; RECTL rclDev; RECTL rclLog; SIZEL DeviceSize; LONG lTemp; BOOL DoRotate; PLOTDBG(DBG_PF, ("\n************* SetPlotForm *************\n")); // // We default using DeviceSize to check against the requested paper // DeviceSize = pPlotGPC->DeviceSize; rclDev = pPlotGPC->DeviceMargin; DoRotate = FALSE; // // Assume we using the current form from the devmode // DevForm = ReqForm = *pCurForm; PLOTDBG(DBG_PF, ("DeviceSize: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld", DeviceSize.cx, DeviceSize.cy, rclDev.left, rclDev.top, rclDev.right, rclDev.bottom)); PLOTDBG(DBG_PF, ("ReqForm: <%s>", pPlotDM->dm.dmFormName, ReqForm.Size.cx, ReqForm.Size.cy)); PLOTDBG(DBG_PF, ("ReqForm: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld [%ld x %ld]", ReqForm.Size.cx, ReqForm.Size.cy, ReqForm.ImageArea.left, ReqForm.ImageArea.top, ReqForm.ImageArea.right, ReqForm.ImageArea.bottom, ReqForm.ImageArea.right - ReqForm.ImageArea.left, ReqForm.ImageArea.bottom - ReqForm.ImageArea.top)); if (pCurPaper->Size.cy == 0) { // // ROLL PAPER CASE // // If we have roll paper installed, we must determine the projection // of the current form on the roll paper in order to get the size // to come out correctly. // DevForm.Size.cx = pCurPaper->Size.cx; DevForm.Size.cy = DeviceSize.cy; PLOTDBG(DBG_PF,(">>ROLL FEED<< RollPaper = %ld x %ld, <RESET rclDev to ALL ZEROs>", DevForm.Size.cx, DevForm.Size.cy)); } else if ((pPlotGPC->Flags & PLOTF_PAPERTRAY) && ((DevForm.Size.cx == DeviceSize.cx) || (DevForm.Size.cy == DeviceSize.cx))) { // // PAPER TRAY CASE: We need to make the DeviceSize equal to the DevForm // so that the margin will be correctly computed // DoRotate = (BOOL)(DevForm.Size.cx != DeviceSize.cx); PLOTDBG(DBG_PF,(">>PAPER TRAY<< Rotate Paper = %hs", (DoRotate) ? "YES" : "NO")); } else { PLOTASSERT(0, "SetPlotForm: Not supposed MANUAL feed the PAPER TRAY type PLOTTER", !(pPlotGPC->Flags & PLOTF_PAPERTRAY), pPlotGPC->Flags); PLOTDBG(DBG_PF,(">>MANUAL FEED<<")); // // MANUAL FEED CASE, this is the way paper is physically loaded, only // problem is if the paper is smaller than device can handle then we // really don't know where they inserted the paper. // DoRotate = (BOOL)(!(pPPData->Flags & PPF_MANUAL_FEED_CX)); PLOTDBG(DBG_PF,("The MANUAL FEED paper Inserted %hs side first.", (DoRotate) ? "Length CY" : "Width CX")); } if (DoRotate) { SWAP(DevForm.Size.cx, DevForm.Size.cy, lTemp); PLOTDBG(DBG_PF, ("### Rotated DevForm to %ld x %ld ###", DevForm.Size.cx, DevForm.Size.cy)); } // // Make sure largest requested form can be installed on the plotter // if (DevForm.Size.cx > DeviceSize.cx) { PLOTDBG(DBG_PF, ("WIDTH: DevForm (%ld) > DeviceSize (%ld). CORRECT IT", DevForm.Size.cx, DeviceSize.cx)); DevForm.Size.cx = DeviceSize.cx; } if (DevForm.Size.cy > DeviceSize.cy) { PLOTDBG(DBG_PF, ("HEIGHT: DevForm (%ld) > DeviceSize (%ld). CORRECT IT", DevForm.Size.cy, DeviceSize.cy)); DevForm.Size.cy = DeviceSize.cy; } // // Figure out how to fit this requested form onto loaded device form // DoRotate = FALSE; if ((DevForm.Size.cx >= ReqForm.Size.cx) && (DevForm.Size.cy >= ReqForm.Size.cy)) { // // Can print without doing any rotation, but check for paper saver, // the paper saver is only possible if: // // 1) Is a Roll paper, // 2) User approves // 3) ReqForm length > width // 4) DevForm width >= ReqForm length // if ((pCurPaper->Size.cy == 0) && (pPPData->Flags & PPF_AUTO_ROTATE) && (ReqForm.Size.cy > ReqForm.Size.cx) && (DevForm.Size.cx >= ReqForm.Size.cy)) { PLOTDBG(DBG_PF, ("ROLL PAPER SAVER: Doing AUTO_ROTATE")); DoRotate = !DoRotate; } } else if ((DevForm.Size.cx >= ReqForm.Size.cy) && (DevForm.Size.cy >= ReqForm.Size.cx)) { // // Can print but we have to rotate the form ourselves // PLOTDBG(DBG_PF, ("INTERNAL ROTATE to fit Requseted FROM into device")); DoRotate = !DoRotate; } else { // // CANNOT print the requested form, so clip the form requested // PLOTDBG(DBG_PF, (">>>>> ReqForm is TOO BIG to FIT, Need to CLIP IT <<<<<")); ReqForm.Size = DevForm.Size; } if (DoRotate) { DoRotate = (BOOL)(pPlotDM->dm.dmOrientation != DMORIENT_LANDSCAPE); // // If we need to rotate one more time back to the same position for // the logical paper size then we must rotate to the left first, this // is because ALL our ORIGIN x,y are either at the front of the plotter // or at the front panel side of the plotter // RotatePaper(&(ReqForm.Size), &(ReqForm.ImageArea), (DoRotate) ? RM_L90 : RM_R90); PLOTDBG(DBG_PF, ("INTERNAL Rotated ReqForm: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld [%ld x %ld]", ReqForm.Size.cx, ReqForm.Size.cy, ReqForm.ImageArea.left, ReqForm.ImageArea.top, ReqForm.ImageArea.right, ReqForm.ImageArea.bottom, ReqForm.ImageArea.right - ReqForm.ImageArea.left, ReqForm.ImageArea.bottom - ReqForm.ImageArea.top)); } else { DoRotate = (BOOL)(pPlotDM->dm.dmOrientation == DMORIENT_LANDSCAPE); } // // Now the ReqForm is guaranteed to fit into the device paper. Find out how // it fits into the printable area and set the hardware margins appropriately. // DevForm.Size = ReqForm.Size; DevForm.ImageArea.left = rclDev.left; DevForm.ImageArea.top = rclDev.top; DevForm.ImageArea.right = DevForm.Size.cx - rclDev.right; DevForm.ImageArea.bottom = DevForm.Size.cy - rclDev.bottom; // // Intersect the requested form imageable area with the DevForm imageable area // IntersectRECTL(&(ReqForm.ImageArea), &(DevForm.ImageArea)); // // Now figure out the offset from the logical margin to the physical margin // rclLog.left = ReqForm.ImageArea.left - DevForm.ImageArea.left; rclLog.top = ReqForm.ImageArea.top - DevForm.ImageArea.top; rclLog.right = DevForm.ImageArea.right - ReqForm.ImageArea.right; rclLog.bottom = DevForm.ImageArea.bottom - ReqForm.ImageArea.bottom; // // Rotate the requested form if necessary // if (DoRotate) { RotatePaper(&(ReqForm.Size), &(ReqForm.ImageArea), RM_R90); // // Now we can pick the right margin/corner for the rotation // // cx Rotate Left 90 Rotate Right 90 // +-------+ // | T | cy cy // | | +------------+ +------------+ // c| | | R | | L | // y| | c| | c| | // |L R| x| | x| | // | | |T B| |B T| // | | | | | | // | | | L | | R | // | B | +------------+ +------------+ // +-------+ // PLOTDBG(DBG_PF, ("ROTATED RIGHT ReqForm: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld [%ld x %ld]", ReqForm.Size.cx, ReqForm.Size.cy, ReqForm.ImageArea.left, ReqForm.ImageArea.top, ReqForm.ImageArea.right, ReqForm.ImageArea.bottom, ReqForm.ImageArea.right - ReqForm.ImageArea.left, ReqForm.ImageArea.bottom - ReqForm.ImageArea.top)); } PLOTDBG(DBG_PF, ("FINAL DevForm: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld [%ld x %ld]", DevForm.Size.cx, DevForm.Size.cy, DevForm.ImageArea.left, DevForm.ImageArea.top, DevForm.ImageArea.right, DevForm.ImageArea.bottom, DevForm.ImageArea.right - DevForm.ImageArea.left, DevForm.ImageArea.bottom - DevForm.ImageArea.top)); PLOTDBG(DBG_PF, ("FINAL ReqForm: %ld x %ld, L=%ld, T=%ld, R=%ld, B=%ld [%ld x %ld]", ReqForm.Size.cx, ReqForm.Size.cy, ReqForm.ImageArea.left, ReqForm.ImageArea.top, ReqForm.ImageArea.right, ReqForm.ImageArea.bottom, ReqForm.ImageArea.right - ReqForm.ImageArea.left, ReqForm.ImageArea.bottom - ReqForm.ImageArea.top)); PLOTDBG(DBG_PF, ("rclLog: L=%ld, T=%ld, R=%ld, B=%ld", rclLog.left, rclLog.top, rclLog.right, rclLog.bottom)); // // Set fields in PLOTFORM // PF.Flags = 0; PF.BmpRotMode = BMP_ROT_NONE; PF.NotUsed = 0; PF.PlotSize.cx = DevForm.ImageArea.right - DevForm.ImageArea.left; PF.PlotSize.cy = DevForm.ImageArea.bottom - DevForm.ImageArea.top; PF.PhyOrg.x = ReqForm.ImageArea.left; PF.PhyOrg.y = ReqForm.ImageArea.top; PF.LogSize = ReqForm.Size; PF.LogExt.cx = ReqForm.ImageArea.right - ReqForm.ImageArea.left; PF.LogExt.cy = ReqForm.ImageArea.bottom - ReqForm.ImageArea.top; PF.BmpOffset.x = rclLog.left; PF.BmpOffset.y = rclLog.top; if (PF.PlotSize.cy >= PF.PlotSize.cx) { PLOTDBG(DBG_FORMSIZE,(">>>>> Plot SIze: CY >= CX (%ld: VERTICAL%hs) <<<<<", (DoRotate) ? 1 : 2, (DoRotate) ? " + ROTATE" : "")); // // The Standard HPGL/2 coordinate Y direction in in reverse, the scale // is from Max Y to 0. // if (DoRotate) { // // Portrait Paper Scale Coord X // Default Negative X // // p2 cx cx // +---------+ +---------+ // | | | <------#| // | | | Y || // | | ^| | | || // c| M || c| M || // y| o || ====> y| o || // | v || | v X|| // | e X|| | e || // | | || | | || // | V || | V || // | Y || | V| // | <------*| | | // +---------+ +---------+ // p1 // PF.Flags |= PFF_FLIP_X_COORD; PF.BmpRotMode = BMP_ROT_RIGHT_90; PF.LogOrg.x = rclLog.top; PF.LogOrg.y = rclLog.left; } else { // // Portrait Paper Rotate Scale Coord Y // Default Left 90 Negative Y // // p2 cx cx p1 cx // +---------+ +---------+ +---------+ // | | | <------@| | | // | | | X || | ^| // | | ^| | | || | | || // c| M || RO90 c| M || c| M || // y| o || =====> y| o || ====> y| o || // | v || | v Y|| | v Y|| // | e X|| | e || | e || // | | || | | || | | || // | V || | V || | V || // | Y || | V| | X || // | <------*| | | | <------#| // +---------+ +---------+ +---------+ // p1 p2 // PF.Flags |= (PFF_ROT_COORD_L90 | PFF_FLIP_Y_COORD); PF.LogOrg.x = rclLog.left; PF.LogOrg.y = rclLog.bottom; } } else { PLOTDBG(DBG_FORMSIZE,(">>>>> SetPlotForm: CY < CX (%ld: HORIZONTAL%hs) <<<<<", (DoRotate) ? 3 : 4, (DoRotate) ? " + ROTATE" : "")); // // The Standard HPGL/2 coordinate X direction in in reverse, the scale // is from Max X to 0 // if (DoRotate) { // // DoRotate Rotate Left 90 Scale Coord X // Paper Default Negative X // // cx p2 p2 cx cx // +---------------+ +---------------+ +---------------+ // | | | | | <--------#| // |^ | | | | ^| | | Y || // c|| M | c| M || c| M || // y|| o | y| o || y| o || // || v | RO90 | v X|| | v X|| // ||Y e |=====> | e || ==> | e || // || | | | | || | | || // || X V | | V Y || | V V| // |*--------> | | <--------@| | | // +---------------+ +---------------+ +---------------+ // p1 p1 // PF.Flags |= (PFF_ROT_COORD_L90 | PFF_FLIP_X_COORD); PF.BmpRotMode = BMP_ROT_RIGHT_90; PF.LogOrg.x = rclLog.top; PF.LogOrg.y = rclLog.left; } else { // // DoRotate Scale Coord X // Paper Default Negative X // // cx p2 cx // +----------------+ +-----------------+ // | | | | // |^ | | | | ^| // c|| M | c| M || // y|| o | y| o || // || v | ====> | v Y|| // ||Y e | | e || // || | | | | || // || X V | | V X || // |*--------> | | <--------#| // +----------------+ +-----------------+ // p1 // PF.Flags |= PFF_FLIP_X_COORD; PF.LogOrg.x = rclLog.right; PF.LogOrg.y = rclLog.top; } } PLOTDBG(DBG_PF, ("FINAL LogOrg: (%ld, %ld), PhyOrg=(%ld, %ld)", PF.LogOrg.x, PF.LogOrg.y, PF.PhyOrg.x, PF.PhyOrg.y)); // // Save result and output some information // *pPlotForm = PF; PLOTDBG(DBG_PLOTFORM,("******************************************************")); PLOTDBG(DBG_PLOTFORM,("******* SetPlotForm: ****** %hs --> %hs ******\n", (pPlotDM->dm.dmOrientation == DMORIENT_LANDSCAPE) ? "LANDSCAPE" : "PORTRAIT", (DoRotate) ? "LANDSCAPE" : "PORTRAIT")); PLOTDBG(DBG_PLOTFORM,(" Flags =%hs%hs%hs", (PF.Flags & PFF_ROT_COORD_L90) ? " <ROT_COORD_L90> " : "", (PF.Flags & PFF_FLIP_X_COORD) ? " <FLIP_X_COORD> " : "", (PF.Flags & PFF_FLIP_Y_COORD) ? " <FLIP_Y_COORD> " : "")); PLOTDBG(DBG_PLOTFORM,(" BmpRotMode = %hs", pBmpRotMode[PF.BmpRotMode])); PLOTDBG(DBG_PLOTFORM,(" PlotSize = (%7ld x%7ld) [%5ld x%6ld]", PF.PlotSize.cx, PF.PlotSize.cy, SPLTOPLOTUNITS(pPlotGPC, PF.PlotSize.cx), SPLTOPLOTUNITS(pPlotGPC, PF.PlotSize.cy))); PLOTDBG(DBG_PLOTFORM,("PhyOrg/Offset = (%7ld,%8ld) [%5ld,%7ld] ", PF.PhyOrg.x, PF.PhyOrg.y, SPLTOPLOTUNITS(pPlotGPC, PF.PhyOrg.x), SPLTOPLOTUNITS(pPlotGPC, PF.PhyOrg.y))); PLOTDBG(DBG_PLOTFORM,(" LogSize = (%7ld x%7ld) [%5ld x%6ld]", PF.LogSize.cx, PF.LogSize.cy, SPLTOPLOTUNITS(pPlotGPC, PF.LogSize.cx), SPLTOPLOTUNITS(pPlotGPC, PF.LogSize.cy))); PLOTDBG(DBG_PLOTFORM,(" LogOrg/p1 = (%7ld,%8ld) [%5ld,%7ld]", PF.LogOrg.x, PF.LogOrg.y, SPLTOPLOTUNITS(pPlotGPC, PF.LogOrg.x), SPLTOPLOTUNITS(pPlotGPC, PF.LogOrg.y))); PLOTDBG(DBG_PLOTFORM,(" LogExt = (%7ld,%8ld) [%5ld,%7ld]\n", PF.LogExt.cx, PF.LogExt.cy, SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cx), SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cy))); PLOTDBG(DBG_PLOTFORM,(" BmpOffset = (%7ld,%8ld) [%5ld,%7ld]", PF.BmpOffset.x, PF.BmpOffset.y, SPLTOPLOTUNITS(pPlotGPC, PF.BmpOffset.x), SPLTOPLOTUNITS(pPlotGPC, PF.BmpOffset.y))); PLOTDBG(DBG_PLOTFORM, ("Commands=PS%ld,%ld;%hsIP%ld,%ld,%ld,%ld;SC%ld,%ld,%ld,%ld\n", SPLTOPLOTUNITS(pPlotGPC, PF.PlotSize.cy), SPLTOPLOTUNITS(pPlotGPC, PF.PlotSize.cx), (PF.Flags & PFF_ROT_COORD_L90) ? "RO90;" : "", SPLTOPLOTUNITS(pPlotGPC, PF.LogOrg.x), SPLTOPLOTUNITS(pPlotGPC, PF.LogOrg.y), SPLTOPLOTUNITS(pPlotGPC, (PF.LogOrg.x + PF.LogExt.cx)) - 1, SPLTOPLOTUNITS(pPlotGPC, (PF.LogOrg.y + PF.LogExt.cy)) - 1, (PF.Flags & PFF_FLIP_X_COORD) ? SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cx) - 1 : 0, (PF.Flags & PFF_FLIP_X_COORD) ? 0 : SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cx) - 1, (PF.Flags & PFF_FLIP_Y_COORD) ? SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cy) - 1 : 0, (PF.Flags & PFF_FLIP_Y_COORD) ? 0 : SPLTOPLOTUNITS(pPlotGPC, PF.LogExt.cy) - 1)); return(TRUE); }
VOID SetDefaultPLOTDM( HANDLE hPrinter, PPLOTGPC pPlotGPC, LPWSTR pwDeviceName, PPLOTDEVMODE pPlotDM, PFORMSIZE pCurForm ) /*++ Routine Description: This function set the default devmode based on the current pPlotGPC Arguments: hPrinter - Handle to the printer pPlotGPC - our loaded/verified GPC data. pwDeviceName - the device name passed in pPlotDM - Pointer to our ExtDevMode pCurForm - Pointer to the FORMSIZE data structure which will be updated if the pointer is not NULL, the final result of the form size/imagable area selected by the user will be written to here. the form name will be in pPlotDM->dmFormName. Return Value: VOID Author: 14-Dec-1993 Tue 20:21:48 updated -by- Daniel Chou (danielc) Update the dmScale based on maximum the device can support 06-Dec-1993 Mon 12:49:52 updated -by- Daniel Chou (danielc) make sure we turn off the DM_xxx bits if one of those is not valid or supported in current plotter 16-Nov-1993 Tue 13:49:27 created -by- Daniel Chou (danielc) Revision History: --*/ { WCHAR DeviceName[CCHDEVICENAME]; if (pwDeviceName) { _WCPYSTR(DeviceName, pwDeviceName, CCHDEVICENAME); // // Make sure the PlotGPC's device name is ssync with the pDeviceName // passed // WStr2Str(pPlotGPC->DeviceName, DeviceName); PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls", pPlotGPC->DeviceName, pwDeviceName)); } else { PLOTERR(("No DeviceName passed, using GPC's '%hs'", pPlotGPC->DeviceName)); str2Wstr(DeviceName, pPlotGPC->DeviceName); } // // Make a default copy first then copy device name down // CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE)); WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, DeviceName); // // We must turn off the DM_xxx bits in dmFields if we do not support it, // look at default fields we copy down then update it // if (pPlotGPC->MaxScale) { if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) { pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale; } } else { pPlotDM->dm.dmFields &= ~DM_SCALE; } if (pPlotGPC->MaxCopies <= 1) { pPlotDM->dm.dmFields &= ~DM_COPIES; } if (!(pPlotGPC->MaxQuality)) { pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY; } // // DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right // if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) { pPlotDM->dm.dmPrintQuality = DMRES_LOW; PLOTWARN(("SetDefaultPLOTDM: HACK Default Qaulity = DMRES_LOW")); } if (!(pPlotGPC->Flags & PLOTF_COLOR)) { if (pPlotGPC->Flags & PLOTF_RASTER) { pPlotDM->dm.dmFields &= ~DM_COLOR; pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME; } else { PLOTASSERT(0, "SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.", (pPlotGPC->Flags & PLOTF_COLOR), 0); pPlotGPC->Flags |= PLOTF_COLOR; } } // // Set default form name based on the country // SetDefaultDMForm(pPlotDM, pCurForm); }
BOOL RotatePaper( PSIZEL pSize, PRECTL pImageArea, UINT RotateMode ) /*++ Routine Description: This function rotate a paper left 90 degree, right 90 degree or 180 degree depends on the RotateMode passed Arguments: pSize - Pointer to the size of the paper to be rotated pImageArea - Pointer to the RECTL of Imageable area RotateMode - Must be one of RM_L90, RM_R90, RM_180 Return Value: No return value, but the pSize, and pImageArea pointed to location will be updated. Author: 16-Dec-1993 Thu 09:18:33 created -by- Daniel Chou (danielc) Revision History: --*/ { SIZEL Size; RECTL Margin; // // To be sucessfully rotate the paper to the left 90 degree we must know // all four sides margin before we can do anything // Size = *pSize; Margin.left = pImageArea->left; Margin.top = pImageArea->top; Margin.right = Size.cx - pImageArea->right; Margin.bottom = Size.cy - pImageArea->bottom; PLOTASSERT(0, "RotatePaper: cx size too small (%ld)", (Size.cx - Margin.left - Margin.right) > 0, Size.cx); PLOTASSERT(0, "RotatePaper: cy size too small (%ld)", (Size.cy - Margin.top - Margin.bottom) > 0, Size.cy); PLOTDBG(DBG_ROTPAPER, ("RotatePaper(%ld) FROM (%ld x %ld), (%ld, %ld)-(%ld, %ld)", (LONG)RotateMode, pSize->cx, pSize->cy, pImageArea->left, pImageArea->top, pImageArea->right, pImageArea->bottom)); // // Now we can pick the right margin/corner for the rotation // // cx Rotate Left 90 Rotate Right 90 // +-------+ // | T | cy cy // | | +------------+ +------------+ // c| | | R | | L | // y| | c| | c| | // |L R| x| | x| | // | | |T B| |B T| // | | | | | | // | | | L | | R | // | B | +------------+ +------------+ // +-------+ // switch (RotateMode) { case RM_L90: pSize->cx = Size.cy; pSize->cy = Size.cx; pImageArea->left = Margin.top; pImageArea->top = Margin.right; pImageArea->right = Size.cy - Margin.bottom; pImageArea->bottom = Size.cx - Margin.left; break; case RM_R90: pSize->cx = Size.cy; pSize->cy = Size.cx; pImageArea->left = Margin.bottom; pImageArea->top = Margin.left; pImageArea->right = Size.cy - Margin.top; pImageArea->bottom = Size.cx - Margin.right; break; case RM_180: pImageArea->top = Margin.bottom; pImageArea->bottom = Size.cy - Margin.top; break; default: PLOTERR(("RotatePaper(%ld): Invalid RotateMode passed", RotateMode)); return(FALSE); } PLOTDBG(DBG_ROTPAPER, ("RotatePaper(%ld) - TO (%ld x %ld), (%ld, %ld)-(%ld, %ld)", (LONG)RotateMode, pSize->cx, pSize->cy, pImageArea->left, pImageArea->top, pImageArea->right, pImageArea->bottom)); return(TRUE); }
DWORD ValidateSetPLOTDM( HANDLE hPrinter, PPLOTGPC pPlotGPC, LPWSTR pwDeviceName, PPLOTDEVMODE pPlotDMIn, PPLOTDEVMODE pPlotDMOut, PFORMSIZE pCurForm ) /*++ Routine Description: This function set and validate the pPlotDMOut from pPlotDMIn (if not null and valid) Arguments: hPrinter - Handle to the printer to be checked pPlotGPC - The plotter's GPC data loaded from the file pwDeviceName - Device Name to be put into dmDeviceName, if NULL then the device name is set from pPlotGPC->DeviceName pPlotDMIn - pointer to the input PLOTDEVMODE data structure, if can be NULL pPlotDMOut - Pointer to the output PLOTDEVMODE data structure, if pPlotDMIn is NULL then a default PLOTDEVMODE is returned pCurForm - Pointer to the FORMSIZE data structure which will be updated if the pointer is not NULL, the final result of the form size/imagable area selected by the user will be written to here. the form name will be in pPlotDM->dmFormName. Return Value: the return value is a DWORD dmField error code which specified dmFields are invalid (DM_xxxxx in wingdi.h) if the return value has any DM_INV_xxx bits set then it should raised an error to the user. if return value is 0 then function sucessful Author: 23-Nov-1993 Tue 10:08:50 created -by- Daniel Chou (danielc) 15-Dec-1993 Wed 21:27:52 updated -by- Daniel Chou (danielc) Fixed bug which compare dmPaperWidth/Length to MIN_SPL_FORM_CX 18-Dec-1993 Sat 03:57:24 updated -by- Daniel Chou (danielc) Fixed bug which reset dmFields when we checking DM_PAPERxxx and DM_FORMNAME, this turn off DM_ORIENTATION fields which let the orientation setting never stick. Also change how this fucntion set the paper fields, this function now only set DM_FORMNAME upon returned if the dmPaperSize getting larger then DMPAPER_LAST, otherwise it set DM_FORMNAME | DM_PAPERSIZE 12-Apr-1994 Tue 15:07:24 updated -by- Daniel Chou (danielc) Make smaller spec version printable 25-Oct-1994 Tue 13:41:03 updated -by- Daniel Chou (danielc) Change to have default as current Printer Properties setting first, Revision History: --*/ { DWORD dmErrFields = 0; PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotDMOut", pPlotDMOut, 0); PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotGPC", pPlotGPC, 0); if ((pPlotDMOut) || (pPlotGPC)) { PPRINTER_INFO_2 pPrinter2 = NULL; DWORD cbNeed; DWORD cbRet; // // First: set the default PLOTDEVMODE for the output then from there // validate/settting from input devmode, if pwDeviceName passed // as NULL then it assume that pPlotDMOut alreay set and // validated // if (pwDeviceName) { SetDefaultPLOTDM(hPrinter, pPlotGPC, pwDeviceName, pPlotDMOut, pCurForm); PLOTDBG(DBG_DEFDEVMODE, ("ValidateSetPLOTDM: Set Default PLOTDM DeviceName=%ls", pwDeviceName)); } // // Now see if we can get the current printman devmode setting as default // cbNeed = cbRet = 0; if ((!xGetPrinter(hPrinter, 2, NULL, 0, &cbNeed)) && (xGetLastError() == ERROR_INSUFFICIENT_BUFFER) && (pPrinter2 = LocalAlloc(LMEM_FIXED, cbNeed)) && (xGetPrinter(hPrinter, 2, (LPBYTE)pPrinter2, cbNeed, &cbRet)) && (cbNeed == cbRet) && (pPrinter2->pDevMode)) { PLOTDBG(DBG_DEFDEVMODE, ("ValidateSetPLOTDM: Got the PrintMan DEVMODE")); dmErrFields = MergePLOTDM(hPrinter, pPlotGPC, (PPLOTDEVMODE)pPrinter2->pDevMode, pPlotDMOut, pCurForm); } else { PLOTWARN(("ValidateSetPLOTDM: CANNOT get the PrintMan's DEVMODE")); PLOTWARN(("pPrinter2=%08lx, pDevMode=%08lx, cbNeed=%ld, cbRet=%ld, LastErr=%ld", pPrinter2, (pPrinter2) ? pPrinter2->pDevMode : 0, cbNeed, cbRet, xGetLastError())); } if (pPrinter2) { LocalFree((HLOCAL)pPrinter2); } // // Now the pPlotDMOut is validated, merge it with user's request // if (pPlotDMIn) { dmErrFields = MergePLOTDM(hPrinter, pPlotGPC, pPlotDMIn, pPlotDMOut, pCurForm); } } return(dmErrFields); }
VOID SetDefaultPLOTDM( HANDLE hPrinter, _In_ PPLOTGPC pPlotGPC, _In_opt_ LPCWSTR pwDeviceName, _In_ PPLOTDEVMODE pPlotDM, _Out_opt_ PFORMSIZE pCurForm ) /*++ Routine Description: This function set the default devmode based on the current pPlotGPC Arguments: hPrinter - Handle to the printer pPlotGPC - our loaded/verified GPC data. pwDeviceName - the device name passed in pPlotDM - Pointer to our ExtDevMode pCurForm - Pointer to the FORMSIZE data structure which will be updated if the pointer is not NULL, the final result of the form size/imagable area selected by the user will be written to here. the form name will be in pPlotDM->dmFormName. Return Value: VOID Author: 14-Dec-1993 Tue 20:21:48 updated Update the dmScale based on maximum the device can support 06-Dec-1993 Mon 12:49:52 updated make sure we turn off the DM_xxx bits if one of those is not valid or supported in current plotter 16-Nov-1993 Tue 13:49:27 created Revision History: --*/ { WCHAR *pwchDeviceName = NULL; ULONG ulStrLen = 0; UNREFERENCED_PARAMETER(hPrinter); // // Device name including NULL terminator // must be equal or shorter than CCHDEVICENAME. // PREFIX doesn' take this assumption. Buffer size needs to be flexible and // should not be on stack. // if (pwDeviceName) { ulStrLen = (ULONG)wcslen(pwDeviceName); // // Allocate buffer to hold pwDeviceName including null terminator. // Make sure that pwDeviceName has a device name. // if (0 == ulStrLen || !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR)))) { PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n")); // // Make sure that pPlotGPC->DeviceName has a null terminator. // pPlotGPC->DeviceName[0] = (BYTE)'\0'; } else { _WCPYSTR_FILL_TRAIL_WITH_NULL(pwchDeviceName, ulStrLen + 1, pwDeviceName); // // Make sure the PlotGPC's device name is ssync with the pDeviceName // passed. // String length must be equal or shorter than CCHDEVICENAME. // DEVMODE's device name and pPlotGPC->DeviceName can't hold a sting // longer than CCHDEVICENAME. // if (ulStrLen + 1 > CCHDEVICENAME) { PLOTERR(("SetDefaultPLOTDM: DeviceName is longer than buffer size.\n")); } else { WStr2Str(pPlotGPC->DeviceName, CCHOF(pPlotGPC->DeviceName), pwchDeviceName); } } PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls", pPlotGPC->DeviceName, pwDeviceName)); } else { PLOTERR(("No DeviceName passed, using GPC's '%hs'", pPlotGPC->DeviceName)); ulStrLen = (ULONG)strlen(pPlotGPC->DeviceName); // // Allocate buffer to hold pwDeviceName including null terminator. // Make sure that pwDeviceName has a device name. // if (0 == ulStrLen || !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR)))) { PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n")); } else { str2Wstr(pwchDeviceName, ulStrLen + 1, pPlotGPC->DeviceName); } } // // Make a default copy first then copy device name down // CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE)); if (pwchDeviceName) { WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, CCHOF(pPlotDM->dm.dmDeviceName), pwchDeviceName); LocalFree(pwchDeviceName); } else { pPlotDM->dm.dmDeviceName[0] = L'\0'; } // // We must turn off the DM_xxx bits in dmFields if we do not support it, // look at default fields we copy down then update it // if (pPlotGPC->MaxScale) { if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) { pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale; } } else { pPlotDM->dm.dmFields &= ~DM_SCALE; } if (pPlotGPC->MaxCopies <= 1) { pPlotDM->dm.dmFields &= ~DM_COPIES; } if (!(pPlotGPC->MaxQuality)) { pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY; } // // DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right // if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) { pPlotDM->dm.dmPrintQuality = DMRES_LOW; PLOTWARN(("SetDefaultPLOTDM: Force Default Qaulity = DMRES_LOW")); } if (!(pPlotGPC->Flags & PLOTF_COLOR)) { if (pPlotGPC->Flags & PLOTF_RASTER) { pPlotDM->dm.dmFields &= ~DM_COLOR; pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME; } else { PLOTASSERT(0, "SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.", (pPlotGPC->Flags & PLOTF_COLOR), 0); pPlotGPC->Flags |= PLOTF_COLOR; } } // // Set default form name based on the country/region // SetDefaultDMForm(pPlotDM, pCurForm); }
SHORT GetDefaultPaper( PPAPERINFO pPaperInfo ) /*++ Routine Description: This function compute the default paper name, size. Arguments: pPaperInfo - Point to the paper info which will be fill by this function Return Value: It return a SHORT value which specified the standard paper index in as DMPAPER_xxx Author: 03-Dec-1993 Fri 13:13:42 created Revision History: --*/ { SHORT dmPaperSize; HRESULT hr; if (pPaperInfo == NULL) { return 0; } pPaperInfo->ImageArea.left = pPaperInfo->ImageArea.top = 0; if (IsA4PaperDefault()) { dmPaperSize = (SHORT)DMPAPER_A4; pPaperInfo->Size.cx = pPaperInfo->ImageArea.right = DMTOSPL(A4_FORM_CX); pPaperInfo->Size.cy = pPaperInfo->ImageArea.bottom = DMTOSPL(A4_FORM_CY); hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), A4_FORM_NAME); if (FAILED(hr) ) { PLOTASSERT(0, "Couldn't copy the string %ls to pPaperInfo", SUCCEEDED(hr), A4_FORM_NAME); } PLOTDBG(DBG_DEFPAPER, ("Pick 'A4' paper as default")); } else { dmPaperSize = (SHORT)DMPAPER_LETTER; pPaperInfo->Size.cx = (LONG)_DefPlotDM.dm.dmPaperWidth; pPaperInfo->Size.cy = (LONG)_DefPlotDM.dm.dmPaperLength; dmPaperSize = (SHORT)DMPAPER_LETTER; pPaperInfo->Size.cx = pPaperInfo->ImageArea.right = DMTOSPL(_DefPlotDM.dm.dmPaperWidth); pPaperInfo->Size.cy = pPaperInfo->ImageArea.bottom = DMTOSPL(_DefPlotDM.dm.dmPaperLength); hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), _DefPlotDM.dm.dmFormName); if (FAILED(hr) ) { PLOTASSERT(0, "Couldn't copy the string %ls to pPaperInfo", SUCCEEDED(hr), _DefPlotDM.dm.dmFormName); } PLOTDBG(DBG_DEFPAPER, ("Pick 'Letter' paper as default")); } PLOTDBG(DBG_DEFPAPER, ("SetDefaultPaper: '%ls' (%ld x %ld)", pPaperInfo->Name, pPaperInfo->Size.cx, pPaperInfo->Size.cy)); return(dmPaperSize); }
VOID SelectColor( PPDEV pPDev, DWORD Color, INTDECIW PenWidth ) /*++ Routine Description: This function is responsible for handling the mechanism of supporting RGB colors on plotters that support this. This is done by using a preset pallete position that the engine does not know about, and constantly update it with the correct color. Arguments: pPDev - Pointer to the PDEV data structure Color - Color to be selected PenWidth - INTDECIW data structrue to specified the pen width Return Value: VOID Author: 30-Nov-1993 Tue 22:15:12 created 12-Apr-1994 Tue 14:35:44 updated Update to take pen plotter into account and take care the error cases Revision History: --*/ { PLOTASSERT(1, "SelectColor: Invalid RGB Color [%08lx] for Raster DEVICE", Color != CLR_INVALID, Color); if (Color == CLR_INVALID) { // // Make it white // Color = (DWORD)(IS_RASTER(pPDev) ? 0x00FFFFFF : WHITE_INDEX); } if (IS_RASTER(pPDev)) { Color = (DWORD)FindCachedPen(pPDev, (PPALENTRY)&Color); } else { if (Color > (DWORD)pPDev->pPlotGPC->Pens.Count) { Color = (DWORD)pPDev->BrightestPen; PLOTDBG(DBG_SELECTCOLOR, ("SelectColor: !!! Match to Closest WHITE PEN=%ld", Color)); PLOTASSERT(1, "SelectColor: Invalid Pen Index [%08ld] for PEN DEVICE", (Color <= (DWORD)pPDev->pPlotGPC->Pens.Count), Color); if (Color > (DWORD)pPDev->pPlotGPC->Pens.Count) { Color = WHITE_INDEX; } } } // // Verify were not selecting the current pen // if (Color != (DWORD)pPDev->CurPenSelected) { PLOTDBG(DBG_SELECTCOLOR, ("SelectColor: Current Pen [%ld] != new PEN [%ld]", pPDev->CurPenSelected, Color)); OutputFormatStr(pPDev,"SP#d", (LONG)Color); pPDev->CurPenSelected = (LONG)Color; } else { PLOTDBG(DBG_SELECTCOLOR, ("SelectColor: Current Pen == new PEN [%ld]", Color)); } // // Set the correct pen width in the target device. This will change // the pen width for all pens. // if ((PenWidth.Integer != pPDev->PenWidth.Integer) || (PenWidth.Decimal != pPDev->PenWidth.Decimal)) { // // Now send the optimal pen width number command to the target device. // OutputString(pPDev, "PW"); if ((PenWidth.Integer) || (PenWidth.Decimal == 0)) { // // This will make the following cases // // 1. 0.0 ---> 0 // 2. 3.2 ---> 3 // 3. 3.0 ---> 3 OutputFormatStr(pPDev, "#d", PenWidth.Integer); } if (PenWidth.Decimal) { // // Do all DECI part as .xx // OutputFormatStr(pPDev, ".#d", PenWidth.Decimal); } PLOTDBG(DBG_SELECTCOLOR, ("SelectColor: PEN WIDTH Change from %ld.%ldmm to %ld.%ldmm", (DWORD)pPDev->PenWidth.Integer, (DWORD)pPDev->PenWidth.Decimal, (DWORD)PenWidth.Integer, (DWORD)PenWidth.Decimal)); // // Update the pen width cache // pPDev->PenWidth = PenWidth; } else { PLOTDBG(DBG_SELECTCOLOR, ("SelectColor: PEN WIDTH is SAME = %ld.%ld", PenWidth.Integer, PenWidth.Decimal)); } }