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.

289 lines
7.4 KiB

  1. #ifndef _INTMAP_HPP
  2. #define _INTMAP_HPP
  3. ///// IntMap - sparse array indexed by int value
  4. //
  5. // Used to store tables indexed by Unicode codepoint or
  6. // by glyph index.
  7. //
  8. // !!! This implementation maps values in the range [0..1114112]
  9. // which is the subset of ISO 10664 addressable (using surrogates)
  10. // in Unicode UTF16.
  11. //
  12. // (1114112 is 17*65536)
  13. template <class C> class IntMap {
  14. public:
  15. IntMap() : Status(Ok)
  16. {
  17. if (UsageCount == 0)
  18. {
  19. // Note that this is not thread safe.
  20. // Currently all font/text APIs are protected by a single critical
  21. // section.
  22. if (!EmptyPage)
  23. EmptyPage = new C[256];
  24. if (!EmptyPage)
  25. {
  26. Status = OutOfMemory;
  27. return;
  28. }
  29. for (INT i=0; i<256; i++)
  30. {
  31. EmptyPage[i] = 0;
  32. }
  33. if (!EmptyPlane)
  34. EmptyPlane = new C*[256];
  35. if (!EmptyPlane)
  36. {
  37. Status = OutOfMemory;
  38. return;
  39. }
  40. for (INT i=0; i<256; i++)
  41. {
  42. EmptyPlane[i] = EmptyPage;
  43. }
  44. }
  45. ++UsageCount;
  46. for (INT i=0; i<17; i++)
  47. {
  48. map[i] = EmptyPlane;
  49. }
  50. #if DBG
  51. ASSERT(map[0][0x05][0x31] == 0);
  52. for (INT i=0; i<256; i++)
  53. {
  54. ASSERT(EmptyPlane[i] == EmptyPage);
  55. ASSERT(EmptyPage[i] == 0);
  56. }
  57. #endif
  58. }
  59. ~IntMap()
  60. {
  61. if (Status != Ok)
  62. return;
  63. for (INT i=0; i<17; i++)
  64. {
  65. if (map[i] != EmptyPlane)
  66. {
  67. for (INT j=0; j<256; j++)
  68. {
  69. if (map[i][j] != EmptyPage)
  70. {
  71. delete map[i][j];
  72. }
  73. }
  74. delete map[i];
  75. }
  76. }
  77. --UsageCount;
  78. if (UsageCount == 0)
  79. {
  80. // Release memory used by static empty pages for IntMap<C>
  81. delete [] EmptyPlane, EmptyPlane = 0;
  82. delete [] EmptyPage, EmptyPage = 0;
  83. }
  84. }
  85. // Insert value for single codepoint
  86. GpStatus Insert(INT i, const C &v)
  87. {
  88. ASSERT(Status == Ok);
  89. ASSERT(i < 17*65536);
  90. ASSERT(map[i>>16] != NULL);
  91. if (map[i>>16] == EmptyPlane)
  92. {
  93. map[i>>16] = new C*[256];
  94. if (!map[i>>16])
  95. {
  96. map[i>>16] = EmptyPlane;
  97. return OutOfMemory;
  98. }
  99. for (INT j=0; j<256; j++)
  100. {
  101. map [i>>16] [j] = EmptyPage;
  102. }
  103. }
  104. ASSERT(map [i>>16] [i>>8 & 0xff] != NULL);
  105. if (map [i>>16] [i>>8 & 0xff] == EmptyPage)
  106. {
  107. if (!(map [i>>16] [i>>8 & 0xff] = new C[256]))
  108. {
  109. map [i>>16] [i>>8 & 0xff] = EmptyPage;
  110. return OutOfMemory;
  111. }
  112. memcpy(map [i>>16] [i>>8 & 0xff], EmptyPage, sizeof(C) * 256);
  113. }
  114. map [i>>16] [i>>8 & 0xff] [i & 0xff] = v;
  115. return Ok;
  116. }
  117. //// Lookup single codepoint
  118. C& Lookup(INT i) const
  119. {
  120. ASSERT(Status == Ok);
  121. ASSERT(i < 17*65536);
  122. return map [i>>16] [i>>8 & 0xff] [i & 0xff];
  123. }
  124. //// Lookup codepoint expressed as surrogate pair
  125. C& Lookup(UINT16 h, UINT16 l) const
  126. {
  127. ASSERT(Status == Ok);
  128. ASSERT((h & 0xFC00) == 0xD800);
  129. ASSERT((l & 0xFC00) == 0xDC00);
  130. INT i = 0x10000 + (((h & 0x3ff) << 10) | (l & 0x3ff));
  131. ASSERT(i < 17*65536);
  132. return map [i>>16] [i>>8 & 0xff] [i & 0xff];
  133. }
  134. //// Lookup array of 16 bit unsigned values
  135. void Lookup(
  136. const UINT16 *source,
  137. INT sourceCount,
  138. C *values
  139. ) const
  140. {
  141. ASSERT(Status == Ok);
  142. for (INT i=0; i<sourceCount; i++)
  143. {
  144. values[i] = Lookup(source[i]);
  145. }
  146. }
  147. //// Lookup 16 bit Unicode character string with surrogate interpretation
  148. //
  149. // If the oneToOne parameter is set, surrogate pairs are translated to
  150. // the correct glyph, followed by 0xffff so as to generate the same
  151. // number of glyphs as codepoints.
  152. void LookupUnicode(
  153. const WCHAR *characters,
  154. INT characterCount,
  155. C *values,
  156. UINT32 *valueCount,
  157. BOOL oneToOne // Glyph count == character count
  158. ) const
  159. {
  160. ASSERT(Status == Ok);
  161. ASSERT(characterCount >= 0);
  162. INT ci = 0; // Character array index
  163. INT vi = 0; // Value array index
  164. while ( ci < characterCount)
  165. {
  166. // Efficient loop through non-surrogates
  167. while ( ci < characterCount
  168. && (characters[ci] & 0xF800) != 0xD800)
  169. {
  170. values[vi++] = Lookup(characters[ci++]);
  171. }
  172. // Loop through surrogates
  173. while ( ci < characterCount
  174. && (characters[ci] & 0xF800) == 0xD800)
  175. {
  176. // Fast loop through valid surrogate pairs
  177. while ( ci+1 < characterCount
  178. && (characters[ci] & 0xFC00) == 0xD800
  179. && (characters[ci+1] & 0xFC00) == 0xDC00)
  180. {
  181. values[vi++] = Lookup(characters[ci], characters[ci+1]);
  182. if (oneToOne)
  183. {
  184. values[vi++] = 0xffff;
  185. }
  186. ci += 2;
  187. }
  188. // Either
  189. // 1. We came to the end of the run of surrogate codepoints
  190. // 2. There's one or more high surrogates with no matching low surrogates
  191. // 3. There's one or more low surrogates
  192. // Handle any misplaced high surrogates as normal codepoints
  193. while ( ci < characterCount
  194. && (characters[ci] & 0xFC00) == 0xD800
  195. && ( ci+1 >= characterCount
  196. || (characters[ci+1] & 0xFC00) != 0xDC00))
  197. {
  198. values[vi++] = Lookup(characters[ci++]);
  199. }
  200. // Handle any misplaced low surrogates as normal codepoints
  201. while ( ci < characterCount
  202. && (characters[ci] & 0xFC00) == 0xDC00)
  203. {
  204. values[vi++] = Lookup(characters[ci++]);
  205. }
  206. }
  207. }
  208. if (valueCount)
  209. {
  210. *valueCount = vi;
  211. }
  212. else
  213. {
  214. ASSERT(vi == characterCount);
  215. }
  216. }
  217. GpStatus GetStatus() const
  218. {
  219. return Status;
  220. }
  221. private:
  222. GpStatus Status;
  223. C **map[17];
  224. static C **EmptyPlane;
  225. static C *EmptyPage;
  226. static LONG UsageCount;
  227. };
  228. template<class C> LONG IntMap<C>::UsageCount = 0; // Tracks static memory usage
  229. template<class C> C **IntMap<C>::EmptyPlane;
  230. template<class C> C *IntMap<C>::EmptyPage;
  231. #endif _INTMAP_HPP