home *** CD-ROM | disk | FTP | other *** search
- //===============================================================
- // vWinDC - Windows Base DC
- //
- // Copyright (C) 1995,1996,1997,1998 Bruce E. Wampler
- //
- // This file is part of the V C++ GUI Framework, and is covered
- // under the terms of the GNU Library General Public License,
- // Version 2. This library has NO WARRANTY. See the source file
- // vapp.cxx for more complete information about license terms.
- //===============================================================
-
- #include <v/vos2.h> // for OS/2 stuff
- extern "C"
- {
- #include <math.h>
- }
- #include <v/vwindc.h>
- #include <v/vmemdc.h>
- #include <v/vapp.h> // need access to the app
- #include <v/vcanvas.h> // our own canvas widget
- #include <v/vicon.h>
-
- //-----------------------------------------------------------------------
- //================>>> vWinDC::vWinDC <<<========================
- vWinDC::vWinDC()
- {
- SysDebug(Constructor,"vWinDC::vWinDC() constructor\n")
-
- _font = theApp->GetDefaultFont(); // Use the default fixed font by default!
- _hdc = 0;
-
- // set some defaults
- _canvasBG = SETRGB(255,255,255); // white
- _hpen = _pen.GetHPEN(); // Get the default pen
- _hbrush = _brush.GetHBRUSH(); // Get the default brush
- // _hpen = 0; // no pen for now
- // _hbrush = 0; // no brush for now
- _isPrinterDC = 0; // Assume not printer
- }
-
- //================>>> vWinDC::~vWinDC <<<========================
- vWinDC::~vWinDC()
- {
- SysDebug(Destructor,"vWinDC::~vWinDC() destructor\n")
- }
- //================>>> vWinDC::CopyFromMemoryDC <<<=======================
- void vWinDC::CopyFromMemoryDC(vMemoryDC* vmemdc, int destX, int destY,
- int srcX, int srcY, int srcW, int srcH) // V:1.13
- {
- BeginPaint();
- int ch = vmemdc->_physHeight;
- int cw = vmemdc->_physWidth;
- int cx = 0;
- int cy = 0;
-
- if (srcX > 0) // Fixed: 10/11/96
- cx = srcX;
- if (srcY > 0)
- cy = srcY;
- if (srcW > 0)
- cw = srcW;
- if (srcH > 0)
- ch = srcH;
-
- if ((cw + cx) > vmemdc->_physWidth && _physWidth > 0) // only copy what will fi
- cw = vmemdc->_physWidth - cx;
- if ((ch + cy) > vmemdc->_physHeight && _physHeight > 0)
- ch = vmemdc->_physHeight - cy;
-
- if ((cw + destX) > _physWidth && _physWidth > 0)
- cw = _physWidth - destX;
- if ((ch + destY) > _physHeight && _physHeight > 0)
- ch = _physHeight - destY;
-
-
- if (cw > _physWidth && _physWidth > 0) // only copy what will fit
- cw = _physWidth;
- if (ch > _physHeight && _physHeight > 0)
- ch = _physHeight;
-
- POINTL cPoints[3] = {destX, destY, // lower left targ
- destX+cw, destY+ch, // upper right targ
- cx, cy }; // lower left src
-
- HPS memDC = vmemdc->_hdc;
- SysDebug1(Constructor,"vWinDC::CopyFromMemoryDC() memDC = %d\n", memDC)
-
- #define BITBLT
- #ifdef BITBLT
- // we need to convert the target coords which are in World Space
- // to Device Space since GpiBitBlt expects device coords
- // GpiConvert(_hdc, CVTC_WORLD, CVTC_DEVICE, 1, &cPoints[0]);
- // GpiConvert(_hdc, CVTC_WORLD, CVTC_DEVICE, 1, &cPoints[1]);
- MapToOS2(&cPoints[0]);
- MapToOS2(&cPoints[1]);
- GpiBitBlt(_hdc, memDC, 3, cPoints, ROP_SRCCOPY, BBO_IGNORE);
- #else
- // register COLORREF color, cout;
- register ULONG color, cout;
- POINTL cPoint;
- LINEBUNDLE Pen;
- for (int row = 0 ; row < ch ; ++row)
- for (int col = 0 ; col < cw ; ++col)
- {
- cPoint.x = row;
- cPoint.y = col;
- MapToOS2(&cPoint);
-
- color = GpiQueryPel (memDC, cPoint);
- cout = GpiQueryAttrs (_hdc, PRIM_LINE, LBB_COLOR, &Pen);
- Pen.lColor = color;
- GpiSetAttrs (_hdc, PRIM_LINE, LBB_COLOR, 0, &Pen);
- GpiSetPel (_hdc, cPoint);
- Pen.lColor = cout;
- GpiSetAttrs (_hdc, PRIM_LINE, LBB_COLOR, 0, &Pen);
- }
- #endif
- EndPaint();
- }
-
- //====================>>> vWinDC::DrawIcon <<<==========================
- void vWinDC::DrawIcon(int x, int y, VCONST vIcon& icon)
- {
- BeginPaint();
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
- // Now, draw the icon
- HBITMAP hbm = icon.GetIconHBM(_hdc); // get the bitmap
- SysDebug1(Build,"vWinDC::DrawIcon() hbm=%u\n", hbm)
-
- // Now BitBlt the icon BMP into the drawing canvas, leaving
- // background untouched, and the pen color to draw 1 bits
- // (Note: Target is in World Coords, and Source is in Device Coords)
- POINTL cPoints[4] = {xx, yy, // lower left targ
- xx+icon.width-1, yy+icon.height-1, // upper right targ
- 0, 0, // lower left src
- icon.width, icon.height}; // upper right src
-
- // Map to OS/2 coord system before calling
- // (only need to map World Coords)
- MapToOS2(&cPoints[0]);
- MapToOS2(&cPoints[1]);
-
- // set ownership of bitmap to canvas
- HBITMAP hbmr = GpiSetBitmap(_hdc, hbm);
- // now reset the original bitmap if there was one
- GpiSetBitmap(_hdc, hbmr);
-
- if (icon.iType == Transparent)
- {
- // for transparent icons, we set the canvas background
- // color to the icon transparent color and then set
- // the background mix mode to BM_SRCTRANSPARENT, OS/2
- // takes care of the rest (compare with the windoze code! :-) )
- IMAGEBUNDLE himage;
- himage.lColor = _pen.GetColor().pixel(); // use pen color
- himage.lBackColor = icon.GetTransparentColor();
- GpiSetAttrs(_hdc, PRIM_IMAGE, IBB_BACK_COLOR | IBB_COLOR, 0, &himage);
- GpiSetBackMix(_hdc,BM_SRCTRANSPARENT);
-
- // blit the image to the canvas
- GpiWCBitBlt(_hdc, hbm, 4, cPoints, ROP_SRCCOPY, BBO_IGNORE);
-
- // restore defaults
- himage.lColor = _pen.GetColor().pixel(); // use pen color
- himage.lBackColor = _canvasBG; // use background color
- GpiSetAttrs(_hdc, PRIM_IMAGE, IBB_BACK_COLOR | IBB_COLOR, 0, &himage);
- GpiSetBackMix(_hdc,BM_DEFAULT);
- }
- else
- {
- // for monochrome bitmaps, we can control the
- // target colors using the image bundle
- IMAGEBUNDLE himage;
- himage.lColor = _pen.GetColor().pixel(); // use pen color
- himage.lBackColor = _canvasBG; // use background color
- GpiSetAttrs(_hdc, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &himage);
-
- // blit the image to the canvas
- GpiWCBitBlt(_hdc, hbm, 4, cPoints, ROP_SRCCOPY, BBO_IGNORE);
- }
- EndPaint();
- }
-
- //#define DRAWARC
- #ifdef DRAWARC
- //====================>>> vWinDC::DrawArc <<<==========================
- // This function is experimental
- // (xx1, yy1) start of arc
- // (xx2, yy2) end of arc
- // (xxc, yyc) centre of arc
-
- void vWinDC::DrawArc(int xx1, int yy1, int xx2, int yy2,
- int xxc, int yyc)
- {
- double dx = xx1 - xxc;
- double dy = yy1 - yyc;
- double radius = sqrt(dx * dx + dy * dy);
- const double PIx2 = 6.283185;
- double angle1, angle2; // angles of points wrt center
-
- BeginPaint();
- if (xx1 == xx2 && yy1 == yy2)
- {
- angle1 = 0.0;
- angle2 = 360.0;
- }
- else if (radius == 0.0)
- angle1 = angle2 = 0.0;
- else
- {
- if (xx1 - xxc == 0)
- {
- if (yy1 - yyc < 0)
- angle1 = 90.0;
- else
- angle1 = -90.0;
- }
- else
- angle1 = -atan2 ((double) (yy1 - yyc), (double) (xx1 - xxc)) * 360.0 / PIx2;
-
- if (xx2 - xxc == 0)
- {
- if (yy2 - yyc < 0)
- angle2 = 90.0;
- else
- angle2 = -90.0;
- }
- else
- angle2 = -atan2 ((double) (yy2 - yyc), (double) (xx2 - xxc)) * 360.0 / PIx2;
- }
-
- POINTL posc = {xxc, yyc};
- POINTL pos1 = {xx1, yy1};
- MapToOS2(&posc);
- MapToOS2(&pos1);
-
- ARCPARAMS arc;
- double ri, Scale;
-
- ri = floor(radius); // radius always >= 0
- Scale = radius/ri;
- arc.lP = (LONG) ri;
- arc.lQ = (LONG) ri;
- arc.lR = 0L;
- arc.lS = 0L;
- GpiSetArcParams(_hdc, &arc);
-
- // compute start and sweep angles (must be >= 0)
- double start = angle1;
- double sweep = fabs(angle2 - angle1);
- while (start < 0)
- start += 360;
- // set pen attributes and draw arc
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH, 0, _hpen);
-
- GpiMove(_hdc, &pos1);
- GpiPartialArc(_hdc, &posc, DBLTOFX(Scale), DBLTOFX(start), DBLTOFX(sweep));
- EndPaint();
- }
- #endif
-
- //====================>>> vWinDC::DrawEllipse <<<==========================
- // (x,y) lower left corner ellipse bounding box
- void vWinDC::DrawEllipse(int x, int y, int width, int height)
- {
- if (height == 0 || width == 0)
- return;
-
- BeginPaint();
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- int x1 = Scale(x+_tx);
- int y1 = Scale(y+_ty);
- int width1 = Scale(width-1);
- int height1 = Scale(height-1);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- _hbrush = _brush.GetHBRUSH();
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
-
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- // set arc params at 2x scale
- ARCPARAMS arc;
- arc.lP = width1;
- arc.lQ = height1;
- arc.lR = 0;
- arc.lS = 0;
- GpiSetArcParams(_hdc , &arc);
-
- // compute center of ellipse
- POINTL posc = {x1+(width1/2), y1+(height1/2)};
- MapToOS2(&posc);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- GpiSetCurrentPosition (_hdc, &posc);
- GpiFullArc (_hdc, DRO_FILL, MAKEFIXED(0,0x8000)); // scale by 1/2
- GpiBeginPath(_hdc, 1L);
- GpiFullArc (_hdc, DRO_OUTLINE, MAKEFIXED(0,0x8000)); // scale by 1/2
- GpiEndPath(_hdc);
-
- AREABUNDLE hlinebrush;
- hlinebrush.lColor = _hpen->lColor;
- hlinebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &hlinebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
- }
- else
- {
- GpiSetCurrentPosition (_hdc, &posc); // move to start point
- GpiFullArc (_hdc, DRO_OUTLINEFILL, MAKEFIXED(0,0x8000)); // scale by 1/2
- }
- EndPaint();
- }
-
- //====================>>> vWinDC::DrawLine <<<==========================
- void vWinDC::DrawLine(int x, int y, int xend, int yend)
- {
- BeginPaint();
- // Draw a line from x,y to xend,yend
- // This method has the typical sequence of code for drawing. All other
- // drawing methods are modeled using this approach
- // First, do the required scaling
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
- int xe = Scale(xend+_tx);
- int ye = Scale(yend+_ty);
-
- // OS/2 can define a presentation space when the window
- // is created, and we can use it until the window is
- // destroyed. This saves us from needing to constantly
- // get and destroy the DC (unlike the windows code) while the user program is
- // drawing stuff interactively (usually in response to mouse input).
- // For Redraw, the canvas redraw event will issue a WinBeginPaint
- // and WinEndPaint, which will bracket all drawing. We feed
- // WinBeginPaint our presentation space for the window so it
- // doesn't create a separate cached micro-PS like it normally would do.
- // This allows us to retain any attributes of the PS for the
- // life of the window.
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- // Shapes will do a similar sequence for brushes as well
- // Now the code to actually do the drawing
- POINTL poss = {xx, yy}; // start point
- POINTL pose = {xe, ye}; // end point
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- GpiBeginPath(_hdc, 1L);
- GpiSetCurrentPosition (_hdc, &poss);
- GpiLine (_hdc , &pose);
- GpiEndPath(_hdc);
-
- // it turns out that to get a line of variable thickness it must be
- // stroked. However, such lines do not support linetypes other
- // than type solid. So to get dots and dashed lines we need to
- // use outlines, but then the width is ignored (dohh!).
- // This behavior is also true for windows though,
- // so I'm not going to worry about it. The major pain though is
- // that the stroked line color is set to the area fill color, which
- // is why I have to do the nonsense with the hlinebrush.
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // for Geometric lines, the fill color is used (what a debacle!)
- AREABUNDLE hlinebrush;
- hlinebrush.lColor = _hpen->lColor; // for stroked lines
- hlinebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &hlinebrush);
- GpiStrokePath(_hdc, 1L, 0L); // solid lines can be stroked
- }
- else
- GpiOutlinePath(_hdc, 1L, 0L); // other lines need to be outlined
-
- EndPaint();
- }
-
- //====================>>> vWinDC::DrawLines <<<==========================
- void vWinDC::DrawLines(vLine* lineList, int count)
- {
- if (count < 1 || lineList == 0)
- return;
-
- BeginPaint();
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- vLine* lp = lineList ;
- POINTL poss; // start point
- POINTL pose; // end point
-
- GpiBeginPath(_hdc, 1L);
- for (int num = 0 ; num < count ; ++lp, ++num)
- {
- poss.x = Scale(lp->x+_tx);
- poss.y = Scale(lp->y+_ty);
- pose.x = Scale(lp->xend+_tx);
- pose.y = Scale(lp->yend+_ty);
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- GpiSetCurrentPosition (_hdc, &poss);
- GpiLine (_hdc , &pose);
- }
- GpiEndPath(_hdc);
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // for Geometric lines, the fill color is used (what a debacle!)
- AREABUNDLE linebrush;
- linebrush.lColor = _hpen->lColor; // for stroked lines
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // solid lines can be stroked
- }
- else
- GpiOutlinePath(_hdc, 1L, 0L); // other lines need to be outlined
-
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawColorPoints <<<======================
- void vWinDC::DrawColorPoints(int x, int y, int nPoints, vColor* pointList)
- {
- // Draw a bunch of color points.
- if (nPoints < 1 || pointList == 0)
- return;
-
- BeginPaint();
-
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
- if (yy < 0)
- return; // row not displayed
-
- #define BITBLT
- #ifdef BITBLT
- // performance was bad with GpiSetPel so do this with
- // a line bitmap blitted to the canvas
-
- // bitmap data structures
- PVBYTE bmbits;
- PBITMAPINFO2 pbmi;
-
- // build a memory PS compatible with calling PS
- HDC DevCxtComp = GpiQueryDevice(_hdc);
- HDC DevCxtMem = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, DevCxtComp);
- SIZEL size = {nPoints, 1};
- HPS hdcMem = GpiCreatePS (theApp->AppHab(), DevCxtMem, &size,
- PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
-
- // set the PS to RGB mode
- GpiCreateLogColorTable(hdcMem, 0L, LCOLF_RGB, 0L, 0L, NULL);
-
- // First, create a blank bitmap compatible with the
- // current context that is size of bitmap.
- BITMAPINFOHEADER2 bmih;
- memset(&bmih, 0, sizeof(BITMAPINFOHEADER2));
- bmih.cbFix = sizeof(BITMAPINFOHEADER2);
- bmih.cx = nPoints;
- bmih.cy = 1;
- bmih.ulColorEncoding = BCE_RGB;
- bmih.cPlanes = 1; // always 1 for OS/2
- bmih.cBitCount = 24; // bits of color per pixel
-
- HBITMAP hbm = GpiCreateBitmap(hdcMem, &bmih, 0L, NULL, NULL);
- // now we need to load the bitmap with data by associating
- // with a memory PS and setting each pel
- GpiSetBitmap(hdcMem, hbm);
-
- // We first need to create the bitmapinfo structure
- // (a color table is not needed for 24 bit bitmaps)
- // allocate space for header
- pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)];
-
- // copy the header to the bitmap info structure
- memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
- pbmi->cclrUsed = 0 ; // no color table needed
- pbmi->cbImage = nPoints*3; // image size (bytes)
-
- // Now need to copy pixel data over from pointList
- int rowwords = ((nPoints*3)+3) / 4; // number of words (for OS/2 bitmap data)
- bmbits = new VBYTE[rowwords*4]; // allocate space
- PVBYTE to = bmbits; // set to first pixel
-
- int col;
- for (col = 0 ; col < nPoints ; ++col) // do each V pixel per row
- {
- // R G B
- *to++ = pointList[col].r();
- *to++ = pointList[col].g();
- *to++ = pointList[col].b();
- }
-
- // Finished a row, need to pad to a word boundary
- while ( (col*3)<(4*rowwords) )
- {
- *to++ = 0x00; // pad with 0's
- col++;
- }
-
- // Now, create the bitmap
- GpiSetBitmapBits(hdcMem, 0L, pbmi->cy, (PBYTE) bmbits, pbmi);
- // free up resources and we are done
- delete [] bmbits;
- delete [] pbmi;
-
- GpiSetBitmap (hdcMem, NULLHANDLE);
- GpiAssociate (hdcMem, NULLHANDLE);
- GpiDestroyPS (hdcMem);
- DevCloseDC (DevCxtMem);
-
- POINTL cPoints[4] = {xx, yy, // lower left targ
- xx+nPoints-1, yy, // upper right targ
- 0, 0, // lower left src
- nPoints, 1}; // upper right src
- MapToOS2(&cPoints[0]);
- MapToOS2(&cPoints[1]);
-
- // set ownership of bitmap to canvas
- HBITMAP hbmr = GpiSetBitmap(_hdc, hbm);
- // now reset the original bitmap if there was one
- GpiSetBitmap(_hdc, hbmr);
- // blit the image to the canvas
- GpiWCBitBlt(_hdc, hbm, 4, cPoints, ROP_SRCCOPY, BBO_IGNORE);
- // destroy the bitmap
- if (hbm != 0)
- GpiDeleteBitmap(hbm);
-
- #else
- // this is the slow but straightforward way using GpiSetPel
- LINEBUNDLE pen;
- POINTL Point, os2Point;
- Point.x = xx;
- Point.y = yy;
-
- if (xx < 0) // need to check every time
- {
- for (int ix = 0 ; ix < nPoints ; ++ix)
- {
- if (xx+ix < 0)
- continue; // this one not displayed
- pen.lColor = pointList[ix].pixel();
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR, 0, &pen);
- Point.x = xx+ix;
- os2Point.x = Point.x;
- os2Point.y = Point.y;
- MapToOS2(&os2Point);
- GpiSetPel (_hdc, &os2Point);
- }
- }
- else // don't need xx check
- {
- for (int ix = 0 ; ix < nPoints ; ++ix)
- {
- pen.lColor = pointList[ix].pixel();
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR, 0, &pen);
- Point.x = xx+ix;
- os2Point.x = Point.x;
- os2Point.y = Point.y;
- MapToOS2(&os2Point);
- GpiSetPel (_hdc, &os2Point);
- }
- }
- #endif
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawPoint <<<======================
- void vWinDC::DrawPoint(int x, int y)
- {
- BeginPaint();
- // First, do the required scaling
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
-
- POINTL Point;
- Point.x = xx;
- Point.y = yy;
- MapToOS2(&Point);
-
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR, 0, _hpen);
-
- // Now the code to actually do the drawing
- GpiSetPel (_hdc, &Point);
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawPoints <<<======================
- void vWinDC::DrawPoints(vPoint* pointList, int count)
- {
- POINTL Point;
-
- if (count < 1 || pointList == 0)
- return;
-
- BeginPaint();
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR, 0, _hpen);
-
- // Now the code to actually do the drawing
- vPoint* pl = pointList ;
- for (int num = 0 ; num < count ; ++pl, ++num)
- {
- Point.x = Scale(pl->x+_tx);
- Point.y = Scale(pl->y+_ty);
- MapToOS2(&Point);
-
- GpiSetPel (_hdc, &Point);
- }
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawPolygon <<<======================
- void vWinDC::DrawPolygon(int n, vPoint points[], int fillStyle)
- {
- // draw a complete polygon (starting point specified twice!)
- BeginPaint();
- if (_hasScale || _tx != 0 || _ty != 0) // If we have to scale, then we need to copy
- {
- for (int i = 0; i < n; i++)
- {
- points[i].x = ((points[i].x+_tx) * _Mult) / _Div; // scale
- points[i].y = ((points[i].y+_ty) * _Mult) / _Div;
- }
- }
-
- // we need to be careful here, since we are actually changing the
- // data in the users own structure here. We will need to put things
- // back the way they were when we are done!
- for (int i = 0; i < n; i++)
- {
- MapToOS2(&points[i]);
- }
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- _hbrush = _brush.GetHBRUSH();
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
-
- // fill the outline
- GpiBeginPath(_hdc, 1L);
- GpiSetCurrentPosition (_hdc , &points[0]); // move to first point
- GpiPolyLine(_hdc, n-1, &points[1]); // draw the outline polygon
- GpiEndPath(_hdc);
-
- GpiFillPath(_hdc, 1L, (fillStyle == vAlternate) ? FPATH_ALTERNATE : FPATH_WINDING);
-
- // draw the outline
- GpiBeginPath(_hdc, 1L);
- GpiSetCurrentPosition (_hdc , &points[0]); // move to last point
- GpiPolyLine(_hdc, n-1, &points[1]); // draw the outline polygon
- GpiEndPath(_hdc);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // for Geometric lines, the fill color is used (what a debacle!)
- AREABUNDLE linebrush;
- linebrush.lColor = _hpen->lColor; // for stroked lines
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // solid lines can be stroked
- }
- else
- GpiOutlinePath(_hdc, 1L, 0L); // other lines need to be outlined
-
- // restore the user's points data back to the original values
- for (i = 0; i < n; i++)
- {
- MapFromOS2(&points[i]);
- }
-
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawRectangle <<<======================
- void vWinDC::DrawRectangle(int x, int y, int width, int height)
- {
- if (height == 0 || width == 0)
- return;
-
- BeginPaint();
- POINTL poss, pose;
- AREABUNDLE linebrush;
-
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- poss.x = Scale(x+_tx);
- poss.y = Scale(y+_ty);
- pose.x = Scale(x+width-1+_tx);
- pose.y = Scale(y+height-1+_ty);
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- _hbrush = _brush.GetHBRUSH();
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- GpiSetCurrentPosition (_hdc, &poss);
- GpiBox(_hdc, DRO_FILL, &pose, 0, 0);
- GpiBeginPath(_hdc, 1L);
- GpiBox(_hdc, DRO_OUTLINE, &pose, 0, 0);
- GpiEndPath(_hdc);
-
- linebrush.lColor = _hpen->lColor;
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
- }
- else
- {
- GpiSetCurrentPosition (_hdc, &poss); // move to start point
- GpiBox(_hdc, DRO_OUTLINEFILL, &pose, 0, 0);
- }
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawRectangles <<<======================
- void vWinDC::DrawRectangles(vRect* rectList, int count)
- {
- if (count < 1 || !rectList)
- return;
-
- POINTL poss, pose;
-
- BeginPaint();
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- _hbrush = _brush.GetHBRUSH();
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
-
- vRect* rp = rectList ;
- for (int num=0 ; num < count ; ++rp, ++num)
- {
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- poss.x = Scale(rp->x+_tx);
- poss.y = Scale(rp->y+_ty);
- pose.x = Scale(rp->x+rp->w-1+_tx);
- pose.y = Scale(rp->y+rp->h-1+_ty);
- if (rp->h == 0 && rp->w == 0)
- continue;
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- // if solid line then we can support variable line widths
- if (_hpen->usType == LINETYPE_SOLID)
- {
- GpiSetCurrentPosition (_hdc, &poss);
- GpiBox(_hdc, DRO_FILL, &pose, 0, 0);
- GpiBeginPath(_hdc, 1L);
- GpiBox(_hdc, DRO_OUTLINE, &pose, 0, 0);
- GpiEndPath(_hdc);
-
- AREABUNDLE linebrush;
- linebrush.lColor = _hpen->lColor;
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
- // don't forget to reset the brush back to what it was
-
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
- }
- else
- // otherwise, we only support single pel width lines
- {
- GpiSetCurrentPosition (_hdc, &poss); // move to start point
- GpiBox(_hdc, DRO_OUTLINEFILL, &pose, 0, 0);
- }
- }
- EndPaint();
- }
-
- //================>>> vWinDC::DrawRoundedRectangle <<<===================
- void vWinDC::DrawRoundedRectangle(int x, int y,
- int width, int height, int radius)
- {
- if (height == 0 || width == 0)
- return;
-
- BeginPaint();
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- POINTL poss, pose;
- poss.x = Scale(x+_tx);
- poss.y = Scale(y+_ty);
- pose.x = Scale(x+width-1+_tx);
- pose.y = Scale(y+height-1+_ty);
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- int r;
- if (radius < 0)
- {
- // Negative radius means divide average of height and width
- // by this
- r = (Scale(width+height)/(-2 * radius));
- }
- else
- r = Scale(radius);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- _hbrush = _brush.GetHBRUSH();
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, _hbrush);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- GpiSetCurrentPosition (_hdc, &poss);
- GpiBox(_hdc, DRO_FILL, &pose, 2*r, 2*r);
- GpiBeginPath(_hdc, 1L);
- GpiBox(_hdc, DRO_OUTLINE, &pose, 2*r, 2*r);
- GpiEndPath(_hdc);
-
- AREABUNDLE linebrush;
- linebrush.lColor = _hpen->lColor;
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
- }
- else
- {
- GpiSetCurrentPosition (_hdc, &poss); // move to start point
- GpiBox(_hdc, DRO_OUTLINEFILL, &pose, 2*r, 2*r);
- }
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawRubberEllipse<<<===================
- void vWinDC::DrawRubberEllipse(int x, int y, int width, int height)
- {
- if (height == 0 || width == 0)
- return;
-
- BeginPaint();
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- int x1 = Scale(x+_tx);
- int y1 = Scale(y+_ty);
- int width1 = Scale(width-1);
- int height1 = Scale(height-1);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH, 0, _hpen);
-
- // set arc params at 2x scale
- ARCPARAMS arc;
- arc.lP = width1;
- arc.lQ = height1;
- arc.lR = 0;
- arc.lS = 0;
- GpiSetArcParams(_hdc , &arc);
-
- // compute center of ellipse
- POINTL posc = {x1+(width1/2), y1+(height1/2)};
- MapToOS2(&posc);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // save the original brush values
- LONG orgColor = _hbrush->lColor;
- USHORT orgMix = _hbrush->usMixMode;
-
- GpiSetCurrentPosition (_hdc, &posc);
- GpiBeginPath(_hdc, 1L);
- GpiFullArc (_hdc, DRO_OUTLINE, MAKEFIXED(0,0x8000)); // scale by 1/2
- GpiEndPath(_hdc);
-
- AREABUNDLE linebrush;
- linebrush.lColor = SETRGB(255,255,255);
- linebrush.usMixMode = FM_XOR; // draw in XOR
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
-
- // restore the original brush values
- linebrush.lColor = orgColor;
- linebrush.usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR, 0, &linebrush);
- }
- else
- {
- // save the original pen values
- LONG orgColor = _hpen->lColor;
- USHORT orgMix = _hpen->usMixMode;
-
- // change pen for rubber line
- _hpen->lColor = SETRGB(255,255,255); // set pen color to white
- _hpen->usMixMode = FM_XOR; // draw in XOR
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
-
- GpiFullArc (_hdc, DRO_OUTLINE, MAKEFIXED(0,0x8000)); // scale by 1/2
- // restore the original pen values
- _hpen->lColor = orgColor;
- _hpen->usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- EndPaint();
- }
- }
-
- //==================>>> vWinDC::DrawRubberLine <<<======================
- void vWinDC::DrawRubberLine(int x, int y, int xend, int yend)
- {
- BeginPaint();
- // Draw a rubber-band line from x,y to xend,yend. Redrawing
- // over the same with will erase it.
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
- int xe = Scale(xend+_tx);
- int ye = Scale(yend+_ty);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH, 0, _hpen);
-
- // Shapes will do a similar sequence for brushes as well
- // Now the code to actually do the drawing
-
- POINTL poss = {xx, yy}; // start point
- POINTL pose = {xe, ye}; // end point
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // save the original brush values
- LONG orgColor = _hbrush->lColor;
- USHORT orgMix = _hbrush->usMixMode;
-
- GpiBeginPath(_hdc, 1L);
- GpiSetCurrentPosition (_hdc, &poss);
- GpiLine (_hdc , &pose);
- GpiEndPath(_hdc);
-
- AREABUNDLE linebrush;
- linebrush.lColor = SETRGB(255,255,255);
- linebrush.usMixMode = FM_XOR; // draw in XOR
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
-
- // restore the original brush values
- linebrush.lColor = orgColor;
- linebrush.usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR, 0, &linebrush);
- }
- else
- {
- // save the original pen values
- LONG orgColor = _hpen->lColor;
- USHORT orgMix = _hpen->usMixMode;
-
- // change pen for rubber line
- _hpen->lColor = SETRGB(255,255,255); // set pen color to white
- _hpen->usMixMode = FM_XOR; // draw in XOR
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- GpiSetCurrentPosition (_hdc, &poss);
- GpiLine (_hdc , &pose);
-
- // restore the original pen values
- _hpen->lColor = orgColor;
- _hpen->usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- }
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawRubberPoint <<<======================
- void vWinDC::DrawRubberPoint(int x, int y)
- {
- BeginPaint();
- // First, do the required scaling
- int xx = Scale(x+_tx);
- int yy = Scale(y+_ty);
-
- POINTL Point;
- Point.x = xx;
- Point.y = yy;
- MapToOS2(&Point);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- // save the original pen values
- LONG orgColor = _hpen->lColor;
- USHORT orgMix = _hpen->usMixMode;
- // change pen for rubber line
- _hpen->lColor = SETRGB(255,255,255); // set pen color to white
- _hpen->usMixMode = FM_XOR; // draw in XOR
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- GpiSetPel (_hdc, &Point);
-
- // restore the original pen values
- _hpen->lColor = orgColor;
- _hpen->usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- EndPaint();
- }
-
- //==================>>> vWinDC::DrawRubberRectangle <<<==================
- void vWinDC::DrawRubberRectangle(int x, int y, int width, int height)
- {
- if (height == 0 || width == 0)
- return;
-
- BeginPaint();
- POINTL poss, pose;
- AREABUNDLE linebrush;
- // coords for GPI functions are inclusive/inclusive
- // right = left + width -1
- // top = bottom + height -1
- poss.x = Scale(x+_tx);
- poss.y = Scale(y+_ty);
- pose.x = Scale(x+width-1+_tx);
- pose.y = Scale(y+height-1+_ty);
- MapToOS2(&poss);
- MapToOS2(&pose);
-
- _hpen = _pen.GetHPEN(); // Get the pen
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_COLOR | LBB_TYPE | LBB_WIDTH | LBB_GEOM_WIDTH,
- 0, _hpen);
-
- if (_hpen->usType == LINETYPE_SOLID)
- {
- // save the original brush values
- LONG orgColor = _hbrush->lColor;
- USHORT orgMix = _hbrush->usMixMode;
-
- GpiSetCurrentPosition (_hdc, &poss);
- GpiBeginPath(_hdc, 1L);
- GpiBox(_hdc, DRO_OUTLINE, &pose, 0, 0);
- GpiEndPath(_hdc);
-
- linebrush.lColor = SETRGB(255,255,255);
- linebrush.usMixMode = FM_XOR; // draw in XOR
- linebrush.usSymbol = PATSYM_SOLID;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR | ABB_SYMBOL, 0, &linebrush);
- GpiStrokePath(_hdc, 1L, 0L); // thick lines need to be stroked
-
- // restore the original brush values
- linebrush.lColor = orgColor;
- linebrush.usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_AREA, ABB_MIX_MODE | ABB_COLOR, 0, &linebrush);
- }
- else
- {
- // save the original pen values
- LONG orgColor = _hpen->lColor;
- USHORT orgMix = _hpen->usMixMode;
- // change pen for rubber line
- _hpen->lColor = SETRGB(255,255,255); // set pen color to white
- _hpen->usMixMode = FM_XOR; // draw in XOR
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
-
- GpiSetCurrentPosition (_hdc, &poss); // move to start point
- GpiBox(_hdc, DRO_OUTLINE, &pose, 0, 0);
-
- // restore the original pen values
- _hpen->lColor = orgColor;
- _hpen->usMixMode = orgMix;
- GpiSetAttrs(_hdc, PRIM_LINE, LBB_MIX_MODE | LBB_COLOR, 0, _hpen);
- }
- EndPaint();
- }
-
- //=====================>>> vWinDC::DrawAttrText <<<==========================
- void vWinDC::DrawAttrText(int x, int y, VCONST char* text, const ChrAttr attr)
- {
- // Draw text with attributes at given x, y.
- static int mapColor[] =
- {
- vC_Black, vC_Blue, vC_Green, vC_Cyan,
- vC_Red, vC_Magenta, vC_Yellow, vC_White,
- vC_DarkGray, vC_DimBlue, vC_DimGreen, vC_DimCyan,
- vC_DimRed, vC_DimMagenta, vC_DimYellow, vC_MedGray
- };
-
- BeginPaint();
- POINTL poss;
- poss.x = Scale(x+_tx);
- poss.y = Scale(y+_ty);
- MapToOS2(&poss);
-
- _font.LoadFont(_hdc); // need to setup font!
- _htext = _font.GetHFONT();
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
-
- // we get the charbundle to control font color
- // we use the current pen to define text colors
- ULONG orgfgc = _pen.GetColor().pixel();
- ULONG orgbgc = _canvasBG;
-
- if (attr & ChHighlight)
- {
- _htext->usBackMixMode = BM_OVERPAINT;
- _htext->lBackColor = WinQuerySysColor(HWND_DESKTOP, SYSCLR_HILITEBACKGROUND, 0L);
- _htext->lColor = WinQuerySysColor(HWND_DESKTOP, SYSCLR_HILITEFOREGROUND, 0L);
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
- }
- else if (attr & ChReverse)
- {
- // default backmixmode is BM_LEAVEALONE, the windows version of V
- // overpaints background so we will do accordingly
- _htext->usBackMixMode = BM_OVERPAINT;
- _htext->lBackColor = orgfgc;
- _htext->lColor = orgbgc;
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
- }
- else
- {
- _htext->usBackMixMode = BM_OVERPAINT;
- // _htext->usBackMixMode = BM_LEAVEALONE;
- _htext->lBackColor = orgbgc;
- _htext->lColor = orgfgc;
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
- }
-
- if (attr & 0xF0) // A color overide
- {
- _htext->lColor = vStdColors[ mapColor[((attr & 0xF0) >> 4)] ].pixel();
- }
-
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_COLOR | CBB_BACK_MIX_MODE | CBB_COLOR | CBB_TEXT_ALIGN,
- 0, _htext);
-
- // Now the code to actually do the drawing
- if (_isPrinterDC)
- {
- GpiCharStringAt (_hdc, &poss, strlen(text), text);
- }
- else
- {
- // need to turn off cursor during screen update
- GpiCharStringAt (_hdc, &poss, strlen(text), text);
- }
-
- if ((attr & ChReverse) || (attr & ChHighlight))
- {
- _htext->usBackMixMode = BM_LEAVEALONE;
- _htext->lBackColor = orgbgc;
- _htext->lColor = orgfgc;
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_COLOR | CBB_BACK_MIX_MODE | CBB_COLOR, 0, _htext);
- }
- else
- {
- _htext->usBackMixMode = BM_LEAVEALONE;
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_MIX_MODE, 0, _htext);
- }
-
- EndPaint();
- }
-
- //=====================>>> vWinDC::DrawText <<<==========================
- void vWinDC::DrawText(int x, int y, VCONST char* text)
- {
- // simple draw text at given x, y
- // First, do the required scaling
- if (!text || !*text)
- return;
-
- BeginPaint();
- POINTL poss;
- poss.x = Scale(x+_tx);
- poss.y = Scale(y+_ty);
- MapToOS2(&poss);
-
- _font.LoadFont(_hdc); // need to setup font!
- _htext = _font.GetHFONT();
-
- _htext->lColor = _pen.GetColor().pixel();
- _htext->lBackColor = _canvasBG;
- _htext->usBackMixMode = BM_OVERPAINT;
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
- GpiSetAttrs(_hdc, PRIM_CHAR,
- CBB_BACK_COLOR | CBB_COLOR | CBB_TEXT_ALIGN | CBB_BACK_MIX_MODE, 0, _htext);
-
- // Now the code to actually do the drawing
- // We fudge the y position to accomodate the
- // model transform that puts the origin at the top left.
- if (_isPrinterDC)
- {
- // poss.y = poss.y + _font.GetPointSize();
- GpiCharStringAt (_hdc, &poss, strlen(text), text);
- }
- else
- {
- // need to turn off cursor during screen update
- GpiCharStringAt (_hdc, &poss, strlen(text), text);
- }
-
- // restore to deafult mix mode
- _htext->usBackMixMode = BM_LEAVEALONE;
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_MIX_MODE, 0, _htext);
-
- EndPaint();
- }
-
- //=====================>>> vWinDC::SetBrush <<<============================
- void vWinDC::SetBrush(VCONST vBrush& brush)
- {
- _brush = brush;
- }
-
- //=====================>>> vWinDC::SetPen <<<============================
- void vWinDC::SetPen(VCONST vPen& pen)
- {
- _pen = pen;
- }
-
- //====================>>> vWinDC::TextHeight <<<=============================
- int vWinDC::TextHeight(int& asc, int& des) VCONST
- {
- // Return total height of this font. V will use total height, which
- // is most often made up of ascent + descent. This is too much
- // detail for the kind of apps V will support.
- _font.LoadFont(_hdc); // need to setup font!
- _htext = _font.GetHFONT();
- _htext->usTextAlign = TA_BOTTOM | TA_LEFT;
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_COLOR | CBB_COLOR | CBB_TEXT_ALIGN, 0, _htext);
-
- FONTMETRICS fm;
- int a = 5, d = 3; // something reasonable?
- GpiQueryFontMetrics (_hdc, sizeof(FONTMETRICS), &fm);
- a = fm.lMaxAscender;
- d = fm.lMaxDescender;
-
- asc = a ; des = d;
-
- if (_isPrinterDC) // need to correct for the scaling of the print canvas
- {
- return ((a+d)*65536/_OS2Scale);
- }
- else
- {
- return (a+d);
- }
- }
-
- //========================>>> vvWinDC::TextWidth <<<==========================
- int vWinDC::TextWidth(char* str) VCONST
- {
- _font.LoadFont(_hdc); // need to setup font!
- _htext = _font.GetHFONT();
- GpiSetAttrs(_hdc, PRIM_CHAR, CBB_BACK_COLOR | CBB_COLOR, 0, _htext);
-
- POINTL box[TXTBOX_COUNT];
- GpiQueryTextBox (_hdc, strlen(str), str, TXTBOX_COUNT, box);
-
- int width = box[TXTBOX_TOPRIGHT].x - box[TXTBOX_TOPLEFT].x;
-
- if (_isPrinterDC) // need to correct for the scaling of the print canvas
- {
- return (width*65536/_OS2Scale);
- }
- else
- {
- return (width);
- }
- }
-
- //========================>>> vvWinDC::MapToOS2 <<<===========================
- void vWinDC::MapToOS2(PPOINTL in)
- {
- // we use the OS/2 FIXED data type to handle fractional
- // scaling while retaining integer math
- ULONG m, f;
-
- m = HIUSHORT(_OS2Scale);
- f = LOUSHORT(_OS2Scale);
- in->y = -(1-_OS2Height + in->y);
- in->y = (in->y * m) + (in->y * f/65536);
- in->x = (in->x * m) + (in->x * f/65536);
- }
-
- //========================>>> vvWinDC::MapFromOS2 <<<=========================
- void vWinDC::MapFromOS2(PPOINTL in)
- {
- // we use the OS/2 FIXED data type to handle fractional
- // scaling while retaining integer math
- in->y = -(1-_OS2Height + (in->y * 65536/_OS2Scale) );
- in->x = in->x * 65536/_OS2Scale;
- }
-
-
-