Skip to content

Commit 6b156e8

Browse files
committed
SDL cursor support
1 parent 4eac2a1 commit 6b156e8

3 files changed

Lines changed: 172 additions & 3 deletions

File tree

kauai/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ add_library(KauaiGui
336336
"${PROJECT_SOURCE_DIR}/kauai/src/appb.cpp"
337337
"${PROJECT_SOURCE_DIR}/kauai/src/clok.cpp"
338338
"${PROJECT_SOURCE_DIR}/kauai/src/cmd.cpp"
339-
"${PROJECT_SOURCE_DIR}/kauai/src/cursor.cpp"
340339
"${PROJECT_SOURCE_DIR}/kauai/src/gfx.cpp"
341340
"${PROJECT_SOURCE_DIR}/kauai/src/gob.cpp"
342341
"${PROJECT_SOURCE_DIR}/kauai/src/mbmpgui.cpp"
@@ -367,6 +366,7 @@ if (3DMM_GUI STREQUAL "Win32")
367366
${PROJECT_SOURCE_DIR}/kauai/src/menuwin.cpp
368367
${PROJECT_SOURCE_DIR}/kauai/src/gfxwin.cpp
369368
${PROJECT_SOURCE_DIR}/kauai/src/gobwin.cpp
369+
${PROJECT_SOURCE_DIR}/kauai/src/cursor.cpp
370370
)
371371
elseif(3DMM_GUI STREQUAL "SDL")
372372
target_sources(
@@ -377,6 +377,7 @@ elseif(3DMM_GUI STREQUAL "SDL")
377377
${PROJECT_SOURCE_DIR}/kauai/src/gfxsdl.cpp
378378
${PROJECT_SOURCE_DIR}/kauai/src/gobsdl.cpp
379379
${PROJECT_SOURCE_DIR}/kauai/src/fontsdl.cpp
380+
${PROJECT_SOURCE_DIR}/kauai/src/cursorsdl.cpp
380381
)
381382
else()
382383
message(FATAL_ERROR "Invalid GUI specified: ${3DMM_GUI}")

kauai/src/cursor.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ class CURS : public CURS_PAR
4444

4545
private:
4646
protected:
47-
#ifdef WIN
47+
#ifdef KAUAI_WIN32
4848
HCRS _hcrs;
49-
#endif // WIN
49+
#endif // KAUAI_WIN32
5050
#ifdef MAC
5151
Cursor _crs;
5252
#endif // MAC
53+
#ifdef KAUAI_SDL
54+
SDL_Cursor *_crs;
55+
#endif // KAUAI_SDL
5356

