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.

1534 lines
45 KiB

  1. #include "annotlib.h"
  2. #include "assert.h"
  3. #include "shlwapi.h"
  4. #pragma hdrstop
  5. #if !defined(ARRAYSIZE)
  6. #define ARRAYSIZE(x) (sizeof((x))/sizeof((x)[0]))
  7. #endif
  8. // Private definitions of tag types and values
  9. //
  10. // Each entry in the annotation has a type
  11. //
  12. #define DEFAULTDATA 2
  13. #define ANNOTMARK 5
  14. #define MARKBLOCK 6
  15. // Reserved names for named blocks. case sensitive
  16. static const char c_szAnoDat[] = "OiAnoDat";
  17. static const char c_szFilNam[] = "OiFilNam";
  18. static const char c_szDIB[] = "OiDIB";
  19. static const char c_szGroup[] = "OiGroup";
  20. static const char c_szIndex[] = "OiIndex";
  21. static const char c_szAnText[] = "OiAnText";
  22. static const char c_szHypLnk[] = "OiHypLnk";
  23. static const char c_szDefaultGroup[] = "[Untitled]";
  24. #define CBHEADER 8 // unused 4 bytes plus int size specifier
  25. #define CBDATATYPE 8 // type specifier plus data size
  26. #define CBNAMEDBLOCK 12 // name of block + sizeof block
  27. #define CBINDEX 10 // length of the index string
  28. #define CBBLOCKNAME 8 // length of the name of the named block
  29. static const SIZE_T c_cbDefaultData = 144;
  30. static const BYTE c_pDefaultData[] = {
  31. 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x69, 0x55, 0x47, 0x72, 0x6f, 0x75, 0x70,
  32. 0x2a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x55, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65,
  33. 0x64, 0x5d, 0x00, 0x00, 0x5b, 0x00, 0x55, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x74, 0x00,
  34. 0x6c, 0x00, 0x65, 0x00, 0x64, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
  35. 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x69, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x00, 0x0c, 0x00,
  36. 0x00, 0x00, 0x5b, 0x55, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x64, 0x5d, 0x00, 0x00, 0x02, 0x00,
  37. 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x69, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x1e, 0x00,
  38. 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  39. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  40. };
  41. static const BYTE c_pDefaultUGroup [] = {
  42. 0x4f, 0x69, 0x55, 0x47, 0x72, 0x6f, 0x75, 0x70,
  43. 0x2a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x55, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65,
  44. 0x64, 0x5d, 0x00, 0x00, 0x5b, 0x00, 0x55, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x74, 0x00,
  45. 0x6c, 0x00, 0x65, 0x00, 0x64, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  46. };
  47. static const INT AnnotHeader[] =
  48. {
  49. 0, 1
  50. };
  51. void NormalizeRect (RECT *prect)
  52. {
  53. int nTemp;
  54. if (prect->left > prect->right)
  55. {
  56. nTemp = prect->left;
  57. prect->left = prect->right;
  58. prect->right = nTemp;
  59. }
  60. if (prect->top > prect->bottom)
  61. {
  62. nTemp = prect->top;
  63. prect->top = prect->bottom;
  64. prect->bottom = nTemp;
  65. }
  66. }
  67. static void RotateHelper(LPPOINT ppoint, int cSize, int nNewImageWidth, int nNewImageHeight, BOOL bClockwise)
  68. {
  69. int nNewX, nNewY;
  70. for(int i=0;i<cSize;i++)
  71. {
  72. if (bClockwise)
  73. {
  74. nNewX = nNewImageWidth - ppoint[i].y;
  75. nNewY = ppoint[i].x;
  76. }
  77. else
  78. {
  79. nNewX = ppoint[i].y;
  80. nNewY = nNewImageHeight - ppoint[i].x;
  81. }
  82. ppoint[i].x = nNewX;
  83. ppoint[i].y = nNewY;
  84. }
  85. }
  86. CAnnotationSet::CAnnotationSet()
  87. : _dpaMarks(NULL)
  88. {
  89. _pDefaultData = (LPBYTE)c_pDefaultData;
  90. _cbDefaultData = c_cbDefaultData;
  91. }
  92. CAnnotationSet::~CAnnotationSet()
  93. {
  94. _ClearMarkList ();
  95. }
  96. void CAnnotationSet::RenderAllMarks(HDC hdc)
  97. {
  98. CAnnotation *pCur;
  99. if(_dpaMarks == NULL)
  100. return;
  101. for (INT_PTR i=0;i<DPA_GetPtrCount(_dpaMarks);i++)
  102. {
  103. pCur = (CAnnotation*)DPA_GetPtr(_dpaMarks, i);
  104. if (pCur)
  105. {
  106. pCur->Render (hdc);
  107. }
  108. }
  109. }
  110. CAnnotation* CAnnotationSet::GetAnnotation(INT_PTR nIndex)
  111. {
  112. if(_dpaMarks == NULL)
  113. return NULL;
  114. if (nIndex >= 0 && nIndex < DPA_GetPtrCount(_dpaMarks))
  115. {
  116. CAnnotation *pCur;
  117. pCur = (CAnnotation *)DPA_GetPtr(_dpaMarks, nIndex);
  118. return pCur;
  119. }
  120. return NULL;
  121. }
  122. BOOL CAnnotationSet::AddAnnotation(CAnnotation *pMark)
  123. {
  124. DPA_AppendPtr(_dpaMarks, pMark);
  125. return true;
  126. }
  127. BOOL CAnnotationSet::RemoveAnnotation(CAnnotation *pMark)
  128. {
  129. CAnnotation *pCur;
  130. if(_dpaMarks == NULL)
  131. return true;
  132. for (int i=0;i<DPA_GetPtrCount(_dpaMarks);i++)
  133. {
  134. pCur = (CAnnotation*)DPA_GetPtr(_dpaMarks, i);
  135. if (pCur == pMark)
  136. {
  137. DPA_DeletePtr(_dpaMarks, i);
  138. return true;
  139. }
  140. }
  141. return false;
  142. }
  143. void CAnnotationSet::SetImageData(IShellImageData *pimg)
  144. {
  145. GUID guidFmt;
  146. pimg->GetRawDataFormat(&guidFmt);
  147. _ClearMarkList();
  148. if (ImageFormatTIFF == guidFmt)
  149. {
  150. _BuildMarkList(pimg);
  151. }
  152. }
  153. //
  154. // This function reassembles the in-file representation of the current
  155. // annotations and writes it to the IPropertyStorage
  156. //
  157. HRESULT CAnnotationSet::CommitAnnotations(IShellImageData * pSID)
  158. {
  159. HRESULT hr = E_OUTOFMEMORY;
  160. SIZE_T cbItem;
  161. CAnnotation *pItem;
  162. LPBYTE pData;
  163. if (NULL == _dpaMarks || DPA_GetPtrCount(_dpaMarks) == 0)
  164. {
  165. hr = _SaveAnnotationProperty(pSID, NULL, 0);
  166. return hr;
  167. }
  168. //
  169. // First, calculate the size of the buffer needed
  170. // Begin with the header and the size of the default data
  171. //
  172. SIZE_T cbBuffer = CBHEADER+_cbDefaultData;
  173. //
  174. // Now query the individual items' sizes
  175. //
  176. for (INT_PTR i=0;i<DPA_GetPtrCount(_dpaMarks);i++)
  177. {
  178. pItem = (CAnnotation*)DPA_GetPtr(_dpaMarks, i);
  179. if (pItem)
  180. {
  181. if (SUCCEEDED(pItem->GetBlob(cbItem, NULL, c_szDefaultGroup, NULL)))
  182. {
  183. // cbItem includes the named blocks of the item as well
  184. // as the ANNOTATIONMARK struct
  185. cbBuffer += CBDATATYPE + cbItem;
  186. }
  187. }
  188. }
  189. //
  190. // Allocate the buffer to hold the annotations
  191. //
  192. pData = new BYTE[cbBuffer];
  193. if (pData)
  194. {
  195. LPBYTE pCur = pData;
  196. //
  197. // Copy in the header and the int size
  198. //
  199. CopyMemory(pCur, AnnotHeader, CBHEADER);
  200. pCur+=CBHEADER;
  201. //
  202. // Copy in the default data
  203. //
  204. CopyMemory(pCur, _pDefaultData, _cbDefaultData);
  205. pCur+=_cbDefaultData;
  206. //
  207. // Scan through the items again and have them copy in their data
  208. //
  209. for (INT_PTR i=0;i<DPA_GetPtrCount(_dpaMarks);i++)
  210. {
  211. pItem = (CAnnotation*)DPA_GetPtr(_dpaMarks, i);
  212. if (pItem)
  213. {
  214. UINT nIndex = (UINT)i;
  215. CHAR szIndex[11];
  216. ZeroMemory(szIndex, 11);
  217. wnsprintfA(szIndex, ARRAYSIZE(szIndex), "%d", nIndex );
  218. if (SUCCEEDED(pItem->GetBlob(cbItem, pCur+CBDATATYPE, c_szDefaultGroup, szIndex)))
  219. {
  220. *(UNALIGNED UINT *)pCur = ANNOTMARK; // next item is an ANNOTATIONMARK
  221. *(UNALIGNED UINT *)(pCur+4) = sizeof(ANNOTATIONMARK); // size of the mark
  222. pCur+=CBDATATYPE + cbItem;
  223. }
  224. }
  225. }
  226. //
  227. // Now save the annotation blob as a property
  228. //
  229. hr = _SaveAnnotationProperty(pSID, pData, cbBuffer);
  230. }
  231. delete [] pData;
  232. return hr;
  233. }
  234. void CAnnotationSet::ClearAllMarks()
  235. {
  236. _ClearMarkList();
  237. }
  238. //
  239. // _BuildMarkList reads the PROPVARIANT for tag 32932 from the image.
  240. // It walks through the data building a list of CAnnotation-derived objects
  241. //
  242. void CAnnotationSet::_BuildMarkList(IShellImageData * pSID)
  243. {
  244. if(!pSID)
  245. {
  246. return;
  247. }
  248. pSID->GetResolution(&_xDPI, &_yDPI);
  249. IPropertySetStorage * pss;
  250. if(SUCCEEDED(pSID->GetProperties(STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &pss)))
  251. {
  252. IPropertyStorage * pstg;
  253. if(SUCCEEDED( pss->Open(FMTID_ImageProperties, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pstg)))
  254. {
  255. _dpaMarks = DPA_Create(16);
  256. PROPVARIANT pv = {0};
  257. PROPSPEC ps;
  258. ps.propid = ANNOTATION_IMAGE_TAG;
  259. ps.ulKind = PRSPEC_PROPID;
  260. if(S_OK == pstg->ReadMultiple(1, &ps, &pv))
  261. {
  262. if (pv.vt != VT_NULL && pv.vt != VT_EMPTY)
  263. {
  264. LPVOID pData = NULL;
  265. long lUBound;
  266. //
  267. // This property is a SAFEARRAY of bytes
  268. //
  269. assert(pv.vt ==(VT_UI1 | VT_ARRAY));
  270. SafeArrayGetUBound(pv.parray, 1, &lUBound);
  271. SafeArrayAccessData(pv.parray, &pData);
  272. if(pData)
  273. {
  274. _BuildListFromData(pData, SafeArrayGetElemsize(pv.parray)*(lUBound+1));
  275. }
  276. SafeArrayUnaccessData(pv.parray);
  277. }
  278. PropVariantClear (&pv);
  279. }
  280. pstg->Release();
  281. }
  282. pss->Release();
  283. }
  284. }
  285. // Given the raw annotation data, do set up and then call _BuildListFromData
  286. HRESULT CAnnotationSet::BuildAllMarksFromData(LPVOID pData, UINT cbSize, ULONG xDPI, ULONG yDPI)
  287. {
  288. // check for bad params
  289. if (!pData)
  290. {
  291. return E_INVALIDARG;
  292. }
  293. // First, clear out any old marks...
  294. _ClearMarkList();
  295. // Set up DPI info
  296. _xDPI = xDPI;
  297. _yDPI = yDPI;
  298. // Create DPA if it doesn't exist
  299. if (!_dpaMarks)
  300. {
  301. _dpaMarks = DPA_Create(16);
  302. if (!_dpaMarks)
  303. {
  304. return E_OUTOFMEMORY;
  305. }
  306. }
  307. // build list of marks
  308. _BuildListFromData(pData,cbSize);
  309. return S_OK;
  310. }
  311. // Given the raw annotation data, swizzle it to in-memory CAnnotation objects
  312. // and add those object pointers to our list
  313. void CAnnotationSet::_BuildListFromData(LPVOID pData, UINT cbSize)
  314. {
  315. ANNOTATIONDESCRIPTOR *pDesc;
  316. LPBYTE pNextData =(LPBYTE)pData;
  317. LPBYTE pDefaultData;
  318. CAnnotation *pMark;
  319. if(!_dpaMarks)
  320. {
  321. return;
  322. }
  323. // Skip the 4 byte header
  324. pNextData += 4;
  325. // Make sure the int size is 32 bits
  326. if(!((UNALIGNED int *)*pNextData))
  327. {
  328. return;
  329. }
  330. // skip the int size marker
  331. pNextData += 4;
  332. pDefaultData = pNextData;
  333. // skip the default data. It gets stored for future use, as it will be appended to all
  334. // new marks the user creates on this image.
  335. pNextData += _NamedBlockDataSize(2,pNextData,(LPBYTE)pData+cbSize);
  336. _cbDefaultData = (SIZE_T)(pNextData-pDefaultData);
  337. _pDefaultData = new BYTE[_cbDefaultData];
  338. if(_pDefaultData)
  339. {
  340. CopyMemory(_pDefaultData, pDefaultData, _cbDefaultData);
  341. }
  342. // pNextData now points to the first mark in the data.
  343. do
  344. {
  345. // Create a descriptor from the raw mark data
  346. pDesc = _ReadMark(pNextData, &pNextData,(LPBYTE)pData+cbSize);
  347. if(pDesc)
  348. {
  349. // Now create a CAnnotation from the descriptor and add it to the list
  350. pMark = CAnnotation::CreateAnnotation(pDesc, _yDPI);
  351. if(pMark)
  352. {
  353. DPA_AppendPtr(_dpaMarks, pMark);
  354. }
  355. delete pDesc;
  356. }
  357. }while(pNextData &&(((LPBYTE)pData+cbSize) > pNextData) );
  358. }
  359. #define CHECKEOD if(pCur>pEOD)return -1;
  360. INT CAnnotationSet::_NamedBlockDataSize(UINT uType, LPBYTE pData, LPBYTE pEOD)
  361. {
  362. LPBYTE pCur = pData;
  363. UINT cbSkip=0;
  364. while(pCur < pEOD && *(UNALIGNED UINT*)pCur == uType)
  365. {
  366. pCur+=4;
  367. CHECKEOD
  368. // skip type and size
  369. cbSkip +=8+*(UNALIGNED UINT*)pCur;
  370. pCur+=4;
  371. //skip name
  372. pCur+=8;
  373. CHECKEOD
  374. // skip size plus the actual data
  375. cbSkip+=*(UNALIGNED UINT*)pCur;
  376. pCur+=4+*(UNALIGNED UINT*)pCur;
  377. }
  378. return cbSkip;
  379. }
  380. ANNOTATIONDESCRIPTOR *CAnnotationSet::_ReadMark(LPBYTE pMark, LPBYTE *ppNext, LPBYTE pEOD)
  381. {
  382. assert(*(UNALIGNED UINT*)pMark == 5);
  383. LPBYTE pBegin;
  384. UINT cbMark; // size of the ANNOTATIONMARK in pMark
  385. UINT cbNamedBlocks= -1; // size of the named blocks in pMark
  386. UINT cbDesc = sizeof(UINT); // size of the ANNOTATIONDESCRIPTOR
  387. ANNOTATIONDESCRIPTOR *pDesc = NULL;
  388. *ppNext = NULL;
  389. if (5 != *(UNALIGNED UINT*)pMark)
  390. {
  391. return pDesc;
  392. }
  393. if (pMark+8+sizeof(ANNOTATIONMARK)+sizeof(UINT) < pEOD)
  394. {
  395. // skip the type
  396. pMark+=4;
  397. //point pBegin at the ANNOTATIONMARK struct
  398. pBegin=pMark+4;
  399. cbMark = *(UNALIGNED UINT*)pMark;
  400. assert(cbMark == sizeof(ANNOTATIONMARK));
  401. if (sizeof(ANNOTATIONMARK) == cbMark)
  402. {
  403. cbDesc+=cbMark;
  404. pMark+=4+cbMark;
  405. cbNamedBlocks = _NamedBlockDataSize(6, pMark, pEOD);
  406. }
  407. }
  408. if (-1 != cbNamedBlocks)
  409. {
  410. cbDesc+=cbNamedBlocks;
  411. // Allocate the descriptor
  412. pDesc =(ANNOTATIONDESCRIPTOR *)new BYTE[cbDesc];
  413. }
  414. if (pDesc)
  415. {
  416. BOOL bFailed = FALSE;
  417. UINT uOffset = 0;
  418. // populate the descriptor
  419. pDesc->cbSize = cbDesc;
  420. CopyMemory(&pDesc->mark, pBegin, sizeof(pDesc->mark));
  421. // Set pBegin at the beginning of the named blocks and read them in
  422. pBegin+=cbMark;
  423. NAMEDBLOCK *pBlock =(NAMEDBLOCK*)(&pDesc->blocks);
  424. while(!bFailed && uOffset < cbNamedBlocks)
  425. {
  426. assert(*(UNALIGNED UINT*)(pBegin+uOffset) == 6);
  427. if (6 == *(UNALIGNED UINT*)(pBegin+uOffset))
  428. {
  429. uOffset += 4;
  430. assert(*(UNALIGNED UINT*)(pBegin+uOffset) == 12); // name plus data size
  431. if (12 == *(UNALIGNED UINT*)(pBegin+uOffset))
  432. {
  433. uOffset+=4;
  434. // Copy in the name of the block
  435. lstrcpynA(pBlock->szType,(LPCSTR)(pBegin+uOffset), ARRAYSIZE(pBlock->szType));
  436. uOffset+=8;
  437. cbMark = *(UNALIGNED UINT*)(pBegin+uOffset);
  438. // Calculate the total size of the NAMEDBLOCK structure
  439. pBlock->cbSize = sizeof(pBlock->cbSize)+sizeof(pBlock->szType)+cbMark;
  440. uOffset+=4;
  441. CopyMemory(&pBlock->data,pBegin+uOffset, cbMark);
  442. uOffset+=cbMark;
  443. // move our block pointer to the next chunk
  444. pBlock =(NAMEDBLOCK*)((LPBYTE)pBlock+pBlock->cbSize);
  445. }
  446. else
  447. {
  448. bFailed = TRUE;
  449. }
  450. }
  451. else
  452. {
  453. bFailed = TRUE;
  454. }
  455. }
  456. if (!bFailed)
  457. {
  458. *ppNext =(LPBYTE)(pBegin+cbNamedBlocks);
  459. }
  460. else // annotations are malformed, don't try to load them
  461. {
  462. delete [] (BYTE*) pDesc;
  463. pDesc = NULL;
  464. }
  465. }
  466. return pDesc;
  467. }
  468. void CAnnotationSet::_ClearMarkList()
  469. {
  470. if(_dpaMarks)
  471. {
  472. DPA_DestroyCallback(_dpaMarks, _FreeMarks, NULL);
  473. _dpaMarks = NULL;
  474. }
  475. if (_pDefaultData != c_pDefaultData)
  476. {
  477. delete[] _pDefaultData;
  478. }
  479. _pDefaultData = (LPBYTE)c_pDefaultData;
  480. _cbDefaultData = c_cbDefaultData;
  481. }
  482. int CALLBACK CAnnotationSet::_FreeMarks(LPVOID pMark, LPVOID pUnused)
  483. {
  484. delete (CAnnotation*)pMark;
  485. return 1;
  486. }
  487. HRESULT CAnnotationSet::_SaveAnnotationProperty(IShellImageData * pSID, LPBYTE pData, SIZE_T cbBuffer)
  488. {
  489. IPropertySetStorage * pss;
  490. HRESULT hr = pSID->GetProperties(STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &pss);
  491. if (SUCCEEDED(hr))
  492. {
  493. IPropertyStorage * pstg;
  494. hr = pss->Open(FMTID_ImageProperties, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pstg);
  495. if (SUCCEEDED(hr))
  496. {
  497. PROPVARIANT pv;
  498. static PROPSPEC ps = {PRSPEC_PROPID, ANNOTATION_IMAGE_TAG};
  499. SAFEARRAYBOUND bound;
  500. bound.cElements = (ULONG)cbBuffer;
  501. bound.lLbound = 0;
  502. PropVariantInit(&pv);
  503. if (pData != NULL)
  504. {
  505. pv.vt = VT_UI1 | VT_ARRAY;
  506. pv.parray = SafeArrayCreate(VT_UI1,1,&bound);
  507. if (pv.parray)
  508. {
  509. LPVOID pBits;
  510. hr = SafeArrayAccessData(pv.parray, &pBits);
  511. if (SUCCEEDED(hr))
  512. {
  513. CopyMemory(pBits, pData, cbBuffer);
  514. SafeArrayUnaccessData(pv.parray);
  515. if (S_OK != pstg->WriteMultiple(1, &ps, &pv, 1024))
  516. {
  517. hr = E_FAIL;
  518. }
  519. }
  520. }
  521. else
  522. {
  523. hr = E_OUTOFMEMORY;
  524. }
  525. }
  526. else
  527. {
  528. pv.vt = VT_NULL;
  529. if (S_OK != pstg->WriteMultiple(1, &ps, &pv, 1024))
  530. {
  531. hr = E_FAIL;
  532. }
  533. }
  534. PropVariantClear(&pv);
  535. pstg->Release();
  536. }
  537. pss->Release();
  538. }
  539. return hr;
  540. }
  541. CAnnotation::CAnnotation(ANNOTATIONDESCRIPTOR *pDescriptor)
  542. {
  543. NAMEDBLOCK *pb;
  544. CopyMemory(&_mark, &pDescriptor->mark, sizeof(_mark));
  545. // every annotation read from the image should have a group name
  546. // and an index
  547. _szGroup = NULL;
  548. pb = _FindNamedBlock("OiGroup", pDescriptor);
  549. if(pb)
  550. {
  551. _szGroup = new char[pb->cbSize-sizeof(pb->szType)];
  552. if(_szGroup)
  553. {
  554. lstrcpynA(_szGroup,(LPCSTR)(pb->data),pb->cbSize-sizeof(pb->szType));
  555. }
  556. }
  557. _pUGroup = (FILENAMEDBLOCK*)c_pDefaultUGroup;
  558. pb = _FindNamedBlock("OiUGroup", pDescriptor);
  559. if (pb)
  560. {
  561. _pUGroup = (FILENAMEDBLOCK*)new BYTE[pb->cbSize-1];
  562. if (_pUGroup)
  563. {
  564. CopyMemory(_pUGroup->szType, pb->szType, ARRAYSIZE(_pUGroup->szType));
  565. _pUGroup->cbSize = pb->cbSize-CBNAMEDBLOCK-1;
  566. CopyMemory(_pUGroup->data, pb->data, _pUGroup->cbSize);
  567. }
  568. else
  569. {
  570. _pUGroup = (FILENAMEDBLOCK*)c_pDefaultUGroup;
  571. }
  572. }
  573. }
  574. // return a blank annotation object
  575. CAnnotation *CAnnotation::CreateAnnotation(UINT type, ULONG uCreationScale)
  576. {
  577. ANNOTATIONDESCRIPTOR desc;
  578. ZeroMemory(&desc, sizeof(desc));
  579. desc.cbSize = sizeof(desc.cbSize)+sizeof(desc.mark)+sizeof(desc.blocks);
  580. desc.mark.uType = type;
  581. // MSDN mentions this required permission value
  582. desc.mark.dwPermissions = 0x0ff83f;
  583. desc.mark.bVisible = 1;
  584. return CreateAnnotation(&desc, uCreationScale);
  585. }
  586. CAnnotation *CAnnotation::CreateAnnotation(ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale)
  587. {
  588. CAnnotation *pNew = NULL;
  589. switch(pDescriptor->mark.uType)
  590. {
  591. case MT_IMAGEEMBED:
  592. case MT_IMAGEREF:
  593. pNew = new CImageMark(pDescriptor, pDescriptor->mark.uType == MT_IMAGEEMBED);
  594. break;
  595. case MT_STRAIGHTLINE:
  596. case MT_FREEHANDLINE:
  597. pNew = new CLineMark(pDescriptor, pDescriptor->mark.uType == MT_FREEHANDLINE);
  598. break;
  599. case MT_FILLRECT:
  600. case MT_HOLLOWRECT:
  601. pNew = new CRectMark(pDescriptor);
  602. break;
  603. case MT_TYPEDTEXT:
  604. pNew = new CTypedTextMark(pDescriptor, uCreationScale);
  605. break;
  606. case MT_FILETEXT:
  607. pNew = new CFileTextMark(pDescriptor, uCreationScale);
  608. break;
  609. case MT_STAMP:
  610. pNew = new CTextStampMark(pDescriptor, uCreationScale);
  611. break;
  612. case MT_ATTACHANOTE:
  613. pNew = new CAttachNoteMark(pDescriptor, uCreationScale);
  614. break;
  615. default:
  616. break;
  617. }
  618. return pNew;
  619. }
  620. void CAnnotation::Resize(RECT rectNewSize)
  621. {
  622. _mark.lrBounds = rectNewSize;
  623. NormalizeRect(&_mark.lrBounds);
  624. }
  625. NAMEDBLOCK *CAnnotation::_FindNamedBlock(LPCSTR szName, ANNOTATIONDESCRIPTOR *pDescriptor)
  626. {
  627. NAMEDBLOCK *pCur;
  628. NAMEDBLOCK *pRet = NULL;
  629. UINT uOffset;
  630. LPBYTE pb =(LPBYTE)pDescriptor;
  631. uOffset = sizeof(pDescriptor->cbSize)+sizeof(pDescriptor->mark);
  632. while(!pRet && uOffset < pDescriptor->cbSize)
  633. {
  634. pCur =(NAMEDBLOCK*)(pb+uOffset);
  635. if(!lstrcmpA(pCur->szType, szName))
  636. {
  637. pRet = pCur;
  638. }
  639. else
  640. {
  641. if (pCur->cbSize == 0)
  642. return NULL;
  643. uOffset+=pCur->cbSize;
  644. }
  645. }
  646. return pRet;
  647. }
  648. CAnnotation::~CAnnotation()
  649. {
  650. if(_szGroup)
  651. {
  652. delete _szGroup;
  653. }
  654. if (_pUGroup && _pUGroup != (FILENAMEDBLOCK*)c_pDefaultUGroup)
  655. {
  656. delete [] (BYTE*)_pUGroup;
  657. }
  658. }
  659. // GetBlob writes out the ANNOTATIONMARK plus the group and index blocks
  660. // It then queries the subclass through a virtual function to get
  661. // extra named blocks
  662. //
  663. HRESULT CAnnotation::GetBlob(SIZE_T &cbSize, LPBYTE pBuffer, LPCSTR szDefaultGroup, LPCSTR szNextIndex)
  664. {
  665. SIZE_T cbExtra = 0;
  666. HRESULT hr = S_OK;
  667. LPCSTR szGroup = _szGroup;
  668. if (szGroup == NULL)
  669. szGroup = szDefaultGroup;
  670. // add in the ANNOTATIONMARK
  671. cbSize = sizeof(_mark);
  672. // for the group and index, add in the
  673. cbSize += 2*(CBDATATYPE+CBNAMEDBLOCK);
  674. // add in the length of the group name
  675. cbSize += lstrlenA(szGroup)+1;
  676. // add in the size of the index string
  677. cbSize += CBINDEX;
  678. if (_pUGroup)
  679. {
  680. cbSize += CBDATATYPE+CBNAMEDBLOCK+_pUGroup->cbSize;
  681. }
  682. // Add in the size of any named blocks from the subclass
  683. _WriteBlocks(cbExtra, NULL);
  684. cbSize += cbExtra;
  685. if (pBuffer)
  686. {
  687. // now write the data
  688. CopyMemory (pBuffer, &_mark, sizeof(_mark));
  689. pBuffer += sizeof(_mark);
  690. // write the mark-specific blocks before the group and index blocks
  691. if (cbExtra)
  692. {
  693. if (SUCCEEDED(_WriteBlocks(cbExtra, pBuffer)))
  694. {
  695. pBuffer+=cbExtra;
  696. }
  697. }
  698. // write the group and index blocks
  699. if (_pUGroup)
  700. {
  701. *(UNALIGNED UINT*)pBuffer = 6;
  702. *(UNALIGNED UINT*)(pBuffer + 4) = CBNAMEDBLOCK;
  703. CopyMemory(pBuffer+CBDATATYPE,_pUGroup, CBNAMEDBLOCK+_pUGroup->cbSize);
  704. pBuffer += CBDATATYPE + CBNAMEDBLOCK+_pUGroup->cbSize;
  705. }
  706. pBuffer += _WriteStringBlock(pBuffer, 6, c_szGroup, szGroup, lstrlenA(szGroup)+1);
  707. pBuffer += _WriteStringBlock(pBuffer, 6, c_szIndex, szNextIndex, CBINDEX);
  708. }
  709. return hr;
  710. }
  711. void CAnnotation::Rotate(int nNewImageWidth, int nNewImageHeight, BOOL bClockwise)
  712. {
  713. RECT rect = _mark.lrBounds;
  714. RotateHelper((LPPOINT)&rect, 2, nNewImageWidth, nNewImageHeight, bClockwise);
  715. NormalizeRect(&rect);
  716. _mark.lrBounds = rect;
  717. }
  718. void CAnnotation::GetFont(LOGFONTW& lfFont)
  719. {
  720. lfFont.lfHeight = _mark.lfFont.lfHeight;
  721. lfFont.lfWidth = _mark.lfFont.lfWidth;
  722. lfFont.lfEscapement = _mark.lfFont.lfEscapement;
  723. lfFont.lfOrientation = _mark.lfFont.lfOrientation;
  724. lfFont.lfWeight = _mark.lfFont.lfWeight;
  725. lfFont.lfItalic = _mark.lfFont.lfItalic;
  726. lfFont.lfUnderline = _mark.lfFont.lfUnderline;
  727. lfFont.lfStrikeOut = _mark.lfFont.lfStrikeOut;
  728. lfFont.lfCharSet = _mark.lfFont.lfCharSet;
  729. lfFont.lfOutPrecision = _mark.lfFont.lfOutPrecision;
  730. lfFont.lfClipPrecision = _mark.lfFont.lfClipPrecision;
  731. lfFont.lfQuality = _mark.lfFont.lfQuality;
  732. lfFont.lfPitchAndFamily = _mark.lfFont.lfPitchAndFamily;
  733. ::MultiByteToWideChar(CP_ACP, 0, _mark.lfFont.lfFaceName, ARRAYSIZE(_mark.lfFont.lfFaceName), lfFont.lfFaceName, ARRAYSIZE(lfFont.lfFaceName));
  734. }
  735. void CAnnotation::SetFont(LOGFONTW& lfFont)
  736. {
  737. _mark.lfFont.lfHeight = lfFont.lfHeight;
  738. _mark.lfFont.lfWidth = lfFont.lfWidth;
  739. _mark.lfFont.lfEscapement = lfFont.lfEscapement;
  740. _mark.lfFont.lfOrientation = lfFont.lfOrientation;
  741. _mark.lfFont.lfWeight = lfFont.lfWeight;
  742. _mark.lfFont.lfItalic = lfFont.lfItalic;
  743. _mark.lfFont.lfUnderline = lfFont.lfUnderline;
  744. _mark.lfFont.lfStrikeOut = lfFont.lfStrikeOut;
  745. _mark.lfFont.lfCharSet = lfFont.lfCharSet;
  746. _mark.lfFont.lfOutPrecision = lfFont.lfOutPrecision;
  747. _mark.lfFont.lfClipPrecision = lfFont.lfClipPrecision;
  748. _mark.lfFont.lfQuality = lfFont.lfQuality;
  749. _mark.lfFont.lfPitchAndFamily = lfFont.lfPitchAndFamily;
  750. ::WideCharToMultiByte(CP_ACP, 0, lfFont.lfFaceName, ARRAYSIZE(lfFont.lfFaceName), _mark.lfFont.lfFaceName, ARRAYSIZE(_mark.lfFont.lfFaceName), NULL, NULL);
  751. }
  752. SIZE_T CAnnotation::_WriteStringBlock(LPBYTE pBuffer, UINT uType, LPCSTR szName, LPCSTR szData, SIZE_T len)
  753. {
  754. if (pBuffer)
  755. {
  756. *(UNALIGNED UINT*)pBuffer = uType;
  757. *(UNALIGNED UINT*)(pBuffer + 4) = CBNAMEDBLOCK;
  758. lstrcpynA((LPSTR)(pBuffer + CBDATATYPE), szName, CBNAMEDBLOCK+1); // named block name
  759. *(UNALIGNED UINT*)(pBuffer + CBDATATYPE + 8) = (UINT)len; // the named block name isn't null terminated
  760. CopyMemory(pBuffer + CBDATATYPE + CBNAMEDBLOCK, szData, len);
  761. }
  762. return CBDATATYPE + CBNAMEDBLOCK + len;
  763. }
  764. SIZE_T CAnnotation::_WritePointsBlock(LPBYTE pBuffer, UINT uType, const POINT *ppts, int nPoints, int nMaxPoints)
  765. {
  766. UINT cbAnPoints = sizeof(int)+sizeof(int)+nPoints*sizeof(POINT);
  767. if (pBuffer)
  768. {
  769. *(UNALIGNED UINT *)pBuffer = uType;
  770. *(UNALIGNED UINT *)(pBuffer + 4) = CBNAMEDBLOCK;
  771. lstrcpynA((LPSTR)(pBuffer + CBDATATYPE), c_szAnoDat, CBNAMEDBLOCK+1);
  772. pBuffer += CBDATATYPE + 8;
  773. *(UNALIGNED UINT *)pBuffer = cbAnPoints;
  774. pBuffer+=4;
  775. // Write out the ANPOINTS equivalent
  776. *(UNALIGNED int*)pBuffer = nMaxPoints;
  777. *(UNALIGNED int*)(pBuffer+4) = nPoints;
  778. CopyMemory(pBuffer+8, ppts, nPoints*sizeof(POINT));
  779. }
  780. return CBDATATYPE + CBNAMEDBLOCK + cbAnPoints;
  781. }
  782. SIZE_T CAnnotation::_WriteRotateBlock(LPBYTE pBuffer, UINT uType, const ANROTATE *pRotate)
  783. {
  784. if (pBuffer)
  785. {
  786. *(UNALIGNED UINT *)pBuffer = uType;
  787. *(UNALIGNED UINT *)(pBuffer + 4) = CBNAMEDBLOCK;
  788. lstrcpynA((LPSTR)(pBuffer + CBDATATYPE), c_szAnoDat, CBNAMEDBLOCK+1);
  789. *(UNALIGNED UINT *)(pBuffer + CBDATATYPE + 8) = sizeof(ANROTATE);
  790. CopyMemory(pBuffer + CBDATATYPE + CBNAMEDBLOCK, pRotate, sizeof(ANROTATE));
  791. }
  792. return CBDATATYPE + CBNAMEDBLOCK + sizeof(ANROTATE);
  793. }
  794. SIZE_T CAnnotation::_WriteTextBlock(LPBYTE pBuffer, UINT uType, int nOrient, UINT uScale, LPCSTR szText, int nMaxLen)
  795. {
  796. LPCSTR pText = szText ? szText : "";
  797. UINT cbString = min(lstrlenA(pText)+1, nMaxLen);
  798. UINT cbPrivData = sizeof(ANTEXTPRIVDATA)+cbString;
  799. if (pBuffer)
  800. {
  801. *(UNALIGNED UINT *)pBuffer = uType;
  802. *(UNALIGNED UINT *)(pBuffer + 4) = CBNAMEDBLOCK;
  803. lstrcpynA((LPSTR)(pBuffer + CBDATATYPE), c_szAnText, CBNAMEDBLOCK+1);
  804. *(UNALIGNED UINT *)(pBuffer + CBDATATYPE + 8) = cbPrivData;
  805. // write out the ANTEXTPRIVDATA equivalent
  806. pBuffer += CBDATATYPE + CBNAMEDBLOCK;
  807. *(UNALIGNED int*)pBuffer = nOrient;
  808. *(UNALIGNED UINT *)(pBuffer+4) = 1000;
  809. *(UNALIGNED UINT *)(pBuffer+8) = uScale;
  810. *(UNALIGNED UINT *)(pBuffer+12) = cbString;
  811. lstrcpynA((LPSTR)(pBuffer+16), pText, nMaxLen);
  812. }
  813. return CBDATATYPE + CBNAMEDBLOCK + cbPrivData;
  814. }
  815. SIZE_T CAnnotation::_WriteImageBlock(LPBYTE pBuffer, UINT uType, LPBYTE pDib, SIZE_T cbDib)
  816. {
  817. if (pBuffer)
  818. {
  819. *(UNALIGNED UINT *)pBuffer = uType;
  820. *(UNALIGNED UINT *)(pBuffer+4) = CBNAMEDBLOCK;
  821. lstrcpynA((LPSTR)(pBuffer + CBDATATYPE), c_szAnText, CBNAMEDBLOCK+1);
  822. /* REVIEW_SDK
  823. Now that I think about it, it might make sense to define a struct that could make this more clear.
  824. Something like:
  825. struct AnnoBlock
  826. {
  827. UINT uBlockType;
  828. UINT uBlockSize;
  829. CHAR sName[8]; // Not NULL terminated
  830. UINT uVariableDataSize;
  831. BYTE Data[];
  832. };
  833. */
  834. *(UNALIGNED UINT *)(pBuffer + CBDATATYPE + 8) = (UINT)cbDib;
  835. CopyMemory(pBuffer + CBDATATYPE + CBNAMEDBLOCK, pDib, cbDib);
  836. }
  837. return CBDATATYPE + CBNAMEDBLOCK + cbDib;
  838. }
  839. CRectMark::CRectMark(ANNOTATIONDESCRIPTOR *pDescriptor)
  840. : CAnnotation(pDescriptor)
  841. {
  842. // rects have no named blocks to read
  843. }
  844. void CRectMark::Render(HDC hdc)
  845. {
  846. int nROP = R2_COPYPEN;
  847. if (_mark.bHighlighting)
  848. nROP = R2_MASKPEN;
  849. int nOldROP = ::SetROP2(hdc, nROP);
  850. HPEN hPen = NULL;
  851. HPEN hOldPen = NULL;
  852. HBRUSH hBrush = NULL;
  853. HBRUSH hOldBrush = NULL;
  854. if (_mark.uType == MT_HOLLOWRECT)
  855. {
  856. hPen = ::CreatePen(PS_INSIDEFRAME, max(1, _mark.uLineSize),
  857. RGB(_mark.rgbColor1.rgbRed,
  858. _mark.rgbColor1.rgbGreen,
  859. _mark.rgbColor1.rgbBlue));
  860. if(hPen)
  861. hOldPen =(HPEN)::SelectObject(hdc, hPen);
  862. hOldBrush = (HBRUSH)::SelectObject(hdc, ::GetStockObject(NULL_BRUSH));
  863. }
  864. else
  865. {
  866. hBrush = CreateSolidBrush(RGB(_mark.rgbColor1.rgbRed,
  867. _mark.rgbColor1.rgbGreen,
  868. _mark.rgbColor1.rgbBlue));
  869. if (hBrush)
  870. hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  871. hOldPen =(HPEN)::SelectObject(hdc, GetStockObject(NULL_PEN));
  872. }
  873. ::Rectangle(hdc, _mark.lrBounds.left, _mark.lrBounds.top, _mark.lrBounds.right, _mark.lrBounds.bottom);
  874. if (hOldPen)
  875. ::SelectObject(hdc, hOldPen);
  876. if (hOldBrush)
  877. ::SelectObject(hdc, hOldBrush);
  878. if (hPen)
  879. ::DeleteObject(hPen);
  880. if (hBrush)
  881. ::DeleteObject(hBrush);
  882. ::SetROP2(hdc, nOldROP);
  883. }
  884. CImageMark::CImageMark(ANNOTATIONDESCRIPTOR *pDescriptor, bool bEmbedded) :
  885. CAnnotation(pDescriptor), _hDibSection(NULL), _pDib(NULL)
  886. {
  887. ZeroMemory(&_rotation, sizeof(_rotation));
  888. NAMEDBLOCK *pb = _FindNamedBlock(c_szAnoDat, pDescriptor);
  889. UINT cb;
  890. _cbDib = 0;
  891. _bRotate = false;
  892. if (pb)
  893. {
  894. CopyMemory(&_rotation, pb->data, sizeof(_rotation));
  895. }
  896. pb= _FindNamedBlock(c_szFilNam, pDescriptor);
  897. if (pb)
  898. {
  899. cb = pb->cbSize-sizeof(pb->cbSize)-sizeof(pb->szType);
  900. _szFilename = new char[cb+1];
  901. if (_szFilename)
  902. {
  903. lstrcpynA (_szFilename, (LPCSTR)(pb->data), cb+1);
  904. }
  905. }
  906. pb = _FindNamedBlock(c_szDIB, pDescriptor);
  907. if (pb)
  908. {
  909. assert (bEmbedded);
  910. cb = pb->cbSize-sizeof(pb->cbSize)-sizeof(pb->szType);
  911. _pDib = new BYTE[cb];
  912. if (_pDib)
  913. {
  914. CopyMemory (_pDib, pb->data, cb);
  915. _cbDib = cb;
  916. }
  917. // what do we do if allocation fails?
  918. }
  919. // If an image has IoAnoDat, the structure is a rotation structure
  920. pb = _FindNamedBlock(c_szAnoDat, pDescriptor);
  921. if (pb)
  922. {
  923. assert(pb->cbSize-sizeof(pb->cbSize)-sizeof(pb->szType) == sizeof(_rotation));
  924. _bRotate = true;
  925. CopyMemory(&_rotation, pb->data, sizeof(_rotation));
  926. }
  927. }
  928. CImageMark::~CImageMark()
  929. {
  930. if (_pDib)
  931. {
  932. delete [] _pDib;
  933. }
  934. if (_szFilename)
  935. {
  936. delete [] _szFilename;
  937. }
  938. }
  939. HRESULT CImageMark::_WriteBlocks(SIZE_T &cbSize, LPBYTE pBuffer)
  940. {
  941. cbSize = 0;
  942. if (_szFilename)
  943. {
  944. cbSize += _WriteStringBlock(pBuffer, 6, c_szFilNam, _szFilename, lstrlenA(_szFilename)+1);
  945. }
  946. if (_pDib)
  947. {
  948. cbSize += _WriteImageBlock(pBuffer, 6, _pDib, _cbDib);
  949. }
  950. if (_bRotate)
  951. {
  952. cbSize += _WriteRotateBlock(pBuffer, 6, &_rotation);
  953. }
  954. return S_OK;
  955. }
  956. void CImageMark::Render(HDC hdc)
  957. {
  958. }
  959. CLineMark::CLineMark(ANNOTATIONDESCRIPTOR *pDescriptor, bool bFreehand)
  960. : CAnnotation(pDescriptor)
  961. {
  962. NAMEDBLOCK *pb=_FindNamedBlock(c_szAnoDat, pDescriptor);
  963. _points = NULL;
  964. _nPoints = 0;
  965. if (pb)
  966. {
  967. ANPOINTS *ppts = (ANPOINTS*)&pb->data;
  968. _iMaxPts = bFreehand ? ppts->nMaxPoints : 2;
  969. assert(_nPoints > 2?bFreehand:TRUE);
  970. _points = new POINT[_iMaxPts];
  971. if (_points)
  972. {
  973. _nPoints = ppts->nPoints;
  974. CopyMemory (_points, &ppts->ptPoint, sizeof(POINT)*_nPoints);
  975. // each point is relative to the upper left cornder of _mark.lrBounds
  976. for (int i=0;i<_nPoints;i++)
  977. {
  978. _points[i].x += _mark.lrBounds.left;
  979. _points[i].y += _mark.lrBounds.top;
  980. }
  981. }
  982. }
  983. }
  984. CLineMark::~CLineMark()
  985. {
  986. if (_points)
  987. {
  988. delete [] _points;
  989. }
  990. }
  991. void CLineMark::SetPoints(POINT* pPoints, int cPoints)
  992. {
  993. assert(_mark.uType == MT_FREEHANDLINE);
  994. if (_points != NULL)
  995. delete[] _points;
  996. _points = pPoints;
  997. _nPoints = cPoints;
  998. _iMaxPts = _nPoints;
  999. RECT rect;
  1000. rect.left = _points[0].x;
  1001. rect.top = _points[0].y;
  1002. rect.right = _points[0].x;
  1003. rect.bottom= _points[0].y;
  1004. for(int i = 1; i < _nPoints; i++)
  1005. {
  1006. if (rect.left > _points[i].x)
  1007. rect.left = _points[i].x;
  1008. else if (rect.right < _points[i].x)
  1009. rect.right = _points[i].x;
  1010. if (rect.top > _points[i].y)
  1011. rect.top = _points[i].y;
  1012. else if (rect.bottom < _points[i].y)
  1013. rect.bottom = _points[i].y;
  1014. }
  1015. _mark.lrBounds = rect;
  1016. }
  1017. void CLineMark::Render(HDC hdc)
  1018. {
  1019. int nROP = R2_COPYPEN;
  1020. if (_mark.bHighlighting)
  1021. nROP = R2_MASKPEN;
  1022. int nOldROP = ::SetROP2(hdc, nROP);
  1023. HPEN hPen = NULL;
  1024. HPEN hOldPen = NULL;
  1025. hPen = ::CreatePen(PS_SOLID, max(1, _mark.uLineSize),
  1026. RGB(_mark.rgbColor1.rgbRed,
  1027. _mark.rgbColor1.rgbGreen,
  1028. _mark.rgbColor1.rgbBlue));
  1029. if(hPen)
  1030. hOldPen =(HPEN)::SelectObject(hdc, hPen);
  1031. ::Polyline(hdc, _points, _nPoints);
  1032. if (hOldPen)
  1033. ::SelectObject(hdc, hOldPen);
  1034. if (hPen)
  1035. ::DeleteObject(hPen);
  1036. ::SetROP2(hdc, nOldROP);
  1037. }
  1038. void CLineMark::GetRect(RECT &rect)
  1039. {
  1040. int nPadding = (_mark.uLineSize / 2) + 6;
  1041. // one because LineTo is inclusive
  1042. // one for rounding error on odd line widths
  1043. // one for rounding error in scaling large files
  1044. // and three more just so we don't have to tweak this again
  1045. rect = _mark.lrBounds;
  1046. InflateRect(&rect, nPadding , nPadding);
  1047. }
  1048. // Usually we are interested in the bounding rect of the line above
  1049. // but if we are directly manipulating the line we need a way to get
  1050. // to the unadjusted points (left, top) and (right, bottom)
  1051. void CLineMark::GetPointsRect(RECT &rect)
  1052. {
  1053. if (_nPoints != 2)
  1054. return;
  1055. rect.top = _points[0].y;
  1056. rect.left = _points[0].x;
  1057. rect.bottom = _points[1].y;
  1058. rect.right = _points[1].x;
  1059. }
  1060. void CLineMark::Move(SIZE sizeOffset)
  1061. {
  1062. _points[0].x += sizeOffset.cx;
  1063. _points[0].y += sizeOffset.cy;
  1064. RECT rect;
  1065. rect.left = _points[0].x;
  1066. rect.top = _points[0].y;
  1067. rect.right = _points[0].x;
  1068. rect.bottom = _points[0].y;
  1069. for(int i = 1; i < _nPoints; i++)
  1070. {
  1071. _points[i].x += sizeOffset.cx;
  1072. if (rect.left > _points[i].x)
  1073. rect.left = _points[i].x;
  1074. else if (rect.right < _points[i].x)
  1075. rect.right = _points[i].x;
  1076. _points[i].y += sizeOffset.cy;
  1077. if (rect.top > _points[i].y)
  1078. rect.top = _points[i].y;
  1079. else if (rect.bottom < _points[i].y)
  1080. rect.bottom = _points[i].y;
  1081. }
  1082. _mark.lrBounds = rect;
  1083. }
  1084. void CLineMark::Resize(RECT rectNewSize)
  1085. {
  1086. if ((_points == NULL) && (_mark.uType == MT_STRAIGHTLINE))
  1087. {
  1088. _iMaxPts = _nPoints = 2;
  1089. _points = new POINT[_iMaxPts];
  1090. }
  1091. if ((_nPoints == 2) && (_points != NULL))
  1092. {
  1093. _points[0].y = rectNewSize.top;
  1094. _points[0].x = rectNewSize.left;
  1095. _points[1].y = rectNewSize.bottom;
  1096. _points[1].x = rectNewSize.right;
  1097. _mark.lrBounds = rectNewSize;
  1098. NormalizeRect(&_mark.lrBounds);
  1099. }
  1100. }
  1101. void CLineMark::Rotate(int nNewImageWidth, int nNewImageHeight, BOOL bClockwise)
  1102. {
  1103. RotateHelper(_points, _nPoints, nNewImageWidth, nNewImageHeight, bClockwise);
  1104. RECT rect;
  1105. rect.left = _points[0].x;
  1106. rect.top = _points[0].y;
  1107. rect.right = _points[0].x;
  1108. rect.bottom= _points[0].y;
  1109. for(int i = 1; i < _nPoints; i++)
  1110. {
  1111. if (rect.left > _points[i].x)
  1112. rect.left = _points[i].x;
  1113. else if (rect.right < _points[i].x)
  1114. rect.right = _points[i].x;
  1115. if (rect.top > _points[i].y)
  1116. rect.top = _points[i].y;
  1117. else if (rect.bottom < _points[i].y)
  1118. rect.bottom = _points[i].y;
  1119. }
  1120. _mark.lrBounds = rect;
  1121. }
  1122. HRESULT CLineMark::_WriteBlocks(SIZE_T &cbSize, LPBYTE pBuffer)
  1123. {
  1124. if (_points)
  1125. {
  1126. for (int i=0;i<_nPoints;i++)
  1127. {
  1128. _points[i].x -= _mark.lrBounds.left;
  1129. _points[i].y -= _mark.lrBounds.top;
  1130. }
  1131. cbSize = _WritePointsBlock(pBuffer, 6, _points, _nPoints, _iMaxPts);
  1132. for (int i=0;i<_nPoints;i++)
  1133. {
  1134. _points[i].x += _mark.lrBounds.left;
  1135. _points[i].y += _mark.lrBounds.top;
  1136. }
  1137. }
  1138. return S_OK;
  1139. }
  1140. CTextAnnotation::CTextAnnotation(ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale, UINT nMaxLen, bool bUseColor2 )
  1141. : CAnnotation(pDescriptor)
  1142. {
  1143. NAMEDBLOCK *pb = _FindNamedBlock(c_szAnText, pDescriptor);
  1144. _nCurrentOrientation = 0;
  1145. _uCreationScale = 0;
  1146. _uAnoTextLength = 0;
  1147. _szText = NULL;
  1148. _nMaxText = nMaxLen;
  1149. _bUseColor2 = bUseColor2;
  1150. if (pb)
  1151. {
  1152. ANTEXTPRIVDATA *pData = (ANTEXTPRIVDATA*)&pb->data;
  1153. _szText = new char[pData->uAnoTextLength+1];
  1154. if (_szText)
  1155. {
  1156. _nCurrentOrientation = pData->nCurrentOrientation;
  1157. _uCreationScale = pData->uCreationScale;
  1158. _uAnoTextLength = pData->uAnoTextLength;
  1159. lstrcpynA (_szText, pData->szAnoText, _uAnoTextLength+1);
  1160. }
  1161. }
  1162. if (_uCreationScale == 0)
  1163. {
  1164. _uCreationScale = 72000 / uCreationScale;
  1165. }
  1166. }
  1167. CTextAnnotation::~CTextAnnotation()
  1168. {
  1169. if (_szText)
  1170. {
  1171. delete [] _szText;
  1172. }
  1173. }
  1174. void CTextAnnotation::Render(HDC hdc)
  1175. {
  1176. COLORREF crOld;
  1177. int nOldROP = ::SetROP2(hdc, R2_COPYPEN);
  1178. if (_mark.uType == MT_ATTACHANOTE)
  1179. {
  1180. HPEN hOldPen =(HPEN)::SelectObject(hdc, GetStockObject(NULL_PEN));
  1181. HBRUSH hBrush = ::CreateSolidBrush(RGB(_mark.rgbColor1.rgbRed,
  1182. _mark.rgbColor1.rgbGreen,
  1183. _mark.rgbColor1.rgbBlue));
  1184. if (hBrush != NULL)
  1185. {
  1186. HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc, hBrush);
  1187. ::Rectangle(hdc, _mark.lrBounds.left, _mark.lrBounds.top, _mark.lrBounds.right, _mark.lrBounds.bottom);
  1188. ::SelectObject(hdc, hOldBrush);
  1189. ::DeleteObject(hBrush);
  1190. }
  1191. ::SelectObject(hdc, hOldPen);
  1192. crOld = ::SetTextColor(hdc, RGB(_mark.rgbColor2.rgbRed,
  1193. _mark.rgbColor2.rgbGreen,
  1194. _mark.rgbColor2.rgbBlue));
  1195. }
  1196. else
  1197. {
  1198. crOld = ::SetTextColor(hdc, RGB(_mark.rgbColor1.rgbRed,
  1199. _mark.rgbColor1.rgbGreen,
  1200. _mark.rgbColor1.rgbBlue));
  1201. }
  1202. int nOldBkMode = ::SetBkMode(hdc, TRANSPARENT);
  1203. LOGFONT lf;
  1204. GetFont(lf);
  1205. lf.lfHeight = GetFontHeight(hdc);
  1206. HFONT hFont = CreateFontIndirect(&lf);
  1207. HFONT hOldFont = NULL;
  1208. if (hFont != NULL)
  1209. hOldFont = (HFONT)::SelectObject(hdc, hFont);
  1210. BSTR bstrText = GetText();
  1211. // Handle angle of orientation in 1/10s of a degree
  1212. if (_nCurrentOrientation != 0)
  1213. {
  1214. XFORM xForm;
  1215. RECT rectSource = _mark.lrBounds;
  1216. ::LPtoDP(hdc, (LPPOINT)&rectSource, 2);
  1217. if (_nCurrentOrientation == 900)
  1218. {
  1219. xForm.eM11 = (FLOAT)0.0;
  1220. xForm.eM12 = (FLOAT)-1.0;
  1221. xForm.eM21 = (FLOAT)1.0;
  1222. xForm.eM22 = (FLOAT)0.0;
  1223. // Rotate Source (left, top) to (left, bottom)
  1224. int nTmp = rectSource.bottom;
  1225. rectSource.bottom = rectSource.top;
  1226. rectSource.top = nTmp;
  1227. }
  1228. else if (_nCurrentOrientation == 1800)
  1229. {
  1230. xForm.eM11 = (FLOAT)-1.0;
  1231. xForm.eM12 = (FLOAT)0.0;
  1232. xForm.eM21 = (FLOAT)0.0;
  1233. xForm.eM22 = (FLOAT)-1.0;
  1234. // Rotate Source (left, top) to (right, bottom)
  1235. int nTmp = rectSource.right;
  1236. rectSource.right = rectSource.left;
  1237. rectSource.left = nTmp;
  1238. nTmp = rectSource.bottom;
  1239. rectSource.bottom = rectSource.top;
  1240. rectSource.top = nTmp;
  1241. }
  1242. else
  1243. {
  1244. xForm.eM11 = (FLOAT)0.0;
  1245. xForm.eM12 = (FLOAT)1.0;
  1246. xForm.eM21 = (FLOAT)-1.0;
  1247. xForm.eM22 = (FLOAT)0.0;
  1248. // Rotate Source (left, top) to (right, top)
  1249. int nTmp = rectSource.right;
  1250. rectSource.right = rectSource.left;
  1251. rectSource.left = nTmp;
  1252. }
  1253. xForm.eDx = (FLOAT)0.0;
  1254. xForm.eDy = (FLOAT)0.0;
  1255. int nOldGraphicsMode = ::SetGraphicsMode(hdc, GM_ADVANCED);
  1256. ::SetWorldTransform(hdc, &xForm);
  1257. RECT rectTarget = rectSource;
  1258. ::DPtoLP(hdc, (LPPOINT)&rectTarget, 2);
  1259. ::DrawText(hdc, bstrText, -1, &rectTarget, DT_LEFT | DT_EDITCONTROL | DT_NOPREFIX | DT_WORDBREAK);
  1260. ::ModifyWorldTransform(hdc, &xForm, MWT_IDENTITY);
  1261. ::SetGraphicsMode(hdc, nOldGraphicsMode);
  1262. }
  1263. else
  1264. {
  1265. ::DrawText(hdc, bstrText, -1, &_mark.lrBounds, DT_LEFT | DT_EDITCONTROL | DT_NOPREFIX | DT_WORDBREAK);
  1266. }
  1267. if (hFont != NULL)
  1268. {
  1269. ::SelectObject(hdc, hOldFont);
  1270. ::DeleteObject(hFont);
  1271. }
  1272. if (nOldBkMode != 0)
  1273. ::SetBkMode(hdc, nOldBkMode);
  1274. if (crOld != CLR_INVALID)
  1275. ::SetTextColor (hdc, crOld);
  1276. ::SetROP2(hdc, nOldROP);
  1277. if (bstrText)
  1278. {
  1279. SysFreeString(bstrText);
  1280. }
  1281. }
  1282. LONG CTextAnnotation::GetFontHeight(HDC hdc)
  1283. {
  1284. LONG lHeight = MulDiv(_mark.lfFont.lfHeight, 96, 72);
  1285. //> REVIEW : This needs work, the 1000 below is rather random and should be fixed after Beta1
  1286. lHeight = MulDiv(lHeight, 1000, _uCreationScale);
  1287. lHeight = max(lHeight, 2);
  1288. return lHeight;
  1289. }
  1290. BSTR CTextAnnotation::GetText()
  1291. {
  1292. if (_szText == NULL)
  1293. return NULL;
  1294. int nLen = ::MultiByteToWideChar(CP_ACP, 0, _szText, -1, NULL, NULL);
  1295. BSTR bstrResult = ::SysAllocStringLen(NULL, nLen);
  1296. if (bstrResult != NULL)
  1297. {
  1298. ::MultiByteToWideChar(CP_ACP, 0, _szText, -1, bstrResult, nLen);
  1299. }
  1300. return bstrResult;
  1301. }
  1302. void CTextAnnotation::SetText(BSTR bstrText)
  1303. {
  1304. UINT nLen = ::WideCharToMultiByte(CP_ACP, 0, bstrText, -1, NULL, 0, NULL, NULL);
  1305. if (nLen > _nMaxText)
  1306. return;
  1307. if (nLen > _uAnoTextLength)
  1308. {
  1309. if (_szText != NULL)
  1310. {
  1311. delete [] _szText;
  1312. }
  1313. _uAnoTextLength = nLen - 1;
  1314. _szText = new char[_uAnoTextLength+1];
  1315. }
  1316. if (_szText)
  1317. ::WideCharToMultiByte(CP_ACP, 0, bstrText, -1, _szText, nLen, NULL, NULL);
  1318. }
  1319. void CTextAnnotation::Rotate(int nNewImageWidth, int nNewImageHeight, BOOL bClockwise)
  1320. {
  1321. RECT rect = _mark.lrBounds;
  1322. RotateHelper((LPPOINT)&rect, 2, nNewImageWidth, nNewImageHeight, bClockwise);
  1323. _mark.lrBounds = rect;
  1324. NormalizeRect(&_mark.lrBounds);
  1325. if (bClockwise)
  1326. _nCurrentOrientation += 2700;
  1327. else
  1328. _nCurrentOrientation += 900;
  1329. _nCurrentOrientation = _nCurrentOrientation % 3600;
  1330. }
  1331. HRESULT CTextAnnotation::_WriteBlocks(SIZE_T &cbSize, LPBYTE pBuffer)
  1332. {
  1333. cbSize = _WriteTextBlock(pBuffer,
  1334. 6,
  1335. _nCurrentOrientation,
  1336. _uCreationScale,
  1337. _szText,
  1338. _nMaxText);
  1339. return S_OK;
  1340. }
  1341. CTypedTextMark::CTypedTextMark (ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale)
  1342. : CTextAnnotation(pDescriptor, uCreationScale)
  1343. {
  1344. }
  1345. CFileTextMark::CFileTextMark (ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale)
  1346. : CTextAnnotation(pDescriptor, uCreationScale)
  1347. {
  1348. }
  1349. CTextStampMark::CTextStampMark (ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale)
  1350. : CTextAnnotation(pDescriptor, uCreationScale, 255)
  1351. {
  1352. }
  1353. CAttachNoteMark::CAttachNoteMark (ANNOTATIONDESCRIPTOR *pDescriptor, ULONG uCreationScale)
  1354. : CTextAnnotation(pDescriptor, uCreationScale, 65536, true)
  1355. {
  1356. }