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.

659 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. glfcach.h
  5. Abstract:
  6. PCL XL glyph cache
  7. Environment:
  8. Windows Whistler
  9. Revision History:
  10. 11/09/00
  11. Created it.
  12. --*/
  13. #include "xlpdev.h"
  14. #include "xldebug.h"
  15. #include "glyfcach.h"
  16. XLGlyphCache::
  17. XLGlyphCache(VOID)
  18. /*++
  19. Routine Description:
  20. Arguments:
  21. Return Value:
  22. Note:
  23. --*/
  24. {
  25. XL_VERBOSE(("XLGlyphCache::Ctor entry.\n"));
  26. m_ulNumberOfFonts = NULL;
  27. m_ulNumberOfArray = NULL;
  28. m_paulFontID = NULL;
  29. m_ppGlyphTable = NULL;
  30. #if DBG
  31. m_dbglevel = GLYPHCACHE;
  32. #endif
  33. }
  34. XLGlyphCache::
  35. ~XLGlyphCache(VOID)
  36. /*++
  37. Routine Description:
  38. Arguments:
  39. Return Value:
  40. Note:
  41. --*/
  42. {
  43. XL_VERBOSE(("XLGlyphCache::Dtor entry.\n"));
  44. FreeAll();
  45. }
  46. VOID
  47. XLGlyphCache::
  48. FreeAll(VOID)
  49. /*++
  50. Routine Description:
  51. Arguments:
  52. Return Value:
  53. Note:
  54. --*/
  55. {
  56. XL_VERBOSE(("XLGlyphCache::FreeAll entry.\n"));
  57. MemFree(m_paulFontID);
  58. ULONG ulI;
  59. PGLYPHTABLE *ppGlyphTable = m_ppGlyphTable;
  60. PGLYPHTABLE pGlyphTable;
  61. for (ulI = 0; ulI < m_ulNumberOfFonts; ulI++, ppGlyphTable++)
  62. {
  63. if (pGlyphTable = *ppGlyphTable)
  64. {
  65. if (pGlyphTable->pGlyphID)
  66. {
  67. MemFree(pGlyphTable->pGlyphID);
  68. }
  69. MemFree(pGlyphTable);
  70. }
  71. }
  72. if (m_ppGlyphTable)
  73. {
  74. MemFree(m_ppGlyphTable);
  75. }
  76. }
  77. HRESULT
  78. XLGlyphCache::
  79. XLCreateFont(
  80. ULONG ulFontID)
  81. /*++
  82. Routine Description:
  83. Arguments:
  84. Return Value:
  85. Note:
  86. --*/
  87. {
  88. XL_VERBOSE(("XLGlyphCache::CreateFont(ulFontiD=%d) entry.\n", ulFontID));
  89. HRESULT hResult;
  90. ULONG ulI;
  91. //
  92. // Search font ID
  93. //
  94. ULONG ulArrayID = UlSearchFontID(ulFontID);
  95. //
  96. // New font ID
  97. //
  98. if (ulArrayID == 0xFFFF || ulArrayID == m_ulNumberOfFonts)
  99. {
  100. //
  101. // Out of buffer. Increase array
  102. //
  103. if (m_ulNumberOfArray == m_ulNumberOfFonts)
  104. {
  105. if (S_OK != (hResult = IncreaseArray()))
  106. {
  107. XL_ERR(("XLGlyphCache::CreateFont IncreaseArray failed.\n"));
  108. return hResult;
  109. }
  110. }
  111. *(m_paulFontID + m_ulNumberOfFonts) = ulFontID;
  112. PGLYPHTABLE pGlyphTable;
  113. if (!(pGlyphTable = (PGLYPHTABLE)MemAllocZ(sizeof(GLYPHTABLE))))
  114. {
  115. XL_ERR(("XLGlyphCache::CreateFont MemAllocZ failed.\n"));
  116. return E_UNEXPECTED;
  117. }
  118. pGlyphTable->wFontID = (WORD)ulFontID;
  119. pGlyphTable->wGlyphNum = 0;
  120. pGlyphTable->pFirstGID = NULL;
  121. pGlyphTable->pGlyphID = NULL;
  122. pGlyphTable->dwAvailableEntries = 0;
  123. PGLYPHID pGlyphID;
  124. if (!(pGlyphID = (PGLYPHID)MemAllocZ(INIT_GLYPH_ARRAY * sizeof(GLYPHID))))
  125. {
  126. XL_ERR(("XLGlyphCache::CreateFont MemAllocZ failed.\n"));
  127. MemFree(pGlyphTable);
  128. return E_UNEXPECTED;
  129. }
  130. pGlyphTable->pGlyphID = pGlyphID;
  131. pGlyphTable->dwAvailableEntries = INIT_GLYPH_ARRAY;
  132. *(m_ppGlyphTable + m_ulNumberOfFonts) = pGlyphTable;
  133. m_ulNumberOfFonts ++;
  134. XL_VERBOSE(("XLGlyphCache::CreateFont New font ID.\n"));
  135. }
  136. return S_OK;
  137. }
  138. HRESULT
  139. XLGlyphCache::
  140. IncreaseArray(
  141. VOID)
  142. /*++
  143. Routine Description:
  144. Arguments:
  145. Return Value:
  146. Note:
  147. --*/
  148. {
  149. XL_VERBOSE(("XLGlyphCache::IncreaseArray entry.\n"));
  150. if (NULL == m_paulFontID || NULL == m_ppGlyphTable)
  151. {
  152. if (NULL == m_paulFontID)
  153. {
  154. if (!(m_paulFontID = (PULONG)MemAllocZ(INIT_ARRAY * sizeof(ULONG))))
  155. {
  156. FreeAll();
  157. XL_ERR(("XLGlyphCache::IncreaseArray MemAllocZ failed.\n"));
  158. return E_UNEXPECTED;
  159. }
  160. }
  161. if (NULL == m_ppGlyphTable)
  162. {
  163. if (!(m_ppGlyphTable = (GLYPHTABLE**)MemAllocZ(INIT_ARRAY * sizeof(GLYPHTABLE))))
  164. {
  165. FreeAll();
  166. XL_ERR(("XLGlyphCache::IncreaseArray MemAllocZ failed.\n"));
  167. return E_UNEXPECTED;
  168. }
  169. }
  170. m_ulNumberOfArray = INIT_ARRAY;
  171. m_ulNumberOfFonts = 0;
  172. }
  173. else if (m_ulNumberOfArray == m_ulNumberOfFonts)
  174. {
  175. ULONG ulArraySize = m_ulNumberOfArray + ADD_ARRAY;
  176. PULONG paulTmpFontID;
  177. PGLYPHTABLE *ppTmpGlyphTable;
  178. //
  179. // Allocate new buffer
  180. //
  181. if (!(paulTmpFontID = (PULONG)MemAllocZ(ulArraySize)))
  182. {
  183. XL_ERR(("XLGlyphCache::IncreaseArray MemAllocZ failed.\n"));
  184. return E_UNEXPECTED;
  185. }
  186. if (!(ppTmpGlyphTable = (GLYPHTABLE**)MemAllocZ(ulArraySize * sizeof(GLYPHTABLE))))
  187. {
  188. MemFree(paulTmpFontID);
  189. XL_ERR(("XLGlyphCache::IncreaseArray MemAllocZ failed.\n"));
  190. return E_UNEXPECTED;
  191. }
  192. //
  193. // Copy old one to new one
  194. //
  195. CopyMemory(paulTmpFontID,
  196. m_paulFontID,
  197. m_ulNumberOfArray * sizeof(ULONG));
  198. CopyMemory(ppTmpGlyphTable,
  199. m_ppGlyphTable,
  200. m_ulNumberOfArray * sizeof(GLYPHTABLE));
  201. //
  202. // Free old buffer
  203. //
  204. MemFree(m_paulFontID);
  205. MemFree(m_ppGlyphTable);
  206. //
  207. // Set new buffer
  208. //
  209. m_paulFontID = paulTmpFontID;
  210. m_ppGlyphTable = ppTmpGlyphTable;
  211. m_ulNumberOfArray = ulArraySize;
  212. }
  213. return S_OK;
  214. }
  215. ULONG
  216. XLGlyphCache::
  217. UlSearchFontID(
  218. ULONG ulFontID)
  219. /*++
  220. Routine Description:
  221. Arguments:
  222. Return Value:
  223. Note:
  224. --*/
  225. {
  226. XL_VERBOSE(("XLGlyphCache::UlSearchFontID entry.\n"));
  227. ULONG ulReturn, ulI;
  228. BOOL bFound;
  229. if (NULL == m_paulFontID)
  230. {
  231. //
  232. // Error case. Returns 0xFFFF.
  233. // Here is an assumption. The number of fonts in one document doesn't
  234. // become larger than 65535.
  235. //
  236. XL_ERR(("XLGlyphCache::UlSearchFontID failed.\n"));
  237. return 0xFFFF;
  238. }
  239. bFound = TRUE;
  240. //
  241. // Search font ID
  242. //
  243. ulI = m_ulNumberOfFonts / 2;
  244. PULONG paulFontID = m_paulFontID + ulI;
  245. while ( *paulFontID != ulFontID)
  246. {
  247. if (ulI == 0)
  248. {
  249. bFound = FALSE;
  250. break;
  251. }
  252. ulI = ulI / 2;
  253. if (ulI == 0)
  254. {
  255. ulI = 1;
  256. }
  257. if (*paulFontID < ulFontID)
  258. {
  259. paulFontID += ulI;
  260. }
  261. else
  262. {
  263. paulFontID -= ulI;
  264. }
  265. if (ulI == 1)
  266. {
  267. ulI = 0;
  268. }
  269. }
  270. if (!bFound)
  271. {
  272. ulReturn = m_ulNumberOfFonts;
  273. }
  274. else
  275. {
  276. ulReturn = (ULONG)(paulFontID - m_paulFontID);
  277. }
  278. XL_VERBOSE(("XLGlyphCache::UlSearchFontID(ulFontID=%d, ulArrayID=%d).\n", ulFontID, ulReturn));
  279. return ulReturn;
  280. }
  281. HRESULT
  282. XLGlyphCache::
  283. AddGlyphID(
  284. ULONG ulFontID,
  285. ULONG ulGlyphID)
  286. /*++
  287. Routine Description:
  288. Arguments:
  289. Return Value:
  290. Note:
  291. --*/
  292. {
  293. XL_VERBOSE(("XLGlyphCache::AddGlyphID entry (ulFontiD=%d, ulGlyphID=%d).\n", ulFontID, ulGlyphID));
  294. ULONG ulArrayID;
  295. //
  296. // Get the pointer to GLYPYTABLE of this font.
  297. //
  298. if (0xFFFF == (ulArrayID = UlSearchFontID(ulFontID)))
  299. {
  300. XL_ERR(("XLGlyphCache::AddGlyphID UlSearchFontID failed.\n"));
  301. return E_UNEXPECTED;
  302. }
  303. PGLYPHTABLE pGlyphTable = *(m_ppGlyphTable+ulArrayID);
  304. PGLYPHID pGlyphID = pGlyphTable->pFirstGID;
  305. BOOL bFound;
  306. WORD wI, wSearchRange;
  307. wSearchRange = pGlyphTable->wGlyphNum / 2;
  308. pGlyphID = PSearchGlyph(wSearchRange, TRUE, pGlyphID);
  309. bFound = TRUE;
  310. if (pGlyphID)
  311. {
  312. while (pGlyphID->ulGlyphID != ulGlyphID)
  313. {
  314. if (wSearchRange == 0)
  315. {
  316. bFound = FALSE;
  317. break;
  318. }
  319. wSearchRange = wSearchRange / 2;
  320. if (wSearchRange == 0)
  321. {
  322. wSearchRange = 1;
  323. }
  324. if (pGlyphID->ulGlyphID > ulGlyphID)
  325. {
  326. pGlyphID = PSearchGlyph(wSearchRange, TRUE, pGlyphID);
  327. }
  328. else
  329. {
  330. pGlyphID = PSearchGlyph(wSearchRange, FALSE, pGlyphID);
  331. }
  332. if (wSearchRange == 1)
  333. {
  334. wSearchRange = 0;
  335. }
  336. if (NULL == pGlyphID)
  337. {
  338. bFound = FALSE;
  339. break;
  340. }
  341. }
  342. }
  343. else
  344. {
  345. //
  346. // PSearchGlyph failed. There is not glyph available in the cache.
  347. //
  348. bFound = FALSE;
  349. }
  350. if (bFound)
  351. {
  352. XL_VERBOSE(("XLGlyphCache::AddGlyphID FOUND glyph in the cache.\n"));
  353. return S_FALSE;
  354. }
  355. else if (pGlyphID)
  356. {
  357. PGLYPHID pPrevGID = pGlyphID->pPrevGID;
  358. PGLYPHID pNextGID = pGlyphID->pNextGID;
  359. PGLYPHID pNewGID;
  360. IncreaseGlyphArray(ulFontID);
  361. pNewGID = pGlyphTable->pGlyphID + pGlyphTable->wGlyphNum;
  362. if (pGlyphID->ulGlyphID < ulGlyphID && ulGlyphID < pNextGID->ulGlyphID)
  363. {
  364. pGlyphID->pNextGID = pNewGID;
  365. pNewGID->pPrevGID = pGlyphID;
  366. pNewGID->pNextGID = pNextGID;
  367. pNextGID->pPrevGID = pNewGID;
  368. }
  369. else
  370. if (pPrevGID->ulGlyphID < ulGlyphID && ulGlyphID < pGlyphID->ulGlyphID)
  371. {
  372. pPrevGID->pNextGID = pNewGID;
  373. pNewGID->pPrevGID = pPrevGID;
  374. pNewGID->pNextGID = pGlyphID;
  375. pGlyphID->pPrevGID = pNewGID;
  376. }
  377. pNewGID->ulGlyphID = ulGlyphID;
  378. pGlyphTable->wGlyphNum++;
  379. XL_VERBOSE(("XLGlyphCache::AddGlyphID ADDED glyph in the cache.\n"));
  380. return S_OK;
  381. }
  382. else
  383. {
  384. PGLYPHID pNewGID;
  385. IncreaseGlyphArray(ulFontID);
  386. pNewGID = pGlyphTable->pGlyphID + pGlyphTable->wGlyphNum;
  387. pNewGID->ulGlyphID = ulGlyphID;
  388. pNewGID->pPrevGID = NULL;
  389. pNewGID->pNextGID = NULL;
  390. pGlyphTable->wGlyphNum++;
  391. XL_VERBOSE(("XLGlyphCache::AddGlyphID ADDED glyph in the cache.\n"));
  392. return S_OK;
  393. }
  394. }
  395. PGLYPHID
  396. XLGlyphCache::
  397. PSearchGlyph(
  398. WORD wSearchRange,
  399. BOOL bForward,
  400. PGLYPHID pGlyphID)
  401. /*++
  402. Routine Description:
  403. Arguments:
  404. Return Value:
  405. Note:
  406. --*/
  407. {
  408. XL_VERBOSE(("XLGlyphCache::PSearchGlyph entry (wSearchRange=%d,bForward=%d).\n",wSearchRange, bForward));
  409. WORD wI;
  410. if (pGlyphID)
  411. {
  412. if (bForward)
  413. {
  414. for (wI = 0; wI < wSearchRange; wI++)
  415. {
  416. if (pGlyphID->pNextGID)
  417. {
  418. pGlyphID = pGlyphID->pNextGID;
  419. }
  420. else
  421. {
  422. pGlyphID = NULL;
  423. break;
  424. }
  425. }
  426. }
  427. else
  428. {
  429. for (wI = 0; wI < wSearchRange; wI++)
  430. {
  431. if (pGlyphID->pNextGID)
  432. {
  433. pGlyphID = pGlyphID->pNextGID;
  434. }
  435. else
  436. {
  437. pGlyphID = NULL;
  438. break;
  439. }
  440. }
  441. }
  442. }
  443. XL_VERBOSE(("XLGlyphCache::PSearchGlyph pGlyphID = %0x.\n", pGlyphID));
  444. return pGlyphID;
  445. }
  446. HRESULT
  447. XLGlyphCache::
  448. IncreaseGlyphArray(
  449. ULONG ulFontID)
  450. {
  451. ULONG ulArrayID;
  452. //
  453. // Get the pointer to GLYPYTABLE of this font.
  454. //
  455. if (0xFFFF == (ulArrayID = UlSearchFontID(ulFontID)))
  456. {
  457. XL_ERR(("XLGlyphCache::AddGlyphID UlSearchFontID failed.\n"));
  458. return E_UNEXPECTED;
  459. }
  460. PGLYPHTABLE pGlyphTable = *(m_ppGlyphTable+ulArrayID);
  461. //
  462. // Get the pointer to GLYPYTABLE of this font.
  463. //
  464. if (0xFFFF == (ulArrayID = UlSearchFontID(ulFontID)))
  465. {
  466. XL_ERR(("XLGlyphCache::AddGlyphID UlSearchFontID failed.\n"));
  467. return E_UNEXPECTED;
  468. }
  469. if (pGlyphTable->wGlyphNum == pGlyphTable->dwAvailableEntries)
  470. {
  471. PGLYPHID pGlyphID;
  472. if (!(pGlyphID = (PGLYPHID)MemAllocZ((pGlyphTable->dwAvailableEntries + ADD_GLYPH_ARRAY) * sizeof(GLYPHID))))
  473. {
  474. XL_ERR(("XLGlyphCache::AddGlyphID MemAllocZ failed.\n"));
  475. return E_UNEXPECTED;
  476. }
  477. CopyMemory(pGlyphID, pGlyphTable->pGlyphID, pGlyphTable->dwAvailableEntries * sizeof(GLYPHID));
  478. pGlyphTable->pFirstGID = pGlyphID + (pGlyphTable->pFirstGID - pGlyphTable->pGlyphID);
  479. MemFree(pGlyphTable->pGlyphID);
  480. pGlyphTable->pGlyphID = pGlyphID;
  481. pGlyphTable->dwAvailableEntries += ADD_GLYPH_ARRAY;
  482. }
  483. return S_OK;
  484. }
  485. #if DBG
  486. VOID
  487. XLGlyphCache::
  488. SetDbgLevel(
  489. DWORD dwLevel)
  490. /*++
  491. Routine Description:
  492. Arguments:
  493. Return Value:
  494. Note:
  495. --*/
  496. {
  497. m_dbglevel = dwLevel;
  498. }
  499. #endif