5457
CURS(void)
5558
{

kauai/src/cursorsdl.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/* Copyright (c) Microsoft Corporation.
2+
Licensed under the MIT License. */
3+
4+
/***************************************************************************
5+
Author: Ben Stone
6+
Project: Kauai
7+
Reviewed:
8+
9+
SDL Mouse cursor support
10+
11+
***************************************************************************/
12+
#include "frame.h"
13+
ASSERTNAME
14+
15+
RTCLASS(CURS)
16+
17+
/***************************************************************************
18+
Destructor for the cursor class.
19+
***************************************************************************/
20+
CURS::~CURS(void)
21+
{
22+
SDL_FreeCursor(_crs);
23+
_crs = pvNil;
24+
}
25+
26+
/***************************************************************************
27+
Read a cursor out of a CRF.
28+
***************************************************************************/
29+
bool CURS::FReadCurs(PCRF pcrf, CTG ctg, CNO cno, PBLCK pblck, PBACO *ppbaco, int32_t *pcb)
30+
{
31+
PGG pggcurf;
32+
int32_t icurf, icurfBest;
33+
CURF curf;
34+
int16_t bo;
35+
int32_t dxp, dyp, dzpT;
36+
int32_t dzpBest;
37+
int32_t cbRowDst, cbRowSrc, cbT;
38+
uint8_t *prgb, *qrgb;
39+
PCURS pcurs = pvNil;
40+
41+
const uint8_t *prgbAnd = pvNil;
42+
const uint8_t *prgbXor = pvNil;
43+
44+
*pcb = SIZEOF(CURS);
45+
if (pvNil == ppbaco)
46+
return fTrue;
47+
48+
if (pvNil == (pggcurf = GG::PggRead(pblck, &bo)) || pggcurf->IvMac() == 0)
49+
{
50+
ReleasePpo(&pggcurf);
51+
return fFalse;
52+
}
53+
54+
// SDL cursor size is always 32 pixels
55+
dxp = dyp = 32;
56+
57+
icurfBest = 0;
58+
dzpBest = klwMax;
59+
for (icurf = 0; icurf < pggcurf->IvMac(); icurf++)
60+
{
61+
pggcurf->GetFixed(icurf, &curf);
62+
if (kboOther == bo)
63+
SwapBytesBom(&curf, kbomCurf);
64+
if (curf.dxp > dxp || curf.dyp > dyp || curf.curt != curtMonochrome ||
65+
pggcurf->Cb(icurf) != (int32_t)curf.dxp * curf.dyp / 4)
66+
{
67+
continue;
68+
}
69+
70+
dzpT = (dxp - curf.dxp) + (dyp - curf.dyp);
71+
if (dzpBest > dzpT)
72+
{
73+
icurfBest = icurf;
74+
if (dzpT == 0)
75+
break;
76+
dzpBest = dzpT;
77+
}
78+
}
79+
AssertIn(icurfBest, 0, pggcurf->IvMac());
80+
pggcurf->GetFixed(icurfBest, &curf);
81+
if (kboOther == bo)
82+
SwapBytesBom(&curf, kbomCurf);
83+
cbRowSrc = LwRoundAway(LwDivAway(curf.dxp, 8), 2);
84+
cbRowDst = LwRoundAway(LwDivAway(dxp, 8), 2);
85+
86+
if (!FAllocPv((void **)&prgb, LwMul(cbRowDst, 2 * dyp), fmemClear, mprNormal))
87+
goto LFail;
88+
89+
if (pvNil == (pcurs = NewObj CURS))
90+
goto LFail;
91+
92+
qrgb = (uint8_t *)pggcurf->QvGet(icurfBest);
93+
cbT = LwMin(cbRowSrc, cbRowDst);
94+
95+
// Convert the cursor to SDL's cursor format
96+
prgbAnd = qrgb;
97+
prgbXor = qrgb + LwMul(curf.dyp, cbRowSrc);
98+
99+
for (dzpT = 0; dzpT < LwMin(dyp, curf.dyp); dzpT++)
100+
{
101+
uint8_t *prgbDstData = prgb + LwMul(dzpT, cbRowSrc);
102+
uint8_t *prgbDstMask = prgb + LwMul(dyp + dzpT, cbRowDst);
103+
104+
for (int32_t xp = 0; xp < LwDivAway(dxp, 8); xp++)
105+
{
106+
for (int32_t ibit = 0; ibit < 8; ibit++)
107+
{
108+
uint32_t mask = 0x80 >> ibit;
109+
uint8_t bAnd = *prgbAnd & mask;
110+
uint8_t bXor = *prgbXor & mask;
111+
112+
if (!bAnd && !bXor)
113+
{
114+
// Win32: both zero: black
115+
// SDL: data=1, mask=1: black
116+
*prgbDstData |= mask;
117+
*prgbDstMask |= mask;
118+
}
119+
else if (!bAnd && bXor)
120+
{
121+
// Win32: XOR only: white
122+
// data=0, mask=1: white
123+
*prgbDstData &= ~mask;
124+
*prgbDstMask |= mask;
125+
}
126+
else if (bAnd && !bXor)
127+
{
128+
// Win32: AND only: screen (transparent)
129+
// SDL: data=0, mask=0: transparent
130+
*prgbDstData &= ~mask;
131+
*prgbDstMask &= ~mask;
132+
}
133+
else if (bAnd && bXor)
134+
{
135+
// Win32: AND and XOR: Reverse screen
136+
// data=1, mask=0: inverted color if possible, black if not.
137+
*prgbDstData |= mask;
138+
*prgbDstMask &= ~mask;
139+
}
140+
}
141+
prgbAnd++;
142+
prgbXor++;
143+
prgbDstData++;
144+
prgbDstMask++;
145+
}
146+
}
147+
148+
pcurs->_crs = SDL_CreateCursor(prgb, prgb + LwMul(dxp, cbRowDst), dxp, dyp, curf.xp, curf.yp);
149+
Assert(pcurs->_crs != pvNil, "SDL_CreateCursor failed");
150+
151+
LFail:
152+
FreePpv((void **)&prgb);
153+
ReleasePpo(&pggcurf);
154+
155+
*ppbaco = pcurs;
156+
return pvNil != pcurs;
157+
}
158+
159+
/***************************************************************************
160+
Set the cursor.
161+
***************************************************************************/
162+
void CURS::Set(void)
163+
{
164+
SDL_SetCursor(_crs);
165+
}

0 commit comments

Comments
 (0)