Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

502 lines
13 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Contains simple engine-wide prototypes and helper functions and
  8. * compile time flags.
  9. *
  10. * History:
  11. *
  12. * 12/04/1998 davidx
  13. * Created it.
  14. *
  15. \**************************************************************************/
  16. #ifndef _ENGINE_HPP
  17. #define _ENGINE_HPP
  18. //--------------------------------------------------------------------------
  19. // GDI+ internal prototypes
  20. //--------------------------------------------------------------------------
  21. class GpDevice;
  22. struct DpPen;
  23. USHORT
  24. GetLanguageID();
  25. BOOL
  26. InitSystemFontsDirs(VOID); //WCHAR **system_dir, WCHAR **fonts_dir);
  27. UINT32
  28. Crc32(
  29. IN const VOID* buf,
  30. IN UINT size,
  31. IN UINT32 checksum
  32. );
  33. // Get the ceiling the same way the rasterizer does
  34. inline INT
  35. RasterizerCeiling(
  36. REAL value
  37. )
  38. {
  39. return GpFix4Ceiling(GpRealToFix4(value));
  40. }
  41. GpStatus
  42. BoundsFToRect(
  43. const GpRectF *rectF,
  44. GpRect * rect
  45. );
  46. /*
  47. REAL
  48. GetPenDelta(
  49. const DpPen* pen,
  50. const GpMatrix* matrix,
  51. REAL dpiX,
  52. REAL dpiY
  53. );
  54. */
  55. REAL GetDeviceWidth(
  56. REAL width,
  57. GpUnit unit,
  58. REAL dpi);
  59. VOID
  60. TransformBounds(
  61. const GpMatrix *matrix,
  62. REAL x0,
  63. REAL y0,
  64. REAL x1,
  65. REAL y1,
  66. GpRectF *bounds
  67. );
  68. LONG
  69. WINAPI
  70. InterlockedCompareExchangeWin95(
  71. IN OUT PLONG destination,
  72. IN LONG exchange,
  73. IN LONG comperand
  74. );
  75. LONG
  76. WINAPI
  77. InterlockedIncrementWin95(
  78. IN LPLONG lpAddend
  79. );
  80. LONG
  81. WINAPI
  82. InterlockedDecrementWin95(
  83. IN LPLONG lpAddend
  84. );
  85. BOOL
  86. APIENTRY
  87. GdiIsMetaPrintDCWin9x(
  88. HDC hdc
  89. );
  90. //--------------------------------------------------------------------------
  91. // The following macro is useful for checking if the creation of an
  92. // internal object succeeds.
  93. //
  94. // We don't want to use exceptions to allow a constructor to indicate failure,
  95. // so the object has to contain an 'IsValid()' member that returns TRUE if
  96. // the object was successfully allocated. But then the caller has to write
  97. // the following code:
  98. //
  99. // p = new Object();
  100. // if (!p || !p->IsValid())
  101. // {
  102. // delete p;
  103. // ...
  104. //
  105. // The following macro can be used to replace this with:
  106. //
  107. // p = new Object();
  108. // if (!CheckValid(p))
  109. // {
  110. // ...
  111. //
  112. // !!!
  113. // Note that CheckValid sets the input parameter to NULL
  114. // when the return value is FALSE.
  115. //
  116. //--------------------------------------------------------------------------
  117. template <class T>
  118. inline BOOL
  119. CheckValid(
  120. T*& p
  121. )
  122. {
  123. if (p && p->IsValid())
  124. {
  125. return TRUE;
  126. }
  127. else
  128. {
  129. delete p;
  130. p = NULL;
  131. return FALSE;
  132. }
  133. }
  134. //--------------------------------------------------------------------------
  135. // Name dynamic array types
  136. //--------------------------------------------------------------------------
  137. typedef DynArray<GpPointF> DynPointFArray;
  138. typedef DynArray<GpPoint> DynPointArray;
  139. typedef DynArray<BYTE> DynByteArray;
  140. typedef DynArray<INT> DynIntArray;
  141. typedef DynArray<REAL> DynRealArray;
  142. typedef DynArray<VOID*> DynPointerArray;
  143. //--------------------------------------------------------------------------
  144. // Raw critical section object
  145. // The Initialize function can throw.
  146. //--------------------------------------------------------------------------
  147. class GpSemaphore
  148. {
  149. private:
  150. CRITICAL_SECTION CriticalSection;
  151. BOOL Initialized;
  152. public:
  153. GpSemaphore()
  154. {
  155. Initialized = FALSE;
  156. }
  157. VOID
  158. Initialize(
  159. VOID
  160. )
  161. {
  162. if (!Initialized)
  163. {
  164. // The caller has to have a Try_Except around us.
  165. __try
  166. {
  167. InitializeCriticalSection(&CriticalSection);
  168. }
  169. __except(EXCEPTION_CONTINUE_SEARCH)
  170. {
  171. }
  172. Initialized = TRUE;
  173. }
  174. }
  175. VOID
  176. Uninitialize(
  177. VOID
  178. );
  179. VOID
  180. Lock(
  181. VOID
  182. )
  183. {
  184. ASSERT(Initialized);
  185. EnterCriticalSection(&CriticalSection);
  186. }
  187. VOID
  188. Unlock(
  189. VOID
  190. )
  191. {
  192. ASSERT(Initialized);
  193. LeaveCriticalSection(&CriticalSection);
  194. }
  195. BOOL
  196. IsLocked(
  197. VOID
  198. );
  199. BOOL
  200. IsLockedByCurrentThread(
  201. VOID
  202. );
  203. };
  204. //------------------------------------------------------------------------
  205. // FillMemoryInt32 - Fill an INT32 array with the specified value
  206. // CopyMemoryInt32 - Copy INT32 values from one array to another
  207. //------------------------------------------------------------------------
  208. inline VOID
  209. FillMemoryInt32(
  210. VOID* buf,
  211. INT count,
  212. INT32 val
  213. )
  214. {
  215. INT32* p = (INT32*) buf;
  216. while (count-- > 0)
  217. *p++ = val;
  218. }
  219. inline VOID
  220. CopyMemoryInt32(
  221. VOID* dst,
  222. const VOID* src,
  223. INT count
  224. )
  225. {
  226. INT32* d = (INT32*) dst;
  227. const INT32* s = (const INT32*) src;
  228. while (count-- > 0)
  229. *d++ = *s++;
  230. }
  231. //------------------------------------------------------------------------
  232. // CompareExchangeLong_Ptr - Perform an interlocked compare-exchange
  233. // on a LONG_PTR. Unfortunately, Win95 does not export
  234. // InterlockedCompareExchange, so on that platform we have
  235. // to create our own. But on NT, we CANNOT roll our own, because
  236. // of MP and NT64 issues.
  237. //
  238. // This method should be called instead of calling through the
  239. // Globals::InterlockedCompareExchangeFunction directly, because
  240. // on Alpha machines, Globals::InterlockedCompareExchangeFunction does
  241. // NOT get initialized.
  242. //------------------------------------------------------------------------
  243. inline LONG_PTR
  244. CompareExchangeLong_Ptr(
  245. LONG_PTR *destination,
  246. LONG_PTR exchange,
  247. LONG_PTR comperand
  248. )
  249. {
  250. #if defined(_X86_)
  251. return InterlockedCompareExchange(destination,
  252. exchange,
  253. comperand);
  254. #else
  255. return (LONG_PTR)InterlockedCompareExchangePointer(
  256. (PVOID *)destination,
  257. (PVOID)exchange,
  258. (PVOID)comperand);
  259. #endif
  260. }
  261. //------------------------------------------------------------------------
  262. // CompareExchangePointer - Perform an interlocked compare-exchange
  263. // on a pointer. Unfortunately, Win95 does not export
  264. // InterlockedCompareExchangePointer, so on that platform we have
  265. // to create our own. But on NT, we CANNOT roll our own, because
  266. // of MP and NT64 issues.
  267. //------------------------------------------------------------------------
  268. inline VOID*
  269. CompareExchangePointer(
  270. VOID** destination,
  271. VOID* exchange,
  272. VOID* comperand
  273. )
  274. {
  275. #if defined(_X86_)
  276. return((VOID*) InterlockedCompareExchange((LONG*) destination,
  277. (LONG) exchange,
  278. (LONG) comperand));
  279. #else
  280. return(InterlockedCompareExchangePointer(destination,
  281. exchange,
  282. comperand));
  283. #endif
  284. }
  285. //--------------------------------------------------------------------------
  286. // This routine retrieves a quick, pre-allocated region from a one-deep
  287. // cache. Note that the contents will be random. This call is intended
  288. // largely for GDI API calls such as GetRandomRgn that require a pre-created
  289. // region.
  290. //
  291. // NOTE: This can return a NULL region handle.
  292. //--------------------------------------------------------------------------
  293. inline
  294. HRGN GetCachedGdiRegion(
  295. VOID
  296. )
  297. {
  298. HRGN regionHandle = Globals::CachedGdiRegion;
  299. // If the Globals::CachedGdiRegion is NULL, that means that someone
  300. // else has the cached region, so we create a new one.
  301. // It is possible during multi thread access for us to create a region
  302. // when it's not strictly necessary --- i.e. a thread releases the cached
  303. // region when this thread is between the above assignment and the next
  304. // if statement, but that's only non-optimal and we'll work correctly
  305. // under those circumstances.
  306. if ((regionHandle == NULL) ||
  307. (CompareExchangePointer(
  308. (VOID**) &Globals::CachedGdiRegion,
  309. NULL,
  310. (VOID*) regionHandle) != regionHandle
  311. )
  312. )
  313. {
  314. regionHandle = CreateRectRgn(0, 0, 1, 1);
  315. }
  316. return(regionHandle);
  317. }
  318. //--------------------------------------------------------------------------
  319. // This routine releases a region to the one-deep cache.
  320. //--------------------------------------------------------------------------
  321. inline
  322. VOID ReleaseCachedGdiRegion(
  323. HRGN regionHandle
  324. )
  325. {
  326. // Note that 'regionHandle' may be NULL at this point if the
  327. // CreateRectRgn failed, but that's okay:
  328. if (CompareExchangePointer((VOID**) &Globals::CachedGdiRegion,
  329. (VOID*) regionHandle,
  330. NULL) != NULL)
  331. {
  332. DeleteObject(regionHandle);
  333. }
  334. }
  335. inline
  336. HDC GetCleanHdc(
  337. HWND hwnd
  338. )
  339. {
  340. // Use GetDCEx(DCX_CACHE) to get a nice clean DC (not a CS_OWNDC).
  341. // Note that with GetDCEx we have to explicitly respect the window's
  342. // clipping styles. We stole this little bit of logic straight from
  343. // ntuser\kernel\dc.c for the DCX_USESTYLE case:
  344. DWORD getDcFlags = DCX_CACHE;
  345. LONG classStyle = GetClassLongA(hwnd, GCL_STYLE);
  346. LONG windowStyle = GetWindowLongA(hwnd, GWL_STYLE);
  347. if (classStyle & CS_PARENTDC)
  348. getDcFlags |= DCX_PARENTCLIP;
  349. if (windowStyle & WS_CLIPCHILDREN)
  350. getDcFlags |= DCX_CLIPCHILDREN;
  351. if (windowStyle & WS_CLIPSIBLINGS)
  352. getDcFlags |= DCX_CLIPSIBLINGS;
  353. // Minimized windows never exclude their children.
  354. if (windowStyle & WS_MINIMIZE)
  355. getDcFlags &= ~DCX_CLIPCHILDREN;
  356. return GetDCEx(hwnd, NULL, getDcFlags);
  357. }
  358. inline INT
  359. GetIntDistance(
  360. POINT & p1,
  361. POINT & p2
  362. )
  363. {
  364. double dx = (double)(p2.x - p1.x);
  365. double dy = (double)(p2.y - p1.y);
  366. REAL distance = (REAL)sqrt((dx * dx) + (dy * dy));
  367. return GpRound(distance);
  368. }
  369. inline REAL
  370. GetDistance(
  371. GpPointF & p1,
  372. GpPointF & p2
  373. )
  374. {
  375. double dx = (double)p2.X - p1.X;
  376. double dy = (double)p2.Y - p1.Y;
  377. return (REAL)sqrt((dx * dx) + (dy * dy));
  378. }
  379. inline REAL
  380. GetDegreesFromRadians(double radians)
  381. {
  382. return (REAL)(radians*180.0/3.1415926535897932);
  383. }
  384. // return angle in degrees from 2 points
  385. inline REAL
  386. GetAngleFromPoints(
  387. const GpPointF & p1,
  388. const GpPointF & p2
  389. )
  390. {
  391. // Compute the angle of the line formed by p1 and p2.
  392. // Note atan2 is only undefined if dP.Y == 0.0 and dP.X == 0.0
  393. // and then it returns 0 radians.
  394. // Also, atan2 correctly computes the quadrant from the two input points.
  395. GpPointF dP = p2 - p1;
  396. double radians = atan2((double)(dP.Y), (double)(dP.X));
  397. return GetDegreesFromRadians(radians);
  398. }
  399. #define DEFAULT_RESOLUTION 96 // most display screens are set to 96 dpi
  400. //--------------------------------------------------------------------------
  401. // The following 3 functions should be used in place of GetObjectType due
  402. // to a bug on Windows 9x where an OBJ_METAFILE and another type of object
  403. // may share the same handle!
  404. //
  405. // GetObjectTypeInternal: Call this to determine any object type except
  406. // when expecting OBJ_METAFILE or OBJ_*DC.
  407. //
  408. // GetDCType: Use this when the object should be a DC,and just the type of
  409. // DC is required.
  410. //
  411. // IsValidMetaFile: OBJ_METAFILE is the special case. Use this function to
  412. // validate when OBJ_METAFILE is expected. This only means
  413. // there is a metafile with this handle. There could also
  414. // be an "aliased" object which the caller intended to be
  415. // used, so this should not be used to handle multiple
  416. // object types.
  417. //--------------------------------------------------------------------------
  418. DWORD
  419. GetObjectTypeInternal(
  420. IN HGDIOBJ handle
  421. );
  422. DWORD
  423. GetDCType(
  424. IN HDC hdc
  425. );
  426. inline
  427. BOOL
  428. IsValidMetaFile(
  429. HMETAFILE handle
  430. )
  431. {
  432. return (GetObjectType(handle) == OBJ_METAFILE);
  433. };
  434. #endif // !_ENGINE_HPP