home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
dsplsurf.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-10
|
34KB
|
1,028 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#if defined(__GNUC__)
#pragma implementation
#endif
#include <iostream.h> // DEBUG
#include "base/bytstrng.h"
#include "ui/cntroler.h"
#include "ui/bitmap.h"
#include "ui/dsplsurf.h"
#include "ui/visualob.h"
#include "ui/color.h"
#include "ui/arc.h"
#include "ui/chord.h"
#include "ui/ellipse.h"
#include "ui/piewedge.h"
#include "ui/containr.h"
#include "ui/stencil.h"
#if defined(__OS2__)
static int _DrawMode [] = {
FM_ZERO, // GMode_Clear: 0
FM_AND, // GMode_And: SRC & DEST
FM_MASKSRCNOT, // GMode_AndReverse: SRC & ~DEST
FM_OVERPAINT, // GMode_Copy: SRC
FM_SUBTRACT, // GMode_AndInverted: ~SRC & DEST
FM_LEAVEALONE, // GMode_NoOp: DEST
FM_XOR, // GMode_Xor: SRC ^ DEST
FM_OR, // GMode_Or: SRC | DEST
FM_NOTMERGESRC, // GMode_Nor: ~(SRC | DEST)
FM_NOTXORSRC, // GMode_Equiv: ~(SRC ^ DEST)
FM_INVERT, // GMode_Invert: ~DEST
FM_MERGESRCNOT, // GMode_OrReverse: SRC | ~DEST
FM_NOTCOPYSRC, // GMode_CopyInverted: ~SRC
FM_MERGENOTSRC, // GMode_OrInverted: ~SRC | DEST
FM_NOTMASKSRC, // GMode_Nand: ~(SRC & DEST)
FM_ONE // GMode_Set: 1
};
#elif defined(__MS_WINDOWS__)
#include <windows.h>
static int _DrawMode [] = {
R2_BLACK, // GMode_Clear = 0
R2_MASKPEN, // GMode_And
R2_MASKNOTPEN, // GMode_AndReverse
R2_COPYPEN, // GMode_Copy
R2_MASKPENNOT, // GMode_AndInverted
R2_NOP, // GMode_NoOp
R2_XORPEN, // GMode_Xor
R2_MERGEPEN, // GMode_Or
R2_NOTMERGEPEN, // GMode_Nor
R2_NOTXORPEN, // GMode_Equiv
R2_NOT, // GMode_Invert
R2_MERGENOTPEN, // GMode_OrReverse
R2_NOTCOPYPEN, // GMode_CopyInverted
R2_MERGEPENNOT, // GMode_OrInverted
R2_NOTMASKPEN, // GMode_Nand
R2_WHITE // GMode_Set
};
#elif defined(__X_MOTIF__)
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
static int _DrawMode [] = {
GXclear, // 0
GXand, // src AND dst
GXandReverse, // src AND NOT dst
GXcopy, // src
GXandInverted, // NOT src AND dst
GXnoop, // dst
GXxor, // src XOR dst
GXor, // src OR dst
GXnor, // NOT src AND NOT dst
GXequiv, // NOT src XOR dst
GXinvert, // NOT dst
GXorReverse, // src OR NOT dst
GXcopyInverted, // NOT src
GXorInverted, // NOT src OR dst
GXnand, // NOT src OR NOT dst
GXset // 1
};
#endif
#if defined(__GNUC__) && __GNUC_MINOR__ >= 6
template class CL_Binding<UI_DisplaySurface>;
#endif
UI_DisplaySurface::UI_DisplaySurface (UI_VisualObject* v)
: _client (*v)
{
_Init ();
_ownFont = FALSE;
}
void UI_DisplaySurface::_Init ()
{
_font = NULL;
#if defined(__MS_WINDOWS__)
_handle = GetDC (_client.ViewHandle ());
if (_handle) {
_horzPPM = ((float) GetDeviceCaps (_handle, LOGPIXELSX)) / 25.4;
_vertPPM = ((float) GetDeviceCaps (_handle, LOGPIXELSY)) / 25.4;
_horzPixels = GetDeviceCaps (_handle, HORZRES);
_vertPixels = GetDeviceCaps (_handle, VERTRES);
}
SetBkColor (_handle, _client.Background().NativeForm());
#elif defined(__OS2__)
_handle = WinGetPS (_client.ViewHandle());
GpiCreateLogColorTable (_handle, LCOL_RESET, LCOLF_RGB, 0, 0, NULL);
// For the moment, we don't support colormaps under OS/2
Mode (GMode_Copy);
#elif defined(__X_MOTIF__)
XGCValues xvalues;
Widget w = _client.ViewHandle ();
Display* dpy = XtDisplay (w);
short screen = DefaultScreen (dpy);
XtVaGetValues (w, XtNbackground, &xvalues.background, XtNforeground,
&xvalues.foreground, NULL);
_handle = XCreateGC (dpy, XtWindow (w), GCForeground|GCBackground,
&xvalues);
_horzPPM = DisplayWidth (dpy, screen) / DisplayWidthMM(dpy, screen);
_vertPPM = DisplayHeight (dpy, screen) / DisplayHeightMM(dpy, screen);
#endif
_brush = new UI_Brush (this, UIColor_White, UIBrush_Hollow);
_pen = new UI_Pen (this);
// _colorMap = new UI_ColorMap (*this);
}
typedef CL_Binding<UI_DisplaySurface> DSBind;
void UI_DisplaySurface::SetFont (UI_Font* fnt)
{
if (fnt && fnt != _font) {
DSBind pre (this, &UI_DisplaySurface::_FontWillChange);
fnt->AddPreChangeDependent (pre, 1);
DSBind post (this, &UI_DisplaySurface::_FontChanged);
fnt->AddDependent (post, 1);
if (_font) {
_font->RemoveDependent (post);
_font->RemovePreChangeDependent (pre);
}
_font = fnt;
_font->UseClient (this);
#if defined (__MS_WINDOWS__)
SelectObject (_handle, _font->Handle());
#elif defined(__OS2__)
GpiSetCharSet (_handle, _font->Handle());
#elif defined(__X_MOTIF__)
UI_ResourceHandle h = _font->Handle();
if (h) {
Display* dpy = XtDisplay (_client.ViewHandle ());
XSetFont (dpy, _handle, h);
}
#endif
}
}
bool UI_DisplaySurface::_FontWillChange (CL_Object&, long)
{
#if defined (__MS_WINDOWS__)
SelectObject (_handle, GetStockObject (SYSTEM_FONT));
#elif defined (__X_MOTIF__)
#endif
return TRUE;
}
bool UI_DisplaySurface::_FontChanged (CL_Object& o, long)
{
#if defined (__MS_WINDOWS__)
SelectObject (_handle, ((UI_Font&) o).Handle ());
#elif defined(__OS2__)
GpiSetCharSet (_handle, ((UI_Font&) o).Handle());
#elif defined (__X_MOTIF__)
UI_ResourceHandle h = _font->Handle();
if (h) {
Display* dpy = XtDisplay (_client.ViewHandle ());
XSetFont (dpy, _handle, h);
}
#endif
return TRUE;
}
UI_Point UI_DisplaySurface::_ProjectToCorner (UI_Rectangle &rect, UI_Point &p)
{
short centerx = (rect.Right() - rect.Left ()) /2;
short centery = (rect.Top () - rect.Bottom()) /2;
long xcoord = 0, ycoord = 0;
if (p.XCoord() >= centerx) xcoord = rect.Right();
else xcoord = rect.Left();
if (p.YCoord() >= centery) ycoord = rect.Bottom();
else ycoord = rect.Top();
return UI_Point (xcoord, ycoord);
}
UI_DisplaySurface::~UI_DisplaySurface()
{
if (_pen)
delete _pen;
if (_font) {
if (_ownFont)
delete _font;
else {
_font->UseClient (NULL);
DSBind pre (this, &UI_DisplaySurface::_FontWillChange);
_font->RemovePreChangeDependent (pre);
DSBind post (this, &UI_DisplaySurface::_FontChanged);
_font->RemoveDependent (post);
}
}
if (_brush)
delete _brush;
// if (_colorMap)
// delete _colorMap;
#if defined(__MS_WINDOWS__)
ReleaseDC (_client.ViewHandle (), _handle);
#elif defined(__OS2__)
WinReleasePS (_handle);
#elif defined(__X_MOTIF__)
XFreeGC (XtDisplay (_client), _handle);
#endif
}
UI_Rectangle UI_DisplaySurface::DrawingArea () const
{
#if defined(__MS_WINDOWS__)
return UI_DrawingSurface::DrawingArea ();
#elif defined(__X_MOTIF__) || defined(__OS2__)
return _client.ClientArea();
#endif
}
UI_Rectangle UI_DisplaySurface::DrawingAreaInMM () const
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
return UI_DisplaySurface::DrawingAreaInMM ();
#elif defined(__X_MOTIF__)
return _client.ClientArea();
#endif
}
UI_DisplaySurface::GraphicsMode UI_DisplaySurface::Mode () const
{
#if defined(__MS_WINDOWS__)
int mode = GetROP2 (_handle);
#elif defined(__X_MOTIF__)
XGCValues xvalues;
XGetGCValues (XtDisplay (_client), _handle, GCFunction, &xvalues);
int mode = xvalues.function;
#elif defined(__OS2__)
long mode = GpiQueryMix (_handle);
#endif
for (short i = 0; i < sizeof (_DrawMode)/sizeof (int); i++) {
if (mode == _DrawMode [i])
return (GraphicsMode) i;
}
// Something wrong: it's not in the table!
return (GraphicsMode) 0;
}
void UI_DisplaySurface::Mode (GraphicsMode mode)
{
if (mode < GMode_Clear || mode > GMode_Set) {
CL_Error::Warning ("UI_DisplaySurface::Mode: invalid parameter %d",
mode);
return;
}
#if defined(__MS_WINDOWS__)
SetROP2 (_handle, _DrawMode [mode]);
#elif defined(__OS2__)
GpiSetMix (_handle, _DrawMode[mode]);
#elif defined (__X_MOTIF__)
XGCValues xvalues;
xvalues.function = _DrawMode [mode];
XChangeGC (XtDisplay (_client), _handle, GCFunction, &xvalues);
#endif
}
bool UI_DisplaySurface::DrawBitmap (const UI_Bitmap& b, const UI_Point& p)
{
#if defined (__MS_WINDOWS__) || defined(__OS2__)
return UI_DrawingSurface::DrawBitmap (b, p);
#elif defined (__X_MOTIF__)
Widget w = _client;
Display* dpy = XtDisplay (w);
Window win = XtWindow (w);
XPutImage (dpy, win, _handle, b.Handle(), 0, 0, p.XCoord(), p.YCoord(),
b.Width(), b.Height());
return TRUE;
#else
NotImplemented ("DrawBitmap");
return FALSE;
#endif
}
void UI_DisplaySurface::ClearDisplay ()
{
#if defined(__MS_WINDOWS__)
HANDLE hbr = CreateSolidBrush (_client.Background().NativeForm());
HANDLE old = SelectObject (_handle, hbr);
RECT rect = DrawingArea().AsMSRect();
FillRect (_handle, &rect, hbr);
if (old)
SelectObject (_handle, old);
DeleteObject (hbr);
#elif defined(__OS2__)
GpiErase (_handle);
#elif defined(__X_MOTIF__)
Widget w = _client.ViewHandle ();
Display *dpy = XtDisplay (w);
XClearWindow (dpy, XtWindow (w));
#endif
}
#if defined(__X_MOTIF__)
class ColorSaver {
public:
ColorSaver (UI_VisualObject& v, const UI_Color& c);
~ColorSaver ();
protected:
UI_VisualObject& _vObj;
UI_Color _tmpColor;
};
ColorSaver::ColorSaver (UI_VisualObject& v, const UI_Color& c)
: _vObj (v)
{
_tmpColor = v.Foreground();
v.Foreground (c);
}
ColorSaver::~ColorSaver ()
{
_vObj.Foreground (_tmpColor);
}
#endif
void UI_DisplaySurface::ColorRectangle (const UI_Rectangle& r,
const UI_Color& cs)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::ColorRectangle (r, cs);
#elif defined(__X_MOTIF__)
ColorSaver s (_client, cs);
Widget w = _client.ViewHandle ();
Display *dpy = XtDisplay (w);
XFillRectangle (dpy, XtWindow (w), _handle,
r.Origin ().XCoord (), r.Origin ().YCoord (),
r.Width (), r.Height ());
#endif
}
void UI_DisplaySurface::DrawEllipse (const UI_Rectangle& r,
ushort opt)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawEllipse (r, opt);
#elif defined(__X_MOTIF__)
Display *dpy = XtDisplay (_client);
if (opt & UID_Fill) {
ColorSaver save (_client, _brush->Color());
XFillArc (dpy, XtWindow (_client), _handle, r.Origin ().XCoord (),
r.Origin ().YCoord (), r.Width (), r.Height (), 0,
64*360);
}
if (opt & UID_Outline) {
ColorSaver save (_client, _pen->Color());
XDrawArc (dpy, XtWindow (_client), _handle,
r.Origin().XCoord (), r.Origin().YCoord (), r.Width (),
r.Height (), 0, 64*360);
}
#endif
}
void UI_DisplaySurface::DrawArc (const UI_Arc& arc)
{
#if defined (__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawArc (arc);
#elif defined (__X_MOTIF__)
UI_Rectangle rect = arc.Ellipse().BoundingRectangle();
long startAngle = arc.StartAngle();
long subtAngle = arc.SubtendedAngle();
Display *dpy = _TheApplication->Controller().AppDisplay();
ColorSaver save (_client, _pen->Color());
XDrawArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
rect.Top(), rect.Width(), rect.Height(), startAngle,
subtAngle);
#endif
}
void UI_DisplaySurface::DrawChord (const UI_Chord& chord,
ushort opt)
{
#if defined (__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawChord (chord, opt);
#elif defined (__X_MOTIF__)
UI_Rectangle rect = chord.Ellipse().BoundingRectangle();
long startAngle = chord.StartAngle();
long subtAngle = chord.SubtendedAngle();
Display *dpy = _TheApplication->Controller().AppDisplay();
if (opt & UID_Fill) {
ColorSaver save (_client, _brush->Color());
XGCValues v;
v.arc_mode = ArcChord;
XChangeGC (dpy, Handle(), GCArcMode, &v);
XFillArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
rect.Top(), rect.Width(), rect.Height(), startAngle,
subtAngle);
}
if (opt & UID_Outline) {
ColorSaver save (_client, _pen->Color());
UI_PointPair pp = chord.EndPoints();
XDrawArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
rect.Top(), rect.Width(), rect.Height(), startAngle,
subtAngle);
XDrawLine (dpy, XtWindow (Client()), Handle(),
pp.p1.XCoord(), pp.p1.YCoord(),
pp.p2.XCoord(), pp.p2.YCoord());
}
#endif
}
void UI_DisplaySurface::DrawPieWedge (const UI_PieWedge& pie,
ushort opt)
{
#if defined (__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawPieWedge (pie, opt);
#elif defined (__X_MOTIF__)
UI_Rectangle rect = pie.Ellipse().BoundingRectangle();
long startAngle = pie.StartAngle();
long subtAngle = pie.SubtendedAngle();
Display *dpy = _TheApplication->Controller().AppDisplay();
if (opt & UID_Fill) {
ColorSaver save (_client, _brush->Color());
XGCValues v;
v.arc_mode = ArcPieSlice;
XChangeGC (dpy, Handle(), GCArcMode, &v);
XFillArc (dpy, XtWindow (Client()), Handle(), rect.Left(),
rect.Top(), rect.Width(), rect.Height(), startAngle,
subtAngle);
}
if (opt & UID_Outline) {
UI_Rectangle rect = pie.Ellipse().BoundingRectangle();
UI_PointPair pp = pie.EndPoints();
ColorSaver save (_client, _pen->Color());
XDrawArc (dpy, XtWindow (Client()), Handle(),
rect.Left(), rect.Top(), rect.Width(),
rect.Height(), startAngle, subtAngle);
XDrawLine (dpy, XtWindow (Client()), Handle(), pp.p1.XCoord(),
pp.p1.YCoord(), rect.Left()+(rect.Width()/2),
rect.Top()+(rect.Height()/2));
XDrawLine (dpy, XtWindow (Client()), Handle(),
pp.p2.XCoord(), pp.p2.YCoord(),
rect.Left()+(rect.Width()/2),
rect.Top()+(rect.Height()/2));
}
#endif
}
void UI_DisplaySurface::DrawPolygon (UI_Point parr[], short numpts,
ushort opt)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawPolygon (parr, numpts, opt);
#elif defined(__X_MOTIF__)
if (numpts <= 1)
return;
Display *dpy = XtDisplay (_client);
if (opt & UID_Fill) {
Display *dpy = XtDisplay (_client);
ColorSaver save (_client, _brush->Color());
XPoint* xp = new XPoint [numpts];
for (long i = 0; i < numpts; i++) {
xp [i].x = parr [i].XCoord ();
xp [i].y = parr [i].YCoord ();
}
XFillPolygon (dpy, XtWindow (_client), _handle, xp, numpts,
Complex, CoordModeOrigin);
delete [] xp;
}
if (opt & UID_Outline) {
DrawPolyLine (parr, numpts);
DrawLine (parr [numpts-1], parr [0]);
}
#endif
}
void UI_DisplaySurface::DrawRectangle (const UI_Rectangle& r,
ushort opt)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawRectangle (r, opt);
#elif defined(__X_MOTIF__)
Display *dpy = XtDisplay (_client);
if (opt & UID_Fill) {
Display *dpy = XtDisplay (_client);
ColorSaver save (_client, _brush->Color());
XFillRectangle (dpy, XtWindow (_client), _handle, r.Left (),
r.Top (), r.Width (), r.Height ());
}
if (opt & UID_Outline) {
ColorSaver save (_client, _pen->Color());
XDrawRectangle (dpy, XtWindow (_client), _handle,
r.Left (), r.Top (), r.Width (), r.Height ());
}
#endif
}
void UI_DisplaySurface::DrawPolyLine (UI_Point parr[], short numpts)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawPolyLine (parr, numpts);
#elif defined(__X_MOTIF__)
if (numpts <= 1)
return;
Display *dpy = XtDisplay (_client);
for (long i = 1; i < numpts; i++)
DrawLine (parr[i-1], parr [i]);
#endif
}
bool UI_DisplaySurface::DrawLine (const UI_Point& p, const UI_Point& q)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
return UI_DrawingSurface::DrawLine (p, q);
#elif defined(__X_MOTIF__)
ColorSaver save (_client, _pen->Color());
Display* dpy = XtDisplay (_TheApplication->Controller().ShellWidget());
XDrawLine (dpy, XtWindow (_client), Handle (),
p.XCoord(), p.YCoord(), q.XCoord(), q.YCoord());
#endif
}
#if defined(__X_MOTIF__)
// This is a table of bytes with their bit reversals. Reverse[i] is the
// value obtained by reading off the bits of i from right to left.
static uchar Reverse[] = {
/* 00 */ 0x00, /* 01 */ 0x80, /* 02 */ 0x40, /* 03 */ 0xc0,
/* 04 */ 0x20, /* 05 */ 0xa0, /* 06 */ 0x60, /* 07 */ 0xe0,
/* 08 */ 0x10, /* 09 */ 0x90, /* 0a */ 0x50, /* 0b */ 0xd0,
/* 0c */ 0x30, /* 0d */ 0xb0, /* 0e */ 0x70, /* 0f */ 0xf0,
/* 10 */ 0x08, /* 11 */ 0x88, /* 12 */ 0x48, /* 13 */ 0xc8,
/* 14 */ 0x28, /* 15 */ 0xa8, /* 16 */ 0x68, /* 17 */ 0xe8,
/* 18 */ 0x18, /* 19 */ 0x98, /* 1a */ 0x58, /* 1b */ 0xd8,
/* 1c */ 0x38, /* 1d */ 0xb8, /* 1e */ 0x78, /* 1f */ 0xf8,
/* 20 */ 0x04, /* 21 */ 0x84, /* 22 */ 0x44, /* 23 */ 0xc4,
/* 24 */ 0x24, /* 25 */ 0xa4, /* 26 */ 0x64, /* 27 */ 0xe4,
/* 28 */ 0x14, /* 29 */ 0x94, /* 2a */ 0x54, /* 2b */ 0xd4,
/* 2c */ 0x34, /* 2d */ 0xb4, /* 2e */ 0x74, /* 2f */ 0xf4,
/* 30 */ 0x0c, /* 31 */ 0x8c, /* 32 */ 0x4c, /* 33 */ 0xcc,
/* 34 */ 0x2c, /* 35 */ 0xac, /* 36 */ 0x6c, /* 37 */ 0xec,
/* 38 */ 0x1c, /* 39 */ 0x9c, /* 3a */ 0x5c, /* 3b */ 0xdc,
/* 3c */ 0x3c, /* 3d */ 0xbc, /* 3e */ 0x7c, /* 3f */ 0xfc,
/* 40 */ 0x02, /* 41 */ 0x82, /* 42 */ 0x42, /* 43 */ 0xc2,
/* 44 */ 0x22, /* 45 */ 0xa2, /* 46 */ 0x62, /* 47 */ 0xe2,
/* 48 */ 0x12, /* 49 */ 0x92, /* 4a */ 0x52, /* 4b */ 0xd2,
/* 4c */ 0x32, /* 4d */ 0xb2, /* 4e */ 0x72, /* 4f */ 0xf2,
/* 50 */ 0x0a, /* 51 */ 0x8a, /* 52 */ 0x4a, /* 53 */ 0xca,
/* 54 */ 0x2a, /* 55 */ 0xaa, /* 56 */ 0x6a, /* 57 */ 0xea,
/* 58 */ 0x1a, /* 59 */ 0x9a, /* 5a */ 0x5a, /* 5b */ 0xda,
/* 5c */ 0x3a, /* 5d */ 0xba, /* 5e */ 0x7a, /* 5f */ 0xfa,
/* 60 */ 0x06, /* 61 */ 0x86, /* 62 */ 0x46, /* 63 */ 0xc6,
/* 64 */ 0x26, /* 65 */ 0xa6, /* 66 */ 0x66, /* 67 */ 0xe6,
/* 68 */ 0x16, /* 69 */ 0x96, /* 6a */ 0x56, /* 6b */ 0xd6,
/* 6c */ 0x36, /* 6d */ 0xb6, /* 6e */ 0x76, /* 6f */ 0xf6,
/* 70 */ 0x0e, /* 71 */ 0x8e, /* 72 */ 0x4e, /* 73 */ 0xce,
/* 74 */ 0x2e, /* 75 */ 0xae, /* 76 */ 0x6e, /* 77 */ 0xee,
/* 78 */ 0x1e, /* 79 */ 0x9e, /* 7a */ 0x5e, /* 7b */ 0xde,
/* 7c */ 0x3e, /* 7d */ 0xbe, /* 7e */ 0x7e, /* 7f */ 0xfe,
/* 80 */ 0x01, /* 81 */ 0x81, /* 82 */ 0x41, /* 83 */ 0xc1,
/* 84 */ 0x21, /* 85 */ 0xa1, /* 86 */ 0x61, /* 87 */ 0xe1,
/* 88 */ 0x11, /* 89 */ 0x91, /* 8a */ 0x51, /* 8b */ 0xd1,
/* 8c */ 0x31, /* 8d */ 0xb1, /* 8e */ 0x71, /* 8f */ 0xf1,
/* 90 */ 0x09, /* 91 */ 0x89, /* 92 */ 0x49, /* 93 */ 0xc9,
/* 94 */ 0x29, /* 95 */ 0xa9, /* 96 */ 0x69, /* 97 */ 0xe9,
/* 98 */ 0x19, /* 99 */ 0x99, /* 9a */ 0x59, /* 9b */ 0xd9,
/* 9c */ 0x39, /* 9d */ 0xb9, /* 9e */ 0x79, /* 9f */ 0xf9,
/* a0 */ 0x05, /* a1 */ 0x85, /* a2 */ 0x45, /* a3 */ 0xc5,
/* a4 */ 0x25, /* a5 */ 0xa5, /* a6 */ 0x65, /* a7 */ 0xe5,
/* a8 */ 0x15, /* a9 */ 0x95, /* aa */ 0x55, /* ab */ 0xd5,
/* ac */ 0x35, /* ad */ 0xb5, /* ae */ 0x75, /* af */ 0xf5,
/* b0 */ 0x0d, /* b1 */ 0x8d, /* b2 */ 0x4d, /* b3 */ 0xcd,
/* b4 */ 0x2d, /* b5 */ 0xad, /* b6 */ 0x6d, /* b7 */ 0xed,
/* b8 */ 0x1d, /* b9 */ 0x9d, /* ba */ 0x5d, /* bb */ 0xdd,
/* bc */ 0x3d, /* bd */ 0xbd, /* be */ 0x7d, /* bf */ 0xfd,
/* c0 */ 0x03, /* c1 */ 0x83, /* c2 */ 0x43, /* c3 */ 0xc3,
/* c4 */ 0x23, /* c5 */ 0xa3, /* c6 */ 0x63, /* c7 */ 0xe3,
/* c8 */ 0x13, /* c9 */ 0x93, /* ca */ 0x53, /* cb */ 0xd3,
/* cc */ 0x33, /* cd */ 0xb3, /* ce */ 0x73, /* cf */ 0xf3,
/* d0 */ 0x0b, /* d1 */ 0x8b, /* d2 */ 0x4b, /* d3 */ 0xcb,
/* d4 */ 0x2b, /* d5 */ 0xab, /* d6 */ 0x6b, /* d7 */ 0xeb,
/* d8 */ 0x1b, /* d9 */ 0x9b, /* da */ 0x5b, /* db */ 0xdb,
/* dc */ 0x3b, /* dd */ 0xbb, /* de */ 0x7b, /* df */ 0xfb,
/* e0 */ 0x07, /* e1 */ 0x87, /* e2 */ 0x47, /* e3 */ 0xc7,
/* e4 */ 0x27, /* e5 */ 0xa7, /* e6 */ 0x67, /* e7 */ 0xe7,
/* e8 */ 0x17, /* e9 */ 0x97, /* ea */ 0x57, /* eb */ 0xd7,
/* ec */ 0x37, /* ed */ 0xb7, /* ee */ 0x77, /* ef */ 0xf7,
/* f0 */ 0x0f, /* f1 */ 0x8f, /* f2 */ 0x4f, /* f3 */ 0xcf,
/* f4 */ 0x2f, /* f5 */ 0xaf, /* f6 */ 0x6f, /* f7 */ 0xef,
/* f8 */ 0x1f, /* f9 */ 0x9f, /* fa */ 0x5f, /* fb */ 0xdf,
/* fc */ 0x3f, /* fd */ 0xbf, /* fe */ 0x7f, /* ff */ 0xff
};
#endif
#if defined(__BORLANDC__) && defined(__OS2__)
#pragma argsused // For the time being, for OS/2
#endif
bool UI_DisplaySurface::Invert (const UI_Stencil& dataMask, const UI_Point& p)
{
#if defined(__MS_WINDOWS__)
HDC hMem = CreateCompatibleDC (_handle);
short m = dataMask.Width(), n = dataMask.Height ();
HBITMAP mapHandle = CreateBitmap (m * 8, n, 1, 1,
dataMask.AsPtr());
HANDLE hOld = SelectObject (hMem, mapHandle);
BitBlt (_handle, p.XCoord(), p.YCoord(), m, n, hMem, 0, 0, SRCINVERT);
SelectObject (hMem, hOld);
DeleteObject (mapHandle);
DeleteDC (hMem);
#elif defined(__X_MOTIF__)
Display *dpy = XtDisplay (_client);
Window win = XtWindow (_client);
UI_Stencil data = dataMask;
short m = data.Width(), n = data.Height ();
if (BitmapBitOrder (dpy) == LSBFirst) {
// Reverse the bit order in each byte
for (short i = 0; i < m; i++)
for (short j = 0; j < n; j++) {
char& c = data.Byte (j, i);
c = Reverse [(uchar) c];
}
}
XGCValues values;
XtGCMask mask = GCForeground | GCBackground | GCFunction
| GCSubwindowMode | GCFillStyle;
GC gc = _handle;
XGCValues oldValues;
XGetGCValues (dpy, gc, mask, &oldValues);
Pixmap stipple = XCreateBitmapFromData (dpy, win, data.AsPtr(), m, n);
if (!stipple)
return FALSE;
values.foreground = 1;
values.background = 0;
values.function = GXxor;
values.subwindow_mode = IncludeInferiors;
values.fill_style = FillOpaqueStippled;
XChangeGC (dpy, gc, mask, &values);
XSetStipple (dpy, gc, stipple);
XSetTSOrigin (dpy, gc, p.XCoord(), p.YCoord());
XFillRectangle (dpy, win, gc, p.XCoord(), p.YCoord(), m, n);
XChangeGC (dpy, gc, mask, &oldValues);
XFreePixmap (dpy, stipple);
#else
NotImplemented ("Invert");
#endif
return TRUE;
}
#if defined(__BORLANDC__)
#pragma argsused // For the time being
#endif
bool UI_DisplaySurface::Draw (const UI_Bitmap& map, const UI_Stencil& s,
const UI_Point& p)
{
#if defined(__MS_WINDOWS__)
#elif defined(__X_MOTIF__)
Display* dpy = XtDisplay (_client);
Window win = XtWindow (_client);
int format = DefaultDepth (dpy, DefaultScreen(dpy)) == 1 ? XYPixmap
: ZPixmap;
struct _XImage* r, *q;
long w = map.Width();
long h = map.Height();
r = XGetImage (dpy, win, p.XCoord(), p.YCoord(), w, h, AllPlanes, format);
q = map.Handle();
for (long i = 0; i < h; i++) {
for (long j = 0; j < w; j++)
if (s.Bit (i, j))
XPutPixel (r, i, j, XGetPixel (q, i, j));
}
XPutImage (dpy, win, _handle, r, 0, 0, p.XCoord(), p.YCoord(), w, h);
#else
NotImplemented ("Invert");
#endif
return TRUE;
}
bool UI_DisplaySurface::InvertRectangle (const UI_Rectangle& r)
{
#if defined(__MS_WINDOWS__)
RECT rect = r.AsMSRect ();
InvertRect (_handle, &rect);
return TRUE;
#elif defined(__OS2__)
long height = DrawingArea ().Height();
RECTL rect;
rect.xLeft = r.Left();
rect.yBottom = height - r.Bottom () - 1;
rect.xRight = r.Right();
rect.yTop = height - 1 - r.Top ();
return WinInvertRect (_handle, &rect);
// There must be a Gpi function for this, but I don't know which.
#elif defined(__X_MOTIF__)
Display *dpy = XtDisplay (_client);
Window win = XtWindow (_client);
long width = r.Width();
long height = r.Height();
long left = r.Left ();
long right = r.Right ();
long top = r.Top ();
long bottom = r.Bottom ();
int scr = DefaultScreen(dpy);
// This code is courtesy of Rajesh Chandran, Jan 25, 1995
XGCValues values;
XtGCMask mask = GCForeground|GCBackground|GCFunction|GCSubwindowMode;
GC gc;
Region region;
XPoint points[5];
points[0].x = left;
points[0].y = top;
points[1].x = right - 1;
points[1].y = top;
points[2].x = right - 1;
points[2].y = bottom;
points[3].x = left;
points[3].y = bottom;
points[4].x = left;
points[4].y = top;
region = XPolygonRegion (points, 5, WindingRule);
values.foreground = 1;
values.background = 0;
values.function = GXxor;
values.subwindow_mode = IncludeInferiors;
gc = _handle;
XGCValues oldValues;
XGetGCValues (dpy, gc, mask, &oldValues);
XChangeGC (dpy, gc, mask, &values);
XSetRegion (dpy, gc, region);
XDestroyRegion (region);
XFillRectangle (dpy, win, gc, r.Left(), r.Top(), width, height);
XChangeGC (dpy, gc, mask, &oldValues);
XSetClipMask (dpy, gc, None);
// The following code uses a more elaborate approach of inverting the
// image pixel by pixel. It is much slower, but illustrates the idea, so
// is retained here but commented out.
// int format = DefaultDepth (dpy, scr) == 1 ? XYPixmap : ZPixmap;
// XImage* handle = XGetImage (dpy, win, r.Left(), r.Top(), width, height,
// AllPlanes, format);
// // Now iterate over the image and complement all its cells
//
// CL_IntIntMap tmpColorMap;
// // This map is used to speed up the loops below, avoiding XQueryColor
// // and XAllocColor calls if we already know what the pixel values are.
// for (long i = 0; i < width; i++) {
// for (long j = 0; j < height; j++) {
// XColor xcolor;
// xcolor.pixel = XGetPixel (handle, i, j);
// long outputPixel = tmpColorMap[xcolor.pixel] - 1;
// // -----------------------------------------^^^^
// // We subtract one here, and add 1 below, because we want the
// // values of the map to be positive and nonzero. Otherwise a
// // lookup failure (which returns a 0) would be indistinguishable
// // from a zero pixel value for outputPixel. Of course, we could
// // use the Map's IncludesKey method, but that would call for two
// // map lookups instead of one.
// if (outputPixel < 0) { // Lookup failed
// long inputPixel = xcolor.pixel;
// XQueryColor (dpy, DefaultColormap (dpy, scr), &xcolor);
// xcolor.green = 65535L - xcolor.green;
// xcolor.blue = 65535L - xcolor.blue;
// xcolor.red = 65535L - xcolor.red;
// XAllocColor (dpy, DefaultColormap (dpy, scr), &xcolor);
// outputPixel = xcolor.pixel;
// tmpColorMap.Add (inputPixel, outputPixel + 1);
// // --------------------------------------^^^ see above
// // comment
// }
// XPutPixel (handle, i, j, outputPixel);
// }
// }
//
// // Finally, output the image
// XPutImage (dpy, win, _handle, handle, 0, 0, r.Left(), r.Top(),
// width, height);
return TRUE;
#endif
}
#if defined(__X_MOTIF__)
void UI_DisplaySurface::_DrawFontLine (const UI_Point& p1,
const UI_Point& p2)
{
ColorSaver save (_client, _pen->Color());
short width = _pen->Thickness ();
_pen->Thickness (2);
DrawLine (p1, p2);
_pen->Thickness (width);
}
#endif
void UI_DisplaySurface::DrawPoint (const UI_Point& p, const UI_Color& color)
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::DrawPoint (p, color);
#elif defined(__X_MOTIF__)
ColorSaver save (_client, color);
Display* dpy = XtDisplay (_TheApplication->Controller().ShellWidget());
XDrawPoint (dpy, XtWindow (_client), _handle, p.XCoord(), p.YCoord());
#endif
}
void UI_DisplaySurface::WriteString
(const CL_String& str, const UI_Rectangle& tRect, UI_TextStyle tStyle)
{
#if defined (__MS_WINDOWS__) || defined(__OS2__)
UI_DrawingSurface::WriteString (str, tRect, tStyle);
#elif defined(__X_MOTIF__)
if (!_font)
return;
Display* dpy = XtDisplay (_client);
XFontStruct* fstr = (XFontStruct*) _font->NativeFontStruct ();
if (!fstr)
return; // Failed
ColorSaver save (_client, _pen->Color());
short width = _font->TextWidth (str);
UI_Point p;
switch (tStyle) {
case UIText_Center:
p = tRect.Origin() + UI_Point ((tRect.Width() - width)/2, 0);
break;
case UIText_Left:
p = tRect.Origin ();
break;
case UIText_Right:
p = tRect.TopRight() - UI_Point (width, 0);
break;
};
XDrawString (dpy, XtWindow (_client), _handle, p.XCoord (),
p.YCoord () + fstr->ascent,
(const char*) str, str.Length ());
if (_font->Underline ()) {
// XGetFontProperty (fstr, XA_UNDERLINE_POSITION, &val); :-(
// Since the XA_UNDERLINE_POSITION property is not reliable, we
// resort to ad-hoc measures.
UI_Point leftEnd = p + UI_Point (0, fstr->ascent + fstr->descent);
UI_Point rightEnd = leftEnd + UI_Point (width, 0);
_DrawFontLine (leftEnd, rightEnd);
}
if (_font->StrikeOut ()) {
int direction, ascent, descent;
XCharStruct cstr;
XTextExtents (fstr, "g", 1, &direction, &ascent, &descent, &cstr);
// XGetFontProperty (fstr, XA_STRIKEOUT_ASCENT, &ascent);
// XGetFontProperty (fstr, XA_STRIKEOUT_DESCENT, &descent);
UI_Point leftEnd = p + UI_Point (0, fstr->ascent - cstr.ascent/2);
UI_Point rightEnd = leftEnd + UI_Point (width, 0);
_DrawFontLine (leftEnd, rightEnd);
}
#endif
}
short UI_DisplaySurface::TextWidth (const char* s) const
{
#if defined(__MS_WINDOWS__) || defined(__OS2__)
return UI_DrawingSurface::TextWidth (s);
#elif defined (__X_MOTIF__)
return _font ? _font->TextWidth (s) : 0;
#endif
}
UI_Font& UI_DisplaySurface::Font ()
{
return _client.Font();
}
UI_VisualObject& UI_DisplaySurface::Client () const
{
return _client;
}