Source code of Windows XP (NT5)
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.

1502 lines
43 KiB

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