Ejemplo n.º 1
0
void RenderMessagePicture(CDrawPort *pdp)
{
  CCompMessage &cm = _acmMessages[_iActiveMessage];
  // try to
  try {
    // load image
    _toPicture.SetData_t(cm.cm_fnmPicture);
    ((CTextureData*)_toPicture.GetData())->Force(TEX_CONSTANT);
  // if failed
  } catch(char *strError) {
    // report error
    CPrintF("Cannot load '%s':\n%s\n", (CTString&)cm.cm_fnmPicture, strError);
    // do nothing
    return;
  }

  // get image and box sizes
  PIX pixImgSizeI = _toPicture.GetWidth();
  PIX pixImgSizeJ = _toPicture.GetHeight();
  PIXaabbox2D boxPic(PIX2D(_pixMarginI, _pixMarginJ),
      PIX2D(_boxMsgImage.Size()(1)-_pixMarginI, _boxMsgImage.Size()(2)-_pixMarginJ));
  PIX pixBoxSizeI = boxPic.Size()(1);
  PIX pixBoxSizeJ = boxPic.Size()(2);
  PIX pixCenterI = _boxMsgImage.Size()(1)/2;
  PIX pixCenterJ = _boxMsgImage.Size()(2)/2;
  // find image stretch to fit in box
  FLOAT fStretch = Min(FLOAT(pixBoxSizeI)/pixImgSizeI, FLOAT(pixBoxSizeJ)/pixImgSizeJ);
  // draw the image
  pdp->PutTexture(&_toPicture,
    PIXaabbox2D(
      PIX2D(pixCenterI-pixImgSizeI*fStretch/2, pixCenterJ-pixImgSizeJ*fStretch/2),
      PIX2D(pixCenterI+pixImgSizeI*fStretch/2, pixCenterJ+pixImgSizeJ*fStretch/2)));
}
Ejemplo n.º 2
0
// Set current texture index
void shaSetTexture(INDEX iTextureIndex)
{
  if(_paTextures==NULL || iTextureIndex<0 || iTextureIndex>=_ctTextures ||  _paTextures[iTextureIndex] == NULL) {
    gfxDisableTexture();
    return;
  }
  ASSERT(iTextureIndex<_ctTextures);

  CTextureObject *pto = _paTextures[iTextureIndex];
  ASSERT(pto!=NULL);

  CTextureData *pTextureData = (CTextureData*)pto->GetData();
  const INDEX iFrameNo = pto->GetFrame();
  pTextureData->SetAsCurrent(iFrameNo);
}
Ejemplo n.º 3
0
static void PaintScreen()
{
  if(_pdpDrawPort==NULL) {
    return;
  }
  _pdpDrawPort->SetAsCurrent();
  // clear browsing window
  _pdpDrawPort->FillZBuffer( ZBUF_BACK);
  _pdpDrawPort->Fill( C_GRAY | CT_OPAQUE);

  if(_pfdCurrentFont!=NULL && _pfdCurrentFont->fd_ptdTextureData!=NULL && _ptdGrid!=NULL) {
    PIX pixWidth = _pfdCurrentFont->fd_ptdTextureData->GetPixWidth();
    PIX pixHeight = _pfdCurrentFont->fd_ptdTextureData->GetPixHeight();

    PIXaabbox2D rectPict;
    rectPict = PIXaabbox2D( PIX2D(0, 0), PIX2D(pixWidth, pixHeight));
    if(_bShowTexture) {
      // Show texture
      _toPreview.SetData(_pfdCurrentFont->fd_ptdTextureData);
      _pdpDrawPort->PutTexture(&_toPreview,rectPict);
      // if grid must be shown
      if(_bShowGrid) {
        // Show character grid
        _toPreview.SetData(_ptdGrid);
        _pdpDrawPort->PutTexture(&_toPreview,rectPict);
      }
      // Show texture grid
      _pdpDrawPort->DrawLine(0,0,pixWidth,0,0xFFFF00FF);
      _pdpDrawPort->DrawLine(0,0,0,pixHeight,0xFFFF00FF);
      _pdpDrawPort->DrawLine(0,pixHeight,pixWidth,pixHeight,0xFFFF00FF);
      _pdpDrawPort->DrawLine(pixWidth,0,pixWidth,pixHeight,0xFFFF00FF);
      _toPreview.SetData(NULL);
    } else {
      char strSampleText[2048];
      GetDlgItemText(_hWnd,IEC_SAMPLE_TEXT,strSampleText,2047);
      _pdpDrawPort->SetFont( _pfdCurrentFont);
      _pdpDrawPort->PutText( strSampleText, 0, 0, 0xFFFFFFFF);
    }
  }

  if(_pvpViewPort!=NULL) {
    // swap it
    _pvpViewPort->SwapBuffers();
  }
}
Ejemplo n.º 4
0
void CMGTrigger::Render(CDrawPort *pdp)
{
  SetFontMedium(pdp);

  PIXaabbox2D box = FloatBoxToPixBox(pdp, mg_boxOnScreen);
  PIX pixIL = box.Min()(1) + box.Size()(1)*0.45f;
  PIX pixIR = box.Min()(1) + box.Size()(1)*0.55f;
  PIX pixJ = box.Min()(2);

  COLOR col = GetCurrentColor();
  if (!mg_bVisual || mg_strValue == "") {
    CTString strValue = mg_strValue;
    if (mg_bVisual) {
      strValue = TRANS("none");
    }

    if (mg_iCenterI == -1) {
      pdp->PutText(mg_strLabel, box.Min()(1), pixJ, col);
      pdp->PutTextR(strValue, box.Max()(1), pixJ, col);
    } else {
      pdp->PutTextR(mg_strLabel, pixIL, pixJ, col);
      pdp->PutText(strValue, pixIR, pixJ, col);
    }
  } else {
    CTString strLabel = mg_strLabel + ": ";
    pdp->PutText(strLabel, box.Min()(1), pixJ, col);
    CTextureObject to;
    try {
      to.SetData_t(mg_strValue);
      CTextureData *ptd = (CTextureData *)to.GetData();
      PIX pixSize = box.Size()(2);
      PIX pixCX = box.Max()(1) - pixSize / 2;
      PIX pixCY = box.Center()(2);
      pdp->PutTexture(&to, PIXaabbox2D(
        PIX2D(pixCX - pixSize / 2, pixCY - pixSize / 2),
        PIX2D(pixCX - pixSize / 2 + pixSize, pixCY - pixSize / 2 + pixSize)), C_WHITE | 255);
    } catch (char *strError) {
      CPrintF("%s\n", strError);
    }
    to.SetData(NULL);
  }
}
Ejemplo n.º 5
0
extern void InternalShader_Mask(void)
{
  // need arrays and texture
  INDEX ctIdx = shaGetIndexCount();
  INDEX ctVtx = shaGetVertexCount();
  if( ctIdx==0 || ctVtx==0) return;
  INDEX *pidx = shaGetIndexArray();
  GFXVertex4  *pvtx = shaGetVertexArray();
  GFXTexCoord *ptex = shaGetUVMap(0);
  CTextureObject *pto = shaGetTexture(0);
  ASSERT( (ctIdx%3) == 0); // must have triangles?

  // prepare texture
  ULONG *pulTexFrame = NULL;
  PIX pixMipWidth=0, pixMipHeight=0;

  if( pto!=NULL && ptex!=NULL) {
    CTextureData *ptd = (CTextureData*)pto->GetData();
    if( ptd!=NULL && ptd->td_ptegEffect==NULL) {
      // fetch some texture params
      pulTexFrame  = ptd->td_pulFrames + (pto->GetFrame()*ptd->td_slFrameSize)/BYTES_PER_TEXEL;
      pixMipWidth  = ptd->GetPixWidth();
      pixMipHeight = ptd->GetPixHeight();
      // reload texture and keep in memory
      ptd->Force(TEX_STATIC);
    }
  }
  // initialize texture for usage thru render triangle routine
  SetTriangleTexture( pulTexFrame, pixMipWidth, pixMipHeight);

  // prepare projection
  const BOOL bPerspective = _aprProjection.IsPerspective();
  CPerspectiveProjection3D &prPerspective = (CPerspectiveProjection3D &)*_aprProjection;
  CParallelProjection3D &prParallel = (CParallelProjection3D &)*_aprProjection;
  FLOAT fCenterI, fCenterJ, fRatioI, fRatioJ, fStepI, fStepJ, fZoomI, fZoomJ; 
  FLOAT fFrontClipDistance, fBackClipDistance, f1oFrontClipDistance, f1oBackClipDistance, fDepthBufferFactor;

  if( bPerspective) {
    fCenterI = prPerspective.pr_ScreenCenter(1);
    fCenterJ = prPerspective.pr_ScreenCenter(2);
    fRatioI  = prPerspective.ppr_PerspectiveRatios(1);
    fRatioJ  = prPerspective.ppr_PerspectiveRatios(2);
    fFrontClipDistance   = -prPerspective.pr_NearClipDistance;
    fBackClipDistance    = -prPerspective.pr_FarClipDistance;
    f1oFrontClipDistance = -1.0f / prPerspective.pr_NearClipDistance;
    f1oBackClipDistance  = -1.0f / prPerspective.pr_FarClipDistance;
    fDepthBufferFactor   = prPerspective.pr_fDepthBufferFactor;
  } else {
    fCenterI = prParallel.pr_ScreenCenter(1);
    fCenterJ = prParallel.pr_ScreenCenter(2);
    fStepI   = prParallel.pr_vStepFactors(1);
    fStepJ   = prParallel.pr_vStepFactors(2);
    fZoomI   = prParallel.pr_vZoomFactors(1);
    fZoomJ   = prParallel.pr_vZoomFactors(2);
    fFrontClipDistance   = -prPerspective.pr_NearClipDistance;
    fBackClipDistance    = -prPerspective.pr_FarClipDistance;
    f1oFrontClipDistance = 1.0f;
    f1oBackClipDistance  = 1.0f;
    fDepthBufferFactor   = 1.0f;
  }

  // copy view space vertices, project 'em to screen space and mark clipping
  CStaticStackArray<TransformedVertexData> atvd;
  INDEX iVtx=0;
  for(; iVtx<ctVtx; iVtx++)
  {
    // copy viewspace and texture coords
    TransformedVertexData &tvd = atvd.Push();
    tvd.tvd_fX = pvtx[iVtx].x;
    tvd.tvd_fY = pvtx[iVtx].y;
    tvd.tvd_fZ = pvtx[iVtx].z;
    tvd.tvd_bClipped = FALSE;   // initially, vertex is not clipped

    // prepare screen coordinates
    if( bPerspective) {
      const FLOAT f1oZ = 1.0f / tvd.tvd_fZ;
      tvd.tvd_pv2.pv2_fI   = fCenterI + tvd.tvd_fX*fRatioI *f1oZ;
      tvd.tvd_pv2.pv2_fJ   = fCenterJ - tvd.tvd_fY*fRatioJ *f1oZ;
      tvd.tvd_pv2.pv2_f1oK = fDepthBufferFactor*f1oZ;
    } else {
      tvd.tvd_pv2.pv2_fI   = fCenterI + tvd.tvd_fX*fZoomI + tvd.tvd_fZ*fStepI;
      tvd.tvd_pv2.pv2_fJ   = fCenterJ - tvd.tvd_fY*fZoomJ - tvd.tvd_fZ*fStepJ;
      tvd.tvd_pv2.pv2_f1oK = 1;
    }

    // adjust texture coords (if any!)
    if( ptex!=NULL) {
      tvd.tvd_fU = ptex[iVtx].s;
      tvd.tvd_fV = ptex[iVtx].t;
      tvd.tvd_pv2.pv2_fUoK = tvd.tvd_fU * tvd.tvd_pv2.pv2_f1oK *pixMipWidth;
      tvd.tvd_pv2.pv2_fVoK = tvd.tvd_fV * tvd.tvd_pv2.pv2_f1oK *pixMipHeight;
    } else tvd.tvd_fU = tvd.tvd_fV = 0;

    // check clipping against horizontal screen boundaries and near clip plane
    if( tvd.tvd_pv2.pv2_fI<0 || tvd.tvd_pv2.pv2_fI>=_slMaskWidth
     || tvd.tvd_fZ>fFrontClipDistance || (fBackClipDistance<0 && tvd.tvd_fZ<fBackClipDistance)) {
      tvd.tvd_bClipped = TRUE;
    }
  }

  // lets clip and render - triangle by triangle
  for( INDEX iIdx=0; iIdx<ctIdx; iIdx+=3)
  {
    // get transformed triangle
    TransformedVertexData tvd[3];
    iVtx = pidx[iIdx+0];  tvd[0] = atvd[iVtx];
    iVtx = pidx[iIdx+1];  tvd[1] = atvd[iVtx];
    iVtx = pidx[iIdx+2];  tvd[2] = atvd[iVtx];

    // clipped?
    if( tvd[0].tvd_bClipped || tvd[1].tvd_bClipped || tvd[2].tvd_bClipped)
    {
      // create array of vertices for polygon clipped to near clip plane
      ctvxDst=0;
      INDEX ivx0=2;
      INDEX ivx1=0;
      {for( INDEX ivx=0; ivx<3; ivx++)
      {
        TransformedVertexData &tvd0 = tvd[ivx0];
        TransformedVertexData &tvd1 = tvd[ivx1];
        FLOAT fd0 = fFrontClipDistance-tvd0.tvd_fZ;
        FLOAT fd1 = fFrontClipDistance-tvd1.tvd_fZ;
        // if first vertex is in
        if( fd0>=0) {
          // add it to clip array
          ptvdDst[ctvxDst] = tvd0;
          ctvxDst++;
          // if second vertex is out
          if( fd1<0) {
            // add clipped vertex at exit
            TransformedVertexData &tvdClipped = ptvdDst[ctvxDst];
            ctvxDst++;
            FLOAT fF = fd1/(fd1-fd0);
            tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF;
            tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF;
            tvdClipped.tvd_fZ = fFrontClipDistance;
            tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance;
            FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF;
            FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF;
            tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK;
            tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK;
          }
        // if first vertex is out (don't add it into clip array)
        } else {
          // if second vertex is in
          if( fd1>=0) {
            // add clipped vertex at entry
            TransformedVertexData &tvdClipped = ptvdDst[ctvxDst];
            ctvxDst++;
            FLOAT fF = fd0/(fd0-fd1);
            tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF;
            tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF;
            tvdClipped.tvd_fZ = fFrontClipDistance;
            tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance;
            FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF;
            FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF;
            tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK;
            tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK;
          }
        }
        // proceed to next vertex in list (i.e. new pair of vertices)
        ivx0=ivx1;
        ivx1++;
      }}
      // swap buffers
      Swap( ptvdSrc, ptvdDst);
      Swap( ctvxSrc, ctvxDst);

      // if clipping to far clip plane is on
      if( fBackClipDistance<0) {
        ctvxDst=0;
        INDEX ivx0=ctvxSrc-1;
        INDEX ivx1=0;
        {for( INDEX ivx=0; ivx<ctvxSrc; ivx++)
        {
          TransformedVertexData &tvd0 = ptvdSrc[ivx0];
          TransformedVertexData &tvd1 = ptvdSrc[ivx1];
          FLOAT fd0 = tvd0.tvd_fZ-fBackClipDistance;
          FLOAT fd1 = tvd1.tvd_fZ-fBackClipDistance;
          // if first vertex is in
          if( fd0>=0) {
            // add it to clip array
            ptvdDst[ctvxDst] = tvd0;
            ctvxDst++;
            // if second vertex is out
            if( fd1<0) {
              // add clipped vertex at exit
              TransformedVertexData &tvdClipped = ptvdDst[ctvxDst];
              ctvxDst++;
              FLOAT fF = fd1/(fd1-fd0);
              tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF;
              tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF;
              tvdClipped.tvd_fZ = fBackClipDistance;
              tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance;
              FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF;
              FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF;
              tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK;
              tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK;
            }
          // if first vertex is out (don't add it into clip array)
          } else {
            // if second vertex is in
            if( fd1>=0) {
              // add clipped vertex at entry
              TransformedVertexData &tvdClipped = ptvdDst[ctvxDst];
              ctvxDst++;
              FLOAT fF = fd0/(fd0-fd1);
              tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF;
              tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF;
              tvdClipped.tvd_fZ = fBackClipDistance;
              tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance;
              FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF;
              FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF;
              tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK;
              tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK;
            }
          }
          // proceed to next vertex in list (i.e. new pair of vertices)
          ivx0=ivx1;
          ivx1++;
        }}
        // swap buffers
        Swap( ptvdSrc, ptvdDst);
        Swap( ctvxSrc, ctvxDst);
      }

      // for each vertex
      {for( INDEX ivx=0; ivx<ctvxSrc; ivx++)
      {
        // calculate projection
        TransformedVertexData &tvd = ptvdSrc[ivx];
        if( bPerspective) {
          const FLOAT f1oZ = 1.0f / tvd.tvd_fZ;
          tvd.tvd_pv2.pv2_fI = fCenterI + tvd.tvd_fX*fRatioI *f1oZ;
          tvd.tvd_pv2.pv2_fJ = fCenterJ - tvd.tvd_fY*fRatioJ *f1oZ;
        } else {
          tvd.tvd_pv2.pv2_fI = fCenterI + tvd.tvd_fX*fZoomI + tvd.tvd_fZ*fStepI;
          tvd.tvd_pv2.pv2_fJ = fCenterJ - tvd.tvd_fY*fZoomJ - tvd.tvd_fZ*fStepJ;
        }
      }}

      // clip polygon against left edge
      ctvxDst=0;
      ivx0=ctvxSrc-1;
      ivx1=0;
      {for( INDEX ivx=0; ivx<ctvxSrc; ivx++)
      {
        PolyVertex2D &pv20 = ptvdSrc[ivx0].tvd_pv2;
        PolyVertex2D &pv21 = ptvdSrc[ivx1].tvd_pv2;
        FLOAT fd0 = pv20.pv2_fI-0;
        FLOAT fd1 = pv21.pv2_fI-0;
        // if first vertex is in
        if( fd0>=0) {
          // add it to clip array
          ptvdDst[ctvxDst].tvd_pv2 = pv20;
          ctvxDst++;
          // if second vertex is out
          if( fd1<0) {
            PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2;
            ctvxDst++;
            FLOAT fF = fd1/(fd1-fd0);
            pv2Clipped.pv2_fI = 0;
            pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ) *fF;
            pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF;
            pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF;
            pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF;
          }
        // if first vertex is out (don't add it into clip array)
        } else {
          // if second vertex is in
          if( fd1>=0) {
            // add clipped vertex at entry
            PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2;
            ctvxDst++;
            FLOAT fF = fd0/(fd0-fd1);
            pv2Clipped.pv2_fI = 0;
            pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF;
            pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF;
            pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF;
            pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF;
          }
        }
        // proceed to next vertex in list (i.e. new pair of vertices)
        ivx0=ivx1;
        ivx1++;
      }}
      // swap buffers
      Swap( ptvdSrc, ptvdDst);
      Swap( ctvxSrc, ctvxDst);

      // clip polygon against right edge
      ctvxDst=0;
      ivx0=ctvxSrc-1;
      ivx1=0;
      {for( INDEX ivx=0; ivx<ctvxSrc; ivx++)
      {
        PolyVertex2D &pv20 = ptvdSrc[ivx0].tvd_pv2;
        PolyVertex2D &pv21 = ptvdSrc[ivx1].tvd_pv2;
        FLOAT fd0 = _slMaskWidth - pv20.pv2_fI;
        FLOAT fd1 = _slMaskWidth - pv21.pv2_fI;
        // if first vertex is in
        if( fd0>=0) {
          // add it to clip array
          ptvdDst[ctvxDst].tvd_pv2 = pv20;
          ctvxDst++;
          // if second vertex is out
          if( fd1<0) {
            PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2;
            ctvxDst++;
            FLOAT fF = fd1/(fd1-fd0);
            pv2Clipped.pv2_fI = _slMaskWidth;
            pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ)*fF;
            pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF;
            pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF;
            pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF;
          }
        // if first vertex is out (don't add it into clip array)
        } else {
          // if second vertex is in
          if( fd1>=0) {
            // add clipped vertex at entry
            PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2;
            ctvxDst++;
            FLOAT fF = fd0/(fd0-fd1);
            pv2Clipped.pv2_fI = _slMaskWidth;
            pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF;
            pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF;
            pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF;
            pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF;
          }
        }
        // proceed to next vertex in list (i.e. new pair of vertices)
        ivx0=ivx1;
        ivx1++;
      }}
      // swap buffers
      Swap( ptvdSrc, ptvdDst);
      Swap( ctvxSrc, ctvxDst);

      // draw all triangles in clipped polygon as a triangle fan, with clipping
      PolyVertex2D &pvx0 = ptvdSrc[0].tvd_pv2;
      {for( INDEX ivx=1; ivx<ctvxSrc-1; ivx++) {
        PolyVertex2D &pvx1 = ptvdSrc[ivx+0].tvd_pv2;
        PolyVertex2D &pvx2 = ptvdSrc[ivx+1].tvd_pv2;
        DrawTriangle_Mask( _pubMask, _slMaskWidth, _slMaskHeight, &pvx0, &pvx1, &pvx2, TRUE);
      }}
    }

    // not clipped - just draw!
    else {
      DrawTriangle_Mask( _pubMask, _slMaskWidth, _slMaskHeight,
                         &tvd[0].tvd_pv2, &tvd[1].tvd_pv2, &tvd[2].tvd_pv2, TRUE);
    }
  }
}