home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
os2cl016.zip
/
bg_paint.cpp
next >
Wrap
C/C++ Source or Header
|
1996-05-04
|
11KB
|
395 lines
/*
bg_paint.cpp (emx+gcc)
1995 Giovanni Iachello
This is freeware software. You can use or modify it as you wish,
provided that the part of code that I wrote remains freeware.
Freeware means that the source code must be available on request
to anyone.
You must also include this notice in all files derived from this
file.
Parts of this code are:
*/
/*---------------------------------------------------------
THREADS3.C -- Demonstrates drawing from a second thread
(c) 1990, Ziff Communications Co.
PC Magazine * Charles Petzold, 2/90
---------------------------------------------------------*/
/*
This example shows some of the library features:
* using the background paint thread
* using semaphores
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define INCL_WIN
#include "pmwin.h"
#include "pmdlg.h"
#include "pmgpi.h"
#include "pmstdres.h"
#include "bg_paint.h"
#define CXIMAGE 150
#define CYIMAGE 150
#define SPLINE 100
#define min(a,b) ((a)>(b)? (b) : (a))
PMApp* App;
/////////////////////////////////////////////////////////////////////////////
//
// PMPaintThread: paint thread class: allows to dump lenghty paint
// operations on a secondary thread.
//
//
// What to do to use the class:
// 1. create the class (you'll want to derive another class and redefine
// the paint function).
// 2. when creating the window that uses the class (in the create() func.)
// open a DC of the window, get a PS, create the paint thread, and if
// you want, you may produce a segment on the PS. (openSegment with
// drawing mode set to DM_RETAIN).
// 3. When WM_PAINT is sent to the window, do default processing (ie erasing
// the window, then stop drawing in the paint thread, wait for ready flag
// (readySem posted), and post the triggerSem to trigger drawing.
// 4. When exiting the window, kill the thread, (optionally calling
// stop and waiting for ready flag).
//
// note: it is not necessary to wait for the ready flag.
//
class PMPaintThread : public PMWindowThread
{
PMPresSpace *pps;
BOOL stopCalled;
public:
PMEventSemaphore *readySem,*triggerSem;
PMPaintThread(PMPresSpace *p) : PMWindowThread()
{
readySem = new PMEventSemaphore;
triggerSem = new PMEventSemaphore;
pps=p;
}
void main(void* =NULL) {
while (TRUE) {
readySem->post(); // we're ready...
triggerSem->wait(); // wait for trigger
pps->setStopDraw(SDW_OFF); // default setting, do not stop drawing
stopCalled=FALSE;
readySem->reset(); // we're not ready...
triggerSem->reset(); // deactivate trigger...
paint();
}
}
PMPresSpace *ps() { return pps; }
void stop()
// try stop drawing, by calling GpiSetStopDraw (if drawing from a
// segment) or by checking a flag in the paint function.
{
stopCalled=TRUE;
pps->setStopDraw(SDW_ON);
}
protected:
void paint()
{
pps->save();
pps->drawSegment(1L);
pps->restore(-1L);
for (int j=0; j<8; j++) {
for (int i=0; i<200 && !stopCalled; i++) {
PMRect rcl(j*100,0,(j+1)*100,i);
pps->fillRect(&rcl,CLR_BLUE+j);
}
}
}
};
class BG_PaintWin : public PMWin
{
PMPaintThread *dthread;
PMDeviceContext *dc;
PMPresSpace *ps;
ULONG prtclass;
LONG delta;
public:
BG_PaintWin(HAB ab,ULONG pc,LONG d) : PMWin("bgpaintwin",ab) {
createArgs->flCreateFlags|=FCF_ICON;
createArgs->idResources=ID_BGPAINT;
createArgs->pszTitle="bgpaint";
delta=d;
prtclass=pc;
} ;
BOOL create(PMEvent &)
{
if (!dthread) {
dc= new PMDeviceContext( hwnd );
ps = new PMPresSpace(dc, 0, 0, PU_LOENGLISH | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC, ab) ;
dthread = new PMPaintThread(ps);
dthread->setPriority(PRTYS_THREAD,prtclass,delta);
// produce a simple segment to show how it is done
// segments are collections of Gpi commands which are not
// executed directly but are kept in the PS. When the
// drawSegment command is invoked the whole segment is
// drawn in one pass. It is possible to stop the lenghty
// drawing operation with setStopDraw.
ps->setDrawingMode ( DM_RETAIN) ;
ps->openSegment (1L) ;
drawImage () ;
ps->closeSegment () ;
}
return TRUE;
}
// parts of this code was taken from an example by Charles Petzold, quote:
/*---------------------------------------------------------
THREADS3.C -- Demonstrates drawing from a second thread
(c) 1990, Ziff Communications Co.
PC Magazine * Charles Petzold, 2/90
---------------------------------------------------------*/
BOOL size(SHORT sx,SHORT sy)
{
dthread->stop();
dthread->readySem->wait();
SIZEL sizlClient ;
// get new size of client window
sizlClient.cx = sx ;
sizlClient.cy = sy ;
// set the new default view matrix
GpiConvert (*ps, CVTC_DEVICE, CVTC_PAGE, 1L, (PPOINTL) &sizlClient);
FIXED afxScale[2] ;
MATRIXLF matlf ;
POINTL ptl ;
afxScale[0] = afxScale[1] = min (65536L * sizlClient.cx / CXIMAGE,
65536L * sizlClient.cy / CYIMAGE) ;
ptl.x = 0 ;
ptl.y = 0 ;
GpiScale (*ps, &matlf, TRANSFORM_REPLACE, afxScale, &ptl) ;
ptl.x = (sizlClient.cx - afxScale[0] *CXIMAGE / 65536L) / 2 ;
ptl.y = (sizlClient.cy - afxScale[1] * CYIMAGE / 65536L) / 2 ;
GpiTranslate (*ps, &matlf, TRANSFORM_ADD, &ptl) ;
GpiSetDefaultViewMatrix (*ps, 9L, &matlf, TRANSFORM_REPLACE) ;
return TRUE;
}
BOOL destroy()
{
if (dthread) {
dthread->stop();
dthread->kill();
delete dthread;
delete ps;
}
return TRUE;
}
BOOL paint()
{
PMRect rcl;
dthread->stop();
dthread->readySem->wait();
WinBeginPaint (hwnd, *ps, NULL) ;
rcl=this;
GpiErase (*ps) ;
ps->fillRect(&rcl,CLR_BLUE);
WinEndPaint (*ps) ;
dthread->triggerSem->post();
return TRUE;
}
BOOL other(PMEvent &event)
{
if (event.msg == WM_ERASEBACKGROUND) {
event.ret=(MRESULT)TRUE;
return TRUE;
}
return FALSE;
}
void drawImage()
{
// PMRect rcl;
// rcl=this;
// ps->setColor (CLR_DARKCYAN);
// ps->fillRect(&rcl,CLR_WHITE);
// ps->drawText (-1, "Background Paint main window ", &rcl, 0, 0, DT_TEXTATTRS | DT_CENTER | DT_VCENTER | DT_ERASERECT);
MATRIXLF matlf ;
POINTL ptl, aptl[4] ;
SHORT iAngle ;
// Draw outline of letters
drawLetters () ;
// Use letters outline as clipping path
GpiBeginPath (*ps, 1L) ;
drawLetters () ;
GpiEndPath (*ps) ;
GpiSetClipPath (*ps, 1L, SCP_AND | SCP_ALTERNATE) ;
for (iAngle = 0 ; iAngle < 360 ; iAngle++)
{
// Find matrix for rotation around origin
ptl.x = 0 ;
ptl.y = 0 ;
GpiRotate (*ps, &matlf, TRANSFORM_REPLACE,
MAKEFIXED (iAngle, 0), &ptl) ;
// Append matrix for translation to center of image
ptl.x = CXIMAGE / 2 ;
ptl.y = CYIMAGE / 2 ;
GpiTranslate (*ps, &matlf, TRANSFORM_ADD, &ptl) ;
// Set model transform using composite matrix
GpiSetModelTransformMatrix (*ps, 9L, &matlf, TRANSFORM_REPLACE) ;
// Draw spline curve
aptl[0].x = 0 ;
aptl[0].y = 0 ;
aptl[1].x = SPLINE / 3 ;
aptl[1].y = SPLINE / 2 ;
aptl[2].x = 2 * SPLINE / 3 ;
aptl[2].y = - SPLINE / 2 ;
aptl[3].x = SPLINE ;
aptl[3].y = 0 ;
GpiMove (*ps, aptl) ;
GpiPolySpline (*ps, 3L, aptl + 1) ;
}
}
void drawLetters ()
{
POINTL ptl, aptl[3] ;
// Outside of 'P'
ptl.x = 4 ; ptl.y = 4 ; GpiMove (*ps, &ptl) ;
ptl.x = 4 ; ptl.y = 146 ; GpiLine (*ps, &ptl) ;
ptl.x = 45 ; ptl.y = 146 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 72 ; aptl[0].y = 146 ;
aptl[1].x = 72 ; aptl[1].y = 119 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 72 ; ptl.y = 85 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 72 ; aptl[0].y = 58 ;
aptl[1].x = 45 ; aptl[1].y = 58 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 35 ; ptl.y = 58 ; GpiLine (*ps, &ptl) ;
ptl.x = 35 ; ptl.y = 4 ; GpiLine (*ps, &ptl) ;
ptl.x = 4 ; ptl.y = 4 ; GpiLine (*ps, &ptl) ;
// Inside of 'P'
ptl.x = 35 ; ptl.y = 77 ; GpiMove (*ps, &ptl) ;
ptl.x = 35 ; ptl.y = 125 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 43 ; aptl[0].y = 125 ;
aptl[1].x = 43 ; aptl[1].y = 117 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 43 ; ptl.y = 85 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 43 ; aptl[0].y = 77 ;
aptl[1].x = 35 ; aptl[1].y = 77 ; GpiPolyFillet (*ps, 2L, aptl) ;
// Outline of 'C'
ptl.x = 116 ; ptl.y = 63 ; GpiMove (*ps, &ptl) ;
ptl.x = 145 ; ptl.y = 63 ; GpiLine (*ps, &ptl) ;
ptl.x = 145 ; ptl.y = 31 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 145 ; aptl[0].y = 4 ;
aptl[1].x = 118 ; aptl[1].y = 4 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 103 ; ptl.y = 4 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 76 ; aptl[0].y = 4 ;
aptl[1].x = 76 ; aptl[1].y = 31 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 76 ; ptl.y = 119 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 76 ; aptl[0].y = 146 ;
aptl[1].x = 103 ; aptl[1].y = 146 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 118 ; ptl.y = 146 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 145 ; aptl[0].y = 146 ;
aptl[1].x = 145 ; aptl[1].y = 119 ; GpiPolyFillet (*ps, 2L, aptl) ;
ptl.x = 145 ; ptl.y = 88 ; GpiLine (*ps, &ptl) ;
ptl.x = 116 ; ptl.y = 88 ; GpiLine (*ps, &ptl) ;
ptl.x = 116 ; ptl.y = 123 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 116 ; aptl[0].y = 127 ;
aptl[1].x = 108 ; aptl[1].y = 127 ;
aptl[2].x = 108 ; aptl[2].y = 123 ; GpiPolyFillet (*ps, 3L, aptl) ;
ptl.x = 108 ; ptl.y = 30 ; GpiLine (*ps, &ptl) ;
aptl[0].x = 108 ; aptl[0].y = 26 ;
aptl[1].x = 116 ; aptl[1].y = 26 ;
aptl[2].x = 116 ; aptl[2].y = 30 ; GpiPolyFillet (*ps, 3L, aptl) ;
ptl.x = 116 ; ptl.y = 63 ; GpiLine (*ps, &ptl) ;
}
};
int main (int argc,char* argv[])
{
ULONG pc;
LONG d;
if (argc>1) {
if (argc!=3 || strcmp(argv[1],"-?")==0) {
fprintf(stderr,"bg_paint <priority class 1..4> <delta level -31..31>\n");
exit(0);
} else {
pc=atol(argv[1]);
d=atol(argv[2]);
}
} else {
pc=1;
d=16;
}
PMAnchorBlock ab;
PMMessageQueue mq;
ab.init();
mq.create(ab);
App=new PMApp(ab,mq,argc,argv);
BG_PaintWin * bgpw=new BG_PaintWin(ab,pc,d);
bgpw->createWin();
App->run();
bgpw->destroyWin();
mq.destroy();
ab.uninit();
return (0);
}
/*
* Local variables:
* compile-command: "dmake bg_paint.exe"
* end:
*/